mongo 1.3.0 → 1.12.5

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 (185) hide show
  1. checksums.yaml +7 -0
  2. checksums.yaml.gz.sig +0 -0
  3. data/{LICENSE.txt → LICENSE} +1 -1
  4. data/README.md +122 -271
  5. data/Rakefile +25 -209
  6. data/VERSION +1 -0
  7. data/bin/mongo_console +31 -9
  8. data/lib/mongo/bulk_write_collection_view.rb +387 -0
  9. data/lib/mongo/collection.rb +576 -269
  10. data/lib/mongo/collection_writer.rb +364 -0
  11. data/lib/mongo/connection/node.rb +249 -0
  12. data/lib/mongo/connection/pool.rb +340 -0
  13. data/lib/mongo/connection/pool_manager.rb +320 -0
  14. data/lib/mongo/connection/sharding_pool_manager.rb +67 -0
  15. data/lib/mongo/connection/socket/socket_util.rb +37 -0
  16. data/lib/mongo/connection/socket/ssl_socket.rb +95 -0
  17. data/lib/mongo/connection/socket/tcp_socket.rb +87 -0
  18. data/lib/mongo/connection/socket/unix_socket.rb +39 -0
  19. data/lib/mongo/connection/socket.rb +18 -0
  20. data/lib/mongo/connection.rb +7 -875
  21. data/lib/mongo/cursor.rb +403 -117
  22. data/lib/mongo/db.rb +444 -243
  23. data/lib/mongo/exception.rb +145 -0
  24. data/lib/mongo/functional/authentication.rb +455 -0
  25. data/lib/mongo/functional/logging.rb +85 -0
  26. data/lib/mongo/functional/read_preference.rb +183 -0
  27. data/lib/mongo/functional/scram.rb +556 -0
  28. data/lib/mongo/functional/uri_parser.rb +409 -0
  29. data/lib/mongo/functional/write_concern.rb +66 -0
  30. data/lib/mongo/functional.rb +20 -0
  31. data/lib/mongo/gridfs/grid.rb +30 -24
  32. data/lib/mongo/gridfs/grid_ext.rb +6 -10
  33. data/lib/mongo/gridfs/grid_file_system.rb +38 -20
  34. data/lib/mongo/gridfs/grid_io.rb +84 -75
  35. data/lib/mongo/gridfs.rb +18 -0
  36. data/lib/mongo/legacy.rb +140 -0
  37. data/lib/mongo/mongo_client.rb +697 -0
  38. data/lib/mongo/mongo_replica_set_client.rb +535 -0
  39. data/lib/mongo/mongo_sharded_client.rb +159 -0
  40. data/lib/mongo/networking.rb +372 -0
  41. data/lib/mongo/{util → utils}/conversions.rb +29 -8
  42. data/lib/mongo/{util → utils}/core_ext.rb +28 -18
  43. data/lib/mongo/{util → utils}/server_version.rb +4 -6
  44. data/lib/mongo/{util → utils}/support.rb +29 -31
  45. data/lib/mongo/utils/thread_local_variable_manager.rb +25 -0
  46. data/lib/mongo/utils.rb +19 -0
  47. data/lib/mongo.rb +51 -50
  48. data/mongo.gemspec +29 -32
  49. data/test/functional/authentication_test.rb +39 -0
  50. data/test/functional/bulk_api_stress_test.rb +133 -0
  51. data/test/functional/bulk_write_collection_view_test.rb +1198 -0
  52. data/test/functional/client_test.rb +627 -0
  53. data/test/functional/collection_test.rb +2175 -0
  54. data/test/functional/collection_writer_test.rb +83 -0
  55. data/test/{conversions_test.rb → functional/conversions_test.rb} +47 -3
  56. data/test/functional/cursor_fail_test.rb +57 -0
  57. data/test/functional/cursor_message_test.rb +56 -0
  58. data/test/functional/cursor_test.rb +683 -0
  59. data/test/functional/db_api_test.rb +835 -0
  60. data/test/functional/db_connection_test.rb +25 -0
  61. data/test/functional/db_test.rb +348 -0
  62. data/test/functional/grid_file_system_test.rb +285 -0
  63. data/test/{grid_io_test.rb → functional/grid_io_test.rb} +72 -11
  64. data/test/{grid_test.rb → functional/grid_test.rb} +88 -15
  65. data/test/functional/pool_test.rb +136 -0
  66. data/test/functional/safe_test.rb +98 -0
  67. data/test/functional/ssl_test.rb +29 -0
  68. data/test/functional/support_test.rb +62 -0
  69. data/test/functional/timeout_test.rb +60 -0
  70. data/test/functional/uri_test.rb +446 -0
  71. data/test/functional/write_concern_test.rb +118 -0
  72. data/test/helpers/general.rb +50 -0
  73. data/test/helpers/test_unit.rb +476 -0
  74. data/test/replica_set/authentication_test.rb +37 -0
  75. data/test/replica_set/basic_test.rb +189 -0
  76. data/test/replica_set/client_test.rb +393 -0
  77. data/test/replica_set/connection_test.rb +138 -0
  78. data/test/replica_set/count_test.rb +66 -0
  79. data/test/replica_set/cursor_test.rb +220 -0
  80. data/test/replica_set/insert_test.rb +157 -0
  81. data/test/replica_set/max_values_test.rb +151 -0
  82. data/test/replica_set/pinning_test.rb +105 -0
  83. data/test/replica_set/query_test.rb +73 -0
  84. data/test/replica_set/read_preference_test.rb +219 -0
  85. data/test/replica_set/refresh_test.rb +211 -0
  86. data/test/replica_set/replication_ack_test.rb +95 -0
  87. data/test/replica_set/ssl_test.rb +32 -0
  88. data/test/sharded_cluster/basic_test.rb +203 -0
  89. data/test/shared/authentication/basic_auth_shared.rb +260 -0
  90. data/test/shared/authentication/bulk_api_auth_shared.rb +249 -0
  91. data/test/shared/authentication/gssapi_shared.rb +176 -0
  92. data/test/shared/authentication/sasl_plain_shared.rb +96 -0
  93. data/test/shared/authentication/scram_shared.rb +92 -0
  94. data/test/shared/ssl_shared.rb +235 -0
  95. data/test/test_helper.rb +53 -94
  96. data/test/threading/basic_test.rb +120 -0
  97. data/test/tools/mongo_config.rb +708 -0
  98. data/test/tools/mongo_config_test.rb +160 -0
  99. data/test/unit/client_test.rb +381 -0
  100. data/test/unit/collection_test.rb +89 -53
  101. data/test/unit/connection_test.rb +282 -32
  102. data/test/unit/cursor_test.rb +206 -8
  103. data/test/unit/db_test.rb +55 -13
  104. data/test/unit/grid_test.rb +43 -16
  105. data/test/unit/mongo_sharded_client_test.rb +48 -0
  106. data/test/unit/node_test.rb +93 -0
  107. data/test/unit/pool_manager_test.rb +111 -0
  108. data/test/unit/read_pref_test.rb +406 -0
  109. data/test/unit/read_test.rb +159 -0
  110. data/test/unit/safe_test.rb +69 -36
  111. data/test/unit/sharding_pool_manager_test.rb +84 -0
  112. data/test/unit/write_concern_test.rb +175 -0
  113. data.tar.gz.sig +3 -0
  114. metadata +227 -216
  115. metadata.gz.sig +0 -0
  116. data/docs/CREDITS.md +0 -123
  117. data/docs/FAQ.md +0 -116
  118. data/docs/GridFS.md +0 -158
  119. data/docs/HISTORY.md +0 -244
  120. data/docs/RELEASES.md +0 -33
  121. data/docs/REPLICA_SETS.md +0 -72
  122. data/docs/TUTORIAL.md +0 -247
  123. data/docs/WRITE_CONCERN.md +0 -28
  124. data/lib/mongo/exceptions.rb +0 -71
  125. data/lib/mongo/gridfs/grid_io_fix.rb +0 -38
  126. data/lib/mongo/repl_set_connection.rb +0 -342
  127. data/lib/mongo/test.rb +0 -20
  128. data/lib/mongo/util/pool.rb +0 -177
  129. data/lib/mongo/util/uri_parser.rb +0 -185
  130. data/test/async/collection_test.rb +0 -224
  131. data/test/async/connection_test.rb +0 -24
  132. data/test/async/cursor_test.rb +0 -162
  133. data/test/async/worker_pool_test.rb +0 -99
  134. data/test/auxillary/1.4_features.rb +0 -166
  135. data/test/auxillary/authentication_test.rb +0 -68
  136. data/test/auxillary/autoreconnect_test.rb +0 -41
  137. data/test/auxillary/fork_test.rb +0 -30
  138. data/test/auxillary/repl_set_auth_test.rb +0 -58
  139. data/test/auxillary/slave_connection_test.rb +0 -36
  140. data/test/auxillary/threaded_authentication_test.rb +0 -101
  141. data/test/bson/binary_test.rb +0 -15
  142. data/test/bson/bson_test.rb +0 -649
  143. data/test/bson/byte_buffer_test.rb +0 -208
  144. data/test/bson/hash_with_indifferent_access_test.rb +0 -38
  145. data/test/bson/json_test.rb +0 -17
  146. data/test/bson/object_id_test.rb +0 -154
  147. data/test/bson/ordered_hash_test.rb +0 -204
  148. data/test/bson/timestamp_test.rb +0 -24
  149. data/test/collection_test.rb +0 -910
  150. data/test/connection_test.rb +0 -309
  151. data/test/cursor_fail_test.rb +0 -75
  152. data/test/cursor_message_test.rb +0 -43
  153. data/test/cursor_test.rb +0 -483
  154. data/test/db_api_test.rb +0 -726
  155. data/test/db_connection_test.rb +0 -15
  156. data/test/db_test.rb +0 -287
  157. data/test/grid_file_system_test.rb +0 -243
  158. data/test/load/resque/load.rb +0 -21
  159. data/test/load/resque/processor.rb +0 -26
  160. data/test/load/thin/load.rb +0 -24
  161. data/test/load/unicorn/load.rb +0 -23
  162. data/test/load/unicorn/unicorn.rb +0 -29
  163. data/test/replica_sets/connect_test.rb +0 -94
  164. data/test/replica_sets/connection_string_test.rb +0 -32
  165. data/test/replica_sets/count_test.rb +0 -35
  166. data/test/replica_sets/insert_test.rb +0 -53
  167. data/test/replica_sets/pooled_insert_test.rb +0 -55
  168. data/test/replica_sets/query_secondaries.rb +0 -96
  169. data/test/replica_sets/query_test.rb +0 -51
  170. data/test/replica_sets/replication_ack_test.rb +0 -66
  171. data/test/replica_sets/rs_test_helper.rb +0 -27
  172. data/test/safe_test.rb +0 -68
  173. data/test/support/hash_with_indifferent_access.rb +0 -186
  174. data/test/support/keys.rb +0 -45
  175. data/test/support_test.rb +0 -18
  176. data/test/threading/threading_with_large_pool_test.rb +0 -90
  177. data/test/threading_test.rb +0 -87
  178. data/test/tools/auth_repl_set_manager.rb +0 -14
  179. data/test/tools/load.rb +0 -58
  180. data/test/tools/repl_set_manager.rb +0 -266
  181. data/test/tools/sharding_manager.rb +0 -202
  182. data/test/tools/test.rb +0 -4
  183. data/test/unit/pool_test.rb +0 -9
  184. data/test/unit/repl_set_connection_test.rb +0 -59
  185. data/test/uri_test.rb +0 -91
