mongo 2.0.6 → 2.1.0

Sign up to get free protection for your applications and to get access to all the features.
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
@@ -2,6 +2,14 @@ require 'spec_helper'
2
2
 
3
3
  describe Mongo::Collection do
4
4
 
5
+ after do
6
+ authorized_collection.delete_many
7
+ end
8
+
9
+ let(:collection_invalid_write_concern) do
10
+ authorized_collection.client.with(write: { w: (WRITE_CONCERN[:w] + 1) })[authorized_collection.name]
11
+ end
12
+
5
13
  describe '#==' do
6
14
 
7
15
  let(:database) do
@@ -82,6 +90,172 @@ describe Mongo::Collection do
82
90
  end
83
91
  end
84
92
 
93
+ describe '#with' do
94
+
95
+ let(:client) do
96
+ Mongo::Client.new(ADDRESSES)
97
+ end
98
+
99
+ let(:database) do
100
+ Mongo::Database.new(client, :test)
101
+ end
102
+
103
+ let(:collection) do
104
+ database.collection(:users)
105
+ end
106
+
107
+ let(:new_collection) do
108
+ collection.with(new_options)
109
+ end
110
+
111
+ context 'when new read options are provided' do
112
+
113
+ let(:new_options) do
114
+ { read: { mode: :secondary } }
115
+ end
116
+
117
+ it 'returns a new collection' do
118
+ expect(new_collection).not_to be(collection)
119
+ end
120
+
121
+ it 'sets the new read options on the new collection' do
122
+ expect(new_collection.read_preference).to eq(Mongo::ServerSelector.get(new_options[:read]))
123
+ end
124
+
125
+ context 'when the client has a server selection timeout setting' do
126
+
127
+ let(:client) do
128
+ Mongo::Client.new(ADDRESSES, server_selection_timeout: 2)
129
+ end
130
+
131
+ let(:server_selection_timeout) do
132
+ new_collection.read_preference.server_selection_timeout
133
+ end
134
+
135
+ it 'keeps the server_selection_timeout setting from client' do
136
+ expect(server_selection_timeout).to eq(client.options[:server_selection_timeout])
137
+ end
138
+ end
139
+
140
+ context 'when the client has a read preference set' do
141
+
142
+ let(:client) do
143
+ Mongo::Client.new(ADDRESSES, read: { mode: :primary_preferred })
144
+ end
145
+
146
+ it 'sets the new read options on the new collection' do
147
+ expect(new_collection.read_preference).to eq(Mongo::ServerSelector.get(new_options[:read]))
148
+ end
149
+ end
150
+
151
+ context 'when the client has a read preference and server selection timeout set' do
152
+
153
+ let(:client) do
154
+ Mongo::Client.new(ADDRESSES, read: { mode: :primary_preferred }, server_selection_timeout: 2)
155
+ end
156
+
157
+ let(:server_selection_timeout) do
158
+ new_collection.read_preference.server_selection_timeout
159
+ end
160
+
161
+ it 'sets the new read options on the new collection' do
162
+ expect(new_collection.read_preference).to eq(Mongo::ServerSelector.get(new_options[:read]))
163
+ end
164
+
165
+ it 'keeps the server_selection_timeout setting from client' do
166
+ expect(server_selection_timeout).to eq(client.options[:server_selection_timeout])
167
+ end
168
+ end
169
+ end
170
+
171
+ context 'when new write options are provided' do
172
+
173
+ let(:new_options) do
174
+ { write: { w: 5 } }
175
+ end
176
+
177
+ it 'returns a new collection' do
178
+ expect(new_collection).not_to be(collection)
179
+ end
180
+
181
+ it 'sets the new write options on the new collection' do
182
+ expect(new_collection.write_concern.options).to eq(Mongo::WriteConcern.get(new_options[:write]).options)
183
+ end
184
+
185
+ context 'when the client has a write concern set' do
186
+
187
+ let(:client) do
188
+ Mongo::Client.new(ADDRESSES, write: { w: 10 })
189
+ end
190
+
191
+ it 'sets the new write options on the new collection' do
192
+ expect(new_collection.write_concern.options).to eq(Mongo::WriteConcern.get(new_options[:write]).options)
193
+ end
194
+ end
195
+ end
196
+
197
+ context 'when new read and write options are provided' do
198
+
199
+ let(:new_options) do
200
+ {
201
+ read: { mode: :secondary },
202
+ write: { w: 4}
203
+ }
204
+ end
205
+
206
+ it 'returns a new collection' do
207
+ expect(new_collection).not_to be(collection)
208
+ end
209
+
210
+ it 'sets the new read options on the new collection' do
211
+ expect(new_collection.read_preference).to eq(Mongo::ServerSelector.get(new_options[:read]))
212
+ end
213
+
214
+ it 'sets the new write options on the new collection' do
215
+ expect(new_collection.write_concern.options).to eq(Mongo::WriteConcern.get(new_options[:write]).options)
216
+ end
217
+
218
+ context 'when the client has a server selection timeout setting' do
219
+
220
+ let(:client) do
221
+ Mongo::Client.new(ADDRESSES, server_selection_timeout: 2)
222
+ end
223
+
224
+ let(:server_selection_timeout) do
225
+ new_collection.read_preference.server_selection_timeout
226
+ end
227
+
228
+ it 'keeps the server_selection_timeout setting from client' do
229
+ expect(server_selection_timeout).to eq(client.options[:server_selection_timeout])
230
+ end
231
+ end
232
+
233
+ context 'when the client has a read preference set' do
234
+
235
+ let(:client) do
236
+ Mongo::Client.new(ADDRESSES, read: { mode: :primary_preferred })
237
+ end
238
+
239
+ it 'sets the new read options on the new collection' do
240
+ expect(new_collection.read_preference).to eq(Mongo::ServerSelector.get(new_options[:read]))
241
+ end
242
+ end
243
+ end
244
+
245
+ context 'when neither read nor write options are provided' do
246
+
247
+ let(:new_options) do
248
+ { some_option: 'invalid' }
249
+ end
250
+
251
+ it 'raises an error' do
252
+ expect {
253
+ new_collection
254
+ }.to raise_exception(Mongo::Error::UnchangeableCollectionOption)
255
+ end
256
+ end
257
+ end
258
+
85
259
  describe '#capped?' do
