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,627 @@
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
+ require 'logger'
17
+
18
+ class ClientTest < Test::Unit::TestCase
19
+
20
+ include Mongo
21
+ include BSON
22
+
23
+ def setup
24
+ @client = standard_connection
25
+ end
26
+
27
+ def teardown
28
+ @client.close
29
+ end
30
+
31
+ def test_connection_failure
32
+ assert_raise Mongo::ConnectionFailure do
33
+ MongoClient.new('localhost', 27347)
34
+ end
35
+ end
36
+
37
+ def test_host_port_accessors
38
+ assert_equal @client.host, TEST_HOST
39
+ assert_equal @client.port, TEST_PORT
40
+ end
41
+
42
+ def test_server_info
43
+ server_info = @client.server_info
44
+ assert server_info.keys.include?("version")
45
+ assert Mongo::Support.ok?(server_info)
46
+ end
47
+
48
+ def test_ping
49
+ ping = @client.ping
50
+ assert ping['ok']
51
+ end
52
+
53
+ def test_ipv6
54
+ with_ipv6_enabled(@client) do
55
+ assert client = MongoClient.new('[::1]')
56
+ end
57
+ end
58
+
59
+ def test_ipv6_uri_no_opts
60
+ with_ipv6_enabled(@client) do
61
+ uri = 'mongodb://[::1]:27017'
62
+ with_preserved_env_uri(uri) do
63
+ assert MongoClient.new
64
+ end
65
+ end
66
+ end
67
+
68
+ def test_ipv6_uri_opts
69
+ with_ipv6_enabled(@client) do
70
+ uri = 'mongodb://[::1]:27017/?slaveOk=true'
71
+ with_preserved_env_uri(uri) do
72
+ assert MongoClient.new
73
+ end
74
+ end
75
+ end
76
+
77
+ def test_unix_sock
78
+ # There's an issue with unix sockets on JRuby with 32-bit libc
79
+ # https://jira.codehaus.org/browse/JRUBY-7183
80
+ return if RUBY_PLATFORM =~ /java/
81
+ begin
82
+ assert MongoClient.new("/tmp/mongodb-#{TEST_PORT}.sock")
83
+ rescue Errno::EAFNOSUPPORT
84
+ # System doesn't support UNIX sockets
85
+ end
86
+ end
87
+
88
+ def test_initialize_with_auths
89
+ auth = { :username => TEST_USER,
90
+ :password => TEST_USER_PWD,
91
+ :db_name => TEST_DB,
92
+ :source => TEST_DB}
93
+
94
+ client = MongoClient.new(:auths => Set.new([auth]))
95
+ assert client['test']['test'].find.to_a
96
+ end
97
+
98
+ def test_connection_uri
99
+ con = MongoClient.from_uri("mongodb://#{host_port}")
100
+ assert_equal mongo_host, con.primary_pool.host
101
+ assert_equal mongo_port, con.primary_pool.port
102
+ end
103
+
104
+ def test_uri_with_extra_opts
105
+ con = MongoClient.from_uri("mongodb://#{host_port}", :pool_size => 10, :slave_ok => true)
106
+ assert_equal 10, con.pool_size
107
+ assert con.slave_ok?
108
+ end
109
+
110
+ def test_env_mongodb_uri
111
+ uri = "mongodb://#{host_port}"
112
+ with_preserved_env_uri(uri) do
113
+ con = MongoClient.new
114
+ assert_equal mongo_host, con.primary_pool.host
115
+ assert_equal mongo_port, con.primary_pool.port
116
+ end
117
+ end
118
+
119
+ def test_from_uri_implicit_mongodb_uri
120
+ uri = "mongodb://#{host_port}"
121
+ with_preserved_env_uri(uri) do
122
+ con = MongoClient.from_uri
123
+ assert_equal mongo_host, con.primary_pool.host
124
+ assert_equal mongo_port, con.primary_pool.port
125
+ end
126
+ end
127
+
128
+ def test_db_from_uri_exists_no_options
129
+ db_name = "_database"
130
+ uri = "mongodb://#{host_port}/#{db_name}"
131
+ with_preserved_env_uri(uri) do
132
+ con = MongoClient.from_uri
133
+ db = con.db
134
+ assert_equal db.name, db_name
135
+ end
136
+ end
137
+
138
+ def test_db_from_uri_exists_options
139
+ db_name = "_database"
140
+ uri = "mongodb://#{host_port}/#{db_name}?"
141
+ with_preserved_env_uri(uri) do
142
+ con = MongoClient.from_uri
143
+ db = con.db
144
+ assert_equal db.name, db_name
145
+ end
146
+ end
147
+
148
+ def test_db_from_uri_exists_no_db_name
149
+ uri = "mongodb://#{host_port}/"
150
+ with_preserved_env_uri(uri) do
151
+ con = MongoClient.from_uri
152
+ db = con.db
153
+ assert_equal db.name, MongoClient::DEFAULT_DB_NAME
154
+ end
155
+ end
156
+
157
+ def test_db_from_uri_from_string_param
158
+ db_name = "_database"
159
+ db = MongoClient.from_uri("mongodb://#{host_port}/#{db_name}").db
160
+ assert_equal db.name, db_name
161
+ end
162
+
163
+ def test_db_from_uri_from_string_param_no_db_name
164
+ db = MongoClient.from_uri("mongodb://#{host_port}").db
165
+ assert_equal db.name, MongoClient::DEFAULT_DB_NAME
166
+ end
167
+
168
+ def test_from_uri_write_concern
169
+ con = MongoClient.from_uri(TEST_URI)
170
+ db = con.db
171
+ coll = db.collection('from-uri-test')
172
+ assert_equal BSON::ObjectId, coll.insert({'a' => 1}).class
173
+ [con, db, coll].each do |component|
174
+ component.write_concern.each do |key,value|
175
+ assert_not_nil(value, "component #{component.class.inspect} should not have write concern #{key.inspect} field with nil value")
176
+ end
177
+ end
178
+ assert_equal({:w => 1}, con.write_concern, "write concern should not have extra pairs that were not specified by the user")
179
+ assert_equal({:w => 1}, db.write_concern, "write concern should not have extra pairs that were not specified by the user")
180
+ assert_equal({:w => 1}, coll.write_concern, "write concern should not have extra pairs that were not specified by the user")
181
+ end
182
+
183
+ def test_server_version
184
+ assert_match(/\d\.\d+(\.\d+)?/, @client.server_version.to_s)
185
+ end
186
+
187
+ def test_invalid_database_names
188
+ assert_raise TypeError do @client.db(4) end
189
+
190
+ assert_raise Mongo::InvalidNSName do @client.db('') end
191
+ assert_raise Mongo::InvalidNSName do @client.db('te$t') end
192
+ assert_raise Mongo::InvalidNSName do @client.db('te.t') end
193
+ assert_raise Mongo::InvalidNSName do @client.db('te\\t') end
194
+ assert_raise Mongo::InvalidNSName do @client.db('te/t') end
195
+ assert_raise Mongo::InvalidNSName do @client.db('te st') end
196
+ end
197
+
198
+ def test_options_passed_to_db
199
+ @pk_mock = Object.new
200
+ db = @client.db('test', :pk => @pk_mock, :strict => true)
201
+ assert_equal @pk_mock, db.pk_factory
202
+ assert db.strict?
203
+ end
204
+
205
+ def test_database_info
206
+ db_name = 'ruby_test'
207
+ @client.drop_database(db_name)
208
+ @client.db(db_name).collection('info-test').insert('a' => 1)
209
+
210
+ info = @client.database_info
211
+ assert_not_nil info
212
+ assert_kind_of Hash, info
213
+ assert_not_nil info[db_name]
214
+ assert info[db_name] > 0
215
+
216
+ @client.drop_database(db_name)
217
+ end
218
+
219
+ def test_copy_database
220
+ return unless @client.server_version >= '2.5' ||
221
+ @client.server_version < '2.4'
222
+ old_db = @client['ruby-test-old']
223
+ new_db = @client['ruby-test-new']
224
+ coll = 'copy-test'
225
+
226
+ old_db[coll].insert('a' => 1)
227
+ @client.drop_database(new_db.name)
228
+ silently { old_db.add_user('chevy', 'chase') }
229
+ @client.copy_database(old_db.name, new_db.name, host_port, 'chevy', 'chase')
230
+ old_db.remove_user('chevy')
231
+ assert_equal old_db[coll].find_one, new_db[coll].find_one
232
+ end
233
+
234
+ def test_database_names
235
+ @client.db(TEST_DB).collection('info-test').remove({})
236
+ @client.db(TEST_DB).collection('info-test').insert('a' => 1)
237
+
238
+ names = @client.database_names
239
+ assert_not_nil names
240
+ assert_kind_of Array, names
241
+ assert names.length >= 1
242
+ assert names.include?(TEST_DB)
243
+ end
244
+
245
+ def test_logging
246
+ output = StringIO.new
247
+ logger = Logger.new(output)
248
+ logger.level = Logger::DEBUG
249
+ standard_connection(:logger => logger).db(TEST_DB)
250
+ assert output.string.include?("admin['$cmd'].find")
251
+ end
252
+
253
+ def test_logging_duration
254
+ output = StringIO.new
255
+ logger = Logger.new(output)
256
+ logger.level = Logger::DEBUG
257
+ standard_connection(:logger => logger).db(TEST_DB)
258
+ assert_match(/\(\d+.\d{1}ms\)/, output.string)
259
+ assert output.string.include?("admin['$cmd'].find")
260
+ end
261
+
262
+ def test_connection_logger
263
+ output = StringIO.new
264
+ logger = Logger.new(output)
265
+ logger.level = Logger::DEBUG
266
+ connection = standard_connection(:logger => logger)
267
+ assert_equal logger, connection.logger
268
+
269
+ connection.logger.debug 'testing'
270
+ assert output.string.include?('testing')
271
+ end
272
+
273
+ def test_drop_database
274
+ db = @client.db(TEST_DB + '_drop_test')
275
+ coll = db.collection('temp')
276
+ coll.remove
277
+ coll.insert(:name => 'temp')
278
+ assert_equal 1, coll.count()
279
+ assert @client.database_names.include?(TEST_DB + '_drop_test')
280
+
281
+ @client.drop_database(TEST_DB + '_drop_test')
282
+ assert !@client.database_names.include?(TEST_DB + '_drop_test')
283
+ end
284
+
285
+ def test_nodes
286
+ silently do
287
+ @client = MongoClient.multi([['foo', 27017], ['bar', 27018]], :connect => false)
288
+ end
289
+ seeds = @client.seeds
290
+ assert_equal 2, seeds.length
291
+ assert_equal ['foo', 27017], seeds[0]
292
+ assert_equal ['bar', 27018], seeds[1]
293
+ end
294
+
295
+ def test_fsync_lock
296
+ assert !@client.locked?
297
+ @client.lock!
298
+ assert @client.locked?
299
+ assert [1, true].include?(@client['admin']['$cmd.sys.inprog'].find_one['fsyncLock'])
300
+ assert_match(/unlock/, @client.unlock!['info'])
301
+ unlocked = false
302
+ counter = 0
303
+ while counter < 100
304
+ if @client['admin']['$cmd.sys.inprog'].find_one['fsyncLock'].nil?
305
+ unlocked = true
306
+ break
307
+ else
308
+ counter += 1
309
+ end
310
+ end
311
+ assert !@client.locked?
312
+ assert unlocked, "mongod failed to unlock"
313
+ end
314
+
315
+ def test_max_bson_size_value
316
+ conn = standard_connection(:connect => false)
317
+
318
+ admin_db = Object.new
319
+ admin_db.expects(:command).returns({'ok' => 1, 'ismaster' => 1, 'maxBsonObjectSize' => 15_000_000})
320
+ conn.expects(:[]).with('admin').returns(admin_db)
321
+ conn.connect
322
+ assert_equal 15_000_000, conn.max_bson_size
323
+
324
+ conn = standard_connection
325
+ if conn.server_version > "1.7.2"
326
+ assert_equal conn['admin'].command({:ismaster => 1})['maxBsonObjectSize'], conn.max_bson_size
327
+ end
328
+ end
329
+
330
+ def test_max_message_size_value
331
+ conn = standard_connection(:connect => false)
332
+
333
+ admin_db = Object.new
334
+ admin_db.expects(:command).returns({'ok' => 1, 'ismaster' => 1, 'maxMessageSizeBytes' => 20_000_000})
335
+ conn.expects(:[]).with('admin').returns(admin_db)
336
+ conn.connect
337
+
338
+ assert_equal 20_000_000, conn.max_message_size
339
+
340
+ conn = standard_connection
341
+ maxMessageSizeBytes = conn['admin'].command({:ismaster => 1})['maxMessageSizeBytes']
342
+ if conn.server_version.to_s[/([^-]+)/,1] >= "2.4.0"
343
+ assert_equal 48_000_000, maxMessageSizeBytes
344
+ elsif conn.server_version > "2.3.2"
345
+ assert_equal conn.max_bson_size, maxMessageSizeBytes
346
+ end
347
+ end
348
+
349
+ def test_max_bson_size_with_no_reported_max_size
350
+ conn = standard_connection(:connect => false)
351
+
352
+ admin_db = Object.new
353
+ admin_db.expects(:command).returns({'ok' => 1, 'ismaster' => 1})
354
+ conn.expects(:[]).with('admin').returns(admin_db)
355
+
356
+ conn.connect
357
+ assert_equal Mongo::DEFAULT_MAX_BSON_SIZE, conn.max_bson_size
358
+ end
359
+
360
+ def test_max_message_size_with_no_reported_max_size
361
+ conn = standard_connection(:connect => false)
362
+
363
+ admin_db = Object.new
364
+ admin_db.expects(:command).returns({'ok' => 1, 'ismaster' => 1})
365
+ conn.expects(:[]).with('admin').returns(admin_db)
366
+
367
+ conn.connect
368
+ assert_equal Mongo::DEFAULT_MAX_BSON_SIZE * Mongo::MESSAGE_SIZE_FACTOR, conn.max_message_size
369
+ end
370
+
371
+ def test_max_wire_version_and_min_wire_version_values
372
+ conn = standard_connection(:connect => false)
373
+
374
+ admin_db = Object.new
375
+ admin_db.expects(:command).returns({'ok' => 1, 'ismaster' => 1, 'maxWireVersion' => 1, 'minWireVersion' => 1, 'maxWriteBatchSize' => 999})
376
+ conn.expects(:[]).with('admin').returns(admin_db)
377
+ conn.connect
378
+
379
+ assert_equal 1, conn.max_wire_version
380
+ assert_equal 1, conn.min_wire_version
381
+ assert_equal 999, conn.max_write_batch_size
382
+ end
383
+
384
+ def test_max_wire_version_and_min_wire_version_values_with_no_reported_values
385
+ conn = standard_connection(:connect => false)
386
+
387
+ admin_db = Object.new
388
+ admin_db.expects(:command).returns({'ok' => 1, 'ismaster' => 1})
389
+ conn.expects(:[]).with('admin').returns(admin_db)
390
+ conn.connect
391
+
392
+ assert_equal 0, conn.max_wire_version
393
+ assert_equal 0, conn.min_wire_version
394
+ assert_equal Mongo::MongoClient::DEFAULT_MAX_WRITE_BATCH_SIZE, conn.max_write_batch_size
395
+ end
396
+
397
+ def test_wire_version_feature
398
+ conn = standard_connection(:connect => false)
399
+ conn.stubs(:min_wire_version).returns(0)
400
+ conn.stubs(:max_wire_version).returns(1)
401
+ assert_true conn.wire_version_feature?(0)
402
+ assert_true conn.wire_version_feature?(1)
403
+ assert_false conn.wire_version_feature?(2)
404
+ assert_false conn.wire_version_feature?(-1)
405
+ end
406
+
407
+ def test_wire_version_not_in_range
408
+ [
409
+ [Mongo::MongoClient::MAX_WIRE_VERSION+1, Mongo::MongoClient::MAX_WIRE_VERSION+1],
410
+ [Mongo::MongoClient::MIN_WIRE_VERSION-1, Mongo::MongoClient::MIN_WIRE_VERSION-1]
411
+ ].each do |min_wire_version, max_wire_version|
412
+ conn = standard_connection(:connect => false)
413
+ admin_db = Object.new
414
+ admin_db.expects(:command).returns({'ok' => 1, 'ismaster' => 1, 'maxWireVersion' => max_wire_version, 'minWireVersion' => min_wire_version})
415
+ conn.expects(:[]).with('admin').returns(admin_db)
416
+ assert_raises Mongo::ConnectionFailure do
417
+ conn.connect
418
+ end
419
+ end
420
+ end
421
+
422
+ def test_use_write_command
423
+ with_write_commands(@client) do
424
+ assert_true @client.use_write_command?({:w => 1})
425
+ assert_false @client.use_write_command?({:w => 0})
426
+ end
427
+ with_write_operations(@client) do
428
+ assert_false @client.use_write_command?({:w => 1})
429
+ assert_false @client.use_write_command?({:w => 0})
430
+ end
431
+ end
432
+
433
+ def test_connection_activity
434
+ conn = standard_connection
435
+ assert conn.active?
436
+
437
+ conn.primary_pool.close
438
+ assert !conn.active?
439
+
440
+ # Simulate a dropped connection.
441
+ dropped_socket = mock('dropped_socket')
442
+ dropped_socket.stubs(:read).raises(Errno::ECONNRESET)
443
+ dropped_socket.stubs(:send).raises(Errno::ECONNRESET)
444
+ dropped_socket.stub_everything
445
+
446
+ conn.primary_pool.host = 'localhost'
447
+ conn.primary_pool.port = Mongo::MongoClient::DEFAULT_PORT
448
+ conn.primary_pool.instance_variable_set("@pids", {dropped_socket => Process.pid})
449
+ conn.primary_pool.instance_variable_set("@sockets", [dropped_socket])
450
+
451
+ assert !conn.active?
452
+ end
453
+
454
+ def test_operation_timeout_with_active
455
+ conn = MongoClient.new
456
+ authenticate_client(conn)
457
+ assert conn.active?
458
+ assert_equal Mongo::MongoClient::DEFAULT_OP_TIMEOUT, conn.op_timeout
459
+
460
+ pool = conn.primary_pool
461
+ socket = pool.instance_variable_get(:@thread_ids_to_sockets)[Thread.current.object_id]
462
+
463
+ socket.stubs(:read).raises(Mongo::OperationTimeout)
464
+ assert_equal false, conn.active?
465
+ end
466
+
467
+ context "Saved authentications" do
468
+ setup do
469
+ @client = Mongo::MongoClient.new
470
+
471
+ @auth = {
472
+ :db_name => TEST_DB,
473
+ :username => TEST_USER,
474
+ :password => TEST_USER_PWD,
475
+ :source => TEST_DB,
476
+ :mechanism => 'MONGODB-CR'
477
+ }
478
+
479
+ @client.auths << @auth
480
+ end
481
+
482
+ should "save and validate the authentication" do
483
+ assert_equal Authentication.validate_credentials(@auth), @client.auths.first
484
+ end
485
+
486
+ should "not allow multiple authentications for the same db" do
487
+ auth = {
488
+ :db_name => TEST_DB,
489
+ :username => TEST_USER,
490
+ :password => TEST_USER_PWD,
491
+ :source => TEST_DB,
492
+ :mechanism => nil
493
+ }
494
+
495
+ assert_raise Mongo::MongoArgumentError do
496
+ @client.add_auth(
497
+ auth[:db_name],
498
+ auth[:username],
499
+ auth[:password],
500
+ auth[:source],
501
+ auth[:mechanism])
502
+ end
503
+ end
504
+
505
+ should "remove auths by database" do
506
+ @client.remove_auth('non-existent database')
507
+ assert_equal 1, @client.auths.length
508
+
509
+ @client.remove_auth(TEST_DB)
510
+ assert_equal 0, @client.auths.length
511
+ end
512
+
513
+ should "remove all auths" do
514
+ @client.clear_auths
515
+ assert_equal 0, @client.auths.length
516
+ end
517
+ end
518
+
519
+ context "Socket pools" do
520
+ context "checking out writers" do
521
+ setup do
522
+ @con = standard_connection(:pool_size => 10, :pool_timeout => 2)
523
+ @coll = @con[TEST_DB]['test-connection-exceptions']
524
+ end
525
+
526
+ should "close the connection on send_message for major exceptions" do
527
+ @con.stubs(:checkout_writer).raises(SystemStackError)
528
+ @con.stubs(:checkout_reader).raises(SystemStackError)
529
+ @con.expects(:close)
530
+ begin
531
+ @coll.insert({:foo => "bar"})
532
+ rescue SystemStackError
533
+ end
534
+ end
535
+
536
+ context "with GLE" do
537
+ setup do
538
+ # Force this connection to use send_message_with_gle for these tests
539
+ @con.stubs(:use_write_command?).returns(false)
540
+ end
541
+
542
+ should "close the connection on send_message_with_gle for major exceptions" do
543
+ @con.stubs(:checkout_writer).raises(SystemStackError)
544
+ @con.stubs(:checkout_reader).raises(SystemStackError)
545
+ @con.expects(:close)
546
+ begin
547
+ @coll.insert({:foo => "bar"}, :w => 1)
548
+ rescue SystemStackError
549
+ end
550
+ end
551
+
552
+ should "release the connection on send_message_with_gle for connection exceptions" do
553
+ mock_writer = mock(:close => true)
554
+ mock_writer.expects(:read).raises(ConnectionFailure)
555
+ @con.expects(:send_message_on_socket)
556
+
557
+ @con.stubs(:checkout_writer).returns(mock_writer)
558
+ @con.expects(:checkin).with(mock_writer)
559
+ @coll.insert({:foo => "bar"}, :w => 1) rescue nil
560
+ end
561
+
562
+ should "release the connection on send_message_with_gle for all exceptions" do
563
+ mock_writer = mock()
564
+ mock_writer.expects(:read).raises(ArgumentError)
565
+ @con.expects(:send_message_on_socket)
566
+ @con.stubs(:checkout_writer).returns(mock_writer)
567
+ @con.expects(:checkin).with(mock_writer).once
568
+ begin
569
+ @coll.insert({:foo => "bar"}, :w => 1)
570
+ rescue ArgumentError
571
+ end
572
+ end
573
+ end
574
+
575
+ should "close the connection on receive_message for major exceptions" do
576
+ @con.expects(:checkout_reader).raises(SystemStackError)
577
+ @con.expects(:close)
578
+ begin
579
+ @coll.find.next
580
+ rescue SystemStackError
581
+ end
582
+ end
583
+ end
584
+ end
585
+
586
+ context "Connection exceptions" do
587
+ setup do
588
+ @con = MongoClient.new(TEST_HOST, TEST_PORT, :pool_size => 10, :pool_timeout => 10)
589
+ @coll = @con[TEST_DB]['test-connection-exceptions']
590
+ end
591
+
592
+ should "release connection if an exception is raised on send_message" do
593
+ @con.stubs(:send_message_on_socket).raises(ConnectionFailure)
594
+ assert_equal 0, @con.primary_pool.checked_out.size
595
+ assert_raise ConnectionFailure do
596
+ @coll.insert({:test => "insert"})
597
+ end
598
+ assert_equal 0, @con.primary_pool.checked_out.size
599
+ end
600
+
601
+ should "release connection if an exception is raised on write concern :w => 1" do
602
+ @con.stubs(:receive).raises(ConnectionFailure)
603
+ assert_equal 0, @con.primary_pool.checked_out.size
604
+ assert_raise ConnectionFailure do
605
+ @coll.insert({:test => "insert"}, :w => 1)
606
+ end
607
+ assert_equal 0, @con.primary_pool.checked_out.size
608
+ end
609
+
610
+ should "release connection if an exception is raised on receive_message" do
611
+ @con.stubs(:receive).raises(ConnectionFailure)
612
+ assert_equal 0, @con.read_pool.checked_out.size
613
+ assert_raise ConnectionFailure do
614
+ @coll.find.to_a
615
+ end
616
+ assert_equal 0, @con.read_pool.checked_out.size
617
+ end
618
+
619
+ should "show a proper exception message if an IOError is raised while closing a socket" do
620
+ TCPSocket.any_instance.stubs(:close).raises(IOError.new)
621
+
622
+ @con.primary_pool.checkout_new_socket
623
+ @con.primary_pool.expects(:warn)
624
+ assert @con.primary_pool.close
625
+ end
626
+ end
627
+ end