mongo 2.1.0.beta → 2.2.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 (342) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/README.md +10 -3
  4. data/Rakefile +1 -7
  5. data/lib/mongo/address/ipv4.rb +6 -1
  6. data/lib/mongo/address/unix.rb +2 -2
  7. data/lib/mongo/address.rb +32 -10
  8. data/lib/mongo/auth/cr/conversation.rb +1 -1
  9. data/lib/mongo/auth/ldap/conversation.rb +7 -3
  10. data/lib/mongo/auth/scram/conversation.rb +9 -3
  11. data/lib/mongo/auth/user/view.rb +23 -2
  12. data/lib/mongo/auth/x509/conversation.rb +1 -1
  13. data/lib/mongo/bulk_write/combineable.rb +51 -0
  14. data/lib/mongo/bulk_write/ordered_combiner.rb +55 -0
  15. data/lib/mongo/bulk_write/result.rb +61 -8
  16. data/lib/mongo/bulk_write/result_combiner.rb +117 -0
  17. data/lib/mongo/bulk_write/transformable.rb +132 -0
  18. data/lib/mongo/bulk_write/unordered_combiner.rb +52 -0
  19. data/lib/mongo/bulk_write/validatable.rb +62 -0
  20. data/lib/mongo/bulk_write.rb +164 -23
  21. data/lib/mongo/client.rb +75 -18
  22. data/lib/mongo/cluster/topology/replica_set.rb +8 -6
  23. data/lib/mongo/cluster/topology/unknown.rb +5 -2
  24. data/lib/mongo/cluster.rb +85 -5
  25. data/lib/mongo/collection/view/aggregation.rb +19 -45
  26. data/lib/mongo/collection/view/builder/aggregation.rb +98 -0
  27. data/lib/mongo/collection/view/builder/find_command.rb +111 -0
  28. data/lib/mongo/collection/view/builder/flags.rb +62 -0
  29. data/lib/mongo/collection/view/builder/map_reduce.rb +134 -0
  30. data/lib/mongo/collection/view/builder/modifiers.rb +80 -0
  31. data/lib/mongo/collection/view/builder/op_query.rb +83 -0
  32. data/lib/mongo/collection/view/builder.rb +20 -0
  33. data/lib/mongo/collection/view/explainable.rb +15 -0
  34. data/lib/mongo/collection/view/immutable.rb +4 -11
  35. data/lib/mongo/collection/view/iterable.rb +40 -5
  36. data/lib/mongo/collection/view/map_reduce.rb +67 -37
  37. data/lib/mongo/collection/view/readable.rb +114 -100
  38. data/lib/mongo/collection/view/writable.rb +46 -22
  39. data/lib/mongo/collection/view.rb +25 -22
  40. data/lib/mongo/collection.rb +130 -12
  41. data/lib/mongo/cursor/builder/get_more_command.rb +71 -0
  42. data/lib/mongo/cursor/builder/kill_cursors_command.rb +62 -0
  43. data/lib/mongo/cursor/builder/op_get_more.rb +61 -0
  44. data/lib/mongo/cursor/builder/op_kill_cursors.rb +56 -0
  45. data/lib/mongo/cursor/builder.rb +18 -0
  46. data/lib/mongo/cursor.rb +76 -21
  47. data/lib/mongo/database/view.rb +11 -6
  48. data/lib/mongo/database.rb +16 -6
  49. data/lib/mongo/dbref.rb +9 -9
  50. data/lib/mongo/{bulk_write/unordered_bulk_write.rb → error/closed_stream.rb} +12 -21
  51. data/lib/mongo/{bulk_write/ordered_bulk_write.rb → error/extra_file_chunk.rb} +13 -27
  52. data/lib/mongo/error/file_not_found.rb +37 -0
  53. data/lib/mongo/error/invalid_file.rb +2 -2
  54. data/lib/mongo/error/invalid_file_revision.rb +37 -0
  55. data/lib/mongo/error/invalid_uri.rb +5 -4
  56. data/lib/mongo/error/invalid_write_concern.rb +35 -0
  57. data/lib/mongo/error/missing_file_chunk.rb +38 -0
  58. data/lib/mongo/error/operation_failure.rb +33 -2
  59. data/lib/mongo/error/unchangeable_collection_option.rb +38 -0
  60. data/lib/mongo/error/unexpected_chunk_length.rb +39 -0
  61. data/lib/mongo/error.rb +8 -0
  62. data/lib/mongo/grid/file/chunk.rb +9 -9
  63. data/lib/mongo/grid/file/{metadata.rb → info.rb} +41 -39
  64. data/lib/mongo/grid/file.rb +12 -9
  65. data/lib/mongo/grid/fs_bucket.rb +448 -0
  66. data/lib/mongo/grid/stream/read.rb +208 -0
  67. data/lib/mongo/grid/stream/write.rb +187 -0
  68. data/lib/mongo/grid/stream.rb +64 -0
  69. data/lib/mongo/grid.rb +2 -1
  70. data/lib/mongo/index/view.rb +7 -4
  71. data/lib/mongo/index.rb +5 -0
  72. data/lib/mongo/loggable.rb +34 -57
  73. data/lib/mongo/logger.rb +16 -78
  74. data/lib/mongo/monitoring/command_log_subscriber.rb +38 -14
  75. data/lib/mongo/monitoring/event/command_started.rb +2 -1
  76. data/lib/mongo/monitoring/event/command_succeeded.rb +24 -2
  77. data/lib/mongo/monitoring/event/secure.rb +58 -0
  78. data/lib/mongo/monitoring/event.rb +1 -0
  79. data/lib/mongo/monitoring/publishable.rb +22 -12
  80. data/lib/mongo/monitoring.rb +1 -5
  81. data/lib/mongo/operation/commands/aggregate/result.rb +89 -0
  82. data/lib/mongo/operation/commands/aggregate.rb +64 -0
  83. data/lib/mongo/operation/commands/collections_info/result.rb +41 -0
  84. data/lib/mongo/operation/{read → commands}/collections_info.rb +5 -3
  85. data/lib/mongo/operation/commands/command.rb +47 -0
  86. data/lib/mongo/operation/commands/find/result.rb +62 -0
  87. data/lib/mongo/operation/commands/find.rb +27 -0
  88. data/lib/mongo/operation/commands/get_more/result.rb +62 -0
  89. data/lib/mongo/operation/commands/get_more.rb +27 -0
  90. data/lib/mongo/operation/{read → commands}/indexes.rb +9 -6
  91. data/lib/mongo/operation/{list_collections → commands/list_collections}/result.rb +1 -21
  92. data/lib/mongo/operation/{read → commands}/list_collections.rb +4 -32
  93. data/lib/mongo/operation/{list_indexes → commands/list_indexes}/result.rb +1 -21
  94. data/lib/mongo/operation/{read → commands}/list_indexes.rb +3 -33
  95. data/lib/mongo/operation/commands/map_reduce/result.rb +119 -0
  96. data/lib/mongo/operation/commands/map_reduce.rb +49 -0
  97. data/lib/mongo/operation/commands/parallel_scan/result.rb +64 -0
  98. data/lib/mongo/operation/commands/parallel_scan.rb +52 -0
  99. data/lib/mongo/operation/commands/user_query.rb +71 -0
  100. data/lib/mongo/operation/commands/users_info/result.rb +38 -0
  101. data/lib/mongo/operation/commands/users_info.rb +48 -0
  102. data/lib/mongo/operation/commands.rb +26 -0
  103. data/lib/mongo/operation/executable.rb +4 -68
  104. data/lib/mongo/operation/kill_cursors.rb +3 -3
  105. data/lib/mongo/operation/object_id_generator.rb +36 -0
  106. data/lib/mongo/operation/read/get_more.rb +2 -22
  107. data/lib/mongo/operation/read/query/result.rb +40 -0
  108. data/lib/mongo/operation/read/query.rb +4 -21
  109. data/lib/mongo/operation/read.rb +0 -4
  110. data/lib/mongo/operation/{read_preferrable.rb → read_preference.rb} +3 -2
  111. data/lib/mongo/operation/result.rb +43 -1
  112. data/lib/mongo/operation/specifiable.rb +59 -1
  113. data/lib/mongo/operation/write/bulk/bulkable.rb +83 -0
  114. data/lib/mongo/operation/write/bulk/delete/result.rb +67 -0
  115. data/lib/mongo/operation/write/bulk/delete.rb +71 -0
  116. data/lib/mongo/operation/write/bulk/insert/result.rb +129 -0
  117. data/lib/mongo/operation/write/bulk/insert.rb +96 -0
  118. data/lib/mongo/operation/write/bulk/legacy_mergable.rb +87 -0
  119. data/lib/mongo/operation/write/bulk/mergable.rb +71 -0
  120. data/lib/mongo/operation/write/bulk/update/result.rb +174 -0
  121. data/lib/mongo/operation/write/bulk/update.rb +81 -0
  122. data/lib/mongo/operation/write/bulk.rb +6 -3
  123. data/lib/mongo/operation/write/command/create_index.rb +0 -1
  124. data/lib/mongo/operation/write/command/create_user.rb +0 -1
  125. data/lib/mongo/operation/write/command/delete.rb +3 -3
  126. data/lib/mongo/operation/write/command/drop_index.rb +0 -1
  127. data/lib/mongo/operation/write/command/insert.rb +4 -3
  128. data/lib/mongo/operation/write/command/remove_user.rb +0 -1
  129. data/lib/mongo/operation/write/command/update.rb +6 -4
  130. data/lib/mongo/operation/write/command/update_user.rb +0 -1
  131. data/lib/mongo/operation/write/command/writable.rb +13 -18
  132. data/lib/mongo/operation/write/create_index.rb +4 -27
  133. data/lib/mongo/operation/write/create_user.rb +4 -30
  134. data/lib/mongo/operation/write/delete.rb +6 -29
  135. data/lib/mongo/operation/write/drop_index.rb +3 -3
  136. data/lib/mongo/operation/write/gle.rb +49 -0
  137. data/lib/mongo/operation/write/idable.rb +24 -2
  138. data/lib/mongo/operation/write/insert.rb +2 -24
  139. data/lib/mongo/operation/write/remove_user.rb +4 -27
  140. data/lib/mongo/operation/write/update.rb +13 -36
  141. data/lib/mongo/operation/write/update_user.rb +4 -30
  142. data/lib/mongo/operation/write/write_command_enabled.rb +53 -0
  143. data/lib/mongo/operation/write.rb +2 -0
  144. data/lib/mongo/operation.rb +33 -5
  145. data/lib/mongo/options/mapper.rb +26 -2
  146. data/lib/mongo/options/redacted.rb +156 -0
  147. data/lib/mongo/options.rb +1 -0
  148. data/lib/mongo/protocol/bit_vector.rb +11 -9
  149. data/lib/mongo/protocol/delete.rb +78 -3
  150. data/lib/mongo/protocol/get_more.rb +59 -2
  151. data/lib/mongo/protocol/insert.rb +73 -1
  152. data/lib/mongo/protocol/kill_cursors.rb +66 -4
  153. data/lib/mongo/protocol/message.rb +44 -20
  154. data/lib/mongo/protocol/query.rb +153 -65
  155. data/lib/mongo/protocol/reply.rb +92 -1
  156. data/lib/mongo/protocol/serializers.rb +49 -40
  157. data/lib/mongo/protocol/update.rb +93 -1
  158. data/lib/mongo/retryable.rb +101 -0
  159. data/lib/mongo/server/connectable.rb +28 -8
  160. data/lib/mongo/server/connection.rb +52 -10
  161. data/lib/mongo/server/connection_pool/queue.rb +15 -0
  162. data/lib/mongo/server/connection_pool.rb +12 -15
  163. data/lib/mongo/server/description/features.rb +4 -2
  164. data/lib/mongo/server/description.rb +39 -3
  165. data/lib/mongo/server/monitor/connection.rb +49 -28
  166. data/lib/mongo/server/monitor.rb +3 -14
  167. data/lib/mongo/server.rb +31 -4
  168. data/lib/mongo/server_selector/selectable.rb +58 -32
  169. data/lib/mongo/server_selector.rb +19 -10
  170. data/lib/mongo/socket/ssl.rb +4 -1
  171. data/lib/mongo/socket/tcp.rb +2 -2
  172. data/lib/mongo/socket/unix.rb +5 -8
  173. data/lib/mongo/socket.rb +11 -4
  174. data/lib/mongo/uri.rb +245 -139
  175. data/lib/mongo/version.rb +1 -1
  176. data/lib/mongo/write_concern.rb +21 -6
  177. data/lib/mongo.rb +4 -4
  178. data/mongo.gemspec +1 -2
  179. data/spec/mongo/address/unix_spec.rb +1 -1
  180. data/spec/mongo/address_spec.rb +25 -0
  181. data/spec/mongo/auth/ldap/conversation_spec.rb +43 -0
  182. data/spec/mongo/auth/user/view_spec.rb +26 -1
  183. data/spec/mongo/bulk_write/ordered_combiner_spec.rb +284 -0
  184. data/spec/mongo/bulk_write/unordered_combiner_spec.rb +239 -0
  185. data/spec/mongo/bulk_write_spec.rb +385 -161
  186. data/spec/mongo/client_spec.rb +193 -23
  187. data/spec/mongo/cluster/topology/replica_set_spec.rb +2 -0
  188. data/spec/mongo/collection/view/aggregation_spec.rb +65 -0
  189. data/spec/mongo/collection/view/builder/find_command_spec.rb +167 -0
  190. data/spec/mongo/collection/view/builder/flags_spec.rb +106 -0
  191. data/spec/mongo/collection/view/builder/modifiers_spec.rb +210 -0
  192. data/spec/mongo/collection/view/builder/op_query_spec.rb +154 -0
  193. data/spec/mongo/collection/view/explainable_spec.rb +1 -2
  194. data/spec/mongo/collection/view/immutable_spec.rb +54 -0
  195. data/spec/mongo/collection/view/map_reduce_spec.rb +104 -9
  196. data/spec/mongo/collection/view/readable_spec.rb +109 -112
  197. data/spec/mongo/collection/view_spec.rb +119 -487
  198. data/spec/mongo/collection_spec.rb +1002 -33
  199. data/spec/mongo/command_monitoring_spec.rb +64 -0
  200. data/spec/mongo/connection_string_spec.rb +115 -0
  201. data/spec/mongo/cursor/builder/get_more_command_spec.rb +160 -0
  202. data/spec/mongo/cursor/builder/op_get_more_spec.rb +52 -0
  203. data/spec/mongo/cursor_spec.rb +10 -60
  204. data/spec/mongo/database_spec.rb +81 -12
  205. data/spec/mongo/dbref_spec.rb +4 -4
  206. data/spec/mongo/grid/file/chunk_spec.rb +6 -6
  207. data/spec/mongo/grid/file/{metadata_spec.rb → info_spec.rb} +29 -17
  208. data/spec/mongo/grid/file_spec.rb +8 -8
  209. data/spec/mongo/grid/fs_bucket_spec.rb +1020 -0
  210. data/spec/mongo/grid/stream/read_spec.rb +275 -0
  211. data/spec/mongo/grid/stream/write_spec.rb +440 -0
  212. data/spec/mongo/grid/stream_spec.rb +48 -0
  213. data/spec/mongo/gridfs_spec.rb +50 -0
  214. data/spec/mongo/index/view_spec.rb +41 -0
  215. data/spec/mongo/logger_spec.rb +0 -40
  216. data/spec/mongo/monitoring/command_log_subscriber_spec.rb +76 -0
  217. data/spec/mongo/monitoring/event/command_started_spec.rb +26 -0
  218. data/spec/mongo/monitoring/event/command_succeeded_spec.rb +26 -0
  219. data/spec/mongo/monitoring/event/secure_spec.rb +57 -0
  220. data/spec/mongo/operation/{aggregate → commands/aggregate}/result_spec.rb +1 -1
  221. data/spec/mongo/operation/commands/aggregate_spec.rb +69 -0
  222. data/spec/mongo/operation/{read → commands}/collections_info_spec.rb +1 -1
  223. data/spec/mongo/operation/{command_spec.rb → commands/command_spec.rb} +1 -19
  224. data/spec/mongo/operation/{read → commands}/indexes_spec.rb +1 -1
  225. data/spec/mongo/operation/{map_reduce_spec.rb → commands/map_reduce_spec.rb} +1 -19
  226. data/spec/mongo/operation/kill_cursors_spec.rb +1 -17
  227. data/spec/mongo/operation/read/get_more_spec.rb +0 -16
  228. data/spec/mongo/operation/read/query_spec.rb +19 -16
  229. data/spec/mongo/operation/{read_preferrable_spec.rb → read_preference_spec.rb} +11 -11
  230. data/spec/mongo/operation/result_spec.rb +19 -0
  231. data/spec/mongo/operation/write/bulk/{bulk_delete_spec.rb → delete_spec.rb} +17 -28
  232. data/spec/mongo/operation/write/bulk/{bulk_insert_spec.rb → insert_spec.rb} +1 -12
  233. data/spec/mongo/operation/write/bulk/{bulk_update_spec.rb → update_spec.rb} +7 -18
  234. data/spec/mongo/operation/write/command/delete_spec.rb +18 -9
  235. data/spec/mongo/operation/write/command/insert_spec.rb +18 -9
  236. data/spec/mongo/operation/write/command/update_spec.rb +18 -9
  237. data/spec/mongo/operation/write/delete_spec.rb +3 -3
  238. data/spec/mongo/operation/write/insert_spec.rb +0 -11
  239. data/spec/mongo/operation/write/update_spec.rb +6 -6
  240. data/spec/mongo/options/redacted_spec.rb +350 -0
  241. data/spec/mongo/protocol/delete_spec.rb +4 -4
  242. data/spec/mongo/protocol/get_more_spec.rb +4 -4
  243. data/spec/mongo/protocol/insert_spec.rb +3 -3
  244. data/spec/mongo/protocol/kill_cursors_spec.rb +8 -6
  245. data/spec/mongo/protocol/query_spec.rb +21 -7
  246. data/spec/mongo/protocol/update_spec.rb +5 -5
  247. data/spec/mongo/retryable_spec.rb +221 -0
  248. data/spec/mongo/server/connection_pool/queue_spec.rb +16 -0
  249. data/spec/mongo/server/connection_pool_spec.rb +42 -6
  250. data/spec/mongo/server/connection_spec.rb +86 -1
  251. data/spec/mongo/server/description/features_spec.rb +25 -0
  252. data/spec/mongo/server/description_spec.rb +42 -0
  253. data/spec/mongo/server/monitor_spec.rb +44 -0
  254. data/spec/mongo/server_discovery_and_monitoring_spec.rb +25 -59
  255. data/spec/mongo/server_selection_rtt_spec.rb +37 -57
  256. data/spec/mongo/server_selection_spec.rb +5 -3
  257. data/spec/mongo/server_selector/nearest_spec.rb +35 -27
  258. data/spec/mongo/server_selector/primary_preferred_spec.rb +32 -30
  259. data/spec/mongo/server_selector/primary_spec.rb +21 -14
  260. data/spec/mongo/server_selector/secondary_preferred_spec.rb +28 -26
  261. data/spec/mongo/server_selector/secondary_spec.rb +24 -22
  262. data/spec/mongo/server_selector_spec.rb +87 -24
  263. data/spec/mongo/server_spec.rb +78 -15
  264. data/spec/mongo/socket/ssl_spec.rb +101 -57
  265. data/spec/mongo/socket/unix_spec.rb +52 -0
  266. data/spec/mongo/uri_spec.rb +271 -59
  267. data/spec/mongo/write_concern_spec.rb +126 -0
  268. data/spec/spec_helper.rb +29 -23
  269. data/spec/support/authorization.rb +4 -5
  270. data/spec/support/command_monitoring/bulkWrite.yml +73 -0
  271. data/spec/support/command_monitoring/command.yml +42 -0
  272. data/spec/support/command_monitoring/deleteMany.yml +55 -0
  273. data/spec/support/command_monitoring/deleteOne.yml +55 -0
  274. data/spec/support/command_monitoring/find.yml +268 -0
  275. data/spec/support/command_monitoring/insertMany.yml +81 -0
  276. data/spec/support/command_monitoring/insertOne.yml +51 -0
  277. data/spec/support/command_monitoring/updateMany.yml +67 -0
  278. data/spec/support/command_monitoring/updateOne.yml +95 -0
  279. data/spec/support/command_monitoring.rb +373 -0
  280. data/spec/support/connection_string.rb +228 -0
  281. data/spec/support/connection_string_tests/invalid-uris.yml +193 -0
  282. data/spec/support/connection_string_tests/valid-auth.yml +256 -0
  283. data/spec/support/connection_string_tests/valid-host_identifiers.yml +121 -0
  284. data/spec/support/connection_string_tests/valid-options.yml +30 -0
  285. data/spec/support/connection_string_tests/valid-unix_socket-absolute.yml +197 -0
  286. data/spec/support/connection_string_tests/valid-unix_socket-relative.yml +213 -0
  287. data/spec/support/connection_string_tests/valid-warnings.yml +55 -0
  288. data/spec/support/crud/read.rb +14 -10
  289. data/spec/support/crud/write.rb +36 -9
  290. data/spec/support/crud.rb +10 -2
  291. data/spec/support/gridfs.rb +637 -0
  292. data/spec/support/gridfs_tests/delete.yml +157 -0
  293. data/spec/support/gridfs_tests/download.yml +210 -0
  294. data/spec/support/gridfs_tests/download_by_name.yml +113 -0
  295. data/spec/support/gridfs_tests/upload.yml +158 -0
  296. data/spec/support/matchers.rb +2 -2
  297. data/spec/support/sdam/rs/equal_electionids.yml +1 -2
  298. data/spec/support/sdam/rs/new_primary_new_electionid.yml +0 -3
  299. data/spec/support/sdam/rs/primary_mismatched_me.yml +37 -0
  300. data/spec/support/sdam/rs/primary_to_no_primary_mismatched_me.yml +75 -0
  301. data/spec/support/sdam/rs/rsother_discovered.yml +24 -3
  302. data/spec/support/sdam/rs/secondary_mismatched_me.yml +37 -0
  303. data/spec/support/sdam/rs/stepdown_change_set_name.yml +59 -0
  304. data/spec/support/sdam/single/direct_connection_rsarbiter.yml +1 -1
  305. data/spec/support/sdam/single/direct_connection_rsprimary.yml +1 -1
  306. data/spec/support/sdam/single/direct_connection_rssecondary.yml +1 -1
  307. data/spec/support/sdam/single/direct_connection_slave.yml +1 -1
  308. data/spec/support/sdam/single/direct_connection_standalone.yml +1 -1
  309. data/spec/support/sdam/single/not_ok_response.yml +0 -1
  310. data/spec/support/server_discovery_and_monitoring.rb +3 -1
  311. data/spec/support/server_selection.rb +3 -1
  312. data/spec/support/shared/bulk_write.rb +192 -0
  313. data/spec/support/shared/protocol.rb +5 -5
  314. data/spec/support/shared/server_selector.rb +78 -13
  315. data/spec/support/travis.rb +1 -1
  316. data.tar.gz.sig +0 -0
  317. metadata +211 -72
  318. metadata.gz.sig +0 -0
  319. data/lib/mongo/bulk_write/bulk_writable.rb +0 -252
  320. data/lib/mongo/bulk_write/deletable.rb +0 -57
  321. data/lib/mongo/bulk_write/insertable.rb +0 -49
  322. data/lib/mongo/bulk_write/replacable.rb +0 -58
  323. data/lib/mongo/bulk_write/updatable.rb +0 -69
  324. data/lib/mongo/grid/fs.rb +0 -146
  325. data/lib/mongo/operation/aggregate/result.rb +0 -103
  326. data/lib/mongo/operation/aggregate.rb +0 -108
  327. data/lib/mongo/operation/command.rb +0 -61
  328. data/lib/mongo/operation/map_reduce/result.rb +0 -122
  329. data/lib/mongo/operation/map_reduce.rb +0 -95
  330. data/lib/mongo/operation/parallel_scan/result.rb +0 -72
  331. data/lib/mongo/operation/parallel_scan.rb +0 -76
  332. data/lib/mongo/operation/write/bulk/bulk_delete/result.rb +0 -75
  333. data/lib/mongo/operation/write/bulk/bulk_delete.rb +0 -145
  334. data/lib/mongo/operation/write/bulk/bulk_insert/result.rb +0 -130
  335. data/lib/mongo/operation/write/bulk/bulk_insert.rb +0 -132
  336. data/lib/mongo/operation/write/bulk/bulk_mergable.rb +0 -67
  337. data/lib/mongo/operation/write/bulk/bulk_update/result.rb +0 -174
  338. data/lib/mongo/operation/write/bulk/bulk_update.rb +0 -154
  339. data/lib/mongo/operation/write/bulk/legacy_bulk_mergable.rb +0 -83
  340. data/spec/mongo/grid/fs_spec.rb +0 -160
  341. data/spec/mongo/loggable_spec.rb +0 -63
  342. data/spec/mongo/operation/aggregate_spec.rb +0 -127
