mongo 1.12.5 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (475) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/CONTRIBUTING.md +64 -0
  4. data/LICENSE +1 -1
  5. data/README.md +21 -126
  6. data/Rakefile +39 -21
  7. data/bin/mongo_console +6 -38
  8. data/lib/mongo/address/ipv4.rb +85 -0
  9. data/lib/mongo/address/ipv6.rb +85 -0
  10. data/lib/mongo/address/unix.rb +76 -0
  11. data/lib/mongo/address.rb +111 -0
  12. data/lib/mongo/auth/cr/conversation.rb +119 -0
  13. data/lib/mongo/auth/cr.rb +44 -0
  14. data/lib/mongo/auth/executable.rb +52 -0
  15. data/lib/mongo/auth/ldap/conversation.rb +92 -0
  16. data/lib/mongo/auth/ldap.rb +48 -0
  17. data/lib/mongo/auth/roles.rb +104 -0
  18. data/lib/mongo/auth/scram/conversation.rb +450 -0
  19. data/lib/mongo/auth/scram.rb +53 -0
  20. data/lib/mongo/auth/user/view.rb +102 -0
  21. data/lib/mongo/auth/user.rb +159 -0
  22. data/lib/mongo/auth/x509/conversation.rb +92 -0
  23. data/lib/mongo/auth/x509.rb +48 -0
  24. data/lib/mongo/auth.rb +108 -0
  25. data/lib/mongo/bulk_write/bulk_writable.rb +191 -0
  26. data/lib/mongo/bulk_write/deletable.rb +60 -0
  27. data/lib/mongo/bulk_write/insertable.rb +52 -0
  28. data/lib/mongo/bulk_write/ordered_bulk_write.rb +48 -0
  29. data/lib/mongo/bulk_write/replacable.rb +57 -0
  30. data/lib/mongo/bulk_write/unordered_bulk_write.rb +46 -0
  31. data/lib/mongo/bulk_write/updatable.rb +68 -0
  32. data/lib/mongo/bulk_write.rb +52 -0
  33. data/lib/mongo/client.rb +246 -0
  34. data/lib/mongo/cluster/topology/replica_set.rb +160 -0
  35. data/lib/mongo/cluster/topology/sharded.rb +132 -0
  36. data/lib/mongo/cluster/topology/standalone.rb +132 -0
  37. data/lib/mongo/cluster/topology/unknown.rb +155 -0
  38. data/lib/mongo/cluster/topology.rb +60 -0
  39. data/lib/mongo/cluster.rb +203 -0
  40. data/lib/mongo/collection/view/aggregation.rb +108 -0
  41. data/lib/mongo/collection/view/explainable.rb +49 -0
  42. data/lib/mongo/collection/view/immutable.rb +43 -0
  43. data/lib/mongo/collection/view/iterable.rb +48 -0
  44. data/lib/mongo/collection/view/map_reduce.rb +191 -0
  45. data/lib/mongo/collection/view/readable.rb +363 -0
  46. data/lib/mongo/collection/view/writable.rb +185 -0
  47. data/lib/mongo/collection/view.rb +169 -0
  48. data/lib/mongo/collection.rb +130 -1101
  49. data/lib/mongo/cursor.rb +78 -681
  50. data/lib/mongo/database/view.rb +101 -0
  51. data/lib/mongo/database.rb +224 -0
  52. data/lib/mongo/error/bulk_write_error.rb +41 -0
  53. data/lib/mongo/error/invalid_bulk_operation.rb +36 -0
  54. data/lib/mongo/error/invalid_bulk_operation_type.rb +36 -0
  55. data/lib/mongo/error/invalid_collection_name.rb +39 -0
  56. data/lib/mongo/error/invalid_database_name.rb +39 -0
  57. data/{test/replica_set/ssl_test.rb → lib/mongo/error/invalid_document.rb} +21 -14
  58. data/lib/mongo/error/invalid_file.rb +38 -0
  59. data/lib/mongo/error/invalid_nonce.rb +46 -0
  60. data/lib/mongo/error/invalid_replacement_document.rb +39 -0
  61. data/lib/mongo/error/invalid_signature.rb +47 -0
  62. data/{test/functional/ssl_test.rb → lib/mongo/error/invalid_update_document.rb} +22 -12
  63. data/lib/mongo/error/max_bson_size.rb +40 -0
  64. data/lib/mongo/error/max_message_size.rb +42 -0
  65. data/{test/functional/db_connection_test.rb → lib/mongo/error/multi_index_drop.rb} +17 -8
  66. data/lib/mongo/{utils.rb → error/need_primary_server.rb} +10 -6
  67. data/lib/mongo/{connection.rb → error/operation_failure.rb} +10 -6
  68. data/lib/mongo/error/parser.rb +77 -0
  69. data/lib/mongo/{connection/socket.rb → error/socket_error.rb} +10 -5
  70. data/lib/mongo/error/socket_timeout_error.rb +23 -0
  71. data/lib/mongo/error/unsupported_features.rb +43 -0
  72. data/lib/mongo/error.rb +82 -0
  73. data/lib/mongo/event/listeners.rb +63 -0
  74. data/lib/mongo/event/primary_elected.rb +53 -0
  75. data/lib/mongo/event/publisher.rb +42 -0
  76. data/lib/mongo/event/server_added.rb +53 -0
  77. data/lib/mongo/event/server_removed.rb +53 -0
  78. data/lib/mongo/event/subscriber.rb +41 -0
  79. data/lib/mongo/event.rb +40 -0
  80. data/lib/mongo/grid/file/chunk.rb +184 -0
  81. data/lib/mongo/grid/file/metadata.rb +229 -0
  82. data/lib/mongo/grid/file.rb +106 -0
  83. data/lib/mongo/grid/fs.rb +149 -0
  84. data/lib/mongo/{gridfs.rb → grid.rb} +3 -5
  85. data/lib/mongo/index/view.rb +261 -0
  86. data/lib/mongo/index.rb +64 -0
  87. data/lib/mongo/loggable.rb +126 -0
  88. data/lib/mongo/logger.rb +132 -0
  89. data/lib/mongo/operation/aggregate/result.rb +88 -0
  90. data/lib/mongo/operation/aggregate.rb +100 -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 +114 -0
  96. data/lib/mongo/operation/list_indexes/result.rb +118 -0
  97. data/lib/mongo/operation/map_reduce/result.rb +122 -0
  98. data/lib/mongo/operation/map_reduce.rb +96 -0
  99. data/lib/mongo/operation/read/collections_info.rb +67 -0
  100. data/lib/mongo/operation/read/get_more.rb +71 -0
  101. data/lib/mongo/operation/read/indexes.rb +68 -0
  102. data/lib/mongo/operation/read/list_collections.rb +75 -0
  103. data/lib/mongo/operation/read/list_indexes.rb +77 -0
  104. data/lib/mongo/operation/read/query.rb +71 -0
  105. data/lib/mongo/{functional.rb → operation/read.rb} +7 -7
  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 +397 -0
  109. data/lib/mongo/operation/write/bulk/bulk_delete/result.rb +75 -0
  110. data/lib/mongo/operation/write/bulk/bulk_delete.rb +144 -0
  111. data/lib/mongo/operation/write/bulk/bulk_insert/result.rb +68 -0
  112. data/lib/mongo/operation/write/bulk/bulk_insert.rb +129 -0
  113. data/lib/mongo/operation/write/bulk/bulk_mergable.rb +67 -0
  114. data/lib/mongo/operation/write/bulk/bulk_update/result.rb +162 -0
  115. data/lib/mongo/operation/write/bulk/bulk_update.rb +153 -0
  116. data/lib/mongo/operation/write/bulk/legacy_bulk_mergable.rb +83 -0
  117. data/lib/mongo/operation/write/bulk.rb +17 -0
  118. data/lib/mongo/operation/write/command/create_index.rb +50 -0
  119. data/lib/mongo/operation/write/command/create_user.rb +43 -0
  120. data/lib/mongo/operation/write/command/delete.rb +56 -0
  121. data/lib/mongo/operation/write/command/drop_index.rb +51 -0
  122. data/lib/mongo/operation/write/command/insert.rb +55 -0
  123. data/lib/mongo/operation/write/command/remove_user.rb +42 -0
  124. data/lib/mongo/operation/write/command/update.rb +60 -0
  125. data/lib/mongo/operation/write/command/writable.rb +61 -0
  126. data/lib/mongo/operation/write/command.rb +22 -0
  127. data/lib/mongo/operation/write/create_index.rb +89 -0
  128. data/lib/mongo/operation/write/create_user.rb +75 -0
  129. data/lib/mongo/operation/write/delete/result.rb +40 -0
  130. data/lib/mongo/operation/write/delete.rb +93 -0
  131. data/lib/mongo/operation/write/drop_index.rb +62 -0
  132. data/lib/mongo/{utils/thread_local_variable_manager.rb → operation/write/insert/result.rb} +15 -8
  133. data/lib/mongo/operation/write/insert.rb +90 -0
  134. data/lib/mongo/operation/write/remove_user.rb +70 -0
  135. data/lib/mongo/operation/write/update/result.rb +160 -0
  136. data/lib/mongo/operation/write/update.rb +103 -0
  137. data/lib/mongo/{connection/socket/socket_util.rb → operation/write.rb} +10 -24
  138. data/lib/mongo/operation.rb +25 -0
  139. data/lib/mongo/options/mapper.rb +78 -0
  140. data/lib/mongo/options.rb +15 -0
  141. data/lib/mongo/protocol/bit_vector.rb +61 -0
  142. data/lib/mongo/protocol/delete.rb +94 -0
  143. data/lib/mongo/protocol/get_more.rb +99 -0
  144. data/lib/mongo/protocol/insert.rb +99 -0
  145. data/lib/mongo/protocol/kill_cursors.rb +74 -0
  146. data/lib/mongo/protocol/message.rb +252 -0
  147. data/lib/mongo/protocol/query.rb +147 -0
  148. data/lib/mongo/protocol/reply.rb +72 -0
  149. data/lib/mongo/protocol/serializers.rb +180 -0
  150. data/lib/mongo/protocol/update.rb +111 -0
  151. data/lib/mongo/protocol.rb +15 -0
  152. data/lib/mongo/server/connectable.rb +110 -0
  153. data/lib/mongo/server/connection.rb +134 -0
  154. data/lib/mongo/server/connection_pool/queue.rb +182 -0
  155. data/lib/mongo/server/connection_pool.rb +141 -0
  156. data/lib/mongo/server/context.rb +66 -0
  157. data/lib/mongo/server/description/features.rb +85 -0
  158. data/lib/mongo/server/description/inspector/primary_elected.rb +58 -0
  159. data/lib/mongo/server/description/inspector/server_added.rb +59 -0
  160. data/lib/mongo/server/description/inspector/server_removed.rb +59 -0
  161. data/lib/mongo/server/description/inspector.rb +79 -0
  162. data/lib/mongo/server/description.rb +450 -0
  163. data/lib/mongo/server/monitor/connection.rb +89 -0
  164. data/lib/mongo/server/monitor.rb +176 -0
  165. data/lib/mongo/server.rb +163 -0
  166. data/lib/mongo/server_selector/nearest.rb +94 -0
  167. data/lib/mongo/server_selector/primary.rb +88 -0
  168. data/lib/mongo/server_selector/primary_preferred.rb +94 -0
  169. data/lib/mongo/server_selector/secondary.rb +91 -0
  170. data/lib/mongo/server_selector/secondary_preferred.rb +96 -0
  171. data/lib/mongo/server_selector/selectable.rb +209 -0
  172. data/lib/mongo/server_selector.rb +81 -0
  173. data/lib/mongo/socket/ssl.rb +130 -0
  174. data/lib/mongo/socket/tcp.rb +69 -0
  175. data/lib/mongo/socket/unix.rb +64 -0
  176. data/lib/mongo/socket.rb +179 -0
  177. data/lib/mongo/uri.rb +504 -0
  178. data/lib/mongo/version.rb +21 -0
  179. data/lib/mongo/write_concern/acknowledged.rb +52 -0
  180. data/lib/mongo/write_concern/normalizable.rb +51 -0
  181. data/lib/mongo/write_concern/unacknowledged.rb +55 -0
  182. data/lib/mongo/write_concern.rb +99 -0
  183. data/lib/mongo.rb +24 -82
  184. data/mongo.gemspec +17 -14
  185. data/spec/certificates/ca.pem +17 -0
  186. data/spec/certificates/client.pem +101 -0
  187. data/spec/certificates/crl.pem +10 -0
  188. data/spec/certificates/crl_client_revoked.pem +12 -0
  189. data/spec/certificates/password_protected.pem +51 -0
  190. data/spec/certificates/server.pem +34 -0
  191. data/spec/mongo/address/ipv4_spec.rb +74 -0
  192. data/spec/mongo/address/ipv6_spec.rb +74 -0
  193. data/spec/mongo/address/unix_spec.rb +30 -0
  194. data/spec/mongo/address_spec.rb +206 -0
  195. data/spec/mongo/auth/cr_spec.rb +59 -0
  196. data/spec/mongo/auth/ldap_spec.rb +40 -0
  197. data/spec/mongo/auth/scram/conversation_spec.rb +197 -0
  198. data/spec/mongo/auth/scram_spec.rb +55 -0
  199. data/spec/mongo/auth/user/view_spec.rb +76 -0
  200. data/spec/mongo/auth/user_spec.rb +190 -0
  201. data/spec/mongo/auth/x509_spec.rb +40 -0
  202. data/spec/mongo/auth_spec.rb +65 -0
  203. data/spec/mongo/bulk/bulk_write_spec.rb +262 -0
  204. data/spec/mongo/client_spec.rb +564 -0
  205. data/spec/mongo/cluster/topology/replica_set_spec.rb +101 -0
  206. data/spec/mongo/cluster/topology/sharded_spec.rb +74 -0
  207. data/spec/mongo/cluster/topology/standalone_spec.rb +79 -0
  208. data/spec/mongo/cluster/topology_spec.rb +65 -0
  209. data/spec/mongo/cluster_spec.rb +129 -0
  210. data/spec/mongo/collection/view/aggregation_spec.rb +148 -0
  211. data/spec/mongo/collection/view/explainable_spec.rb +32 -0
  212. data/spec/mongo/collection/view/map_reduce_spec.rb +242 -0
  213. data/spec/mongo/collection/view/readable_spec.rb +603 -0
  214. data/spec/mongo/collection/view/writable_spec.rb +679 -0
  215. data/spec/mongo/collection/view_spec.rb +530 -0
  216. data/spec/mongo/collection_spec.rb +362 -0
  217. data/spec/mongo/crud_spec.rb +42 -0
  218. data/spec/mongo/cursor_spec.rb +295 -0
  219. data/spec/mongo/database_spec.rb +302 -0
  220. data/spec/mongo/error/parser_spec.rb +119 -0
  221. data/spec/mongo/event/publisher_spec.rb +50 -0
  222. data/spec/mongo/event/subscriber_spec.rb +34 -0
  223. data/spec/mongo/grid/file/chunk_spec.rb +226 -0
  224. data/spec/mongo/grid/file/metadata_spec.rb +92 -0
  225. data/spec/mongo/grid/file_spec.rb +172 -0
  226. data/spec/mongo/grid/fs_spec.rb +129 -0
  227. data/spec/mongo/index/view_spec.rb +330 -0
  228. data/spec/mongo/loggable_spec.rb +62 -0
  229. data/spec/mongo/logger_spec.rb +97 -0
  230. data/spec/mongo/operation/aggregate/result_spec.rb +80 -0
  231. data/spec/mongo/operation/aggregate_spec.rb +127 -0
  232. data/spec/mongo/operation/command_spec.rb +98 -0
  233. data/spec/mongo/operation/kill_cursors_spec.rb +66 -0
  234. data/spec/mongo/operation/limited_spec.rb +50 -0
  235. data/spec/mongo/operation/map_reduce_spec.rb +143 -0
  236. data/spec/mongo/operation/read/collections_info_spec.rb +40 -0
  237. data/spec/mongo/operation/read/get_more_spec.rb +81 -0
  238. data/spec/mongo/operation/read/indexes_spec.rb +31 -0
  239. data/spec/mongo/operation/read/query_spec.rb +84 -0
  240. data/spec/mongo/operation/result_spec.rb +275 -0
  241. data/spec/mongo/operation/specifiable_spec.rb +53 -0
  242. data/spec/mongo/operation/write/bulk_delete_spec.rb +235 -0
  243. data/spec/mongo/operation/write/bulk_insert_spec.rb +235 -0
  244. data/spec/mongo/operation/write/bulk_update_spec.rb +236 -0
  245. data/spec/mongo/operation/write/command/delete_spec.rb +103 -0
  246. data/spec/mongo/operation/write/command/insert_spec.rb +103 -0
  247. data/spec/mongo/operation/write/command/update_spec.rb +109 -0
  248. data/spec/mongo/operation/write/create_index_spec.rb +63 -0
  249. data/spec/mongo/operation/write/create_user_spec.rb +44 -0
  250. data/spec/mongo/operation/write/delete_spec.rb +186 -0
  251. data/spec/mongo/operation/write/drop_index_spec.rb +51 -0
  252. data/spec/mongo/operation/write/insert_spec.rb +244 -0
  253. data/spec/mongo/operation/write/remove_user_spec.rb +46 -0
  254. data/spec/mongo/operation/write/response_spec.rb +85 -0
  255. data/spec/mongo/operation/write/update_spec.rb +228 -0
  256. data/spec/mongo/protocol/delete_spec.rb +167 -0
  257. data/spec/mongo/protocol/get_more_spec.rb +146 -0
  258. data/spec/mongo/protocol/insert_spec.rb +161 -0
  259. data/spec/mongo/protocol/kill_cursors_spec.rb +101 -0
  260. data/spec/mongo/protocol/query_spec.rb +285 -0
  261. data/spec/mongo/protocol/reply_spec.rb +157 -0
  262. data/spec/mongo/protocol/update_spec.rb +186 -0
  263. data/spec/mongo/server/connection_pool/queue_spec.rb +170 -0
  264. data/spec/mongo/server/connection_pool_spec.rb +120 -0
  265. data/spec/mongo/server/connection_spec.rb +312 -0
  266. data/spec/mongo/server/description/features_spec.rb +138 -0
  267. data/spec/mongo/server/description/inspector/primary_elected_spec.rb +94 -0
  268. data/spec/mongo/server/description/inspector/server_added_spec.rb +92 -0
  269. data/spec/mongo/server/description/inspector/server_removed_spec.rb +95 -0
  270. data/spec/mongo/server/description_spec.rb +510 -0
  271. data/spec/mongo/server/monitor_spec.rb +144 -0
  272. data/spec/mongo/server_discovery_and_monitoring_spec.rb +103 -0
  273. data/spec/mongo/server_selection_rtt_spec.rb +104 -0
  274. data/spec/mongo/server_selection_spec.rb +89 -0
  275. data/spec/mongo/server_selector/nearest_spec.rb +250 -0
  276. data/spec/mongo/server_selector/primary_preferred_spec.rb +290 -0
  277. data/spec/mongo/server_selector/primary_spec.rb +114 -0
  278. data/spec/mongo/server_selector/secondary_preferred_spec.rb +252 -0
  279. data/spec/mongo/server_selector/secondary_spec.rb +196 -0
  280. data/spec/mongo/server_selector_spec.rb +101 -0
  281. data/spec/mongo/server_spec.rb +131 -0
  282. data/spec/mongo/uri_spec.rb +517 -0
  283. data/spec/mongo/write_concern/acknowledged_spec.rb +44 -0
  284. data/spec/mongo/write_concern/unacknowledged_spec.rb +15 -0
  285. data/spec/spec_helper.rb +133 -0
  286. data/spec/support/authorization.rb +247 -0
  287. data/spec/support/crud/read.rb +144 -0
  288. data/spec/support/crud/write.rb +214 -0
  289. data/spec/support/crud.rb +203 -0
  290. data/spec/support/crud_tests/read/aggregate.yml +43 -0
  291. data/spec/support/crud_tests/read/count.yml +37 -0
  292. data/spec/support/crud_tests/read/distinct.yml +33 -0
  293. data/spec/support/crud_tests/read/find.yml +50 -0
  294. data/spec/support/crud_tests/write/deleteMany.yml +36 -0
  295. data/spec/support/crud_tests/write/deleteOne.yml +49 -0
  296. data/spec/support/crud_tests/write/findOneAndDelete.yml +54 -0
  297. data/spec/support/crud_tests/write/findOneAndReplace.yml +153 -0
  298. data/spec/support/crud_tests/write/findOneAndUpdate.yml +161 -0
  299. data/spec/support/crud_tests/write/insertMany.yml +24 -0
  300. data/spec/support/crud_tests/write/insertOne.yml +19 -0
  301. data/spec/support/crud_tests/write/replaceOne.yml +96 -0
  302. data/spec/support/crud_tests/write/updateMany.yml +83 -0
  303. data/spec/support/crud_tests/write/updateOne.yml +80 -0
  304. data/spec/support/helpers.rb +140 -0
  305. data/spec/support/matchers.rb +37 -0
  306. data/spec/support/sdam/rs/discover_arbiters.yml +41 -0
  307. data/spec/support/sdam/rs/discover_passives.yml +41 -0
  308. data/spec/support/sdam/rs/discover_primary.yml +40 -0
  309. data/spec/support/sdam/rs/discover_secondary.yml +41 -0
  310. data/spec/support/sdam/rs/discovery.yml +195 -0
  311. data/spec/support/sdam/rs/ghost_discovered.yml +39 -0
  312. data/spec/support/sdam/rs/hosts_differ_from_seeds.yml +34 -0
  313. data/spec/support/sdam/rs/member_reconfig.yml +68 -0
  314. data/spec/support/sdam/rs/member_standalone.yml +60 -0
  315. data/spec/support/sdam/rs/new_primary.yml +74 -0
  316. data/spec/support/sdam/rs/new_primary_wrong_set_name.yml +71 -0
  317. data/spec/support/sdam/rs/non_rs_member.yml +31 -0
  318. data/spec/support/sdam/rs/normalize_case.yml +49 -0
  319. data/spec/support/sdam/rs/primary_becomes_standalone.yml +52 -0
  320. data/spec/support/sdam/rs/primary_changes_set_name.yml +57 -0
  321. data/spec/support/sdam/rs/primary_disconnect.yml +56 -0
  322. data/spec/support/sdam/rs/primary_wrong_set_name.yml +27 -0
  323. data/spec/support/sdam/rs/response_from_removed.yml +63 -0
  324. data/spec/support/sdam/rs/rsother_discovered.yml +41 -0
  325. data/spec/support/sdam/rs/sec_not_auth.yml +49 -0
  326. data/spec/support/sdam/rs/secondary_wrong_set_name.yml +28 -0
  327. data/spec/support/sdam/rs/secondary_wrong_set_name_with_primary.yml +69 -0
  328. data/spec/support/sdam/rs/unexpected_mongos.yml +26 -0
  329. data/spec/support/sdam/rs/wrong_set_name.yml +35 -0
  330. data/spec/support/sdam/sharded/multiple_mongoses.yml +46 -0
  331. data/spec/support/sdam/sharded/non_mongos_removed.yml +41 -0
  332. data/spec/support/sdam/sharded/normalize_uri_case.yml +32 -0
  333. data/spec/support/sdam/single/direct_connection_external_ip.yml +34 -0
  334. data/spec/support/sdam/single/direct_connection_mongos.yml +33 -0
  335. data/spec/support/sdam/single/direct_connection_rsarbiter.yml +35 -0
  336. data/spec/support/sdam/single/direct_connection_rsprimary.yml +34 -0
  337. data/spec/support/sdam/single/direct_connection_rssecondary.yml +35 -0
  338. data/spec/support/sdam/single/direct_connection_slave.yml +32 -0
  339. data/spec/support/sdam/single/direct_connection_standalone.yml +32 -0
  340. data/spec/support/sdam/single/not_ok_response.yml +39 -0
  341. data/spec/support/sdam/single/standalone_removed.yml +32 -0
  342. data/spec/support/sdam/single/unavailable_seed.yml +28 -0
  343. data/spec/support/server_discovery_and_monitoring.rb +167 -0
  344. data/spec/support/server_selection/rtt/first_value.yml +4 -0
  345. data/spec/support/server_selection/rtt/first_value_zero.yml +4 -0
  346. data/spec/support/server_selection/rtt/value_test_1.yml +4 -0
  347. data/spec/support/server_selection/rtt/value_test_2.yml +4 -0
  348. data/spec/support/server_selection/rtt/value_test_3.yml +4 -0
  349. data/spec/support/server_selection/rtt/value_test_4.yml +4 -0
  350. data/spec/support/server_selection/rtt/value_test_5.yml +4 -0
  351. data/spec/support/server_selection/selection/ReplicaSetNoPrimary/read/Nearest.yml +26 -0
  352. data/spec/support/server_selection/selection/ReplicaSetNoPrimary/read/Nearest_non_matching.yml +21 -0
  353. data/spec/support/server_selection/selection/ReplicaSetNoPrimary/read/Primary.yml +21 -0
  354. data/spec/support/server_selection/selection/ReplicaSetNoPrimary/read/PrimaryPreferred.yml +26 -0
  355. data/spec/support/server_selection/selection/ReplicaSetNoPrimary/read/PrimaryPreferred_non_matching.yml +21 -0
  356. data/spec/support/server_selection/selection/ReplicaSetNoPrimary/read/Secondary.yml +26 -0
  357. data/spec/support/server_selection/selection/ReplicaSetNoPrimary/read/SecondaryPreferred.yml +26 -0
  358. data/spec/support/server_selection/selection/ReplicaSetNoPrimary/read/SecondaryPreferred_non_matching.yml +21 -0
  359. data/spec/support/server_selection/selection/ReplicaSetNoPrimary/read/Secondary_non_matching.yml +21 -0
  360. data/spec/support/server_selection/selection/ReplicaSetWithPrimary/read/Nearest.yml +33 -0
  361. data/spec/support/server_selection/selection/ReplicaSetWithPrimary/read/Nearest_non_matching.yml +26 -0
  362. data/spec/support/server_selection/selection/ReplicaSetWithPrimary/read/Primary.yml +29 -0
  363. data/spec/support/server_selection/selection/ReplicaSetWithPrimary/read/PrimaryPreferred.yml +29 -0
  364. data/spec/support/server_selection/selection/ReplicaSetWithPrimary/read/PrimaryPreferred_non_matching.yml +29 -0
  365. data/spec/support/server_selection/selection/ReplicaSetWithPrimary/read/Secondary.yml +31 -0
  366. data/spec/support/server_selection/selection/ReplicaSetWithPrimary/read/SecondaryPreferred.yml +31 -0
  367. data/spec/support/server_selection/selection/ReplicaSetWithPrimary/read/SecondaryPreferred_non_matching.yml +29 -0
  368. data/spec/support/server_selection/selection/ReplicaSetWithPrimary/read/Secondary_non_matching.yml +26 -0
  369. data/spec/support/server_selection/selection/Sharded/read/SecondaryPreferred.yml +26 -0
  370. data/spec/support/server_selection/selection/Single/read/SecondaryPreferred.yml +19 -0
  371. data/spec/support/server_selection/selection/Unknown/read/SecondaryPreferred.yml +11 -0
  372. data/spec/support/server_selection.rb +157 -0
  373. data/spec/support/server_selection_rtt.rb +41 -0
  374. data/spec/support/shared/bulk_write.rb +535 -0
  375. data/spec/support/shared/cursor.rb +38 -0
  376. data/spec/support/shared/operation.rb +77 -0
  377. data/spec/support/shared/protocol.rb +31 -0
  378. data/spec/support/shared/server_selector.rb +111 -0
  379. data/spec/support/shared/socket.rb +82 -0
  380. data/spec/support/travis.rb +14 -0
  381. data.tar.gz.sig +2 -3
  382. metadata +583 -186
  383. metadata.gz.sig +0 -0
  384. data/VERSION +0 -1
  385. data/lib/mongo/bulk_write_collection_view.rb +0 -387
  386. data/lib/mongo/collection_writer.rb +0 -364
  387. data/lib/mongo/connection/node.rb +0 -249
  388. data/lib/mongo/connection/pool.rb +0 -340
  389. data/lib/mongo/connection/pool_manager.rb +0 -320
  390. data/lib/mongo/connection/sharding_pool_manager.rb +0 -67
  391. data/lib/mongo/connection/socket/ssl_socket.rb +0 -95
  392. data/lib/mongo/connection/socket/tcp_socket.rb +0 -87
  393. data/lib/mongo/connection/socket/unix_socket.rb +0 -39
  394. data/lib/mongo/db.rb +0 -808
  395. data/lib/mongo/exception.rb +0 -145
  396. data/lib/mongo/functional/authentication.rb +0 -455
  397. data/lib/mongo/functional/logging.rb +0 -85
  398. data/lib/mongo/functional/read_preference.rb +0 -183
  399. data/lib/mongo/functional/scram.rb +0 -556
  400. data/lib/mongo/functional/uri_parser.rb +0 -409
  401. data/lib/mongo/functional/write_concern.rb +0 -66
  402. data/lib/mongo/gridfs/grid.rb +0 -112
  403. data/lib/mongo/gridfs/grid_ext.rb +0 -53
  404. data/lib/mongo/gridfs/grid_file_system.rb +0 -163
  405. data/lib/mongo/gridfs/grid_io.rb +0 -484
  406. data/lib/mongo/legacy.rb +0 -140
  407. data/lib/mongo/mongo_client.rb +0 -697
  408. data/lib/mongo/mongo_replica_set_client.rb +0 -535
  409. data/lib/mongo/mongo_sharded_client.rb +0 -159
  410. data/lib/mongo/networking.rb +0 -372
  411. data/lib/mongo/utils/conversions.rb +0 -110
  412. data/lib/mongo/utils/core_ext.rb +0 -70
  413. data/lib/mongo/utils/server_version.rb +0 -69
  414. data/lib/mongo/utils/support.rb +0 -80
  415. data/test/functional/authentication_test.rb +0 -39
  416. data/test/functional/bulk_api_stress_test.rb +0 -133
  417. data/test/functional/bulk_write_collection_view_test.rb +0 -1198
  418. data/test/functional/client_test.rb +0 -627
  419. data/test/functional/collection_test.rb +0 -2175
  420. data/test/functional/collection_writer_test.rb +0 -83
  421. data/test/functional/conversions_test.rb +0 -163
  422. data/test/functional/cursor_fail_test.rb +0 -57
  423. data/test/functional/cursor_message_test.rb +0 -56
  424. data/test/functional/cursor_test.rb +0 -683
  425. data/test/functional/db_api_test.rb +0 -835
  426. data/test/functional/db_test.rb +0 -348
  427. data/test/functional/grid_file_system_test.rb +0 -285
  428. data/test/functional/grid_io_test.rb +0 -252
  429. data/test/functional/grid_test.rb +0 -273
  430. data/test/functional/pool_test.rb +0 -136
  431. data/test/functional/safe_test.rb +0 -98
  432. data/test/functional/support_test.rb +0 -62
  433. data/test/functional/timeout_test.rb +0 -60
  434. data/test/functional/uri_test.rb +0 -446
  435. data/test/functional/write_concern_test.rb +0 -118
  436. data/test/helpers/general.rb +0 -50
  437. data/test/helpers/test_unit.rb +0 -476
  438. data/test/replica_set/authentication_test.rb +0 -37
  439. data/test/replica_set/basic_test.rb +0 -189
  440. data/test/replica_set/client_test.rb +0 -393
  441. data/test/replica_set/connection_test.rb +0 -138
  442. data/test/replica_set/count_test.rb +0 -66
  443. data/test/replica_set/cursor_test.rb +0 -220
  444. data/test/replica_set/insert_test.rb +0 -157
  445. data/test/replica_set/max_values_test.rb +0 -151
  446. data/test/replica_set/pinning_test.rb +0 -105
  447. data/test/replica_set/query_test.rb +0 -73
  448. data/test/replica_set/read_preference_test.rb +0 -219
  449. data/test/replica_set/refresh_test.rb +0 -211
  450. data/test/replica_set/replication_ack_test.rb +0 -95
  451. data/test/sharded_cluster/basic_test.rb +0 -203
  452. data/test/shared/authentication/basic_auth_shared.rb +0 -260
  453. data/test/shared/authentication/bulk_api_auth_shared.rb +0 -249
  454. data/test/shared/authentication/gssapi_shared.rb +0 -176
  455. data/test/shared/authentication/sasl_plain_shared.rb +0 -96
  456. data/test/shared/authentication/scram_shared.rb +0 -92
  457. data/test/shared/ssl_shared.rb +0 -235
  458. data/test/test_helper.rb +0 -61
  459. data/test/threading/basic_test.rb +0 -120
  460. data/test/tools/mongo_config.rb +0 -708
  461. data/test/tools/mongo_config_test.rb +0 -160
  462. data/test/unit/client_test.rb +0 -381
  463. data/test/unit/collection_test.rb +0 -166
  464. data/test/unit/connection_test.rb +0 -335
  465. data/test/unit/cursor_test.rb +0 -307
  466. data/test/unit/db_test.rb +0 -136
  467. data/test/unit/grid_test.rb +0 -76
  468. data/test/unit/mongo_sharded_client_test.rb +0 -48
  469. data/test/unit/node_test.rb +0 -93
  470. data/test/unit/pool_manager_test.rb +0 -111
  471. data/test/unit/read_pref_test.rb +0 -406
  472. data/test/unit/read_test.rb +0 -159
  473. data/test/unit/safe_test.rb +0 -158
  474. data/test/unit/sharding_pool_manager_test.rb +0 -84
  475. data/test/unit/write_concern_test.rb +0 -175
