mongo 1.10.2 → 1.11.1
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 +4 -4
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +0 -0
- data/README.md +43 -9
- data/VERSION +1 -1
- data/lib/mongo.rb +1 -0
- data/lib/mongo/collection.rb +36 -21
- data/lib/mongo/connection/pool.rb +14 -22
- data/lib/mongo/cursor.rb +13 -0
- data/lib/mongo/db.rb +18 -13
- data/lib/mongo/functional.rb +0 -2
- data/lib/mongo/functional/authentication.rb +35 -25
- data/lib/mongo/legacy.rb +4 -4
- data/mongo.gemspec +0 -5
- data/test/functional/authentication_test.rb +3 -2
- data/test/functional/bulk_write_collection_view_test.rb +9 -14
- data/test/functional/client_test.rb +42 -43
- data/test/functional/collection_test.rb +1073 -995
- data/test/functional/collection_writer_test.rb +1 -1
- data/test/functional/cursor_fail_test.rb +3 -9
- data/test/functional/cursor_message_test.rb +14 -15
- data/test/functional/cursor_test.rb +224 -166
- data/test/functional/db_api_test.rb +262 -261
- data/test/functional/db_connection_test.rb +1 -3
- data/test/functional/db_test.rb +116 -115
- data/test/functional/grid_file_system_test.rb +108 -108
- data/test/functional/pool_test.rb +73 -0
- data/test/functional/timeout_test.rb +2 -0
- data/test/helpers/test_unit.rb +146 -11
- data/test/replica_set/authentication_test.rb +4 -2
- data/test/replica_set/basic_test.rb +5 -13
- data/test/replica_set/client_test.rb +8 -6
- data/test/replica_set/complex_connect_test.rb +3 -0
- data/test/replica_set/count_test.rb +2 -0
- data/test/replica_set/cursor_test.rb +5 -0
- data/test/replica_set/insert_test.rb +1 -1
- data/test/replica_set/max_values_test.rb +1 -1
- data/test/replica_set/pinning_test.rb +1 -1
- data/test/replica_set/query_test.rb +1 -1
- data/test/replica_set/read_preference_test.rb +7 -1
- data/test/replica_set/refresh_test.rb +11 -8
- data/test/replica_set/replication_ack_test.rb +2 -1
- data/test/sharded_cluster/basic_test.rb +17 -11
- data/test/shared/authentication/basic_auth_shared.rb +59 -98
- data/test/shared/authentication/bulk_api_auth_shared.rb +11 -21
- data/test/shared/authentication/gssapi_shared.rb +28 -21
- data/test/test_helper.rb +5 -0
- data/test/tools/mongo_config.rb +96 -11
- metadata +4 -5
- metadata.gz.sig +0 -0
- data/lib/mongo/functional/sasl_java.rb +0 -48
data/lib/mongo/legacy.rb
CHANGED
@@ -87,14 +87,14 @@ module Mongo
|
|
87
87
|
class MongoClient
|
88
88
|
# @deprecated This method is no longer in use and never needs to be called
|
89
89
|
# directly. Support will be removed after v2.0
|
90
|
+
# Authentication of sockets is handled upon checkout and checkin.
|
90
91
|
def authenticate_pools
|
91
|
-
@primary_pool.authenticate_existing
|
92
92
|
end
|
93
93
|
|
94
94
|
# @deprecated This method is no longer in use and never needs to be called
|
95
95
|
# directly. Support will be removed after v2.0
|
96
|
+
# Authentication of sockets is handled upon checkout and checkin.
|
96
97
|
def logout_pools(database)
|
97
|
-
@primary_pool.logout_existing(database)
|
98
98
|
end
|
99
99
|
|
100
100
|
# @deprecated This method is no longer in use and never needs to be called
|
@@ -107,14 +107,14 @@ module Mongo
|
|
107
107
|
class MongoReplicaSetClient
|
108
108
|
# @deprecated This method is no longer in use and never needs to be called
|
109
109
|
# directly. Support will be removed after v2.0
|
110
|
+
# Authentication of sockets is handled upon checkout and checkin.
|
110
111
|
def authenticate_pools
|
111
|
-
@manager.pools.each { |pool| pool.authenticate_existing }
|
112
112
|
end
|
113
113
|
|
114
114
|
# @deprecated This method is no longer in use and never needs to be called
|
115
115
|
# directly. Support will be removed after v2.0
|
116
|
+
# Authentication of sockets is handled upon checkout and checkin.
|
116
117
|
def logout_pools(database)
|
117
|
-
@manager.pools.each { |pool| pool.logout_existing(database) }
|
118
118
|
end
|
119
119
|
end
|
120
120
|
|
data/mongo.gemspec
CHANGED
@@ -22,11 +22,6 @@ Gem::Specification.new do |s|
|
|
22
22
|
s.files += ['README.md', 'Rakefile', 'bin/mongo_console']
|
23
23
|
s.files += ['lib/mongo.rb'] + Dir['lib/mongo/**/*.rb']
|
24
24
|
|
25
|
-
if RUBY_PLATFORM =~ /java/
|
26
|
-
s.platform = 'java'
|
27
|
-
s.files << 'ext/jsasl/target/jsasl.jar'
|
28
|
-
end
|
29
|
-
|
30
25
|
s.test_files = Dir['test/**/*.rb'] - Dir['test/bson/*']
|
31
26
|
s.executables = ['mongo_console']
|
32
27
|
s.require_paths = ['lib']
|
@@ -27,9 +27,10 @@ class AuthenticationTest < Test::Unit::TestCase
|
|
27
27
|
include GSSAPITests
|
28
28
|
|
29
29
|
def setup
|
30
|
-
@client =
|
30
|
+
@client = standard_connection
|
31
|
+
@admin = @client['admin']
|
31
32
|
@version = @client.server_version
|
32
|
-
@db = @client[
|
33
|
+
@db = @client['ruby-test']
|
33
34
|
@host_info = host_port
|
34
35
|
end
|
35
36
|
end
|
@@ -52,12 +52,6 @@ module BSON
|
|
52
52
|
end
|
53
53
|
|
54
54
|
class BulkWriteCollectionViewTest < Test::Unit::TestCase
|
55
|
-
@@client ||= standard_connection(:op_timeout => 10)
|
56
|
-
@@db = @@client.db(TEST_DB)
|
57
|
-
@@test = @@db.collection("test")
|
58
|
-
@@version = @@client.server_version
|
59
|
-
|
60
|
-
DATABASE_NAME = 'ruby_test_bulk_write_collection_view'
|
61
55
|
COLLECTION_NAME = 'test'
|
62
56
|
DUPLICATE_KEY_ERROR_CODE_SET = [11000, 11001, 12582, 16460].to_set
|
63
57
|
|
@@ -78,8 +72,9 @@ class BulkWriteCollectionViewTest < Test::Unit::TestCase
|
|
78
72
|
end
|
79
73
|
|
80
74
|
def default_setup
|
81
|
-
@client =
|
82
|
-
@
|
75
|
+
@client = standard_connection
|
76
|
+
@version = @client.server_version
|
77
|
+
@db = @client[TEST_DB]
|
83
78
|
@collection = @db[COLLECTION_NAME]
|
84
79
|
@collection.drop
|
85
80
|
@bulk = @collection.initialize_ordered_bulk_op
|
@@ -339,7 +334,7 @@ class BulkWriteCollectionViewTest < Test::Unit::TestCase
|
|
339
334
|
end
|
340
335
|
end
|
341
336
|
|
342
|
-
|
337
|
+
# ----- REPLACE -----
|
343
338
|
|
344
339
|
should "raise an error when we attempt to use replace" do
|
345
340
|
assert_raise NoMethodError do
|
@@ -858,10 +853,10 @@ class BulkWriteCollectionViewTest < Test::Unit::TestCase
|
|
858
853
|
should "handle error for serialization with offset" do
|
859
854
|
with_write_commands_and_operations(@db.connection) do |wire_version|
|
860
855
|
@collection.remove
|
861
|
-
assert_equal 16777216,
|
856
|
+
assert_equal 16777216, @client.max_bson_size
|
862
857
|
@bulk.find({:a => 1}).update_one({"$inc" => {:x => 1}})
|
863
858
|
@bulk.insert({:_id => 1, :a => 1})
|
864
|
-
@bulk.insert(generate_sized_doc(
|
859
|
+
@bulk.insert(generate_sized_doc(@client.max_message_size + 1))
|
865
860
|
@bulk.insert({:_id => 3, :a => 3})
|
866
861
|
ex = assert_raise BulkWriteError do
|
867
862
|
@bulk.execute
|
@@ -999,7 +994,7 @@ class BulkWriteCollectionViewTest < Test::Unit::TestCase
|
|
999
994
|
@bulk.execute(write_concern)
|
1000
995
|
end
|
1001
996
|
result = ex.result
|
1002
|
-
if
|
997
|
+
if @version >= "2.5.5"
|
1003
998
|
assert_match_document(
|
1004
999
|
{
|
1005
1000
|
"ok" => 0,
|
@@ -1098,7 +1093,7 @@ class BulkWriteCollectionViewTest < Test::Unit::TestCase
|
|
1098
1093
|
@bulk = @collection.initialize_unordered_bulk_op
|
1099
1094
|
@bulk.insert({:_id => 1, :a => 1})
|
1100
1095
|
@bulk.insert({:_id => 1, :a => 2})
|
1101
|
-
@bulk.insert(generate_sized_doc(
|
1096
|
+
@bulk.insert(generate_sized_doc(@client.max_message_size + 1))
|
1102
1097
|
@bulk.insert({:_id => 3, :a => 3})
|
1103
1098
|
@bulk.find({:a => 4}).upsert.replace_one({:x => 3})
|
1104
1099
|
ex = assert_raise BulkWriteError do
|
@@ -1127,7 +1122,7 @@ class BulkWriteCollectionViewTest < Test::Unit::TestCase
|
|
1127
1122
|
@bulk.execute(write_concern)
|
1128
1123
|
end
|
1129
1124
|
result = ex.result
|
1130
|
-
if
|
1125
|
+
if @version >= "2.5.5"
|
1131
1126
|
assert_match_document(
|
1132
1127
|
{
|
1133
1128
|
"ok" => 0,
|
@@ -145,7 +145,7 @@ class ClientTest < Test::Unit::TestCase
|
|
145
145
|
end
|
146
146
|
|
147
147
|
def test_from_uri_write_concern
|
148
|
-
con = MongoClient.from_uri(
|
148
|
+
con = MongoClient.from_uri(TEST_URI)
|
149
149
|
db = con.db
|
150
150
|
coll = db.collection('from-uri-test')
|
151
151
|
assert_equal BSON::ObjectId, coll.insert({'a' => 1}).class
|
@@ -182,33 +182,36 @@ class ClientTest < Test::Unit::TestCase
|
|
182
182
|
end
|
183
183
|
|
184
184
|
def test_database_info
|
185
|
-
|
186
|
-
@client.
|
185
|
+
db_name = 'ruby_test'
|
186
|
+
@client.drop_database(db_name)
|
187
|
+
@client.db(db_name).collection('info-test').insert('a' => 1)
|
187
188
|
|
188
189
|
info = @client.database_info
|
189
190
|
assert_not_nil info
|
190
191
|
assert_kind_of Hash, info
|
191
|
-
assert_not_nil info[
|
192
|
-
assert info[
|
192
|
+
assert_not_nil info[db_name]
|
193
|
+
assert info[db_name] > 0
|
193
194
|
|
194
|
-
@client.drop_database(
|
195
|
+
@client.drop_database(db_name)
|
195
196
|
end
|
196
197
|
|
197
198
|
def test_copy_database
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
@client
|
202
|
-
|
203
|
-
@client.copy_database(old_name, new_name, host_port)
|
199
|
+
return unless @client.server_version >= '2.5' ||
|
200
|
+
@client.server_version < '2.4'
|
201
|
+
old_db = @client['ruby-test-old']
|
202
|
+
new_db = @client['ruby-test-new']
|
203
|
+
coll = 'copy-test'
|
204
204
|
|
205
|
-
|
206
|
-
|
207
|
-
|
205
|
+
old_db[coll].insert('a' => 1)
|
206
|
+
@client.drop_database(new_db.name)
|
207
|
+
silently { old_db.add_user('chevy', 'chase') }
|
208
|
+
@client.copy_database(old_db.name, new_db.name, host_port, 'chevy', 'chase')
|
209
|
+
old_db.remove_user('chevy')
|
210
|
+
assert_equal old_db[coll].find_one, new_db[coll].find_one
|
208
211
|
end
|
209
212
|
|
210
213
|
def test_database_names
|
211
|
-
@client.
|
214
|
+
@client.db(TEST_DB).collection('info-test').remove({})
|
212
215
|
@client.db(TEST_DB).collection('info-test').insert('a' => 1)
|
213
216
|
|
214
217
|
names = @client.database_names
|
@@ -429,44 +432,40 @@ class ClientTest < Test::Unit::TestCase
|
|
429
432
|
|
430
433
|
context "Saved authentications" do
|
431
434
|
setup do
|
432
|
-
@client =
|
435
|
+
@client = Mongo::MongoClient.new
|
433
436
|
|
434
437
|
@auth = {
|
435
|
-
|
436
|
-
|
437
|
-
|
438
|
-
|
439
|
-
|
438
|
+
:db_name => TEST_DB,
|
439
|
+
:username => TEST_USER,
|
440
|
+
:password => TEST_USER_PWD,
|
441
|
+
:source => TEST_DB,
|
442
|
+
:mechanism => 'MONGODB-CR'
|
440
443
|
}
|
441
444
|
|
442
445
|
@client.auths << @auth
|
443
446
|
end
|
444
447
|
|
445
|
-
teardown do
|
446
|
-
@client.clear_auths
|
447
|
-
end
|
448
|
-
|
449
448
|
should "save and validate the authentication" do
|
450
449
|
assert_equal Authentication.validate_credentials(@auth), @client.auths.first
|
451
450
|
end
|
452
451
|
|
453
452
|
should "not allow multiple authentications for the same db" do
|
454
|
-
|
455
|
-
|
456
|
-
|
457
|
-
|
458
|
-
|
459
|
-
|
460
|
-
|
461
|
-
|
462
|
-
|
463
|
-
|
464
|
-
|
465
|
-
|
466
|
-
|
467
|
-
|
468
|
-
|
469
|
-
|
453
|
+
auth = {
|
454
|
+
:db_name => TEST_DB,
|
455
|
+
:username => TEST_USER,
|
456
|
+
:password => TEST_USER_PWD,
|
457
|
+
:source => TEST_DB,
|
458
|
+
:mechanism => nil
|
459
|
+
}
|
460
|
+
|
461
|
+
assert_raise Mongo::MongoArgumentError do
|
462
|
+
@client.add_auth(
|
463
|
+
auth[:db_name],
|
464
|
+
auth[:username],
|
465
|
+
auth[:password],
|
466
|
+
auth[:source],
|
467
|
+
auth[:mechanism])
|
468
|
+
end
|
470
469
|
end
|
471
470
|
|
472
471
|
should "remove auths by database" do
|
@@ -523,7 +522,7 @@ class ClientTest < Test::Unit::TestCase
|
|
523
522
|
|
524
523
|
context "Connection exceptions" do
|
525
524
|
setup do
|
526
|
-
@con =
|
525
|
+
@con = MongoClient.new(TEST_HOST, TEST_PORT, :pool_size => 10, :pool_timeout => 10)
|
527
526
|
@coll = @con[TEST_DB]['test-connection-exceptions']
|
528
527
|
end
|
529
528
|
|
@@ -16,10 +16,6 @@ require 'rbconfig'
|
|
16
16
|
require 'test_helper'
|
17
17
|
|
18
18
|
class CollectionTest < Test::Unit::TestCase
|
19
|
-
@@client ||= standard_connection(:op_timeout => 10)
|
20
|
-
@@db = @@client.db(TEST_DB)
|
21
|
-
@@test = @@db.collection("test")
|
22
|
-
@@version = @@client.server_version
|
23
19
|
|
24
20
|
LIMITED_MAX_BSON_SIZE = 1024
|
25
21
|
LIMITED_MAX_MESSAGE_SIZE = 3 * LIMITED_MAX_BSON_SIZE
|
@@ -28,7 +24,11 @@ class CollectionTest < Test::Unit::TestCase
|
|
28
24
|
LIMITED_INVALID_VALUE_SIZE = LIMITED_MAX_BSON_SIZE + Mongo::MongoClient::COMMAND_HEADROOM + 1
|
29
25
|
|
30
26
|
def setup
|
31
|
-
|
27
|
+
@client ||= standard_connection(:op_timeout => 10)
|
28
|
+
@db = @client.db(TEST_DB)
|
29
|
+
@test = @db.collection("test")
|
30
|
+
@version = @client.server_version
|
31
|
+
@test.remove
|
32
32
|
end
|
33
33
|
|
34
34
|
@@wv0 = Mongo::MongoClient::RELEASE_2_4_AND_BEFORE
|
@@ -36,26 +36,34 @@ class CollectionTest < Test::Unit::TestCase
|
|
36
36
|
@@a_h = Mongo::MongoClient::APPEND_HEADROOM
|
37
37
|
@@s_h = Mongo::MongoClient::SERIALIZE_HEADROOM
|
38
38
|
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
[
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
39
|
+
def max_size_exception_test(client)
|
40
|
+
base = [
|
41
|
+
#[@@wv0, client.max_bson_size, nil, /xyzzy/], # succeeds standalone, fails whole suite
|
42
|
+
]
|
43
|
+
base += max_size_exception_cruby_test(client) unless RUBY_PLATFORM == 'java'
|
44
|
+
#base += max_size_exception_jruby_test if RUBY_PLATFORM == 'java'
|
45
|
+
base += max_size_exception_commands_test(client) if @version >= '2.5.2'
|
46
|
+
base
|
47
|
+
end
|
48
|
+
|
49
|
+
def max_size_exception_cruby_test(client)
|
50
|
+
[
|
51
|
+
[@@wv0, client.max_bson_size + 1, BSON::InvalidDocument, /Document.* too large/]
|
52
|
+
]
|
53
|
+
end
|
54
|
+
|
55
|
+
def max_size_exception_jruby_test(client)
|
56
|
+
[@@wv0, client.max_bson_size + 1, Mongo::OperationFailure, /object to insert too large/]
|
57
|
+
end
|
58
|
+
|
59
|
+
def max_size_exception_commands_test(client)
|
60
|
+
[
|
61
|
+
#[@@wv2, client.max_bson_size, nil, /xyzzy/], # succeeds standalone, fails whole suite
|
62
|
+
[@@wv2, client.max_bson_size + 1, Mongo::OperationFailure, /object to insert too large/],
|
63
|
+
[@@wv2, client.max_bson_size + @@s_h, Mongo::OperationFailure, /object to insert too large/],
|
64
|
+
[@@wv2, client.max_bson_size + @@a_h, BSON::InvalidDocument, /Document.* too large/]
|
65
|
+
]
|
66
|
+
end
|
59
67
|
|
60
68
|
def generate_sized_doc(size)
|
61
69
|
doc = {"_id" => BSON::ObjectId.new, "x" => "y"}
|
@@ -81,334 +89,349 @@ class CollectionTest < Test::Unit::TestCase
|
|
81
89
|
end
|
82
90
|
|
83
91
|
def test_insert_batch_max_sizes
|
84
|
-
|
85
|
-
with_max_wire_version(
|
86
|
-
|
92
|
+
max_size_exception_test(@client).each do |wire_version, size, exc, regexp|
|
93
|
+
with_max_wire_version(@client, wire_version) do
|
94
|
+
@test.remove
|
87
95
|
doc = generate_sized_doc(size)
|
88
96
|
begin
|
89
|
-
|
97
|
+
@test.insert([doc.dup])
|
90
98
|
assert_equal nil, exc
|
91
99
|
rescue => e
|
92
|
-
assert_equal exc, e.class, "wire_version:#{wire_version}, size:#{size}, exc:#{exc} e:#{e.message.inspect}
|
100
|
+
assert_equal exc, e.class, "wire_version:#{wire_version}, size:#{size}, exc:#{exc} e:#{e.message.inspect} @version:#{@version}"
|
93
101
|
assert_match regexp, e.message
|
94
102
|
end
|
95
103
|
end
|
96
104
|
end
|
97
105
|
end
|
98
106
|
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
@@test.insert([{ :a => 1 }, { :a => 1 }])
|
107
|
+
def test_single_delete_write_command
|
108
|
+
return unless @version >= '2.5.4'
|
109
|
+
@test.drop
|
110
|
+
@test.insert([{ :a => 1 }, { :a => 1 }])
|
104
111
|
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
112
|
+
command = BSON::OrderedHash['delete', @test.name,
|
113
|
+
:deletes, [{ :q => { :a => 1 }, :limit => 1 }],
|
114
|
+
:writeConcern, { :w => 1 },
|
115
|
+
:ordered, false]
|
109
116
|
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
117
|
+
result = @db.command(command)
|
118
|
+
assert_equal 1, result['n']
|
119
|
+
assert_equal 1, result['ok']
|
120
|
+
assert_equal 1, @test.count
|
121
|
+
end
|
115
122
|
|
116
|
-
|
117
|
-
|
118
|
-
|
123
|
+
def test_multi_ordered_delete_write_command
|
124
|
+
return unless @version >= '2.5.4'
|
125
|
+
@test.drop
|
126
|
+
@test.insert([{ :a => 1 }, { :a => 1 }])
|
119
127
|
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
128
|
+
command = BSON::OrderedHash['delete', @test.name,
|
129
|
+
:deletes, [{ :q => { :a => 1 }, :limit => 0 }],
|
130
|
+
:writeConcern, { :w => 1 },
|
131
|
+
:ordered, true]
|
124
132
|
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
133
|
+
result = @db.command(command)
|
134
|
+
assert_equal 2, result['n']
|
135
|
+
assert_equal 1, result['ok']
|
136
|
+
assert_equal 0, @test.count
|
137
|
+
end
|
130
138
|
|
131
|
-
|
132
|
-
|
133
|
-
|
139
|
+
def test_multi_unordered_delete_write_command
|
140
|
+
return unless @version >= '2.5.4'
|
141
|
+
@test.drop
|
142
|
+
@test.insert([{ :a => 1 }, { :a => 1 }])
|
134
143
|
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
144
|
+
command = BSON::OrderedHash['delete', @test.name,
|
145
|
+
:deletes, [{ :q => { :a => 1 }, :limit => 0 }],
|
146
|
+
:writeConcern, { :w => 1 },
|
147
|
+
:ordered, false]
|
139
148
|
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
149
|
+
result = @db.command(command)
|
150
|
+
assert_equal 2, result['n']
|
151
|
+
assert_equal 1, result['ok']
|
152
|
+
assert_equal 0, @test.count
|
153
|
+
end
|
145
154
|
|
146
|
-
|
147
|
-
|
148
|
-
|
155
|
+
def test_delete_write_command_with_no_concern
|
156
|
+
return unless @version >= '2.5.4'
|
157
|
+
@test.drop
|
158
|
+
@test.insert([{ :a => 1 }, { :a => 1 }])
|
149
159
|
|
150
|
-
|
151
|
-
|
152
|
-
|
160
|
+
command = BSON::OrderedHash['delete', @test.name,
|
161
|
+
:deletes, [{ :q => { :a => 1 }, :limit => 0 }],
|
162
|
+
:ordered, false]
|
153
163
|
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
164
|
+
result = @db.command(command)
|
165
|
+
assert_equal 2, result['n']
|
166
|
+
assert_equal 1, result['ok']
|
167
|
+
assert_equal 0, @test.count
|
168
|
+
end
|
159
169
|
|
160
|
-
|
161
|
-
|
162
|
-
|
170
|
+
def test_delete_write_command_with_error
|
171
|
+
return unless @version >= '2.5.4'
|
172
|
+
@test.drop
|
173
|
+
@test.insert([{ :a => 1 }, { :a => 1 }])
|
163
174
|
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
175
|
+
command = BSON::OrderedHash['delete', @test.name,
|
176
|
+
:deletes, [{ :q => { '$set' => { :a => 1 }}, :limit => 0 }],
|
177
|
+
:writeConcern, { :w => 1 },
|
178
|
+
:ordered, false]
|
168
179
|
|
169
|
-
|
170
|
-
|
171
|
-
end
|
180
|
+
assert_raise Mongo::OperationFailure do
|
181
|
+
@db.command(command)
|
172
182
|
end
|
183
|
+
end
|
173
184
|
|
174
|
-
|
175
|
-
|
185
|
+
def test_single_insert_write_command
|
186
|
+
return unless @version >= '2.5.4'
|
187
|
+
@test.drop
|
176
188
|
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
189
|
+
command = BSON::OrderedHash['insert', @test.name,
|
190
|
+
:documents, [{ :a => 1 }],
|
191
|
+
:writeConcern, { :w => 1 },
|
192
|
+
:ordered, false]
|
181
193
|
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
194
|
+
result = @db.command(command)
|
195
|
+
assert_equal 1, result['ok']
|
196
|
+
assert_equal 1, @test.count
|
197
|
+
end
|
186
198
|
|
187
|
-
|
188
|
-
|
199
|
+
def test_multi_ordered_insert_write_command
|
200
|
+
return unless @version >= '2.5.4'
|
201
|
+
@test.drop
|
189
202
|
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
203
|
+
command = BSON::OrderedHash['insert', @test.name,
|
204
|
+
:documents, [{ :a => 1 }, { :a => 2 }],
|
205
|
+
:writeConcern, { :w => 1 },
|
206
|
+
:ordered, true]
|
194
207
|
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
208
|
+
result = @db.command(command)
|
209
|
+
assert_equal 1, result['ok']
|
210
|
+
assert_equal 2, @test.count
|
211
|
+
end
|
199
212
|
|
200
|
-
|
201
|
-
|
213
|
+
def test_multi_unordered_insert_write_command
|
214
|
+
return unless @version >= '2.5.4'
|
215
|
+
@test.drop
|
202
216
|
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
217
|
+
command = BSON::OrderedHash['insert', @test.name,
|
218
|
+
:documents, [{ :a => 1 }, { :a => 2 }],
|
219
|
+
:writeConcern, { :w => 1 },
|
220
|
+
:ordered, false]
|
207
221
|
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
222
|
+
result = @db.command(command)
|
223
|
+
assert_equal 1, result['ok']
|
224
|
+
assert_equal 2, @test.count
|
225
|
+
end
|
212
226
|
|
213
|
-
|
214
|
-
|
227
|
+
def test_insert_write_command_with_no_concern
|
228
|
+
return unless @version >= '2.5.4'
|
229
|
+
@test.drop
|
215
230
|
|
216
|
-
|
217
|
-
|
218
|
-
|
231
|
+
command = BSON::OrderedHash['insert', @test.name,
|
232
|
+
:documents, [{ :a => 1 }, { :a => 2 }],
|
233
|
+
:ordered, false]
|
219
234
|
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
235
|
+
result = @db.command(command)
|
236
|
+
assert_equal 1, result['ok']
|
237
|
+
assert_equal 2, @test.count
|
238
|
+
end
|
224
239
|
|
225
|
-
|
226
|
-
|
227
|
-
|
240
|
+
def test_insert_write_command_with_error
|
241
|
+
return unless @version >= '2.5.4'
|
242
|
+
@test.drop
|
243
|
+
@test.ensure_index([[:a, 1]], { :unique => true })
|
228
244
|
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
245
|
+
command = BSON::OrderedHash['insert', @test.name,
|
246
|
+
:documents, [{ :a => 1 }, { :a => 1 }],
|
247
|
+
:writeConcern, { :w => 1 },
|
248
|
+
:ordered, false]
|
233
249
|
|
234
|
-
|
235
|
-
|
236
|
-
end
|
250
|
+
assert_raise Mongo::OperationFailure do
|
251
|
+
@db.command(command)
|
237
252
|
end
|
253
|
+
end
|
238
254
|
|
239
|
-
|
240
|
-
|
241
|
-
|
255
|
+
def test_single_update_write_command
|
256
|
+
return unless @version >= '2.5.4'
|
257
|
+
@test.drop
|
258
|
+
@test.insert([{ :a => 1 }, { :a => 2 }])
|
242
259
|
|
243
|
-
|
244
|
-
|
245
|
-
|
260
|
+
command = BSON::OrderedHash['update', @test.name,
|
261
|
+
:updates, [{ :q => { :a => 1 }, :u => { '$set' => { :a => 2 }}}],
|
262
|
+
:writeConcern, { :w => 1 }]
|
246
263
|
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
264
|
+
result = @db.command(command)
|
265
|
+
assert_equal 1, result['ok']
|
266
|
+
assert_equal 1, result['n']
|
267
|
+
assert_equal 2, @test.find({ :a => 2 }).count
|
268
|
+
end
|
252
269
|
|
253
|
-
|
254
|
-
|
255
|
-
|
270
|
+
def test_multi_ordered_update_write_command
|
271
|
+
return unless @version >= '2.5.4'
|
272
|
+
@test.drop
|
273
|
+
@test.insert([{ :a => 1 }, { :a => 3 }])
|
256
274
|
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
275
|
+
command = BSON::OrderedHash['update', @test.name,
|
276
|
+
:updates, [
|
277
|
+
{ :q => { :a => 1 }, :u => { '$set' => { :a => 2 }}},
|
278
|
+
{ :q => { :a => 3 }, :u => { '$set' => { :a => 4 }}}
|
279
|
+
],
|
280
|
+
:writeConcern, { :w => 1 },
|
281
|
+
:ordered, true]
|
264
282
|
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
283
|
+
result = @db.command(command)
|
284
|
+
assert_equal 1, result['ok']
|
285
|
+
assert_equal 2, result['n']
|
286
|
+
assert_equal 1, @test.find({ :a => 2 }).count
|
287
|
+
assert_equal 1, @test.find({ :a => 4 }).count
|
288
|
+
end
|
271
289
|
|
272
|
-
|
273
|
-
|
274
|
-
|
290
|
+
def test_multi_unordered_update_write_command
|
291
|
+
return unless @version >= '2.5.4'
|
292
|
+
@test.drop
|
293
|
+
@test.insert([{ :a => 1 }, { :a => 3 }])
|
275
294
|
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
295
|
+
command = BSON::OrderedHash['update', @test.name,
|
296
|
+
:updates, [
|
297
|
+
{ :q => { :a => 1 }, :u => { '$set' => { :a => 2 }}},
|
298
|
+
{ :q => { :a => 3 }, :u => { '$set' => { :a => 4 }}}
|
299
|
+
],
|
300
|
+
:writeConcern, { :w => 1 },
|
301
|
+
:ordered, false]
|
283
302
|
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
303
|
+
result = @db.command(command)
|
304
|
+
assert_equal 1, result['ok']
|
305
|
+
assert_equal 2, result['n']
|
306
|
+
assert_equal 1, @test.find({ :a => 2 }).count
|
307
|
+
assert_equal 1, @test.find({ :a => 4 }).count
|
308
|
+
end
|
290
309
|
|
291
|
-
|
292
|
-
|
293
|
-
|
310
|
+
def test_update_write_command_with_no_concern
|
311
|
+
return unless @version >= '2.5.4'
|
312
|
+
@test.drop
|
313
|
+
@test.insert([{ :a => 1 }, { :a => 3 }])
|
294
314
|
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
315
|
+
command = BSON::OrderedHash['update', @test.name,
|
316
|
+
:updates, [
|
317
|
+
{ :q => { :a => 1 }, :u => { '$set' => { :a => 2 }}},
|
318
|
+
{ :q => { :a => 3 }, :u => { '$set' => { :a => 4 }}}
|
319
|
+
],
|
320
|
+
:ordered, false]
|
301
321
|
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
322
|
+
result = @db.command(command)
|
323
|
+
assert_equal 1, result['ok']
|
324
|
+
assert_equal 2, result['n']
|
325
|
+
assert_equal 1, @test.find({ :a => 2 }).count
|
326
|
+
assert_equal 1, @test.find({ :a => 4 }).count
|
327
|
+
end
|
308
328
|
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
329
|
+
def test_update_write_command_with_error
|
330
|
+
return unless @version >= '2.5.4'
|
331
|
+
@test.drop
|
332
|
+
@test.ensure_index([[:a, 1]], { :unique => true })
|
333
|
+
@test.insert([{ :a => 1 }, { :a => 2 }])
|
313
334
|
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
335
|
+
command = BSON::OrderedHash['update', @test.name,
|
336
|
+
:updates, [
|
337
|
+
{ :q => { :a => 2 }, :u => { '$set' => { :a => 1 }}}
|
338
|
+
],
|
339
|
+
:ordered, false]
|
319
340
|
|
320
|
-
|
321
|
-
|
322
|
-
end
|
341
|
+
assert_raise Mongo::OperationFailure do
|
342
|
+
@db.command(command)
|
323
343
|
end
|
324
344
|
end
|
325
345
|
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
expected_sum = size.times.reduce(:+)
|
346
|
+
def test_aggregation_cursor
|
347
|
+
return unless @version >= '2.5.1'
|
348
|
+
[10, 1000].each do |size|
|
349
|
+
@test.drop
|
350
|
+
size.times {|i| @test.insert({ :_id => i }) }
|
351
|
+
expected_sum = size.times.reduce(:+)
|
333
352
|
|
334
|
-
|
353
|
+
cursor = @test.aggregate(
|
335
354
|
[{ :$project => {:_id => '$_id'}} ],
|
336
355
|
:cursor => {}
|
337
|
-
|
338
|
-
|
339
|
-
assert_equal Mongo::Cursor, cursor.class
|
356
|
+
)
|
340
357
|
|
341
|
-
|
342
|
-
sum += doc['_id']
|
343
|
-
end
|
358
|
+
assert_equal Mongo::Cursor, cursor.class
|
344
359
|
|
345
|
-
|
360
|
+
cursor_sum = cursor.reduce(0) do |sum, doc|
|
361
|
+
sum += doc['_id']
|
346
362
|
end
|
347
|
-
|
363
|
+
|
364
|
+
assert_equal expected_sum, cursor_sum
|
348
365
|
end
|
366
|
+
@test.drop
|
367
|
+
end
|
349
368
|
|
350
|
-
|
351
|
-
|
352
|
-
|
353
|
-
|
369
|
+
def test_aggregation_array
|
370
|
+
return unless @version >= '2.5.1'
|
371
|
+
@test.drop
|
372
|
+
100.times {|i| @test.insert({ :_id => i }) }
|
373
|
+
agg = @test.aggregate([{ :$project => {:_id => '$_id'}} ])
|
354
374
|
|
355
|
-
|
375
|
+
assert agg.kind_of?(Array)
|
356
376
|
|
357
|
-
|
358
|
-
|
377
|
+
@test.drop
|
378
|
+
end
|
359
379
|
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
|
380
|
+
def test_aggregation_cursor_invalid_ops
|
381
|
+
return unless @version >= '2.5.1'
|
382
|
+
cursor = @test.aggregate([], :cursor => {})
|
383
|
+
assert_raise(Mongo::InvalidOperation) { cursor.rewind! }
|
384
|
+
assert_raise(Mongo::InvalidOperation) { cursor.explain }
|
385
|
+
assert_raise(Mongo::InvalidOperation) { cursor.count }
|
366
386
|
end
|
367
387
|
|
368
388
|
def test_aggregation_invalid_read_pref
|
369
389
|
assert_raise Mongo::MongoArgumentError do
|
370
|
-
|
390
|
+
@test.aggregate([], :read => :invalid_read_pref)
|
371
391
|
end
|
372
392
|
end
|
373
393
|
|
374
|
-
|
375
|
-
|
376
|
-
|
377
|
-
|
378
|
-
|
379
|
-
|
380
|
-
|
394
|
+
def test_aggregation_supports_explain
|
395
|
+
return unless @version >= '2.5.3'
|
396
|
+
@db.expects(:command).with do |selector, opts|
|
397
|
+
opts[:explain] == true
|
398
|
+
end.returns({ 'ok' => 1 })
|
399
|
+
@test.aggregate([], :explain => true)
|
400
|
+
end
|
381
401
|
|
382
|
-
|
383
|
-
|
384
|
-
|
385
|
-
|
402
|
+
def test_aggregation_explain_returns_raw_result
|
403
|
+
return unless @version >= '2.5.3'
|
404
|
+
response = @test.aggregate([], :explain => true)
|
405
|
+
assert response['stages']
|
386
406
|
end
|
387
407
|
|
388
408
|
def test_capped_method
|
389
|
-
|
390
|
-
assert
|
391
|
-
|
409
|
+
@db.create_collection('normal')
|
410
|
+
assert !@db['normal'].capped?
|
411
|
+
@db.drop_collection('normal')
|
392
412
|
|
393
|
-
|
394
|
-
assert
|
395
|
-
|
413
|
+
@db.create_collection('c', :capped => true, :size => 100_000)
|
414
|
+
assert @db['c'].capped?
|
415
|
+
@db.drop_collection('c')
|
396
416
|
end
|
397
417
|
|
398
418
|
def test_optional_pk_factory
|
399
|
-
@coll_default_pk =
|
419
|
+
@coll_default_pk = @db.collection('stuff')
|
400
420
|
assert_equal BSON::ObjectId, @coll_default_pk.pk_factory
|
401
|
-
@coll_default_pk =
|
421
|
+
@coll_default_pk = @db.create_collection('more-stuff')
|
402
422
|
assert_equal BSON::ObjectId, @coll_default_pk.pk_factory
|
403
423
|
|
404
424
|
# Create a db with a pk_factory.
|
405
|
-
|
406
|
-
|
407
|
-
|
408
|
-
|
425
|
+
client = MongoClient.new(ENV['MONGO_RUBY_DRIVER_HOST'] || 'localhost',
|
426
|
+
ENV['MONGO_RUBY_DRIVER_PORT'] || MongoClient::DEFAULT_PORT)
|
427
|
+
client[TEST_DB].authenticate(TEST_USER, TEST_USER_PWD)
|
428
|
+
db = client.db(TEST_DB, :pk => Object.new)
|
429
|
+
|
430
|
+
coll = db.collection('coll-with-pk')
|
431
|
+
assert coll.pk_factory.is_a?(Object)
|
409
432
|
|
410
|
-
|
411
|
-
assert
|
433
|
+
coll = db.create_collection('created_coll_with_pk')
|
434
|
+
assert coll.pk_factory.is_a?(Object)
|
412
435
|
end
|
413
436
|
|
414
437
|
class PKTest
|
@@ -418,46 +441,46 @@ class CollectionTest < Test::Unit::TestCase
|
|
418
441
|
|
419
442
|
def test_pk_factory_on_collection
|
420
443
|
silently do
|
421
|
-
@coll = Collection.new('foo',
|
444
|
+
@coll = Collection.new('foo', @db, PKTest)
|
422
445
|
assert_equal PKTest, @coll.pk_factory
|
423
446
|
end
|
424
447
|
|
425
|
-
@coll2 = Collection.new('foo',
|
448
|
+
@coll2 = Collection.new('foo', @db, :pk => PKTest)
|
426
449
|
assert_equal PKTest, @coll2.pk_factory
|
427
450
|
end
|
428
451
|
|
429
452
|
def test_valid_names
|
430
453
|
assert_raise Mongo::InvalidNSName do
|
431
|
-
|
454
|
+
@db["te$t"]
|
432
455
|
end
|
433
456
|
|
434
457
|
assert_raise Mongo::InvalidNSName do
|
435
|
-
|
458
|
+
@db['$main']
|
436
459
|
end
|
437
460
|
|
438
|
-
assert
|
439
|
-
assert
|
461
|
+
assert @db['$cmd']
|
462
|
+
assert @db['oplog.$main']
|
440
463
|
end
|
441
464
|
|
442
465
|
def test_collection
|
443
|
-
assert_kind_of Collection,
|
444
|
-
assert_equal
|
445
|
-
assert_equal
|
466
|
+
assert_kind_of Collection, @db["test"]
|
467
|
+
assert_equal @db["test"].name(), @db.collection("test").name()
|
468
|
+
assert_equal @db["test"].name(), @db[:test].name()
|
446
469
|
|
447
|
-
assert_kind_of Collection,
|
448
|
-
assert_equal
|
449
|
-
assert_equal
|
470
|
+
assert_kind_of Collection, @db["test"]["foo"]
|
471
|
+
assert_equal @db["test"]["foo"].name(), @db.collection("test.foo").name()
|
472
|
+
assert_equal @db["test"]["foo"].name(), @db["test.foo"].name()
|
450
473
|
|
451
|
-
|
452
|
-
|
453
|
-
assert_equal 5,
|
474
|
+
@db["test"]["foo"].remove
|
475
|
+
@db["test"]["foo"].insert("x" => 5)
|
476
|
+
assert_equal 5, @db.collection("test.foo").find_one()["x"]
|
454
477
|
end
|
455
478
|
|
456
479
|
def test_rename_collection
|
457
|
-
|
458
|
-
|
480
|
+
@db.drop_collection('foo1')
|
481
|
+
@db.drop_collection('bar1')
|
459
482
|
|
460
|
-
@col =
|
483
|
+
@col = @db.create_collection('foo1')
|
461
484
|
assert_equal 'foo1', @col.name
|
462
485
|
|
463
486
|
@col.rename('bar1')
|
@@ -465,69 +488,69 @@ class CollectionTest < Test::Unit::TestCase
|
|
465
488
|
end
|
466
489
|
|
467
490
|
def test_nil_id
|
468
|
-
assert_equal 5,
|
469
|
-
assert_equal 5,
|
470
|
-
assert_equal nil,
|
471
|
-
assert_equal "baz",
|
491
|
+
assert_equal 5, @test.insert({"_id" => 5, "foo" => "bar"})
|
492
|
+
assert_equal 5, @test.save({"_id" => 5, "foo" => "baz"})
|
493
|
+
assert_equal nil, @test.find_one("foo" => "bar")
|
494
|
+
assert_equal "baz", @test.find_one(:_id => 5)["foo"]
|
472
495
|
assert_raise OperationFailure do
|
473
|
-
|
496
|
+
@test.insert({"_id" => 5, "foo" => "bar"})
|
474
497
|
end
|
475
498
|
|
476
|
-
assert_equal nil,
|
477
|
-
assert_equal nil,
|
478
|
-
assert_equal nil,
|
479
|
-
assert_equal "baz",
|
499
|
+
assert_equal nil, @test.insert({"_id" => nil, "foo" => "bar"})
|
500
|
+
assert_equal nil, @test.save({"_id" => nil, "foo" => "baz"})
|
501
|
+
assert_equal nil, @test.find_one("foo" => "bar")
|
502
|
+
assert_equal "baz", @test.find_one(:_id => nil)["foo"]
|
480
503
|
assert_raise OperationFailure do
|
481
|
-
|
504
|
+
@test.insert({"_id" => nil, "foo" => "bar"})
|
482
505
|
end
|
483
506
|
assert_raise OperationFailure do
|
484
|
-
|
507
|
+
@test.insert({:_id => nil, "foo" => "bar"})
|
485
508
|
end
|
486
509
|
end
|
487
510
|
|
488
|
-
|
489
|
-
|
490
|
-
|
491
|
-
|
492
|
-
|
493
|
-
|
494
|
-
|
495
|
-
|
496
|
-
|
497
|
-
|
511
|
+
def setup_for_distinct
|
512
|
+
return unless @version > "1.1"
|
513
|
+
@test.remove
|
514
|
+
@test.insert([{:a => 0, :b => {:c => "a"}},
|
515
|
+
{:a => 1, :b => {:c => "b"}},
|
516
|
+
{:a => 1, :b => {:c => "c"}},
|
517
|
+
{:a => 2, :b => {:c => "a"}},
|
518
|
+
{:a => 3},
|
519
|
+
{:a => 3}])
|
520
|
+
end
|
498
521
|
|
499
|
-
|
500
|
-
|
501
|
-
|
502
|
-
|
503
|
-
|
522
|
+
def test_distinct_queries
|
523
|
+
return unless @version > "1.1"
|
524
|
+
setup_for_distinct
|
525
|
+
assert_equal [0, 1, 2, 3], @test.distinct(:a).sort
|
526
|
+
assert_equal ["a", "b", "c"], @test.distinct("b.c").sort
|
527
|
+
end
|
504
528
|
|
505
|
-
|
506
|
-
|
507
|
-
|
508
|
-
|
509
|
-
|
529
|
+
def test_filter_collection_with_query
|
530
|
+
return unless @version >= "1.2"
|
531
|
+
setup_for_distinct
|
532
|
+
assert_equal [2, 3], @test.distinct(:a, {:a => {"$gt" => 1}}).sort
|
533
|
+
end
|
510
534
|
|
511
|
-
|
512
|
-
|
513
|
-
|
514
|
-
|
515
|
-
end
|
535
|
+
def test_filter_nested_objects
|
536
|
+
return unless @version >= "1.2"
|
537
|
+
setup_for_distinct
|
538
|
+
assert_equal ["a", "b"], @test.distinct("b.c", {"b.c" => {"$ne" => "c"}}).sort
|
516
539
|
end
|
517
540
|
|
518
541
|
def test_safe_insert
|
519
|
-
|
542
|
+
@test.create_index("hello", :unique => true)
|
520
543
|
begin
|
521
544
|
a = {"hello" => "world"}
|
522
|
-
|
523
|
-
|
524
|
-
assert(
|
545
|
+
@test.insert(a)
|
546
|
+
@test.insert(a, :w => 0)
|
547
|
+
assert(@db.get_last_error['err'].include?("11000"))
|
525
548
|
|
526
549
|
assert_raise OperationFailure do
|
527
|
-
|
550
|
+
@test.insert(a)
|
528
551
|
end
|
529
552
|
ensure
|
530
|
-
|
553
|
+
@test.drop_indexes
|
531
554
|
end
|
532
555
|
end
|
533
556
|
|
@@ -536,15 +559,15 @@ class CollectionTest < Test::Unit::TestCase
|
|
536
559
|
docs << {:foo => 1}
|
537
560
|
docs << {:foo => 2}
|
538
561
|
docs << {:foo => 3}
|
539
|
-
response =
|
562
|
+
response = @test.insert(docs)
|
540
563
|
assert_equal 3, response.length
|
541
564
|
assert response.all? {|id| id.is_a?(BSON::ObjectId)}
|
542
|
-
assert_equal 3,
|
565
|
+
assert_equal 3, @test.count
|
543
566
|
end
|
544
567
|
|
545
568
|
def test_bulk_insert_with_continue_on_error
|
546
|
-
if
|
547
|
-
|
569
|
+
if @version >= "2.0"
|
570
|
+
@test.create_index([["foo", 1]], :unique => true)
|
548
571
|
begin
|
549
572
|
docs = []
|
550
573
|
docs << {:foo => 1}
|
@@ -552,10 +575,10 @@ class CollectionTest < Test::Unit::TestCase
|
|
552
575
|
docs << {:foo => 2}
|
553
576
|
docs << {:foo => 3}
|
554
577
|
assert_raise OperationFailure do
|
555
|
-
|
578
|
+
@test.insert(docs)
|
556
579
|
end
|
557
|
-
assert_equal 1,
|
558
|
-
|
580
|
+
assert_equal 1, @test.count
|
581
|
+
@test.remove
|
559
582
|
|
560
583
|
docs = []
|
561
584
|
docs << {:foo => 1}
|
@@ -563,13 +586,13 @@ class CollectionTest < Test::Unit::TestCase
|
|
563
586
|
docs << {:foo => 2}
|
564
587
|
docs << {:foo => 3}
|
565
588
|
assert_raise OperationFailure do
|
566
|
-
|
589
|
+
@test.insert(docs, :continue_on_error => true)
|
567
590
|
end
|
568
|
-
assert_equal 3,
|
591
|
+
assert_equal 3, @test.count
|
569
592
|
|
570
|
-
|
593
|
+
@test.remove
|
571
594
|
ensure
|
572
|
-
|
595
|
+
@test.drop_index("foo_1")
|
573
596
|
end
|
574
597
|
end
|
575
598
|
end
|
@@ -578,8 +601,8 @@ class CollectionTest < Test::Unit::TestCase
|
|
578
601
|
docs = []
|
579
602
|
docs << {:foo => 1}
|
580
603
|
docs << {:bar => 1}
|
581
|
-
doc_ids, error_docs =
|
582
|
-
assert_equal 2,
|
604
|
+
doc_ids, error_docs = @test.insert(docs, :collect_on_error => true)
|
605
|
+
assert_equal 2, @test.count
|
583
606
|
assert_equal 2, doc_ids.count
|
584
607
|
assert_equal error_docs, []
|
585
608
|
end
|
@@ -593,12 +616,12 @@ class CollectionTest < Test::Unit::TestCase
|
|
593
616
|
invalid_docs << {'invalid.key' => 1}
|
594
617
|
docs += invalid_docs
|
595
618
|
assert_raise BSON::InvalidKeyName do
|
596
|
-
|
619
|
+
@test.insert(docs, :collect_on_error => false)
|
597
620
|
end
|
598
|
-
assert_equal 2,
|
621
|
+
assert_equal 2, @test.count
|
599
622
|
|
600
|
-
doc_ids, error_docs =
|
601
|
-
assert_equal 2,
|
623
|
+
doc_ids, error_docs = @test.insert(docs, :collect_on_error => true)
|
624
|
+
assert_equal 2, @test.count
|
602
625
|
assert_equal 2, doc_ids.count
|
603
626
|
assert_equal error_docs, invalid_docs
|
604
627
|
end
|
@@ -614,12 +637,12 @@ class CollectionTest < Test::Unit::TestCase
|
|
614
637
|
docs += invalid_docs
|
615
638
|
|
616
639
|
assert_raise BSON::InvalidStringEncoding do
|
617
|
-
|
640
|
+
@test.insert(docs, :collect_on_error => false)
|
618
641
|
end
|
619
|
-
assert_equal 2,
|
642
|
+
assert_equal 2, @test.count
|
620
643
|
|
621
|
-
doc_ids, error_docs =
|
622
|
-
assert_equal 2,
|
644
|
+
doc_ids, error_docs = @test.insert(docs, :collect_on_error => true)
|
645
|
+
assert_equal 2, @test.count
|
623
646
|
assert_equal 2, doc_ids.count
|
624
647
|
assert_equal error_docs, invalid_docs
|
625
648
|
end
|
@@ -627,20 +650,20 @@ class CollectionTest < Test::Unit::TestCase
|
|
627
650
|
def test_insert_one_error_doc_with_collect_on_error
|
628
651
|
invalid_doc = {'$invalid-key' => 1}
|
629
652
|
invalid_docs = [invalid_doc]
|
630
|
-
doc_ids, error_docs =
|
653
|
+
doc_ids, error_docs = @test.insert(invalid_docs, :collect_on_error => true)
|
631
654
|
assert_equal [], doc_ids
|
632
655
|
assert_equal [invalid_doc], error_docs
|
633
656
|
end
|
634
657
|
|
635
658
|
def test_insert_empty_docs_raises_exception
|
636
659
|
assert_raise OperationFailure do
|
637
|
-
|
660
|
+
@test.insert([])
|
638
661
|
end
|
639
662
|
end
|
640
663
|
|
641
664
|
def test_insert_empty_docs_with_collect_on_error_raises_exception
|
642
665
|
assert_raise OperationFailure do
|
643
|
-
|
666
|
+
@test.insert([], :collect_on_error => true)
|
644
667
|
end
|
645
668
|
end
|
646
669
|
|
@@ -648,11 +671,11 @@ class CollectionTest < Test::Unit::TestCase
|
|
648
671
|
conn = standard_connection(:connect => false)
|
649
672
|
admin_db = Object.new
|
650
673
|
admin_db.expects(:command).returns({
|
651
|
-
|
652
|
-
|
653
|
-
|
654
|
-
|
655
|
-
|
674
|
+
'ok' => 1,
|
675
|
+
'ismaster' => 1,
|
676
|
+
'maxBsonObjectSize' => LIMITED_MAX_BSON_SIZE,
|
677
|
+
'maxMessageSizeBytes' => LIMITED_MAX_MESSAGE_SIZE
|
678
|
+
})
|
656
679
|
conn.expects(:[]).with('admin').returns(admin_db)
|
657
680
|
conn.connect
|
658
681
|
return conn.db(TEST_DB)["test"]
|
@@ -671,13 +694,13 @@ class CollectionTest < Test::Unit::TestCase
|
|
671
694
|
end
|
672
695
|
|
673
696
|
def test_chunking_batch_insert
|
674
|
-
|
675
|
-
|
676
|
-
|
677
|
-
|
678
|
-
|
679
|
-
|
680
|
-
|
697
|
+
docs = []
|
698
|
+
10.times do
|
699
|
+
docs << {'foo' => 'a' * LIMITED_VALID_VALUE_SIZE}
|
700
|
+
end
|
701
|
+
limited_collection.insert(docs)
|
702
|
+
assert_equal 10, limited_collection.count
|
703
|
+
end
|
681
704
|
|
682
705
|
def test_chunking_batch_insert_without_collect_on_error
|
683
706
|
docs = []
|
@@ -696,8 +719,8 @@ class CollectionTest < Test::Unit::TestCase
|
|
696
719
|
end
|
697
720
|
|
698
721
|
def test_chunking_batch_insert_with_collect_on_error
|
699
|
-
|
700
|
-
|
722
|
+
# Broken for current JRuby
|
723
|
+
if RUBY_PLATFORM == 'java' then return end
|
701
724
|
docs = []
|
702
725
|
4.times do
|
703
726
|
docs << {'foo' => 'a' * LIMITED_VALID_VALUE_SIZE}
|
@@ -797,17 +820,17 @@ class CollectionTest < Test::Unit::TestCase
|
|
797
820
|
end
|
798
821
|
|
799
822
|
assert limited_collection.update(
|
800
|
-
|
801
|
-
|
802
|
-
|
823
|
+
{'foo' => 'a' * LIMITED_VALID_VALUE_SIZE},
|
824
|
+
{'foo' => 'a' * LIMITED_VALID_VALUE_SIZE}
|
825
|
+
)
|
803
826
|
end
|
804
827
|
|
805
828
|
def test_maximum_query_size
|
806
829
|
assert limited_collection.find({'foo' => 'a' * LIMITED_VALID_VALUE_SIZE}).to_a
|
807
830
|
assert limited_collection.find(
|
808
|
-
|
809
|
-
|
810
|
-
|
831
|
+
{'foo' => 'a' * LIMITED_VALID_VALUE_SIZE},
|
832
|
+
{:fields => {'foo' => 'a' * LIMITED_VALID_VALUE_SIZE}}
|
833
|
+
).to_a
|
811
834
|
|
812
835
|
assert_raise InvalidDocument do
|
813
836
|
limited_collection.find({'foo' => 'a' * LIMITED_INVALID_VALUE_SIZE}).to_a
|
@@ -821,138 +844,120 @@ class CollectionTest < Test::Unit::TestCase
|
|
821
844
|
end
|
822
845
|
end
|
823
846
|
|
824
|
-
#if
|
847
|
+
#if @version >= "1.5.1"
|
825
848
|
# def test_safe_mode_with_advanced_safe_with_invalid_options
|
826
849
|
# assert_raise_error ArgumentError, "Unknown key(s): wtime" do
|
827
|
-
#
|
850
|
+
# @test.insert({:foo => 1}, :w => 2, :wtime => 1, :fsync => true)
|
828
851
|
# end
|
829
852
|
# assert_raise_error ArgumentError, "Unknown key(s): wtime" do
|
830
|
-
#
|
853
|
+
# @test.update({:foo => 1}, {:foo => 2}, :w => 2, :wtime => 1, :fsync => true)
|
831
854
|
# end
|
832
855
|
#
|
833
856
|
# assert_raise_error ArgumentError, "Unknown key(s): wtime" do
|
834
|
-
#
|
857
|
+
# @test.remove({:foo => 2}, :w => 2, :wtime => 1, :fsync => true)
|
835
858
|
# end
|
836
859
|
# end
|
837
860
|
#end
|
838
861
|
|
839
862
|
def test_safe_mode_with_journal_commit_option
|
840
|
-
with_default_journaling(
|
841
|
-
|
842
|
-
|
843
|
-
|
863
|
+
with_default_journaling(@client) do
|
864
|
+
@test.insert({:foo => 1}, :j => true)
|
865
|
+
@test.update({:foo => 1}, {:foo => 2}, :j => true)
|
866
|
+
@test.remove({:foo => 2}, :j => true)
|
844
867
|
end
|
845
868
|
end
|
846
869
|
|
847
|
-
|
848
|
-
|
849
|
-
|
850
|
-
ex = assert_raise Mongo::WriteConcernError do
|
851
|
-
@@test.insert({:foo => 1}, :j => true)
|
852
|
-
end
|
853
|
-
result = ex.result
|
854
|
-
assert_true result.has_key?("jnote")
|
855
|
-
end
|
856
|
-
end
|
857
|
-
|
858
|
-
def test_wnote_raises_exception_with_err_not_nil
|
870
|
+
def test_jnote_raises_exception
|
871
|
+
return unless @version < "2.5.3"
|
872
|
+
with_no_journaling(@client) do
|
859
873
|
ex = assert_raise Mongo::WriteConcernError do
|
860
|
-
|
874
|
+
@test.insert({:foo => 1}, :j => true)
|
861
875
|
end
|
862
876
|
result = ex.result
|
863
|
-
|
864
|
-
assert_true result.has_key?("wnote")
|
877
|
+
assert_true result.has_key?("jnote")
|
865
878
|
end
|
866
879
|
end
|
867
880
|
|
881
|
+
def test_wnote_raises_exception_with_err_not_nil
|
882
|
+
return unless @version < "2.5.3"
|
883
|
+
ex = assert_raise Mongo::WriteConcernError do
|
884
|
+
@test.insert({:foo => 1}, :w => 2)
|
885
|
+
end
|
886
|
+
result = ex.result
|
887
|
+
assert_not_nil result["err"]
|
888
|
+
assert_true result.has_key?("wnote")
|
889
|
+
end
|
890
|
+
|
868
891
|
def test_update
|
869
|
-
id1 =
|
870
|
-
|
871
|
-
assert_equal 1,
|
872
|
-
assert_equal 6,
|
892
|
+
id1 = @test.save("x" => 5)
|
893
|
+
@test.update({}, {"$inc" => {"x" => 1}})
|
894
|
+
assert_equal 1, @test.count()
|
895
|
+
assert_equal 6, @test.find_one(:_id => id1)["x"]
|
873
896
|
|
874
|
-
id2 =
|
875
|
-
|
876
|
-
assert_equal 7,
|
877
|
-
assert_equal 1,
|
897
|
+
id2 = @test.save("x" => 1)
|
898
|
+
@test.update({"x" => 6}, {"$inc" => {"x" => 1}})
|
899
|
+
assert_equal 7, @test.find_one(:_id => id1)["x"]
|
900
|
+
assert_equal 1, @test.find_one(:_id => id2)["x"]
|
878
901
|
end
|
879
902
|
|
880
|
-
|
881
|
-
|
882
|
-
|
883
|
-
|
884
|
-
|
903
|
+
def test_update_check_keys
|
904
|
+
return unless @version < "2.5.3"
|
905
|
+
@test.save("x" => 1)
|
906
|
+
@test.update({"x" => 1}, {"$set" => {"a.b" => 2}})
|
907
|
+
assert_equal 2, @test.find_one("x" => 1)["a"]["b"]
|
885
908
|
|
886
|
-
|
887
|
-
|
888
|
-
end
|
909
|
+
assert_raise_error BSON::InvalidKeyName do
|
910
|
+
@test.update({"x" => 1}, {"a.b" => 3})
|
889
911
|
end
|
890
912
|
end
|
891
913
|
|
892
|
-
|
893
|
-
|
894
|
-
|
895
|
-
|
896
|
-
|
897
|
-
|
914
|
+
def test_multi_update
|
915
|
+
return unless @version >= "1.1.3"
|
916
|
+
@test.save("num" => 10)
|
917
|
+
@test.save("num" => 10)
|
918
|
+
@test.save("num" => 10)
|
919
|
+
assert_equal 3, @test.count
|
898
920
|
|
899
|
-
|
900
|
-
|
901
|
-
|
902
|
-
end
|
921
|
+
@test.update({"num" => 10}, {"$set" => {"num" => 100}}, :multi => true)
|
922
|
+
@test.find.each do |doc|
|
923
|
+
assert_equal 100, doc["num"]
|
903
924
|
end
|
904
925
|
end
|
905
926
|
|
906
927
|
def test_upsert
|
907
|
-
|
908
|
-
|
928
|
+
@test.update({"page" => "/"}, {"$inc" => {"count" => 1}}, :upsert => true)
|
929
|
+
@test.update({"page" => "/"}, {"$inc" => {"count" => 1}}, :upsert => true)
|
909
930
|
|
910
|
-
assert_equal 1,
|
911
|
-
assert_equal 2,
|
931
|
+
assert_equal 1, @test.count()
|
932
|
+
assert_equal 2, @test.find_one()["count"]
|
912
933
|
end
|
913
934
|
|
914
|
-
|
915
|
-
|
916
|
-
|
917
|
-
|
918
|
-
|
919
|
-
@@test.update({}, {"$inc" => {"x" => 1}})
|
920
|
-
assert @@db.error?
|
921
|
-
|
922
|
-
# Can't change an index.
|
923
|
-
assert_raise OperationFailure do
|
924
|
-
@@test.update({}, {"$inc" => {"x" => 1}})
|
925
|
-
end
|
926
|
-
@@test.drop
|
927
|
-
end
|
928
|
-
else
|
929
|
-
def test_safe_update
|
930
|
-
@@test.create_index("x", :unique => true)
|
931
|
-
@@test.insert("x" => 5)
|
932
|
-
@@test.insert("x" => 10)
|
935
|
+
def test_safe_update
|
936
|
+
@test.create_index("x", :unique => true)
|
937
|
+
@test.insert("x" => 5)
|
938
|
+
@test.insert("x" => 10)
|
933
939
|
|
934
|
-
|
935
|
-
|
936
|
-
|
940
|
+
# Can update an indexed collection.
|
941
|
+
@test.update({}, {"$inc" => {"x" => 1}})
|
942
|
+
assert !@db.error?
|
937
943
|
|
938
|
-
|
939
|
-
|
940
|
-
|
941
|
-
end
|
942
|
-
@@test.drop
|
944
|
+
# Can't duplicate an index.
|
945
|
+
assert_raise OperationFailure do
|
946
|
+
@test.update({}, {"x" => 10})
|
943
947
|
end
|
948
|
+
@test.drop
|
944
949
|
end
|
945
950
|
|
946
951
|
def test_safe_save
|
947
|
-
|
952
|
+
@test.create_index("hello", :unique => true)
|
948
953
|
|
949
|
-
|
950
|
-
|
954
|
+
@test.save("hello" => "world")
|
955
|
+
@test.save({"hello" => "world"}, :w => 0)
|
951
956
|
|
952
957
|
assert_raise OperationFailure do
|
953
|
-
|
958
|
+
@test.save({"hello" => "world"})
|
954
959
|
end
|
955
|
-
|
960
|
+
@test.drop
|
956
961
|
end
|
957
962
|
|
958
963
|
def test_mocked_safe_remove
|
@@ -979,161 +984,216 @@ class CollectionTest < Test::Unit::TestCase
|
|
979
984
|
end
|
980
985
|
|
981
986
|
def test_remove_return_value
|
982
|
-
assert_equal true,
|
987
|
+
assert_equal true, @test.remove({}, :w => 0)
|
983
988
|
end
|
984
989
|
|
985
990
|
def test_remove_with_limit
|
986
|
-
|
987
|
-
|
988
|
-
assert_equal 2,
|
989
|
-
|
990
|
-
assert_equal 0,
|
991
|
+
@test.insert([{:n => 1},{:n => 2},{:n => 3}])
|
992
|
+
@test.remove({}, :limit => 1)
|
993
|
+
assert_equal 2, @test.count
|
994
|
+
@test.remove({}, :limit => 0)
|
995
|
+
assert_equal 0, @test.count
|
991
996
|
end
|
992
997
|
|
993
998
|
def test_count
|
994
|
-
|
999
|
+
@test.drop
|
1000
|
+
|
1001
|
+
assert_equal 0, @test.count
|
1002
|
+
@test.save(:x => 1)
|
1003
|
+
@test.save(:x => 2)
|
1004
|
+
assert_equal 2, @test.count
|
1005
|
+
|
1006
|
+
assert_equal 1, @test.count(:query => {:x => 1})
|
1007
|
+
assert_equal 1, @test.count(:limit => 1)
|
1008
|
+
assert_equal 0, @test.count(:skip => 2)
|
1009
|
+
end
|
1010
|
+
|
1011
|
+
def test_count_with_hint
|
1012
|
+
@test.drop
|
1013
|
+
@test.save(:i => 1)
|
1014
|
+
@test.save(:i => 2)
|
1015
|
+
assert_equal 2, @test.count
|
1016
|
+
|
1017
|
+
@test.ensure_index(BSON::OrderedHash[:i, Mongo::ASCENDING])
|
1018
|
+
|
1019
|
+
# Check that a named_hint can be specified
|
1020
|
+
assert_equal 1, @test.count(:query => { :i => 1 }, :named_hint => '_id_')
|
1021
|
+
assert_equal 2, @test.count(:query => { }, :named_hint => '_id_')
|
1022
|
+
|
1023
|
+
# Verify that the hint is being sent to the server by providing a bad hint
|
1024
|
+
if @version > '2.6'
|
1025
|
+
assert_raise Mongo::OperationFailure do
|
1026
|
+
@test.count(:query => { :i => 1 }, :hint => 'bad_hint')
|
1027
|
+
end
|
1028
|
+
else
|
1029
|
+
assert_equal 1, @test.count(:query => { :i => 1 }, :hint => 'bad_hint')
|
1030
|
+
end
|
1031
|
+
|
1032
|
+
# Verify that the named_hint is being sent to the server by providing a bad hint
|
1033
|
+
if @version > '2.6'
|
1034
|
+
assert_raise Mongo::OperationFailure do
|
1035
|
+
@test.count(:query => { :i => 1 }, :named_hint => 'bad_hint')
|
1036
|
+
end
|
1037
|
+
else
|
1038
|
+
assert_equal 1, @test.count(:query => { :i => 1 }, :named_hint => 'bad_hint')
|
1039
|
+
end
|
1040
|
+
|
1041
|
+
@test.ensure_index(BSON::OrderedHash[:x, Mongo::ASCENDING], :sparse => true)
|
995
1042
|
|
996
|
-
|
997
|
-
|
998
|
-
|
999
|
-
assert_equal
|
1043
|
+
# The sparse index won't have any entries.
|
1044
|
+
# Check that count returns 0 when using the hint.
|
1045
|
+
expected = @version > '2.6' ? 0 : 1
|
1046
|
+
assert_equal expected, @test.count(:query => { :i => 1 }, :hint => { 'x' => 1 })
|
1047
|
+
assert_equal expected, @test.count(:query => { :i => 1 }, :hint => 'x')
|
1048
|
+
assert_equal expected, @test.count(:query => { :i => 1 }, :named_hint => 'x_1')
|
1000
1049
|
|
1001
|
-
|
1002
|
-
|
1003
|
-
assert_equal
|
1050
|
+
# Verify that the hint / named hint set on the collection is used.
|
1051
|
+
@test.hint = { 'x' => 1 }
|
1052
|
+
assert_equal expected, @test.count(:query => { :i => 1 })
|
1053
|
+
|
1054
|
+
@test.hint = 'x'
|
1055
|
+
assert_equal expected, @test.count(:query => { :i => 1 })
|
1056
|
+
|
1057
|
+
# The driver should allow x_1, but the code sets named_hint to @hint without
|
1058
|
+
# normalizing.
|
1059
|
+
@test.named_hint = 'x'
|
1060
|
+
assert_equal expected, @test.count(:query => { :i => 1 })
|
1061
|
+
|
1062
|
+
assert_equal 2, @test.count(:query => { }, :hint => 'x')
|
1063
|
+
assert_equal 2, @test.count(:query => { }, :named_hint => 'x_1')
|
1004
1064
|
end
|
1005
1065
|
|
1006
1066
|
# Note: #size is just an alias for #count.
|
1007
1067
|
def test_size
|
1008
|
-
|
1068
|
+
@test.drop
|
1009
1069
|
|
1010
|
-
assert_equal 0,
|
1011
|
-
assert_equal
|
1012
|
-
|
1013
|
-
|
1014
|
-
assert_equal
|
1070
|
+
assert_equal 0, @test.count
|
1071
|
+
assert_equal @test.size, @test.count
|
1072
|
+
@test.save("x" => 1)
|
1073
|
+
@test.save("x" => 2)
|
1074
|
+
assert_equal @test.size, @test.count
|
1015
1075
|
end
|
1016
1076
|
|
1017
1077
|
def test_no_timeout_option
|
1018
|
-
|
1078
|
+
@test.drop
|
1019
1079
|
|
1020
1080
|
assert_raise ArgumentError, "Timeout can be set to false only when #find is invoked with a block." do
|
1021
|
-
|
1081
|
+
@test.find({}, :timeout => false)
|
1022
1082
|
end
|
1023
1083
|
|
1024
|
-
|
1084
|
+
@test.find({}, :timeout => false) do |cursor|
|
1025
1085
|
assert_equal 0, cursor.count
|
1026
1086
|
end
|
1027
1087
|
|
1028
|
-
|
1029
|
-
|
1030
|
-
|
1088
|
+
@test.save("x" => 1)
|
1089
|
+
@test.save("x" => 2)
|
1090
|
+
@test.find({}, :timeout => false) do |cursor|
|
1031
1091
|
assert_equal 2, cursor.count
|
1032
1092
|
end
|
1033
1093
|
end
|
1034
1094
|
|
1035
1095
|
def test_default_timeout
|
1036
|
-
cursor =
|
1096
|
+
cursor = @test.find
|
1037
1097
|
assert_equal true, cursor.timeout
|
1038
1098
|
end
|
1039
1099
|
|
1040
1100
|
def test_fields_as_hash
|
1041
|
-
|
1101
|
+
@test.save(:a => 1, :b => 1, :c => 1)
|
1042
1102
|
|
1043
|
-
doc =
|
1103
|
+
doc = @test.find_one({:a => 1}, :fields => {:b => 0})
|
1044
1104
|
assert_nil doc['b']
|
1045
1105
|
assert doc['a']
|
1046
1106
|
assert doc['c']
|
1047
1107
|
|
1048
|
-
doc =
|
1108
|
+
doc = @test.find_one({:a => 1}, :fields => {:a => 1, :b => 1})
|
1049
1109
|
assert_nil doc['c']
|
1050
1110
|
assert doc['a']
|
1051
1111
|
assert doc['b']
|
1052
1112
|
|
1053
1113
|
|
1054
1114
|
assert_raise Mongo::OperationFailure do
|
1055
|
-
|
1115
|
+
@test.find_one({:a => 1}, :fields => {:a => 1, :b => 0})
|
1056
1116
|
end
|
1057
1117
|
end
|
1058
1118
|
|
1059
|
-
if @@version >= '2.5.5'
|
1060
|
-
def test_meta_field_projection
|
1061
|
-
@@test.save({ :t => 'spam eggs and spam'})
|
1062
|
-
@@test.save({ :t => 'spam'})
|
1063
|
-
@@test.save({ :t => 'egg sausage and bacon'})
|
1064
1119
|
|
1065
|
-
|
1066
|
-
|
1067
|
-
|
1068
|
-
|
1120
|
+
def test_meta_field_projection
|
1121
|
+
return unless @version >= '2.5.5'
|
1122
|
+
@test.save({ :t => 'spam eggs and spam'})
|
1123
|
+
@test.save({ :t => 'spam'})
|
1124
|
+
@test.save({ :t => 'egg sausage and bacon'})
|
1069
1125
|
|
1070
|
-
|
1071
|
-
|
1072
|
-
|
1073
|
-
|
1126
|
+
@test.ensure_index([[:t, 'text']])
|
1127
|
+
assert @test.find_one({ :$text => { :$search => 'spam' }},
|
1128
|
+
{ :fields => [:t, { :score => { :$meta => 'textScore' } }] })
|
1129
|
+
end
|
1074
1130
|
|
1075
|
-
|
1076
|
-
|
1077
|
-
|
1078
|
-
|
1131
|
+
def test_sort_by_meta
|
1132
|
+
return unless @version >= '2.5.5'
|
1133
|
+
@test.save({ :t => 'spam eggs and spam'})
|
1134
|
+
@test.save({ :t => 'spam'})
|
1135
|
+
@test.save({ :t => 'egg sausage and bacon'})
|
1136
|
+
|
1137
|
+
@test.ensure_index([[:t, 'text']])
|
1138
|
+
assert @test.find({ :$text => { :$search => 'spam' }}).sort([:score, { '$meta' => 'textScore' }])
|
1139
|
+
assert @test.find({ :$text => { :$search => 'spam' }}).sort(:score => { '$meta' =>'textScore' })
|
1079
1140
|
end
|
1080
1141
|
|
1081
|
-
|
1082
|
-
|
1083
|
-
|
1142
|
+
def test_fields_with_slice
|
1143
|
+
return unless @version >= "1.5.1"
|
1144
|
+
@test.save({:foo => [1, 2, 3, 4, 5, 6], :test => 'slice'})
|
1084
1145
|
|
1085
|
-
|
1086
|
-
|
1087
|
-
|
1088
|
-
end
|
1146
|
+
doc = @test.find_one({:test => 'slice'}, :fields => {'foo' => {'$slice' => [0, 3]}})
|
1147
|
+
assert_equal [1, 2, 3], doc['foo']
|
1148
|
+
@test.remove
|
1089
1149
|
end
|
1090
1150
|
|
1091
1151
|
def test_find_one
|
1092
|
-
id =
|
1152
|
+
id = @test.save("hello" => "world", "foo" => "bar")
|
1093
1153
|
|
1094
|
-
assert_equal "world",
|
1095
|
-
assert_equal
|
1096
|
-
assert_equal
|
1097
|
-
assert_equal
|
1098
|
-
assert_equal
|
1099
|
-
assert_equal
|
1154
|
+
assert_equal "world", @test.find_one()["hello"]
|
1155
|
+
assert_equal @test.find_one(id), @test.find_one()
|
1156
|
+
assert_equal @test.find_one(nil), @test.find_one()
|
1157
|
+
assert_equal @test.find_one({}), @test.find_one()
|
1158
|
+
assert_equal @test.find_one("hello" => "world"), @test.find_one()
|
1159
|
+
assert_equal @test.find_one(BSON::OrderedHash["hello", "world"]), @test.find_one()
|
1100
1160
|
|
1101
|
-
assert
|
1102
|
-
assert
|
1103
|
-
assert_equal ["_id"],
|
1161
|
+
assert @test.find_one(nil, :fields => ["hello"]).include?("hello")
|
1162
|
+
assert !@test.find_one(nil, :fields => ["foo"]).include?("hello")
|
1163
|
+
assert_equal ["_id"], @test.find_one(nil, :fields => []).keys()
|
1104
1164
|
|
1105
|
-
assert_equal nil,
|
1106
|
-
assert_equal nil,
|
1107
|
-
assert_equal nil,
|
1165
|
+
assert_equal nil, @test.find_one("hello" => "foo")
|
1166
|
+
assert_equal nil, @test.find_one(BSON::OrderedHash["hello", "foo"])
|
1167
|
+
assert_equal nil, @test.find_one(ObjectId.new)
|
1108
1168
|
|
1109
1169
|
assert_raise TypeError do
|
1110
|
-
|
1170
|
+
@test.find_one(6)
|
1111
1171
|
end
|
1112
1172
|
end
|
1113
1173
|
|
1114
1174
|
def test_find_one_with_max_time_ms
|
1115
|
-
with_forced_timeout(
|
1175
|
+
with_forced_timeout(@client) do
|
1116
1176
|
assert_raise ExecutionTimeout do
|
1117
|
-
|
1177
|
+
@test.find_one({}, { :max_time_ms => 100 })
|
1118
1178
|
end
|
1119
1179
|
end
|
1120
1180
|
end
|
1121
1181
|
|
1122
1182
|
def test_find_one_with_compile_regex_option
|
1123
1183
|
regex = /.*/
|
1124
|
-
|
1125
|
-
assert_kind_of Regexp,
|
1126
|
-
assert_kind_of Regexp,
|
1127
|
-
assert_equal BSON::Regex,
|
1184
|
+
@test.insert('r' => /.*/)
|
1185
|
+
assert_kind_of Regexp, @test.find_one({})['r']
|
1186
|
+
assert_kind_of Regexp, @test.find_one({}, :compile_regex => true)['r']
|
1187
|
+
assert_equal BSON::Regex, @test.find_one({}, :compile_regex => false)['r'].class
|
1128
1188
|
end
|
1129
1189
|
|
1130
1190
|
def test_insert_adds_id
|
1131
1191
|
doc = {"hello" => "world"}
|
1132
|
-
|
1192
|
+
@test.insert(doc)
|
1133
1193
|
assert(doc.include?(:_id))
|
1134
1194
|
|
1135
1195
|
docs = [{"hello" => "world"}, {"hello" => "world"}]
|
1136
|
-
|
1196
|
+
@test.insert(docs)
|
1137
1197
|
docs.each do |d|
|
1138
1198
|
assert(d.include?(:_id))
|
1139
1199
|
end
|
@@ -1141,23 +1201,23 @@ class CollectionTest < Test::Unit::TestCase
|
|
1141
1201
|
|
1142
1202
|
def test_save_adds_id
|
1143
1203
|
doc = {"hello" => "world"}
|
1144
|
-
|
1204
|
+
@test.save(doc)
|
1145
1205
|
assert(doc.include?(:_id))
|
1146
1206
|
end
|
1147
1207
|
|
1148
1208
|
def test_optional_find_block
|
1149
1209
|
10.times do |i|
|
1150
|
-
|
1210
|
+
@test.save("i" => i)
|
1151
1211
|
end
|
1152
1212
|
|
1153
1213
|
x = nil
|
1154
|
-
|
1214
|
+
@test.find("i" => 2) { |cursor|
|
1155
1215
|
x = cursor.count()
|
1156
1216
|
}
|
1157
1217
|
assert_equal 1, x
|
1158
1218
|
|
1159
1219
|
i = 0
|
1160
|
-
|
1220
|
+
@test.find({}, :skip => 5) do |cursor|
|
1161
1221
|
cursor.each do |doc|
|
1162
1222
|
i = i + 1
|
1163
1223
|
end
|
@@ -1165,7 +1225,7 @@ class CollectionTest < Test::Unit::TestCase
|
|
1165
1225
|
assert_equal 5, i
|
1166
1226
|
|
1167
1227
|
c = nil
|
1168
|
-
|
1228
|
+
@test.find() do |cursor|
|
1169
1229
|
c = cursor
|
1170
1230
|
end
|
1171
1231
|
assert c.closed?
|
@@ -1173,396 +1233,408 @@ class CollectionTest < Test::Unit::TestCase
|
|
1173
1233
|
|
1174
1234
|
def setup_aggregate_data
|
1175
1235
|
# save some data
|
1176
|
-
|
1177
|
-
|
1178
|
-
|
1179
|
-
|
1180
|
-
|
1181
|
-
|
1182
|
-
|
1183
|
-
|
1184
|
-
|
1185
|
-
|
1186
|
-
|
1187
|
-
|
1188
|
-
|
1189
|
-
|
1190
|
-
|
1191
|
-
|
1192
|
-
|
1193
|
-
|
1194
|
-
|
1195
|
-
|
1196
|
-
|
1197
|
-
|
1236
|
+
@test.save( {
|
1237
|
+
"_id" => 1,
|
1238
|
+
"title" => "this is my title",
|
1239
|
+
"author" => "bob",
|
1240
|
+
"posted" => Time.utc(2000),
|
1241
|
+
"pageViews" => 5 ,
|
1242
|
+
"tags" => [ "fun" , "good" , "fun" ],
|
1243
|
+
"comments" => [
|
1244
|
+
{ "author" => "joe", "text" => "this is cool" },
|
1245
|
+
{ "author" => "sam", "text" => "this is bad" }
|
1246
|
+
],
|
1247
|
+
"other" => { "foo" => 5 }
|
1248
|
+
} )
|
1249
|
+
|
1250
|
+
@test.save( {
|
1251
|
+
"_id" => 2,
|
1252
|
+
"title" => "this is your title",
|
1253
|
+
"author" => "dave",
|
1254
|
+
"posted" => Time.utc(2001),
|
1255
|
+
"pageViews" => 7,
|
1256
|
+
"tags" => [ "fun" , "nasty" ],
|
1257
|
+
"comments" => [
|
1198
1258
|
{ "author" => "barbara" , "text" => "this is interesting" },
|
1199
1259
|
{ "author" => "jenny", "text" => "i like to play pinball", "votes" => 10 }
|
1200
|
-
|
1201
|
-
|
1202
|
-
|
1260
|
+
],
|
1261
|
+
"other" => { "bar" => 14 }
|
1262
|
+
})
|
1203
1263
|
|
1204
|
-
|
1205
|
-
|
1206
|
-
|
1207
|
-
|
1208
|
-
|
1209
|
-
|
1210
|
-
|
1211
|
-
|
1212
|
-
|
1213
|
-
|
1214
|
-
|
1215
|
-
|
1216
|
-
|
1264
|
+
@test.save( {
|
1265
|
+
"_id" => 3,
|
1266
|
+
"title" => "this is some other title",
|
1267
|
+
"author" => "jane",
|
1268
|
+
"posted" => Time.utc(2002),
|
1269
|
+
"pageViews" => 6 ,
|
1270
|
+
"tags" => [ "nasty", "filthy" ],
|
1271
|
+
"comments" => [
|
1272
|
+
{ "author" => "will" , "text" => "i don't like the color" } ,
|
1273
|
+
{ "author" => "jenny" , "text" => "can i get that in green?" }
|
1274
|
+
],
|
1275
|
+
"other" => { "bar" => 14 }
|
1276
|
+
})
|
1217
1277
|
|
1218
1278
|
end
|
1219
1279
|
|
1220
|
-
|
1221
|
-
|
1222
|
-
|
1223
|
-
|
1224
|
-
|
1225
|
-
def test_aggregate_requires_arguments
|
1226
|
-
assert_raise MongoArgumentError do
|
1227
|
-
@@test.aggregate()
|
1228
|
-
end
|
1229
|
-
end
|
1230
|
-
|
1231
|
-
def test_aggregate_requires_valid_arguments
|
1232
|
-
assert_raise MongoArgumentError do
|
1233
|
-
@@test.aggregate({})
|
1234
|
-
end
|
1235
|
-
end
|
1236
|
-
|
1237
|
-
def test_aggregate_pipeline_operator_format
|
1238
|
-
assert_raise Mongo::OperationFailure do
|
1239
|
-
@@test.aggregate([{"$project" => "_id"}])
|
1240
|
-
end
|
1241
|
-
end
|
1242
|
-
|
1243
|
-
def test_aggregate_pipeline_operators_using_strings
|
1244
|
-
setup_aggregate_data
|
1245
|
-
desired_results = [ {"_id"=>1, "pageViews"=>5, "tags"=>["fun", "good", "fun"]},
|
1246
|
-
{"_id"=>2, "pageViews"=>7, "tags"=>["fun", "nasty"]},
|
1247
|
-
{"_id"=>3, "pageViews"=>6, "tags"=>["nasty", "filthy"]} ]
|
1248
|
-
results = @@test.aggregate([{"$project" => {"tags" => 1, "pageViews" => 1}}])
|
1249
|
-
assert_equal desired_results, results
|
1250
|
-
end
|
1251
|
-
|
1252
|
-
def test_aggregate_pipeline_operators_using_symbols
|
1253
|
-
setup_aggregate_data
|
1254
|
-
desired_results = [ {"_id"=>1, "pageViews"=>5, "tags"=>["fun", "good", "fun"]},
|
1255
|
-
{"_id"=>2, "pageViews"=>7, "tags"=>["fun", "nasty"]},
|
1256
|
-
{"_id"=>3, "pageViews"=>6, "tags"=>["nasty", "filthy"]} ]
|
1257
|
-
results = @@test.aggregate([{"$project" => {:tags => 1, :pageViews => 1}}])
|
1258
|
-
assert_equal desired_results, results
|
1259
|
-
end
|
1260
|
-
|
1261
|
-
def test_aggregate_pipeline_multiple_operators
|
1262
|
-
setup_aggregate_data
|
1263
|
-
results = @@test.aggregate([{"$project" => {"tags" => 1, "pageViews" => 1}}, {"$match" => {"pageViews" => 7}}])
|
1264
|
-
assert_equal 1, results.length
|
1265
|
-
end
|
1266
|
-
|
1267
|
-
def test_aggregate_pipeline_unwind
|
1268
|
-
setup_aggregate_data
|
1269
|
-
desired_results = [ {"_id"=>1, "title"=>"this is my title", "author"=>"bob", "posted"=>Time.utc(2000),
|
1270
|
-
"pageViews"=>5, "tags"=>"fun", "comments"=>[{"author"=>"joe", "text"=>"this is cool"},
|
1271
|
-
{"author"=>"sam", "text"=>"this is bad"}], "other"=>{"foo"=>5 } },
|
1272
|
-
{"_id"=>1, "title"=>"this is my title", "author"=>"bob", "posted"=>Time.utc(2000),
|
1273
|
-
"pageViews"=>5, "tags"=>"good", "comments"=>[{"author"=>"joe", "text"=>"this is cool"},
|
1274
|
-
{"author"=>"sam", "text"=>"this is bad"}], "other"=>{"foo"=>5 } },
|
1275
|
-
{"_id"=>1, "title"=>"this is my title", "author"=>"bob", "posted"=>Time.utc(2000),
|
1276
|
-
"pageViews"=>5, "tags"=>"fun", "comments"=>[{"author"=>"joe", "text"=>"this is cool"},
|
1277
|
-
{"author"=>"sam", "text"=>"this is bad"}], "other"=>{"foo"=>5 } },
|
1278
|
-
{"_id"=>2, "title"=>"this is your title", "author"=>"dave", "posted"=>Time.utc(2001),
|
1279
|
-
"pageViews"=>7, "tags"=>"fun", "comments"=>[{"author"=>"barbara", "text"=>"this is interesting"},
|
1280
|
-
{"author"=>"jenny", "text"=>"i like to play pinball", "votes"=>10 }], "other"=>{"bar"=>14 } },
|
1281
|
-
{"_id"=>2, "title"=>"this is your title", "author"=>"dave", "posted"=>Time.utc(2001),
|
1282
|
-
"pageViews"=>7, "tags"=>"nasty", "comments"=>[{"author"=>"barbara", "text"=>"this is interesting"},
|
1283
|
-
{"author"=>"jenny", "text"=>"i like to play pinball", "votes"=>10 }], "other"=>{"bar"=>14 } },
|
1284
|
-
{"_id"=>3, "title"=>"this is some other title", "author"=>"jane", "posted"=>Time.utc(2002),
|
1285
|
-
"pageViews"=>6, "tags"=>"nasty", "comments"=>[{"author"=>"will", "text"=>"i don't like the color"},
|
1286
|
-
{"author"=>"jenny", "text"=>"can i get that in green?"}], "other"=>{"bar"=>14 } },
|
1287
|
-
{"_id"=>3, "title"=>"this is some other title", "author"=>"jane", "posted"=>Time.utc(2002),
|
1288
|
-
"pageViews"=>6, "tags"=>"filthy", "comments"=>[{"author"=>"will", "text"=>"i don't like the color"},
|
1289
|
-
{"author"=>"jenny", "text"=>"can i get that in green?"}], "other"=>{"bar"=>14 } }
|
1290
|
-
]
|
1291
|
-
results = @@test.aggregate([{"$unwind"=> "$tags"}])
|
1292
|
-
assert_equal desired_results, results
|
1293
|
-
end
|
1294
|
-
|
1295
|
-
def test_aggregate_with_compile_regex_option
|
1296
|
-
# see SERVER-6470
|
1297
|
-
return unless @@version >= '2.3.2'
|
1298
|
-
@@test.insert({ 'r' => /.*/ })
|
1299
|
-
result1 = @@test.aggregate([])
|
1300
|
-
assert_kind_of Regexp, result1.first['r']
|
1301
|
-
|
1302
|
-
result2 = @@test.aggregate([], :compile_regex => false)
|
1303
|
-
assert_kind_of BSON::Regex, result2.first['r']
|
1304
|
-
|
1305
|
-
return unless @@version >= '2.5.1'
|
1306
|
-
result = @@test.aggregate([], :compile_regex => false, :cursor => {})
|
1307
|
-
assert_kind_of BSON::Regex, result.first['r']
|
1308
|
-
end
|
1309
|
-
end
|
1310
|
-
|
1311
|
-
if @@version >= "2.5.2"
|
1312
|
-
def test_out_aggregate
|
1313
|
-
out_collection = 'test_out'
|
1314
|
-
@@db.drop_collection(out_collection)
|
1315
|
-
setup_aggregate_data
|
1316
|
-
docs = @@test.find.to_a
|
1317
|
-
pipeline = [{:$out => out_collection}]
|
1318
|
-
@@test.aggregate(pipeline)
|
1319
|
-
assert_equal docs, @@db.collection(out_collection).find.to_a
|
1320
|
-
end
|
1321
|
-
|
1322
|
-
def test_out_aggregate_nonprimary_sym_warns
|
1323
|
-
ReadPreference::expects(:warn).with(regexp_matches(/rerouted to primary/))
|
1324
|
-
pipeline = [{:$out => 'test_out'}]
|
1325
|
-
@@test.aggregate(pipeline, :read => :secondary)
|
1326
|
-
end
|
1327
|
-
|
1328
|
-
def test_out_aggregate_nonprimary_string_warns
|
1329
|
-
ReadPreference::expects(:warn).with(regexp_matches(/rerouted to primary/))
|
1330
|
-
pipeline = [{'$out' => 'test_out'}]
|
1331
|
-
@@test.aggregate(pipeline, :read => :secondary)
|
1332
|
-
end
|
1333
|
-
|
1334
|
-
def test_out_aggregate_string_returns_raw_response
|
1335
|
-
pipeline = [{'$out' => 'test_out'}]
|
1336
|
-
response = @@test.aggregate(pipeline)
|
1337
|
-
assert response.respond_to?(:keys)
|
1338
|
-
end
|
1339
|
-
|
1340
|
-
def test_out_aggregate_sym_returns_raw_response
|
1341
|
-
pipeline = [{:$out => 'test_out'}]
|
1342
|
-
response = @@test.aggregate(pipeline)
|
1343
|
-
assert response.respond_to?(:keys)
|
1344
|
-
end
|
1345
|
-
end
|
1346
|
-
|
1347
|
-
if @@version > "1.1.1"
|
1348
|
-
def test_map_reduce
|
1349
|
-
@@test << { "user_id" => 1 }
|
1350
|
-
@@test << { "user_id" => 2 }
|
1351
|
-
|
1352
|
-
m = "function() { emit(this.user_id, 1); }"
|
1353
|
-
r = "function(k,vals) { return 1; }"
|
1354
|
-
res = @@test.map_reduce(m, r, :out => 'foo')
|
1355
|
-
assert res.find_one({"_id" => 1})
|
1356
|
-
assert res.find_one({"_id" => 2})
|
1357
|
-
end
|
1358
|
-
|
1359
|
-
def test_map_reduce_with_code_objects
|
1360
|
-
@@test << { "user_id" => 1 }
|
1361
|
-
@@test << { "user_id" => 2 }
|
1362
|
-
|
1363
|
-
m = Code.new("function() { emit(this.user_id, 1); }")
|
1364
|
-
r = Code.new("function(k,vals) { return 1; }")
|
1365
|
-
res = @@test.map_reduce(m, r, :out => 'foo')
|
1366
|
-
assert res.find_one({"_id" => 1})
|
1367
|
-
assert res.find_one({"_id" => 2})
|
1368
|
-
end
|
1369
|
-
|
1370
|
-
def test_map_reduce_with_options
|
1371
|
-
@@test.remove
|
1372
|
-
@@test << { "user_id" => 1 }
|
1373
|
-
@@test << { "user_id" => 2 }
|
1374
|
-
@@test << { "user_id" => 3 }
|
1375
|
-
|
1376
|
-
m = Code.new("function() { emit(this.user_id, 1); }")
|
1377
|
-
r = Code.new("function(k,vals) { return 1; }")
|
1378
|
-
res = @@test.map_reduce(m, r, :query => {"user_id" => {"$gt" => 1}}, :out => 'foo')
|
1379
|
-
assert_equal 2, res.count
|
1380
|
-
assert res.find_one({"_id" => 2})
|
1381
|
-
assert res.find_one({"_id" => 3})
|
1382
|
-
end
|
1383
|
-
|
1384
|
-
def test_map_reduce_with_raw_response
|
1385
|
-
m = Code.new("function() { emit(this.user_id, 1); }")
|
1386
|
-
r = Code.new("function(k,vals) { return 1; }")
|
1387
|
-
res = @@test.map_reduce(m, r, :raw => true, :out => 'foo')
|
1388
|
-
assert res["result"]
|
1389
|
-
assert res["counts"]
|
1390
|
-
assert res["timeMillis"]
|
1391
|
-
end
|
1392
|
-
|
1393
|
-
def test_map_reduce_with_output_collection
|
1394
|
-
output_collection = "test-map-coll"
|
1395
|
-
m = Code.new("function() { emit(this.user_id, 1); }")
|
1396
|
-
r = Code.new("function(k,vals) { return 1; }")
|
1397
|
-
res = @@test.map_reduce(m, r, :raw => true, :out => output_collection)
|
1398
|
-
assert_equal output_collection, res["result"]
|
1399
|
-
assert res["counts"]
|
1400
|
-
assert res["timeMillis"]
|
1401
|
-
end
|
1280
|
+
def test_reponds_to_aggregate
|
1281
|
+
return unless @version > '2.1.1'
|
1282
|
+
assert_respond_to @test, :aggregate
|
1283
|
+
end
|
1402
1284
|
|
1403
|
-
|
1404
|
-
|
1405
|
-
|
1406
|
-
|
1407
|
-
Mongo::ReadPreference.expects(:warn).with(regexp_matches(/rerouted to primary/))
|
1408
|
-
res = @@test.map_reduce(m, r, :raw => true, :out => output_collection, :read => :secondary)
|
1285
|
+
def test_aggregate_requires_arguments
|
1286
|
+
return unless @version > '2.1.1'
|
1287
|
+
assert_raise MongoArgumentError do
|
1288
|
+
@test.aggregate()
|
1409
1289
|
end
|
1290
|
+
end
|
1410
1291
|
|
1411
|
-
|
1412
|
-
|
1413
|
-
|
1414
|
-
|
1415
|
-
output_collection = "test-map-coll"
|
1416
|
-
m = Code.new("function() { emit(this.user_id, {count: 1}); }")
|
1417
|
-
r = Code.new("function(k,vals) { var sum = 0;" +
|
1418
|
-
" vals.forEach(function(v) { sum += v.count;} ); return {count: sum}; }")
|
1419
|
-
res = @@test.map_reduce(m, r, :out => output_collection)
|
1420
|
-
|
1421
|
-
@@test.remove
|
1422
|
-
@@test << {:user_id => 3}
|
1423
|
-
res = @@test.map_reduce(m, r, :out => {:merge => output_collection})
|
1424
|
-
assert res.find.to_a.any? {|doc| doc["_id"] == 3 && doc["value"]["count"] == 1}
|
1425
|
-
|
1426
|
-
@@test.remove
|
1427
|
-
@@test << {:user_id => 3}
|
1428
|
-
res = @@test.map_reduce(m, r, :out => {:reduce => output_collection})
|
1429
|
-
assert res.find.to_a.any? {|doc| doc["_id"] == 3 && doc["value"]["count"] == 2}
|
1430
|
-
|
1431
|
-
assert_raise ArgumentError do
|
1432
|
-
@@test.map_reduce(m, r, :out => {:inline => 1})
|
1433
|
-
end
|
1434
|
-
|
1435
|
-
@@test.map_reduce(m, r, :raw => true, :out => {:inline => 1})
|
1436
|
-
assert res["results"]
|
1437
|
-
end
|
1438
|
-
|
1439
|
-
def test_map_reduce_with_collection_output_to_other_db
|
1440
|
-
@@test << {:user_id => 1}
|
1441
|
-
@@test << {:user_id => 2}
|
1442
|
-
|
1443
|
-
m = Code.new("function() { emit(this.user_id, 1); }")
|
1444
|
-
r = Code.new("function(k,vals) { return 1; }")
|
1445
|
-
oh = BSON::OrderedHash.new
|
1446
|
-
oh[:replace] = 'foo'
|
1447
|
-
oh[:db] = TEST_DB
|
1448
|
-
res = @@test.map_reduce(m, r, :out => (oh))
|
1449
|
-
assert res["result"]
|
1450
|
-
assert res["counts"]
|
1451
|
-
assert res["timeMillis"]
|
1452
|
-
assert res.find.to_a.any? {|doc| doc["_id"] == 2 && doc["value"] == 1}
|
1453
|
-
end
|
1292
|
+
def test_aggregate_requires_valid_arguments
|
1293
|
+
return unless @version > '2.1.1'
|
1294
|
+
assert_raise MongoArgumentError do
|
1295
|
+
@test.aggregate({})
|
1454
1296
|
end
|
1455
1297
|
end
|
1456
1298
|
|
1457
|
-
|
1458
|
-
|
1459
|
-
|
1460
|
-
|
1461
|
-
|
1462
|
-
|
1463
|
-
|
1299
|
+
def test_aggregate_pipeline_operator_format
|
1300
|
+
return unless @version > '2.1.1'
|
1301
|
+
assert_raise Mongo::OperationFailure do
|
1302
|
+
@test.aggregate([{"$project" => "_id"}])
|
1303
|
+
end
|
1304
|
+
end
|
1305
|
+
|
1306
|
+
def test_aggregate_pipeline_operators_using_strings
|
1307
|
+
return unless @version > '2.1.1'
|
1308
|
+
setup_aggregate_data
|
1309
|
+
desired_results = [ {"_id"=>1, "pageViews"=>5, "tags"=>["fun", "good", "fun"]},
|
1310
|
+
{"_id"=>2, "pageViews"=>7, "tags"=>["fun", "nasty"]},
|
1311
|
+
{"_id"=>3, "pageViews"=>6, "tags"=>["nasty", "filthy"]} ]
|
1312
|
+
results = @test.aggregate([{"$project" => {"tags" => 1, "pageViews" => 1}}])
|
1313
|
+
assert_equal desired_results, results
|
1314
|
+
end
|
1315
|
+
|
1316
|
+
def test_aggregate_pipeline_operators_using_symbols
|
1317
|
+
return unless @version > '2.1.1'
|
1318
|
+
setup_aggregate_data
|
1319
|
+
desired_results = [ {"_id"=>1, "pageViews"=>5, "tags"=>["fun", "good", "fun"]},
|
1320
|
+
{"_id"=>2, "pageViews"=>7, "tags"=>["fun", "nasty"]},
|
1321
|
+
{"_id"=>3, "pageViews"=>6, "tags"=>["nasty", "filthy"]} ]
|
1322
|
+
results = @test.aggregate([{"$project" => {:tags => 1, :pageViews => 1}}])
|
1323
|
+
assert_equal desired_results, results
|
1324
|
+
end
|
1325
|
+
|
1326
|
+
def test_aggregate_pipeline_multiple_operators
|
1327
|
+
return unless @version > '2.1.1'
|
1328
|
+
setup_aggregate_data
|
1329
|
+
results = @test.aggregate([{"$project" => {"tags" => 1, "pageViews" => 1}}, {"$match" => {"pageViews" => 7}}])
|
1330
|
+
assert_equal 1, results.length
|
1331
|
+
end
|
1332
|
+
|
1333
|
+
def test_aggregate_pipeline_unwind
|
1334
|
+
return unless @version > '2.1.1'
|
1335
|
+
setup_aggregate_data
|
1336
|
+
desired_results = [ {"_id"=>1, "title"=>"this is my title", "author"=>"bob", "posted"=>Time.utc(2000),
|
1337
|
+
"pageViews"=>5, "tags"=>"fun", "comments"=>[{"author"=>"joe", "text"=>"this is cool"},
|
1338
|
+
{"author"=>"sam", "text"=>"this is bad"}], "other"=>{"foo"=>5 } },
|
1339
|
+
{"_id"=>1, "title"=>"this is my title", "author"=>"bob", "posted"=>Time.utc(2000),
|
1340
|
+
"pageViews"=>5, "tags"=>"good", "comments"=>[{"author"=>"joe", "text"=>"this is cool"},
|
1341
|
+
{"author"=>"sam", "text"=>"this is bad"}], "other"=>{"foo"=>5 } },
|
1342
|
+
{"_id"=>1, "title"=>"this is my title", "author"=>"bob", "posted"=>Time.utc(2000),
|
1343
|
+
"pageViews"=>5, "tags"=>"fun", "comments"=>[{"author"=>"joe", "text"=>"this is cool"},
|
1344
|
+
{"author"=>"sam", "text"=>"this is bad"}], "other"=>{"foo"=>5 } },
|
1345
|
+
{"_id"=>2, "title"=>"this is your title", "author"=>"dave", "posted"=>Time.utc(2001),
|
1346
|
+
"pageViews"=>7, "tags"=>"fun", "comments"=>[{"author"=>"barbara", "text"=>"this is interesting"},
|
1347
|
+
{"author"=>"jenny", "text"=>"i like to play pinball", "votes"=>10 }], "other"=>{"bar"=>14 } },
|
1348
|
+
{"_id"=>2, "title"=>"this is your title", "author"=>"dave", "posted"=>Time.utc(2001),
|
1349
|
+
"pageViews"=>7, "tags"=>"nasty", "comments"=>[{"author"=>"barbara", "text"=>"this is interesting"},
|
1350
|
+
{"author"=>"jenny", "text"=>"i like to play pinball", "votes"=>10 }], "other"=>{"bar"=>14 } },
|
1351
|
+
{"_id"=>3, "title"=>"this is some other title", "author"=>"jane", "posted"=>Time.utc(2002),
|
1352
|
+
"pageViews"=>6, "tags"=>"nasty", "comments"=>[{"author"=>"will", "text"=>"i don't like the color"},
|
1353
|
+
{"author"=>"jenny", "text"=>"can i get that in green?"}], "other"=>{"bar"=>14 } },
|
1354
|
+
{"_id"=>3, "title"=>"this is some other title", "author"=>"jane", "posted"=>Time.utc(2002),
|
1355
|
+
"pageViews"=>6, "tags"=>"filthy", "comments"=>[{"author"=>"will", "text"=>"i don't like the color"},
|
1356
|
+
{"author"=>"jenny", "text"=>"can i get that in green?"}], "other"=>{"bar"=>14 } }
|
1357
|
+
]
|
1358
|
+
results = @test.aggregate([{"$unwind"=> "$tags"}])
|
1359
|
+
assert_equal desired_results, results
|
1360
|
+
end
|
1361
|
+
|
1362
|
+
def test_aggregate_with_compile_regex_option
|
1363
|
+
return unless @version > '2.1.1'
|
1364
|
+
# see SERVER-6470
|
1365
|
+
return unless @version >= '2.3.2'
|
1366
|
+
@test.insert({ 'r' => /.*/ })
|
1367
|
+
result1 = @test.aggregate([])
|
1368
|
+
assert_kind_of Regexp, result1.first['r']
|
1369
|
+
|
1370
|
+
result2 = @test.aggregate([], :compile_regex => false)
|
1371
|
+
assert_kind_of BSON::Regex, result2.first['r']
|
1372
|
+
|
1373
|
+
return unless @version >= '2.5.1'
|
1374
|
+
result = @test.aggregate([], :compile_regex => false, :cursor => {})
|
1375
|
+
assert_kind_of BSON::Regex, result.first['r']
|
1376
|
+
end
|
1377
|
+
|
1378
|
+
def test_out_aggregate
|
1379
|
+
return unless @version >= "2.5.2"
|
1380
|
+
out_collection = 'test_out'
|
1381
|
+
@db.drop_collection(out_collection)
|
1382
|
+
setup_aggregate_data
|
1383
|
+
docs = @test.find.to_a
|
1384
|
+
pipeline = [{:$out => out_collection}]
|
1385
|
+
@test.aggregate(pipeline)
|
1386
|
+
assert_equal docs, @db.collection(out_collection).find.to_a
|
1387
|
+
end
|
1388
|
+
|
1389
|
+
def test_out_aggregate_nonprimary_sym_warns
|
1390
|
+
return unless @version >= "2.5.2"
|
1391
|
+
ReadPreference::expects(:warn).with(regexp_matches(/rerouted to primary/))
|
1392
|
+
pipeline = [{:$out => 'test_out'}]
|
1393
|
+
@test.aggregate(pipeline, :read => :secondary)
|
1394
|
+
end
|
1395
|
+
|
1396
|
+
def test_out_aggregate_nonprimary_string_warns
|
1397
|
+
return unless @version >= "2.5.2"
|
1398
|
+
ReadPreference::expects(:warn).with(regexp_matches(/rerouted to primary/))
|
1399
|
+
pipeline = [{'$out' => 'test_out'}]
|
1400
|
+
@test.aggregate(pipeline, :read => :secondary)
|
1401
|
+
end
|
1402
|
+
|
1403
|
+
def test_out_aggregate_string_returns_raw_response
|
1404
|
+
return unless @version >= "2.5.2"
|
1405
|
+
pipeline = [{'$out' => 'test_out'}]
|
1406
|
+
response = @test.aggregate(pipeline)
|
1407
|
+
assert response.respond_to?(:keys)
|
1408
|
+
end
|
1409
|
+
|
1410
|
+
def test_out_aggregate_sym_returns_raw_response
|
1411
|
+
return unless @version >= "2.5.2"
|
1412
|
+
pipeline = [{:$out => 'test_out'}]
|
1413
|
+
response = @test.aggregate(pipeline)
|
1414
|
+
assert response.respond_to?(:keys)
|
1415
|
+
end
|
1416
|
+
|
1417
|
+
def test_map_reduce
|
1418
|
+
return unless @version > "1.1.1"
|
1419
|
+
@test << { "user_id" => 1 }
|
1420
|
+
@test << { "user_id" => 2 }
|
1421
|
+
|
1422
|
+
m = "function() { emit(this.user_id, 1); }"
|
1423
|
+
r = "function(k,vals) { return 1; }"
|
1424
|
+
res = @test.map_reduce(m, r, :out => 'foo')
|
1425
|
+
assert res.find_one({"_id" => 1})
|
1426
|
+
assert res.find_one({"_id" => 2})
|
1427
|
+
end
|
1428
|
+
|
1429
|
+
def test_map_reduce_with_code_objects
|
1430
|
+
return unless @version > "1.1.1"
|
1431
|
+
@test << { "user_id" => 1 }
|
1432
|
+
@test << { "user_id" => 2 }
|
1433
|
+
|
1434
|
+
m = Code.new("function() { emit(this.user_id, 1); }")
|
1435
|
+
r = Code.new("function(k,vals) { return 1; }")
|
1436
|
+
res = @test.map_reduce(m, r, :out => 'foo')
|
1437
|
+
assert res.find_one({"_id" => 1})
|
1438
|
+
assert res.find_one({"_id" => 2})
|
1439
|
+
end
|
1440
|
+
|
1441
|
+
def test_map_reduce_with_options
|
1442
|
+
return unless @version > "1.1.1"
|
1443
|
+
@test.remove
|
1444
|
+
@test << { "user_id" => 1 }
|
1445
|
+
@test << { "user_id" => 2 }
|
1446
|
+
@test << { "user_id" => 3 }
|
1447
|
+
|
1448
|
+
m = Code.new("function() { emit(this.user_id, 1); }")
|
1449
|
+
r = Code.new("function(k,vals) { return 1; }")
|
1450
|
+
res = @test.map_reduce(m, r, :query => {"user_id" => {"$gt" => 1}}, :out => 'foo')
|
1451
|
+
assert_equal 2, res.count
|
1452
|
+
assert res.find_one({"_id" => 2})
|
1453
|
+
assert res.find_one({"_id" => 3})
|
1454
|
+
end
|
1455
|
+
|
1456
|
+
def test_map_reduce_with_raw_response
|
1457
|
+
return unless @version > "1.1.1"
|
1458
|
+
m = Code.new("function() { emit(this.user_id, 1); }")
|
1459
|
+
r = Code.new("function(k,vals) { return 1; }")
|
1460
|
+
res = @test.map_reduce(m, r, :raw => true, :out => 'foo')
|
1461
|
+
assert res["result"]
|
1462
|
+
assert res["counts"]
|
1463
|
+
assert res["timeMillis"]
|
1464
|
+
end
|
1465
|
+
|
1466
|
+
def test_map_reduce_with_output_collection
|
1467
|
+
return unless @version > "1.1.1"
|
1468
|
+
output_collection = "test-map-coll"
|
1469
|
+
m = Code.new("function() { emit(this.user_id, 1); }")
|
1470
|
+
r = Code.new("function(k,vals) { return 1; }")
|
1471
|
+
res = @test.map_reduce(m, r, :raw => true, :out => output_collection)
|
1472
|
+
assert_equal output_collection, res["result"]
|
1473
|
+
assert res["counts"]
|
1474
|
+
assert res["timeMillis"]
|
1475
|
+
end
|
1476
|
+
|
1477
|
+
def test_map_reduce_nonprimary_output_collection_reroutes
|
1478
|
+
return unless @version > "1.1.1"
|
1479
|
+
output_collection = "test-map-coll"
|
1480
|
+
m = Code.new("function() { emit(this.user_id, 1); }")
|
1481
|
+
r = Code.new("function(k,vals) { return 1; }")
|
1482
|
+
Mongo::ReadPreference.expects(:warn).with(regexp_matches(/rerouted to primary/))
|
1483
|
+
res = @test.map_reduce(m, r, :raw => true, :out => output_collection, :read => :secondary)
|
1484
|
+
end
|
1485
|
+
|
1486
|
+
def test_map_reduce_with_collection_merge
|
1487
|
+
return unless @version >= "1.8.0"
|
1488
|
+
@test << {:user_id => 1}
|
1489
|
+
@test << {:user_id => 2}
|
1490
|
+
output_collection = "test-map-coll"
|
1491
|
+
m = Code.new("function() { emit(this.user_id, {count: 1}); }")
|
1492
|
+
r = Code.new("function(k,vals) { var sum = 0;" +
|
1493
|
+
" vals.forEach(function(v) { sum += v.count;} ); return {count: sum}; }")
|
1494
|
+
res = @test.map_reduce(m, r, :out => output_collection)
|
1464
1495
|
|
1465
|
-
|
1466
|
-
|
1496
|
+
@test.remove
|
1497
|
+
@test << {:user_id => 3}
|
1498
|
+
res = @test.map_reduce(m, r, :out => {:merge => output_collection})
|
1499
|
+
assert res.find.to_a.any? {|doc| doc["_id"] == 3 && doc["value"]["count"] == 1}
|
1467
1500
|
|
1468
|
-
|
1469
|
-
|
1470
|
-
|
1471
|
-
|
1472
|
-
|
1473
|
-
|
1474
|
-
|
1475
|
-
|
1476
|
-
|
1477
|
-
|
1478
|
-
|
1501
|
+
@test.remove
|
1502
|
+
@test << {:user_id => 3}
|
1503
|
+
res = @test.map_reduce(m, r, :out => {:reduce => output_collection})
|
1504
|
+
assert res.find.to_a.any? {|doc| doc["_id"] == 3 && doc["value"]["count"] == 2}
|
1505
|
+
|
1506
|
+
assert_raise ArgumentError do
|
1507
|
+
@test.map_reduce(m, r, :out => {:inline => 1})
|
1508
|
+
end
|
1509
|
+
|
1510
|
+
@test.map_reduce(m, r, :raw => true, :out => {:inline => 1})
|
1511
|
+
assert res["results"]
|
1512
|
+
end
|
1513
|
+
|
1514
|
+
def test_map_reduce_with_collection_output_to_other_db
|
1515
|
+
return unless @version > "1.1.1"
|
1516
|
+
@test << {:user_id => 1}
|
1517
|
+
@test << {:user_id => 2}
|
1518
|
+
|
1519
|
+
m = Code.new("function() { emit(this.user_id, 1); }")
|
1520
|
+
r = Code.new("function(k,vals) { return 1; }")
|
1521
|
+
oh = BSON::OrderedHash.new
|
1522
|
+
oh[:replace] = 'foo'
|
1523
|
+
oh[:db] = TEST_DB
|
1524
|
+
res = @test.map_reduce(m, r, :out => (oh))
|
1525
|
+
assert res["result"]
|
1526
|
+
assert res["counts"]
|
1527
|
+
assert res["timeMillis"]
|
1528
|
+
assert res.find.to_a.any? {|doc| doc["_id"] == 2 && doc["value"] == 1}
|
1529
|
+
end
|
1530
|
+
|
1531
|
+
def test_aggregation_allow_disk_use
|
1532
|
+
return unless @version >= '2.5.5'
|
1533
|
+
@db.expects(:command).with do |selector, opts|
|
1534
|
+
opts[:allowDiskUse] == true
|
1535
|
+
end.returns({ 'ok' => 1 })
|
1536
|
+
@test.aggregate([], :allowDiskUse => true)
|
1537
|
+
end
|
1538
|
+
|
1539
|
+
def test_parallel_scan
|
1540
|
+
return unless @version >= '2.5.5'
|
1541
|
+
8000.times { |i| @test.insert({ :_id => i }) }
|
1542
|
+
|
1543
|
+
lock = Mutex.new
|
1544
|
+
doc_ids = Set.new
|
1545
|
+
threads = []
|
1546
|
+
cursors = @test.parallel_scan(3)
|
1547
|
+
cursors.each_with_index do |cursor, i|
|
1548
|
+
threads << Thread.new do
|
1549
|
+
docs = cursor.to_a
|
1550
|
+
lock.synchronize do
|
1551
|
+
docs.each do |doc|
|
1552
|
+
doc_ids << doc['_id']
|
1479
1553
|
end
|
1480
1554
|
end
|
1481
1555
|
end
|
1482
|
-
threads.each(&:join)
|
1483
|
-
assert_equal 8000, doc_ids.count
|
1484
1556
|
end
|
1557
|
+
threads.each(&:join)
|
1558
|
+
assert_equal 8000, doc_ids.count
|
1485
1559
|
end
|
1486
1560
|
|
1487
|
-
|
1488
|
-
|
1489
|
-
|
1490
|
-
|
1491
|
-
|
1561
|
+
def test_find_and_modify
|
1562
|
+
return unless @version > "1.3.0"
|
1563
|
+
@test << { :a => 1, :processed => false }
|
1564
|
+
@test << { :a => 2, :processed => false }
|
1565
|
+
@test << { :a => 3, :processed => false }
|
1492
1566
|
|
1493
|
-
|
1494
|
-
|
1495
|
-
|
1567
|
+
@test.find_and_modify(:query => {},
|
1568
|
+
:sort => [['a', -1]],
|
1569
|
+
:update => {"$set" => {:processed => true}})
|
1496
1570
|
|
1497
|
-
|
1498
|
-
|
1571
|
+
assert @test.find_one({:a => 3})['processed']
|
1572
|
+
end
|
1499
1573
|
|
1500
|
-
|
1501
|
-
|
1502
|
-
|
1503
|
-
|
1574
|
+
def test_find_and_modify_with_invalid_options
|
1575
|
+
@test << { :a => 1, :processed => false }
|
1576
|
+
@test << { :a => 2, :processed => false }
|
1577
|
+
@test << { :a => 3, :processed => false }
|
1504
1578
|
|
1505
|
-
|
1506
|
-
|
1507
|
-
end
|
1579
|
+
assert_raise Mongo::OperationFailure do
|
1580
|
+
@test.find_and_modify(:blimey => {})
|
1508
1581
|
end
|
1582
|
+
end
|
1509
1583
|
|
1510
|
-
|
1511
|
-
|
1512
|
-
|
1513
|
-
|
1584
|
+
def test_find_and_modify_with_full_response
|
1585
|
+
@test << { :a => 1, :processed => false }
|
1586
|
+
@test << { :a => 2, :processed => false }
|
1587
|
+
@test << { :a => 3, :processed => false }
|
1514
1588
|
|
1515
|
-
|
1516
|
-
|
1517
|
-
|
1518
|
-
|
1519
|
-
|
1589
|
+
doc = @test.find_and_modify(:query => {},
|
1590
|
+
:sort => [['a', -1]],
|
1591
|
+
:update => {"$set" => {:processed => true}},
|
1592
|
+
:full_response => true,
|
1593
|
+
:new => true)
|
1520
1594
|
|
1521
|
-
|
1522
|
-
|
1523
|
-
end
|
1595
|
+
assert doc['value']['processed']
|
1596
|
+
assert ['ok', 'value', 'lastErrorObject'].all? { |key| doc.key?(key) }
|
1524
1597
|
end
|
1525
1598
|
|
1526
|
-
|
1527
|
-
|
1528
|
-
|
1529
|
-
|
1599
|
+
def test_coll_stats
|
1600
|
+
return unless @version >= "1.3.5"
|
1601
|
+
@test << {:n => 1}
|
1602
|
+
@test.create_index("n")
|
1530
1603
|
|
1531
|
-
|
1532
|
-
|
1533
|
-
end
|
1604
|
+
assert_equal "#{TEST_DB}.test", @test.stats['ns']
|
1605
|
+
@test.drop
|
1534
1606
|
end
|
1535
1607
|
|
1536
1608
|
def test_saving_dates_pre_epoch
|
1537
1609
|
if RbConfig::CONFIG['host_os'] =~ /mswin|mingw|cygwin/ then return true end
|
1538
1610
|
begin
|
1539
|
-
|
1540
|
-
assert_in_delta Time.utc(1600),
|
1611
|
+
@test.save({'date' => Time.utc(1600)})
|
1612
|
+
assert_in_delta Time.utc(1600), @test.find_one()["date"], 2
|
1541
1613
|
rescue ArgumentError
|
1542
1614
|
# See note in test_date_before_epoch (BSONTest)
|
1543
1615
|
end
|
1544
1616
|
end
|
1545
1617
|
|
1546
1618
|
def test_save_symbol_find_string
|
1547
|
-
|
1619
|
+
@test.save(:foo => :mike)
|
1548
1620
|
|
1549
|
-
assert_equal :mike,
|
1550
|
-
assert_equal :mike,
|
1621
|
+
assert_equal :mike, @test.find_one(:foo => :mike)["foo"]
|
1622
|
+
assert_equal :mike, @test.find_one("foo" => :mike)["foo"]
|
1551
1623
|
|
1552
1624
|
# TODO enable these tests conditionally based on server version (if >1.0)
|
1553
|
-
# assert_equal :mike,
|
1554
|
-
# assert_equal :mike,
|
1625
|
+
# assert_equal :mike, @test.find_one(:foo => "mike")["foo"]
|
1626
|
+
# assert_equal :mike, @test.find_one("foo" => "mike")["foo"]
|
1555
1627
|
end
|
1556
1628
|
|
1557
1629
|
def test_batch_size
|
1558
1630
|
n_docs = 6
|
1559
1631
|
batch_size = n_docs/2
|
1560
1632
|
n_docs.times do |i|
|
1561
|
-
|
1633
|
+
@test.save(:foo => i)
|
1562
1634
|
end
|
1563
1635
|
|
1564
1636
|
doc_count = 0
|
1565
|
-
cursor =
|
1637
|
+
cursor = @test.find({}, :batch_size => batch_size)
|
1566
1638
|
cursor.next
|
1567
1639
|
assert_equal batch_size, cursor.instance_variable_get(:@returned)
|
1568
1640
|
doc_count += batch_size
|
@@ -1576,10 +1648,10 @@ class CollectionTest < Test::Unit::TestCase
|
|
1576
1648
|
n_docs = 6
|
1577
1649
|
batch_size = n_docs/2
|
1578
1650
|
n_docs.times do |i|
|
1579
|
-
|
1651
|
+
@test.insert(:foo => i)
|
1580
1652
|
end
|
1581
1653
|
|
1582
|
-
cursor =
|
1654
|
+
cursor = @test.find({}, :batch_size => batch_size, :limit => 2)
|
1583
1655
|
cursor.next
|
1584
1656
|
assert_equal 2, cursor.instance_variable_get(:@returned)
|
1585
1657
|
end
|
@@ -1588,11 +1660,11 @@ class CollectionTest < Test::Unit::TestCase
|
|
1588
1660
|
n_docs = 6
|
1589
1661
|
batch_size = n_docs/2
|
1590
1662
|
n_docs.times do |i|
|
1591
|
-
|
1663
|
+
@test.insert(:foo => i)
|
1592
1664
|
end
|
1593
1665
|
|
1594
1666
|
doc_count = 0
|
1595
|
-
cursor =
|
1667
|
+
cursor = @test.find({}, :batch_size => batch_size, :limit => n_docs + 5)
|
1596
1668
|
cursor.next
|
1597
1669
|
assert_equal batch_size, cursor.instance_variable_get(:@returned)
|
1598
1670
|
doc_count += batch_size
|
@@ -1600,44 +1672,44 @@ class CollectionTest < Test::Unit::TestCase
|
|
1600
1672
|
assert_equal doc_count + batch_size, cursor.instance_variable_get(:@returned)
|
1601
1673
|
doc_count += batch_size
|
1602
1674
|
assert_equal n_docs, doc_count
|
1603
|
-
end
|
1675
|
+
end
|
1604
1676
|
|
1605
1677
|
def test_batch_size_with_negative_limit
|
1606
1678
|
n_docs = 6
|
1607
1679
|
batch_size = n_docs/2
|
1608
1680
|
n_docs.times do |i|
|
1609
|
-
|
1681
|
+
@test.insert(:foo => i)
|
1610
1682
|
end
|
1611
1683
|
|
1612
|
-
cursor =
|
1684
|
+
cursor = @test.find({}, :batch_size => batch_size, :limit => -7)
|
1613
1685
|
cursor.next
|
1614
1686
|
assert_equal n_docs, cursor.instance_variable_get(:@returned)
|
1615
1687
|
end
|
1616
1688
|
|
1617
1689
|
def test_limit_and_skip
|
1618
1690
|
10.times do |i|
|
1619
|
-
|
1691
|
+
@test.save(:foo => i)
|
1620
1692
|
end
|
1621
1693
|
|
1622
|
-
assert_equal 5,
|
1623
|
-
assert_equal nil,
|
1694
|
+
assert_equal 5, @test.find({}, :skip => 5).next_document()["foo"]
|
1695
|
+
assert_equal nil, @test.find({}, :skip => 10).next_document()
|
1624
1696
|
|
1625
|
-
assert_equal 5,
|
1697
|
+
assert_equal 5, @test.find({}, :limit => 5).to_a.length
|
1626
1698
|
|
1627
|
-
assert_equal 3,
|
1628
|
-
assert_equal 5,
|
1699
|
+
assert_equal 3, @test.find({}, :skip => 3, :limit => 5).next_document()["foo"]
|
1700
|
+
assert_equal 5, @test.find({}, :skip => 3, :limit => 5).to_a.length
|
1629
1701
|
end
|
1630
1702
|
|
1631
1703
|
def test_large_limit
|
1632
1704
|
2000.times do |i|
|
1633
|
-
|
1705
|
+
@test.insert("x" => i, "y" => "mongomongo" * 1000)
|
1634
1706
|
end
|
1635
1707
|
|
1636
|
-
assert_equal 2000,
|
1708
|
+
assert_equal 2000, @test.count
|
1637
1709
|
|
1638
1710
|
i = 0
|
1639
1711
|
y = 0
|
1640
|
-
|
1712
|
+
@test.find({}, :limit => 1900).each do |doc|
|
1641
1713
|
i += 1
|
1642
1714
|
y += doc["x"]
|
1643
1715
|
end
|
@@ -1647,13 +1719,13 @@ end
|
|
1647
1719
|
end
|
1648
1720
|
|
1649
1721
|
def test_small_limit
|
1650
|
-
|
1651
|
-
|
1722
|
+
@test.insert("x" => "hello world")
|
1723
|
+
@test.insert("x" => "goodbye world")
|
1652
1724
|
|
1653
|
-
assert_equal 2,
|
1725
|
+
assert_equal 2, @test.count
|
1654
1726
|
|
1655
1727
|
x = 0
|
1656
|
-
|
1728
|
+
@test.find({}, :limit => 1).each do |doc|
|
1657
1729
|
x += 1
|
1658
1730
|
assert_equal "hello world", doc["x"]
|
1659
1731
|
end
|
@@ -1664,56 +1736,56 @@ end
|
|
1664
1736
|
def test_find_with_transformer
|
1665
1737
|
klass = Struct.new(:id, :a)
|
1666
1738
|
transformer = Proc.new { |doc| klass.new(doc['_id'], doc['a']) }
|
1667
|
-
cursor =
|
1739
|
+
cursor = @test.find({}, :transformer => transformer)
|
1668
1740
|
assert_equal(transformer, cursor.transformer)
|
1669
1741
|
end
|
1670
1742
|
|
1671
1743
|
def test_find_one_with_transformer
|
1672
1744
|
klass = Struct.new(:id, :a)
|
1673
1745
|
transformer = Proc.new { |doc| klass.new(doc['_id'], doc['a']) }
|
1674
|
-
id =
|
1675
|
-
doc =
|
1746
|
+
id = @test.insert('a' => 1)
|
1747
|
+
doc = @test.find_one(id, :transformer => transformer)
|
1676
1748
|
assert_instance_of(klass, doc)
|
1677
1749
|
end
|
1678
1750
|
|
1679
1751
|
def test_ensure_index
|
1680
|
-
|
1681
|
-
|
1682
|
-
assert_equal 1,
|
1752
|
+
@test.drop_indexes
|
1753
|
+
@test.insert("x" => "hello world")
|
1754
|
+
assert_equal 1, @test.index_information.keys.count #default index
|
1683
1755
|
|
1684
|
-
|
1685
|
-
assert_equal 2,
|
1686
|
-
assert
|
1756
|
+
@test.ensure_index([["x", Mongo::DESCENDING]], {})
|
1757
|
+
assert_equal 2, @test.index_information.keys.count
|
1758
|
+
assert @test.index_information.keys.include?("x_-1")
|
1687
1759
|
|
1688
|
-
|
1689
|
-
assert
|
1760
|
+
@test.ensure_index([["x", Mongo::ASCENDING]])
|
1761
|
+
assert @test.index_information.keys.include?("x_1")
|
1690
1762
|
|
1691
|
-
|
1692
|
-
assert
|
1763
|
+
@test.ensure_index([["type", 1], ["date", -1]])
|
1764
|
+
assert @test.index_information.keys.include?("type_1_date_-1")
|
1693
1765
|
|
1694
|
-
|
1695
|
-
assert_equal 3,
|
1696
|
-
|
1697
|
-
assert_equal 2,
|
1766
|
+
@test.drop_index("x_1")
|
1767
|
+
assert_equal 3, @test.index_information.keys.count
|
1768
|
+
@test.drop_index("x_-1")
|
1769
|
+
assert_equal 2, @test.index_information.keys.count
|
1698
1770
|
|
1699
|
-
|
1700
|
-
assert_equal 3,
|
1701
|
-
assert
|
1771
|
+
@test.ensure_index([["x", Mongo::DESCENDING]], {})
|
1772
|
+
assert_equal 3, @test.index_information.keys.count
|
1773
|
+
assert @test.index_information.keys.include?("x_-1")
|
1702
1774
|
|
1703
1775
|
# Make sure that drop_index expires cache properly
|
1704
|
-
|
1705
|
-
assert
|
1706
|
-
|
1707
|
-
assert
|
1708
|
-
|
1709
|
-
assert
|
1710
|
-
|
1711
|
-
|
1776
|
+
@test.ensure_index([['a', 1]])
|
1777
|
+
assert @test.index_information.keys.include?("a_1")
|
1778
|
+
@test.drop_index("a_1")
|
1779
|
+
assert !@test.index_information.keys.include?("a_1")
|
1780
|
+
@test.ensure_index([['a', 1]])
|
1781
|
+
assert @test.index_information.keys.include?("a_1")
|
1782
|
+
@test.drop_index("a_1")
|
1783
|
+
@test.drop_indexes
|
1712
1784
|
end
|
1713
1785
|
|
1714
1786
|
def test_ensure_index_timeout
|
1715
|
-
|
1716
|
-
coll =
|
1787
|
+
@db.cache_time = 1
|
1788
|
+
coll = @db['ensure_test']
|
1717
1789
|
coll.expects(:generate_indexes).twice
|
1718
1790
|
coll.ensure_index([['a', 1]])
|
1719
1791
|
|
@@ -1729,101 +1801,101 @@ end
|
|
1729
1801
|
coll.drop
|
1730
1802
|
end
|
1731
1803
|
|
1732
|
-
|
1733
|
-
|
1734
|
-
|
1735
|
-
|
1736
|
-
|
1737
|
-
|
1738
|
-
|
1739
|
-
|
1804
|
+
def test_show_disk_loc
|
1805
|
+
return unless @version > '2.0.0'
|
1806
|
+
@test.save({:a => 1})
|
1807
|
+
@test.save({:a => 2})
|
1808
|
+
assert @test.find({:a => 1}, :show_disk_loc => true).show_disk_loc
|
1809
|
+
assert @test.find({:a => 1}, :show_disk_loc => true).next['$diskLoc']
|
1810
|
+
@test.remove
|
1811
|
+
end
|
1740
1812
|
|
1741
|
-
|
1742
|
-
|
1743
|
-
|
1744
|
-
|
1745
|
-
|
1746
|
-
|
1747
|
-
|
1748
|
-
|
1749
|
-
|
1750
|
-
|
1751
|
-
|
1752
|
-
|
1753
|
-
|
1754
|
-
|
1813
|
+
def test_max_scan
|
1814
|
+
return unless @version > '2.0.0'
|
1815
|
+
@test.drop
|
1816
|
+
n = 100
|
1817
|
+
n.times do |i|
|
1818
|
+
@test.save({:_id => i, :x => i % 10})
|
1819
|
+
end
|
1820
|
+
assert_equal(n, @test.find.to_a.size)
|
1821
|
+
assert_equal(50, @test.find({}, :max_scan => 50).to_a.size)
|
1822
|
+
assert_equal(10, @test.find({:x => 2}).to_a.size)
|
1823
|
+
assert_equal(5, @test.find({:x => 2}, :max_scan => 50).to_a.size)
|
1824
|
+
@test.ensure_index([[:x, 1]])
|
1825
|
+
assert_equal(10, @test.find({:x => 2}, :max_scan => n).to_a.size)
|
1826
|
+
@test.drop
|
1755
1827
|
end
|
1756
1828
|
|
1757
1829
|
context "Grouping" do
|
1758
1830
|
setup do
|
1759
|
-
|
1760
|
-
|
1761
|
-
|
1831
|
+
@test.remove
|
1832
|
+
@test.save("a" => 1)
|
1833
|
+
@test.save("b" => 1)
|
1762
1834
|
@initial = {"count" => 0}
|
1763
1835
|
@reduce_function = "function (obj, prev) { prev.count += inc_value; }"
|
1764
1836
|
end
|
1765
1837
|
|
1766
1838
|
should "fail if missing required options" do
|
1767
1839
|
assert_raise MongoArgumentError do
|
1768
|
-
|
1840
|
+
@test.group(:initial => {})
|
1769
1841
|
end
|
1770
1842
|
|
1771
1843
|
assert_raise MongoArgumentError do
|
1772
|
-
|
1844
|
+
@test.group(:reduce => "foo")
|
1773
1845
|
end
|
1774
1846
|
end
|
1775
1847
|
|
1776
1848
|
should "group results using eval form" do
|
1777
|
-
assert_equal 1,
|
1778
|
-
assert_equal 2,
|
1779
|
-
assert_equal 4,
|
1849
|
+
assert_equal 1, @test.group(:initial => @initial, :reduce => Code.new(@reduce_function, {"inc_value" => 0.5}))[0]["count"]
|
1850
|
+
assert_equal 2, @test.group(:initial => @initial, :reduce => Code.new(@reduce_function, {"inc_value" => 1}))[0]["count"]
|
1851
|
+
assert_equal 4, @test.group(:initial => @initial, :reduce => Code.new(@reduce_function, {"inc_value" => 2}))[0]["count"]
|
1780
1852
|
end
|
1781
1853
|
|
1782
1854
|
should "finalize grouped results" do
|
1783
1855
|
@finalize = "function(doc) {doc.f = doc.count + 200; }"
|
1784
|
-
assert_equal 202,
|
1856
|
+
assert_equal 202, @test.group(:initial => @initial, :reduce => Code.new(@reduce_function, {"inc_value" => 1}), :finalize => @finalize)[0]["f"]
|
1785
1857
|
end
|
1786
1858
|
end
|
1787
1859
|
|
1788
1860
|
context "Grouping with key" do
|
1789
1861
|
setup do
|
1790
|
-
|
1791
|
-
|
1792
|
-
|
1793
|
-
|
1794
|
-
|
1862
|
+
@test.remove
|
1863
|
+
@test.save("a" => 1, "pop" => 100)
|
1864
|
+
@test.save("a" => 1, "pop" => 100)
|
1865
|
+
@test.save("a" => 2, "pop" => 100)
|
1866
|
+
@test.save("a" => 2, "pop" => 100)
|
1795
1867
|
@initial = {"count" => 0, "foo" => 1}
|
1796
1868
|
@reduce_function = "function (obj, prev) { prev.count += obj.pop; }"
|
1797
1869
|
end
|
1798
1870
|
|
1799
1871
|
should "group" do
|
1800
|
-
result =
|
1872
|
+
result = @test.group(:key => :a, :initial => @initial, :reduce => @reduce_function)
|
1801
1873
|
assert result.all? { |r| r['count'] == 200 }
|
1802
1874
|
end
|
1803
1875
|
end
|
1804
1876
|
|
1805
1877
|
context "Grouping with a key function" do
|
1806
1878
|
setup do
|
1807
|
-
|
1808
|
-
|
1809
|
-
|
1810
|
-
|
1811
|
-
|
1812
|
-
|
1879
|
+
@test.remove
|
1880
|
+
@test.save("a" => 1)
|
1881
|
+
@test.save("a" => 2)
|
1882
|
+
@test.save("a" => 3)
|
1883
|
+
@test.save("a" => 4)
|
1884
|
+
@test.save("a" => 5)
|
1813
1885
|
@initial = {"count" => 0}
|
1814
1886
|
@keyf = "function (doc) { if(doc.a % 2 == 0) { return {even: true}; } else {return {odd: true}} };"
|
1815
1887
|
@reduce = "function (obj, prev) { prev.count += 1; }"
|
1816
1888
|
end
|
1817
1889
|
|
1818
1890
|
should "group results" do
|
1819
|
-
results =
|
1891
|
+
results = @test.group(:keyf => @keyf, :initial => @initial, :reduce => @reduce).sort {|a, b| a['count'] <=> b['count']}
|
1820
1892
|
assert results[0]['even'] && results[0]['count'] == 2.0
|
1821
1893
|
assert results[1]['odd'] && results[1]['count'] == 3.0
|
1822
1894
|
end
|
1823
1895
|
|
1824
1896
|
should "group filtered results" do
|
1825
|
-
results =
|
1826
|
-
|
1897
|
+
results = @test.group(:keyf => @keyf, :cond => {:a => {'$ne' => 2}},
|
1898
|
+
:initial => @initial, :reduce => @reduce).sort {|a, b| a['count'] <=> b['count']}
|
1827
1899
|
assert results[0]['even'] && results[0]['count'] == 1.0
|
1828
1900
|
assert results[1]['odd'] && results[1]['count'] == 3.0
|
1829
1901
|
end
|
@@ -1831,7 +1903,7 @@ end
|
|
1831
1903
|
|
1832
1904
|
context "A collection with two records" do
|
1833
1905
|
setup do
|
1834
|
-
@collection =
|
1906
|
+
@collection = @db.collection('test-collection')
|
1835
1907
|
@collection.remove
|
1836
1908
|
@collection.insert({:name => "Jones"})
|
1837
1909
|
@collection.insert({:name => "Smith"})
|
@@ -1859,8 +1931,8 @@ end
|
|
1859
1931
|
|
1860
1932
|
context "Drop index " do
|
1861
1933
|
setup do
|
1862
|
-
|
1863
|
-
@collection =
|
1934
|
+
@db.drop_collection('test-collection')
|
1935
|
+
@collection = @db.collection('test-collection')
|
1864
1936
|
end
|
1865
1937
|
|
1866
1938
|
should "drop an index" do
|
@@ -1894,10 +1966,10 @@ end
|
|
1894
1966
|
|
1895
1967
|
context "Creating indexes " do
|
1896
1968
|
setup do
|
1897
|
-
|
1898
|
-
|
1899
|
-
@collection =
|
1900
|
-
@geo =
|
1969
|
+
@db.drop_collection('geo')
|
1970
|
+
@db.drop_collection('test-collection')
|
1971
|
+
@collection = @db.collection('test-collection')
|
1972
|
+
@geo = @db.collection('geo')
|
1901
1973
|
end
|
1902
1974
|
|
1903
1975
|
should "create index using symbols" do
|
@@ -1947,31 +2019,37 @@ end
|
|
1947
2019
|
end
|
1948
2020
|
|
1949
2021
|
should "drop duplicates" do
|
1950
|
-
@
|
1951
|
-
|
1952
|
-
|
1953
|
-
|
1954
|
-
|
2022
|
+
if @version < '2.7'
|
2023
|
+
@collection.insert({:a => 1})
|
2024
|
+
@collection.insert({:a => 1})
|
2025
|
+
assert_equal 2, @collection.find({:a => 1}).count
|
2026
|
+
@collection.create_index([['a', Mongo::ASCENDING]], :unique => true, :dropDups => true)
|
2027
|
+
assert_equal 1, @collection.find({:a => 1}).count
|
2028
|
+
end
|
1955
2029
|
end
|
1956
2030
|
|
1957
2031
|
should "drop duplicates with ruby-like drop_dups key" do
|
1958
|
-
@
|
1959
|
-
|
1960
|
-
|
1961
|
-
|
1962
|
-
|
2032
|
+
if @version < '2.7'
|
2033
|
+
@collection.insert({:a => 1})
|
2034
|
+
@collection.insert({:a => 1})
|
2035
|
+
assert_equal 2, @collection.find({:a => 1}).count
|
2036
|
+
@collection.create_index([['a', Mongo::ASCENDING]], :unique => true, :drop_dups => true)
|
2037
|
+
assert_equal 1, @collection.find({:a => 1}).count
|
2038
|
+
end
|
1963
2039
|
end
|
1964
2040
|
|
1965
2041
|
should "drop duplicates with ensure_index and drop_dups key" do
|
1966
|
-
@
|
1967
|
-
|
1968
|
-
|
1969
|
-
|
1970
|
-
|
2042
|
+
if @version < '2.7'
|
2043
|
+
@collection.insert({:a => 1})
|
2044
|
+
@collection.insert({:a => 1})
|
2045
|
+
assert_equal 2, @collection.find({:a => 1}).count
|
2046
|
+
@collection.ensure_index([['a', Mongo::ASCENDING]], :unique => true, :drop_dups => true)
|
2047
|
+
assert_equal 1, @collection.find({:a => 1}).count
|
2048
|
+
end
|
1971
2049
|
end
|
1972
2050
|
|
1973
2051
|
should "create an index in the background" do
|
1974
|
-
if
|
2052
|
+
if @version > '1.3.1'
|
1975
2053
|
@collection.create_index([['b', Mongo::ASCENDING]], :background => true)
|
1976
2054
|
assert @collection.index_information['b_1']['background'] == true
|
1977
2055
|
else
|
@@ -1994,19 +2072,19 @@ end
|
|
1994
2072
|
should "raise an error if index name is greater than 128" do
|
1995
2073
|
assert_raise Mongo::OperationFailure do
|
1996
2074
|
@collection.create_index([['a' * 25, 1], ['b' * 25, 1],
|
1997
|
-
|
2075
|
+
['c' * 25, 1], ['d' * 25, 1], ['e' * 25, 1]])
|
1998
2076
|
end
|
1999
2077
|
end
|
2000
2078
|
|
2001
2079
|
should "allow for an alternate name to be specified" do
|
2002
2080
|
@collection.create_index([['a' * 25, 1], ['b' * 25, 1],
|
2003
|
-
|
2081
|
+
['c' * 25, 1], ['d' * 25, 1], ['e' * 25, 1]], :name => 'foo_index')
|
2004
2082
|
assert @collection.index_information['foo_index']
|
2005
2083
|
end
|
2006
2084
|
|
2007
2085
|
should "generate indexes in the proper order" do
|
2008
2086
|
key = BSON::OrderedHash['b', 1, 'a', 1]
|
2009
|
-
if
|
2087
|
+
if @version < '2.5.5'
|
2010
2088
|
@collection.expects(:send_write) do |type, selector, documents, check_keys, opts, collection_name|
|
2011
2089
|
assert_equal key, selector[:key]
|
2012
2090
|
end
|
@@ -2036,8 +2114,8 @@ end
|
|
2036
2114
|
|
2037
2115
|
context "Capped collections" do
|
2038
2116
|
setup do
|
2039
|
-
|
2040
|
-
@capped =
|
2117
|
+
@db.drop_collection('log')
|
2118
|
+
@capped = @db.create_collection('log', :capped => true, :size => LIMITED_MAX_BSON_SIZE)
|
2041
2119
|
|
2042
2120
|
10.times { |n| @capped.insert({:n => n}) }
|
2043
2121
|
end
|
@@ -2053,7 +2131,7 @@ end
|
|
2053
2131
|
end
|
2054
2132
|
|
2055
2133
|
should "fail tailable cursor on a non-capped collection" do
|
2056
|
-
col =
|
2134
|
+
col = @db['regular-collection']
|
2057
2135
|
col.insert({:a => 1000})
|
2058
2136
|
tail = Cursor.new(col, :tailable => true, :order => [['$natural', 1]])
|
2059
2137
|
assert_raise OperationFailure do
|