@@ -4,6 +4,17 @@ describe Mongo::Collection do
4
4
 
5
5
  after do
6
6
  authorized_collection.delete_many
7
+ collection_with_validator.drop()
8
+ end
9
+
10
+ let(:collection_invalid_write_concern) do
11
+ authorized_collection.client.with(write: { w: (WRITE_CONCERN[:w] + 1) })[authorized_collection.name]
12
+ end
13
+ let(:collection_with_validator) do
14
+ authorized_client[:validating,
15
+ :validator => { :a => { '$exists' => true } }].tap do |c|
16
+ c.create
17
+ end
7
18
  end
8
19
 
9
20
  describe '#==' do
@@ -86,6 +97,172 @@ describe Mongo::Collection do
86
97
  end
87
98
  end
88
99
 
100
+ describe '#with' do
101
+
102
+ let(:client) do
103
+ Mongo::Client.new(ADDRESSES)
104
+ end
105
+
106
+ let(:database) do
107
+ Mongo::Database.new(client, :test)
108
+ end
109
+
110
+ let(:collection) do
111
+ database.collection(:users)
112
+ end
113
+
114
+ let(:new_collection) do
115
+ collection.with(new_options)
116
+ end
117
+
118
+ context 'when new read options are provided' do
119
+
120
+ let(:new_options) do
121
+ { read: { mode: :secondary } }
122
+ end
123
+
124
+ it 'returns a new collection' do
125
+ expect(new_collection).not_to be(collection)
126
+ end
127
+
128
+ it 'sets the new read options on the new collection' do
129
+ expect(new_collection.read_preference).to eq(Mongo::ServerSelector.get(new_options[:read]))
130
+ end
131
+
132
+ context 'when the client has a server selection timeout setting' do
133
+
134
+ let(:client) do
135
+ Mongo::Client.new(ADDRESSES, server_selection_timeout: 2)
136
+ end
137
+
138
+ let(:server_selection_timeout) do
139
+ new_collection.read_preference.server_selection_timeout
140
+ end
141
+
142
+ it 'keeps the server_selection_timeout setting from client' do
143
+ expect(server_selection_timeout).to eq(client.options[:server_selection_timeout])
144
+ end
145
+ end
146
+
147
+ context 'when the client has a read preference set' do
148
+
149
+ let(:client) do
150
+ Mongo::Client.new(ADDRESSES, read: { mode: :primary_preferred })
151
+ end
152
+
153
+ it 'sets the new read options on the new collection' do
154
+ expect(new_collection.read_preference).to eq(Mongo::ServerSelector.get(new_options[:read]))
155
+ end
156
+ end
157
+
158
+ context 'when the client has a read preference and server selection timeout set' do
159
+
160
+ let(:client) do
161
+ Mongo::Client.new(ADDRESSES, read: { mode: :primary_preferred }, server_selection_timeout: 2)
162
+ end
163
+
164
+ let(:server_selection_timeout) do
165
+ new_collection.read_preference.server_selection_timeout
166
+ end
167
+
168
+ it 'sets the new read options on the new collection' do
169
+ expect(new_collection.read_preference).to eq(Mongo::ServerSelector.get(new_options[:read]))
170
+ end
171
+
172
+ it 'keeps the server_selection_timeout setting from client' do
173
+ expect(server_selection_timeout).to eq(client.options[:server_selection_timeout])
174
+ end
175
+ end
176
+ end
177
+
178
+ context 'when new write options are provided' do
179
+
180
+ let(:new_options) do
181
+ { write: { w: 5 } }
182
+ end
183
+
184
+ it 'returns a new collection' do
185
+ expect(new_collection).not_to be(collection)
186
+ end
187
+
188
+ it 'sets the new write options on the new collection' do
189
+ expect(new_collection.write_concern.options).to eq(Mongo::WriteConcern.get(new_options[:write]).options)
190
+ end
191
+
192
+ context 'when the client has a write concern set' do
193
+
194
+ let(:client) do
195
+ Mongo::Client.new(ADDRESSES, write: { w: 10 })
196
+ end
197
+
198
+ it 'sets the new write options on the new collection' do
199
+ expect(new_collection.write_concern.options).to eq(Mongo::WriteConcern.get(new_options[:write]).options)
200
+ end
201
+ end
202
+ end
203
+
204
+ context 'when new read and write options are provided' do
205
+
206
+ let(:new_options) do
207
+ {
208
+ read: { mode: :secondary },
209
+ write: { w: 4}
210
+ }
211
+ end
212
+
213
+ it 'returns a new collection' do
214
+ expect(new_collection).not_to be(collection)
215
+ end
216
+
217
+ it 'sets the new read options on the new collection' do
218
+ expect(new_collection.read_preference).to eq(Mongo::ServerSelector.get(new_options[:read]))
219
+ end
220
+
221
+ it 'sets the new write options on the new collection' do
222
+ expect(new_collection.write_concern.options).to eq(Mongo::WriteConcern.get(new_options[:write]).options)
223
+ end
224
+
225
+ context 'when the client has a server selection timeout setting' do
226
+
227
+ let(:client) do
228
+ Mongo::Client.new(ADDRESSES, server_selection_timeout: 2)
229
+ end
230
+
231
+ let(:server_selection_timeout) do
232
+ new_collection.read_preference.server_selection_timeout
233
+ end
234
+
235
+ it 'keeps the server_selection_timeout setting from client' do
236
+ expect(server_selection_timeout).to eq(client.options[:server_selection_timeout])
237
+ end
238
+ end
239
+
240
+ context 'when the client has a read preference set' do
241
+
242
+ let(:client) do
243
+ Mongo::Client.new(ADDRESSES, read: { mode: :primary_preferred })
244
+ end
245
+
246
+ it 'sets the new read options on the new collection' do
247
+ expect(new_collection.read_preference).to eq(Mongo::ServerSelector.get(new_options[:read]))
248
+ end
249
+ end
250
+ end
251
+
252
+ context 'when neither read nor write options are provided' do
253
+
254
+ let(:new_options) do
255
+ { some_option: 'invalid' }
256
+ end
257
+
258
+ it 'raises an error' do
259
+ expect {
260
+ new_collection
261
+ }.to raise_exception(Mongo::Error::UnchangeableCollectionOption)
262
+ end
263
+ end
264
+ end
265
+
89
266
  describe '#capped?' do
