mongo 2.0.6 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (317) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +5 -2
  3. data/lib/mongo/address/ipv4.rb +6 -1
  4. data/lib/mongo/address/unix.rb +2 -2
  5. data/lib/mongo/address.rb +18 -10
  6. data/lib/mongo/auth/cr/conversation.rb +1 -1
  7. data/lib/mongo/auth/ldap/conversation.rb +7 -3
  8. data/lib/mongo/auth/scram/conversation.rb +9 -3
  9. data/lib/mongo/auth/user/view.rb +23 -2
  10. data/lib/mongo/auth/x509/conversation.rb +1 -1
  11. data/lib/mongo/bulk_write/combineable.rb +51 -0
  12. data/lib/mongo/bulk_write/ordered_combiner.rb +55 -0
  13. data/lib/mongo/bulk_write/result.rb +191 -0
  14. data/lib/mongo/bulk_write/result_combiner.rb +117 -0
  15. data/lib/mongo/bulk_write/transformable.rb +132 -0
  16. data/lib/mongo/bulk_write/unordered_combiner.rb +52 -0
  17. data/lib/mongo/bulk_write/validatable.rb +62 -0
  18. data/lib/mongo/bulk_write.rb +159 -23
  19. data/lib/mongo/client.rb +52 -16
  20. data/lib/mongo/cluster/topology/replica_set.rb +27 -9
  21. data/lib/mongo/cluster/topology/sharded.rb +1 -1
  22. data/lib/mongo/cluster/topology/unknown.rb +5 -2
  23. data/lib/mongo/cluster.rb +42 -7
  24. data/lib/mongo/collection/view/aggregation.rb +48 -9
  25. data/lib/mongo/collection/view/immutable.rb +6 -6
  26. data/lib/mongo/collection/view/iterable.rb +18 -4
  27. data/lib/mongo/collection/view/map_reduce.rb +58 -17
  28. data/lib/mongo/collection/view/readable.rb +173 -42
  29. data/lib/mongo/collection/view/writable.rb +37 -23
  30. data/lib/mongo/collection/view.rb +2 -2
  31. data/lib/mongo/collection.rb +370 -33
  32. data/lib/mongo/cursor.rb +15 -3
  33. data/lib/mongo/database/view.rb +5 -4
  34. data/lib/mongo/database.rb +14 -4
  35. data/lib/mongo/dbref.rb +113 -0
  36. data/lib/mongo/error/closed_stream.rb +34 -0
  37. data/lib/mongo/error/extra_file_chunk.rb +34 -0
  38. data/lib/mongo/error/{invalid_uri_option.rb → file_not_found.rb} +11 -12
  39. data/lib/mongo/error/invalid_file.rb +2 -2
  40. data/lib/mongo/error/invalid_file_revision.rb +37 -0
  41. data/lib/mongo/error/invalid_uri.rb +5 -4
  42. data/lib/mongo/error/missing_file_chunk.rb +38 -0
  43. data/lib/mongo/error/operation_failure.rb +1 -1
  44. data/lib/mongo/error/parser.rb +1 -1
  45. data/lib/mongo/error/unchangeable_collection_option.rb +38 -0
  46. data/lib/mongo/error/unexpected_chunk_length.rb +39 -0
  47. data/lib/mongo/error.rb +13 -2
  48. data/lib/mongo/event/description_changed.rb +1 -1
  49. data/lib/mongo/grid/file/chunk.rb +6 -6
  50. data/lib/mongo/grid/file/{metadata.rb → info.rb} +41 -39
  51. data/lib/mongo/grid/file.rb +13 -10
  52. data/lib/mongo/grid/fs_bucket.rb +448 -0
  53. data/lib/mongo/grid/stream/read.rb +208 -0
  54. data/lib/mongo/grid/stream/write.rb +187 -0
  55. data/lib/mongo/grid/stream.rb +64 -0
  56. data/lib/mongo/grid.rb +2 -1
  57. data/lib/mongo/index/view.rb +3 -3
  58. data/lib/mongo/index.rb +5 -0
  59. data/lib/mongo/loggable.rb +34 -57
  60. data/lib/mongo/logger.rb +16 -78
  61. data/lib/mongo/monitoring/command_log_subscriber.rb +112 -0
  62. data/lib/mongo/monitoring/event/command_failed.rb +96 -0
  63. data/lib/mongo/monitoring/event/command_started.rb +89 -0
  64. data/lib/mongo/monitoring/event/command_succeeded.rb +118 -0
  65. data/lib/mongo/monitoring/event/secure.rb +58 -0
  66. data/lib/mongo/monitoring/event.rb +18 -0
  67. data/lib/mongo/monitoring/publishable.rb +106 -0
  68. data/lib/mongo/monitoring.rb +195 -0
  69. data/lib/mongo/operation/{aggregate.rb → commands/aggregate.rb} +3 -41
  70. data/lib/mongo/operation/commands/collections_info/result.rb +39 -0
  71. data/lib/mongo/operation/commands/collections_info.rb +68 -0
  72. data/lib/mongo/operation/{command.rb → commands/command.rb} +2 -18
  73. data/lib/mongo/operation/commands/indexes.rb +70 -0
  74. data/lib/mongo/operation/commands/list_collections/result.rb +112 -0
  75. data/lib/mongo/operation/commands/list_collections.rb +54 -0
  76. data/lib/mongo/operation/commands/list_indexes/result.rb +116 -0
  77. data/lib/mongo/operation/commands/list_indexes.rb +56 -0
  78. data/lib/mongo/operation/{map_reduce → commands/map_reduce}/result.rb +1 -1
  79. data/lib/mongo/operation/{map_reduce.rb → commands/map_reduce.rb} +3 -41
  80. data/lib/mongo/operation/commands/parallel_scan/result.rb +72 -0
  81. data/lib/mongo/operation/commands/parallel_scan.rb +56 -0
  82. data/lib/mongo/operation/commands/user_query.rb +69 -0
  83. data/lib/mongo/{bulk_write/ordered_bulk_write.rb → operation/commands/users_info/result.rb} +18 -30
  84. data/lib/mongo/operation/commands/users_info.rb +53 -0
  85. data/lib/mongo/operation/commands.rb +24 -0
  86. data/lib/mongo/operation/executable.rb +4 -68
  87. data/lib/mongo/operation/kill_cursors.rb +3 -3
  88. data/lib/mongo/operation/read/get_more.rb +2 -22
  89. data/lib/mongo/{bulk_write/unordered_bulk_write.rb → operation/read/query/result.rb} +20 -26
  90. data/lib/mongo/operation/read/query.rb +4 -21
  91. data/lib/mongo/operation/read.rb +0 -4
  92. data/lib/mongo/operation/{read_preferrable.rb → read_preference.rb} +3 -2
  93. data/lib/mongo/operation/result.rb +13 -1
  94. data/lib/mongo/operation/specifiable.rb +42 -0
  95. data/lib/mongo/operation/write/bulk/bulkable.rb +82 -0
  96. data/lib/mongo/operation/write/bulk/delete/result.rb +74 -0
  97. data/lib/mongo/operation/write/bulk/delete.rb +71 -0
  98. data/lib/mongo/operation/write/bulk/insert/result.rb +129 -0
  99. data/lib/mongo/operation/write/bulk/insert.rb +96 -0
  100. data/lib/mongo/operation/write/bulk/legacy_mergable.rb +87 -0
  101. data/lib/mongo/operation/write/bulk/mergable.rb +71 -0
  102. data/lib/mongo/operation/write/bulk/update/result.rb +174 -0
  103. data/lib/mongo/operation/write/bulk/update.rb +81 -0
  104. data/lib/mongo/operation/write/bulk.rb +6 -3
  105. data/lib/mongo/operation/write/command/create_index.rb +0 -1
  106. data/lib/mongo/operation/write/command/create_user.rb +0 -1
  107. data/lib/mongo/operation/write/command/delete.rb +0 -1
  108. data/lib/mongo/operation/write/command/drop_index.rb +0 -1
  109. data/lib/mongo/operation/write/command/insert.rb +0 -1
  110. data/lib/mongo/operation/write/command/remove_user.rb +0 -1
  111. data/lib/mongo/operation/write/command/update.rb +0 -1
  112. data/lib/mongo/operation/write/command/update_user.rb +0 -1
  113. data/lib/mongo/operation/write/command/writable.rb +13 -18
  114. data/lib/mongo/operation/write/create_index.rb +4 -27
  115. data/lib/mongo/operation/write/create_user.rb +4 -30
  116. data/lib/mongo/operation/write/delete.rb +6 -29
  117. data/lib/mongo/operation/write/drop_index.rb +3 -3
  118. data/lib/mongo/operation/write/gle.rb +48 -0
  119. data/lib/mongo/operation/write/idable.rb +5 -0
  120. data/lib/mongo/operation/write/insert.rb +2 -24
  121. data/lib/mongo/operation/write/remove_user.rb +4 -27
  122. data/lib/mongo/operation/write/update.rb +13 -36
  123. data/lib/mongo/operation/write/update_user.rb +4 -30
  124. data/lib/mongo/operation/write/write_command_enabled.rb +53 -0
  125. data/lib/mongo/operation/write.rb +2 -0
  126. data/lib/mongo/operation.rb +32 -4
  127. data/lib/mongo/options/mapper.rb +4 -2
  128. data/lib/mongo/options/redacted.rb +156 -0
  129. data/lib/mongo/options.rb +1 -0
  130. data/lib/mongo/protocol/delete.rb +75 -15
  131. data/lib/mongo/protocol/get_more.rb +65 -13
  132. data/lib/mongo/protocol/insert.rb +85 -13
  133. data/lib/mongo/protocol/kill_cursors.rb +59 -14
  134. data/lib/mongo/protocol/message.rb +12 -12
  135. data/lib/mongo/protocol/query.rb +163 -37
  136. data/lib/mongo/protocol/reply.rb +103 -0
  137. data/lib/mongo/protocol/serializers.rb +1 -1
  138. data/lib/mongo/protocol/update.rb +82 -14
  139. data/lib/mongo/retryable.rb +83 -0
  140. data/lib/mongo/server/connectable.rb +21 -25
  141. data/lib/mongo/server/connection.rb +75 -4
  142. data/lib/mongo/server/connection_pool/queue.rb +15 -0
  143. data/lib/mongo/server/connection_pool.rb +12 -0
  144. data/lib/mongo/server/description/features.rb +2 -1
  145. data/lib/mongo/server/description.rb +52 -1
  146. data/lib/mongo/server/monitor/connection.rb +26 -2
  147. data/lib/mongo/server/monitor.rb +19 -3
  148. data/lib/mongo/server.rb +39 -5
  149. data/lib/mongo/server_selector/selectable.rb +40 -31
  150. data/lib/mongo/server_selector.rb +19 -10
  151. data/lib/mongo/socket/ssl.rb +28 -16
  152. data/lib/mongo/socket/tcp.rb +3 -3
  153. data/lib/mongo/socket/unix.rb +5 -8
  154. data/lib/mongo/socket.rb +11 -4
  155. data/lib/mongo/uri.rb +248 -137
  156. data/lib/mongo/version.rb +1 -1
  157. data/lib/mongo.rb +5 -3
  158. data/spec/mongo/address/unix_spec.rb +1 -1
  159. data/spec/mongo/address_spec.rb +25 -0
  160. data/spec/mongo/auth/cr_spec.rb +9 -1
  161. data/spec/mongo/auth/ldap/conversation_spec.rb +43 -0
  162. data/spec/mongo/auth/ldap_spec.rb +9 -1
  163. data/spec/mongo/auth/scram_spec.rb +9 -1
  164. data/spec/mongo/auth/user/view_spec.rb +26 -1
  165. data/spec/mongo/auth/x509_spec.rb +9 -1
  166. data/spec/mongo/bulk_write/ordered_combiner_spec.rb +271 -0
  167. data/spec/mongo/bulk_write/unordered_combiner_spec.rb +239 -0
  168. data/spec/mongo/bulk_write_spec.rb +428 -0
  169. data/spec/mongo/client_spec.rb +167 -17
  170. data/spec/mongo/cluster/topology/replica_set_spec.rb +18 -9
  171. data/spec/mongo/cluster/topology/sharded_spec.rb +11 -3
  172. data/spec/mongo/cluster/topology/single_spec.rb +12 -4
  173. data/spec/mongo/cluster_spec.rb +55 -10
  174. data/spec/mongo/collection/view/aggregation_spec.rb +188 -1
  175. data/spec/mongo/collection/view/explainable_spec.rb +1 -1
  176. data/spec/mongo/collection/view/immutable_spec.rb +103 -0
  177. data/spec/mongo/collection/view/map_reduce_spec.rb +99 -4
  178. data/spec/mongo/collection/view/readable_spec.rb +238 -6
  179. data/spec/mongo/collection/view/writable_spec.rb +4 -4
  180. data/spec/mongo/collection/view_spec.rb +459 -71
  181. data/spec/mongo/collection_spec.rb +1291 -9
  182. data/spec/mongo/command_monitoring_spec.rb +51 -0
  183. data/spec/mongo/connection_string_spec.rb +115 -0
  184. data/spec/mongo/crud_spec.rb +2 -2
  185. data/spec/mongo/cursor_spec.rb +3 -3
  186. data/spec/mongo/database_spec.rb +47 -11
  187. data/spec/mongo/dbref_spec.rb +149 -0
  188. data/spec/mongo/grid/file/chunk_spec.rb +5 -5
  189. data/spec/mongo/grid/file/{metadata_spec.rb → info_spec.rb} +29 -17
  190. data/spec/mongo/grid/file_spec.rb +8 -8
  191. data/spec/mongo/grid/fs_bucket_spec.rb +1020 -0
  192. data/spec/mongo/grid/stream/read_spec.rb +275 -0
  193. data/spec/mongo/grid/stream/write_spec.rb +440 -0
  194. data/spec/mongo/grid/stream_spec.rb +48 -0
  195. data/spec/mongo/gridfs_spec.rb +50 -0
  196. data/spec/mongo/logger_spec.rb +0 -40
  197. data/spec/mongo/monitoring/command_log_subscriber_spec.rb +76 -0
  198. data/spec/mongo/monitoring/event/command_started_spec.rb +26 -0
  199. data/spec/mongo/monitoring/event/command_succeeded_spec.rb +26 -0
  200. data/spec/mongo/monitoring/event/secure_spec.rb +57 -0
  201. data/spec/mongo/monitoring_spec.rb +168 -0
  202. data/spec/mongo/operation/commands/aggregate_spec.rb +69 -0
  203. data/spec/mongo/operation/{read → commands}/collections_info_spec.rb +1 -1
  204. data/spec/mongo/operation/{command_spec.rb → commands/command_spec.rb} +0 -18
  205. data/spec/mongo/operation/{read → commands}/indexes_spec.rb +1 -1
  206. data/spec/mongo/operation/{map_reduce_spec.rb → commands/map_reduce_spec.rb} +1 -19
  207. data/spec/mongo/operation/kill_cursors_spec.rb +1 -17
  208. data/spec/mongo/operation/read/get_more_spec.rb +0 -16
  209. data/spec/mongo/operation/read/query_spec.rb +19 -16
  210. data/spec/mongo/operation/{read_preferrable_spec.rb → read_preference_spec.rb} +11 -11
  211. data/spec/mongo/operation/write/bulk/{bulk_delete_spec.rb → delete_spec.rb} +18 -29
  212. data/spec/mongo/operation/write/bulk/{bulk_insert_spec.rb → insert_spec.rb} +3 -14
  213. data/spec/mongo/operation/write/bulk/{bulk_update_spec.rb → update_spec.rb} +8 -19
  214. data/spec/mongo/operation/write/command/delete_spec.rb +0 -16
  215. data/spec/mongo/operation/write/command/insert_spec.rb +0 -16
  216. data/spec/mongo/operation/write/command/update_spec.rb +0 -16
  217. data/spec/mongo/operation/write/delete_spec.rb +4 -4
  218. data/spec/mongo/operation/write/insert_spec.rb +2 -13
  219. data/spec/mongo/operation/write/update_spec.rb +7 -7
  220. data/spec/mongo/options/redacted_spec.rb +350 -0
  221. data/spec/mongo/protocol/kill_cursors_spec.rb +5 -3
  222. data/spec/mongo/protocol/query_spec.rb +15 -30
  223. data/spec/mongo/retryable_spec.rb +147 -0
  224. data/spec/mongo/server/connection_pool/queue_spec.rb +16 -0
  225. data/spec/mongo/server/connection_pool_spec.rb +50 -6
  226. data/spec/mongo/server/connection_spec.rb +49 -4
  227. data/spec/mongo/server/description_spec.rb +49 -3
  228. data/spec/mongo/server/monitor_spec.rb +51 -0
  229. data/spec/mongo/server_discovery_and_monitoring_spec.rb +32 -59
  230. data/spec/mongo/server_selection_rtt_spec.rb +37 -57
  231. data/spec/mongo/server_selection_spec.rb +19 -9
  232. data/spec/mongo/server_selector/nearest_spec.rb +35 -27
  233. data/spec/mongo/server_selector/primary_preferred_spec.rb +32 -30
  234. data/spec/mongo/server_selector/primary_spec.rb +21 -14
  235. data/spec/mongo/server_selector/secondary_preferred_spec.rb +28 -26
  236. data/spec/mongo/server_selector/secondary_spec.rb +24 -22
  237. data/spec/mongo/server_selector_spec.rb +87 -24
  238. data/spec/mongo/server_spec.rb +94 -8
  239. data/spec/mongo/socket/ssl_spec.rb +123 -13
  240. data/spec/mongo/socket/unix_spec.rb +52 -0
  241. data/spec/mongo/uri_spec.rb +295 -67
  242. data/spec/spec_helper.rb +40 -24
  243. data/spec/support/authorization.rb +23 -9
  244. data/spec/support/certificates/client.pem +4 -4
  245. data/spec/support/command_monitoring/bulkWrite.yml +73 -0
  246. data/spec/support/command_monitoring/command.yml +42 -0
  247. data/spec/support/command_monitoring/deleteMany.yml +55 -0
  248. data/spec/support/command_monitoring/deleteOne.yml +55 -0
  249. data/spec/support/command_monitoring/find.yml +219 -0
  250. data/spec/support/command_monitoring/insertMany.yml +81 -0
  251. data/spec/support/command_monitoring/insertOne.yml +51 -0
  252. data/spec/support/command_monitoring/updateMany.yml +67 -0
  253. data/spec/support/command_monitoring/updateOne.yml +95 -0
  254. data/spec/support/command_monitoring.rb +365 -0
  255. data/spec/support/connection_string.rb +228 -0
  256. data/spec/support/connection_string_tests/invalid-uris.yml +193 -0
  257. data/spec/support/connection_string_tests/valid-auth.yml +256 -0
  258. data/spec/support/connection_string_tests/valid-host_identifiers.yml +121 -0
  259. data/spec/support/connection_string_tests/valid-options.yml +30 -0
  260. data/spec/support/connection_string_tests/valid-unix_socket-absolute.yml +197 -0
  261. data/spec/support/connection_string_tests/valid-unix_socket-relative.yml +213 -0
  262. data/spec/support/connection_string_tests/valid-warnings.yml +55 -0
  263. data/spec/support/crud/read.rb +22 -19
  264. data/spec/support/crud/write.rb +58 -27
  265. data/spec/support/crud.rb +10 -2
  266. data/spec/support/gridfs.rb +637 -0
  267. data/spec/support/gridfs_tests/delete.yml +157 -0
  268. data/spec/support/gridfs_tests/download.yml +210 -0
  269. data/spec/support/gridfs_tests/download_by_name.yml +113 -0
  270. data/spec/support/gridfs_tests/upload.yml +158 -0
  271. data/spec/support/matchers.rb +1 -1
  272. data/spec/support/sdam/rs/equal_electionids.yml +44 -0
  273. data/spec/support/sdam/rs/new_primary_new_electionid.yml +95 -0
  274. data/spec/support/sdam/rs/null_election_id.yml +144 -0
  275. data/spec/support/sdam/rs/primary_disconnect_electionid.yml +124 -0
  276. data/spec/support/sdam/rs/primary_mismatched_me.yml +37 -0
  277. data/spec/support/sdam/rs/primary_to_no_primary_mismatched_me.yml +75 -0
  278. data/spec/support/sdam/rs/secondary_mismatched_me.yml +37 -0
  279. data/spec/support/sdam/sharded/mongos_disconnect.yml +104 -0
  280. data/spec/support/sdam/single/direct_connection_rsarbiter.yml +1 -1
  281. data/spec/support/sdam/single/direct_connection_rsprimary.yml +1 -1
  282. data/spec/support/sdam/single/direct_connection_rssecondary.yml +1 -1
  283. data/spec/support/sdam/single/direct_connection_slave.yml +1 -1
  284. data/spec/support/sdam/single/direct_connection_standalone.yml +1 -1
  285. data/spec/support/sdam/single/not_ok_response.yml +0 -1
  286. data/spec/support/server_discovery_and_monitoring.rb +22 -3
  287. data/spec/support/server_selection.rb +3 -1
  288. data/spec/support/shared/bulk_write.rb +218 -22
  289. data/spec/support/shared/server_selector.rb +80 -14
  290. data.tar.gz.sig +0 -0
  291. metadata +188 -59
  292. metadata.gz.sig +0 -0
  293. data/lib/mongo/bulk_write/bulk_writable.rb +0 -196
  294. data/lib/mongo/bulk_write/deletable.rb +0 -56
  295. data/lib/mongo/bulk_write/insertable.rb +0 -48
  296. data/lib/mongo/bulk_write/replacable.rb +0 -57
  297. data/lib/mongo/bulk_write/updatable.rb +0 -68
  298. data/lib/mongo/grid/fs.rb +0 -149
  299. data/lib/mongo/operation/list_collections/result.rb +0 -114
  300. data/lib/mongo/operation/list_indexes/result.rb +0 -118
  301. data/lib/mongo/operation/read/collections_info.rb +0 -68
  302. data/lib/mongo/operation/read/indexes.rb +0 -69
  303. data/lib/mongo/operation/read/list_collections.rb +0 -76
  304. data/lib/mongo/operation/read/list_indexes.rb +0 -78
  305. data/lib/mongo/operation/write/bulk/bulk_delete/result.rb +0 -75
  306. data/lib/mongo/operation/write/bulk/bulk_delete.rb +0 -145
  307. data/lib/mongo/operation/write/bulk/bulk_insert/result.rb +0 -130
  308. data/lib/mongo/operation/write/bulk/bulk_insert.rb +0 -132
  309. data/lib/mongo/operation/write/bulk/bulk_mergable.rb +0 -67
  310. data/lib/mongo/operation/write/bulk/bulk_update/result.rb +0 -162
  311. data/lib/mongo/operation/write/bulk/bulk_update.rb +0 -154
  312. data/lib/mongo/operation/write/bulk/legacy_bulk_mergable.rb +0 -83
  313. data/spec/mongo/bulk/bulk_write_spec.rb +0 -262
  314. data/spec/mongo/grid/fs_spec.rb +0 -160
  315. data/spec/mongo/loggable_spec.rb +0 -63
  316. data/spec/mongo/operation/aggregate_spec.rb +0 -127
  317. /data/lib/mongo/operation/{aggregate → commands/aggregate}/result.rb +0 -0
