mongo 2.0.6 → 2.1.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 (317) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +5 -2
  3. data/lib/mongo/address/ipv4.rb +6 -1
  4. data/lib/mongo/address/unix.rb +2 -2
  5. data/lib/mongo/address.rb +18 -10
  6. data/lib/mongo/auth/cr/conversation.rb +1 -1
  7. data/lib/mongo/auth/ldap/conversation.rb +7 -3
  8. data/lib/mongo/auth/scram/conversation.rb +9 -3
  9. data/lib/mongo/auth/user/view.rb +23 -2
  10. data/lib/mongo/auth/x509/conversation.rb +1 -1
  11. data/lib/mongo/bulk_write/combineable.rb +51 -0
  12. data/lib/mongo/bulk_write/ordered_combiner.rb +55 -0
  13. data/lib/mongo/bulk_write/result.rb +191 -0
  14. data/lib/mongo/bulk_write/result_combiner.rb +117 -0
  15. data/lib/mongo/bulk_write/transformable.rb +132 -0
  16. data/lib/mongo/bulk_write/unordered_combiner.rb +52 -0
  17. data/lib/mongo/bulk_write/validatable.rb +62 -0
  18. data/lib/mongo/bulk_write.rb +159 -23
  19. data/lib/mongo/client.rb +52 -16
  20. data/lib/mongo/cluster/topology/replica_set.rb +27 -9
  21. data/lib/mongo/cluster/topology/sharded.rb +1 -1
  22. data/lib/mongo/cluster/topology/unknown.rb +5 -2
  23. data/lib/mongo/cluster.rb +42 -7
  24. data/lib/mongo/collection/view/aggregation.rb +48 -9
  25. data/lib/mongo/collection/view/immutable.rb +6 -6
  26. data/lib/mongo/collection/view/iterable.rb +18 -4
  27. data/lib/mongo/collection/view/map_reduce.rb +58 -17
  28. data/lib/mongo/collection/view/readable.rb +173 -42
  29. data/lib/mongo/collection/view/writable.rb +37 -23
  30. data/lib/mongo/collection/view.rb +2 -2
  31. data/lib/mongo/collection.rb +370 -33
  32. data/lib/mongo/cursor.rb +15 -3
  33. data/lib/mongo/database/view.rb +5 -4
  34. data/lib/mongo/database.rb +14 -4
  35. data/lib/mongo/dbref.rb +113 -0
  36. data/lib/mongo/error/closed_stream.rb +34 -0
  37. data/lib/mongo/error/extra_file_chunk.rb +34 -0
  38. data/lib/mongo/error/{invalid_uri_option.rb → file_not_found.rb} +11 -12
  39. data/lib/mongo/error/invalid_file.rb +2 -2
  40. data/lib/mongo/error/invalid_file_revision.rb +37 -0
  41. data/lib/mongo/error/invalid_uri.rb +5 -4
  42. data/lib/mongo/error/missing_file_chunk.rb +38 -0
  43. data/lib/mongo/error/operation_failure.rb +1 -1
  44. data/lib/mongo/error/parser.rb +1 -1
  45. data/lib/mongo/error/unchangeable_collection_option.rb +38 -0
  46. data/lib/mongo/error/unexpected_chunk_length.rb +39 -0
  47. data/lib/mongo/error.rb +13 -2
  48. data/lib/mongo/event/description_changed.rb +1 -1
  49. data/lib/mongo/grid/file/chunk.rb +6 -6
  50. data/lib/mongo/grid/file/{metadata.rb → info.rb} +41 -39
  51. data/lib/mongo/grid/file.rb +13 -10
  52. data/lib/mongo/grid/fs_bucket.rb +448 -0
  53. data/lib/mongo/grid/stream/read.rb +208 -0
  54. data/lib/mongo/grid/stream/write.rb +187 -0
  55. data/lib/mongo/grid/stream.rb +64 -0
  56. data/lib/mongo/grid.rb +2 -1
  57. data/lib/mongo/index/view.rb +3 -3
  58. data/lib/mongo/index.rb +5 -0
  59. data/lib/mongo/loggable.rb +34 -57
  60. data/lib/mongo/logger.rb +16 -78
  61. data/lib/mongo/monitoring/command_log_subscriber.rb +112 -0
  62. data/lib/mongo/monitoring/event/command_failed.rb +96 -0
  63. data/lib/mongo/monitoring/event/command_started.rb +89 -0
  64. data/lib/mongo/monitoring/event/command_succeeded.rb +118 -0
  65. data/lib/mongo/monitoring/event/secure.rb +58 -0
  66. data/lib/mongo/monitoring/event.rb +18 -0
  67. data/lib/mongo/monitoring/publishable.rb +106 -0
  68. data/lib/mongo/monitoring.rb +195 -0
  69. data/lib/mongo/operation/{aggregate.rb → commands/aggregate.rb} +3 -41
  70. data/lib/mongo/operation/commands/collections_info/result.rb +39 -0
  71. data/lib/mongo/operation/commands/collections_info.rb +68 -0
  72. data/lib/mongo/operation/{command.rb → commands/command.rb} +2 -18
  73. data/lib/mongo/operation/commands/indexes.rb +70 -0
  74. data/lib/mongo/operation/commands/list_collections/result.rb +112 -0
  75. data/lib/mongo/operation/commands/list_collections.rb +54 -0
  76. data/lib/mongo/operation/commands/list_indexes/result.rb +116 -0
  77. data/lib/mongo/operation/commands/list_indexes.rb +56 -0
  78. data/lib/mongo/operation/{map_reduce → commands/map_reduce}/result.rb +1 -1
  79. data/lib/mongo/operation/{map_reduce.rb → commands/map_reduce.rb} +3 -41
  80. data/lib/mongo/operation/commands/parallel_scan/result.rb +72 -0
  81. data/lib/mongo/operation/commands/parallel_scan.rb +56 -0
  82. data/lib/mongo/operation/commands/user_query.rb +69 -0
  83. data/lib/mongo/{bulk_write/ordered_bulk_write.rb → operation/commands/users_info/result.rb} +18 -30
  84. data/lib/mongo/operation/commands/users_info.rb +53 -0
  85. data/lib/mongo/operation/commands.rb +24 -0
  86. data/lib/mongo/operation/executable.rb +4 -68
  87. data/lib/mongo/operation/kill_cursors.rb +3 -3
  88. data/lib/mongo/operation/read/get_more.rb +2 -22
  89. data/lib/mongo/{bulk_write/unordered_bulk_write.rb → operation/read/query/result.rb} +20 -26
  90. data/lib/mongo/operation/read/query.rb +4 -21
  91. data/lib/mongo/operation/read.rb +0 -4
  92. data/lib/mongo/operation/{read_preferrable.rb → read_preference.rb} +3 -2
  93. data/lib/mongo/operation/result.rb +13 -1
  94. data/lib/mongo/operation/specifiable.rb +42 -0
  95. data/lib/mongo/operation/write/bulk/bulkable.rb +82 -0
  96. data/lib/mongo/operation/write/bulk/delete/result.rb +74 -0
  97. data/lib/mongo/operation/write/bulk/delete.rb +71 -0
  98. data/lib/mongo/operation/write/bulk/insert/result.rb +129 -0
  99. data/lib/mongo/operation/write/bulk/insert.rb +96 -0
  100. data/lib/mongo/operation/write/bulk/legacy_mergable.rb +87 -0
  101. data/lib/mongo/operation/write/bulk/mergable.rb +71 -0
  102. data/lib/mongo/operation/write/bulk/update/result.rb +174 -0
  103. data/lib/mongo/operation/write/bulk/update.rb +81 -0
  104. data/lib/mongo/operation/write/bulk.rb +6 -3
  105. data/lib/mongo/operation/write/command/create_index.rb +0 -1
  106. data/lib/mongo/operation/write/command/create_user.rb +0 -1
  107. data/lib/mongo/operation/write/command/delete.rb +0 -1
  108. data/lib/mongo/operation/write/command/drop_index.rb +0 -1
  109. data/lib/mongo/operation/write/command/insert.rb +0 -1
  110. data/lib/mongo/operation/write/command/remove_user.rb +0 -1
  111. data/lib/mongo/operation/write/command/update.rb +0 -1
  112. data/lib/mongo/operation/write/command/update_user.rb +0 -1
  113. data/lib/mongo/operation/write/command/writable.rb +13 -18
  114. data/lib/mongo/operation/write/create_index.rb +4 -27
  115. data/lib/mongo/operation/write/create_user.rb +4 -30
  116. data/lib/mongo/operation/write/delete.rb +6 -29
  117. data/lib/mongo/operation/write/drop_index.rb +3 -3
  118. data/lib/mongo/operation/write/gle.rb +48 -0
  119. data/lib/mongo/operation/write/idable.rb +5 -0
  120. data/lib/mongo/operation/write/insert.rb +2 -24
  121. data/lib/mongo/operation/write/remove_user.rb +4 -27
  122. data/lib/mongo/operation/write/update.rb +13 -36
  123. data/lib/mongo/operation/write/update_user.rb +4 -30
  124. data/lib/mongo/operation/write/write_command_enabled.rb +53 -0
  125. data/lib/mongo/operation/write.rb +2 -0
  126. data/lib/mongo/operation.rb +32 -4
  127. data/lib/mongo/options/mapper.rb +4 -2
  128. data/lib/mongo/options/redacted.rb +156 -0
  129. data/lib/mongo/options.rb +1 -0
  130. data/lib/mongo/protocol/delete.rb +75 -15
  131. data/lib/mongo/protocol/get_more.rb +65 -13
  132. data/lib/mongo/protocol/insert.rb +85 -13
  133. data/lib/mongo/protocol/kill_cursors.rb +59 -14
  134. data/lib/mongo/protocol/message.rb +12 -12
  135. data/lib/mongo/protocol/query.rb +163 -37
  136. data/lib/mongo/protocol/reply.rb +103 -0
  137. data/lib/mongo/protocol/serializers.rb +1 -1
  138. data/lib/mongo/protocol/update.rb +82 -14
  139. data/lib/mongo/retryable.rb +83 -0
  140. data/lib/mongo/server/connectable.rb +21 -25
  141. data/lib/mongo/server/connection.rb +75 -4
  142. data/lib/mongo/server/connection_pool/queue.rb +15 -0
  143. data/lib/mongo/server/connection_pool.rb +12 -0
  144. data/lib/mongo/server/description/features.rb +2 -1
  145. data/lib/mongo/server/description.rb +52 -1
  146. data/lib/mongo/server/monitor/connection.rb +26 -2
  147. data/lib/mongo/server/monitor.rb +19 -3
  148. data/lib/mongo/server.rb +39 -5
  149. data/lib/mongo/server_selector/selectable.rb +40 -31
  150. data/lib/mongo/server_selector.rb +19 -10
  151. data/lib/mongo/socket/ssl.rb +28 -16
  152. data/lib/mongo/socket/tcp.rb +3 -3
  153. data/lib/mongo/socket/unix.rb +5 -8
  154. data/lib/mongo/socket.rb +11 -4
  155. data/lib/mongo/uri.rb +248 -137
  156. data/lib/mongo/version.rb +1 -1
  157. data/lib/mongo.rb +5 -3
  158. data/spec/mongo/address/unix_spec.rb +1 -1
  159. data/spec/mongo/address_spec.rb +25 -0
  160. data/spec/mongo/auth/cr_spec.rb +9 -1
  161. data/spec/mongo/auth/ldap/conversation_spec.rb +43 -0
  162. data/spec/mongo/auth/ldap_spec.rb +9 -1
  163. data/spec/mongo/auth/scram_spec.rb +9 -1
  164. data/spec/mongo/auth/user/view_spec.rb +26 -1
  165. data/spec/mongo/auth/x509_spec.rb +9 -1
  166. data/spec/mongo/bulk_write/ordered_combiner_spec.rb +271 -0
  167. data/spec/mongo/bulk_write/unordered_combiner_spec.rb +239 -0
  168. data/spec/mongo/bulk_write_spec.rb +428 -0
  169. data/spec/mongo/client_spec.rb +167 -17
  170. data/spec/mongo/cluster/topology/replica_set_spec.rb +18 -9
  171. data/spec/mongo/cluster/topology/sharded_spec.rb +11 -3
  172. data/spec/mongo/cluster/topology/single_spec.rb +12 -4
  173. data/spec/mongo/cluster_spec.rb +55 -10
  174. data/spec/mongo/collection/view/aggregation_spec.rb +188 -1
  175. data/spec/mongo/collection/view/explainable_spec.rb +1 -1
  176. data/spec/mongo/collection/view/immutable_spec.rb +103 -0
  177. data/spec/mongo/collection/view/map_reduce_spec.rb +99 -4
  178. data/spec/mongo/collection/view/readable_spec.rb +238 -6
  179. data/spec/mongo/collection/view/writable_spec.rb +4 -4
  180. data/spec/mongo/collection/view_spec.rb +459 -71
  181. data/spec/mongo/collection_spec.rb +1291 -9
  182. data/spec/mongo/command_monitoring_spec.rb +51 -0
  183. data/spec/mongo/connection_string_spec.rb +115 -0
  184. data/spec/mongo/crud_spec.rb +2 -2
  185. data/spec/mongo/cursor_spec.rb +3 -3
  186. data/spec/mongo/database_spec.rb +47 -11
  187. data/spec/mongo/dbref_spec.rb +149 -0
  188. data/spec/mongo/grid/file/chunk_spec.rb +5 -5
  189. data/spec/mongo/grid/file/{metadata_spec.rb → info_spec.rb} +29 -17
  190. data/spec/mongo/grid/file_spec.rb +8 -8
  191. data/spec/mongo/grid/fs_bucket_spec.rb +1020 -0
  192. data/spec/mongo/grid/stream/read_spec.rb +275 -0
  193. data/spec/mongo/grid/stream/write_spec.rb +440 -0
  194. data/spec/mongo/grid/stream_spec.rb +48 -0
  195. data/spec/mongo/gridfs_spec.rb +50 -0
  196. data/spec/mongo/logger_spec.rb +0 -40
  197. data/spec/mongo/monitoring/command_log_subscriber_spec.rb +76 -0
  198. data/spec/mongo/monitoring/event/command_started_spec.rb +26 -0
  199. data/spec/mongo/monitoring/event/command_succeeded_spec.rb +26 -0
  200. data/spec/mongo/monitoring/event/secure_spec.rb +57 -0
  201. data/spec/mongo/monitoring_spec.rb +168 -0
  202. data/spec/mongo/operation/commands/aggregate_spec.rb +69 -0
  203. data/spec/mongo/operation/{read → commands}/collections_info_spec.rb +1 -1
  204. data/spec/mongo/operation/{command_spec.rb → commands/command_spec.rb} +0 -18
  205. data/spec/mongo/operation/{read → commands}/indexes_spec.rb +1 -1
  206. data/spec/mongo/operation/{map_reduce_spec.rb → commands/map_reduce_spec.rb} +1 -19
  207. data/spec/mongo/operation/kill_cursors_spec.rb +1 -17
  208. data/spec/mongo/operation/read/get_more_spec.rb +0 -16
  209. data/spec/mongo/operation/read/query_spec.rb +19 -16
  210. data/spec/mongo/operation/{read_preferrable_spec.rb → read_preference_spec.rb} +11 -11
  211. data/spec/mongo/operation/write/bulk/{bulk_delete_spec.rb → delete_spec.rb} +18 -29
  212. data/spec/mongo/operation/write/bulk/{bulk_insert_spec.rb → insert_spec.rb} +3 -14
  213. data/spec/mongo/operation/write/bulk/{bulk_update_spec.rb → update_spec.rb} +8 -19
  214. data/spec/mongo/operation/write/command/delete_spec.rb +0 -16
  215. data/spec/mongo/operation/write/command/insert_spec.rb +0 -16
  216. data/spec/mongo/operation/write/command/update_spec.rb +0 -16
  217. data/spec/mongo/operation/write/delete_spec.rb +4 -4
  218. data/spec/mongo/operation/write/insert_spec.rb +2 -13
  219. data/spec/mongo/operation/write/update_spec.rb +7 -7
  220. data/spec/mongo/options/redacted_spec.rb +350 -0
  221. data/spec/mongo/protocol/kill_cursors_spec.rb +5 -3
  222. data/spec/mongo/protocol/query_spec.rb +15 -30
  223. data/spec/mongo/retryable_spec.rb +147 -0
  224. data/spec/mongo/server/connection_pool/queue_spec.rb +16 -0
  225. data/spec/mongo/server/connection_pool_spec.rb +50 -6
  226. data/spec/mongo/server/connection_spec.rb +49 -4
  227. data/spec/mongo/server/description_spec.rb +49 -3
  228. data/spec/mongo/server/monitor_spec.rb +51 -0
  229. data/spec/mongo/server_discovery_and_monitoring_spec.rb +32 -59
  230. data/spec/mongo/server_selection_rtt_spec.rb +37 -57
  231. data/spec/mongo/server_selection_spec.rb +19 -9
  232. data/spec/mongo/server_selector/nearest_spec.rb +35 -27
  233. data/spec/mongo/server_selector/primary_preferred_spec.rb +32 -30
  234. data/spec/mongo/server_selector/primary_spec.rb +21 -14
  235. data/spec/mongo/server_selector/secondary_preferred_spec.rb +28 -26
  236. data/spec/mongo/server_selector/secondary_spec.rb +24 -22
  237. data/spec/mongo/server_selector_spec.rb +87 -24
  238. data/spec/mongo/server_spec.rb +94 -8
  239. data/spec/mongo/socket/ssl_spec.rb +123 -13
  240. data/spec/mongo/socket/unix_spec.rb +52 -0
  241. data/spec/mongo/uri_spec.rb +295 -67
  242. data/spec/spec_helper.rb +40 -24
  243. data/spec/support/authorization.rb +23 -9
  244. data/spec/support/certificates/client.pem +4 -4
  245. data/spec/support/command_monitoring/bulkWrite.yml +73 -0
  246. data/spec/support/command_monitoring/command.yml +42 -0
  247. data/spec/support/command_monitoring/deleteMany.yml +55 -0
  248. data/spec/support/command_monitoring/deleteOne.yml +55 -0
  249. data/spec/support/command_monitoring/find.yml +219 -0
  250. data/spec/support/command_monitoring/insertMany.yml +81 -0
  251. data/spec/support/command_monitoring/insertOne.yml +51 -0
  252. data/spec/support/command_monitoring/updateMany.yml +67 -0
  253. data/spec/support/command_monitoring/updateOne.yml +95 -0
  254. data/spec/support/command_monitoring.rb +365 -0
  255. data/spec/support/connection_string.rb +228 -0
  256. data/spec/support/connection_string_tests/invalid-uris.yml +193 -0
  257. data/spec/support/connection_string_tests/valid-auth.yml +256 -0
  258. data/spec/support/connection_string_tests/valid-host_identifiers.yml +121 -0
  259. data/spec/support/connection_string_tests/valid-options.yml +30 -0
  260. data/spec/support/connection_string_tests/valid-unix_socket-absolute.yml +197 -0
  261. data/spec/support/connection_string_tests/valid-unix_socket-relative.yml +213 -0
  262. data/spec/support/connection_string_tests/valid-warnings.yml +55 -0
  263. data/spec/support/crud/read.rb +22 -19
  264. data/spec/support/crud/write.rb +58 -27
  265. data/spec/support/crud.rb +10 -2
  266. data/spec/support/gridfs.rb +637 -0
  267. data/spec/support/gridfs_tests/delete.yml +157 -0
  268. data/spec/support/gridfs_tests/download.yml +210 -0
  269. data/spec/support/gridfs_tests/download_by_name.yml +113 -0
  270. data/spec/support/gridfs_tests/upload.yml +158 -0
  271. data/spec/support/matchers.rb +1 -1
  272. data/spec/support/sdam/rs/equal_electionids.yml +44 -0
  273. data/spec/support/sdam/rs/new_primary_new_electionid.yml +95 -0
  274. data/spec/support/sdam/rs/null_election_id.yml +144 -0
  275. data/spec/support/sdam/rs/primary_disconnect_electionid.yml +124 -0
  276. data/spec/support/sdam/rs/primary_mismatched_me.yml +37 -0
  277. data/spec/support/sdam/rs/primary_to_no_primary_mismatched_me.yml +75 -0
  278. data/spec/support/sdam/rs/secondary_mismatched_me.yml +37 -0
  279. data/spec/support/sdam/sharded/mongos_disconnect.yml +104 -0
  280. data/spec/support/sdam/single/direct_connection_rsarbiter.yml +1 -1
  281. data/spec/support/sdam/single/direct_connection_rsprimary.yml +1 -1
  282. data/spec/support/sdam/single/direct_connection_rssecondary.yml +1 -1
  283. data/spec/support/sdam/single/direct_connection_slave.yml +1 -1
  284. data/spec/support/sdam/single/direct_connection_standalone.yml +1 -1
  285. data/spec/support/sdam/single/not_ok_response.yml +0 -1
  286. data/spec/support/server_discovery_and_monitoring.rb +22 -3
  287. data/spec/support/server_selection.rb +3 -1
  288. data/spec/support/shared/bulk_write.rb +218 -22
  289. data/spec/support/shared/server_selector.rb +80 -14
  290. data.tar.gz.sig +0 -0
  291. metadata +188 -59
  292. metadata.gz.sig +0 -0
  293. data/lib/mongo/bulk_write/bulk_writable.rb +0 -196
  294. data/lib/mongo/bulk_write/deletable.rb +0 -56
  295. data/lib/mongo/bulk_write/insertable.rb +0 -48
  296. data/lib/mongo/bulk_write/replacable.rb +0 -57
  297. data/lib/mongo/bulk_write/updatable.rb +0 -68
  298. data/lib/mongo/grid/fs.rb +0 -149
  299. data/lib/mongo/operation/list_collections/result.rb +0 -114
  300. data/lib/mongo/operation/list_indexes/result.rb +0 -118
  301. data/lib/mongo/operation/read/collections_info.rb +0 -68
  302. data/lib/mongo/operation/read/indexes.rb +0 -69
  303. data/lib/mongo/operation/read/list_collections.rb +0 -76
  304. data/lib/mongo/operation/read/list_indexes.rb +0 -78
  305. data/lib/mongo/operation/write/bulk/bulk_delete/result.rb +0 -75
  306. data/lib/mongo/operation/write/bulk/bulk_delete.rb +0 -145
  307. data/lib/mongo/operation/write/bulk/bulk_insert/result.rb +0 -130
  308. data/lib/mongo/operation/write/bulk/bulk_insert.rb +0 -132
  309. data/lib/mongo/operation/write/bulk/bulk_mergable.rb +0 -67
  310. data/lib/mongo/operation/write/bulk/bulk_update/result.rb +0 -162
  311. data/lib/mongo/operation/write/bulk/bulk_update.rb +0 -154
  312. data/lib/mongo/operation/write/bulk/legacy_bulk_mergable.rb +0 -83
  313. data/spec/mongo/bulk/bulk_write_spec.rb +0 -262
  314. data/spec/mongo/grid/fs_spec.rb +0 -160
  315. data/spec/mongo/loggable_spec.rb +0 -63
  316. data/spec/mongo/operation/aggregate_spec.rb +0 -127
  317. /data/lib/mongo/operation/{aggregate → commands/aggregate}/result.rb +0 -0