@@ -0,0 +1,144 @@
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 calling multiple times in succession' do
16
+
17
+ let(:monitor) do
18
+ described_class.new(address, listeners)
19
+ end
20
+
21
+ it 'throttles the scans to minimum 500ms' do
22
+ start = Time.now
23
+ monitor.scan!
24
+ monitor.scan!
25
+ expect(Time.now - start).to be > 0.5
26
+ end
27
+ end
28
+
29
+ context 'when the ismaster command succeeds' do
30
+
31
+ let(:monitor) do
32
+ described_class.new(address, listeners)
33
+ end
34
+
35
+ before do
36
+ monitor.scan!
37
+ end
38
+
39
+ it 'updates the server description', if: standalone? do
40
+ expect(monitor.description).to be_standalone
41
+ end
42
+
43
+ it 'updates the server description', if: replica_set? do
44
+ expect(monitor.description).to be_primary
45
+ end
46
+
47
+ it 'updates the server description', if: sharded? do
48
+ expect(monitor.description).to be_mongos
49
+ end
50
+ end
51
+
52
+ context 'when the ismaster command fails' do
53
+
54
+ context 'when no server is running on the address' do
55
+
56
+ let(:bad_address) do
57
+ Mongo::Address.new('127.0.0.1:27050')
58
+ end
59
+
60
+ let(:monitor) do
61
+ described_class.new(bad_address, listeners)
62
+ end
63
+
64
+ before do
65
+ monitor.scan!
66
+ end
67
+
68
+ it 'keeps the server unknown' do
69
+ expect(monitor.description).to be_unknown
70
+ end
71
+ end
72
+
73
+ context 'when the socket gets an exception' do
74
+
75
+ let(:bad_address) do
76
+ Mongo::Address.new(DEFAULT_ADDRESS)
77
+ end
78
+
79
+ let(:monitor) do
80
+ described_class.new(bad_address, listeners)
81
+ end
82
+
83
+ let(:socket) do
84
+ monitor.connection.connect!
85
+ monitor.connection.__send__(:socket)
86
+ end
87
+
88
+ before do
89
+ expect(socket).to receive(:write).and_raise(Mongo::Error::SocketError)
90
+ monitor.scan!
91
+ end
92
+
93
+ it 'keeps the server unknown' do
94
+ expect(monitor.description).to be_unknown
95
+ end
96
+
97
+ it 'disconnects the connection' do
98
+ expect(monitor.connection).to_not be_connected
99
+ end
100
+ end
101
+ end
102
+ end
103
+
104
+ describe '#heartbeat_frequency' do
105
+
106
+ context 'when an option is provided' do
107
+
108
+ let(:monitor) do
109
+ described_class.new(address, listeners, :heartbeat_frequency => 5)
110
+ end
111
+
112
+ it 'returns the option' do
113
+ expect(monitor.heartbeat_frequency).to eq(5)
114
+ end
115
+ end
116
+
117
+ context 'when no option is provided' do
118
+
119
+ let(:monitor) do
120
+ described_class.new(address, listeners)
121
+ end
122
+
123
+ it 'defaults to 5' do
124
+ expect(monitor.heartbeat_frequency).to eq(10)
125
+ end
126
+ end
127
+ end
128
+
129
+ describe '#run!' do
130
+
131
+ let(:monitor) do
132
+ described_class.new(address, listeners, :heartbeat_frequency => 1)
133
+ end
134
+
135
+ before do
136
+ monitor.run!
137
+ sleep(1)
138
+ end
139
+
140
+ it 'refreshes the server on the provided interval' do
141
+ expect(monitor.description).to_not be_nil
142
+ end
143
+ end
144
+ 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['tags'])
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['tags'])
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