@@ -0,0 +1,428 @@
1
+ require 'spec_helper'
2
+
3
+ describe Mongo::BulkWrite do
4
+
5
+ before do
6
+ authorized_collection.delete_many
7
+ end
8
+
9
+ after do
10
+ authorized_collection.delete_many
11
+ end
12
+
13
+ describe '#execute' do
14
+
15
+ shared_examples_for 'an executable bulk write' do
16
+
17
+ context 'when providing a bad operation' do
18
+
19
+ let(:requests) do
20
+ [{ not_an_operation: { _id: 0 }}]
21
+ end
22
+
23
+ it 'raises an exception' do
24
+ expect {
25
+ bulk_write.execute
26
+ }.to raise_error(Mongo::Error::InvalidBulkOperationType)
27
+ end
28
+ end
29
+
30
+ context 'when the operations do not need to be split' do
31
+
32
+ context 'when a write error occurs' do
33
+
34
+ let(:requests) do
35
+ [
36
+ { insert_one: { _id: 0 }},
37
+ { insert_one: { _id: 1 }},
38
+ { insert_one: { _id: 0 }},
39
+ { insert_one: { _id: 1 }}
40
+ ]
41
+ end
42
+
43
+ let(:error) do
44
+ begin
45
+ bulk_write.execute
46
+ rescue => e
47
+ e
48
+ end
49
+ end
50
+
51
+ it 'raises an exception' do
52
+ expect {
53
+ bulk_write.execute
54
+ }.to raise_error(Mongo::Error::BulkWriteError)
55
+ end
56
+
57
+ it 'sets the document index on the error' do
58
+ expect(error.result[Mongo::Error::WRITE_ERRORS].first['index']).to eq(2)
59
+ end
60
+ end
61
+
62
+ context 'when provided a single insert one' do
63
+
64
+ let(:requests) do
65
+ [{ insert_one: { _id: 0 }}]
66
+ end
67
+
68
+ let(:result) do
69
+ bulk_write.execute
70
+ end
71
+
72
+ it 'inserts the document' do
73
+ expect(result.inserted_count).to eq(1)
74
+ expect(authorized_collection.find(_id: 0).count).to eq(1)
75
+ end
76
+ end
77
+
78
+ context 'when provided multiple insert ones' do
79
+
80
+ let(:requests) do
81
+ [
82
+ { insert_one: { _id: 0 }},
83
+ { insert_one: { _id: 1 }},
84
+ { insert_one: { _id: 2 }}
85
+ ]
86
+ end
87
+
88
+ let(:result) do
89
+ bulk_write.execute
90
+ end
91
+
92
+ it 'inserts the documents' do
93
+ expect(result.inserted_count).to eq(3)
94
+ expect(authorized_collection.find(_id: { '$in'=> [ 0, 1, 2 ]}).count).to eq(3)
95
+ end
96
+ end
97
+
98
+ context 'when provided a single delete one' do
99
+
100
+ let(:requests) do
101
+ [{ delete_one: { filter: { _id: 0 }}}]
102
+ end
103
+
104
+ let(:result) do
105
+ bulk_write.execute
106
+ end
107
+
108
+ before do
109
+ authorized_collection.insert_one({ _id: 0 })
110
+ end
111
+
112
+ it 'deletes the document' do
113
+ expect(result.deleted_count).to eq(1)
114
+ expect(authorized_collection.find(_id: 0).count).to eq(0)
115
+ end
116
+ end
117
+
118
+ context 'when provided multiple delete ones' do
119
+
120
+ let(:requests) do
121
+ [
122
+ { delete_one: { filter: { _id: 0 }}},
123
+ { delete_one: { filter: { _id: 1 }}},
124
+ { delete_one: { filter: { _id: 2 }}}
125
+ ]
126
+ end
127
+
128
+ let(:result) do
129
+ bulk_write.execute
130
+ end
131
+
132
+ before do
133
+ authorized_collection.insert_many([
134
+ { _id: 0 }, { _id: 1 }, { _id: 2 }
135
+ ])
136
+ end
137
+
138
+ it 'deletes the documents' do
139
+ expect(result.deleted_count).to eq(3)
140
+ expect(authorized_collection.find(_id: { '$in'=> [ 0, 1, 2 ]}).count).to eq(0)
141
+ end
142
+ end
143
+
144
+ context 'when provided a single delete many' do
145
+
146
+ let(:requests) do
147
+ [{ delete_many: { filter: { _id: 0 }}}]
148
+ end
149
+
150
+ let(:result) do
151
+ bulk_write.execute
152
+ end
153
+
154
+ before do
155
+ authorized_collection.insert_one({ _id: 0 })
156
+ end
157
+
158
+ it 'deletes the documents' do
159
+ expect(result.deleted_count).to eq(1)
160
+ expect(authorized_collection.find(_id: 0).count).to eq(0)
161
+ end
162
+ end
163
+
164
+ context 'when provided multiple delete many ops' do
165
+
166
+ let(:requests) do
167
+ [
168
+ { delete_many: { filter: { _id: 0 }}},
169
+ { delete_many: { filter: { _id: 1 }}},
170
+ { delete_many: { filter: { _id: 2 }}}
171
+ ]
172
+ end
173
+
174
+ let(:result) do
175
+ bulk_write.execute
176
+ end
177
+
178
+ before do
179
+ authorized_collection.insert_many([
180
+ { _id: 0 }, { _id: 1 }, { _id: 2 }
181
+ ])
182
+ end
183
+
184
+ it 'deletes the documents' do
185
+ expect(result.deleted_count).to eq(3)
186
+ expect(authorized_collection.find(_id: { '$in'=> [ 0, 1, 2 ]}).count).to eq(0)
187
+ end
188
+ end
189
+
190
+ context 'when providing a single replace one' do
191
+
192
+ let(:requests) do
193
+ [{ replace_one: { filter: { _id: 0 }, replacement: { name: 'test' }}}]
194
+ end
195
+
196
+ let(:result) do
197
+ bulk_write.execute
198
+ end
199
+
200
+ before do
201
+ authorized_collection.insert_one({ _id: 0 })
202
+ end
203
+
204
+ it 'replaces the document' do
205
+ expect(result.modified_count).to eq(1)
206
+ expect(authorized_collection.find(_id: 0).first[:name]).to eq('test')
207
+ end
208
+ end
209
+
210
+ context 'when providing a single update one' do
211
+
212
+ let(:requests) do
213
+ [{ update_one: { filter: { _id: 0 }, update: { "$set" => { name: 'test' }}}}]
214
+ end
215
+
216
+ let(:result) do
217
+ bulk_write.execute
218
+ end
219
+
220
+ before do
221
+ authorized_collection.insert_one({ _id: 0 })
222
+ end
223
+
224
+ it 'updates the document' do
225
+ expect(result.modified_count).to eq(1)
226
+ expect(authorized_collection.find(_id: 0).first[:name]).to eq('test')
227
+ end
228
+ end
229
+
230
+ context 'when providing a single update many' do
231
+
232
+ let(:requests) do
233
+ [{ update_many: { filter: { _id: 0 }, update: { "$set" => { name: 'test' }}}}]
234
+ end
235
+
236
+ let(:result) do
237
+ bulk_write.execute
238
+ end
239
+
240
+ before do
241
+ authorized_collection.insert_one({ _id: 0 })
242
+ end
243
+
244
+ it 'updates the documents' do
245
+ expect(result.modified_count).to eq(1)
246
+ expect(authorized_collection.find(_id: 0).first[:name]).to eq('test')
247
+ end
248
+ end
249
+ end
250
+
251
+ context 'when the operations need to be split' do
252
+
253
+ context 'when a write error occurs' do
254
+
255
+ let(:requests) do
256
+ 1001.times.map do |i|
257
+ { insert_one: { _id: i }}
258
+ end
259
+ end
260
+
261
+ let(:error) do
262
+ begin
263
+ bulk_write.execute
264
+ rescue => e
265
+ e
266
+ end
267
+ end
268
+
269
+ it 'raises an exception' do
270
+ expect {
271
+ requests.push({ insert_one: { _id: 5 }})
272
+ bulk_write.execute
273
+ }.to raise_error(Mongo::Error::BulkWriteError)
274
+ end
275
+
276
+ it 'sets the document index on the error' do
277
+ requests.push({ insert_one: { _id: 5 }})
278
+ expect(error.result[Mongo::Error::WRITE_ERRORS].first['index']).to eq(1001)
279
+ end
280
+ end
281
+
282
+ context 'when no write errors occur' do
283
+
284
+ let(:requests) do
285
+ 1001.times.map do |i|
286
+ { insert_one: { _id: i }}
287
+ end
288
+ end
289
+
290
+ let(:result) do
291
+ bulk_write.execute
292
+ end
293
+
294
+ it 'inserts the documents' do
295
+ expect(result.inserted_count).to eq(1001)
296
+ end
297
+ end
298
+ end
299
+
300
+ context 'when an operation exceeds the max bson size' do
301
+
302
+ let(:requests) do
303
+ 5.times.map do |i|
304
+ { insert_one: { _id: i, x: 'y' * 4000000 }}
305
+ end
306
+ end
307
+
308
+ let(:result) do
309
+ bulk_write.execute
310
+ end
311
+
312
+ it 'inserts the documents' do
313
+ expect(result.inserted_count).to eq(5)
314
+ end
315
+ end
316
+ end
317
+
318
+ context 'when the bulk write is unordered' do
319
+
320
+ let(:bulk_write) do
321
+ described_class.new(authorized_collection, requests, ordered: false)
322
+ end
323
+
324
+ it_behaves_like 'an executable bulk write'
325
+ end
326
+
327
+ context 'when the bulk write is ordered' do
328
+
329
+ let(:bulk_write) do
330
+ described_class.new(authorized_collection, requests, ordered: true)
331
+ end
332
+
333
+ it_behaves_like 'an executable bulk write'
334
+ end
335
+ end
336
+
337
+ describe '#initialize' do
338
+
339
+ let(:requests) do
340
+ [{ insert_one: { _id: 0 }}]
341
+ end
342
+
343
+ shared_examples_for 'a bulk write initializer' do
344
+
345
+ it 'sets the collection' do
346
+ expect(bulk_write.collection).to eq(authorized_collection)
347
+ end
348
+
349
+ it 'sets the requests' do
350
+ expect(bulk_write.requests).to eq(requests)
351
+ end
352
+ end
353
+
354
+ context 'when no options are provided' do
355
+
356
+ let(:bulk_write) do
357
+ described_class.new(authorized_collection, requests)
358
+ end
359
+
360
+ it 'sets empty options' do
361
+ expect(bulk_write.options).to be_empty
362
+ end
363
+
364
+ it_behaves_like 'a bulk write initializer'
365
+ end
366
+
367
+ context 'when options are provided' do
368
+
369
+ let(:bulk_write) do
370
+ described_class.new(authorized_collection, requests, ordered: true)
371
+ end
372
+
373
+ it 'sets the options' do
374
+ expect(bulk_write.options).to eq(ordered: true)
375
+ end
376
+ end
377
+
378
+ context 'when nil options are provided' do
379
+
380
+ let(:bulk_write) do
381
+ described_class.new(authorized_collection, requests, nil)
382
+ end
383
+
384
+ it 'sets empty options' do
385
+ expect(bulk_write.options).to be_empty
386
+ end
387
+ end
388
+ end
389
+
390
+ describe '#ordered?' do
391
+
392
+ context 'when no option provided' do
393
+
394
+ let(:bulk_write) do
395
+ described_class.new(authorized_collection, [])
396
+ end
397
+
398
+ it 'returns true' do
399
+ expect(bulk_write).to be_ordered
400
+ end
401
+ end
402
+
403
+ context 'when the option is provided' do
404
+
405
+ context 'when the option is true' do
406
+
407
+ let(:bulk_write) do
408
+ described_class.new(authorized_collection, [], ordered: true)
409
+ end
410
+
411
+ it 'returns true' do
412
+ expect(bulk_write).to be_ordered
413
+ end
414
+ end
415
+
416
+ context 'when the option is false' do
417
+
418
+ let(:bulk_write) do
419
+ described_class.new(authorized_collection, [], ordered: false)
420
+ end
421
+
422
+ it 'returns false' do
423
+ expect(bulk_write).to_not be_ordered
424
+ end
425
+ end
426
+ end
427
+ end
428
+ end
@@ -20,6 +20,10 @@ describe Mongo::Client do
20
20
  )