data/lib/mongo/uri.rb CHANGED
@@ -27,59 +27,118 @@ module Mongo
27
27
  #
28
28
  # @since 2.0.0
29
29
  class URI
30
+ include Loggable
30
31
 
31
- # Scheme Regex: non-capturing, matches scheme.
32
+ # The uri parser object options.
32
33
  #
33
34
  # @since 2.0.0
34
- SCHEME = %r{(?:mongodb://)}.freeze
35
+ attr_reader :options
35
36
 
36
- # User Regex: capturing, group 1, matches anything but ':'
37
+ # The options specified in the uri.
37
38
  #
38
- # @since 2.0.0
39
- USER = /([^:]+)/.freeze
39
+ # @since 2.1.0
40
+ attr_reader :uri_options
40
41
 
41
- # Password Regex: capturing, group 2, matches anything but '@'
42
+ # The servers specified in the uri.
42
43
  #
43
44
  # @since 2.0.0
44
- PASSWORD = /([^@]+)/.freeze
45
+ attr_reader :servers
45
46
 
46
- # Credentials Regex: non capturing, matches 'user:password@'
47
+ # Unsafe characters that must be urlencoded.
47
48
  #
48
- # @since 2.0.0
49
- CREDENTIALS = /(?:#{USER}:#{PASSWORD}?@)?/.freeze
49
+ # @since 2.1.0
50
+ UNSAFE = /[\:\/\+\@]/
50
51
 
51
- # Host and port server Regex: matches anything but a forward slash
52
+ # Unix socket suffix.
52
53
  #
53
- # @since 2.0.0
54
- HOSTPORT = /[^\/]+/.freeze
54
+ # @since 2.1.0
55
+ UNIX_SOCKET = /.sock/
55
56
 
56
- # Unix socket server Regex: matches unix socket server
57
+ # The mongodb connection string scheme.
57
58
  #
58
59
  # @since 2.0.0
59
- UNIX = /\/.+.sock?/.freeze
60
+ SCHEME = 'mongodb://'.freeze
60
61
 
61
- # server Regex: capturing, matches host and port server or unix server
62
+ # The character delimiting hosts.
62
63
  #
63
- # @since 2.0.0
64
- SERVERS = /((?:(?:#{HOSTPORT}|#{UNIX}),?)+)/.freeze
64
+ # @since 2.1.0
65
+ HOST_DELIM = ','.freeze
65
66
 
66
- # Database Regex: matches anything but the characters that cannot
67
- # be part of any MongoDB database name.
67
+ # The character separating a host and port.
68
68
  #
69
- # @since 2.0.0
70
- DATABASE = %r{(?:/([^/\.\ "*<>:\|\?]*))?}.freeze
69
+ # @since 2.1.0
70
+ HOST_PORT_DELIM = ':'.freeze
71
71
 
72
- # Option Regex: notably only matches the ampersand separator and does
73
- # not allow for semicolon to be used to separate options.
72
+ # The character delimiting a database.
74
73
  #
75
- # @since 2.0.0
76
- OPTIONS = /(?:\?(?:(.+=.+)&?)+)*/.freeze
74
+ # @since 2.1.0
75
+ DATABASE_DELIM = '/'.freeze
77
76
 
78
- # Complete URI Regex: matches all of the combined components
77
+ # The character delimiting options.
79
78
  #
80
- # @since 2.0.0
81
- URI = /#{SCHEME}#{CREDENTIALS}#{SERVERS}#{DATABASE}#{OPTIONS}/.freeze
79
+ # @since 2.1.0
80
+ URI_OPTS_DELIM = '?'.freeze
82
81
 
82
+ # The character delimiting multiple options.
83
+ #
84
+ # @since 2.1.0
85
+ INDIV_URI_OPTS_DELIM = '&'.freeze
86
+
87
+ # The character delimiting an option and its value.
88
+ #
89
+ # @since 2.1.0
90
+ URI_OPTS_VALUE_DELIM = '='.freeze
91
+
92
+ # The character separating a username from the password.
93
+ #
94
+ # @since 2.1.0
95
+ AUTH_USER_PWD_DELIM = ':'.freeze
96
+
97
+ # The character delimiting auth credentials.
98
+ #
99
+ # @since 2.1.0
100
+ AUTH_DELIM = '@'.freeze
101
+
102
+ # Error details for an invalid scheme.
103
+ #
104
+ # @since 2.1.0
105
+ INVALID_SCHEME = "Invalid scheme. Scheme must be '#{SCHEME}'".freeze
106
+
107
+ # Error details for an invalid options format.
108
+ #
109
+ # @since 2.1.0
110
+ INVALID_OPTS_VALUE_DELIM = "Options and their values must be delimited" +
111
+ " by '#{URI_OPTS_VALUE_DELIM}'".freeze
112
+
113
+ # Error details for an non-urlencoded user name or password.
114
+ #
115
+ # @since 2.1.0
116
+ UNESCAPED_USER_PWD = "User name and password must be urlencoded.".freeze
117
+
118
+ # Error details for a non-urlencoded unix socket path.
119
+ #
120
+ # @since 2.1.0
121
+ UNESCAPED_UNIX_SOCKET = "UNIX domain sockets must be urlencoded.".freeze
122
+
123
+ # Error details for a non-urlencoded auth databsae name.
124
+ #
125
+ # @since 2.1.0
126
+ UNESCAPED_DATABASE = "Auth database must be urlencoded.".freeze
127
+
128
+ # Error details for providing options without a database delimiter.
129
+ #
130
+ # @since 2.1.0
131
+ INVALID_OPTS_DELIM = "Database delimiter '#{DATABASE_DELIM}' must be present if options are specified.".freeze
132
+
133
+ # Error details for a missing host.
134
+ #
135
+ # @since 2.1.0
136
+ INVALID_HOST = "Missing host; at least one must be provided.".freeze
137
+
138
+ # Error details for an invalid port.
139
+ #
140
+ # @since 2.1.0
141
+ INVALID_PORT = "Invalid port. Port must be an integer greater than 0 and less than 65536".freeze
83
142
 
84
143
  # MongoDB URI format specification.
85
144
  #
@@ -112,31 +171,28 @@ module Mongo
112
171
  'GSSAPI' => :gssapi
113
172
  }.freeze
114
173
 
174
+ # Options that are allowed to appear more than once in the uri.
175
+ #
176
+ # @since 2.1.0
177
+ REPEATABLE_OPTIONS = [ :tag_sets ]
178
+
115
179
  # Create the new uri from the provided string.
116
180
  #
117
181
  # @example Create the new URI.
118
182
  # URI.new('mongodb://localhost:27017')
119
183
  #
120
184
  # @param [ String ] string The uri string.
185
+ # @param [ Hash ] options The options.
121
186
  #
122
- # @raise [ BadURI ] If the uri does not match the spec.
123
- #
124
- # @since 2.0.0
125
- def initialize(string)
126
- @match = string.match(URI)
127
- raise Error::InvalidURI.new(string) unless @match
128
- end
129
-
130
- # Get the servers provided in the URI.
131
- #
132
- # @example Get the servers.
133
- # uri.servers
134
- #
135
- # @return [ Array<String> ] The servers.
187
+ # @raise [ Error::InvalidURI ] If the uri does not match the spec.
136
188
  #
137
189
  # @since 2.0.0
138
- def servers
139
- @match[3].split(',')
190
+ def initialize(string, options = {})
191
+ @string = string
192
+ @options = options
193
+ empty, scheme, remaining = @string.partition(SCHEME)
194
+ raise_invalid_error!(INVALID_SCHEME) unless scheme == SCHEME
195
+ setup!(remaining)
140
196
  end
141
197
 
142
198
  # Gets the options hash that needs to be passed to a Mongo::Client on
@@ -150,8 +206,8 @@ module Mongo
150
206
  #
151
207
  # @since 2.0.0
152
208
  def client_options
153
- opts = options.merge(:database => database)
154
- user ? opts.merge(credentials) : opts
209
+ opts = uri_options.merge(:database => database)
210
+ @user ? opts.merge(credentials) : opts
155
211
  end
156
212
 
157
213
  # Get the credentials provided in the URI.
@@ -165,7 +221,7 @@ module Mongo
165
221
  #
166
222
  # @since 2.0.0
167
223
  def credentials
168
- { :user => user, :password => password }
224
+ { :user => @user, :password => @password }
169
225
  end
170
226
 
171
227
  # Get the database provided in the URI.
@@ -177,110 +233,161 @@ module Mongo
177
233
  #
178
234
  # @since 2.0.0
179
235
  def database
180
- @match[4].nil? ? Database::ADMIN : @match[4]
236
+ @database ? @database : Database::ADMIN
181
237
  end
182
238
 
183
- # Get the options provided in the URI.
184
- #
185
- # @example Get The options.
186
- # uri.options
187
- #
188
- # @return [Hash] The options.
189
- #
190
- # Generic Options
191
- # * :replica_set [String] replica set name
192
- # * :connect_timeout [Fixnum] connect timeout
193
- # * :socket_timeout [Fixnum] socket timeout
194
- # * :ssl [true, false] ssl enabled?
195
- #
196
- # Write Options (returned in a hash under the :write key)
197
- # * :w [String, Fixnum] write concern value
198
- # * :j [true, false] journal
199
- # * :fsync [true, false] fsync
200
- # * :timeout [Fixnum] timeout for write operation
201
- #
202
- # Read Options (returned in a hash under the :read key)
203
- # * :mode [Symbol] read mode
204
- # * :tag_sets [Array<Hash>] read tag sets
205
- #
206
- # @since 2.0.0
207
- def options
208
- parsed_options = @match[5]
209
- return {} unless parsed_options
210
- parsed_options.split('&').reduce({}) do |options, option|
211
- key, value = option.split('=')
212
- strategy = OPTION_MAP[key]
213
- raise Error::InvalidURIOption.new(key) if strategy.nil?
214
- add_option(strategy, value, options)
215
- options
239
+ private
240
+
241
+ def setup!(remaining)
242
+ creds_hosts, db_opts = extract_db_opts!(remaining)
243
+ parse_creds_hosts!(creds_hosts)
244
+ parse_db_opts!(db_opts)
245
+ end
246
+
247
+ def extract_db_opts!(string)
248
+ db_opts, d, creds_hosts = string.reverse.partition(DATABASE_DELIM)
249
+ db_opts, creds_hosts = creds_hosts, db_opts if creds_hosts.empty?
250
+ if db_opts.empty? && creds_hosts.include?(URI_OPTS_DELIM)
251
+ raise_invalid_error!(INVALID_OPTS_DELIM)
216
252
  end
253
+ [ creds_hosts, db_opts ].map { |s| s.reverse }
217
254
  end
218
255
 
219
- private
256
+ def parse_creds_hosts!(string)
257
+ hosts, creds = split_creds_hosts(string)
258
+ @servers = parse_servers!(hosts)
259
+ @user = parse_user!(creds)
260
+ @password = parse_password!(creds)
261
+ end
262
+
263
+ def split_creds_hosts(string)
264
+ hosts, d, creds = string.reverse.partition(AUTH_DELIM)
265
+ hosts, creds = creds, hosts if hosts.empty?
266
+ [ hosts, creds ].map { |s| s.reverse }
267
+ end
268
+
269
+ def parse_db_opts!(string)
270
+ auth_db, d, uri_opts = string.partition(URI_OPTS_DELIM)
271
+ @uri_options = Options::Redacted.new(parse_uri_options!(uri_opts))
272
+ @database = parse_database!(auth_db)
273
+ end
274
+
275
+ def parse_uri_options!(string)
276
+ return {} unless string
277
+ string.split(INDIV_URI_OPTS_DELIM).reduce({}) do |uri_options, opt|
278
+ raise_invalid_error!(INVALID_OPTS_VALUE_DELIM) unless opt.index(URI_OPTS_VALUE_DELIM)
279
+ key, value = opt.split(URI_OPTS_VALUE_DELIM)
280
+ strategy = URI_OPTION_MAP[key.downcase]
281
+ if strategy.nil?
282
+ log_warn("Unsupported URI option '#{key}' on URI '#{@string}'. It will be ignored.")
283
+ else
284
+ add_uri_option(strategy, value, uri_options)
285
+ end
286
+ uri_options
287
+ end
288
+ end
289
+
290
+ def parse_user!(string)
291
+ if (string && user = string.partition(AUTH_USER_PWD_DELIM)[0])
292
+ raise_invalid_error!(UNESCAPED_USER_PWD) if user =~ UNSAFE
293
+ decode(user) if user.length > 0
294
+ end
295
+ end
296
+
297
+ def parse_password!(string)
298
+ if (string && pwd = string.partition(AUTH_USER_PWD_DELIM)[2])
299
+ raise_invalid_error!(UNESCAPED_USER_PWD) if pwd =~ UNSAFE
300
+ decode(pwd) if pwd.length > 0
301
+ end
302
+ end
303
+
304
+ def parse_database!(string)
305
+ raise_invalid_error!(UNESCAPED_DATABASE) if string =~ UNSAFE
306
+ decode(string) if string.length > 0
307
+ end
308
+
309
+ def validate_port_string!(port)
310
+ unless port.nil? || (port.length > 0 && port.to_i > 0 && port.to_i <= 65535)
311
+ raise_invalid_error!(INVALID_PORT)
312
+ end
313
+ end
314
+
315
+ def parse_servers!(string)
316
+ raise_invalid_error!(INVALID_HOST) unless string.size > 0
317
+ string.split(HOST_DELIM).reduce([]) do |servers, host|
318
+ if host[0] == '['
319
+ if host.index(']:')
320
+ h, p = host.split(']:')
321
+ validate_port_string!(p)
322
+ end
323
+ elsif host.index(HOST_PORT_DELIM)
324
+ h, d, p = host.partition(HOST_PORT_DELIM)
325
+ raise_invalid_error!(INVALID_HOST) unless h.size > 0
326
+ validate_port_string!(p)
327
+ elsif host =~ UNIX_SOCKET
328
+ raise_invalid_error!(UNESCAPED_UNIX_SOCKET) if host =~ UNSAFE
329
+ end
330
+ servers << host
331
+ end
332
+ end
333
+
334
+ def raise_invalid_error!(details)
335
+ raise Error::InvalidURI.new(@string, details)
336
+ end
337
+
338
+ def decode(value)
339
+ ::URI.decode(value)
340
+ end
220
341
 
221
342
  # Hash for storing map of URI option parameters to conversion strategies
222
- OPTION_MAP = {}
343
+ URI_OPTION_MAP = {}
223
344
 
224
- # Simple internal dsl to register a MongoDB URI option in the OPTION_MAP.
345
+ # Simple internal dsl to register a MongoDB URI option in the URI_OPTION_MAP.
225
346
  #
226
347
  # @param uri_key [String] The MongoDB URI option to register.
227
348
  # @param name [Symbol] The name of the option in the driver.
228
349
  # @param extra [Hash] Extra options.
229
350
  # * :group [Symbol] Nested hash where option will go.
230
351
  # * :type [Symbol] Name of function to transform value.
231
- def self.option(uri_key, name, extra = {})
232
- OPTION_MAP[uri_key] = { :name => name }.merge(extra)
352
+ def self.uri_option(uri_key, name, extra = {})
353
+ URI_OPTION_MAP[uri_key] = { :name => name }.merge(extra)
233
354
  end
234
355
 
235
356
  # Replica Set Options
236
- option 'replicaSet', :replica_set, :type => :replica_set
357
+ uri_option 'replicaset', :replica_set, :type => :replica_set
237
358
 
238
359
  # Timeout Options
239
- option 'connectTimeoutMS', :connect_timeout, :type => :ms_convert
240
- option 'socketTimeoutMS', :socket_timeout, :type => :ms_convert
241
- option 'serverSelectionTimeoutMS', :server_selection_timeout, :type => :ms_convert
242
- option 'localThresholdMS', :local_threshold, :type => :ms_convert
360
+ uri_option 'connecttimeoutms', :connect_timeout, :type => :ms_convert
361
+ uri_option 'sockettimeoutms', :socket_timeout, :type => :ms_convert
362
+ uri_option 'serverselectiontimeoutms', :server_selection_timeout, :type => :ms_convert
363
+ uri_option 'localthresholdms', :local_threshold, :type => :ms_convert
243
364
 
244
365
  # Write Options
245
- option 'w', :w, :group => :write
246
- option 'j', :j, :group => :write
247
- option 'fsync', :fsync, :group => :write
248
- option 'wtimeoutMS', :timeout, :group => :write
366
+ uri_option 'w', :w, :group => :write
367
+ uri_option 'journal', :j, :group => :write
368
+ uri_option 'fsync', :fsync, :group => :write
369
+ uri_option 'wtimeoutms', :timeout, :group => :write
249
370
 
250
371
  # Read Options
251
- option 'readPreference', :mode, :group => :read, :type => :read_mode
252
- option 'readPreferenceTags', :tag_sets, :group => :read, :type => :read_tags
372
+ uri_option 'readpreference', :mode, :group => :read, :type => :read_mode
373
+ uri_option 'readpreferencetags', :tag_sets, :group => :read, :type => :read_tags
253
374
 
254
375
  # Pool options
255
- option 'minPoolSize', :min_pool_size
256
- option 'maxPoolSize', :max_pool_size
257
- option 'waitQueueTimeoutMS', :wait_queue_timeout, :type => :ms_convert
376
+ uri_option 'minpoolsize', :min_pool_size
377
+ uri_option 'maxpoolsize', :max_pool_size
378
+ uri_option 'waitqueuetimeoutms', :wait_queue_timeout, :type => :ms_convert
258
379
 
259
380
  # Security Options
260
- option 'ssl', :ssl
381
+ uri_option 'ssl', :ssl
261
382
 
262
383
  # Topology options
263
- option 'connect', :connect
384
+ uri_option 'connect', :connect
264
385
 
265
386
  # Auth Options
266
- option 'authSource', :source, :group => :auth, :type => :auth_source
267
- option 'authMechanism', :mechanism, :group => :auth, :type => :auth_mech
268
- option 'authMechanismProperties', :auth_mech_properties, :group => :auth,
269
- :type => :auth_mech_props
270
-
271
- # Gets the user provided in the URI
272
- #
273
- # @return [String] The user.
274
- def user
275
- @match[1]
276
- end
277
-
278
- # Gets the password provided in the URI
279
- #
280
- # @return [String] The password.
281
- def password
282
- @match[2]
283
- end
387
+ uri_option 'authsource', :source, :group => :auth, :type => :auth_source
388
+ uri_option 'authmechanism', :auth_mech, :type => :auth_mech
389
+ uri_option 'authmechanismproperties', :auth_mech_properties, :group => :auth,
390
+ :type => :auth_mech_props
284
391
 
285
392
  # Casts option values that do not have a specifically provided
286
393
  # transofrmation to the appropriate type.
@@ -296,7 +403,7 @@ module Mongo
296
403
  elsif value =~ /[\d]/
297
404
  value.to_i
298
405
  else
299
- value.to_sym
406
+ decode(value).to_sym
300
407
  end
301
408
  end
302
409
 
@@ -315,15 +422,15 @@ module Mongo
315
422
 
316
423
  # Selects the output destination for an option.
317
424
  #
318
- # @param options [Hash] The base target.
319
- # @param group [Symbol] Group subtarget.
425
+ # @param [Hash] uri_options The base target.
426
+ # @param [Symbol] group Group subtarget.
320
427
  #
321
428
  # @return [Hash] The target for the option.
322
- def select_target(options, group = nil)
429
+ def select_target(uri_options, group = nil)
323
430
  if group
324
- options[group] ||= {}
431
+ uri_options[group] ||= {}
325
432
  else
326
- options
433
+ uri_options
327
434
  end
328
435
  end
329
436
 
@@ -338,15 +445,19 @@ module Mongo
338
445
  # @param target [Hash] The destination.
339
446
  # @param value [Object] The value to be merged.
340
447
  # @param name [Symbol] The name of the option.
341
- def merge_option(target, value, name)
448
+ def merge_uri_option(target, value, name)
342
449
  if target.key?(name)
343
- target[name] += value
450
+ if REPEATABLE_OPTIONS.include?(name)
451
+ target[name] += value
452
+ else
453
+ log_warn("Repeated option key: #{name}.")
454
+ end
344
455
  else
345
456
  target.merge!(name => value)
346
457
  end
347
458
  end
348
459
 
349
- # Adds an option to the options hash via the supplied strategy.
460
+ # Adds an option to the uri options hash via the supplied strategy.
350
461
  #
351
462
  # Acquires a target for the option based on group.
352
463
  # Transforms the value.
@@ -354,11 +465,11 @@ module Mongo
354
465
  #
355
466
  # @param strategy [Symbol] The strategy for this option.
356
467
  # @param value [String] The value of the option.
357
- # @param options [Hash] The base option target.
358
- def add_option(strategy, value, options)
359
- target = select_target(options, strategy[:group])
468
+ # @param uri_options [Hash] The base option target.
469
+ def add_uri_option(strategy, value, uri_options)
470
+ target = select_target(uri_options, strategy[:group])
360
471
  value = apply_transform(value, strategy[:type])
361
- merge_option(target, value, strategy[:name])
472
+ merge_uri_option(target, value, strategy[:name])
362
473
  end
363
474
 
364
475
  # Replica set transformation, avoid converting to Symbol.
@@ -367,7 +478,7 @@ module Mongo
367
478
  #
368
479
  # @return [String] Same value to avoid cast to Symbol.
369
480
  def replica_set(value)
370
- value
481
+ decode(value)
371
482
  end
372
483
 
373
484
  # Auth source transformation, either db string or :external.
@@ -377,7 +488,7 @@ module Mongo
377
488
  # @return [String] If auth source is database name.
378
489
  # @return [:external] If auth source is external authentication.
379
490
  def auth_source(value)
380
- value == '$external' ? :external : value
491
+ value == '$external' ? :external : decode(value)
381
492
  end
382
493
 
383
494
  # Authentication mechanism transformation.
@@ -451,7 +562,7 @@ module Mongo
451
562
  def hash_extractor(value)
452
563
  value.split(',').reduce({}) do |set, tag|
453
564
  k, v = tag.split(':')
454
- set.merge(k.downcase.to_sym => v)
565
+ set.merge(decode(k).downcase.to_sym => decode(v))
455
566
  end
456
567
  end
457
568
  end
data/lib/mongo/version.rb CHANGED
@@ -17,5 +17,5 @@ module Mongo
17
17
  # The current version of the driver.
18
18
  #
19
19
  # @since 2.0.0
20
- VERSION = '2.0.6'.freeze
20
+ VERSION = '2.1.0'.freeze
21
21
  end
data/lib/mongo.rb CHANGED
@@ -15,22 +15,24 @@
15
15
  require 'forwardable'
16
16
  require 'bson'
17
17
  require 'openssl'
18
+ require 'mongo/options'
18
19
  require 'mongo/loggable'
20
+ require 'mongo/monitoring'
19
21
  require 'mongo/logger'
22
+ require 'mongo/retryable'
23
+ require 'mongo/operation'
20
24
  require 'mongo/error'
21
25
  require 'mongo/event'
22
26
  require 'mongo/address'
23
27
  require 'mongo/auth'
24
- require 'mongo/bulk_write'
25
28
  require 'mongo/client'
26
29
  require 'mongo/cluster'
27
30
  require 'mongo/collection'
28
31
  require 'mongo/cursor'
29
32
  require 'mongo/database'
33
+ require 'mongo/dbref'
30
34
  require 'mongo/grid'
31
35
  require 'mongo/index'
32
- require 'mongo/operation'
33
- require 'mongo/options'
34
36
  require 'mongo/protocol'
35
37
  require 'mongo/server'
36
38
  require 'mongo/server_selector'
@@ -27,7 +27,7 @@ describe Mongo::Address::Unix do
27
27
  describe '#socket' do
28
28
 
29
29
  let(:address) do
30
- '/path/to/socket.sock'
30
+ '/tmp/mongodb-27017.sock'
31
31
  end
32
32
 
33
33
  let(:socket) do
@@ -203,4 +203,29 @@ describe Mongo::Address do
203
203
  end
204
204
  end
205
205
  end
206
+
207
+ describe "#socket" do
208
+
209
+ context 'when providing a DNS entry that resolves to both IPv6 and IPv4' do
210
+
211
+ let(:address) do
212
+ described_class.new(DEFAULT_ADDRESS)
213
+ end
214
+
215
+ let(:host) do
216
+ DEFAULT_ADDRESS.split(':').first
217
+ end
218
+
219
+ before do
220
+ allow(::Socket).to receive(:getaddrinfo).and_return(
221
+ [ ["AF_INET6", 0, '::1', '::1', ::Socket::AF_INET6, 1, 6],
222
+ ["AF_INET", 0, host, host, ::Socket::AF_INET, 1, 6]]
223
+ )
224
+ end
225
+
226
+ it "attempts to use IPv6 and fallbacks to IPv4" do
227
+ expect(address.socket(0.0)).not_to be_nil
228
+ end
229
+ end
230
+ end
206
231
  end
@@ -6,8 +6,16 @@ describe Mongo::Auth::CR do
6
6
  Mongo::Address.new(DEFAULT_ADDRESS)
7
7
  end
8
8
 
9
+ let(:monitoring) do
10
+ Mongo::Monitoring.new
11
+ end
12
+
13
+ let(:listeners) do
14
+ Mongo::Event::Listeners.new
15
+ end
16
+
9
17
  let(:server) do
10
- Mongo::Server.new(address, double('cluster'), Mongo::Event::Listeners.new, TEST_OPTIONS)
18
+ Mongo::Server.new(address, double('cluster'), monitoring, listeners, TEST_OPTIONS)
11
19
  end
12
20
 
13
21
  let(:connection) do
@@ -0,0 +1,43 @@
1
+ require 'spec_helper'
2
+
3
+ describe Mongo::Auth::LDAP::Conversation do
4
+
5
+ let(:user) do
6
+ Mongo::Auth::User.new(
7
+ database: Mongo::Database::ADMIN,
8
+ user: 'user',
9
+ password: 'pencil'
10
+ )
11
+ end
12
+
13
+ let(:conversation) do
14
+ described_class.new(user)
15
+ end
16
+
17
+ describe '#start' do
18
+
19
+ let(:query) do
20
+ conversation.start
21
+ end
22
+
23
+ let(:selector) do
24
+ query.selector
25
+ end
26
+
27
+ it 'sets the sasl start flag' do
28
+ expect(selector[:saslStart]).to eq(1)
29
+ end
30
+
31
+ it 'sets the auto authorize flag' do
32
+ expect(selector[:autoAuthorize]).to eq(1)
33
+ end
34
+
35
+ it 'sets the mechanism' do
36
+ expect(selector[:mechanism]).to eq('PLAIN')
37
+ end
38
+
39
+ it 'sets the payload' do
40
+ expect(selector[:payload].data).to eq("\x00user\x00pencil")
41
+ end
42
+ end
43
+ end