mongo 1.12.5 → 2.0.0.beta

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (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
@@ -0,0 +1,130 @@
1
+ require 'spec_helper'
2
+
3
+ describe Mongo::Server::Monitor do
4
+
5
+ let(:address) do
6
+ Mongo::Address.new(DEFAULT_ADDRESS)
7
+ end
8
+
9
+ let(:listeners) do
10
+ Mongo::Event::Listeners.new
11
+ end
12
+
13
+ describe '#scan!' do
14
+
15
+ context 'when the ismaster command succeeds' do
16
+
17
+ let(:monitor) do
18
+ described_class.new(address, listeners)
19
+ end
20
+
21
+ before do
22
+ monitor.scan!
23
+ end
24
+
25
+ it 'updates the server description', if: standalone? do
26
+ expect(monitor.description).to be_standalone
27
+ end
28
+
29
+ it 'updates the server description', if: replica_set? do
30
+ expect(monitor.description).to be_primary
31
+ end
32
+
33
+ it 'updates the server description', if: sharded? do
34
+ expect(monitor.description).to be_mongos
35
+ end
36
+ end
37
+
38
+ context 'when the ismaster command fails' do
39
+
40
+ context 'when no server is running on the address' do
41
+
42
+ let(:bad_address) do
43
+ Mongo::Address.new('127.0.0.1:27050')
44
+ end
45
+
46
+ let(:monitor) do
47
+ described_class.new(bad_address, listeners)
48
+ end
49
+
50
+ before do
51
+ monitor.scan!
52
+ end
53
+
54
+ it 'keeps the server unknown' do
55
+ expect(monitor.description).to be_unknown
56
+ end
57
+ end
58
+
59
+ context 'when the socket gets an exception' do
60
+
61
+ let(:bad_address) do
62
+ Mongo::Address.new(DEFAULT_ADDRESS)
63
+ end
64
+
65
+ let(:monitor) do
66
+ described_class.new(bad_address, listeners)
67
+ end
68
+
69
+ let(:socket) do
70
+ monitor.connection.connect!
71
+ monitor.connection.__send__(:socket)
72
+ end
73
+
74
+ before do
75
+ expect(socket).to receive(:write).and_raise(Mongo::Error::SocketError)
76
+ monitor.scan!
77
+ end
78
+
79
+ it 'keeps the server unknown' do
80
+ expect(monitor.description).to be_unknown
81
+ end
82
+
83
+ it 'disconnects the connection' do
84
+ expect(monitor.connection).to_not be_connected
85
+ end
86
+ end
87
+ end
88
+ end
89
+
90
+ describe '#heartbeat_frequency' do
91
+
92
+ context 'when an option is provided' do
93
+
94
+ let(:monitor) do
95
+ described_class.new(address, listeners, :heartbeat_frequency => 5)
96
+ end
97
+
98
+ it 'returns the option' do
99
+ expect(monitor.heartbeat_frequency).to eq(5)
100
+ end
101
+ end
102
+
103
+ context 'when no option is provided' do
104
+
105
+ let(:monitor) do
106
+ described_class.new(address, listeners)
107
+ end
108
+
109
+ it 'defaults to 5' do
110
+ expect(monitor.heartbeat_frequency).to eq(10)
111
+ end
112
+ end
113
+ end
114
+
115
+ describe '#run!' do
116
+
117
+ let(:monitor) do
118
+ described_class.new(address, listeners, :heartbeat_frequency => 1)
119
+ end
120
+
121
+ before do
122
+ monitor.run!
123
+ sleep(1)
124
+ end
125
+
126
+ it 'refreshes the server on the provided interval' do
127
+ expect(monitor.description).to_not be_nil
128
+ end
129
+ end
130
+ end
@@ -0,0 +1,103 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'Server Discovery and Monitoring' do
4
+ include Mongo::SDAM
5
+
6
+ SERVER_DISCOVERY_TESTS.each do |file|
7
+
8
+ spec = Mongo::SDAM::Spec.new(file)
9
+
10
+ context(spec.description) do
11
+
12
+ before(:all) do
13
+
14
+ # We monkey-patch the server here, so the monitors do not run and no
15
+ # real TCP connection is attempted. Thus we can control the server
16
+ # descriptions per-phase.
17
+ #
18
+ # @since 2.0.0
19
+ class Mongo::Server
20
+
21
+ # The contructor keeps the same API, but does not instantiate a
22
+ # monitor and run it.
23
+ def initialize(address, event_listeners, options = {})
24
+ @address = address
25
+ @options = options.freeze
26
+ @monitor = Monitor.new(address, event_listeners, options)
27
+ end
28
+
29
+ # Disconnect simply needs to return true since we have no monitor and
30
+ # no connection.
31
+ def disconnect!; true; end
32
+ end
33
+
34
+ # Client is set as an instance variable inside the scope of the spec to
35
+ # retain its modifications across contexts/phases. Let is no good
36
+ # here as we have a clean slate for each context/phase.
37
+ @client = Mongo::Client.new(spec.uri_string)
38
+ end
39
+
40
+ after(:all) do
41
+
42
+ # Return the server implementation to its original for the other
43
+ # tests in the suite.
44
+ class Mongo::Server
45
+
46
+ # Returns the constructor to its original implementation.
47
+ def initialize(address, event_listeners, options = {})
48
+ @address = address
49
+ @options = options.freeze
50
+ @monitor = Monitor.new(address, event_listeners, options)
51
+ @monitor.scan!
52
+ @monitor.run!
53
+ end
54
+
55
+ # Returns disconnect! to its original implementation.
56
+ def disconnect!
57
+ context.with_connection do |connection|
58
+ connection.disconnect!
59
+ end
60
+ @monitor.stop! and true
61
+ end
62
+ end
63
+ end
64
+
65
+ spec.phases.each_with_index do |phase, index|
66
+
67
+ context("Phase: #{index + 1}") do
68
+
69
+ phase.responses.each do |response|
70
+
71
+ before do
72
+ # For each response in the phase, we need to change that server's
73
+ # description.
74
+ server = find_server(@client, response.address)
75
+ monitor = server.instance_variable_get(:@monitor)
76
+ description = monitor.inspector.run(server.description, response.ismaster, 0.5)
77
+ monitor.instance_variable_set(:@description, description)
78
+ end
79
+ end
80
+
81
+ it "sets the cluster topology to #{phase.outcome.topology_type}" do
82
+ expect(@client.cluster).to be_topology(phase.outcome.topology_type)
83
+ end
84
+
85
+ it "sets the cluster replica set name to #{phase.outcome.set_name.inspect}" do
86
+ expect(@client.cluster.replica_set_name).to eq(phase.outcome.set_name)
87
+ end
88
+
89
+ phase.outcome.servers.each do |uri, server|
90
+
91
+ it "sets #{uri} to #{server['type']}" do
92
+ expect(find_server(@client, uri)).to be_server_type(server['type'])
93
+ end
94
+
95
+ it "sets #{uri} replica set name to #{server['setName'].inspect}" do
96
+ expect(find_server(@client, uri).replica_set_name).to eq(server['setName'])
97
+ end
98
+ end
99
+ end
100
+ end
101
+ end
102
+ end
103
+ end
@@ -0,0 +1,104 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'Server Selection moving average round trip time calculation' do
4
+
5
+ include Mongo::ServerSelection::RTT
6
+
7
+ SERVER_SELECTION_RTT_TESTS.each do |file|
8
+
9
+ spec = Mongo::ServerSelection::RTT::Spec.new(file)
10
+
11
+ before(:all) do
12
+
13
+ module Mongo
14
+ class Server
15
+
16
+ # We monkey-patch the monitor here, so the last average rtt can be controlled.
17
+ # We keep the API of Monitor#initialize but add in an extra option and set the last rtt.
18
+ #
19
+ # @since 2.0.0
20
+ class Monitor
21
+
22
+ def initialize(address, listeners, options = {})
23
+ @description = Mongo::Server::Description.new(address, {})
24
+ @inspector = Mongo::Server::Description::Inspector.new(listeners)
25
+ @options = options.freeze
26
+ @connection = Connection.new(address, options)
27
+ @last_round_trip_time = options[:avg_rtt_ms]
28
+ @mutex = Mutex.new
29
+ end
30
+
31
+ private
32
+
33
+ # We monkey patch this method to use an instance variable instead of calculating time elapsed.
34
+ #
35
+ # @since 2.0.0
36
+ def average_round_trip_time(start)
37
+ new_rtt = @new_rtt_ms
38
+ RTT_WEIGHT_FACTOR * new_rtt + (1 - RTT_WEIGHT_FACTOR) * (@last_round_trip_time || new_rtt)
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
44
+
45
+ after(:all) do
46
+
47
+ module Mongo
48
+ class Server
49
+
50
+ # Return the monitor implementation to its original for the other
51
+ # tests in the suite.
52
+ class Monitor
53
+
54
+ # Create the new server monitor.
55
+ #
56
+ # @example Create the server monitor.
57
+ # Mongo::Server::Monitor.new(address, listeners)
58
+ #
59
+ # @param [ Address ] address The address to monitor.
60
+ # @param [ Event::Listeners ] listeners The event listeners.
61
+ # @param [ Hash ] options The options.
62
+ #
63
+ # @since 2.0.0
64
+ def initialize(address, listeners, options = {})
65
+ @description = Description.new(address, {})
66
+ @inspector = Description::Inspector.new(listeners)
67
+ @options = options.freeze
68
+ @connection = Connection.new(address, options)
69
+ @last_round_trip_time = nil
70
+ @mutex = Mutex.new
71
+ end
72
+
73
+ private
74
+
75
+ def average_round_trip_time(start)
76
+ new_rtt = Time.now - start
77
+ RTT_WEIGHT_FACTOR * new_rtt + (1 - RTT_WEIGHT_FACTOR) * (@last_round_trip_time || new_rtt)
78
+ end
79
+ end
80
+ end
81
+ end
82
+ end
83
+
84
+ context(spec.description) do
85
+
86
+ let(:address) do
87
+ Mongo::Address.new('127.0.0.1:27017')
88
+ end
89
+
90
+ let(:monitor) do
91
+ Mongo::Server::Monitor.new(address, Mongo::Event::Listeners.new, avg_rtt_ms: spec.avg_rtt_ms)
92
+ end
93
+
94
+ before do
95
+ monitor.instance_variable_set(:@new_rtt_ms, spec.new_rtt_ms)
96
+ monitor.scan!
97
+ end
98
+
99
+ it 'correctly calculates the moving average round trip time' do
100
+ expect(monitor.description.average_round_trip_time).to eq(spec.new_avg_rtt)
101
+ end
102
+ end
103
+ end
104
+ end
@@ -0,0 +1,89 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'Server Selection' do
4
+
5
+ include Mongo::ServerSelection::Read
6
+
7
+ SERVER_SELECTION_TESTS.each do |file|
8
+
9
+ spec = Mongo::ServerSelection::Read::Spec.new(file)
10
+
11
+ context(spec.description) do
12
+
13
+ let(:topology) do
14
+ spec.type.new({})
15
+ end
16
+
17
+ let(:cluster) do
18
+ double('cluster').tap do |c|
19
+ allow(c).to receive(:topology).and_return(topology)
20
+ allow(c).to receive(:standalone?).and_return(topology.standalone?)
21
+ allow(c).to receive(:sharded?).and_return(topology.sharded?)
22
+ allow(c).to receive(:replica_set?).and_return(topology.replica_set?)
23
+ end
24
+ end
25
+
26
+ let(:candidate_servers) do
27
+ spec.candidate_servers.collect do |server|
28
+ address = Mongo::Address.new(server['address'])
29
+ Mongo::Server.new(address, Mongo::Event::Listeners.new).tap do |s|
30
+ allow(s).to receive(:average_round_trip_time).and_return(server['avg_rtt_ms'])
31
+ allow(s).to receive(:tags).and_return(server['tag_sets'].first)
32
+ allow(s).to receive(:secondary?).and_return(server['type'] == 'RSSecondary')
33
+ allow(s).to receive(:primary?).and_return(server['type'] == 'RSPrimary')
34
+ end
35
+ end
36
+ end
37
+
38
+ let(:in_latency_window) do
39
+ spec.in_latency_window.collect do |server|
40
+ address = Mongo::Address.new(server['address'])
41
+ Mongo::Server.new(address, Mongo::Event::Listeners.new).tap do |s|
42
+ allow(s).to receive(:average_round_trip_time).and_return(server['avg_rtt_ms'])
43
+ allow(s).to receive(:tags).and_return(server['tag_sets'].first)
44
+ end
45
+ end
46
+ end
47
+
48
+ let(:server_selector) do
49
+ Mongo::ServerSelector.get({ :mode => spec.read_preference['mode'],
50
+ :tag_sets => spec.read_preference['tag_sets'] },
51
+ :server_selection_timeout => 1)
52
+ end
53
+
54
+ before do
55
+ allow(cluster).to receive(:servers).and_return(candidate_servers)
56
+ allow(cluster).to receive(:scan!).and_return(true)
57
+ end
58
+
59
+ context 'Valid read preference and matching server available', unless: spec.raises_exception? do
60
+
61
+ it 'Finds all suitable servers in the latency window', if: spec.replica_set? do
62
+ expect(server_selector.send(:select, cluster.servers)).to eq(in_latency_window)
63
+ end
64
+
65
+ it 'Finds the most suitable server in the latency window' do
66
+ expect(in_latency_window).to include(server_selector.select_server(cluster))
67
+ end
68
+ end
69
+
70
+ context 'Invalid read preference', if: spec.invalid_server_preference? do
71
+
72
+ it 'Raises exception' do
73
+ expect do
74
+ server_selector.select_server(cluster)
75
+ end.to raise_exception(Mongo::ServerSelector::InvalidServerPreference)
76
+ end
77
+ end
78
+
79
+ context 'No matching server available', unless: spec.server_available? do
80
+
81
+ it 'Raises exception' do
82
+ expect do
83
+ server_selector.select_server(cluster)
84
+ end.to raise_exception(Mongo::ServerSelector::NoServerAvailable)
85
+ end
86
+ end
87
+ end
88
+ end
89
+ end
@@ -0,0 +1,250 @@
1
+ require 'spec_helper'
2
+
3
+ describe Mongo::ServerSelector::Nearest do
4
+
5
+ include_context 'server selector'
6
+
7
+ it_behaves_like 'a read preference mode' do
8
+ let(:name) { :nearest }
9
+ let(:slave_ok) { true }
10
+ end
11
+
12
+ it_behaves_like 'a read preference mode accepting tag sets'
13
+
14
+ describe '#to_mongos' do
15
+
16
+ context 'tag set not provided' do
17
+ it 'returns a read preference formatted for mongos' do
18
+ expect(read_pref.to_mongos).to eq({ :mode => 'nearest' })
19
+ end
20
+ end
21
+
22
+ context 'tag set provided' do
23
+ let(:tag_sets) do
24
+ [tag_set]
25
+ end
26
+
27
+ it 'returns a read preference formatted for mongos' do
28
+ expect(read_pref.to_mongos).to eq(
29
+ { :mode => 'nearest', :tags => tag_sets }
30
+ )
31
+ end
32
+ end
33
+ end
34
+
35
+ describe '#select' do
36
+
37
+ context 'no candidates' do
38
+ let(:candidates) { [] }
39
+
40
+ it 'returns an empty array' do
41
+ expect(read_pref.send(:select, candidates)).to be_empty
42
+ end
43
+ end
44
+
45
+ context 'single primary candidates' do
46
+ let(:candidates) { [primary] }
47
+
48
+ it 'returns an array with the primary' do
49
+ expect(read_pref.send(:select, candidates)).to eq([primary])
50
+ end
51
+ end
52
+
53
+ context 'single secondary candidate' do
54
+ let(:candidates) { [secondary] }
55
+
56
+ it 'returns an array with the secondary' do
57
+ expect(read_pref.send(:select, candidates)).to eq([secondary])
58
+ end
59
+ end
60
+
61
+ context 'primary and secondary candidates' do
62
+ let(:candidates) { [primary, secondary] }
63
+
64
+ it 'returns an array with the primary and secondary' do
65
+ expect(read_pref.send(:select, candidates)).to match_array([primary, secondary])
66
+ end
67
+ end
68
+
69
+ context 'multiple secondary candidates' do
70
+ let(:candidates) { [secondary, secondary] }
71
+
72
+ it 'returns an array with the secondaries' do
73
+ expect(read_pref.send(:select, candidates)).to match_array([secondary, secondary])
74
+ end
75
+ end
76
+
77
+ context 'tag sets provided' do
78
+ let(:tag_sets) { [tag_set] }
79
+ let(:matching_primary) do
80
+ server(:primary, :tags => server_tags)
81
+ end
82
+ let(:matching_secondary) do
83
+ server(:secondary, :tags => server_tags)
84
+ end
85
+
86
+ context 'single candidate' do
87
+
88
+ context 'primary' do
89
+ let(:candidates) { [primary] }
90
+
91
+ it 'returns an empty array' do
92
+ expect(read_pref.send(:select, candidates)).to be_empty
93
+ end
94
+ end
95
+
96
+ context 'matching primary' do
97
+ let(:candidates) { [matching_primary] }
98
+
99
+ it 'returns an array with the primary' do
100
+ expect(read_pref.send(:select, candidates)).to eq([matching_primary])
101
+ end
102
+ end
103
+
104
+ context 'secondary' do
105
+ let(:candidates) { [secondary] }
106
+
107
+ it 'returns an empty array' do
108
+ expect(read_pref.send(:select, candidates)).to be_empty
109
+ end
110
+ end
111
+
112
+ context 'matching secondary' do
113
+ let(:candidates) { [matching_secondary] }
114
+
115
+ it 'returns an array with the matching secondary' do
116
+ expect(read_pref.send(:select, candidates)).to eq([matching_secondary])
117
+ end
118
+ end
119
+ end
120
+
121
+ context 'mtuliple candidates' do
122
+
123
+ context 'no matching servers' do
124
+ let(:candidates) { [primary, secondary, secondary] }
125
+
126
+ it 'returns an empty array' do
127
+ expect(read_pref.send(:select, candidates)).to be_empty
128
+ end
129
+ end
130
+
131
+ context 'one matching primary' do
132
+ let(:candidates) { [matching_primary, secondary, secondary] }
133
+
134
+ it 'returns an array with the matching primary' do
135
+ expect(read_pref.send(:select, candidates)).to eq([matching_primary])
136
+ end
137
+ end
138
+
139
+ context 'one matching secondary' do
140
+ let(:candidates) { [primary, matching_secondary, secondary] }
141
+
142
+ it 'returns an array with the matching secondary' do
143
+ expect(read_pref.send(:select, candidates)).to eq([matching_secondary])
144
+ end
145
+ end
146
+
147
+ context 'two matching secondaries' do
148
+ let(:candidates) { [primary, matching_secondary, matching_secondary] }
149
+ let(:expected) { [matching_secondary, matching_secondary] }
150
+
151
+ it 'returns an array with the matching secondaries' do
152
+ expect(read_pref.send(:select, candidates)).to eq(expected)
153
+ end
154
+ end
155
+
156
+ context 'one matching primary and one matching secondary' do
157
+ let(:candidates) { [matching_primary, matching_secondary, secondary] }
158
+ let(:expected) { [matching_primary, matching_secondary] }
159
+
160
+ it 'returns an array with the matching primary and secondary' do
161
+ expect(read_pref.send(:select, candidates)).to match_array(expected)
162
+ end
163
+ end
164
+ end
165
+ end
166
+
167
+ context 'high latency servers' do
168
+ let(:far_primary) { server(:primary, :average_round_trip_time => 113) }
169
+ let(:far_secondary) { server(:secondary, :average_round_trip_time => 114) }
170
+
171
+ context 'single candidate' do
172
+
173
+ context 'far primary' do
174
+ let(:candidates) { [far_primary] }
175
+
176
+ it 'returns array with far primary' do
177
+ expect(read_pref.send(:select, candidates)).to eq([far_primary])
178
+ end
179
+ end
180
+
181
+ context 'far secondary' do
182
+ let(:candidates) { [far_secondary] }
183
+
184
+ it 'returns array with far primary' do
185
+ expect(read_pref.send(:select, candidates)).to eq([far_secondary])
186
+ end
187
+ end
188
+ end
189
+
190
+ context 'multiple candidates' do
191
+
192
+ context 'local primary, local secondary' do
193
+ let(:candidates) { [primary, secondary] }
194
+
195
+ it 'returns array with primary and secondary' do
196
+ expect(read_pref.send(:select, candidates)).to match_array(
197
+ [primary, secondary]
198
+ )
199
+ end
200
+ end
201
+
202
+ context 'local primary, far secondary' do
203
+ let(:candidates) { [primary, far_secondary] }
204
+
205
+ it 'returns array with local primary' do
206
+ expect(read_pref.send(:select, candidates)).to eq([primary])
207
+ end
208
+ end
209
+
210
+ context 'far primary, local secondary' do
211
+ let(:candidates) { [far_primary, secondary] }
212
+
213
+ it 'returns array with local secondary' do
214
+ expect(read_pref.send(:select, candidates)).to eq([secondary])
215
+ end
216
+ end
217
+
218
+ context 'far primary, far secondary' do
219
+ let(:candidates) { [far_primary, far_secondary] }
220
+ let(:expected) { [far_primary, far_secondary] }
221
+
222
+ it 'returns array with both servers' do
223
+ expect(read_pref.send(:select, candidates)).to match_array(expected)
224
+ end
225
+ end
226
+
227
+ context 'two local servers, one far server' do
228
+
229
+ context 'local primary, local secondary' do
230
+ let(:candidates) { [primary, secondary, far_secondary] }
231
+ let(:expected) { [primary, secondary] }
232
+
233
+ it 'returns array with local primary and local secondary' do
234
+ expect(read_pref.send(:select, candidates)).to match_array(expected)
235
+ end
236
+ end
237
+
238
+ context 'two near secondaries' do
239
+ let(:candidates) { [far_primary, secondary, secondary] }
240
+ let(:expected) { [secondary, secondary] }
241
+
242
+ it 'returns array with the two local secondaries' do
243
+ expect(read_pref.send(:select, candidates)).to match_array(expected)
244
+ end
245
+ end
246
+ end
247
+ end
248
+ end
249
+ end
250
+ end