21
21
  end
22
22
 
23
+ after do
24
+ client.close
25
+ end
26
+
23
27
  context 'when the other is a client' do
24
28
 
25
29
  context 'when the options and cluster are equal' do
@@ -163,16 +167,20 @@ describe Mongo::Client do
163
167
  ['127.0.0.1:27017'],
164
168
  :read => { :mode => :primary },
165
169
  :local_threshold_ms => 10,
166
- :server_selection_timeout_ms => 10000,
170
+ :server_selection_timeout => 10000,
167
171
  :database => TEST_DB
168
172
  )
169
173
  end
170
174
 
175
+ let(:options) do
176
+ Mongo::Options::Redacted.new(:read => { :mode => :primary },
177
+ :local_threshold_ms => 10,
178
+ :server_selection_timeout => 10000,
179
+ :database => TEST_DB)
180
+ end
181
+
171
182
  let(:expected) do
172
- [client.cluster, { :read => { :mode => :primary },
173
- :local_threshold_ms => 10,
174
- :server_selection_timeout_ms => 10000,
175
- :database => TEST_DB }].hash
183
+ [client.cluster, options].hash
176
184
  end
177
185
 
178
186
  it 'returns a hash of the cluster and options' do
@@ -195,6 +203,23 @@ describe Mongo::Client do
195
203
  "<Mongo::Client:0x#{client.object_id} cluster=127.0.0.1:27017"