86
260
 
87
261
  let(:database) do
@@ -282,7 +456,7 @@ describe Mongo::Collection do
282
456
  end
283
457
 
284
458
  after do
285
- authorized_collection.find.delete_many
459
+ authorized_collection.delete_many
286
460
  end
287
461
 
288
462
  let(:view) do
@@ -295,35 +469,222 @@ describe Mongo::Collection do
295
469
  end
296
470
  end
297
471
  end
472
+
473
+ context 'when the user is not authorized' do
474
+
475
+ let(:view) do
476
+ unauthorized_collection.find
477
+ end
478
+
479
+ it 'iterates over the documents' do
480
+ expect {
481
+ view.each{ |document| document }
482
+ }.to raise_error(Mongo::Error::OperationFailure)
483
+ end
484
+ end
485
+
486
+ context 'when documents contain potential error message fields' do
487
+
488
+ [ Mongo::Error::ERRMSG, Mongo::Error::ERROR, Mongo::Operation::Result::OK ].each do |field|
489
+
490
+ context "when the document contains a '#{field}' field" do
491
+
492
+ let(:value) do
493
+ 'testing'
494
+ end
495
+
496
+ let(:view) do
497
+ authorized_collection.find
498
+ end
499
+
500
+ before do
501
+ authorized_collection.insert_one({ field => value })
502
+ end
503
+
504
+ after do
505
+ authorized_collection.delete_many
506
+ end
507
+
508
+ it 'iterates over the documents' do
509
+ view.each do |document|
510
+ expect(document[field]).to eq(value)
511
+ end
512
+ end
513
+ end
514
+ end
515
+ end
516
+
517
+ context 'when provided options' do
518
+
519
+ let(:view) do
520
+ authorized_collection.find({}, options)
521
+ end
522
+
523
+ context 'when provided :allow_partial_results' do
524
+
525
+ let(:options) do
526
+ { allow_partial_results: true }
527
+ end
528
+
529
+ it 'returns a view with :allow_partial_results set' do
530
+ expect(view.options[:allow_partial_results]).to be(options[:allow_partial_results])
531
+ end
532
+ end
533
+
534
+ context 'when provided :batch_size' do
535
+
536
+ let(:options) do
537
+ { batch_size: 100 }
538
+ end
539
+
540
+ it 'returns a view with :batch_size set' do
541
+ expect(view.options[:batch_size]).to eq(options[:batch_size])
542
+ end
543
+ end
544
+
545
+ context 'when provided :comment' do
546
+
547
+ let(:options) do
548
+ { comment: 'slow query' }
549
+ end
550
+
551
+ it 'returns a view with :comment set' do
552
+ expect(view.modifiers[:$comment]).to eq(options[:comment])
553
+ end
554
+ end
555
+
556
+ context 'when provided :cursor_type' do
557
+
558
+ let(:options) do
559
+ { cursor_type: :tailable }
560
+ end
561
+
562
+ it 'returns a view with :cursor_type set' do
563
+ expect(view.options[:cursor_type]).to eq(options[:cursor_type])
564
+ end
565
+ end
566
+
567
+ #limit
568
+
569
+ context 'when provided :max_time_ms' do
570
+
571
+ let(:options) do
572
+ { max_time_ms: 500 }
573
+ end
574
+
575
+ it 'returns a view with :max_time_ms set' do
576
+ expect(view.modifiers[:$maxTimeMS]).to eq(options[:max_time_ms])
577
+ end
578
+ end
579
+
580
+ context 'when provided :modifiers' do
581
+
582
+ let(:options) do
583
+ { modifiers: { :$orderby => Mongo::Index::ASCENDING } }
584
+ end
585
+
586
+ it 'returns a view with modifiers set' do
587
+ expect(view.modifiers).to eq(options[:modifiers])
588
+ end
589
+
590
+ it 'dups the modifiers hash' do
591
+ expect(view.modifiers).not_to be(options[:modifiers])
592
+ end
593
+ end
594
+
595
+ context 'when provided :no_cursor_timeout' do
596
+
597
+ let(:options) do
598
+ { no_cursor_timeout: true }
599
+ end
600
+
601
+ it 'returns a view with :no_cursor_timeout set' do
602
+ expect(view.options[:no_cursor_timeout]).to eq(options[:no_cursor_timeout])
603
+ end
604
+ end
605
+
606
+ context 'when provided :oplog_replay' do
607
+
608
+ let(:options) do
609
+ { oplog_replay: false }
610
+ end
611
+
612
+ it 'returns a view with :oplog_replay set' do
613
+ expect(view.options[:oplog_replay]).to eq(options[:oplog_replay])
614
+ end
615
+ end
616
+
617
+ context 'when provided :projection' do
618
+
619
+ let(:options) do
620
+ { projection: { 'x' => 1 } }
621
+ end
622
+
623
+ it 'returns a view with :projection set' do
624
+ expect(view.options[:projection]).to eq(options[:projection])
625
+ end
626
+ end
627
+
628
+ context 'when provided :skip' do
629
+
630
+ let(:options) do
631
+ { skip: 5 }
632
+ end
633
+
634
+ it 'returns a view with :skip set' do
635
+ expect(view.options[:skip]).to eq(options[:skip])
636
+ end
637
+ end
638
+
639
+ context 'when provided :sort' do
640
+
641
+ let(:options) do
642
+ { sort: { 'x' => Mongo::Index::ASCENDING } }
643
+ end
644
+
645
+ it 'returns a view with :sort set' do
646
+ expect(view.modifiers[:$orderby]).to eq(options[:sort])
647
+ end
648
+ end
649
+ end
298
650
  end