90
267
 
91
268
  let(:database) do
@@ -170,6 +347,10 @@ describe Mongo::Collection do
170
347
  collection.create
171
348
  end
172
349
 
350
+ let(:options) do
351
+ { :capped => true, :size => 1024 }
352
+ end
353
+
173
354
  after do
174
355
  collection.drop
175
356
  end
@@ -187,22 +368,62 @@ describe Mongo::Collection do
187
368
  end
188
369
  end
189
370
 
371
+ shared_examples 'a validated collection command' do
372
+
373
+ let!(:response) do
374
+ collection.create
375
+ end
376
+
377
+ let(:options) do
378
+ { :validator => { fieldName: { '$gte' => 1024 } },
379
+ :validationLevel => 'strict' }
380
+ end
381
+
382
+ let(:collection_info) do
383
+ database.list_collections.find { |i| i['name'] == 'specs' }
384
+ end
385
+
386
+ after do
387
+ collection.drop
388
+ end
389
+
390
+ it 'executes the command' do
391
+ expect(response).to be_successful
392
+ end
393
+
394
+ it 'sets the collection with validators' do
395
+ expect(collection_info['options']['validator']).to eq({ 'fieldName' => { '$gte' => 1024 } })
396
+ end
397
+
398
+ it 'creates the collection in the database' do
399
+ expect(database.collection_names).to include('specs')
400
+ end
401
+ end
402
+
190
403
  context 'when instantiating a collection directly' do