@@ -0,0 +1,60 @@
1
+ # Copyright (C) 2009-2013 MongoDB, Inc.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ require 'test_helper'
16
+
17
+ class TimeoutTest < Test::Unit::TestCase
18
+
19
+ def test_op_timeout
20
+ grant_admin_user_eval_role(standard_connection)
21
+ connection = standard_connection(:op_timeout => 0.5)
22
+
23
+ admin = connection.db('admin')
24
+
25
+ command = {:eval => "sleep(100)"}
26
+ # Should not timeout
27
+ assert admin.command(command)
28
+
29
+ # Should timeout
30
+ command = {:eval => "sleep(1000)"}
31
+ assert_raise Mongo::OperationTimeout do
32
+ admin.command(command)
33
+ end
34
+ end
35
+
36
+ def test_external_timeout_does_not_leave_socket_in_bad_state
37
+ client = standard_connection
38
+ db = client[TEST_DB]
39
+ coll = db['timeout-tests']
40
+ grant_admin_user_eval_role(client)
41
+
42
+ # prepare the database
43
+ coll.drop
44
+ coll.insert({:a => 1})
45
+
46
+ # use external timeout to mangle socket
47
+ begin
48
+ Timeout::timeout(0.5) do
49
+ db.command({:eval => "sleep(1000)"})
50
+ end
51
+ rescue Timeout::Error
52
+ #puts "Thread timed out and has now mangled the socket"
53
+ end
54
+
55
+ assert_nothing_raised do
56
+ coll.find_one
57
+ end
58
+ end
59
+
60
+ end
@@ -0,0 +1,446 @@
1
+ # Copyright (C) 2009-2013 MongoDB, Inc.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ require 'test_helper'
16
+
17
+ class URITest < Test::Unit::TestCase
18
+ include Mongo
19
+
20
+ def test_uri_without_port
21
+ parser = Mongo::URIParser.new('mongodb://localhost')
22
+ assert_equal 1, parser.nodes.length
23
+ assert_equal 'localhost', parser.nodes[0][0]
24
+ assert_equal 27017, parser.nodes[0][1]
25
+ end
26
+
27
+ def test_basic_uri
28
+ parser = Mongo::URIParser.new('mongodb://localhost:27018')
29
+ assert_equal 1, parser.nodes.length
30
+ assert_equal 'localhost', parser.nodes[0][0]
31
+ assert_equal 27018, parser.nodes[0][1]
32
+ end
33
+
34
+ def test_unix_socket
35
+ parser = Mongo::URIParser.new('mongodb:///tmp/mongod.sock')
36
+ assert_equal 1, parser.nodes.length
37
+ assert_equal '/tmp/mongod.sock', parser.nodes[0][0]
38
+ end
39
+
40
+ def test_unix_socket_with_user
41
+ parser = Mongo::URIParser.new('mongodb://bob:secret.word@/tmp/mongod.sock')
42
+ assert_equal 1, parser.nodes.length
43
+ assert_equal '/tmp/mongod.sock', parser.nodes[0][0]
44
+ assert_equal "bob", parser.auths.first[:username]
45
+ assert_equal "secret.word", parser.auths.first[:password]
46
+ assert_equal 'admin', parser.auths.first[:source]
47
+ end
48
+
49
+ def test_unix_socket_with_db
50
+ parser = Mongo::URIParser.new('mongodb://bob:secret.word@/tmp/mongod.sock/some_db')
51
+ assert_equal 1, parser.nodes.length
52
+ assert_equal '/tmp/mongod.sock', parser.nodes[0][0]
53
+ assert_equal 'bob', parser.auths.first[:username]
54
+ assert_equal 'secret.word', parser.auths.first[:password]
55
+ assert_equal 'some_db', parser.auths.first[:source]
56
+ end
57
+
58
+ def test_ipv6_format
59
+ parser = Mongo::URIParser.new('mongodb://[::1]:27018')
60
+ assert_equal 1, parser.nodes.length
61
+ assert_equal '::1', parser.nodes[0][0]
62
+ assert_equal 27018, parser.nodes[0][1]
63
+
64
+ parser = Mongo::URIParser.new('mongodb://[::1]')
65
+ assert_equal 1, parser.nodes.length
66
+ assert_equal '::1', parser.nodes[0][0]
67
+ end
68
+
69
+ def test_ipv6_format_multi
70
+ parser = Mongo::URIParser.new('mongodb://[::1]:27017,[::1]:27018')
71
+ assert_equal 2, parser.nodes.length
72
+ assert_equal '::1', parser.nodes[0][0]
73
+ assert_equal 27017, parser.nodes[0][1]
74
+ assert_equal '::1', parser.nodes[1][0]
75
+ assert_equal 27018, parser.nodes[1][1]
76
+
77
+ parser = Mongo::URIParser.new('mongodb://[::1]:27017,localhost:27018')
78
+ assert_equal 2, parser.nodes.length
79
+ assert_equal '::1', parser.nodes[0][0]
80
+ assert_equal 27017, parser.nodes[0][1]
81
+ assert_equal 'localhost', parser.nodes[1][0]
82
+ assert_equal 27018, parser.nodes[1][1]
83
+
84
+ parser = Mongo::URIParser.new('mongodb://localhost:27017,[::1]:27018')
85
+ assert_equal 2, parser.nodes.length
86
+ assert_equal 'localhost', parser.nodes[0][0]
87
+ assert_equal 27017, parser.nodes[0][1]
88
+ assert_equal '::1', parser.nodes[1][0]
89
+ assert_equal 27018, parser.nodes[1][1]
90
+ end
91
+
92
+ def test_multiple_uris
93
+ parser = Mongo::URIParser.new('mongodb://a.example.com:27018,b.example.com')
94
+ assert_equal 2, parser.nodes.length
95
+ assert_equal ['a.example.com', 27018], parser.nodes[0]
96
+ assert_equal ['b.example.com', 27017], parser.nodes[1]
97
+ end
98
+
99
+ def test_username_without_password
100
+ parser = Mongo::URIParser.new('mongodb://bob:@localhost?authMechanism=GSSAPI')
101
+ assert_equal "bob", parser.auths.first[:username]
102
+ assert_equal nil, parser.auths.first[:password]
103
+
104
+ parser = Mongo::URIParser.new('mongodb://bob@localhost?authMechanism=GSSAPI')
105
+ assert_equal nil, parser.auths.first[:password]
106
+
107
+ assert_raise_error MongoArgumentError do
108
+ Mongo::URIParser.new('mongodb://bob:@localhost')
109
+ end
110
+
111
+ assert_raise_error MongoArgumentError do
112
+ Mongo::URIParser.new('mongodb://bob@localhost')
113
+ end
114
+ end
115
+
116
+ def test_username_without_password_unix_socket
117
+ parser = Mongo::URIParser.new('mongodb://bob:@/tmp/mongod.sock?authMechanism=GSSAPI')
118
+ assert_equal "bob", parser.auths.first[:username]
119
+ assert_equal nil, parser.auths.first[:password]
120
+
121
+ parser = Mongo::URIParser.new('mongodb://bob@/tmp/mongod.sock?authMechanism=GSSAPI')
122
+ assert_equal nil, parser.auths.first[:password]
123
+
124
+ assert_raise_error MongoArgumentError do
125
+ Mongo::URIParser.new('mongodb://bob:@/tmp/mongod.sock')
126
+ end
127
+
128
+ assert_raise_error MongoArgumentError do
129
+ Mongo::URIParser.new('mongodb://bob@/tmp/mongod.sock')
130
+ end
131
+ end
132
+
133
+ def test_complex_passwords
134
+ parser = Mongo::URIParser.new('mongodb://bob:secret.word@a.example.com:27018/test')
135
+ assert_equal "bob", parser.auths.first[:username]
136
+ assert_equal "secret.word", parser.auths.first[:password]
137
+
138
+ parser = Mongo::URIParser.new('mongodb://bob:s-_3#%R.t@a.example.com:27018/test')
139
+ assert_equal "bob", parser.auths.first[:username]
140
+ assert_equal "s-_3#%R.t", parser.auths.first[:password]
141
+
142
+ assert_raise_error MongoArgumentError do
143
+ Mongo::URIParser.new('mongodb://doctor:bad:wolf@gallifrey.com:27018/test')
144
+ end
145
+
146
+ assert_raise_error MongoArgumentError do
147
+ Mongo::URIParser.new('mongodb://doctor:bow@tie@gallifrey.com:27018/test')
148
+ end
149
+ end
150
+
151
+ def test_complex_usernames
152
+ parser = Mongo::URIParser.new('mongodb://s-_3#%R.t:secret.word@a.example.com:27018/test')
153
+ assert_equal "s-_3#%R.t", parser.auths.first[:username]
154
+
155
+ assert_raise_error MongoArgumentError do
156
+ Mongo::URIParser.new('mongodb://doc:tor:badwolf@gallifrey.com:27018/test')
157
+ end
158
+
159
+ assert_raise_error MongoArgumentError do
160
+ Mongo::URIParser.new('mongodb://d@ctor:bowtie@gallifrey.com:27018/test')
161
+ end
162
+ end
163
+
164
+ def test_username_with_encoded_symbol
165
+ parser = Mongo::URIParser.new('mongodb://f%40o:bar@localhost/admin')
166
+ username = parser.auths.first[:username]
167
+ assert_equal 'f@o', username
168
+
169
+ parser = Mongo::URIParser.new('mongodb://f%3Ao:bar@localhost/admin')
170
+ username = parser.auths.first[:username]
171
+ assert_equal 'f:o', username
172
+ end
173
+
174
+ def test_password_with_encoded_symbol
175
+ parser = Mongo::URIParser.new('mongodb://foo:b%40r@localhost/admin')
176
+ password = parser.auths.first[:password]
177
+ assert_equal 'b@r', password
178
+
179
+ parser = Mongo::URIParser.new('mongodb://foo:b%3Ar@localhost/admin')
180
+ password = parser.auths.first[:password]
181
+ assert_equal 'b:r', password
182
+ end
183
+
184
+ def test_opts_with_semincolon_separator
185
+ parser = Mongo::URIParser.new('mongodb://localhost:27018?connect=direct;slaveok=true;safe=true')
186
+ assert_equal 'direct', parser.connect
187
+ assert parser.direct?
188
+ assert parser.slaveok
189
+ assert parser.safe
190
+ end
191
+
192
+ def test_opts_with_amp_separator
193
+ parser = Mongo::URIParser.new('mongodb://localhost:27018?connect=direct&slaveok=true&safe=true')
194
+ assert_equal 'direct', parser.connect
195
+ assert parser.direct?
196
+ assert parser.slaveok
197
+ assert parser.safe
198
+ end
199
+
200
+ def test_opts_with_uri_encoded_stuff
201
+ parser = Mongo::URIParser.new('mongodb://localhost:27018?connect=%64%69%72%65%63%74&slaveok=%74%72%75%65&safe=true')
202
+ assert_equal 'direct', parser.connect
203
+ assert parser.direct?
204
+ assert parser.slaveok
205
+ assert parser.safe
206
+ end
207
+
208
+ def test_opts_made_invalid_by_mixed_separators
209
+ assert_raise_error MongoArgumentError, "must not mix URL separators ; and &" do
210
+ Mongo::URIParser.new('mongodb://localhost:27018?replicaset=foo;bar&slaveok=true&safe=true')
211
+ end
212
+ end
213
+
214
+ def test_opts_safe
215
+ parser = Mongo::URIParser.new('mongodb://localhost:27018?safe=true;w=2;journal=true;fsync=true;wtimeoutMS=200')
216
+ assert parser.safe
217
+ assert_equal 2, parser.w
218
+ assert parser.fsync
219
+ assert parser.journal
220
+ assert_equal 200, parser.wtimeoutms
221
+ end
222
+
223
+ def test_opts_ssl
224
+ parser = Mongo::URIParser.new('mongodb://localhost:27018?ssl=true;w=2;journal=true;fsync=true;wtimeoutMS=200')
225
+ assert parser.ssl
226
+ end
227
+
228
+ def test_opts_nonsafe_timeout
229
+ parser = Mongo::URIParser.new('mongodb://localhost:27018?connectTimeoutMS=5500&socketTimeoutMS=500')
230
+ assert_equal 5.5, parser.connecttimeoutms
231
+ assert_equal 0.5, parser.sockettimeoutms
232
+ end
233
+
234
+ def test_opts_replica_set
235
+ parser = Mongo::URIParser.new('mongodb://localhost:27018?connect=replicaset;replicaset=foo')
236
+ assert_equal 'foo', parser.replicaset
237
+ assert_equal 'replicaset', parser.connect
238
+ assert parser.replicaset?
239
+ end
240
+
241
+ def test_opts_conflicting_replica_set
242
+ assert_raise_error MongoArgumentError, "connect=direct conflicts with setting a replicaset name" do
243
+ Mongo::URIParser.new('mongodb://localhost:27018?connect=direct;replicaset=foo')
244
+ end
245
+ end
246
+
247
+ def test_case_insensitivity
248
+ parser = Mongo::URIParser.new('mongodb://localhost:27018?wtimeoutms=500&JOURNAL=true&SaFe=true')
249
+ assert_equal 500, parser.wtimeoutms
250
+ assert_equal true, parser.journal
251
+ assert_equal true, parser.safe
252
+ end
253
+
254
+ def test_read_preference_option_primary
255
+ parser = Mongo::URIParser.new("mongodb://localhost:27018?readPreference=primary")
256
+ assert_equal :primary, parser.readpreference
257
+ end
258
+
259
+ def test_read_preference_option_primary_unix_sock
260
+ parser = Mongo::URIParser.new("mongodb:///tmp/mongod.sock?readPreference=primary")
261
+ assert_equal :primary, parser.readpreference
262
+ end
263
+
264
+ def test_read_preference_option_primary_preferred
265
+ parser = Mongo::URIParser.new("mongodb://localhost:27018?readPreference=primaryPreferred")
266
+ assert_equal :primary_preferred, parser.readpreference
267
+ end
268
+
269
+ def test_read_preference_option_secondary
270
+ parser = Mongo::URIParser.new("mongodb://localhost:27018?readPreference=secondary")
271
+ assert_equal :secondary, parser.readpreference
272
+ end
273
+
274
+ def test_read_preference_option_secondary_preferred
275
+ parser = Mongo::URIParser.new("mongodb://localhost:27018?readPreference=secondaryPreferred")
276
+ assert_equal :secondary_preferred, parser.readpreference
277
+ end
278
+
279
+ def test_read_preference_option_nearest
280
+ parser = Mongo::URIParser.new("mongodb://localhost:27018?readPreference=nearest")
281
+ assert_equal :nearest, parser.readpreference
282
+ end
283
+
284
+ def test_read_preference_option_with_invalid
285
+ assert_raise_error MongoArgumentError do
286
+ Mongo::URIParser.new("mongodb://localhost:27018?readPreference=invalid")
287
+ end
288
+ end
289
+
290
+ def test_read_preference_connection_options
291
+ parser = Mongo::URIParser.new("mongodb://localhost:27018?replicaset=test&readPreference=nearest")
292
+ assert_equal :nearest, parser.connection_options[:read]
293
+ end
294
+
295
+ def test_read_preference_connection_options_with_no_replica_set
296
+ parser = Mongo::URIParser.new("mongodb://localhost:27018?readPreference=nearest")
297
+ assert_equal :nearest, parser.connection_options[:read]
298
+ end
299
+
300
+ def test_read_preference_connection_options_prefers_preference_over_slaveok
301
+ parser = Mongo::URIParser.new("mongodb://localhost:27018?replicaset=test&readPreference=nearest&slaveok=true")
302
+ assert_equal :nearest, parser.connection_options[:read]
303
+ end
304
+
305
+ def test_read_preference_tags
306
+ parser = Mongo::URIParser.new("mongodb://localhost:27017?replicaset=test&" +
307
+ "readPreferenceTags=dc:ny,rack:1")
308
+ expected_tags = [{ 'dc' => 'ny', 'rack' => '1' }]
309
+ assert_equal expected_tags, parser.connection_options[:tag_sets]
310
+ end
311
+
312
+ def test_read_preference_tags_multiple
313
+ parser = Mongo::URIParser.new("mongodb://localhost:27017?replicaset=test&" +
314
+ "readPreferenceTags=dc:ny,rack:1&readPreferenceTags=dc:bos")
315
+ expected_tags = [{'dc' => 'ny', 'rack' => '1'}, { 'dc' => 'bos' }]
316
+ assert_equal expected_tags, parser.connection_options[:tag_sets]
317
+ end
318
+
319
+ def test_invalid_read_preference_tags
320
+ assert_raise_error MongoArgumentError do
321
+ Mongo::URIParser.new("mongodb://localhost:27017?replicaset=test&" +
322
+ "readPreferenceTags=dc")
323
+ end
324
+ end
325
+
326
+ def test_invalid_read_preference_tags_multiple
327
+ assert_raise_error MongoArgumentError do
328
+ Mongo::URIParser.new("mongodb://localhost:27017?replicaset=test&" +
329
+ "readPreferenceTags=dc:nyc&readPreferenceTags=dc")
330
+ end
331
+ end
332
+
333
+ def test_connection_when_sharded_with_no_options
334
+ parser = Mongo::URIParser.new("mongodb://localhost:27017,localhost:27018")
335
+ client = parser.connection({}, false, true)
336
+ assert_equal [[ "localhost", 27017 ], [ "localhost", 27018 ]], client.seeds
337
+ assert_true client.mongos?
338
+ end
339
+
340
+ def test_connection_when_sharded_with_options
341
+ parser = Mongo::URIParser.new("mongodb://localhost:27017,localhost:27018")
342
+ client = parser.connection({ :refresh_interval => 10 }, false, true)
343
+ assert_equal [[ "localhost", 27017 ], [ "localhost", 27018 ]], client.seeds
344
+ assert_equal 10, client.refresh_interval
345
+ assert_true client.mongos?
346
+ end
347
+
348
+ def test_connection_when_sharded_with_uri_options
349
+ parser = Mongo::URIParser.new("mongodb://localhost:27017,localhost:27018?readPreference=nearest")
350
+ client = parser.connection({}, false, true)
351
+ assert_equal [[ "localhost", 27017 ], [ "localhost", 27018 ]], client.seeds
352
+ assert_equal :nearest, client.read
353
+ assert_true client.mongos?
354
+ end
355
+
356
+ def test_auth_source
357
+ parser = Mongo::URIParser.new("mongodb://user:pass@localhost?authSource=foobar")
358
+ assert_equal 'foobar', parser.authsource
359
+ end
360
+
361
+ def test_auth_mechanism
362
+ parser = Mongo::URIParser.new("mongodb://user@localhost?authMechanism=MONGODB-X509")
363
+ assert_equal 'MONGODB-X509', parser.authmechanism
364
+
365
+ assert_raise_error MongoArgumentError do
366
+ Mongo::URIParser.new("mongodb://user@localhost?authMechanism=INVALID")
367
+ end
368
+ end
369
+
370
+ def test_auth_mechanism_properties
371
+ uri = "mongodb://user@localhost?authMechanism=GSSAPI&authMechanismProperties=SERVICE_NAME" +
372
+ ":mongodb,CANONICALIZE_HOST_NAME:true"
373
+ parser = Mongo::URIParser.new(uri)
374
+ properties = {:service_name => "mongodb", :canonicalize_host_name => true}
375
+ assert_equal properties, parser.authmechanismproperties
376
+ assert_equal 'GSSAPI', parser.authmechanism
377
+
378
+ uri = "mongodb://user@localhost?authMechanism=GSSAPI&authMechanismProperties=SERVICE_NAME" +
379
+ ":MongoDB,CANONICALIZE_HOST_NAME:false,SERVICE_REALM:test"
380
+ parser = Mongo::URIParser.new(uri)
381
+ properties = {:service_name => "MongoDB", :canonicalize_host_name => false, :service_realm => "test"}
382
+ assert_equal properties, parser.authmechanismproperties
383
+ assert_equal 'GSSAPI', parser.authmechanism
384
+ end
385
+
386
+ def test_invalid_auth_mechanism_properties
387
+ uri = "mongodb://user@localhost?authMechanism=GSSAPI&authMechanismProperties=SERVICE_NAME" +
388
+ ":mongodb,INVALID_PROPERTY:true"
389
+ assert_raise_error MongoArgumentError do
390
+ parser = Mongo::URIParser.new(uri)
391
+ end
392
+
393
+ uri = "mongodb://user@localhost?authMechanism=PLAIN&authMechanismProperties="+
394
+ "SERVICE_NAME:mongodb"
395
+ assert_raise_error MongoArgumentError do
396
+ parser = Mongo::URIParser.new(uri)
397
+ end
398
+ end
399
+
400
+ def test_sasl_plain
401
+ parser = Mongo::URIParser.new("mongodb://user:pass@localhost?authMechanism=PLAIN")
402
+ assert_equal 'PLAIN', parser.auths.first[:mechanism]
403
+ assert_equal 'user', parser.auths.first[:username]
404
+ assert_equal 'pass', parser.auths.first[:password]
405
+ assert_equal 'admin', parser.auths.first[:source]
406
+
407
+ parser = Mongo::URIParser.new("mongodb://foo%2Fbar%40example.net:pass@localhost/some_db?authMechanism=PLAIN")
408
+ assert_equal 'PLAIN', parser.auths.first[:mechanism]
409
+ assert_equal 'foo/bar@example.net', parser.auths.first[:username]
410
+ assert_equal 'pass', parser.auths.first[:password]
411
+ assert_equal 'some_db', parser.auths.first[:source]
412
+
413
+ assert_raise_error MongoArgumentError do
414
+ Mongo::URIParser.new("mongodb://user@localhost/some_db?authMechanism=PLAIN")
415
+ end
416
+ end
417
+
418
+ def test_gssapi
419
+ uri = "mongodb://foo%2Fbar%40example.net@localhost?authMechanism=GSSAPI;"
420
+ parser = Mongo::URIParser.new(uri)
421
+ assert_equal 'GSSAPI', parser.auths.first[:mechanism]
422
+ assert_equal 'foo/bar@example.net', parser.auths.first[:username]
423
+
424
+
425
+ uri = "mongodb://foo%2Fbar%40example.net@localhost?authMechanism=GSSAPI;" +
426
+ "authMechanismProperties=SERVICE_NAME:mongodb,SERVICE_REALM:example," +
427
+ "CANONICALIZE_HOST_NAME:true"
428
+ parser = Mongo::URIParser.new(uri)
429
+ assert_equal 'GSSAPI', parser.auths.first[:mechanism]
430
+ assert_equal 'foo/bar@example.net', parser.auths.first[:username]
431
+ assert_equal 'mongodb', parser.auths.first[:extra][:service_name]
432
+ assert_equal true, parser.auths.first[:extra][:canonicalize_host_name]
433
+ assert_equal 'example', parser.auths.first[:extra][:service_realm]
434
+ end
435
+
436
+ def test_opts_case_sensitivity
437
+ # options authsource, replicaset, w should be case sensitive
438
+ uri = "mongodb://localhost?authSource=FooBar;" +
439
+ "replicaSet=Foo;" +
440
+ "w=Majority"
441
+ parser = Mongo::URIParser.new(uri)
442
+ assert_equal 'FooBar', parser.authsource
443
+ assert_equal 'Foo', parser.replicaset
444
+ assert_equal :Majority, parser.w
445
+ end
446
+ end
@@ -0,0 +1,118 @@
1
+ # Copyright (C) 2009-2013 MongoDB, Inc.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ require 'test_helper'
16
+ include Mongo
17
+
18
+ class WriteConcernTest < Test::Unit::TestCase
19
+ context "Write concern propogation: " do
20
+ setup do
21
+ @con = standard_connection
22
+ @db = @con[TEST_DB]
23
+ @col = @db['test-safe']
24
+ @col.create_index([[:a, 1]], :unique => true)
25
+ @col.remove
26
+ end
27
+
28
+ #TODO: add write concern tests for remove
29
+
30
+ should "propogate write concern options on insert" do
31
+ @col.insert({:a => 1})
32
+
33
+ assert_raise_error(OperationFailure, "duplicate key") do
34
+ @col.insert({:a => 1})
35
+ end
36
+ end
37
+
38
+ should "allow write concern override on insert" do
39
+ @col.insert({:a => 1})
40
+ @col.insert({:a => 1}, :w => 0)
41
+ end
42
+
43
+ should "propogate write concern option on update" do
44
+ @col.insert({:a => 1})
45
+ @col.insert({:a => 2})
46
+
47
+ assert_raise_error(OperationFailure, "duplicate key") do
48
+ @col.update({:a => 2}, {:a => 1})
49
+ end
50
+ end
51
+
52
+ should "allow write concern override on update" do
53
+ @col.insert({:a => 1})
54
+ @col.insert({:a => 2})
55
+ @col.update({:a => 2}, {:a => 1}, :w => 0)
56
+ end
57
+ end
58
+
59
+ context "Write concern error objects" do
60
+ setup do
61
+ @con = standard_connection
62
+ @db = @con[TEST_DB]
63
+ @col = @db['test']
64
+ @col.remove
65
+ @col.insert({:a => 1})
66
+ @col.insert({:a => 1})
67
+ @col.insert({:a => 1})
68
+ end
69
+
70
+ should "return object on update" do
71
+ response = @col.update({:a => 1}, {"$set" => {:a => 2}},
72
+ :multi => true)
73
+
74
+ assert(response['updatedExisting'] || @db.connection.wire_version_feature?(Mongo::MongoClient::BATCH_COMMANDS)) # TODO - review new write command return values
75
+ assert(response['n'] == 3 || @db.connection.wire_version_feature?(Mongo::MongoClient::BATCH_COMMANDS)) # TODO - update command top pending
76
+ end
77
+
78
+ should "return object on remove" do
79
+ response = @col.remove({})
80
+ assert_equal 3, response['n']
81
+ end
82
+ end
83
+
84
+ context "Write concern in gridfs" do
85
+ setup do
86
+ @db = standard_connection.db(TEST_DB)
87
+ @grid = Mongo::GridFileSystem.new(@db)
88
+ @filename = 'sample'
89
+ end
90
+
91
+ teardown do
92
+ @grid.delete(@filename)
93
+ end
94
+
95
+ should "should acknowledge writes by default using md5" do
96
+ file = @grid.open(@filename, 'w')
97
+ file.write "Hello world!"
98
+ file.close
99
+ assert_equal file.client_md5, file.server_md5
100
+ end
101
+
102
+ should "should allow for unacknowledged writes" do
103
+ file = @grid.open(@filename, 'w', {:w => 0} )
104
+ file.write "Hello world!"
105
+ file.close
106
+ assert_nil file.client_md5, file.server_md5
107
+ end
108
+
109
+ should "should support legacy write concern api" do
110
+ file = @grid.open(@filename, 'w', {:safe => false} )
111
+ file.write "Hello world!"
112
+ file.close
113
+ assert_nil file.client_md5, file.server_md5
114
+ end
115
+
116
+ end
117
+
118
+ end
@@ -0,0 +1,50 @@
1
+ # Copyright (C) 2009-2013 MongoDB, Inc.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ # Redirects output while yielding a given block of code.
16
+ #
17
+ # @return [Object] The result of the block.
18
+ def silently
19
+ warn_level = $VERBOSE
20
+ $VERBOSE = nil
21
+ begin
22
+ result = yield
23
+ ensure
24
+ $VERBOSE = warn_level
25
+ end
26
+ result
27
+ end
28
+
29
+ class Hash
30
+ def stringify_keys
31
+ dup.stringify_keys!
32
+ end
33
+
34
+ def stringify_keys!
35
+ keys.each do |key|
36
+ self[key.to_s] = delete(key)
37
+ end
38
+ self
39
+ end
40
+
41
+ def except(*keys)
42
+ dup.except!(*keys)
43
+ end
44
+
45
+ # Replaces the hash without the given keys.
46
+ def except!(*keys)
47
+ keys.each { |key| delete(key) }
48
+ self
49
+ end
50
+ end