299
651
 
300
652
  describe '#insert_many' do
301
653
 
302
654
  after do
303
- authorized_collection.find.delete_many
655
+ authorized_collection.delete_many
304
656
  end
305
657
 
306
658
  let(:result) do
307
659
  authorized_collection.insert_many([{ name: 'test1' }, { name: 'test2' }])
308
660
  end
309
661
 
310
- it 'inserts the documents into the collection', if: write_command_enabled? do
311
- expect(result.written_count).to eq(2)
312
- end
313
-
314
- it 'inserts the documents into the collection', unless: write_command_enabled? do
315
- expect(result.written_count).to eq(0)
662
+ it 'inserts the documents into the collection' do
663
+ expect(result.inserted_count).to eq(2)
316
664
  end
317
665
 
318
666
  it 'contains the ids in the result' do
319
667
  expect(result.inserted_ids.size).to eq(2)
320
668
  end
669
+
670
+ context 'when the inserts fail' do
671
+
672
+ let(:result) do
673
+ authorized_collection.insert_many([{ _id: 1 }, { _id: 1 }])
674
+ end
675
+
676
+ it 'raises an BulkWriteError' do
677
+ expect {
678
+ result
679
+ }.to raise_exception(Mongo::Error::BulkWriteError)
680
+ end
681
+ end
321
682
  end
322
683
 
323
684
  describe '#insert_one' do
324
685
 
325
686
  after do
326
- authorized_collection.find.delete_many
687
+ authorized_collection.delete_many
327
688
  end
328
689
 
329
690
  let(:result) do
@@ -341,6 +702,20 @@ describe Mongo::Collection do
341
702
  it 'contains the id in the result' do
342
703
  expect(result.inserted_id).to_not be_nil
343
704
  end
705
+
706
+ context 'when the insert fails' do
707
+
708
+ let(:result) do
709
+ authorized_collection.insert_one(_id: 1)
710
+ authorized_collection.insert_one(_id: 1)
711
+ end
712
+
713
+ it 'raises an OperationFailure' do
714
+ expect {
715
+ result
716
+ }.to raise_exception(Mongo::Error::OperationFailure)
717
+ end
718
+ end
344
719
  end
345
720
 
346
721
  describe '#inspect' do
@@ -387,4 +762,911 @@ describe Mongo::Collection do
387
762
  end
388
763
  end
389
764
  end