191
404
 
192
405
  let(:collection) do
193
- described_class.new(database, :specs, :capped => true, :size => 1024)
406
+ described_class.new(database, :specs, options)
194
407
  end
195
408
 
196
409
  it_behaves_like 'a capped collection command'
410
+
411
+ context 'when validators can be set', if: find_command_enabled? do
412
+ it_behaves_like 'a validated collection command'
413
+ end
197
414
  end
198
415
 
199
416
  context 'when instantiating a collection through the database' do
200
417
 
201
418
  let(:collection) do
202
- authorized_client[:specs, :capped => true, :size => 1024]
419
+ authorized_client[:specs, options]
203
420
  end
204
421
 
205
422
  it_behaves_like 'a capped collection command'
423
+
424
+ context 'when validators can be set', if: find_command_enabled? do
425
+ it_behaves_like 'a validated collection command'
426
+ end
206
427
  end
207
428
  end
208
429
  end
@@ -244,29 +465,29 @@ describe Mongo::Collection do
244
465
 
245
466
  describe '#find' do
246
467
 
247
- context 'when provided a selector' do
468
+ context 'when provided a filter' do
248
469
 
249
470
  let(:view) do
250
471
  authorized_collection.find(name: 1)
251
472
  end
252
473
 
253
- it 'returns a authorized_collection view for the selector' do
254
- expect(view.selector).to eq(name: 1)
474
+ it 'returns a authorized_collection view for the filter' do
475
+ expect(view.filter).to eq('name' => 1)
255
476
  end
