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.
- checksums.yaml +7 -0
- checksums.yaml.gz.sig +0 -0
- data/{LICENSE.txt → LICENSE} +1 -1
- data/README.md +122 -271
- data/Rakefile +25 -209
- data/VERSION +1 -0
- data/bin/mongo_console +31 -9
- data/lib/mongo/bulk_write_collection_view.rb +387 -0
- data/lib/mongo/collection.rb +576 -269
- data/lib/mongo/collection_writer.rb +364 -0
- data/lib/mongo/connection/node.rb +249 -0
- data/lib/mongo/connection/pool.rb +340 -0
- data/lib/mongo/connection/pool_manager.rb +320 -0
- data/lib/mongo/connection/sharding_pool_manager.rb +67 -0
- data/lib/mongo/connection/socket/socket_util.rb +37 -0
- data/lib/mongo/connection/socket/ssl_socket.rb +95 -0
- data/lib/mongo/connection/socket/tcp_socket.rb +87 -0
- data/lib/mongo/connection/socket/unix_socket.rb +39 -0
- data/lib/mongo/connection/socket.rb +18 -0
- data/lib/mongo/connection.rb +7 -875
- data/lib/mongo/cursor.rb +403 -117
- data/lib/mongo/db.rb +444 -243
- data/lib/mongo/exception.rb +145 -0
- data/lib/mongo/functional/authentication.rb +455 -0
- data/lib/mongo/functional/logging.rb +85 -0
- data/lib/mongo/functional/read_preference.rb +183 -0
- data/lib/mongo/functional/scram.rb +556 -0
- data/lib/mongo/functional/uri_parser.rb +409 -0
- data/lib/mongo/functional/write_concern.rb +66 -0
- data/lib/mongo/functional.rb +20 -0
- data/lib/mongo/gridfs/grid.rb +30 -24
- data/lib/mongo/gridfs/grid_ext.rb +6 -10
- data/lib/mongo/gridfs/grid_file_system.rb +38 -20
- data/lib/mongo/gridfs/grid_io.rb +84 -75
- data/lib/mongo/gridfs.rb +18 -0
- data/lib/mongo/legacy.rb +140 -0
- data/lib/mongo/mongo_client.rb +697 -0
- data/lib/mongo/mongo_replica_set_client.rb +535 -0
- data/lib/mongo/mongo_sharded_client.rb +159 -0
- data/lib/mongo/networking.rb +372 -0
- data/lib/mongo/{util → utils}/conversions.rb +29 -8
- data/lib/mongo/{util → utils}/core_ext.rb +28 -18
- data/lib/mongo/{util → utils}/server_version.rb +4 -6
- data/lib/mongo/{util → utils}/support.rb +29 -31
- data/lib/mongo/utils/thread_local_variable_manager.rb +25 -0
- data/lib/mongo/utils.rb +19 -0
- data/lib/mongo.rb +51 -50
- data/mongo.gemspec +29 -32
- data/test/functional/authentication_test.rb +39 -0
- data/test/functional/bulk_api_stress_test.rb +133 -0
- data/test/functional/bulk_write_collection_view_test.rb +1198 -0
- data/test/functional/client_test.rb +627 -0
- data/test/functional/collection_test.rb +2175 -0
- data/test/functional/collection_writer_test.rb +83 -0
- data/test/{conversions_test.rb → functional/conversions_test.rb} +47 -3
- data/test/functional/cursor_fail_test.rb +57 -0
- data/test/functional/cursor_message_test.rb +56 -0
- data/test/functional/cursor_test.rb +683 -0
- data/test/functional/db_api_test.rb +835 -0
- data/test/functional/db_connection_test.rb +25 -0
- data/test/functional/db_test.rb +348 -0
- data/test/functional/grid_file_system_test.rb +285 -0
- data/test/{grid_io_test.rb → functional/grid_io_test.rb} +72 -11
- data/test/{grid_test.rb → functional/grid_test.rb} +88 -15
- data/test/functional/pool_test.rb +136 -0
- data/test/functional/safe_test.rb +98 -0
- data/test/functional/ssl_test.rb +29 -0
- data/test/functional/support_test.rb +62 -0
- data/test/functional/timeout_test.rb +60 -0
- data/test/functional/uri_test.rb +446 -0
- data/test/functional/write_concern_test.rb +118 -0
- data/test/helpers/general.rb +50 -0
- data/test/helpers/test_unit.rb +476 -0
- data/test/replica_set/authentication_test.rb +37 -0
- data/test/replica_set/basic_test.rb +189 -0
- data/test/replica_set/client_test.rb +393 -0
- data/test/replica_set/connection_test.rb +138 -0
- data/test/replica_set/count_test.rb +66 -0
- data/test/replica_set/cursor_test.rb +220 -0
- data/test/replica_set/insert_test.rb +157 -0
- data/test/replica_set/max_values_test.rb +151 -0
- data/test/replica_set/pinning_test.rb +105 -0
- data/test/replica_set/query_test.rb +73 -0
- data/test/replica_set/read_preference_test.rb +219 -0
- data/test/replica_set/refresh_test.rb +211 -0
- data/test/replica_set/replication_ack_test.rb +95 -0
- data/test/replica_set/ssl_test.rb +32 -0
- data/test/sharded_cluster/basic_test.rb +203 -0
- data/test/shared/authentication/basic_auth_shared.rb +260 -0
- data/test/shared/authentication/bulk_api_auth_shared.rb +249 -0
- data/test/shared/authentication/gssapi_shared.rb +176 -0
- data/test/shared/authentication/sasl_plain_shared.rb +96 -0
- data/test/shared/authentication/scram_shared.rb +92 -0
- data/test/shared/ssl_shared.rb +235 -0
- data/test/test_helper.rb +53 -94
- data/test/threading/basic_test.rb +120 -0
- data/test/tools/mongo_config.rb +708 -0
- data/test/tools/mongo_config_test.rb +160 -0
- data/test/unit/client_test.rb +381 -0
- data/test/unit/collection_test.rb +89 -53
- data/test/unit/connection_test.rb +282 -32
- data/test/unit/cursor_test.rb +206 -8
- data/test/unit/db_test.rb +55 -13
- data/test/unit/grid_test.rb +43 -16
- data/test/unit/mongo_sharded_client_test.rb +48 -0
- data/test/unit/node_test.rb +93 -0
- data/test/unit/pool_manager_test.rb +111 -0
- data/test/unit/read_pref_test.rb +406 -0
- data/test/unit/read_test.rb +159 -0
- data/test/unit/safe_test.rb +69 -36
- data/test/unit/sharding_pool_manager_test.rb +84 -0
- data/test/unit/write_concern_test.rb +175 -0
- data.tar.gz.sig +3 -0
- metadata +227 -216
- metadata.gz.sig +0 -0
- data/docs/CREDITS.md +0 -123
- data/docs/FAQ.md +0 -116
- data/docs/GridFS.md +0 -158
- data/docs/HISTORY.md +0 -244
- data/docs/RELEASES.md +0 -33
- data/docs/REPLICA_SETS.md +0 -72
- data/docs/TUTORIAL.md +0 -247
- data/docs/WRITE_CONCERN.md +0 -28
- data/lib/mongo/exceptions.rb +0 -71
- data/lib/mongo/gridfs/grid_io_fix.rb +0 -38
- data/lib/mongo/repl_set_connection.rb +0 -342
- data/lib/mongo/test.rb +0 -20
- data/lib/mongo/util/pool.rb +0 -177
- data/lib/mongo/util/uri_parser.rb +0 -185
- data/test/async/collection_test.rb +0 -224
- data/test/async/connection_test.rb +0 -24
- data/test/async/cursor_test.rb +0 -162
- data/test/async/worker_pool_test.rb +0 -99
- data/test/auxillary/1.4_features.rb +0 -166
- data/test/auxillary/authentication_test.rb +0 -68
- data/test/auxillary/autoreconnect_test.rb +0 -41
- data/test/auxillary/fork_test.rb +0 -30
- data/test/auxillary/repl_set_auth_test.rb +0 -58
- data/test/auxillary/slave_connection_test.rb +0 -36
- data/test/auxillary/threaded_authentication_test.rb +0 -101
- data/test/bson/binary_test.rb +0 -15
- data/test/bson/bson_test.rb +0 -649
- data/test/bson/byte_buffer_test.rb +0 -208
- data/test/bson/hash_with_indifferent_access_test.rb +0 -38
- data/test/bson/json_test.rb +0 -17
- data/test/bson/object_id_test.rb +0 -154
- data/test/bson/ordered_hash_test.rb +0 -204
- data/test/bson/timestamp_test.rb +0 -24
- data/test/collection_test.rb +0 -910
- data/test/connection_test.rb +0 -309
- data/test/cursor_fail_test.rb +0 -75
- data/test/cursor_message_test.rb +0 -43
- data/test/cursor_test.rb +0 -483
- data/test/db_api_test.rb +0 -726
- data/test/db_connection_test.rb +0 -15
- data/test/db_test.rb +0 -287
- data/test/grid_file_system_test.rb +0 -243
- data/test/load/resque/load.rb +0 -21
- data/test/load/resque/processor.rb +0 -26
- data/test/load/thin/load.rb +0 -24
- data/test/load/unicorn/load.rb +0 -23
- data/test/load/unicorn/unicorn.rb +0 -29
- data/test/replica_sets/connect_test.rb +0 -94
- data/test/replica_sets/connection_string_test.rb +0 -32
- data/test/replica_sets/count_test.rb +0 -35
- data/test/replica_sets/insert_test.rb +0 -53
- data/test/replica_sets/pooled_insert_test.rb +0 -55
- data/test/replica_sets/query_secondaries.rb +0 -96
- data/test/replica_sets/query_test.rb +0 -51
- data/test/replica_sets/replication_ack_test.rb +0 -66
- data/test/replica_sets/rs_test_helper.rb +0 -27
- data/test/safe_test.rb +0 -68
- data/test/support/hash_with_indifferent_access.rb +0 -186
- data/test/support/keys.rb +0 -45
- data/test/support_test.rb +0 -18
- data/test/threading/threading_with_large_pool_test.rb +0 -90
- data/test/threading_test.rb +0 -87
- data/test/tools/auth_repl_set_manager.rb +0 -14
- data/test/tools/load.rb +0 -58
- data/test/tools/repl_set_manager.rb +0 -266
- data/test/tools/sharding_manager.rb +0 -202
- data/test/tools/test.rb +0 -4
- data/test/unit/pool_test.rb +0 -9
- data/test/unit/repl_set_connection_test.rb +0 -59
- 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
|