196
204
  )
197
205
  end
206
+
207
+ context 'when there is sensitive data in the options' do
208
+
209
+ let(:client) do
210
+ described_class.new(
211
+ ['127.0.0.1:27017'],
212
+ :read => { :mode => :primary },
213
+ :database => TEST_DB,
214
+ :password => 'some_password',
215
+ :user => 'emily'
216
+ )
217
+ end
218
+
219
+ it 'does not print out sensitive data' do
220
+ expect(client.inspect).not_to match('some_password')
221
+ end
222
+ end
198
223
  end
199
224
 
200
225
  describe '#initialize' do
@@ -222,6 +247,27 @@ describe Mongo::Client do
222
247
  expect(client[:users].name).to eq('users')
223
248
  end
224
249
  end
250
+
251
+ context 'when providing a custom logger' do
252
+
253
+ let(:logger) do
254
+ Logger.new($stdout).tap do |l|
255
+ l.level = Logger::FATAL
256
+ end
257
+ end
258
+
259
+ let(:client) do
260
+ authorized_client.with(logger: logger)
261
+ end
262
+
263
+ after do
264
+ client.close
265
+ end
266
+
267
+ it 'does not use the global logger' do
268
+ expect(client.cluster.logger).to_not eq(Mongo::Logger.logger)
269
+ end
270
+ end
225
271
  end