256
477
  end
257
478
 
258
- context 'when provided no selector' do
479
+ context 'when provided no filter' do
259
480
 
260
481
  let(:view) do
261
482
  authorized_collection.find
262
483
  end
263
484
 
264
- it 'returns a authorized_collection view with an empty selector' do
265
- expect(view.selector).to be_empty
485
+ it 'returns a authorized_collection view with an empty filter' do
486
+ expect(view.filter).to be_empty
266
487
  end
267
488
  end
268
489
 
269
- context 'when providing a bad selector' do
490
+ context 'when providing a bad filter' do
270
491
 
271
492
  let(:view) do
272
493
  authorized_collection.find('$or' => [])
@@ -300,6 +521,50 @@ describe Mongo::Collection do
300
521
  end
301
522
  end
302
523
 
524
+ context 'when the user is not authorized', if: auth_enabled? do
525
+
526
+ let(:view) do
527
+ unauthorized_collection.find
528
+ end
529
+
530
+ it 'iterates over the documents' do
531
+ expect {
532
+ view.each{ |document| document }
533
+ }.to raise_error(Mongo::Error::OperationFailure)
534
+ end
535
+ end
536
+
537
+ context 'when documents contain potential error message fields' do
538
+
539
+ [ Mongo::Error::ERRMSG, Mongo::Error::ERROR, Mongo::Operation::Result::OK ].each do |field|
540
+
541
+ context "when the document contains a '#{field}' field" do
542
+
543
+ let(:value) do
544
+ 'testing'
545
+ end
546
+
547
+ let(:view) do
548
+ authorized_collection.find
549
+ end
550
+
551
+ before do
552
+ authorized_collection.insert_one({ field => value })
553
+ end
554
+
555
+ after do
556
+ authorized_collection.delete_many
557
+ end
558
+
559
+ it 'iterates over the documents' do
560
+ view.each do |document|
561
+ expect(document[field]).to eq(value)
562
+ end
563
+ end
564
+ end
565
+ end
566
+ end
567
+
303
568
  context 'when provided options' do
304
569
 
305
570
  let(:view) do
@@ -324,7 +589,7 @@ describe Mongo::Collection do
324
589
  end
325
590
 
326
591
  it 'returns a view with :batch_size set' do
327
- expect(view.options[:batch_size]).to be(options[:batch_size])
592
+ expect(view.options[:batch_size]).to eq(options[:batch_size])
328
593
  end
329
594
  end
330
595
 
@@ -335,7 +600,7 @@ describe Mongo::Collection do
335
600
  end
336
601
 
337
602
  it 'returns a view with :comment set' do
338
- expect(view.options[:comment]).to be(options[:comment])
603
+ expect(view.modifiers[:$comment]).to eq(options[:comment])
339
604
  end
340
605
  end
341
606
 
@@ -346,10 +611,12 @@ describe Mongo::Collection do
346
611
  end
347
612
 
348
613
  it 'returns a view with :cursor_type set' do
349
- expect(view.options[:cursor_type]).to be(options[:cursor_type])
614
+ expect(view.options[:cursor_type]).to eq(options[:cursor_type])
350
615
  end
351
616
  end
352
617
 
618
+ #limit
619
+
353
620
  context 'when provided :max_time_ms' do
354
621
 
355
622
  let(:options) do
@@ -357,18 +624,22 @@ describe Mongo::Collection do
357
624
  end
358
625
 
359
626
  it 'returns a view with :max_time_ms set' do
360
- expect(view.options[:max_time_ms]).to be(options[:max_time_ms])
627
+ expect(view.modifiers[:$maxTimeMS]).to eq(options[:max_time_ms])
361
628
  end
362
629
  end
363
630
 
364
631
  context 'when provided :modifiers' do
365
632
 
366
633
  let(:options) do
367
- { modifiers: { :$orderby => Mongo::Index::ASCENDING } }
634
+ { modifiers: { '$orderby' => Mongo::Index::ASCENDING } }
368
635
  end
369
636
 
370
637
  it 'returns a view with modifiers set' do
371
- expect(view.options[:modifiers]).to be(options[:modifiers])
638
+ expect(view.modifiers).to eq(options[:modifiers])
639
+ end
640
+
641
+ it 'dups the modifiers hash' do
642
+ expect(view.modifiers).not_to be(options[:modifiers])
372
643
  end
373
644
  end
374
645
 
@@ -379,7 +650,7 @@ describe Mongo::Collection do
379
650
  end
380
651
 
381
652
  it 'returns a view with :no_cursor_timeout set' do
382
- expect(view.options[:no_cursor_timeout]).to be(options[:no_cursor_timeout])
653
+ expect(view.options[:no_cursor_timeout]).to eq(options[:no_cursor_timeout])
383
654
  end
384
655
  end
385
656
 
@@ -390,7 +661,7 @@ describe Mongo::Collection do
390
661
  end
391
662
 
392
663
  it 'returns a view with :oplog_replay set' do
393
- expect(view.options[:oplog_replay]).to be(options[:oplog_replay])
664
+ expect(view.options[:oplog_replay]).to eq(options[:oplog_replay])
394
665
  end
395
666
  end
396
667
 
@@ -401,7 +672,7 @@ describe Mongo::Collection do
401
672
  end
402
673
 
403
674
  it 'returns a view with :projection set' do
404
- expect(view.options[:projection]).to be(options[:projection])
675
+ expect(view.options[:projection]).to eq(options[:projection])
405
676
  end
406
677
  end
407
678
 
@@ -412,7 +683,7 @@ describe Mongo::Collection do
412
683
  end
413
684
 
414
685
  it 'returns a view with :skip set' do
415
- expect(view.options[:skip]).to be(options[:skip])
686
+ expect(view.options[:skip]).to eq(options[:skip])
416
687
  end
417
688
  end
418
689
 
@@ -423,7 +694,7 @@ describe Mongo::Collection do
423
694
  end
424
695
 
425
696
  it 'returns a view with :sort set' do
426
- expect(view.options[:sort]).to be(options[:sort])
697
+ expect(view.modifiers[:$orderby]).to eq(options[:sort])
427
698
  end
428
699
  end
429
700
  end
@@ -433,6 +704,7 @@ describe Mongo::Collection do
433
704
 
434
705
  after do
435
706
  authorized_collection.delete_many
707
+ collection_with_validator.delete_many
436
708
  end
437
709
 
438
710
  let(:result) do
@@ -446,12 +718,112 @@ describe Mongo::Collection do
446
718
  it 'contains the ids in the result' do
447
719
  expect(result.inserted_ids.size).to eq(2)
448
720
  end
721
+
722
+ context 'when the client has a custom id generator' do
723
+
724
+ let(:generator) do
725
+ Class.new do
726
+ def generate
727
+ 1
728
+ end
729
+ end.new
730
+ end
731
+
732
+ let(:custom_client) do
733
+ authorized_client.with(id_generator: generator)
734
+ end
735
+
736
+ let(:custom_collection) do
737
+ custom_client[TEST_COLL]
738
+ end
739
+
740
+ before do
741
+ custom_collection.insert_many([{ name: 'testing' }])
742
+ end
743
+
744
+ after do
745
+ custom_client.close
746
+ end
747
+
748
+ it 'inserts with the custom id' do
749
+ expect(custom_collection.find.first[:_id]).to eq(1)
750
+ end
751
+ end
752
+
753
+ context 'when the inserts fail' do
754
+
755
+ let(:result) do
756
+ authorized_collection.insert_many([{ _id: 1 }, { _id: 1 }])
757
+ end
758
+
759
+ it 'raises an BulkWriteError' do
760
+ expect {
761
+ result
762
+ }.to raise_exception(Mongo::Error::BulkWriteError)
763
+ end
764
+ end
765
+
766
+ context "when the documents exceed the max bson size" do
767
+
768
+ let(:documents) do
769
+ [{ '_id' => 1, 'name' => '1'*17000000 }]
770
+ end
771
+
772
+ it 'raises a MaxBSONSize error' do
773
+ expect {
774
+ authorized_collection.insert_many(documents)
775
+ }.to raise_error(Mongo::Error::MaxBSONSize)
776
+ end
777
+ end
778
+
779
+ context 'when collection has a validator', if: find_command_enabled? do
780
+
781
+ context 'when the document is valid' do
782
+
783
+ let(:result) do
784
+ collection_with_validator.insert_many([{ a: 1 }, { a: 2 }])
785
+ end
786
+
787
+ it 'inserts successfully' do
788
+ expect(result.inserted_count).to eq(2)
789
+ end
790
+ end
791
+
792
+ context 'when the document is invalid' do
793
+
794
+ context 'when bypass_document_validation is not set' do
795
+
796
+ let(:result2) do
797
+ collection_with_validator.insert_many([{ x: 1 }, { x: 2 }])
798
+ end
799
+
800
+ it 'raises a BulkWriteError' do
801
+ expect {
802
+ result2
803
+ }.to raise_exception(Mongo::Error::BulkWriteError)
804
+ end
805
+ end
806
+
807
+ context 'when bypass_document_validation is true' do
808
+
809
+ let(:result3) do
810
+ collection_with_validator.insert_many(
811
+ [{ x: 1 }, { x: 2 }], :bypass_document_validation => true)
812
+ end
813
+
814
+ it 'inserts successfully' do
815
+ expect(result3.inserted_count).to eq(2)
816
+ end
817
+ end
818
+ end
819
+ end
449
820
  end