765
+
766
+ describe '#aggregate' do
767
+
768
+ it 'returns an Aggregation object' do
769
+ expect(authorized_collection.aggregate([])).to be_a(Mongo::Collection::View::Aggregation)
770
+ end
771
+
772
+ context 'when options are provided' do
773
+
774
+ let(:options) do
775
+ { :allow_disk_use => true }
776
+ end
777
+
778
+ it 'sets the options on the Aggregation object' do
779
+ expect(authorized_collection.aggregate([], options).options).to eq(options)
780
+ end
781
+ end
782
+ end
783
+
784
+ describe '#count' do
785
+
786
+ let(:documents) do
787
+ (1..10).map{ |i| { field: "test#{i}" }}
788
+ end
789
+
790
+ before do
791
+ authorized_collection.insert_many(documents)
792
+ end
793
+
794
+ after do
795
+ authorized_collection.delete_many
796
+ end
797
+
798
+ it 'returns an integer count' do
799
+ expect(authorized_collection.count).to eq(10)
800
+ end
801
+
802
+ context 'when options are provided' do
803
+
804
+ it 'passes the options to the count' do
805
+ expect(authorized_collection.count({}, limit: 5)).to eq(5)
806
+ end
807
+ end
808
+ end
809
+
810
+ describe '#distinct' do
811
+
812
+ let(:documents) do
813
+ (1..3).map{ |i| { field: "test#{i}" }}
814
+ end
815
+
816
+ before do
817
+ authorized_collection.insert_many(documents)
818
+ end
819
+
820
+ after do
821
+ authorized_collection.delete_many
822
+ end
823
+
824
+ it 'returns the distinct values' do
825
+ expect(authorized_collection.distinct(:field)).to eq([ 'test1', 'test2', 'test3' ])
826
+ end
827
+
828
+ context 'when a selector is provided' do
829
+
830
+ it 'returns the distinct values' do
831
+ expect(authorized_collection.distinct(:field, field: 'test1')).to eq([ 'test1' ])
832
+ end
833
+ end
834
+
835
+ context 'when options are provided' do
836
+
837
+ it 'passes the options to the distinct command' do
838
+ expect(authorized_collection.distinct(:field, {}, max_time_ms: 100)).to eq([ 'test1', 'test2', 'test3' ])
839
+ end
840
+ end
841
+ end
842
+
843
+ describe '#delete_one' do
844
+
845
+ context 'when a selector was provided' do
846
+
847
+ let(:selector) do
848
+ { field: 'test1' }
849
+ end
850
+
851
+ before do
852
+ authorized_collection.insert_many([
853
+ { field: 'test1' },
854
+ { field: 'test1' },
855
+ { field: 'test1' }
856
+ ])
857
+ end
858
+
859
+ after do
860
+ authorized_collection.delete_many
861
+ end
862
+
863
+ let(:response) do
864
+ authorized_collection.delete_one(selector)
865
+ end
866
+
867
+ it 'deletes the first matching document in the collection' do
868
+ expect(response.deleted_count).to eq(1)
869
+ end
870
+ end
871
+
872
+ context 'when no selector was provided' do
873
+
874
+ before do
875
+ authorized_collection.insert_many([{ field: 'test1' }, { field: 'test2' }])
876
+ end
877
+
878
+ let(:response) do
879
+ authorized_collection.delete_one
880
+ end
881
+
882
+ it 'deletes the first document in the collection' do
883
+ expect(response.deleted_count).to eq(1)
884
+ end
885
+ end
886
+
887
+ context 'when the delete fails', if: standalone? do
888
+
889
+ let(:result) do
890
+ collection_invalid_write_concern.delete_one
891
+ end
892
+
893
+ it 'raises an OperationFailure' do
894
+ expect {
895
+ result
896
+ }.to raise_exception(Mongo::Error::OperationFailure)
897
+ end
898
+ end
899
+ end
900
+
901
+ describe '#delete_many' do
902
+
903
+ before do
904
+ authorized_collection.insert_many([{ field: 'test1' }, { field: 'test2' }])
905
+ end
906
+
907
+ after do
908
+ authorized_collection.delete_many
909
+ end
910
+
911
+ context 'when a selector was provided' do
912
+
913
+ let(:selector) do
914
+ { field: 'test1' }
915
+ end
916
+
917
+ it 'deletes the matching documents in the collection' do
918
+ expect(authorized_collection.delete_many(selector).deleted_count).to eq(1)
919
+ end
920
+ end
921
+
922
+ context 'when no selector was provided' do
923
+
924
+ it 'deletes all the documents in the collection' do
925
+ expect(authorized_collection.delete_many.deleted_count).to eq(2)
926
+ end
927
+ end
928
+
929
+ context 'when the deletes fail', if: standalone? do
930
+
931
+ let(:result) do
932
+ collection_invalid_write_concern.delete_many
933
+ end
934
+
935
+ it 'raises an OperationFailure' do
936
+ expect {
937
+ result
938
+ }.to raise_exception(Mongo::Error::OperationFailure)
939
+ end
940
+ end
941
+ end
942
+
943
+ describe '#parallel_scan', unless: sharded? do
944
+
945
+ let(:documents) do
946
+ (1..200).map do |i|
947
+ { name: "testing-scan-#{i}" }
948
+ end
949
+ end
950
+
951
+ before do
952
+ authorized_collection.insert_many(documents)
953
+ end
954
+
955
+ let(:cursors) do
956
+ authorized_collection.parallel_scan(2)
957
+ end
958
+
959
+ it 'returns an array of cursors', if: write_command_enabled? do
960
+ cursors.each do |cursor|
961
+ expect(cursor.class).to be(Mongo::Cursor)
962
+ end
963
+ end
964
+
965
+ it 'returns the correct number of documents', if: write_command_enabled? do
966
+ expect(
967
+ cursors.reduce(0) { |total, cursor| total + cursor.to_a.size }
968
+ ).to eq(200)
969
+ end
970
+
971
+ it 'raises an error', unless: write_command_enabled? do
972
+ expect {
973
+ cursors
974
+ }.to raise_error(Mongo::Error::OperationFailure)
975
+ end
976
+ end
977
+
978
+ describe '#replace_one' do
979
+
980
+ let(:selector) do
981
+ { field: 'test1' }
982
+ end
983
+
984
+ context 'when a selector was provided' do
985
+
986
+ before do
987
+ authorized_collection.insert_many([{ field: 'test1' }, { field: 'test1' }])
988
+ end
989
+
990
+ after do
991
+ authorized_collection.delete_many
992
+ end
993
+
994
+ let!(:response) do
995
+ authorized_collection.replace_one(selector, { field: 'testing' })
996
+ end
997
+
998
+ let(:updated) do
999
+ authorized_collection.find(field: 'testing').first
1000
+ end
1001
+
1002
+ it 'updates the first matching document in the collection' do
1003
+ expect(response.modified_count).to eq(1)
1004
+ end
1005
+
1006
+ it 'updates the documents in the collection' do
1007
+ expect(updated[:field]).to eq('testing')
1008
+ end
1009
+ end
1010
+
1011
+ context 'when upsert is false' do
1012
+
1013
+ let!(:response) do
1014
+ authorized_collection.replace_one(selector, { field: 'test1' }, upsert: false)
1015
+ end
1016
+
1017
+ let(:updated) do
1018
+ authorized_collection.find(field: 'test1').to_a
1019
+ end
1020
+
1021
+ it 'reports that no documents were written' do
1022
+ expect(response.modified_count).to eq(0)
1023
+ end
1024
+
1025
+ it 'does not insert the document' do
1026
+ expect(updated).to be_empty
1027
+ end
1028
+ end
1029
+
1030
+ context 'when upsert is true' do
1031
+
1032
+ let!(:response) do
1033
+ authorized_collection.replace_one(selector, { field: 'test1' }, upsert: true)
1034
+ end
1035
+
1036
+ let(:updated) do
1037
+ authorized_collection.find(field: 'test1').first
1038
+ end
1039
+
1040
+ after do
1041
+ authorized_collection.delete_many
1042
+ end
1043
+
1044
+ it 'reports that a document was written' do
1045
+ expect(response.written_count).to eq(1)
1046
+ end
1047
+
1048
+ it 'inserts the document' do
1049
+ expect(updated[:field]).to eq('test1')
1050
+ end
1051
+ end
1052
+
1053
+ context 'when upsert is not specified' do
1054
+
1055
+ let!(:response) do
1056
+ authorized_collection.replace_one(selector, { field: 'test1' })
1057
+ end
1058
+
1059
+ let(:updated) do
1060
+ authorized_collection.find(field: 'test1').to_a
1061
+ end
1062
+
1063
+ it 'reports that no documents were written' do
1064
+ expect(response.modified_count).to eq(0)
1065
+ end
1066
+
1067
+ it 'does not insert the document' do
1068
+ expect(updated).to be_empty
1069
+ end
1070
+ end
1071
+
1072
+ context 'when the replace fails' do
1073
+
1074
+ let(:result) do
1075
+ authorized_collection.replace_one(selector, { '$s' => 'test1' })
1076
+ end
1077
+
1078
+ it 'raises an OperationFailure' do
1079
+ expect {
1080
+ result
1081
+ }.to raise_exception(Mongo::Error::OperationFailure)
1082
+ end
1083
+ end
1084
+ end
1085
+
1086
+ describe '#update_many' do
1087
+
1088
+ let(:selector) do
1089
+ { field: 'test' }
1090
+ end
1091
+
1092
+ after do
1093
+ authorized_collection.delete_many
1094
+ end
1095
+
1096
+ context 'when a selector was provided' do
1097
+
1098
+ before do
1099
+ authorized_collection.insert_many([{ field: 'test' }, { field: 'test' }])
1100
+ end
1101
+
1102
+ let!(:response) do
1103
+ authorized_collection.update_many(selector, '$set'=> { field: 'testing' })
1104
+ end
1105
+
1106
+ let(:updated) do
1107
+ authorized_collection.find(field: 'testing').to_a.last
1108
+ end
1109
+
1110
+ it 'returns the number updated' do
1111
+ expect(response.modified_count).to eq(2)
1112
+ end
1113
+
1114
+ it 'updates the documents in the collection' do
1115
+ expect(updated[:field]).to eq('testing')
1116
+ end
1117
+ end
1118
+
1119
+ context 'when upsert is false' do
1120
+
1121
+ let(:response) do
1122
+ authorized_collection.update_many(selector, { '$set'=> { field: 'testing' } },
1123
+ upsert: false)
1124
+ end
1125
+
1126
+ let(:updated) do
1127
+ authorized_collection.find.to_a
1128
+ end
1129
+
1130
+ it 'reports that no documents were updated' do
1131
+ expect(response.modified_count).to eq(0)
1132
+ end
1133
+
1134
+ it 'updates no documents in the collection' do
1135
+ expect(updated).to be_empty
1136
+ end
1137
+ end
1138
+
1139
+ context 'when upsert is true' do
1140
+
1141
+ let!(:response) do
1142
+ authorized_collection.update_many(selector, { '$set'=> { field: 'testing' } },
1143
+ upsert: true)
1144
+ end
1145
+
1146
+ let(:updated) do
1147
+ authorized_collection.find.to_a.last
1148
+ end
1149
+
1150
+ it 'reports that a document was written' do
1151
+ expect(response.written_count).to eq(1)
1152
+ end
1153
+
1154
+ it 'inserts a document into the collection' do
1155
+ expect(updated[:field]).to eq('testing')
1156
+ end
1157
+ end
1158
+
1159
+ context 'when upsert is not specified' do
1160
+
1161
+ let(:response) do
1162
+ authorized_collection.update_many(selector, { '$set'=> { field: 'testing' } })
1163
+ end
1164
+
1165
+ let(:updated) do
1166
+ authorized_collection.find.to_a
1167
+ end
1168
+
1169
+ it 'reports that no documents were updated' do
1170
+ expect(response.modified_count).to eq(0)
1171
+ end
1172
+
1173
+ it 'updates no documents in the collection' do
1174
+ expect(updated).to be_empty
1175
+ end
1176
+ end
1177
+
1178
+ context 'when the updates fail' do
1179
+
1180
+ let(:result) do
1181
+ authorized_collection.update_many(selector, { '$s'=> { field: 'testing' } })
1182
+ end
1183
+
1184
+ it 'raises an OperationFailure' do
1185
+ expect {
1186
+ result
1187
+ }.to raise_exception(Mongo::Error::OperationFailure)
1188
+ end
1189
+ end
1190
+ end
1191
+
1192
+ describe '#update_one' do
1193
+
1194
+ let(:selector) do
1195
+ { field: 'test1' }
1196
+ end
1197
+
1198
+ context 'when a selector was provided' do
1199
+
1200
+ before do
1201
+ authorized_collection.insert_many([{ field: 'test1' }, { field: 'test1' }])
1202
+ end
1203
+
1204
+ let!(:response) do
1205
+ authorized_collection.update_one(selector, '$set'=> { field: 'testing' })
1206
+ end
1207
+
1208
+ let(:updated) do
1209
+ authorized_collection.find(field: 'testing').first
1210
+ end
1211
+
1212
+ it 'updates the first matching document in the collection' do
1213
+ expect(response.modified_count).to eq(1)
1214
+ end
1215
+
1216
+ it 'updates the documents in the collection' do
1217
+ expect(updated[:field]).to eq('testing')
1218
+ end
1219
+ end
1220
+
1221
+ context 'when upsert is false' do
1222
+
1223
+ let(:response) do
1224
+ authorized_collection.update_one(selector, { '$set'=> { field: 'testing' } },
1225
+ upsert: false)
1226
+ end
1227
+
1228
+ let(:updated) do
1229
+ authorized_collection.find.to_a
1230
+ end
1231
+
1232
+ it 'reports that no documents were updated' do
1233
+ expect(response.modified_count).to eq(0)
1234
+ end
1235
+
1236
+ it 'updates no documents in the collection' do
1237
+ expect(updated).to be_empty
1238
+ end
1239
+ end
1240
+
1241
+ context 'when upsert is true' do
1242
+
1243
+ let!(:response) do
1244
+ authorized_collection.update_one(selector, { '$set'=> { field: 'testing' } },
1245
+ upsert: true)
1246
+ end
1247
+
1248
+ let(:updated) do
1249
+ authorized_collection.find.first
1250
+ end
1251
+
1252
+ it 'reports that a document was written' do
1253
+ expect(response.written_count).to eq(1)
1254
+ end
1255
+
1256
+ it 'inserts a document into the collection' do
1257
+ expect(updated[:field]).to eq('testing')
1258
+ end
1259
+ end
1260
+
1261
+ context 'when upsert is not specified' do
1262
+
1263
+ let(:response) do
1264
+ authorized_collection.update_one(selector, { '$set'=> { field: 'testing' } })
1265
+ end
1266
+
1267
+ let(:updated) do
1268
+ authorized_collection.find.to_a
1269
+ end
1270
+
1271
+ it 'reports that no documents were updated' do
1272
+ expect(response.modified_count).to eq(0)
1273
+ end
1274
+
1275
+ it 'updates no documents in the collection' do
1276
+ expect(updated).to be_empty
1277
+ end
1278
+ end
1279
+
1280
+ context 'when the update fails' do
1281
+
1282
+ let(:result) do
1283
+ authorized_collection.update_one(selector, { '$s'=> { field: 'testing' } })
1284
+ end
1285
+
1286
+ it 'raises an OperationFailure' do
1287
+ expect {
1288
+ result
1289
+ }.to raise_exception(Mongo::Error::OperationFailure)
1290
+ end
1291
+ end
1292
+ end
1293
+
1294
+ describe '#find_one_and_delete' do
1295
+
1296
+ before do
1297
+ authorized_collection.insert_many([{ field: 'test1' }])
1298
+ end
1299
+
1300
+ let(:selector) do
1301
+ { field: 'test1' }
1302
+ end
1303
+
1304
+ context 'when a matching document is found' do
1305
+
1306
+ context 'when no options are provided' do
1307
+
1308
+ let!(:document) do
1309
+ authorized_collection.find_one_and_delete(selector)
1310
+ end
1311
+
1312
+ it 'deletes the document from the database' do
1313
+ expect(authorized_collection.find.to_a).to be_empty
1314
+ end
1315
+
1316
+ it 'returns the document' do
1317
+ expect(document['field']).to eq('test1')
1318
+ end
1319
+ end
1320
+
1321
+ context 'when a projection is provided' do
1322
+
1323
+ let!(:document) do
1324
+ authorized_collection.find_one_and_delete(selector, projection: { _id: 1 })
1325
+ end
1326
+
1327
+ it 'deletes the document from the database' do
1328
+ expect(authorized_collection.find.to_a).to be_empty
1329
+ end
1330
+
1331
+ it 'returns the document with limited fields' do
1332
+ expect(document['field']).to be_nil
1333
+ expect(document['_id']).to_not be_nil
1334
+ end
1335
+ end
1336
+
1337
+ context 'when a sort is provided' do
1338
+
1339
+ let!(:document) do
1340
+ authorized_collection.find_one_and_delete(selector, sort: { field: 1 })
1341
+ end
1342
+
1343
+ it 'deletes the document from the database' do
1344
+ expect(authorized_collection.find.to_a).to be_empty
1345
+ end
1346
+
1347
+ it 'returns the document with limited fields' do
1348
+ expect(document['field']).to eq('test1')
1349
+ end
1350
+ end
1351
+
1352
+ context 'when max_time_ms is provided', if: write_command_enabled? do
1353
+
1354
+ it 'includes the max_time_ms value in the command' do
1355
+ expect {
1356
+ authorized_collection.find_one_and_delete(selector, max_time_ms: 0.1)
1357
+ }.to raise_error(Mongo::Error::OperationFailure)
1358
+ end
1359
+ end
1360
+ end
1361
+
1362
+ context 'when no matching document is found' do
1363
+
1364
+ let(:selector) do
1365
+ { field: 'test5' }
1366
+ end
1367
+
1368
+ let!(:document) do
1369
+ authorized_collection.find_one_and_delete(selector)
1370
+ end
1371
+
1372
+ it 'returns nil' do
1373
+ expect(document).to be_nil
1374
+ end
1375
+ end
1376
+
1377
+ context 'when the operation fails', if: write_command_enabled? do
1378
+
1379
+ let(:result) do
1380
+ authorized_collection.find_one_and_delete(selector, max_time_ms: 0.1)
1381
+ end
1382
+
1383
+ it 'raises an OperationFailure' do
1384
+ expect {
1385
+ result
1386
+ }.to raise_exception(Mongo::Error::OperationFailure)
1387
+ end
1388
+ end
1389
+ end
1390
+
1391
+ describe '#find_one_and_update' do
1392
+
1393
+ let(:selector) do
1394
+ { field: 'test1' }
1395
+ end
1396
+
1397
+ before do
1398
+ authorized_collection.insert_many([{ field: 'test1' }])
1399
+ end
1400
+
1401
+ context 'when a matching document is found' do
1402
+
1403
+ context 'when no options are provided' do
1404
+
1405
+ let(:document) do
1406
+ authorized_collection.find_one_and_update(selector, { '$set' => { field: 'testing' }})
1407
+ end
1408
+
1409
+ it 'returns the original document' do
1410
+ expect(document['field']).to eq('test1')
1411
+ end
1412
+ end
1413
+
1414
+ context 'when no options are provided' do
1415
+
1416
+ let(:document) do
1417
+ authorized_collection.find_one_and_update(selector, { '$set' => { field: 'testing' }})
1418
+ end
1419
+
1420
+ it 'returns the original document' do
1421
+ expect(document['field']).to eq('test1')
1422
+ end
1423
+ end
1424
+
1425
+ context 'when return_document options are provided' do
1426
+
1427
+ context 'when return_document is :after' do
1428
+
1429
+ let(:document) do
1430
+ authorized_collection.find_one_and_update(selector, { '$set' => { field: 'testing' }}, :return_document => :after)
1431
+ end
1432
+
1433
+ it 'returns the new document' do
1434
+ expect(document['field']).to eq('testing')
1435
+ end
1436
+ end
1437
+
1438
+ context 'when return_document is :before' do
1439
+
1440
+ let(:document) do
1441
+ authorized_collection.find_one_and_update(selector, { '$set' => { field: 'testing' }}, :return_document => :before)
1442
+ end
1443
+
1444
+ it 'returns the original document' do
1445
+ expect(document['field']).to eq('test1')
1446
+ end
1447
+ end
1448
+ end
1449
+
1450
+ context 'when a projection is provided' do
1451
+
1452
+ let(:document) do
1453
+ authorized_collection.find_one_and_update(selector, { '$set' => { field: 'testing' }}, projection: { _id: 1 })
1454
+ end
1455
+
1456
+ it 'returns the document with limited fields' do
1457
+ expect(document['field']).to be_nil
1458
+ expect(document['_id']).to_not be_nil
1459
+ end
1460
+ end
1461
+
1462
+ context 'when a sort is provided' do
1463
+
1464
+ let(:document) do
1465
+ authorized_collection.find_one_and_update(selector, { '$set' => { field: 'testing' }}, sort: { field: 1 })
1466
+ end
1467
+
1468
+ it 'returns the original document' do
1469
+ expect(document['field']).to eq('test1')
1470
+ end
1471
+ end
1472
+ end
1473
+
1474
+ context 'when max_time_ms is provided' do
1475
+
1476
+ it 'includes the max_time_ms value in the command', if: write_command_enabled? do
1477
+ expect {
1478
+ authorized_collection.find_one_and_update(selector, { '$set' => { field: 'testing' }}, max_time_ms: 0.1)
1479
+ }.to raise_error(Mongo::Error::OperationFailure)
1480
+ end
1481
+ end
1482
+
1483
+ context 'when no matching document is found' do
1484
+
1485
+ let(:selector) do
1486
+ { field: 'test5' }
1487
+ end
1488
+
1489
+ let(:document) do
1490
+ authorized_collection.find_one_and_update(selector, { '$set' => { field: 'testing' }})
1491
+ end
1492
+
1493
+ it 'returns nil' do
1494
+ expect(document).to be_nil
1495
+ end
1496
+ end
1497
+
1498
+ context 'when no matching document is found' do
1499
+
1500
+ context 'when no upsert options are provided' do
1501
+
1502
+ let(:selector) do
1503
+ { field: 'test5' }
1504
+ end
1505
+
1506
+ let(:document) do
1507
+ authorized_collection.find_one_and_update(selector, { '$set' => { field: 'testing' }})
1508
+ end
1509
+
1510
+ it 'returns nil' do
1511
+ expect(document).to be_nil
1512
+ end
1513
+ end
1514
+
1515
+ context 'when upsert options are provided' do
1516
+
1517
+ let(:selector) do
1518
+ { field: 'test5' }
1519
+ end
1520
+
1521
+ let(:document) do
1522
+ authorized_collection.find_one_and_update(selector, { '$set' => { field: 'testing' }}, :upsert => true, :return_document => :after)
1523
+ end
1524
+
1525
+ it 'returns the new document' do
1526
+ expect(document['field']).to eq('testing')
1527
+ end
1528
+ end
1529
+ end
1530
+
1531
+ context 'when the operation fails', if: write_command_enabled? do
1532
+
1533
+ let(:result) do
1534
+ authorized_collection.find_one_and_update(selector, { '$set' => { field: 'testing' }}, max_time_ms: 0.1)
1535
+ end
1536
+
1537
+ it 'raises an OperationFailure' do
1538
+ expect {
1539
+ result
1540
+ }.to raise_exception(Mongo::Error::OperationFailure)
1541
+ end
1542
+ end
1543
+ end
1544
+
1545
+ describe '#find_one_and_replace' do
1546
+
1547
+ before do
1548
+ authorized_collection.insert_many([{ field: 'test1', other: 'sth' }])
1549
+ end
1550
+
1551
+ let(:selector) do
1552
+ { field: 'test1' }
1553
+ end
1554
+
1555
+ context 'when a matching document is found' do
1556
+
1557
+ context 'when no options are provided' do
1558
+
1559
+ let(:document) do
1560
+ authorized_collection.find_one_and_replace(selector, { field: 'testing' })
1561
+ end
1562
+
1563
+ it 'returns the original document' do
1564
+ expect(document['field']).to eq('test1')
1565
+ end
1566
+ end
1567
+
1568
+ context 'when return_document options are provided' do
1569
+
1570
+ context 'when return_document is :after' do
1571
+
1572
+ let(:document) do
1573
+ authorized_collection.find_one_and_replace(selector, { field: 'testing' }, :return_document => :after)
1574
+ end
1575
+
1576
+ it 'returns the new document' do
1577
+ expect(document['field']).to eq('testing')
1578
+ end
1579
+ end
1580
+
1581
+ context 'when return_document is :before' do
1582
+
1583
+ let(:document) do
1584
+ authorized_collection.find_one_and_replace(selector, { field: 'testing' }, :return_document => :before)
1585
+ end
1586
+
1587
+ it 'returns the original document' do
1588
+ expect(document['field']).to eq('test1')
1589
+ end
1590
+ end
1591
+ end
1592
+
1593
+ context 'when a projection is provided' do
1594
+
1595
+ let(:document) do
1596
+ authorized_collection.find_one_and_replace(selector, { field: 'testing' }, projection: { _id: 1 })
1597
+ end
1598
+
1599
+ it 'returns the document with limited fields' do
1600
+ expect(document['field']).to be_nil
1601
+ expect(document['_id']).to_not be_nil
1602
+ end
1603
+ end
1604
+
1605
+ context 'when a sort is provided' do
1606
+
1607
+ let(:document) do
1608
+ authorized_collection.find_one_and_replace(selector, { field: 'testing' }, :sort => { field: 1 })
1609
+ end
1610
+
1611
+ it 'returns the original document' do
1612
+ expect(document['field']).to eq('test1')
1613
+ end
1614
+ end
1615
+ end
1616
+
1617
+ context 'when no matching document is found' do
1618
+
1619
+ context 'when no upsert options are provided' do
1620
+
1621
+ let(:selector) do
1622
+ { field: 'test5' }
1623
+ end
1624
+
1625
+ let(:document) do
1626
+ authorized_collection.find_one_and_replace(selector, { field: 'testing' })
1627
+ end
1628
+
1629
+ it 'returns nil' do
1630
+ expect(document).to be_nil
1631
+ end
1632
+ end
1633
+
1634
+ context 'when upsert options are provided' do
1635
+
1636
+ let(:selector) do
1637
+ { field: 'test5' }
1638
+ end
1639
+
1640
+ let(:document) do
1641
+ authorized_collection.find_one_and_replace(selector, { field: 'testing' }, :upsert => true, :return_document => :after)
1642
+ end
1643
+
1644
+ it 'returns the new document' do
1645
+ expect(document['field']).to eq('testing')
1646
+ end
1647
+ end
1648
+ end
1649
+
1650
+ context 'when max_time_ms is provided', if: write_command_enabled? do
1651
+
1652
+ it 'includes the max_time_ms value in the command' do
1653
+ expect {
1654
+ authorized_collection.find_one_and_replace(selector, { field: 'testing' }, max_time_ms: 0.1)
1655
+ }.to raise_error(Mongo::Error::OperationFailure)
1656
+ end
1657
+ end
1658
+
1659
+ context 'when the operation fails', if: write_command_enabled? do
1660
+
1661
+ let(:result) do
1662
+ authorized_collection.find_one_and_replace(selector, { field: 'testing' }, max_time_ms: 0.1)
1663
+ end
1664
+
1665
+ it 'raises an OperationFailure' do
1666
+ expect {
1667
+ result
1668
+ }.to raise_exception(Mongo::Error::OperationFailure)
1669
+ end
1670
+ end
1671
+ end
390
1672
  end