226
272
 
227
273
  context 'when providing a connection string' do
@@ -266,8 +312,12 @@ describe Mongo::Client do
266
312
  described_class.new(uri)
267
313
  end
268
314
 
315
+ let(:expected_options) do
316
+ Mongo::Options::Redacted.new(:write => { :w => 3 }, :database => 'testdb')
317
+ end
318
+
269
319
  it 'sets the options' do
270
- expect(client.options).to eq(:write => { :w => 3 }, :database => 'testdb')
320
+ expect(client.options).to eq(expected_options)
271
321
  end
272
322
  end
273
323
 
@@ -281,8 +331,12 @@ describe Mongo::Client do
281
331
  described_class.new(uri, :write => { :w => 3 })
282
332
  end
283
333
 
334
+ let(:expected_options) do
335
+ Mongo::Options::Redacted.new(:write => { :w => 3 }, :database => 'testdb')
336
+ end
337
+
284
338
  it 'sets the options' do
285
- expect(client.options).to eq(:write => { :w => 3 }, :database => 'testdb')
339
+ expect(client.options).to eq(expected_options)
286
340
  end
287
341
  end
288
342
 
@@ -296,8 +350,12 @@ describe Mongo::Client do
296
350
  described_class.new(uri, :write => { :w => 4 })