450
821
 
451
822
  describe '#insert_one' do
452
823
 
453
824
  after do
454
825
  authorized_collection.delete_many
826
+ collection_with_validator.delete_many
455
827
  end
456
828
 
457
829
  let(:result) do
@@ -469,6 +841,93 @@ describe Mongo::Collection do
469
841
  it 'contains the id in the result' do
470
842
  expect(result.inserted_id).to_not be_nil
471
843
  end
844
+
845
+ context 'when the insert fails' do
846
+
847
+ let(:result) do
848
+ authorized_collection.insert_one(_id: 1)
849
+ authorized_collection.insert_one(_id: 1)
850
+ end
851
+
852
+ it 'raises an OperationFailure' do
853
+ expect {
854
+ result
855
+ }.to raise_exception(Mongo::Error::OperationFailure)
856
+ end
857
+ end
858
+
859
+ context 'when the client has a custom id generator' do
860
+
861
+ let(:generator) do
862
+ Class.new do
863
+ def generate
864
+ 1
865
+ end
866
+ end.new
867
+ end
868
+
869
+ let(:custom_client) do
870
+ authorized_client.with(id_generator: generator)
871
+ end
872
+
873
+ let(:custom_collection) do
874
+ custom_client[TEST_COLL]
875
+ end
876
+
877
+ before do
878
+ custom_collection.insert_one({ name: 'testing' })
879
+ end
880
+
881
+ after do
882
+ custom_client.close
883
+ end
884
+
885
+ it 'inserts with the custom id' do
886
+ expect(custom_collection.find.first[:_id]).to eq(1)
887
+ end
888
+ end
889
+
890
+ context 'when collection has a validator', if: find_command_enabled? do
891
+
892
+ context 'when the document is valid' do
893
+
894
+ let(:result) do
895
+ collection_with_validator.insert_one({ a: 1 })
896
+ end
897
+
898
+ it 'inserts successfully' do
899
+ expect(result.written_count).to eq(1)
900
+ end
901
+ end
902
+
903
+ context 'when the document is invalid' do
904
+
905
+ context 'when bypass_document_validation is not set' do
906
+
907
+ let(:result2) do
908
+ collection_with_validator.insert_one({ x: 1 })
909
+ end
910
+
911
+ it 'raises a OperationFailure' do
912
+ expect {
913
+ result2
914
+ }.to raise_exception(Mongo::Error::OperationFailure)
915
+ end
916
+ end
917
+
918
+ context 'when bypass_document_validation is true' do
919
+
920
+ let(:result3) do
921
+ collection_with_validator.insert_one(
922
+ { x: 1 }, :bypass_document_validation => true)
923
+ end
924
+
925
+ it 'inserts successfully' do
926
+ expect(result3.written_count).to eq(1)
927
+ end
928
+ end
929
+ end
930
+ end
472
931
  end
473
932
 
474
933
  describe '#inspect' do
@@ -525,7 +984,7 @@ describe Mongo::Collection do
525
984
  context 'when options are provided' do
526
985
 
527
986
  let(:options) do
528
- { :allow_disk_use => true }
987
+ { :allow_disk_use => true, :bypass_document_validation => true }
529
988
  end
530
989
 
531
990
  it 'sets the options on the Aggregation object' do
@@ -575,7 +1034,7 @@ describe Mongo::Collection do
575
1034
  end
576
1035
 
577
1036
  it 'returns the distinct values' do
578
- expect(authorized_collection.distinct(:field)).to eq([ 'test1', 'test2', 'test3' ])
1037
+ expect(authorized_collection.distinct(:field).sort).to eq([ 'test1', 'test2', 'test3' ])
579
1038
  end
580
1039
 
581
1040
  context 'when a selector is provided' do
@@ -588,7 +1047,7 @@ describe Mongo::Collection do
588
1047
  context 'when options are provided' do
589
1048
 
590
1049
  it 'passes the options to the distinct command' do
591
- expect(authorized_collection.distinct(:field, {}, max_time_ms: 100)).to eq([ 'test1', 'test2', 'test3' ])
1050
+ expect(authorized_collection.distinct(:field, {}, max_time_ms: 100).sort).to eq([ 'test1', 'test2', 'test3' ])
592
1051
  end
593
1052
  end
594
1053
  end
@@ -636,6 +1095,19 @@ describe Mongo::Collection do
636
1095
  expect(response.deleted_count).to eq(1)
637
1096
  end
638
1097
  end
1098
+
1099
+ context 'when the delete fails', if: standalone? do
1100
+
1101
+ let(:result) do
1102
+ collection_invalid_write_concern.delete_one
1103
+ end
1104
+
1105
+ it 'raises an OperationFailure' do
1106
+ expect {
1107
+ result
1108
+ }.to raise_exception(Mongo::Error::OperationFailure)
1109
+ end
1110
+ end
639
1111
  end
640
1112
 
641
1113
  describe '#delete_many' do
@@ -661,8 +1133,87 @@ describe Mongo::Collection do
661
1133
 
662
1134
  context 'when no selector was provided' do
663
1135
 
664
- it 'deletes all the documents in the collection' do
665
- expect(authorized_collection.delete_many.deleted_count).to eq(2)
1136
+ it 'deletes all the documents in the collection' do
1137
+ expect(authorized_collection.delete_many.deleted_count).to eq(2)
1138
+ end
1139
+ end
1140
+
1141
+ context 'when the deletes fail', if: standalone? do
1142
+
1143
+ let(:result) do
1144
+ collection_invalid_write_concern.delete_many
1145
+ end
1146
+
1147
+ it 'raises an OperationFailure' do
1148
+ expect {
1149
+ result
1150
+ }.to raise_exception(Mongo::Error::OperationFailure)
1151
+ end
1152
+ end
1153
+ end
1154
+
1155
+ describe '#parallel_scan', unless: sharded? do
1156
+
1157
+ let(:documents) do
1158
+ (1..200).map do |i|
1159
+ { name: "testing-scan-#{i}" }
1160
+ end
1161
+ end
1162
+
1163
+ before do
1164
+ authorized_collection.insert_many(documents)
1165
+ end
1166
+
1167
+ let(:cursors) do
1168
+ authorized_collection.parallel_scan(2)
1169
+ end
1170
+
1171
+ it 'returns an array of cursors', if: write_command_enabled? do
1172
+ cursors.each do |cursor|
1173
+ expect(cursor.class).to be(Mongo::Cursor)
1174
+ end
1175
+ end
1176
+
1177
+ it 'returns the correct number of documents', if: write_command_enabled? do
1178
+ expect(
1179
+ cursors.reduce(0) { |total, cursor| total + cursor.to_a.size }
1180
+ ).to eq(200)
1181
+ end
1182
+
1183
+ it 'raises an error', unless: write_command_enabled? do
1184
+ expect {
1185
+ cursors
1186
+ }.to raise_error(Mongo::Error::OperationFailure)
1187
+ end
1188
+
1189
+ context 'when a read concern is provided', if: find_command_enabled? do
1190
+
1191
+ let(:result) do
1192
+ authorized_collection.with(options).parallel_scan(2)
1193
+ end
1194
+
1195
+ context 'when the read concern is valid' do
1196
+
1197
+ let(:options) do
1198
+ { read_concern: { level: 'local' }}
1199
+ end
1200
+
1201
+ it 'sends the read concern' do
1202
+ expect { result }.to_not raise_error
1203
+ end
1204
+ end
1205
+
1206
+ context 'when the read concern is not valid' do
1207
+
1208
+ let(:options) do
1209
+ { read_concern: { level: 'idontknow' }}
1210
+ end
1211
+
1212
+ it 'raises an exception' do
1213
+ expect {
1214
+ result
1215
+ }.to raise_error(Mongo::Error::OperationFailure)
1216
+ end
666
1217
  end
