mongo 1.12.5 → 2.0.0.beta

Sign up to get free protection for your applications and to get access to all the features.
Files changed (437) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data.tar.gz.sig +0 -0
  4. data/CONTRIBUTING.md +64 -0
  5. data/LICENSE +1 -1
  6. data/README.md +23 -125
  7. data/Rakefile +26 -21
  8. data/bin/mongo_console +6 -38
  9. data/lib/mongo.rb +23 -82
  10. data/lib/mongo/address.rb +111 -0
  11. data/lib/mongo/address/ipv4.rb +85 -0
  12. data/lib/mongo/address/ipv6.rb +85 -0
  13. data/lib/mongo/address/unix.rb +76 -0
  14. data/lib/mongo/auth.rb +108 -0
  15. data/lib/mongo/auth/cr.rb +44 -0
  16. data/lib/mongo/auth/cr/conversation.rb +119 -0
  17. data/lib/mongo/auth/executable.rb +52 -0
  18. data/lib/mongo/auth/ldap.rb +48 -0
  19. data/lib/mongo/auth/ldap/conversation.rb +92 -0
  20. data/lib/mongo/auth/roles.rb +104 -0
  21. data/lib/mongo/auth/scram.rb +53 -0
  22. data/lib/mongo/auth/scram/conversation.rb +450 -0
  23. data/lib/mongo/auth/user.rb +159 -0
  24. data/lib/mongo/auth/user/view.rb +102 -0
  25. data/lib/mongo/auth/x509.rb +48 -0
  26. data/lib/mongo/auth/x509/conversation.rb +92 -0
  27. data/lib/mongo/{gridfs.rb → bulk.rb} +2 -5
  28. data/lib/mongo/bulk/bulk_write.rb +307 -0
  29. data/lib/mongo/client.rb +233 -0
  30. data/lib/mongo/cluster.rb +203 -0
  31. data/lib/mongo/cluster/topology.rb +60 -0
  32. data/lib/mongo/cluster/topology/replica_set.rb +160 -0
  33. data/lib/mongo/cluster/topology/sharded.rb +132 -0
  34. data/lib/mongo/cluster/topology/standalone.rb +132 -0
  35. data/lib/mongo/cluster/topology/unknown.rb +155 -0
  36. data/lib/mongo/collection.rb +130 -1101
  37. data/lib/mongo/collection/view.rb +169 -0
  38. data/lib/mongo/collection/view/aggregation.rb +108 -0
  39. data/lib/mongo/collection/view/explainable.rb +49 -0
  40. data/lib/mongo/collection/view/immutable.rb +43 -0
  41. data/lib/mongo/collection/view/iterable.rb +48 -0
  42. data/lib/mongo/collection/view/map_reduce.rb +191 -0
  43. data/lib/mongo/collection/view/readable.rb +363 -0
  44. data/lib/mongo/collection/view/writable.rb +169 -0
  45. data/lib/mongo/cursor.rb +79 -680
  46. data/lib/mongo/database.rb +224 -0
  47. data/lib/mongo/database/view.rb +101 -0
  48. data/lib/mongo/error.rb +81 -0
  49. data/lib/mongo/error/bulk_write_failure.rb +41 -0
  50. data/lib/mongo/{utils/thread_local_variable_manager.rb → error/empty_batch.rb} +22 -8
  51. data/{test/functional/db_connection_test.rb → lib/mongo/error/invalid_bulk_operation.rb} +19 -8
  52. data/lib/mongo/error/invalid_collection_name.rb +39 -0
  53. data/lib/mongo/error/invalid_database_name.rb +39 -0
  54. data/{test/replica_set/ssl_test.rb → lib/mongo/error/invalid_document.rb} +21 -14
  55. data/lib/mongo/error/invalid_file.rb +38 -0
  56. data/lib/mongo/error/invalid_nonce.rb +46 -0
  57. data/lib/mongo/error/invalid_replacement_document.rb +39 -0
  58. data/lib/mongo/error/invalid_signature.rb +47 -0
  59. data/{test/functional/ssl_test.rb → lib/mongo/error/invalid_update_document.rb} +22 -12
  60. data/lib/mongo/error/max_bson_size.rb +40 -0
  61. data/lib/mongo/error/max_message_size.rb +42 -0
  62. data/lib/mongo/{utils.rb → error/need_primary_server.rb} +10 -6
  63. data/lib/mongo/{connection.rb → error/operation_failure.rb} +10 -6
  64. data/lib/mongo/error/parser.rb +77 -0
  65. data/lib/mongo/{connection/socket.rb → error/socket_error.rb} +10 -5
  66. data/lib/mongo/error/socket_timeout_error.rb +23 -0
  67. data/lib/mongo/error/unsupported_features.rb +43 -0
  68. data/lib/mongo/event.rb +40 -0
  69. data/lib/mongo/event/listeners.rb +63 -0
  70. data/lib/mongo/event/primary_elected.rb +53 -0
  71. data/lib/mongo/event/publisher.rb +42 -0
  72. data/lib/mongo/event/server_added.rb +53 -0
  73. data/lib/mongo/event/server_removed.rb +53 -0
  74. data/lib/mongo/event/subscriber.rb +41 -0
  75. data/lib/mongo/grid.rb +16 -0
  76. data/lib/mongo/grid/file.rb +94 -0
  77. data/lib/mongo/grid/file/chunk.rb +184 -0
  78. data/lib/mongo/grid/file/metadata.rb +223 -0
  79. data/lib/mongo/grid/fs.rb +149 -0
  80. data/lib/mongo/index.rb +64 -0
  81. data/lib/mongo/index/view.rb +205 -0
  82. data/lib/mongo/loggable.rb +126 -0
  83. data/lib/mongo/logger.rb +132 -0
  84. data/lib/mongo/operation.rb +26 -0
  85. data/lib/mongo/operation/aggregate.rb +100 -0
  86. data/lib/mongo/operation/aggregate/result.rb +84 -0
  87. data/lib/mongo/operation/batchable.rb +103 -0
  88. data/lib/mongo/operation/bulk_delete/result.rb +197 -0
  89. data/lib/mongo/operation/bulk_insert/result.rb +195 -0
  90. data/lib/mongo/operation/bulk_update/result.rb +295 -0
  91. data/lib/mongo/operation/command.rb +62 -0
  92. data/lib/mongo/operation/executable.rb +105 -0
  93. data/lib/mongo/operation/kill_cursors.rb +39 -0
  94. data/lib/mongo/operation/limited.rb +37 -0
  95. data/lib/mongo/operation/list_collections/result.rb +116 -0
  96. data/lib/mongo/operation/list_indexes/result.rb +118 -0
  97. data/lib/mongo/operation/map_reduce.rb +96 -0
  98. data/lib/mongo/operation/map_reduce/result.rb +122 -0
  99. data/lib/mongo/{functional.rb → operation/read.rb} +7 -7
  100. data/lib/mongo/operation/read/collections_info.rb +67 -0
  101. data/lib/mongo/operation/read/get_more.rb +71 -0
  102. data/lib/mongo/operation/read/indexes.rb +68 -0
  103. data/lib/mongo/operation/read/list_collections.rb +75 -0
  104. data/lib/mongo/operation/read/list_indexes.rb +77 -0
  105. data/lib/mongo/operation/read/query.rb +71 -0
  106. data/lib/mongo/operation/read_preferrable.rb +34 -0
  107. data/lib/mongo/operation/result.rb +259 -0
  108. data/lib/mongo/operation/specifiable.rb +380 -0
  109. data/lib/mongo/operation/write.rb +25 -0
  110. data/lib/mongo/operation/write/bulk_delete.rb +158 -0
  111. data/lib/mongo/operation/write/bulk_insert.rb +160 -0
  112. data/lib/mongo/operation/write/bulk_update.rb +167 -0
  113. data/lib/mongo/{connection/socket/socket_util.rb → operation/write/command.rb} +9 -24
  114. data/lib/mongo/operation/write/command/create_user.rb +43 -0
  115. data/lib/mongo/operation/write/command/delete.rb +56 -0
  116. data/lib/mongo/operation/write/command/drop_index.rb +51 -0
  117. data/lib/mongo/operation/write/command/ensure_index.rb +55 -0
  118. data/lib/mongo/operation/write/command/insert.rb +55 -0
  119. data/lib/mongo/operation/write/command/remove_user.rb +42 -0
  120. data/lib/mongo/operation/write/command/update.rb +60 -0
  121. data/lib/mongo/operation/write/command/writable.rb +61 -0
  122. data/lib/mongo/operation/write/create_index.rb +84 -0
  123. data/lib/mongo/operation/write/create_user.rb +75 -0
  124. data/lib/mongo/operation/write/delete.rb +91 -0
  125. data/lib/mongo/operation/write/drop_index.rb +62 -0
  126. data/lib/mongo/operation/write/insert.rb +88 -0
  127. data/lib/mongo/operation/write/remove_user.rb +70 -0
  128. data/lib/mongo/operation/write/update.rb +98 -0
  129. data/lib/mongo/protocol.rb +15 -0
  130. data/lib/mongo/protocol/bit_vector.rb +61 -0
  131. data/lib/mongo/protocol/delete.rb +94 -0
  132. data/lib/mongo/protocol/get_more.rb +99 -0
  133. data/lib/mongo/protocol/insert.rb +99 -0
  134. data/lib/mongo/protocol/kill_cursors.rb +74 -0
  135. data/lib/mongo/protocol/message.rb +252 -0
  136. data/lib/mongo/protocol/query.rb +147 -0
  137. data/lib/mongo/protocol/reply.rb +72 -0
  138. data/lib/mongo/protocol/serializers.rb +180 -0
  139. data/lib/mongo/protocol/update.rb +111 -0
  140. data/lib/mongo/server.rb +163 -0
  141. data/lib/mongo/server/connectable.rb +99 -0
  142. data/lib/mongo/server/connection.rb +133 -0
  143. data/lib/mongo/server/connection_pool.rb +141 -0
  144. data/lib/mongo/server/connection_pool/queue.rb +182 -0
  145. data/lib/mongo/server/context.rb +66 -0
  146. data/lib/mongo/server/description.rb +450 -0
  147. data/lib/mongo/server/description/features.rb +85 -0
  148. data/lib/mongo/server/description/inspector.rb +79 -0
  149. data/lib/mongo/server/description/inspector/primary_elected.rb +58 -0
  150. data/lib/mongo/server/description/inspector/server_added.rb +59 -0
  151. data/lib/mongo/server/description/inspector/server_removed.rb +59 -0
  152. data/lib/mongo/server/monitor.rb +160 -0
  153. data/lib/mongo/server/monitor/connection.rb +88 -0
  154. data/lib/mongo/server_selector.rb +81 -0
  155. data/lib/mongo/server_selector/nearest.rb +94 -0
  156. data/lib/mongo/server_selector/primary.rb +88 -0
  157. data/lib/mongo/server_selector/primary_preferred.rb +94 -0
  158. data/lib/mongo/server_selector/secondary.rb +91 -0
  159. data/lib/mongo/server_selector/secondary_preferred.rb +96 -0
  160. data/lib/mongo/server_selector/selectable.rb +209 -0
  161. data/lib/mongo/socket.rb +179 -0
  162. data/lib/mongo/socket/ssl.rb +108 -0
  163. data/lib/mongo/socket/tcp.rb +69 -0
  164. data/lib/mongo/socket/unix.rb +66 -0
  165. data/lib/mongo/uri.rb +504 -0
  166. data/lib/mongo/version.rb +21 -0
  167. data/lib/mongo/write_concern.rb +99 -0
  168. data/lib/mongo/write_concern/acknowledged.rb +38 -0
  169. data/lib/mongo/write_concern/normalizable.rb +73 -0
  170. data/lib/mongo/write_concern/unacknowledged.rb +43 -0
  171. data/mongo.gemspec +17 -14
  172. data/spec/mongo/address/ipv4_spec.rb +74 -0
  173. data/spec/mongo/address/ipv6_spec.rb +74 -0
  174. data/spec/mongo/address/unix_spec.rb +30 -0
  175. data/spec/mongo/address_spec.rb +206 -0
  176. data/spec/mongo/auth/cr_spec.rb +59 -0
  177. data/spec/mongo/auth/ldap_spec.rb +40 -0
  178. data/spec/mongo/auth/scram/conversation_spec.rb +197 -0
  179. data/spec/mongo/auth/scram_spec.rb +55 -0
  180. data/spec/mongo/auth/user/view_spec.rb +76 -0
  181. data/spec/mongo/auth/user_spec.rb +190 -0
  182. data/spec/mongo/auth/x509_spec.rb +40 -0
  183. data/spec/mongo/auth_spec.rb +65 -0
  184. data/spec/mongo/bulk/bulk_write_spec.rb +175 -0
  185. data/spec/mongo/client_spec.rb +564 -0
  186. data/spec/mongo/cluster/topology/replica_set_spec.rb +101 -0
  187. data/spec/mongo/cluster/topology/sharded_spec.rb +74 -0
  188. data/spec/mongo/cluster/topology/standalone_spec.rb +79 -0
  189. data/spec/mongo/cluster/topology_spec.rb +65 -0
  190. data/spec/mongo/cluster_spec.rb +129 -0
  191. data/spec/mongo/collection/view/aggregation_spec.rb +135 -0
  192. data/spec/mongo/collection/view/explainable_spec.rb +32 -0
  193. data/spec/mongo/collection/view/map_reduce_spec.rb +242 -0
  194. data/spec/mongo/collection/view/readable_spec.rb +603 -0
  195. data/spec/mongo/collection/view/writable_spec.rb +504 -0
  196. data/spec/mongo/collection/view_spec.rb +521 -0
  197. data/spec/mongo/collection_spec.rb +362 -0
  198. data/spec/mongo/cursor_spec.rb +295 -0
  199. data/spec/mongo/database_spec.rb +306 -0
  200. data/spec/mongo/error/parser_spec.rb +119 -0
  201. data/spec/mongo/event/publisher_spec.rb +50 -0
  202. data/spec/mongo/event/subscriber_spec.rb +34 -0
  203. data/spec/mongo/grid/file/chunk_spec.rb +226 -0
  204. data/spec/mongo/grid/file/metadata_spec.rb +69 -0
  205. data/spec/mongo/grid/file_spec.rb +138 -0
  206. data/spec/mongo/grid/fs_spec.rb +129 -0
  207. data/spec/mongo/index/view_spec.rb +226 -0
  208. data/spec/mongo/loggable_spec.rb +62 -0
  209. data/spec/mongo/logger_spec.rb +97 -0
  210. data/spec/mongo/operation/aggregate/result_spec.rb +80 -0
  211. data/spec/mongo/operation/aggregate_spec.rb +135 -0
  212. data/spec/mongo/operation/command_spec.rb +106 -0
  213. data/spec/mongo/operation/kill_cursors_spec.rb +66 -0
  214. data/spec/mongo/operation/limited_spec.rb +50 -0
  215. data/spec/mongo/operation/map_reduce_spec.rb +143 -0
  216. data/spec/mongo/operation/read/collections_info_spec.rb +40 -0
  217. data/spec/mongo/operation/read/get_more_spec.rb +81 -0
  218. data/spec/mongo/operation/read/indexes_spec.rb +31 -0
  219. data/spec/mongo/operation/read/query_spec.rb +84 -0
  220. data/spec/mongo/operation/result_spec.rb +275 -0
  221. data/spec/mongo/operation/specifiable_spec.rb +53 -0
  222. data/spec/mongo/operation/write/bulk_delete_spec.rb +473 -0
  223. data/spec/mongo/operation/write/bulk_insert_spec.rb +466 -0
  224. data/spec/mongo/operation/write/bulk_update_spec.rb +524 -0
  225. data/spec/mongo/operation/write/command/delete_spec.rb +116 -0
  226. data/spec/mongo/operation/write/command/insert_spec.rb +117 -0
  227. data/spec/mongo/operation/write/command/update_spec.rb +123 -0
  228. data/spec/mongo/operation/write/create_user_spec.rb +44 -0
  229. data/spec/mongo/operation/write/delete_spec.rb +178 -0
  230. data/spec/mongo/operation/write/drop_index_spec.rb +51 -0
  231. data/spec/mongo/operation/write/ensure_index_spec.rb +81 -0
  232. data/spec/mongo/operation/write/insert_spec.rb +231 -0
  233. data/spec/mongo/operation/write/remove_user_spec.rb +46 -0
  234. data/spec/mongo/operation/write/response_spec.rb +85 -0
  235. data/spec/mongo/operation/write/update_spec.rb +177 -0
  236. data/spec/mongo/protocol/delete_spec.rb +167 -0
  237. data/spec/mongo/protocol/get_more_spec.rb +146 -0
  238. data/spec/mongo/protocol/insert_spec.rb +161 -0
  239. data/spec/mongo/protocol/kill_cursors_spec.rb +101 -0
  240. data/spec/mongo/protocol/query_spec.rb +285 -0
  241. data/spec/mongo/protocol/reply_spec.rb +157 -0
  242. data/spec/mongo/protocol/update_spec.rb +186 -0
  243. data/spec/mongo/server/connection_pool/queue_spec.rb +170 -0
  244. data/spec/mongo/server/connection_pool_spec.rb +120 -0
  245. data/spec/mongo/server/connection_spec.rb +289 -0
  246. data/spec/mongo/server/description/features_spec.rb +138 -0
  247. data/spec/mongo/server/description/inspector/primary_elected_spec.rb +94 -0
  248. data/spec/mongo/server/description/inspector/server_added_spec.rb +92 -0
  249. data/spec/mongo/server/description/inspector/server_removed_spec.rb +95 -0
  250. data/spec/mongo/server/description_spec.rb +510 -0
  251. data/spec/mongo/server/monitor_spec.rb +130 -0
  252. data/spec/mongo/server_discovery_and_monitoring_spec.rb +103 -0
  253. data/spec/mongo/server_selection_rtt_spec.rb +104 -0
  254. data/spec/mongo/server_selection_spec.rb +89 -0
  255. data/spec/mongo/server_selector/nearest_spec.rb +250 -0
  256. data/spec/mongo/server_selector/primary_preferred_spec.rb +290 -0
  257. data/spec/mongo/server_selector/primary_spec.rb +114 -0
  258. data/spec/mongo/server_selector/secondary_preferred_spec.rb +252 -0
  259. data/spec/mongo/server_selector/secondary_spec.rb +196 -0
  260. data/spec/mongo/server_selector_spec.rb +101 -0
  261. data/spec/mongo/server_spec.rb +131 -0
  262. data/spec/mongo/uri_spec.rb +517 -0
  263. data/spec/mongo/write_concern/acknowledged_spec.rb +44 -0
  264. data/spec/mongo/write_concern/unacknowledged_spec.rb +15 -0
  265. data/spec/mongo_orchestration_spec.rb +70 -0
  266. data/spec/spec_helper.rb +148 -0
  267. data/spec/support/authorization.rb +245 -0
  268. data/spec/support/helpers.rb +140 -0
  269. data/spec/support/matchers.rb +37 -0
  270. data/spec/support/mongo_orchestration.rb +61 -0
  271. data/spec/support/mongo_orchestration/requestable.rb +109 -0
  272. data/spec/support/mongo_orchestration/standalone.rb +57 -0
  273. data/spec/support/sdam/rs/discover_arbiters.yml +41 -0
  274. data/spec/support/sdam/rs/discover_passives.yml +41 -0
  275. data/spec/support/sdam/rs/discover_primary.yml +40 -0
  276. data/spec/support/sdam/rs/discover_secondary.yml +41 -0
  277. data/spec/support/sdam/rs/discovery.yml +195 -0
  278. data/spec/support/sdam/rs/ghost_discovered.yml +39 -0
  279. data/spec/support/sdam/rs/hosts_differ_from_seeds.yml +34 -0
  280. data/spec/support/sdam/rs/member_reconfig.yml +68 -0
  281. data/spec/support/sdam/rs/member_standalone.yml +60 -0
  282. data/spec/support/sdam/rs/new_primary.yml +74 -0
  283. data/spec/support/sdam/rs/new_primary_wrong_set_name.yml +71 -0
  284. data/spec/support/sdam/rs/non_rs_member.yml +31 -0
  285. data/spec/support/sdam/rs/normalize_case.yml +49 -0
  286. data/spec/support/sdam/rs/primary_becomes_standalone.yml +52 -0
  287. data/spec/support/sdam/rs/primary_changes_set_name.yml +57 -0
  288. data/spec/support/sdam/rs/primary_disconnect.yml +56 -0
  289. data/spec/support/sdam/rs/primary_wrong_set_name.yml +27 -0
  290. data/spec/support/sdam/rs/response_from_removed.yml +63 -0
  291. data/spec/support/sdam/rs/rsother_discovered.yml +41 -0
  292. data/spec/support/sdam/rs/sec_not_auth.yml +49 -0
  293. data/spec/support/sdam/rs/secondary_wrong_set_name.yml +28 -0
  294. data/spec/support/sdam/rs/secondary_wrong_set_name_with_primary.yml +69 -0
  295. data/spec/support/sdam/rs/unexpected_mongos.yml +26 -0
  296. data/spec/support/sdam/rs/wrong_set_name.yml +35 -0
  297. data/spec/support/sdam/sharded/multiple_mongoses.yml +46 -0
  298. data/spec/support/sdam/sharded/non_mongos_removed.yml +41 -0
  299. data/spec/support/sdam/sharded/normalize_uri_case.yml +32 -0
  300. data/spec/support/sdam/single/direct_connection_external_ip.yml +34 -0
  301. data/spec/support/sdam/single/direct_connection_mongos.yml +33 -0
  302. data/spec/support/sdam/single/direct_connection_rsarbiter.yml +35 -0
  303. data/spec/support/sdam/single/direct_connection_rsprimary.yml +34 -0
  304. data/spec/support/sdam/single/direct_connection_rssecondary.yml +35 -0
  305. data/spec/support/sdam/single/direct_connection_slave.yml +32 -0
  306. data/spec/support/sdam/single/direct_connection_standalone.yml +32 -0
  307. data/spec/support/sdam/single/not_ok_response.yml +39 -0
  308. data/spec/support/sdam/single/standalone_removed.yml +32 -0
  309. data/spec/support/sdam/single/unavailable_seed.yml +28 -0
  310. data/spec/support/server_discovery_and_monitoring.rb +167 -0
  311. data/spec/support/server_selection.rb +140 -0
  312. data/spec/support/server_selection/rtt/first_value.yml +4 -0
  313. data/spec/support/server_selection/rtt/first_value_zero.yml +4 -0
  314. data/spec/support/server_selection/rtt/value_test_1.yml +4 -0
  315. data/spec/support/server_selection/rtt/value_test_2.yml +4 -0
  316. data/spec/support/server_selection/rtt/value_test_3.yml +4 -0
  317. data/spec/support/server_selection/rtt/value_test_4.yml +4 -0
  318. data/spec/support/server_selection/rtt/value_test_5.yml +4 -0
  319. data/spec/support/server_selection/selection/ReplicaSetNoPrimary/read/Nearest.yml +32 -0
  320. data/spec/support/server_selection/selection/ReplicaSetNoPrimary/read/Nearest_non_matching.yml +27 -0
  321. data/spec/support/server_selection/selection/ReplicaSetNoPrimary/read/Primary.yml +23 -0
  322. data/spec/support/server_selection/selection/ReplicaSetNoPrimary/read/PrimaryPreferred.yml +32 -0
  323. data/spec/support/server_selection/selection/ReplicaSetNoPrimary/read/PrimaryPreferred_non_matching.yml +27 -0
  324. data/spec/support/server_selection/selection/ReplicaSetNoPrimary/read/Secondary.yml +32 -0
  325. data/spec/support/server_selection/selection/ReplicaSetNoPrimary/read/SecondaryPreferred.yml +32 -0
  326. data/spec/support/server_selection/selection/ReplicaSetNoPrimary/read/SecondaryPreferred_non_matching.yml +27 -0
  327. data/spec/support/server_selection/selection/ReplicaSetNoPrimary/read/Secondary_non_matching.yml +27 -0
  328. data/spec/support/server_selection/selection/ReplicaSetWithPrimary/read/Nearest.yml +41 -0
  329. data/spec/support/server_selection/selection/ReplicaSetWithPrimary/read/Nearest_non_matching.yml +34 -0
  330. data/spec/support/server_selection/selection/ReplicaSetWithPrimary/read/Primary.yml +33 -0
  331. data/spec/support/server_selection/selection/ReplicaSetWithPrimary/read/PrimaryPreferred.yml +39 -0
  332. data/spec/support/server_selection/selection/ReplicaSetWithPrimary/read/PrimaryPreferred_non_matching.yml +36 -0
  333. data/spec/support/server_selection/selection/Sharded/read/SecondaryPreferred.yml +32 -0
  334. data/spec/support/server_selection/selection/Single/read/SecondaryPreferred.yml +23 -0
  335. data/spec/support/server_selection/selection/Unknown/read/SecondaryPreferred.yml +13 -0
  336. data/spec/support/server_selection_rtt.rb +41 -0
  337. data/spec/support/shared/bulk_write.rb +498 -0
  338. data/spec/support/shared/cursor.rb +38 -0
  339. data/spec/support/shared/operation.rb +77 -0
  340. data/spec/support/shared/protocol.rb +31 -0
  341. data/spec/support/shared/server_selector.rb +111 -0
  342. data/spec/support/shared/socket.rb +82 -0
  343. data/spec/support/travis.rb +14 -0
  344. metadata +523 -189
  345. metadata.gz.sig +0 -0
  346. data/VERSION +0 -1
  347. data/lib/mongo/bulk_write_collection_view.rb +0 -387
  348. data/lib/mongo/collection_writer.rb +0 -364
  349. data/lib/mongo/connection/node.rb +0 -249
  350. data/lib/mongo/connection/pool.rb +0 -340
  351. data/lib/mongo/connection/pool_manager.rb +0 -320
  352. data/lib/mongo/connection/sharding_pool_manager.rb +0 -67
  353. data/lib/mongo/connection/socket/ssl_socket.rb +0 -95
  354. data/lib/mongo/connection/socket/tcp_socket.rb +0 -87
  355. data/lib/mongo/connection/socket/unix_socket.rb +0 -39
  356. data/lib/mongo/db.rb +0 -808
  357. data/lib/mongo/exception.rb +0 -145
  358. data/lib/mongo/functional/authentication.rb +0 -455
  359. data/lib/mongo/functional/logging.rb +0 -85
  360. data/lib/mongo/functional/read_preference.rb +0 -183
  361. data/lib/mongo/functional/scram.rb +0 -556
  362. data/lib/mongo/functional/uri_parser.rb +0 -409
  363. data/lib/mongo/functional/write_concern.rb +0 -66
  364. data/lib/mongo/gridfs/grid.rb +0 -112
  365. data/lib/mongo/gridfs/grid_ext.rb +0 -53
  366. data/lib/mongo/gridfs/grid_file_system.rb +0 -163
  367. data/lib/mongo/gridfs/grid_io.rb +0 -484
  368. data/lib/mongo/legacy.rb +0 -140
  369. data/lib/mongo/mongo_client.rb +0 -697
  370. data/lib/mongo/mongo_replica_set_client.rb +0 -535
  371. data/lib/mongo/mongo_sharded_client.rb +0 -159
  372. data/lib/mongo/networking.rb +0 -372
  373. data/lib/mongo/utils/conversions.rb +0 -110
  374. data/lib/mongo/utils/core_ext.rb +0 -70
  375. data/lib/mongo/utils/server_version.rb +0 -69
  376. data/lib/mongo/utils/support.rb +0 -80
  377. data/test/functional/authentication_test.rb +0 -39
  378. data/test/functional/bulk_api_stress_test.rb +0 -133
  379. data/test/functional/bulk_write_collection_view_test.rb +0 -1198
  380. data/test/functional/client_test.rb +0 -627
  381. data/test/functional/collection_test.rb +0 -2175
  382. data/test/functional/collection_writer_test.rb +0 -83
  383. data/test/functional/conversions_test.rb +0 -163
  384. data/test/functional/cursor_fail_test.rb +0 -57
  385. data/test/functional/cursor_message_test.rb +0 -56
  386. data/test/functional/cursor_test.rb +0 -683
  387. data/test/functional/db_api_test.rb +0 -835
  388. data/test/functional/db_test.rb +0 -348
  389. data/test/functional/grid_file_system_test.rb +0 -285
  390. data/test/functional/grid_io_test.rb +0 -252
  391. data/test/functional/grid_test.rb +0 -273
  392. data/test/functional/pool_test.rb +0 -136
  393. data/test/functional/safe_test.rb +0 -98
  394. data/test/functional/support_test.rb +0 -62
  395. data/test/functional/timeout_test.rb +0 -60
  396. data/test/functional/uri_test.rb +0 -446
  397. data/test/functional/write_concern_test.rb +0 -118
  398. data/test/helpers/general.rb +0 -50
  399. data/test/helpers/test_unit.rb +0 -476
  400. data/test/replica_set/authentication_test.rb +0 -37
  401. data/test/replica_set/basic_test.rb +0 -189
  402. data/test/replica_set/client_test.rb +0 -393
  403. data/test/replica_set/connection_test.rb +0 -138
  404. data/test/replica_set/count_test.rb +0 -66
  405. data/test/replica_set/cursor_test.rb +0 -220
  406. data/test/replica_set/insert_test.rb +0 -157
  407. data/test/replica_set/max_values_test.rb +0 -151
  408. data/test/replica_set/pinning_test.rb +0 -105
  409. data/test/replica_set/query_test.rb +0 -73
  410. data/test/replica_set/read_preference_test.rb +0 -219
  411. data/test/replica_set/refresh_test.rb +0 -211
  412. data/test/replica_set/replication_ack_test.rb +0 -95
  413. data/test/sharded_cluster/basic_test.rb +0 -203
  414. data/test/shared/authentication/basic_auth_shared.rb +0 -260
  415. data/test/shared/authentication/bulk_api_auth_shared.rb +0 -249
  416. data/test/shared/authentication/gssapi_shared.rb +0 -176
  417. data/test/shared/authentication/sasl_plain_shared.rb +0 -96
  418. data/test/shared/authentication/scram_shared.rb +0 -92
  419. data/test/shared/ssl_shared.rb +0 -235
  420. data/test/test_helper.rb +0 -61
  421. data/test/threading/basic_test.rb +0 -120
  422. data/test/tools/mongo_config.rb +0 -708
  423. data/test/tools/mongo_config_test.rb +0 -160
  424. data/test/unit/client_test.rb +0 -381
  425. data/test/unit/collection_test.rb +0 -166
  426. data/test/unit/connection_test.rb +0 -335
  427. data/test/unit/cursor_test.rb +0 -307
  428. data/test/unit/db_test.rb +0 -136
  429. data/test/unit/grid_test.rb +0 -76
  430. data/test/unit/mongo_sharded_client_test.rb +0 -48
  431. data/test/unit/node_test.rb +0 -93
  432. data/test/unit/pool_manager_test.rb +0 -111
  433. data/test/unit/read_pref_test.rb +0 -406
  434. data/test/unit/read_test.rb +0 -159
  435. data/test/unit/safe_test.rb +0 -158
  436. data/test/unit/sharding_pool_manager_test.rb +0 -84
  437. data/test/unit/write_concern_test.rb +0 -175