297
351
  end
298
352
 
353
+ let(:expected_options) do
354
+ Mongo::Options::Redacted.new(:write => { :w => 4 }, :database => 'testdb')
355
+ end
356
+
299
357
  it 'allows explicit options to take preference' do
300
- expect(client.options).to eq(:write => { :w => 4 }, :database => 'testdb')
358
+ expect(client.options).to eq(expected_options)
301
359
  end
302
360
  end
303
361
 
@@ -323,7 +381,8 @@ describe Mongo::Client do
323
381
  let(:client) do
324
382
  described_class.new(['127.0.0.1:27017'],
325
383
  :database => TEST_DB,
326
- :read => mode)
384
+ :read => mode,
385
+ :server_selection_timeout => 2)
327
386
  end
328
387
 
329
388
  let(:preference) do
@@ -341,7 +400,7 @@ describe Mongo::Client do
341
400
  end
342
401
 
343
402
  it 'passes the options to the read preference' do
344
- expect(preference.options[:database]).to eq(TEST_DB)
403
+ expect(preference.options[:server_selection_timeout]).to eq(2)
345
404
  end
346
405
  end
347
406
 
@@ -399,6 +458,33 @@ describe Mongo::Client do
399
458
  expect(preference).to be_a(Mongo::ServerSelector::Primary)