667
1218
  end
668
1219
  end
@@ -760,6 +1311,69 @@ describe Mongo::Collection do
760
1311
  expect(updated).to be_empty
761
1312
  end
762
1313
  end
1314
+
1315
+ context 'when the replace fails' do
1316
+
1317
+ let(:result) do
1318
+ authorized_collection.replace_one(selector, { '$s' => 'test1' })
1319
+ end
1320
+
1321
+ it 'raises an OperationFailure' do
1322
+ expect {
1323
+ result
1324
+ }.to raise_exception(Mongo::Error::OperationFailure)
1325
+ end
1326
+ end
1327
+
1328
+ context 'when collection has a validator', if: find_command_enabled? do
1329
+
1330
+ before do
1331
+ collection_with_validator.insert_one({ a: 1 })
1332
+ end
1333
+
1334
+ after do
1335
+ collection_with_validator.delete_many
1336
+ end
1337
+
1338
+ context 'when the document is valid' do
1339
+
1340
+ let(:result) do
1341
+ collection_with_validator.replace_one({ a: 1 }, { a: 5 })
1342
+ end
1343
+
1344
+ it 'replaces successfully' do
1345
+ expect(result.modified_count).to eq(1)
1346
+ end
1347
+ end
1348
+
1349
+ context 'when the document is invalid' do
1350
+
1351
+ context 'when bypass_document_validation is not set' do
1352
+
1353
+ let(:result2) do
1354
+ collection_with_validator.replace_one({ a: 1 }, { x: 5 })
1355
+ end
1356
+
1357
+ it 'raises OperationFailure' do
1358
+ expect {
1359
+ result2
1360
+ }.to raise_exception(Mongo::Error::OperationFailure)
1361
+ end
1362
+ end
1363
+
1364
+ context 'when bypass_document_validation is true' do
1365
+
1366
+ let(:result3) do
1367
+ collection_with_validator.replace_one(
1368
+ { a: 1 }, { x: 1 }, :bypass_document_validation => true)
1369
+ end
1370
+
1371
+ it 'replaces successfully' do
1372
+ expect(result3.written_count).to eq(1)
1373
+ end
1374
+ end
1375
+ end
1376
+ end
763
1377
  end
764
1378
 
765
1379
  describe '#update_many' do
@@ -853,6 +1467,72 @@ describe Mongo::Collection do
853
1467
  expect(updated).to be_empty
854
1468
  end
855
1469
  end
1470
+
1471
+ context 'when the updates fail' do
1472
+
1473
+ let(:result) do
1474
+ authorized_collection.update_many(selector, { '$s'=> { field: 'testing' } })
1475
+ end
1476
+
1477
+ it 'raises an OperationFailure' do
1478
+ expect {
1479
+ result
1480
+ }.to raise_exception(Mongo::Error::OperationFailure)
1481
+ end
1482
+ end
1483
+
1484
+ context 'when collection has a validator', if: find_command_enabled? do
1485
+
1486
+ before do
1487
+ collection_with_validator.insert_many([{ a: 1 }, { a: 2 }])
1488
+ end
1489
+
1490
+ after do
1491
+ collection_with_validator.delete_many
1492
+ end
1493
+
1494
+ context 'when the document is valid' do
1495
+
1496
+ let(:result) do
1497
+ collection_with_validator.update_many(
1498
+ { :a => { '$gt' => 0 } }, '$inc' => { :a => 1 } )
1499
+ end
1500
+
1501
+ it 'updates successfully' do
1502
+ expect(result.modified_count).to eq(2)
1503
+ end
1504
+ end
1505
+
1506
+ context 'when the document is invalid' do
1507
+
1508
+ context 'when bypass_document_validation is not set' do
1509
+
1510
+ let(:result2) do
1511
+ collection_with_validator.update_many(
1512
+ { :a => { '$gt' => 0 } }, '$unset' => { :a => '' })
1513
+ end
1514
+
1515
+ it 'raises OperationFailure' do
1516
+ expect {
1517
+ result2
1518
+ }.to raise_exception(Mongo::Error::OperationFailure)
1519
+ end
1520
+ end
1521
+
1522
+ context 'when bypass_document_validation is true' do
1523
+
1524
+ let(:result3) do
1525
+ collection_with_validator.update_many(
1526
+ { :a => { '$gt' => 0 } }, { '$unset' => { :a => '' } },
1527
+ :bypass_document_validation => true)
1528
+ end
1529
+
1530
+ it 'updates successfully' do
1531
+ expect(result3.written_count).to eq(2)
1532
+ end
1533
+ end
1534
+ end
1535
+ end
856
1536
  end
857
1537
 
858
1538
  describe '#update_one' do
@@ -942,6 +1622,72 @@ describe Mongo::Collection do
942
1622
  expect(updated).to be_empty
943
1623
  end
944
1624
  end
1625
+
1626
+ context 'when the update fails' do
1627
+
1628
+ let(:result) do
1629
+ authorized_collection.update_one(selector, { '$s'=> { field: 'testing' } })
1630
+ end
1631
+
1632
+ it 'raises an OperationFailure' do
1633
+ expect {
1634
+ result
1635
+ }.to raise_exception(Mongo::Error::OperationFailure)
1636
+ end
1637
+ end
1638
+
1639
+ context 'when collection has a validator', if: find_command_enabled? do
1640
+
1641
+ before do
1642
+ collection_with_validator.insert_one({ a: 1 })
1643
+ end
1644
+
1645
+ after do
1646
+ collection_with_validator.delete_many
1647
+ end
1648
+
1649
+ context 'when the document is valid' do
1650
+
1651
+ let(:result) do
1652
+ collection_with_validator.update_one(
1653
+ { :a => { '$gt' => 0 } }, '$inc' => { :a => 1 } )
1654
+ end
1655
+
1656
+ it 'updates successfully' do
1657
+ expect(result.modified_count).to eq(1)
1658
+ end
1659
+ end
1660
+
1661
+ context 'when the document is invalid' do
1662
+
1663
+ context 'when bypass_document_validation is not set' do
1664
+
1665
+ let(:result2) do
1666
+ collection_with_validator.update_one(
1667
+ { :a => { '$gt' => 0 } }, '$unset' => { :a => '' })
1668
+ end
1669
+
1670
+ it 'raises OperationFailure' do
1671
+ expect {
1672
+ result2
1673
+ }.to raise_exception(Mongo::Error::OperationFailure)
1674
+ end
1675
+ end
1676
+
1677
+ context 'when bypass_document_validation is true' do
1678
+
1679
+ let(:result3) do
1680
+ collection_with_validator.update_one(
1681
+ { :a => { '$gt' => 0 } }, { '$unset' => { :a => '' } },
1682
+ :bypass_document_validation => true)
1683
+ end
1684
+
1685
+ it 'updates successfully' do
1686
+ expect(result3.written_count).to eq(1)
1687
+ end
1688
+ end
1689
+ end
1690
+ end
945
1691
  end
946
1692
 
947
1693
  describe '#find_one_and_delete' do
@@ -950,11 +1696,11 @@ describe Mongo::Collection do
950
1696
  authorized_collection.insert_many([{ field: 'test1' }])
951
1697
  end
952
1698
 
953
- context 'when a matching document is found' do
1699
+ let(:selector) do
1700
+ { field: 'test1' }
1701
+ end
954
1702
 
955
- let(:selector) do
956
- { field: 'test1' }
957
- end
1703
+ context 'when a matching document is found' do
958
1704
 
959
1705
  context 'when no options are provided' do
960
1706
 
@@ -1026,18 +1772,55 @@ describe Mongo::Collection do
1026
1772
  expect(document).to be_nil
1027
1773
  end
1028
1774
  end
1029
- end
1030
1775
 
1031
- describe '#find_one_and_update' do
1776
+ context 'when the operation fails', if: write_command_enabled? do
1032
1777
 