@@ -1,2175 +0,0 @@
1
- # Copyright (C) 2009-2013 MongoDB, Inc.
2
- #
3
- # Licensed under the Apache License, Version 2.0 (the "License");
4
- # you may not use this file except in compliance with the License.
5
- # You may obtain a copy of the License at
6
- #
7
- # http://www.apache.org/licenses/LICENSE-2.0
8
- #
9
- # Unless required by applicable law or agreed to in writing, software
10
- # distributed under the License is distributed on an "AS IS" BASIS,
11
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
- # See the License for the specific language governing permissions and
13
- # limitations under the License.
14
-
15
- require 'rbconfig'
16
- require 'test_helper'
17
-
18
- class CollectionTest < Test::Unit::TestCase
19
-
20
- LIMITED_MAX_BSON_SIZE = 1024
21
- LIMITED_BSON_SIZE_WITH_HEADROOM = LIMITED_MAX_BSON_SIZE + MongoClient::APPEND_HEADROOM
22
- LIMITED_MAX_MESSAGE_SIZE = 3 * LIMITED_MAX_BSON_SIZE
23
- LIMITED_TEST_HEADROOM = 50
24
- LIMITED_VALID_VALUE_SIZE = LIMITED_MAX_BSON_SIZE - LIMITED_TEST_HEADROOM
25
- LIMITED_INVALID_VALUE_SIZE = LIMITED_MAX_BSON_SIZE + Mongo::MongoClient::COMMAND_HEADROOM + 1
26
-
27
- def setup
28
- @client ||= standard_connection(:op_timeout => 10)
29
- @db = @client.db(TEST_DB)
30
- @test = @db.collection("test")
31
- @version = @client.server_version
32
- @test.remove
33
- @ismaster = @client['admin'].command(:isMaster => 1)
34
- end
35
-
36
- @@wv0 = Mongo::MongoClient::RELEASE_2_4_AND_BEFORE
37
- @@wv2 = Mongo::MongoClient::BATCH_COMMANDS
38
- @@a_h = Mongo::MongoClient::APPEND_HEADROOM
39
- @@s_h = Mongo::MongoClient::SERIALIZE_HEADROOM
40
-
41
- def max_size_exception_test(client)
42
- base = [
43
- #[@@wv0, client.max_bson_size, nil, /xyzzy/], # succeeds standalone, fails whole suite
44
- ]
45
- base += max_size_exception_cruby_test(client) unless RUBY_PLATFORM == 'java'
46
- #base += max_size_exception_jruby_test if RUBY_PLATFORM == 'java'
47
- base += max_size_exception_commands_test(client) if @version >= '2.5.2'
48
- base
49
- end
50
-
51
- def max_size_exception_cruby_test(client)
52
- [
53
- [@@wv0, client.max_bson_size + 1, BSON::InvalidDocument, /Document.* too large/]
54
- ]
55
- end
56
-
57
- def max_size_exception_jruby_test(client)
58
- [@@wv0, client.max_bson_size + 1, Mongo::OperationFailure, /object to insert too large/]
59
- end
60
-
61
- def max_size_exception_commands_test(client)
62
- [
63
- #[@@wv2, client.max_bson_size, nil, /xyzzy/], # succeeds standalone, fails whole suite
64
- [@@wv2, client.max_bson_size + 1, Mongo::OperationFailure, /object to insert too large/],
65
- [@@wv2, client.max_bson_size + @@s_h, Mongo::OperationFailure, /object to insert too large/],
66
- [@@wv2, client.max_bson_size + @@a_h, BSON::InvalidDocument, /Document.* too large/]
67
- ]
68
- end
69
-
70
- def generate_sized_doc(size)
71
- doc = {"_id" => BSON::ObjectId.new, "x" => "y"}
72
- serialize_doc = BSON::BSON_CODER.serialize(doc, false, false, size)
73
- doc = {"_id" => BSON::ObjectId.new, "x" => "y" * (1 + size - serialize_doc.size)}
74
- assert_equal size, BSON::BSON_CODER.serialize(doc, false, false, size).size
75
- doc
76
- end
77
-
78
- def with_max_wire_version(client, wire_version) # does not support replica sets
79
- if client.wire_version_feature?(wire_version)
80
- client.class.class_eval(%Q{
81
- alias :old_max_wire_version :max_wire_version
82
- def max_wire_version
83
- #{wire_version}
84
- end
85
- })
86
- yield wire_version
87
- client.class.class_eval(%Q{
88
- alias :max_wire_version :old_max_wire_version
89
- })
90
- end
91
- end
92
-
93
- def test_insert_batch_max_sizes
94
- max_size_exception_test(@client).each do |wire_version, size, exc, regexp|
95
- with_max_wire_version(@client, wire_version) do
96
- @test.remove
97
- doc = generate_sized_doc(size)
98
- begin
99
- @test.insert([doc.dup])
100
- assert_equal nil, exc
101
- rescue => e
102
- assert_equal exc, e.class, "wire_version:#{wire_version}, size:#{size}, exc:#{exc} e:#{e.message.inspect} @version:#{@version}"
103
- assert_match regexp, e.message
104
- end
105
- end
106
- end
107
- end
108
-
109
- def test_single_delete_write_command
110
- return unless @version >= '2.5.4'
111
- @test.drop
112
- @test.insert([{ :a => 1 }, { :a => 1 }])
113
-
114
- command = BSON::OrderedHash['delete', @test.name,
115
- :deletes, [{ :q => { :a => 1 }, :limit => 1 }],
116
- :writeConcern, { :w => 1 },
117
- :ordered, false]
118
-
119
- result = @db.command(command)
120
- assert_equal 1, result['n']
121
- assert_equal 1, result['ok']
122
- assert_equal 1, @test.count
123
- end
124
-
125
- def test_multi_ordered_delete_write_command
126
- return unless @version >= '2.5.4'
127
- @test.drop
128
- @test.insert([{ :a => 1 }, { :a => 1 }])
129
-
130
- command = BSON::OrderedHash['delete', @test.name,
131
- :deletes, [{ :q => { :a => 1 }, :limit => 0 }],
132
- :writeConcern, { :w => 1 },
133
- :ordered, true]
134
-
135
- result = @db.command(command)
136
- assert_equal 2, result['n']
137
- assert_equal 1, result['ok']
138
- assert_equal 0, @test.count
139
- end
140
-
141
- def test_multi_unordered_delete_write_command
142
- return unless @version >= '2.5.4'
143
- @test.drop
144
- @test.insert([{ :a => 1 }, { :a => 1 }])
145
-
146
- command = BSON::OrderedHash['delete', @test.name,
147
- :deletes, [{ :q => { :a => 1 }, :limit => 0 }],
148
- :writeConcern, { :w => 1 },
149
- :ordered, false]
150
-
151
- result = @db.command(command)
152
- assert_equal 2, result['n']
153
- assert_equal 1, result['ok']
154
- assert_equal 0, @test.count
155
- end
156
-
157
- def test_delete_write_command_with_no_concern
158
- return unless @version >= '2.5.4'
159
- @test.drop
160
- @test.insert([{ :a => 1 }, { :a => 1 }])
161
-
162
- command = BSON::OrderedHash['delete', @test.name,
163
- :deletes, [{ :q => { :a => 1 }, :limit => 0 }],
164
- :ordered, false]
165
-
166
- result = @db.command(command)
167
- assert_equal 2, result['n']
168
- assert_equal 1, result['ok']
169
- assert_equal 0, @test.count
170
- end
171
-
172
- def test_delete_write_command_with_error
173
- return unless @version >= '2.5.4'
174
- @test.drop
175
- @test.insert([{ :a => 1 }, { :a => 1 }])
176
-
177
- command = BSON::OrderedHash['delete', @test.name,
178
- :deletes, [{ :q => { '$set' => { :a => 1 }}, :limit => 0 }],
179
- :writeConcern, { :w => 1 },
180
- :ordered, false]
181
-
182
- assert_raise Mongo::OperationFailure do
183
- @db.command(command)
184
- end
185
- end
186
-
187
- def test_single_insert_write_command
188
- return unless @version >= '2.5.4'
189
- @test.drop
190
-
191
- command = BSON::OrderedHash['insert', @test.name,
192
- :documents, [{ :a => 1 }],
193
- :writeConcern, { :w => 1 },
194
- :ordered, false]
195
-
196
- result = @db.command(command)
197
- assert_equal 1, result['ok']
198
- assert_equal 1, @test.count
199
- end
200
-
201
- def test_multi_ordered_insert_write_command
202
- return unless @version >= '2.5.4'
203
- @test.drop
204
-
205
- command = BSON::OrderedHash['insert', @test.name,
206
- :documents, [{ :a => 1 }, { :a => 2 }],
207
- :writeConcern, { :w => 1 },
208
- :ordered, true]
209
-
210
- result = @db.command(command)
211
- assert_equal 1, result['ok']
212
- assert_equal 2, @test.count
213
- end
214
-
215
- def test_multi_unordered_insert_write_command
216
- return unless @version >= '2.5.4'
217
- @test.drop
218
-
219
- command = BSON::OrderedHash['insert', @test.name,
220
- :documents, [{ :a => 1 }, { :a => 2 }],
221
- :writeConcern, { :w => 1 },
222
- :ordered, false]
223
-
224
- result = @db.command(command)
225
- assert_equal 1, result['ok']
226
- assert_equal 2, @test.count
227
- end
228
-
229
- def test_insert_write_command_with_no_concern
230
- return unless @version >= '2.5.4'
231
- @test.drop
232
-
233
- command = BSON::OrderedHash['insert', @test.name,
234
- :documents, [{ :a => 1 }, { :a => 2 }],
235
- :ordered, false]
236
-
237
- result = @db.command(command)
238
- assert_equal 1, result['ok']
239
- assert_equal 2, @test.count
240
- end
241
-
242
- def test_insert_write_command_with_error
243
- return unless @version >= '2.5.4'
244
- @test.drop
245
- @test.ensure_index([[:a, 1]], { :unique => true })
246
-
247
- command = BSON::OrderedHash['insert', @test.name,
248
- :documents, [{ :a => 1 }, { :a => 1 }],
249
- :writeConcern, { :w => 1 },
250
- :ordered, false]
251
-
252
- assert_raise Mongo::OperationFailure do
253
- @db.command(command)
254
- end
255
- end
256
-
257
- def test_single_update_write_command
258
- return unless @version >= '2.5.4'
259
- @test.drop
260
- @test.insert([{ :a => 1 }, { :a => 2 }])
261
-
262
- command = BSON::OrderedHash['update', @test.name,
263
- :updates, [{ :q => { :a => 1 }, :u => { '$set' => { :a => 2 }}}],
264
- :writeConcern, { :w => 1 }]
265
-
266
- result = @db.command(command)
267
- assert_equal 1, result['ok']
268
- assert_equal 1, result['n']
269
- assert_equal 2, @test.find({ :a => 2 }).count
270
- end
271
-
272
- def test_multi_ordered_update_write_command
273
- return unless @version >= '2.5.4'
274
- @test.drop
275
- @test.insert([{ :a => 1 }, { :a => 3 }])
276
-
277
- command = BSON::OrderedHash['update', @test.name,
278
- :updates, [
279
- { :q => { :a => 1 }, :u => { '$set' => { :a => 2 }}},
280
- { :q => { :a => 3 }, :u => { '$set' => { :a => 4 }}}
281
- ],
282
- :writeConcern, { :w => 1 },
283
- :ordered, true]
284
-
285
- result = @db.command(command)
286
- assert_equal 1, result['ok']
287
- assert_equal 2, result['n']
288
- assert_equal 1, @test.find({ :a => 2 }).count
289
- assert_equal 1, @test.find({ :a => 4 }).count
290
- end
291
-
292
- def test_multi_unordered_update_write_command
293
- return unless @version >= '2.5.4'
294
- @test.drop
295
- @test.insert([{ :a => 1 }, { :a => 3 }])
296
-
297
- command = BSON::OrderedHash['update', @test.name,
298
- :updates, [
299
- { :q => { :a => 1 }, :u => { '$set' => { :a => 2 }}},
300
- { :q => { :a => 3 }, :u => { '$set' => { :a => 4 }}}
301
- ],
302
- :writeConcern, { :w => 1 },
303
- :ordered, false]
304
-
305
- result = @db.command(command)
306
- assert_equal 1, result['ok']
307
- assert_equal 2, result['n']
308
- assert_equal 1, @test.find({ :a => 2 }).count
309
- assert_equal 1, @test.find({ :a => 4 }).count
310
- end
311
-
312
- def test_update_write_command_with_no_concern
313
- return unless @version >= '2.5.4'
314
- @test.drop
315
- @test.insert([{ :a => 1 }, { :a => 3 }])
316
-
317
- command = BSON::OrderedHash['update', @test.name,
318
- :updates, [
319
- { :q => { :a => 1 }, :u => { '$set' => { :a => 2 }}},
320
- { :q => { :a => 3 }, :u => { '$set' => { :a => 4 }}}
321
- ],
322
- :ordered, false]
323
-
324
- result = @db.command(command)
325
- assert_equal 1, result['ok']
326
- assert_equal 2, result['n']
327
- assert_equal 1, @test.find({ :a => 2 }).count
328
- assert_equal 1, @test.find({ :a => 4 }).count
329
- end
330
-
331
- def test_update_write_command_with_error
332
- return unless @version >= '2.5.4'
333
- @test.drop
334
- @test.ensure_index([[:a, 1]], { :unique => true })
335
- @test.insert([{ :a => 1 }, { :a => 2 }])
336
-
337
- command = BSON::OrderedHash['update', @test.name,
338
- :updates, [
339
- { :q => { :a => 2 }, :u => { '$set' => { :a => 1 }}}
340
- ],
341
- :ordered, false]
342
-
343
- assert_raise Mongo::OperationFailure do
344
- @db.command(command)
345
- end
346
- end
347
-
348
- def test_error_code
349
- coll = @db['test-error-code']
350
- coll.ensure_index(BSON::OrderedHash[:x, Mongo::ASCENDING], { :unique => true })
351
- coll.save(:x => 2)
352
- begin
353
- coll.save(:x => 2)
354
- rescue => ex
355
- assert_not_nil ex.error_code
356
- end
357
- coll.drop
358
- end
359
-
360
- def test_aggregation_cursor
361
- return unless @version >= '2.5.1'
362
- [10, 1000].each do |size|
363
- @test.drop
364
- size.times {|i| @test.insert({ :_id => i }) }
365
- expected_sum = size.times.reduce(:+)
366
-
367
- cursor = @test.aggregate(
368
- [{ :$project => {:_id => '$_id'}} ],
369
- :cursor => {}
370
- )
371
-
372
- assert_equal Mongo::Cursor, cursor.class
373
-
374
- cursor_sum = cursor.reduce(0) do |sum, doc|
375
- sum += doc['_id']
376
- end
377
-
378
- assert_equal expected_sum, cursor_sum
379
- end
380
- @test.drop
381
- end
382
-
383
- def test_aggregation_array
384
- return unless @version >= '2.5.1'
385
- @test.drop
386
- 100.times {|i| @test.insert({ :_id => i }) }
387
- agg = @test.aggregate([{ :$project => {:_id => '$_id'}} ])
388
-
389
- assert agg.kind_of?(Array)
390
-
391
- @test.drop
392
- end
393
-
394
- def test_aggregation_cursor_invalid_ops
395
- return unless @version >= '2.5.1'
396
- cursor = @test.aggregate([], :cursor => {})
397
- assert_raise(Mongo::InvalidOperation) { cursor.rewind! }
398
- assert_raise(Mongo::InvalidOperation) { cursor.explain }
399
- assert_raise(Mongo::InvalidOperation) { cursor.count }
400
- end
401
-
402
- def test_aggregation_invalid_read_pref
403
- assert_raise Mongo::MongoArgumentError do
404
- @test.aggregate([], :read => :invalid_read_pref)
405
- end
406
- end
407
-
408
- def test_aggregation_supports_explain
409
- return unless @version >= '2.5.3'
410
- @db.expects(:command).with do |selector, opts|
411
- opts[:explain] == true
412
- end.returns({ 'ok' => 1 })
413
- @test.aggregate([], :explain => true)
414
- end
415
-
416
- def test_aggregation_explain_returns_raw_result
417
- return unless @version >= '2.5.3'
418
- response = @test.aggregate([], :explain => true)
419
- assert response['stages']
420
- end
421
-
422
- def test_capped_method
423
- @db.create_collection('normal')
424
- assert !@db['normal'].capped?
425
- @db.drop_collection('normal')
426
-
427
- @db.create_collection('c', :capped => true, :size => 100_000)
428
- assert @db['c'].capped?
429
- @db.drop_collection('c')
430
- end
431
-
432
- def test_optional_pk_factory
433
- @coll_default_pk = @db.collection('stuff')
434
- assert_equal BSON::ObjectId, @coll_default_pk.pk_factory
435
- @coll_default_pk = @db.create_collection('more-stuff')
436
- assert_equal BSON::ObjectId, @coll_default_pk.pk_factory
437
-
438
- # Create a db with a pk_factory.
439
- client = MongoClient.new(ENV['MONGO_RUBY_DRIVER_HOST'] || 'localhost',
440
- ENV['MONGO_RUBY_DRIVER_PORT'] || MongoClient::DEFAULT_PORT)
441
- client[TEST_DB].authenticate(TEST_USER, TEST_USER_PWD)
442
- db = client.db(TEST_DB, :pk => Object.new)
443
-
444
- coll = db.collection('coll-with-pk')
445
- assert coll.pk_factory.is_a?(Object)
446
-
447
- coll = db.create_collection('created_coll_with_pk')
448
- assert coll.pk_factory.is_a?(Object)
449
- end
450
-
451
- class PKTest
452
- def self.create_pk
453
- end
454
- end
455
-
456
- def test_pk_factory_on_collection
457
- silently do
458
- @coll = Collection.new('foo', @db, PKTest)
459
- assert_equal PKTest, @coll.pk_factory
460
- end
461
-
462
- @coll2 = Collection.new('foo', @db, :pk => PKTest)
463
- assert_equal PKTest, @coll2.pk_factory
464
- end
465
-
466
- def test_valid_names
467
- assert_raise Mongo::InvalidNSName do
468
- @db["te$t"]
469
- end
470
-
471
- assert_raise Mongo::InvalidNSName do
472
- @db['$main']
473
- end
474
-
475
- assert @db['$cmd']
476
- assert @db['oplog.$main']
477
- end
478
-
479
- def test_collection
480
- assert_kind_of Collection, @db["test"]
481
- assert_equal @db["test"].name(), @db.collection("test").name()
482
- assert_equal @db["test"].name(), @db[:test].name()
483
-
484
- assert_kind_of Collection, @db["test"]["foo"]
485
- assert_equal @db["test"]["foo"].name(), @db.collection("test.foo").name()
486
- assert_equal @db["test"]["foo"].name(), @db["test.foo"].name()
487
-
488
- @db["test"]["foo"].remove
489
- @db["test"]["foo"].insert("x" => 5)
490
- assert_equal 5, @db.collection("test.foo").find_one()["x"]
491
- end
492
-
493
- def test_rename_collection
494
- @db.drop_collection('foo1')
495
- @db.drop_collection('bar1')
496
-
497
- @col = @db.create_collection('foo1')
498
- assert_equal 'foo1', @col.name
499
-
500
- @col.rename('bar1')
501
- assert_equal 'bar1', @col.name
502
- end
503
-
504
- def test_nil_id
505
- assert_equal 5, @test.insert({"_id" => 5, "foo" => "bar"})
506
- assert_equal 5, @test.save({"_id" => 5, "foo" => "baz"})
507
- assert_equal nil, @test.find_one("foo" => "bar")
508
- assert_equal "baz", @test.find_one(:_id => 5)["foo"]
509
- assert_raise OperationFailure do
510
- @test.insert({"_id" => 5, "foo" => "bar"})
511
- end
512
-
513
- assert_equal nil, @test.insert({"_id" => nil, "foo" => "bar"})
514
- assert_equal nil, @test.save({"_id" => nil, "foo" => "baz"})
515
- assert_equal nil, @test.find_one("foo" => "bar")
516
- assert_equal "baz", @test.find_one(:_id => nil)["foo"]
517
- assert_raise OperationFailure do
518
- @test.insert({"_id" => nil, "foo" => "bar"})
519
- end
520
- assert_raise OperationFailure do
521
- @test.insert({:_id => nil, "foo" => "bar"})
522
- end
523
- end
524
-
525
- def setup_for_distinct
526
- return unless @version > "1.1"
527
- @test.remove
528
- @test.insert([{:a => 0, :b => {:c => "a"}},
529
- {:a => 1, :b => {:c => "b"}},
530
- {:a => 1, :b => {:c => "c"}},
531
- {:a => 2, :b => {:c => "a"}},
532
- {:a => 3},
533
- {:a => 3}])
534
- end
535
-
536
- def test_distinct_queries
537
- return unless @version > "1.1"
538
- setup_for_distinct
539
- assert_equal [0, 1, 2, 3], @test.distinct(:a).sort
540
- assert_equal ["a", "b", "c"], @test.distinct("b.c").sort
541
- end
542
-
543
- def test_filter_collection_with_query
544
- return unless @version >= "1.2"
545
- setup_for_distinct
546
- assert_equal [2, 3], @test.distinct(:a, {:a => {"$gt" => 1}}).sort
547
- end
548
-
549
- def test_filter_nested_objects
550
- return unless @version >= "1.2"
551
- setup_for_distinct
552
- assert_equal ["a", "b"], @test.distinct("b.c", {"b.c" => {"$ne" => "c"}}).sort
553
- end
554
-
555
- def test_safe_insert
556
- @test.create_index("hello", :unique => true)
557
- begin
558
- a = {"hello" => "world"}
559
- @test.insert(a)
560
- @test.insert(a, :w => 0)
561
- assert(@db.get_last_error['err'].include?("11000"))
562
-
563
- assert_raise OperationFailure do
564
- @test.insert(a)
565
- end
566
- ensure
567
- @test.drop_indexes
568
- end
569
- end
570
-
571
- def test_bulk_insert
572
- docs = []
573
- docs << {:foo => 1}
574
- docs << {:foo => 2}
575
- docs << {:foo => 3}
576
- response = @test.insert(docs)
577
- assert_equal 3, response.length
578
- assert response.all? {|id| id.is_a?(BSON::ObjectId)}
579
- assert_equal 3, @test.count
580
- end
581
-
582
- def test_bulk_insert_with_continue_on_error
583
- if @version >= "2.0"
584
- @test.create_index([["foo", 1]], :unique => true)
585
- begin
586
- docs = []
587
- docs << {:foo => 1}
588
- docs << {:foo => 1}
589
- docs << {:foo => 2}
590
- docs << {:foo => 3}
591
- assert_raise OperationFailure do
592
- @test.insert(docs)
593
- end
594
- assert_equal 1, @test.count
595
- @test.remove
596
-
597
- docs = []
598
- docs << {:foo => 1}
599
- docs << {:foo => 1}
600
- docs << {:foo => 2}
601
- docs << {:foo => 3}
602
- assert_raise OperationFailure do
603
- @test.insert(docs, :continue_on_error => true)
604
- end
605
- assert_equal 3, @test.count
606
-
607
- @test.remove
608
- ensure
609
- @test.drop_index("foo_1")
610
- end
611
- end
612
- end
613
-
614
- def test_bson_valid_with_collect_on_error
615
- docs = []
616
- docs << {:foo => 1}
617
- docs << {:bar => 1}
618
- doc_ids, error_docs = @test.insert(docs, :collect_on_error => true)
619
- assert_equal 2, @test.count
620
- assert_equal 2, doc_ids.count
621
- assert_equal error_docs, []
622
- end
623
-
624
- def test_bson_invalid_key_serialize_error_with_collect_on_error
625
- docs = []
626
- docs << {:foo => 1}
627
- docs << {:bar => 1}
628
- invalid_docs = []
629
- invalid_docs << {'$invalid-key' => 1}
630
- invalid_docs << {'invalid.key' => 1}
631
- docs += invalid_docs
632
- assert_raise BSON::InvalidKeyName do
633
- @test.insert(docs, :collect_on_error => false)
634
- end
635
- assert_equal 2, @test.count
636
-
637
- doc_ids, error_docs = @test.insert(docs, :collect_on_error => true)
638
- assert_equal 2, @test.count
639
- assert_equal 2, doc_ids.count
640
- assert_equal error_docs, invalid_docs
641
- end
642
-
643
- def test_bson_invalid_encoding_serialize_error_with_collect_on_error
644
- # Broken for current JRuby
645
- if RUBY_PLATFORM == 'java' then return end
646
- docs = []
647
- docs << {:foo => 1}
648
- docs << {:bar => 1}
649
- invalid_docs = []
650
- invalid_docs << {"\223\372\226}" => 1} # non utf8 encoding
651
- docs += invalid_docs
652
-
653
- assert_raise BSON::InvalidStringEncoding do
654
- @test.insert(docs, :collect_on_error => false)
655
- end
656
- assert_equal 2, @test.count
657
-
658
- doc_ids, error_docs = @test.insert(docs, :collect_on_error => true)
659
- assert_equal 2, @test.count
660
- assert_equal 2, doc_ids.count
661
- assert_equal error_docs, invalid_docs
662
- end
663
-
664
- def test_insert_one_error_doc_with_collect_on_error
665
- invalid_doc = {'$invalid-key' => 1}
666
- invalid_docs = [invalid_doc]
667
- doc_ids, error_docs = @test.insert(invalid_docs, :collect_on_error => true)
668
- assert_equal [], doc_ids
669
- assert_equal [invalid_doc], error_docs
670
- end
671
-
672
- def test_insert_empty_docs_raises_exception
673
- assert_raise OperationFailure do
674
- @test.insert([])
675
- end
676
- end
677
-
678
- def test_insert_empty_docs_with_collect_on_error_raises_exception
679
- assert_raise OperationFailure do
680
- @test.insert([], :collect_on_error => true)
681
- end
682
- end
683
-
684
- def limited_collection
685
- conn = standard_connection(:connect => false)
686
- is_master = @ismaster.merge('maxBsonObjectSize' => LIMITED_MAX_BSON_SIZE,
687
- 'maxMessageSizeBytes' => LIMITED_MAX_BSON_SIZE)
688
- admin_db = Object.new
689
- admin_db.expects(:command).returns(is_master)
690
- conn.expects(:[]).with(TEST_DB).returns(admin_db)
691
- conn.connect
692
- return conn.db(TEST_DB)["test"]
693
- end
694
-
695
- def test_non_operation_failure_halts_insertion_with_continue_on_error
696
- coll = limited_collection
697
- if @client.wire_version_feature?(MongoClient::BATCH_COMMANDS)
698
- coll.db.stubs(:command).raises(OperationTimeout).times(1)
699
- else
700
- coll.db.connection.stubs(:send_message_with_gle).raises(OperationTimeout).times(1)
701
- end
702
- docs = []
703
- 10.times do
704
- docs << {'foo' => 'a' * LIMITED_VALID_VALUE_SIZE}
705
- end
706
- assert_raise OperationTimeout do
707
- coll.insert(docs, :continue_on_error => true)
708
- end
709
- end
710
-
711
- def test_chunking_batch_insert
712
- docs = []
713
- 10.times do
714
- docs << {'foo' => 'a' * LIMITED_VALID_VALUE_SIZE}
715
- end
716
- limited_collection.insert(docs)
717
- assert_equal 10, limited_collection.count
718
- end
719
-
720
- def test_chunking_batch_insert_without_collect_on_error
721
- docs = []
722
- 4.times do
723
- docs << {'foo' => 'a' * LIMITED_VALID_VALUE_SIZE}
724
- end
725
- invalid_docs = []
726
- invalid_docs << {'$invalid-key' => 1} # non utf8 encoding
727
- docs += invalid_docs
728
- 4.times do
729
- docs << {'foo' => 'a' * LIMITED_VALID_VALUE_SIZE}
730
- end
731
- assert_raise BSON::InvalidKeyName do
732
- limited_collection.insert(docs, :collect_on_error => false)
733
- end
734
- end
735
-
736
- def test_chunking_batch_insert_with_collect_on_error
737
- # Broken for current JRuby
738
- if RUBY_PLATFORM == 'java' then return end
739
- docs = []
740
- 4.times do
741
- docs << {'foo' => 'a' * LIMITED_VALID_VALUE_SIZE}
742
- end
743
- invalid_docs = []
744
- invalid_docs << {'$invalid-key' => 1} # non utf8 encoding
745
- docs += invalid_docs
746
- 4.times do
747
- docs << {'foo' => 'a' * LIMITED_VALID_VALUE_SIZE}
748
- end
749
- doc_ids, error_docs = limited_collection.insert(docs, :collect_on_error => true)
750
- assert_equal 8, doc_ids.count
751
- assert_equal doc_ids.count, limited_collection.count
752
- assert_equal error_docs, invalid_docs
753
- end
754
-
755
- def test_chunking_batch_insert_with_continue_on_error
756
- coll = limited_collection
757
- docs = []
758
- 4.times do
759
- docs << {'foo' => 'a' * LIMITED_VALID_VALUE_SIZE}
760
- end
761
- docs << {'_id' => 'b', 'foo' => 'a'}
762
- docs << {'_id' => 'b', 'foo' => 'c'}
763
- 4.times do
764
- docs << {'foo' => 'a' * LIMITED_VALID_VALUE_SIZE}
765
- end
766
- assert_raise OperationFailure do
767
- coll.insert(docs, :continue_on_error => true)
768
- end
769
- assert coll.count >= 6, "write commands need headroom for doc wrapping overhead - count:#{coll.count}"
770
- end
771
-
772
- def test_chunking_batch_insert_without_continue_on_error
773
- docs = []
774
- 4.times do
775
- docs << {'foo' => 'a' * LIMITED_VALID_VALUE_SIZE}
776
- end
777
- docs << {'_id' => 'b', 'foo' => 'a'}
778
- docs << {'_id' => 'b', 'foo' => 'c'}
779
- 4.times do
780
- docs << {'foo' => 'a' * LIMITED_VALID_VALUE_SIZE}
781
- end
782
- assert_raise OperationFailure do
783
- limited_collection.insert(docs, :continue_on_error => false)
784
- end
785
- assert_equal 5, limited_collection.count
786
- end
787
-
788
- def test_maximum_insert_size
789
- docs = []
790
- 3.times do
791
- docs << {'foo' => 'a' * LIMITED_VALID_VALUE_SIZE}
792
- end
793
- assert_equal limited_collection.insert(docs).length, 3
794
- end
795
-
796
- def test_maximum_document_size
797
- assert_raise InvalidDocument do
798
- limited_collection.insert({'foo' => 'a' * LIMITED_BSON_SIZE_WITH_HEADROOM})
799
- end
800
- end
801
-
802
- def test_maximum_save_size
803
- assert limited_collection.save({'foo' => 'a' * LIMITED_VALID_VALUE_SIZE})
804
- assert_raise InvalidDocument do
805
- limited_collection.save({'foo' => 'a' * LIMITED_BSON_SIZE_WITH_HEADROOM})
806
- end
807
- end
808
-
809
- def test_maximum_remove_size
810
- assert limited_collection.remove({'foo' => 'a' * LIMITED_VALID_VALUE_SIZE})
811
- assert_raise InvalidDocument do
812
- limited_collection.remove({'foo' => 'a' * LIMITED_BSON_SIZE_WITH_HEADROOM})
813
- end
814
- end
815
-
816
- def test_maximum_update_size
817
- assert_raise InvalidDocument do
818
- limited_collection.update(
819
- {'foo' => 'a' * LIMITED_BSON_SIZE_WITH_HEADROOM},
820
- {'foo' => 'a' * LIMITED_VALID_VALUE_SIZE}
821
- )
822
- end
823
-
824
- assert_raise InvalidDocument do
825
- limited_collection.update(
826
- {'foo' => 'a' * LIMITED_BSON_SIZE_WITH_HEADROOM},
827
- {'foo' => 'a' * LIMITED_MAX_BSON_SIZE}
828
- )
829
- end
830
-
831
- assert_raise InvalidDocument do
832
- limited_collection.update(
833
- {'foo' => 'a' * LIMITED_BSON_SIZE_WITH_HEADROOM},
834
- {'foo' => 'a' * LIMITED_BSON_SIZE_WITH_HEADROOM}
835
- )
836
- end
837
-
838
- assert limited_collection.update(
839
- {'foo' => 'a' * (LIMITED_VALID_VALUE_SIZE/2)},
840
- {'foo' => 'a' * (LIMITED_VALID_VALUE_SIZE/2)}
841
- )
842
- end
843
-
844
- def test_maximum_query_size
845
- assert limited_collection.find({'foo' => 'a' * LIMITED_VALID_VALUE_SIZE}).to_a
846
- assert limited_collection.find(
847
- {'foo' => 'a' * LIMITED_VALID_VALUE_SIZE},
848
- {:fields => {'foo' => 'a' * LIMITED_VALID_VALUE_SIZE}}
849
- ).to_a
850
-
851
- assert_raise InvalidDocument do
852
- limited_collection.find({'foo' => 'a' * LIMITED_INVALID_VALUE_SIZE}).to_a
853
- end
854
-
855
- assert_raise InvalidDocument do
856
- limited_collection.find(
857
- {'foo' => 'a' * LIMITED_VALID_VALUE_SIZE},
858
- {:fields => {'foo' => 'a' * LIMITED_MAX_BSON_SIZE}}
859
- ).to_a
860
- end
861
- end
862
-
863
- #if @version >= "1.5.1"
864
- # def test_safe_mode_with_advanced_safe_with_invalid_options
865
- # assert_raise_error ArgumentError, "Unknown key(s): wtime" do
866
- # @test.insert({:foo => 1}, :w => 2, :wtime => 1, :fsync => true)
867
- # end
868
- # assert_raise_error ArgumentError, "Unknown key(s): wtime" do
869
- # @test.update({:foo => 1}, {:foo => 2}, :w => 2, :wtime => 1, :fsync => true)
870
- # end
871
- #
872
- # assert_raise_error ArgumentError, "Unknown key(s): wtime" do
873
- # @test.remove({:foo => 2}, :w => 2, :wtime => 1, :fsync => true)
874
- # end
875
- # end
876
- #end
877
-
878
- def test_safe_mode_with_journal_commit_option
879
- with_default_journaling(@client) do
880
- @test.insert({:foo => 1}, :j => true)
881
- @test.update({:foo => 1}, {:foo => 2}, :j => true)
882
- @test.remove({:foo => 2}, :j => true)
883
- end
884
- end
885
-
886
- def test_jnote_raises_exception
887
- return unless @version < "2.5.3"
888
- with_no_journaling(@client) do
889
- ex = assert_raise Mongo::WriteConcernError do
890
- @test.insert({:foo => 1}, :j => true)
891
- end
892
- result = ex.result
893
- assert_true result.has_key?("jnote")
894
- end
895
- end
896
-
897
- def test_wnote_raises_exception_with_err_not_nil
898
- return unless @version < "2.5.3"
899
- ex = assert_raise Mongo::WriteConcernError do
900
- @test.insert({:foo => 1}, :w => 2)
901
- end
902
- result = ex.result
903
- assert_not_nil result["err"]
904
- assert_true result.has_key?("wnote")
905
- end
906
-
907
- def test_update
908
- id1 = @test.save("x" => 5)
909
- @test.update({}, {"$inc" => {"x" => 1}})
910
- assert_equal 1, @test.count()
911
- assert_equal 6, @test.find_one(:_id => id1)["x"]
912
-
913
- id2 = @test.save("x" => 1)
914
- @test.update({"x" => 6}, {"$inc" => {"x" => 1}})
915
- assert_equal 7, @test.find_one(:_id => id1)["x"]
916
- assert_equal 1, @test.find_one(:_id => id2)["x"]
917
- end
918
-
919
- def test_update_check_keys
920
- return unless @version < "2.5.3"
921
- @test.save("x" => 1)
922
- @test.update({"x" => 1}, {"$set" => {"a.b" => 2}})
923
- assert_equal 2, @test.find_one("x" => 1)["a"]["b"]
924
-
925
- assert_raise_error BSON::InvalidKeyName do
926
- @test.update({"x" => 1}, {"a.b" => 3})
927
- end
928
- end
929
-
930
- def test_multi_update
931
- return unless @version >= "1.1.3"
932
- @test.save("num" => 10)
933
- @test.save("num" => 10)
934
- @test.save("num" => 10)
935
- assert_equal 3, @test.count
936
-
937
- @test.update({"num" => 10}, {"$set" => {"num" => 100}}, :multi => true)
938
- @test.find.each do |doc|
939
- assert_equal 100, doc["num"]
940
- end
941
- end
942
-
943
- def test_upsert
944
- @test.update({"page" => "/"}, {"$inc" => {"count" => 1}}, :upsert => true)
945
- @test.update({"page" => "/"}, {"$inc" => {"count" => 1}}, :upsert => true)
946
-
947
- assert_equal 1, @test.count()
948
- assert_equal 2, @test.find_one()["count"]
949
- end
950
-
951
- def test_safe_update
952
- @test.create_index("x", :unique => true)
953
- @test.insert("x" => 5)
954
- @test.insert("x" => 10)
955
-
956
- # Can update an indexed collection.
957
- @test.update({}, {"$inc" => {"x" => 1}})
958
- assert !@db.error?
959
-
960
- # Can't duplicate an index.
961
- assert_raise OperationFailure do
962
- @test.update({}, {"x" => 10})
963
- end
964
- @test.drop
965
- end
966
-
967
- def test_safe_save
968
- @test.create_index("hello", :unique => true)
969
-
970
- @test.save("hello" => "world")
971
- @test.save({"hello" => "world"}, :w => 0)
972
-
973
- assert_raise OperationFailure do
974
- @test.save({"hello" => "world"})
975
- end
976
- @test.drop
977
- end
978
-
979
- def test_mocked_safe_remove
980
- @client = standard_connection
981
- @db = @client[TEST_DB]
982
- @test = @db['test-safe-remove']
983
- @test.save({:a => 20})
984
- @client.stubs(:receive).returns([[{'ok' => 0, 'err' => 'failed'}], 1, 0])
985
-
986
- assert_raise OperationFailure do
987
- @test.remove({})
988
- end
989
- @test.drop
990
- end
991
-
992
- def test_safe_remove
993
- @client = standard_connection
994
- @db = @client[TEST_DB]
995
- @test = @db['test-safe-remove']
996
- @test.remove
997
- @test.save({:a => 50})
998
- assert_equal 1, @test.remove({})["n"]
999
- @test.drop
1000
- end
1001
-
1002
- def test_remove_return_value
1003
- assert_equal true, @test.remove({}, :w => 0)
1004
- end
1005
-
1006
- def test_remove_with_limit
1007
- @test.insert([{:n => 1},{:n => 2},{:n => 3}])
1008
- @test.remove({}, :limit => 1)
1009
- assert_equal 2, @test.count
1010
- @test.remove({}, :limit => 0)
1011
- assert_equal 0, @test.count
1012
- end
1013
-
1014
- def test_count
1015
- @test.drop
1016
-
1017
- assert_equal 0, @test.count
1018
- @test.save(:x => 1)
1019
- @test.save(:x => 2)
1020
- assert_equal 2, @test.count
1021
-
1022
- assert_equal 1, @test.count(:query => {:x => 1})
1023
- assert_equal 1, @test.count(:limit => 1)
1024
- assert_equal 0, @test.count(:skip => 2)
1025
- end
1026
-
1027
- def test_count_with_hint
1028
- @test.drop
1029
- @test.save(:i => 1)
1030
- @test.save(:i => 2)
1031
- assert_equal 2, @test.count
1032
-
1033
- @test.ensure_index(BSON::OrderedHash[:i, Mongo::ASCENDING])
1034
-
1035
- # Check that a named_hint can be specified
1036
- assert_equal 1, @test.count(:query => { :i => 1 }, :named_hint => '_id_')
1037
- assert_equal 2, @test.count(:query => { }, :named_hint => '_id_')
1038
-
1039
- # Verify that the hint is being sent to the server by providing a bad hint
1040
- if @version > '2.6'
1041
- assert_raise Mongo::OperationFailure do
1042
- @test.count(:query => { :i => 1 }, :hint => 'bad_hint')
1043
- end
1044
- else
1045
- assert_equal 1, @test.count(:query => { :i => 1 }, :hint => 'bad_hint')
1046
- end
1047
-
1048
- # Verify that the named_hint is being sent to the server by providing a bad hint
1049
- if @version > '2.6'
1050
- assert_raise Mongo::OperationFailure do
1051
- @test.count(:query => { :i => 1 }, :named_hint => 'bad_hint')
1052
- end
1053
- else
1054
- assert_equal 1, @test.count(:query => { :i => 1 }, :named_hint => 'bad_hint')
1055
- end
1056
-
1057
- @test.ensure_index(BSON::OrderedHash[:x, Mongo::ASCENDING], :sparse => true)
1058
-
1059
- # The sparse index won't have any entries.
1060
- # Check that count returns 0 when using the hint.
1061
- expected = @version > '2.6' ? 0 : 1
1062
- assert_equal expected, @test.count(:query => { :i => 1 }, :hint => { 'x' => 1 })
1063
- assert_equal expected, @test.count(:query => { :i => 1 }, :hint => 'x')
1064
- assert_equal expected, @test.count(:query => { :i => 1 }, :named_hint => 'x_1')
1065
-
1066
- # Verify that the hint / named hint set on the collection is used.
1067
- @test.hint = { 'x' => 1 }
1068
- assert_equal expected, @test.count(:query => { :i => 1 })
1069
-
1070
- @test.hint = 'x'
1071
- assert_equal expected, @test.count(:query => { :i => 1 })
1072
-
1073
- # The driver should allow x_1, but the code sets named_hint to @hint without
1074
- # normalizing.
1075
- @test.named_hint = 'x'
1076
- assert_equal expected, @test.count(:query => { :i => 1 })
1077
-
1078
- assert_equal 2, @test.count(:query => { }, :hint => 'x')
1079
- assert_equal 2, @test.count(:query => { }, :named_hint => 'x_1')
1080
- end
1081
-
1082
- # Note: #size is just an alias for #count.
1083
- def test_size
1084
- @test.drop
1085
-
1086
- assert_equal 0, @test.count
1087
- assert_equal @test.size, @test.count
1088
- @test.save("x" => 1)
1089
- @test.save("x" => 2)
1090
- assert_equal @test.size, @test.count
1091
- end
1092
-
1093
- def test_no_timeout_option
1094
- @test.drop
1095
-
1096
- assert_raise ArgumentError, "Timeout can be set to false only when #find is invoked with a block." do
1097
- @test.find({}, :timeout => false)
1098
- end
1099
-
1100
- @test.find({}, :timeout => false) do |cursor|
1101
- assert_equal 0, cursor.count
1102
- end
1103
-
1104
- @test.save("x" => 1)
1105
- @test.save("x" => 2)
1106
- @test.find({}, :timeout => false) do |cursor|
1107
- assert_equal 2, cursor.count
1108
- end
1109
- end
1110
-
1111
- def test_default_timeout
1112
- cursor = @test.find
1113
- assert_equal true, cursor.timeout
1114
- end
1115
-
1116
- def test_fields_as_hash
1117
- @test.save(:a => 1, :b => 1, :c => 1)
1118
-
1119
- doc = @test.find_one({:a => 1}, :fields => {:b => 0})
1120
- assert_nil doc['b']
1121
- assert doc['a']
1122
- assert doc['c']
1123
-
1124
- doc = @test.find_one({:a => 1}, :fields => {:a => 1, :b => 1})
1125
- assert_nil doc['c']
1126
- assert doc['a']
1127
- assert doc['b']
1128
-
1129
-
1130
- assert_raise Mongo::OperationFailure do
1131
- @test.find_one({:a => 1}, :fields => {:a => 1, :b => 0})
1132
- end
1133
- end
1134
-
1135
-
1136
- def test_meta_field_projection
1137
- return unless @version >= '2.5.5'
1138
- @test.save({ :t => 'spam eggs and spam'})
1139
- @test.save({ :t => 'spam'})
1140
- @test.save({ :t => 'egg sausage and bacon'})
1141
-
1142
- @test.ensure_index([[:t, 'text']])
1143
- assert @test.find_one({ :$text => { :$search => 'spam' }},
1144
- { :fields => [:t, { :score => { :$meta => 'textScore' } }] })
1145
- end
1146
-
1147
- def test_sort_by_meta
1148
- return unless @version >= '2.5.5'
1149
- @test.save({ :t => 'spam eggs and spam'})
1150
- @test.save({ :t => 'spam'})
1151
- @test.save({ :t => 'egg sausage and bacon'})
1152
-
1153
- @test.ensure_index([[:t, 'text']])
1154
- assert @test.find({ :$text => { :$search => 'spam' }}).sort([:score, { '$meta' => 'textScore' }])
1155
- assert @test.find({ :$text => { :$search => 'spam' }}).sort(:score => { '$meta' =>'textScore' })
1156
- end
1157
-
1158
- def test_fields_with_slice
1159
- return unless @version >= "1.5.1"
1160
- @test.save({:foo => [1, 2, 3, 4, 5, 6], :test => 'slice'})
1161
-
1162
- doc = @test.find_one({:test => 'slice'}, :fields => {'foo' => {'$slice' => [0, 3]}})
1163
- assert_equal [1, 2, 3], doc['foo']
1164
- @test.remove
1165
- end
1166
-
1167
- def test_find_one
1168
- id = @test.save("hello" => "world", "foo" => "bar")
1169
-
1170
- assert_equal "world", @test.find_one()["hello"]
1171
- assert_equal @test.find_one(id), @test.find_one()
1172
- assert_equal @test.find_one(nil), @test.find_one()
1173
- assert_equal @test.find_one({}), @test.find_one()
1174
- assert_equal @test.find_one("hello" => "world"), @test.find_one()
1175
- assert_equal @test.find_one(BSON::OrderedHash["hello", "world"]), @test.find_one()
1176
-
1177
- assert @test.find_one(nil, :fields => ["hello"]).include?("hello")
1178
- assert !@test.find_one(nil, :fields => ["foo"]).include?("hello")
1179
- assert_equal ["_id"], @test.find_one(nil, :fields => []).keys()
1180
-
1181
- assert_equal nil, @test.find_one("hello" => "foo")
1182
- assert_equal nil, @test.find_one(BSON::OrderedHash["hello", "foo"])
1183
- assert_equal nil, @test.find_one(ObjectId.new)
1184
-
1185
- assert_raise TypeError do
1186
- @test.find_one(6)
1187
- end
1188
- end
1189
-
1190
- def test_find_one_with_max_time_ms
1191
- with_forced_timeout(@client) do
1192
- assert_raise ExecutionTimeout do
1193
- @test.find_one({}, { :max_time_ms => 100 })
1194
- end
1195
- end
1196
- end
1197
-
1198
- def test_find_one_with_compile_regex_option
1199
- regex = /.*/
1200
- @test.insert('r' => /.*/)
1201
- assert_kind_of Regexp, @test.find_one({})['r']
1202
- assert_kind_of Regexp, @test.find_one({}, :compile_regex => true)['r']
1203
- assert_equal BSON::Regex, @test.find_one({}, :compile_regex => false)['r'].class
1204
- end
1205
-
1206
- def test_insert_adds_id
1207
- doc = {"hello" => "world"}
1208
- @test.insert(doc)
1209
- assert(doc.include?(:_id))
1210
-
1211
- docs = [{"hello" => "world"}, {"hello" => "world"}]
1212
- @test.insert(docs)
1213
- docs.each do |d|
1214
- assert(d.include?(:_id))
1215
- end
1216
- end
1217
-
1218
- def test_save_adds_id
1219
- doc = {"hello" => "world"}
1220
- @test.save(doc)
1221
- assert(doc.include?(:_id))
1222
- end
1223
-
1224
- def test_optional_find_block
1225
- 10.times do |i|
1226
- @test.save("i" => i)
1227
- end
1228
-
1229
- x = nil
1230
- @test.find("i" => 2) { |cursor|
1231
- x = cursor.count()
1232
- }
1233
- assert_equal 1, x
1234
-
1235
- i = 0
1236
- @test.find({}, :skip => 5) do |cursor|
1237
- cursor.each do |doc|
1238
- i = i + 1
1239
- end
1240
- end
1241
- assert_equal 5, i
1242
-
1243
- c = nil
1244
- @test.find() do |cursor|
1245
- c = cursor
1246
- end
1247
- assert c.closed?
1248
- end
1249
-
1250
- def setup_aggregate_data
1251
- # save some data
1252
- @test.save( {
1253
- "_id" => 1,
1254
- "title" => "this is my title",
1255
- "author" => "bob",
1256
- "posted" => Time.utc(2000),
1257
- "pageViews" => 5 ,
1258
- "tags" => [ "fun" , "good" , "fun" ],
1259
- "comments" => [
1260
- { "author" => "joe", "text" => "this is cool" },
1261
- { "author" => "sam", "text" => "this is bad" }
1262
- ],
1263
- "other" => { "foo" => 5 }
1264
- } )
1265
-
1266
- @test.save( {
1267
- "_id" => 2,
1268
- "title" => "this is your title",
1269
- "author" => "dave",
1270
- "posted" => Time.utc(2001),
1271
- "pageViews" => 7,
1272
- "tags" => [ "fun" , "nasty" ],
1273
- "comments" => [
1274
- { "author" => "barbara" , "text" => "this is interesting" },
1275
- { "author" => "jenny", "text" => "i like to play pinball", "votes" => 10 }
1276
- ],
1277
- "other" => { "bar" => 14 }
1278
- })
1279
-
1280
- @test.save( {
1281
- "_id" => 3,
1282
- "title" => "this is some other title",
1283
- "author" => "jane",
1284
- "posted" => Time.utc(2002),
1285
- "pageViews" => 6 ,
1286
- "tags" => [ "nasty", "filthy" ],
1287
- "comments" => [
1288
- { "author" => "will" , "text" => "i don't like the color" } ,
1289
- { "author" => "jenny" , "text" => "can i get that in green?" }
1290
- ],
1291
- "other" => { "bar" => 14 }
1292
- })
1293
-
1294
- end
1295
-
1296
- def test_reponds_to_aggregate
1297
- return unless @version > '2.1.1'
1298
- assert_respond_to @test, :aggregate
1299
- end
1300
-
1301
- def test_aggregate_requires_arguments
1302
- return unless @version > '2.1.1'
1303
- assert_raise MongoArgumentError do
1304
- @test.aggregate()
1305
- end
1306
- end
1307
-
1308
- def test_aggregate_requires_valid_arguments
1309
- return unless @version > '2.1.1'
1310
- assert_raise MongoArgumentError do
1311
- @test.aggregate({})
1312
- end
1313
- end
1314
-
1315
- def test_aggregate_pipeline_operator_format
1316
- return unless @version > '2.1.1'
1317
- assert_raise Mongo::OperationFailure do
1318
- @test.aggregate([{"$project" => "_id"}])
1319
- end
1320
- end
1321
-
1322
- def test_aggregate_pipeline_operators_using_strings
1323
- return unless @version > '2.1.1'
1324
- setup_aggregate_data
1325
- desired_results = [ {"_id"=>1, "pageViews"=>5, "tags"=>["fun", "good", "fun"]},
1326
- {"_id"=>2, "pageViews"=>7, "tags"=>["fun", "nasty"]},
1327
- {"_id"=>3, "pageViews"=>6, "tags"=>["nasty", "filthy"]} ]
1328
- results = @test.aggregate([{"$project" => {"tags" => 1, "pageViews" => 1}}])
1329
- assert_equal desired_results, results
1330
- end
1331
-
1332
- def test_aggregate_pipeline_operators_using_symbols
1333
- return unless @version > '2.1.1'
1334
- setup_aggregate_data
1335
- desired_results = [ {"_id"=>1, "pageViews"=>5, "tags"=>["fun", "good", "fun"]},
1336
- {"_id"=>2, "pageViews"=>7, "tags"=>["fun", "nasty"]},
1337
- {"_id"=>3, "pageViews"=>6, "tags"=>["nasty", "filthy"]} ]
1338
- results = @test.aggregate([{"$project" => {:tags => 1, :pageViews => 1}}])
1339
- assert_equal desired_results, results
1340
- end
1341
-
1342
- def test_aggregate_command_using_sym
1343
- return unless @version > '2.1.1'
1344
- cmd = BSON::OrderedHash[:aggregate, @test.name, :pipeline, [{'$match' => {:_id => true}}]]
1345
- assert @db.command(cmd)
1346
- end
1347
-
1348
- def test_aggregate_pipeline_multiple_operators
1349
- return unless @version > '2.1.1'
1350
- setup_aggregate_data
1351
- results = @test.aggregate([{"$project" => {"tags" => 1, "pageViews" => 1}}, {"$match" => {"pageViews" => 7}}])
1352
- assert_equal 1, results.length
1353
- end
1354
-
1355
- def test_aggregate_pipeline_unwind
1356
- return unless @version > '2.1.1'
1357
- setup_aggregate_data
1358
- desired_results = [ {"_id"=>1, "title"=>"this is my title", "author"=>"bob", "posted"=>Time.utc(2000),
1359
- "pageViews"=>5, "tags"=>"fun", "comments"=>[{"author"=>"joe", "text"=>"this is cool"},
1360
- {"author"=>"sam", "text"=>"this is bad"}], "other"=>{"foo"=>5 } },
1361
- {"_id"=>1, "title"=>"this is my title", "author"=>"bob", "posted"=>Time.utc(2000),
1362
- "pageViews"=>5, "tags"=>"good", "comments"=>[{"author"=>"joe", "text"=>"this is cool"},
1363
- {"author"=>"sam", "text"=>"this is bad"}], "other"=>{"foo"=>5 } },
1364
- {"_id"=>1, "title"=>"this is my title", "author"=>"bob", "posted"=>Time.utc(2000),
1365
- "pageViews"=>5, "tags"=>"fun", "comments"=>[{"author"=>"joe", "text"=>"this is cool"},
1366
- {"author"=>"sam", "text"=>"this is bad"}], "other"=>{"foo"=>5 } },
1367
- {"_id"=>2, "title"=>"this is your title", "author"=>"dave", "posted"=>Time.utc(2001),
1368
- "pageViews"=>7, "tags"=>"fun", "comments"=>[{"author"=>"barbara", "text"=>"this is interesting"},
1369
- {"author"=>"jenny", "text"=>"i like to play pinball", "votes"=>10 }], "other"=>{"bar"=>14 } },
1370
- {"_id"=>2, "title"=>"this is your title", "author"=>"dave", "posted"=>Time.utc(2001),
1371
- "pageViews"=>7, "tags"=>"nasty", "comments"=>[{"author"=>"barbara", "text"=>"this is interesting"},
1372
- {"author"=>"jenny", "text"=>"i like to play pinball", "votes"=>10 }], "other"=>{"bar"=>14 } },
1373
- {"_id"=>3, "title"=>"this is some other title", "author"=>"jane", "posted"=>Time.utc(2002),
1374
- "pageViews"=>6, "tags"=>"nasty", "comments"=>[{"author"=>"will", "text"=>"i don't like the color"},
1375
- {"author"=>"jenny", "text"=>"can i get that in green?"}], "other"=>{"bar"=>14 } },
1376
- {"_id"=>3, "title"=>"this is some other title", "author"=>"jane", "posted"=>Time.utc(2002),
1377
- "pageViews"=>6, "tags"=>"filthy", "comments"=>[{"author"=>"will", "text"=>"i don't like the color"},
1378
- {"author"=>"jenny", "text"=>"can i get that in green?"}], "other"=>{"bar"=>14 } }
1379
- ]
1380
- results = @test.aggregate([{"$unwind"=> "$tags"}])
1381
- assert_equal desired_results, results
1382
- end
1383
-
1384
- def test_aggregate_with_compile_regex_option
1385
- return unless @version > '2.1.1'
1386
- # see SERVER-6470
1387
- return unless @version >= '2.3.2'
1388
- @test.insert({ 'r' => /.*/ })
1389
- result1 = @test.aggregate([])
1390
- assert_kind_of Regexp, result1.first['r']
1391
-
1392
- result2 = @test.aggregate([], :compile_regex => false)
1393
- assert_kind_of BSON::Regex, result2.first['r']
1394
-
1395
- return unless @version >= '2.5.1'
1396
- result = @test.aggregate([], :compile_regex => false, :cursor => {})
1397
- assert_kind_of BSON::Regex, result.first['r']
1398
- end
1399
-
1400
- def test_out_aggregate
1401
- return unless @version >= "2.5.2"
1402
- out_collection = 'test_out'
1403
- @db.drop_collection(out_collection)
1404
- setup_aggregate_data
1405
- docs = @test.find.to_a
1406
- pipeline = [{:$out => out_collection}]
1407
- @test.aggregate(pipeline)
1408
- assert_equal docs, @db.collection(out_collection).find.to_a
1409
- end
1410
-
1411
- def test_out_aggregate_nonprimary_sym_warns
1412
- return unless @version >= "2.5.2"
1413
- ReadPreference::expects(:warn).with(regexp_matches(/rerouted to primary/))
1414
- pipeline = [{:$out => 'test_out'}]
1415
- @test.aggregate(pipeline, :read => :secondary)
1416
- end
1417
-
1418
- def test_out_aggregate_nonprimary_string_warns
1419
- return unless @version >= "2.5.2"
1420
- ReadPreference::expects(:warn).with(regexp_matches(/rerouted to primary/))
1421
- pipeline = [{'$out' => 'test_out'}]
1422
- @test.aggregate(pipeline, :read => :secondary)
1423
- end
1424
-
1425
- def test_out_aggregate_string_returns_raw_response
1426
- return unless @version >= "2.5.2"
1427
- pipeline = [{'$out' => 'test_out'}]
1428
- response = @test.aggregate(pipeline)
1429
- assert response.respond_to?(:keys)
1430
- end
1431
-
1432
- def test_out_aggregate_sym_returns_raw_response
1433
- return unless @version >= "2.5.2"
1434
- pipeline = [{:$out => 'test_out'}]
1435
- response = @test.aggregate(pipeline)
1436
- assert response.respond_to?(:keys)
1437
- end
1438
-
1439
- def test_map_reduce
1440
- return unless @version > "1.1.1"
1441
- @test << { "user_id" => 1 }
1442
- @test << { "user_id" => 2 }
1443
-
1444
- m = "function() { emit(this.user_id, 1); }"
1445
- r = "function(k,vals) { return 1; }"
1446
- res = @test.map_reduce(m, r, :out => 'foo')
1447
- assert res.find_one({"_id" => 1})
1448
- assert res.find_one({"_id" => 2})
1449
- end
1450
-
1451
- def test_map_reduce_with_code_objects
1452
- return unless @version > "1.1.1"
1453
- @test << { "user_id" => 1 }
1454
- @test << { "user_id" => 2 }
1455
-
1456
- m = Code.new("function() { emit(this.user_id, 1); }")
1457
- r = Code.new("function(k,vals) { return 1; }")
1458
- res = @test.map_reduce(m, r, :out => 'foo')
1459
- assert res.find_one({"_id" => 1})
1460
- assert res.find_one({"_id" => 2})
1461
- end
1462
-
1463
- def test_map_reduce_with_options
1464
- return unless @version > "1.1.1"
1465
- @test.remove
1466
- @test << { "user_id" => 1 }
1467
- @test << { "user_id" => 2 }
1468
- @test << { "user_id" => 3 }
1469
-
1470
- m = Code.new("function() { emit(this.user_id, 1); }")
1471
- r = Code.new("function(k,vals) { return 1; }")
1472
- res = @test.map_reduce(m, r, :query => {"user_id" => {"$gt" => 1}}, :out => 'foo')
1473
- assert_equal 2, res.count
1474
- assert res.find_one({"_id" => 2})
1475
- assert res.find_one({"_id" => 3})
1476
- end
1477
-
1478
- def test_map_reduce_with_raw_response
1479
- return unless @version > "1.1.1"
1480
- m = Code.new("function() { emit(this.user_id, 1); }")
1481
- r = Code.new("function(k,vals) { return 1; }")
1482
- res = @test.map_reduce(m, r, :raw => true, :out => 'foo')
1483
- assert res["result"]
1484
- assert res["counts"]
1485
- assert res["timeMillis"]
1486
- end
1487
-
1488
- def test_map_reduce_with_output_collection
1489
- return unless @version > "1.1.1"
1490
- output_collection = "test-map-coll"
1491
- m = Code.new("function() { emit(this.user_id, 1); }")
1492
- r = Code.new("function(k,vals) { return 1; }")
1493
- res = @test.map_reduce(m, r, :raw => true, :out => output_collection)
1494
- assert_equal output_collection, res["result"]
1495
- assert res["counts"]
1496
- assert res["timeMillis"]
1497
- end
1498
-
1499
- def test_map_reduce_nonprimary_output_collection_reroutes
1500
- return unless @version > "1.1.1"
1501
- output_collection = "test-map-coll"
1502
- m = Code.new("function() { emit(this.user_id, 1); }")
1503
- r = Code.new("function(k,vals) { return 1; }")
1504
- Mongo::ReadPreference.expects(:warn).with(regexp_matches(/rerouted to primary/))
1505
- res = @test.map_reduce(m, r, :raw => true, :out => output_collection, :read => :secondary)
1506
- end
1507
-
1508
- def test_map_reduce_with_collection_merge
1509
- return unless @version >= "1.8.0"
1510
- @test << {:user_id => 1}
1511
- @test << {:user_id => 2}
1512
- output_collection = "test-map-coll"
1513
- m = Code.new("function() { emit(this.user_id, {count: 1}); }")
1514
- r = Code.new("function(k,vals) { var sum = 0;" +
1515
- " vals.forEach(function(v) { sum += v.count;} ); return {count: sum}; }")
1516
- res = @test.map_reduce(m, r, :out => output_collection)
1517
-
1518
- @test.remove
1519
- @test << {:user_id => 3}
1520
- res = @test.map_reduce(m, r, :out => {:merge => output_collection})
1521
- assert res.find.to_a.any? {|doc| doc["_id"] == 3 && doc["value"]["count"] == 1}
1522
-
1523
- @test.remove
1524
- @test << {:user_id => 3}
1525
- res = @test.map_reduce(m, r, :out => {:reduce => output_collection})
1526
- assert res.find.to_a.any? {|doc| doc["_id"] == 3 && doc["value"]["count"] == 2}
1527
-
1528
- assert_raise ArgumentError do
1529
- @test.map_reduce(m, r, :out => {:inline => 1})
1530
- end
1531
-
1532
- @test.map_reduce(m, r, :raw => true, :out => {:inline => 1})
1533
- assert res["results"]
1534
- end
1535
-
1536
- def test_map_reduce_with_collection_output_to_other_db
1537
- return unless @version > "1.1.1"
1538
- @test << {:user_id => 1}
1539
- @test << {:user_id => 2}
1540
-
1541
- m = Code.new("function() { emit(this.user_id, 1); }")
1542
- r = Code.new("function(k,vals) { return 1; }")
1543
- oh = BSON::OrderedHash.new
1544
- oh[:replace] = 'foo'
1545
- oh[:db] = TEST_DB
1546
- res = @test.map_reduce(m, r, :out => (oh))
1547
- assert res["result"]
1548
- assert res["counts"]
1549
- assert res["timeMillis"]
1550
- assert res.find.to_a.any? {|doc| doc["_id"] == 2 && doc["value"] == 1}
1551
- end
1552
-
1553
- def test_aggregation_allow_disk_use
1554
- return unless @version >= '2.5.5'
1555
- @db.expects(:command).with do |selector, opts|
1556
- opts[:allowDiskUse] == true
1557
- end.returns({ 'ok' => 1 })
1558
- @test.aggregate([], :allowDiskUse => true)
1559
- end
1560
-
1561
- def test_parallel_scan
1562
- return unless @version >= '2.5.5'
1563
- 8000.times { |i| @test.insert({ :_id => i }) }
1564
-
1565
- lock = Mutex.new
1566
- doc_ids = Set.new
1567
- threads = []
1568
- cursors = @test.parallel_scan(3)
1569
- cursors.each_with_index do |cursor, i|
1570
- threads << Thread.new do
1571
- docs = cursor.to_a
1572
- lock.synchronize do
1573
- docs.each do |doc|
1574
- doc_ids << doc['_id']
1575
- end
1576
- end
1577
- end
1578
- end
1579
- threads.each(&:join)
1580
- assert_equal 8000, doc_ids.count
1581
- end
1582
-
1583
- def test_find_and_modify
1584
- return unless @version > "1.3.0"
1585
- @test << { :a => 1, :processed => false }
1586
- @test << { :a => 2, :processed => false }
1587
- @test << { :a => 3, :processed => false }
1588
-
1589
- @test.find_and_modify(:query => {},
1590
- :sort => [['a', -1]],
1591
- :update => {"$set" => {:processed => true}})
1592
-
1593
- assert @test.find_one({:a => 3})['processed']
1594
- end
1595
-
1596
- def test_find_and_modify_with_invalid_options
1597
- @test << { :a => 1, :processed => false }
1598
- @test << { :a => 2, :processed => false }
1599
- @test << { :a => 3, :processed => false }
1600
-
1601
- assert_raise Mongo::OperationFailure do
1602
- @test.find_and_modify(:blimey => {})
1603
- end
1604
- end
1605
-
1606
- def test_find_and_modify_with_full_response
1607
- @test << { :a => 1, :processed => false }
1608
- @test << { :a => 2, :processed => false }
1609
- @test << { :a => 3, :processed => false }
1610
-
1611
- doc = @test.find_and_modify(:query => {},
1612
- :sort => [['a', -1]],
1613
- :update => {"$set" => {:processed => true}},
1614
- :full_response => true,
1615
- :new => true)
1616
-
1617
- assert doc['value']['processed']
1618
- assert ['ok', 'value', 'lastErrorObject'].all? { |key| doc.key?(key) }
1619
- end
1620
-
1621
- def test_coll_stats
1622
- return unless @version >= "1.3.5"
1623
- @test << {:n => 1}
1624
- @test.create_index("n")
1625
-
1626
- assert_equal "#{TEST_DB}.test", @test.stats['ns']
1627
- @test.drop
1628
- end
1629
-
1630
- def test_saving_dates_pre_epoch
1631
- if RbConfig::CONFIG['host_os'] =~ /mswin|mingw|cygwin/ then return true end
1632
- begin
1633
- @test.save({'date' => Time.utc(1600)})
1634
- assert_in_delta Time.utc(1600), @test.find_one()["date"], 2
1635
- rescue ArgumentError
1636
- # See note in test_date_before_epoch (BSONTest)
1637
- end
1638
- end
1639
-
1640
- def test_save_symbol_find_string
1641
- @test.save(:foo => :mike)
1642
-
1643
- assert_equal :mike, @test.find_one(:foo => :mike)["foo"]
1644
- assert_equal :mike, @test.find_one("foo" => :mike)["foo"]
1645
-
1646
- # TODO enable these tests conditionally based on server version (if >1.0)
1647
- # assert_equal :mike, @test.find_one(:foo => "mike")["foo"]
1648
- # assert_equal :mike, @test.find_one("foo" => "mike")["foo"]
1649
- end
1650
-
1651
- def test_batch_size
1652
- n_docs = 6
1653
- batch_size = n_docs/2
1654
- n_docs.times do |i|
1655
- @test.save(:foo => i)
1656
- end
1657
-
1658
- doc_count = 0
1659
- cursor = @test.find({}, :batch_size => batch_size)
1660
- cursor.next
1661
- assert_equal batch_size, cursor.instance_variable_get(:@returned)
1662
- doc_count += batch_size
1663
- batch_size.times { cursor.next }
1664
- assert_equal doc_count + batch_size, cursor.instance_variable_get(:@returned)
1665
- doc_count += batch_size
1666
- assert_equal n_docs, doc_count
1667
- end
1668
-
1669
- def test_batch_size_with_smaller_limit
1670
- n_docs = 6
1671
- batch_size = n_docs/2
1672
- n_docs.times do |i|
1673
- @test.insert(:foo => i)
1674
- end
1675
-
1676
- cursor = @test.find({}, :batch_size => batch_size, :limit => 2)
1677
- cursor.next
1678
- assert_equal 2, cursor.instance_variable_get(:@returned)
1679
- end
1680
-
1681
- def test_batch_size_with_larger_limit
1682
- n_docs = 6
1683
- batch_size = n_docs/2
1684
- n_docs.times do |i|
1685
- @test.insert(:foo => i)
1686
- end
1687
-
1688
- doc_count = 0
1689
- cursor = @test.find({}, :batch_size => batch_size, :limit => n_docs + 5)
1690
- cursor.next
1691
- assert_equal batch_size, cursor.instance_variable_get(:@returned)
1692
- doc_count += batch_size
1693
- batch_size.times { cursor.next }
1694
- assert_equal doc_count + batch_size, cursor.instance_variable_get(:@returned)
1695
- doc_count += batch_size
1696
- assert_equal n_docs, doc_count
1697
- end
1698
-
1699
- def test_batch_size_with_negative_limit
1700
- n_docs = 6
1701
- batch_size = n_docs/2
1702
- n_docs.times do |i|
1703
- @test.insert(:foo => i)
1704
- end
1705
-
1706
- cursor = @test.find({}, :batch_size => batch_size, :limit => -7)
1707
- cursor.next
1708
- assert_equal n_docs, cursor.instance_variable_get(:@returned)
1709
- end
1710
-
1711
- def test_limit_and_skip
1712
- 10.times do |i|
1713
- @test.save(:foo => i)
1714
- end
1715
-
1716
- assert_equal 5, @test.find({}, :skip => 5).next_document()["foo"]
1717
- assert_equal nil, @test.find({}, :skip => 10).next_document()
1718
-
1719
- assert_equal 5, @test.find({}, :limit => 5).to_a.length
1720
-
1721
- assert_equal 3, @test.find({}, :skip => 3, :limit => 5).next_document()["foo"]
1722
- assert_equal 5, @test.find({}, :skip => 3, :limit => 5).to_a.length
1723
- end
1724
-
1725
- def test_large_limit
1726
- 2000.times do |i|
1727
- @test.insert("x" => i, "y" => "mongomongo" * 1000)
1728
- end
1729
-
1730
- assert_equal 2000, @test.count
1731
-
1732
- i = 0
1733
- y = 0
1734
- @test.find({}, :limit => 1900).each do |doc|
1735
- i += 1
1736
- y += doc["x"]
1737
- end
1738
-
1739
- assert_equal 1900, i
1740
- assert_equal 1804050, y
1741
- end
1742
-
1743
- def test_small_limit
1744
- @test.insert("x" => "hello world")
1745
- @test.insert("x" => "goodbye world")
1746
-
1747
- assert_equal 2, @test.count
1748
-
1749
- x = 0
1750
- @test.find({}, :limit => 1).each do |doc|
1751
- x += 1
1752
- assert_equal "hello world", doc["x"]
1753
- end
1754
-
1755
- assert_equal 1, x
1756
- end
1757
-
1758
- def test_find_with_transformer
1759
- klass = Struct.new(:id, :a)
1760
- transformer = Proc.new { |doc| klass.new(doc['_id'], doc['a']) }
1761
- cursor = @test.find({}, :transformer => transformer)
1762
- assert_equal(transformer, cursor.transformer)
1763
- end
1764
-
1765
- def test_find_one_with_transformer
1766
- klass = Struct.new(:id, :a)
1767
- transformer = Proc.new { |doc| klass.new(doc['_id'], doc['a']) }
1768
- id = @test.insert('a' => 1)
1769
- doc = @test.find_one(id, :transformer => transformer)
1770
- assert_instance_of(klass, doc)
1771
- end
1772
-
1773
- def test_ensure_index
1774
- @test.drop_indexes
1775
- @test.insert("x" => "hello world")
1776
- assert_equal 1, @test.index_information.keys.count #default index
1777
-
1778
- @test.ensure_index([["x", Mongo::DESCENDING]], {})
1779
- assert_equal 2, @test.index_information.keys.count
1780
- assert @test.index_information.keys.include?("x_-1")
1781
-
1782
- @test.ensure_index([["x", Mongo::ASCENDING]])
1783
- assert @test.index_information.keys.include?("x_1")
1784
-
1785
- @test.ensure_index([["type", 1], ["date", -1]])
1786
- assert @test.index_information.keys.include?("type_1_date_-1")
1787
-
1788
- @test.drop_index("x_1")
1789
- assert_equal 3, @test.index_information.keys.count
1790
- @test.drop_index("x_-1")
1791
- assert_equal 2, @test.index_information.keys.count
1792
-
1793
- @test.ensure_index([["x", Mongo::DESCENDING]], {})
1794
- assert_equal 3, @test.index_information.keys.count
1795
- assert @test.index_information.keys.include?("x_-1")
1796
-
1797
- # Make sure that drop_index expires cache properly
1798
- @test.ensure_index([['a', 1]])
1799
- assert @test.index_information.keys.include?("a_1")
1800
- @test.drop_index("a_1")
1801
- assert !@test.index_information.keys.include?("a_1")
1802
- @test.ensure_index([['a', 1]])
1803
- assert @test.index_information.keys.include?("a_1")
1804
- @test.drop_index("a_1")
1805
- @test.drop_indexes
1806
- end
1807
-
1808
- def test_ensure_index_timeout
1809
- @db.cache_time = 1
1810
- coll = @db['ensure_test']
1811
- coll.expects(:generate_indexes).twice
1812
- coll.ensure_index([['a', 1]])
1813
-
1814
- # These will be cached
1815
- coll.ensure_index([['a', 1]])
1816
- coll.ensure_index([['a', 1]])
1817
- coll.ensure_index([['a', 1]])
1818
- coll.ensure_index([['a', 1]])
1819
-
1820
- sleep(1)
1821
- # This won't be, so generate_indexes will be called twice
1822
- coll.ensure_index([['a', 1]])
1823
- coll.drop
1824
- end
1825
-
1826
- def test_show_disk_loc
1827
- return unless @version > '2.0.0'
1828
- @test.save({:a => 1})
1829
- @test.save({:a => 2})
1830
- assert @test.find({:a => 1}, :show_disk_loc => true).show_disk_loc
1831
- doc = @test.find({:a => 1}, :show_disk_loc => true).next
1832
- assert (doc['$diskLoc'] || doc['$recordId'])
1833
- @test.remove
1834
- end
1835
-
1836
- def test_max_scan
1837
- return unless @version > '2.0.0'
1838
- @test.drop
1839
- n = 100
1840
- n.times do |i|
1841
- @test.save({:_id => i, :x => i % 10})
1842
- end
1843
- assert_equal(n, @test.find.to_a.size)
1844
- assert_equal(50, @test.find({}, :max_scan => 50).to_a.size)
1845
- assert_equal(10, @test.find({:x => 2}).to_a.size)
1846
- assert_equal(5, @test.find({:x => 2}, :max_scan => 50).to_a.size)
1847
- @test.ensure_index([[:x, 1]])
1848
- assert_equal(10, @test.find({:x => 2}, :max_scan => n).to_a.size)
1849
- @test.drop
1850
- end
1851
-
1852
- context "Grouping" do
1853
- setup do
1854
- @test.remove
1855
- @test.save("a" => 1)
1856
- @test.save("b" => 1)
1857
- @initial = {"count" => 0}
1858
- @reduce_function = "function (obj, prev) { prev.count += inc_value; }"
1859
- end
1860
-
1861
- should "fail if missing required options" do
1862
- assert_raise MongoArgumentError do
1863
- @test.group(:initial => {})
1864
- end
1865
-
1866
- assert_raise MongoArgumentError do
1867
- @test.group(:reduce => "foo")
1868
- end
1869
- end
1870
-
1871
- should "group results using eval form" do
1872
- assert_equal 1, @test.group(:initial => @initial, :reduce => Code.new(@reduce_function, {"inc_value" => 0.5}))[0]["count"]
1873
- assert_equal 2, @test.group(:initial => @initial, :reduce => Code.new(@reduce_function, {"inc_value" => 1}))[0]["count"]
1874
- assert_equal 4, @test.group(:initial => @initial, :reduce => Code.new(@reduce_function, {"inc_value" => 2}))[0]["count"]
1875
- end
1876
-
1877
- should "finalize grouped results" do
1878
- @finalize = "function(doc) {doc.f = doc.count + 200; }"
1879
- assert_equal 202, @test.group(:initial => @initial, :reduce => Code.new(@reduce_function, {"inc_value" => 1}), :finalize => @finalize)[0]["f"]
1880
- end
1881
- end
1882
-
1883
- context "Grouping with key" do
1884
- setup do
1885
- @test.remove
1886
- @test.save("a" => 1, "pop" => 100)
1887
- @test.save("a" => 1, "pop" => 100)
1888
- @test.save("a" => 2, "pop" => 100)
1889
- @test.save("a" => 2, "pop" => 100)
1890
- @initial = {"count" => 0, "foo" => 1}
1891
- @reduce_function = "function (obj, prev) { prev.count += obj.pop; }"
1892
- end
1893
-
1894
- should "group" do
1895
- result = @test.group(:key => :a, :initial => @initial, :reduce => @reduce_function)
1896
- assert result.all? { |r| r['count'] == 200 }
1897
- end
1898
- end
1899
-
1900
- context "Grouping with a key function" do
1901
- setup do
1902
- @test.remove
1903
- @test.save("a" => 1)
1904
- @test.save("a" => 2)
1905
- @test.save("a" => 3)
1906
- @test.save("a" => 4)
1907
- @test.save("a" => 5)
1908
- @initial = {"count" => 0}
1909
- @keyf = "function (doc) { if(doc.a % 2 == 0) { return {even: true}; } else {return {odd: true}} };"
1910
- @reduce = "function (obj, prev) { prev.count += 1; }"
1911
- end
1912
-
1913
- should "group results" do
1914
- results = @test.group(:keyf => @keyf, :initial => @initial, :reduce => @reduce).sort {|a, b| a['count'] <=> b['count']}
1915
- assert results[0]['even'] && results[0]['count'] == 2.0
1916
- assert results[1]['odd'] && results[1]['count'] == 3.0
1917
- end
1918
-
1919
- should "group filtered results" do
1920
- results = @test.group(:keyf => @keyf, :cond => {:a => {'$ne' => 2}},
1921
- :initial => @initial, :reduce => @reduce).sort {|a, b| a['count'] <=> b['count']}
1922
- assert results[0]['even'] && results[0]['count'] == 1.0
1923
- assert results[1]['odd'] && results[1]['count'] == 3.0
1924
- end
1925
- end
1926
-
1927
- context "A collection with two records" do
1928
- setup do
1929
- @collection = @db.collection('test-collection')
1930
- @collection.remove
1931
- @collection.insert({:name => "Jones"})
1932
- @collection.insert({:name => "Smith"})
1933
- end
1934
-
1935
- should "have two records" do
1936
- assert_equal 2, @collection.size
1937
- end
1938
-
1939
- should "remove the two records" do
1940
- @collection.remove()
1941
- assert_equal 0, @collection.size
1942
- end
1943
-
1944
- should "remove all records if an empty document is specified" do
1945
- @collection.remove({})
1946
- assert_equal 0, @collection.find.count
1947
- end
1948
-
1949
- should "remove only matching records" do
1950
- @collection.remove({:name => "Jones"})
1951
- assert_equal 1, @collection.size
1952
- end
1953
- end
1954
-
1955
- context "Drop index " do
1956
- setup do
1957
- @db.drop_collection('test-collection')
1958
- @collection = @db.collection('test-collection')
1959
- end
1960
-
1961
- should "drop an index" do
1962
- @collection.create_index([['a', Mongo::ASCENDING]])
1963
- assert @collection.index_information['a_1']
1964
- @collection.drop_index([['a', Mongo::ASCENDING]])
1965
- assert_nil @collection.index_information['a_1']
1966
- end
1967
-
1968
- should "drop an index which was given a specific name" do
1969
- @collection.create_index([['a', Mongo::DESCENDING]], {:name => 'i_will_not_fear'})
1970
- assert @collection.index_information['i_will_not_fear']
1971
- @collection.drop_index([['a', Mongo::DESCENDING]])
1972
- assert_nil @collection.index_information['i_will_not_fear']
1973
- end
1974
-
1975
- should "drops an composite index" do
1976
- @collection.create_index([['a', Mongo::DESCENDING], ['b', Mongo::ASCENDING]])
1977
- assert @collection.index_information['a_-1_b_1']
1978
- @collection.drop_index([['a', Mongo::DESCENDING], ['b', Mongo::ASCENDING]])
1979
- assert_nil @collection.index_information['a_-1_b_1']
1980
- end
1981
-
1982
- should "drops an index with symbols" do
1983
- @collection.create_index([['a', Mongo::DESCENDING], [:b, Mongo::ASCENDING]])
1984
- assert @collection.index_information['a_-1_b_1']
1985
- @collection.drop_index([['a', Mongo::DESCENDING], [:b, Mongo::ASCENDING]])
1986
- assert_nil @collection.index_information['a_-1_b_1']
1987
- end
1988
- end
1989
-
1990
- context "Creating indexes " do
1991
- setup do
1992
- @db.drop_collection('geo')
1993
- @db.drop_collection('test-collection')
1994
- @collection = @db.collection('test-collection')
1995
- @geo = @db.collection('geo')
1996
- end
1997
-
1998
- should "create index using symbols" do
1999
- @collection.create_index :foo, :name => :bar
2000
- @geo.create_index :goo, :name => :baz
2001
- assert @collection.index_information['bar']
2002
- @collection.drop_index :bar
2003
- assert_nil @collection.index_information['bar']
2004
- assert @geo.index_information['baz']
2005
- @geo.drop_index(:baz)
2006
- assert_nil @geo.index_information['baz']
2007
- end
2008
-
2009
- #should "create a text index" do
2010
- # @geo.save({'title' => "some text"})
2011
- # @geo.create_index([['title', Mongo::TEXT]])
2012
- # assert @geo.index_information['title_text']
2013
- #end
2014
-
2015
- should "create a hashed index" do
2016
- @geo.save({'a' => 1})
2017
- @geo.create_index([['a', Mongo::HASHED]])
2018
- assert @geo.index_information['a_hashed']
2019
- end
2020
-
2021
- should "create a geospatial index" do
2022
- @geo.save({'loc' => [-100, 100]})
2023
- @geo.create_index([['loc', Mongo::GEO2D]])
2024
- assert @geo.index_information['loc_2d']
2025
- end
2026
-
2027
- should "create a geoHaystack index" do
2028
- @geo.save({ "_id" => 100, "pos" => { "long" => 126.9, "lat" => 35.2 }, "type" => "restaurant"})
2029
- @geo.create_index([['pos', Mongo::GEOHAYSTACK], ['type', Mongo::ASCENDING]], :bucket_size => 1)
2030
- assert @geo.index_information['pos_geoHaystack_type_1']
2031
- end
2032
-
2033
- should "create a geo 2dsphere index" do
2034
- @collection.insert({"coordinates" => [ 5 , 5 ], "type" => "Point"})
2035
- @geo.create_index([['coordinates', Mongo::GEO2DSPHERE]])
2036
- assert @geo.index_information['coordinates_2dsphere']
2037
- end
2038
-
2039
- should "create a unique index" do
2040
- @collection.create_index([['a', Mongo::ASCENDING]], :unique => true)
2041
- assert @collection.index_information['a_1']['unique'] == true
2042
- end
2043
-
2044
- should "drop duplicates" do
2045
- if @version < '2.7'
2046
- @collection.insert({:a => 1})
2047
- @collection.insert({:a => 1})
2048
- assert_equal 2, @collection.find({:a => 1}).count
2049
- @collection.create_index([['a', Mongo::ASCENDING]], :unique => true, :dropDups => true)
2050
- assert_equal 1, @collection.find({:a => 1}).count
2051
- end
2052
- end
2053
-
2054
- should "drop duplicates with ruby-like drop_dups key" do
2055
- if @version < '2.7'
2056
- @collection.insert({:a => 1})
2057
- @collection.insert({:a => 1})
2058
- assert_equal 2, @collection.find({:a => 1}).count
2059
- @collection.create_index([['a', Mongo::ASCENDING]], :unique => true, :drop_dups => true)
2060
- assert_equal 1, @collection.find({:a => 1}).count
2061
- end
2062
- end
2063
-
2064
- should "drop duplicates with ensure_index and drop_dups key" do
2065
- if @version < '2.7'
2066
- @collection.insert({:a => 1})
2067
- @collection.insert({:a => 1})
2068
- assert_equal 2, @collection.find({:a => 1}).count
2069
- @collection.ensure_index([['a', Mongo::ASCENDING]], :unique => true, :drop_dups => true)
2070
- assert_equal 1, @collection.find({:a => 1}).count
2071
- end
2072
- end
2073
-
2074
- should "create an index in the background" do
2075
- if @version > '1.3.1'
2076
- @collection.create_index([['b', Mongo::ASCENDING]], :background => true)
2077
- assert @collection.index_information['b_1']['background'] == true
2078
- else
2079
- assert true
2080
- end
2081
- end
2082
-
2083
- should "require an array of arrays" do
2084
- assert_raise MongoArgumentError do
2085
- @collection.create_index(['c', Mongo::ASCENDING])
2086
- end
2087
- end
2088
-
2089
- should "enforce proper index types" do
2090
- assert_raise MongoArgumentError do
2091
- @collection.create_index([['c', 'blah']])
2092
- end
2093
- end
2094
-
2095
- should "raise an error if index name is greater than 128" do
2096
- assert_raise Mongo::OperationFailure do
2097
- @collection.create_index([['a' * 25, 1], ['b' * 25, 1],
2098
- ['c' * 25, 1], ['d' * 25, 1], ['e' * 25, 1]])
2099
- end
2100
- end
2101
-
2102
- should "allow for an alternate name to be specified" do
2103
- @collection.create_index([['a' * 25, 1], ['b' * 25, 1],
2104
- ['c' * 25, 1], ['d' * 25, 1], ['e' * 25, 1]], :name => 'foo_index')
2105
- assert @collection.index_information['foo_index']
2106
- end
2107
-
2108
- should "generate indexes in the proper order" do
2109
- key = BSON::OrderedHash['b', 1, 'a', 1]
2110
- if @version < '2.5.5'
2111
- @collection.expects(:send_write) do |type, selector, documents, check_keys, opts, collection_name|
2112
- assert_equal key, selector[:key]
2113
- end
2114
- else
2115
- @collection.db.expects(:command) do |selector|
2116
- assert_equal key, selector[:indexes].first[:key]
2117
- end
2118
- end
2119
- @collection.create_index([['b', 1], ['a', 1]])
2120
- end
2121
-
2122
- should "allow creation of multiple indexes" do
2123
- assert @collection.create_index([['a', 1]])
2124
- assert @collection.create_index([['a', 1]])
2125
- end
2126
-
2127
- context "with an index created" do
2128
- setup do
2129
- @collection.create_index([['b', 1], ['a', 1]])
2130
- end
2131
-
2132
- should "return properly ordered index information" do
2133
- assert @collection.index_information['b_1_a_1']
2134
- end
2135
- end
2136
- end
2137
-
2138
- context "Capped collections" do
2139
- setup do
2140
- @db.drop_collection('log')
2141
- @capped = @db.create_collection('log', :capped => true, :size => LIMITED_MAX_BSON_SIZE)
2142
-
2143
- 10.times { |n| @capped.insert({:n => n}) }
2144
- end
2145
-
2146
- should "find using a standard cursor" do
2147
- cursor = @capped.find
2148
- 10.times do
2149
- assert cursor.next_document
2150
- end
2151
- assert_nil cursor.next_document
2152
- @capped.insert({:n => 100})
2153
- assert_nil cursor.next_document
2154
- end
2155
-
2156
- should "fail tailable cursor on a non-capped collection" do
2157
- col = @db['regular-collection']
2158
- col.insert({:a => 1000})
2159
- tail = Cursor.new(col, :tailable => true, :order => [['$natural', 1]])
2160
- assert_raise OperationFailure do
2161
- tail.next_document
2162
- end
2163
- end
2164
-
2165
- should "find using a tailable cursor" do
2166
- tail = Cursor.new(@capped, :tailable => true, :order => [['$natural', 1]])
2167
- 10.times do
2168
- assert tail.next_document
2169
- end
2170
- assert_nil tail.next_document
2171
- @capped.insert({:n => 100})
2172
- assert tail.next_document
2173
- end
2174
- end
2175
- end