400
459
  end
401
460
  end
461
+
462
+ context 'when the read preference is printed' do
463
+
464
+ let(:client) do
465
+ described_class.new([ DEFAULT_ADDRESS ], options)
466
+ end
467
+
468
+ let(:options) do
469
+ { user: 'Emily', password: 'sensitive_data', server_selection_timeout: 0.1 }
470
+ end
471
+
472
+ before do
473
+ allow(client.database.cluster).to receive(:single?).and_return(false)
474
+ end
475
+
476
+ let(:error) do
477
+ begin
478
+ client.database.command(ping: 1)
479
+ rescue => e
480
+ e
481
+ end
482
+ end
483
+
484
+ it 'redacts sensitive client options' do
485
+ expect(error.message).not_to match(options[:password])
486
+ end
487
+ end
402
488
  end
403
489
 
404
490
  describe '#use' do
@@ -448,6 +534,17 @@ describe Mongo::Client do
448
534
 
449
535
  describe '#with' do
450
536
 
537
+ let(:client) do
538
+ described_class.new(['127.0.0.1:27017'], :database => TEST_DB)
539
+ end
540
+
541
+ context 'when providing nil' do
542
+
543
+ it 'returns the cloned client' do
544
+ expect(client.with(nil)).to eq(client)
545
+ end
546
+ end
547
+
451
548
  context 'when the write concern is not changed' do