1033
- before do
1034
- authorized_collection.insert_many([{ field: 'test1' }])
1778
+ let(:result) do
1779
+ authorized_collection.find_one_and_delete(selector, max_time_ms: 0.1)
1780
+ end
1781
+
1782
+ it 'raises an OperationFailure' do
1783
+ expect {
1784
+ result
1785
+ }.to raise_exception(Mongo::Error::OperationFailure)
1786
+ end
1787
+ end
1788
+
1789
+ context 'when write_concern is provided', if: find_command_enabled? && standalone? do
1790
+
1791
+ it 'uses the write concern' do
1792
+ expect {
1793
+ authorized_collection.find_one_and_delete(selector,
1794
+ write_concern: { w: 2 })
1795
+ }.to raise_error(Mongo::Error::OperationFailure)
1796
+ end
1797
+ end
1798
+
1799
+ context 'when the collection has a write concern', if: find_command_enabled? && standalone? do
1800
+
1801
+ let(:collection) do
1802
+ authorized_collection.with(write: { w: 2 })
1803
+ end
1804
+
1805
+ it 'uses the write concern' do
1806
+ expect {
1807
+ collection.find_one_and_delete(selector,
1808
+ write_concern: { w: 2 })
1809
+ }.to raise_error(Mongo::Error::OperationFailure)
1810
+ end
1035
1811
  end
1812
+ end
1813
+
1814
+ describe '#find_one_and_update' do
1036
1815
 
1037
1816
  let(:selector) do
1038
1817
  { field: 'test1' }
1039
1818
  end
1040
1819
 
1820
+ before do
1821
+ authorized_collection.insert_many([{ field: 'test1' }])
1822
+ end
1823
+
1041
1824
  context 'when a matching document is found' do
1042
1825
 
1043
1826
  context 'when no options are provided' do
@@ -1167,6 +1950,99 @@ describe Mongo::Collection do
1167
1950
  end
1168
1951
  end
1169
1952
  end
1953
+
1954
+ context 'when the operation fails', if: write_command_enabled? do
1955
+
1956
+ let(:result) do
1957
+ authorized_collection.find_one_and_update(selector, { '$set' => { field: 'testing' }}, max_time_ms: 0.1)
1958
+ end
1959
+
1960
+ it 'raises an OperationFailure' do
1961
+ expect {
1962
+ result
1963
+ }.to raise_exception(Mongo::Error::OperationFailure)
1964
+ end
1965
+ end
1966
+
1967
+ context 'when collection has a validator', if: find_command_enabled? do
1968
+
1969
+ before do
1970
+ collection_with_validator.insert_one({ a: 1 })
1971
+ end
1972
+
1973
+ after do
1974
+ collection_with_validator.delete_many
1975
+ end
1976
+
1977
+ context 'when the document is valid' do
1978
+
1979
+ let(:result) do
1980
+ collection_with_validator.find_one_and_update(
1981
+ { a: 1 }, { '$inc' => { :a => 1 } }, :return_document => :after)
1982
+ end
1983
+
1984
+ it 'updates successfully' do
1985
+ expect(result['a']).to eq(2)
1986
+ end
1987
+ end
1988
+
1989
+ context 'when the document is invalid' do
1990
+
1991
+ context 'when bypass_document_validation is not set' do
1992
+
1993
+ let(:result2) do
1994
+ collection_with_validator.find_one_and_update(
1995
+ { a: 1 }, { '$unset' => { :a => '' } }, :return_document => :after)
1996
+ end
1997
+
1998
+ it 'raises OperationFailure' do
1999
+ expect {
2000
+ result2
2001
+ }.to raise_exception(Mongo::Error::OperationFailure)
2002
+ end
2003
+ end
2004
+
2005
+ context 'when bypass_document_validation is true' do
2006
+
2007
+ let(:result3) do
2008
+ collection_with_validator.find_one_and_update(
2009
+ { a: 1 }, { '$unset' => { :a => '' } },
2010
+ :bypass_document_validation => true,
2011
+ :return_document => :after)
2012
+ end
2013
+
2014
+ it 'updates successfully' do
2015
+ expect(result3['a']).to be_nil
2016
+ end
2017
+ end
2018
+ end
2019
+ end
2020
+
2021
+ context 'when write_concern is provided', if: find_command_enabled? && standalone? do
2022
+
2023
+ it 'uses the write concern' do
2024
+ expect {
2025
+ authorized_collection.find_one_and_update(selector,
2026
+ { '$set' => { field: 'testing' }},
2027
+ write_concern: { w: 2 })
2028
+ }.to raise_error(Mongo::Error::OperationFailure)
2029
+ end
2030
+ end
2031
+
2032
+ context 'when the collection has a write concern', if: find_command_enabled? && standalone? do
2033
+
2034
+ let(:collection) do
2035
+ authorized_collection.with(write: { w: 2 })
2036
+ end
2037
+
2038
+ it 'uses the write concern' do
2039
+ expect {
2040
+ collection.find_one_and_update(selector,
2041
+ { '$set' => { field: 'testing' }},
2042
+ write_concern: { w: 2 })
2043
+ }.to raise_error(Mongo::Error::OperationFailure)
2044
+ end
2045
+ end
1170
2046
  end
1171
2047
 
1172
2048
  describe '#find_one_and_replace' do
@@ -1282,5 +2158,98 @@ describe Mongo::Collection do
1282
2158
  }.to raise_error(Mongo::Error::OperationFailure)
1283
2159
  end
1284
2160
  end
2161
+
2162
+ context 'when the operation fails', if: write_command_enabled? do
2163
+
2164
+ let(:result) do
2165
+ authorized_collection.find_one_and_replace(selector, { field: 'testing' }, max_time_ms: 0.1)
2166
+ end
2167
+
2168
+ it 'raises an OperationFailure' do
2169
+ expect {
2170
+ result
2171
+ }.to raise_exception(Mongo::Error::OperationFailure)
2172
+ end
2173
+ end
2174
+
2175
+ context 'when collection has a validator', if: find_command_enabled? do
2176
+
2177
+ before do
2178
+ collection_with_validator.insert_one({ a: 1 })
2179
+ end
2180
+
2181
+ after do
2182
+ collection_with_validator.delete_many
2183
+ end
2184
+
2185
+ context 'when the document is valid' do
2186
+
2187
+ let(:result) do
2188
+ collection_with_validator.find_one_and_replace(
2189
+ { a: 1 }, { a: 5 }, :return_document => :after)
2190
+ end
2191
+
2192
+ it 'replaces successfully when document is valid' do
2193
+ expect(result[:a]).to eq(5)
2194
+ end
2195
+ end
2196
+
2197
+ context 'when the document is invalid' do
2198
+
2199
+ context 'when bypass_document_validation is not set' do
2200
+
2201
+ let(:result2) do
2202
+ collection_with_validator.find_one_and_replace(
2203
+ { a: 1 }, { x: 5 }, :return_document => :after)
2204
+ end
2205
+
2206
+ it 'raises OperationFailure' do
2207
+ expect {
2208
+ result2
2209
+ }.to raise_exception(Mongo::Error::OperationFailure)
2210
+ end
2211
+ end
2212
+
2213
+ context 'when bypass_document_validation is true' do
2214
+
2215
+ let(:result3) do
2216
+ collection_with_validator.find_one_and_replace(
2217
+ { a: 1 }, { x: 1 }, :bypass_document_validation => true,
2218
+ :return_document => :after)
2219
+ end
2220
+
2221
+ it 'replaces successfully' do
2222
+ expect(result3[:x]).to eq(1)
2223
+ expect(result3[:a]).to be_nil
2224
+ end
2225
+ end
2226
+ end
2227
+ end
2228
+
2229
+ context 'when write_concern is provided', if: find_command_enabled? && standalone? do
2230
+
2231
+ it 'uses the write concern' do
2232
+ expect {
2233
+ authorized_collection.find_one_and_replace(selector,
2234
+ { field: 'testing' },
2235
+ write_concern: { w: 2 })
2236
+ }.to raise_error(Mongo::Error::OperationFailure)
2237
+ end
2238
+ end
2239
+
2240
+ context 'when the collection has a write concern', if: find_command_enabled? && standalone? do
2241
+
2242
+ let(:collection) do
2243
+ authorized_collection.with(write: { w: 2 })
2244
+ end
2245
+
2246
+ it 'uses the write concern' do
2247
+ expect {
2248
+ collection.find_one_and_replace(selector,
2249
+ { field: 'testing' },
2250
+ write_concern: { w: 2 })
2251
+ }.to raise_error(Mongo::Error::OperationFailure)
2252
+ end
2253
+ end
1285
2254
  end
1286
2255
  end