452
549
 
453
550
  let(:client) do
@@ -461,20 +558,28 @@ describe Mongo::Client do
461
558
  client.with(:read => { :mode => :primary })
462
559
  end
463
560
 
561
+ let(:new_options) do
562
+ Mongo::Options::Redacted.new(:read => { :mode => :primary },
563
+ :write => { :w => 1 },
564
+ :database => TEST_DB)
565
+ end
566
+
567
+ let(:original_options) do
568
+ Mongo::Options::Redacted.new(:read => { :mode => :secondary },
569
+ :write => { :w => 1 },
570
+ :database => TEST_DB)
571
+ end
572
+
464
573
  it 'returns a new client' do
465
574
  expect(new_client).not_to equal(client)
466
575
  end
467
576
 
468
577
  it 'replaces the existing options' do
469
- expect(new_client.options).to eq({
470
- :read => { :mode => :primary }, :write => { :w => 1 }, :database => TEST_DB
471
- })
578
+ expect(new_client.options).to eq(new_options)
472
579
  end
473
580
 
474
581
  it 'does not modify the original client' do
475
- expect(client.options).to eq({
476
- :read => { :mode => :secondary }, :write => { :w => 1 }, :database => TEST_DB
477
- })
582
+ expect(client.options).to eq(original_options)
478
583
  end
479
584
 
480
585
  it 'keeps the same cluster' do
@@ -543,7 +648,7 @@ describe Mongo::Client do
543
648
  end
544
649
 
545
650
  it 'returns a acknowledged write concern' do
546
- expect(concern.get_last_error).to eq(:getlasterror => 1, :j => true)
651
+ expect(concern.get_last_error).to eq(:getlasterror => 1, 'j' => true)
547
652
  end
548
653
  end
549
654
 
@@ -592,4 +697,49 @@ describe Mongo::Client do
592
697
  end).to include('admin')
593
698
  end
594
699
  end
700
+
701
+ describe '#close' do
702
+
703
+ let(:client) do
704
+ described_class.new(['127.0.0.1:27017'])
705
+ end
706
+
707
+ before do
708
+ expect(client.cluster).to receive(:disconnect!).and_call_original
709
+ end
710
+
711
+ it 'disconnects the cluster and returns true' do
712
+ expect(client.close).to be(true)
713
+ end
714
+ end
715
+
716
+ describe '#reconnect' do
717
+
718
+ let(:client) do
719
+ described_class.new(['127.0.0.1:27017'])
720
+ end
721
+
722
+ before do
723
+ expect(client.cluster).to receive(:reconnect!).and_call_original
724
+ end
725
+
726
+ it 'reconnects the cluster and returns true' do
727
+ expect(client.reconnect).to be(true)
728
+ end
729
+ end
730
+
731
+ describe '#dup' do
732
+
733
+ let(:client) do
734
+ described_class.new(
735
+ ['127.0.0.1:27017'],
736
+ :read => { :mode => :primary },
737
+ :database => TEST_DB
738
+ )
739
+ end
740
+
741
+ it 'creates a client with Redacted options' do
742
+ expect(client.dup.options).to be_a(Mongo::Options::Redacted)
743
+ end
744
+ end
595
745
  end