mongo 1.3.0 → 1.12.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- checksums.yaml.gz.sig +0 -0
- data/{LICENSE.txt → LICENSE} +1 -1
- data/README.md +122 -271
- data/Rakefile +25 -209
- data/VERSION +1 -0
- data/bin/mongo_console +31 -9
- data/lib/mongo/bulk_write_collection_view.rb +387 -0
- data/lib/mongo/collection.rb +576 -269
- data/lib/mongo/collection_writer.rb +364 -0
- data/lib/mongo/connection/node.rb +249 -0
- data/lib/mongo/connection/pool.rb +340 -0
- data/lib/mongo/connection/pool_manager.rb +320 -0
- data/lib/mongo/connection/sharding_pool_manager.rb +67 -0
- data/lib/mongo/connection/socket/socket_util.rb +37 -0
- data/lib/mongo/connection/socket/ssl_socket.rb +95 -0
- data/lib/mongo/connection/socket/tcp_socket.rb +87 -0
- data/lib/mongo/connection/socket/unix_socket.rb +39 -0
- data/lib/mongo/connection/socket.rb +18 -0
- data/lib/mongo/connection.rb +7 -875
- data/lib/mongo/cursor.rb +403 -117
- data/lib/mongo/db.rb +444 -243
- data/lib/mongo/exception.rb +145 -0
- data/lib/mongo/functional/authentication.rb +455 -0
- data/lib/mongo/functional/logging.rb +85 -0
- data/lib/mongo/functional/read_preference.rb +183 -0
- data/lib/mongo/functional/scram.rb +556 -0
- data/lib/mongo/functional/uri_parser.rb +409 -0
- data/lib/mongo/functional/write_concern.rb +66 -0
- data/lib/mongo/functional.rb +20 -0
- data/lib/mongo/gridfs/grid.rb +30 -24
- data/lib/mongo/gridfs/grid_ext.rb +6 -10
- data/lib/mongo/gridfs/grid_file_system.rb +38 -20
- data/lib/mongo/gridfs/grid_io.rb +84 -75
- data/lib/mongo/gridfs.rb +18 -0
- data/lib/mongo/legacy.rb +140 -0
- data/lib/mongo/mongo_client.rb +697 -0
- data/lib/mongo/mongo_replica_set_client.rb +535 -0
- data/lib/mongo/mongo_sharded_client.rb +159 -0
- data/lib/mongo/networking.rb +372 -0
- data/lib/mongo/{util → utils}/conversions.rb +29 -8
- data/lib/mongo/{util → utils}/core_ext.rb +28 -18
- data/lib/mongo/{util → utils}/server_version.rb +4 -6
- data/lib/mongo/{util → utils}/support.rb +29 -31
- data/lib/mongo/utils/thread_local_variable_manager.rb +25 -0
- data/lib/mongo/utils.rb +19 -0
- data/lib/mongo.rb +51 -50
- data/mongo.gemspec +29 -32
- data/test/functional/authentication_test.rb +39 -0
- data/test/functional/bulk_api_stress_test.rb +133 -0
- data/test/functional/bulk_write_collection_view_test.rb +1198 -0
- data/test/functional/client_test.rb +627 -0
- data/test/functional/collection_test.rb +2175 -0
- data/test/functional/collection_writer_test.rb +83 -0
- data/test/{conversions_test.rb → functional/conversions_test.rb} +47 -3
- data/test/functional/cursor_fail_test.rb +57 -0
- data/test/functional/cursor_message_test.rb +56 -0
- data/test/functional/cursor_test.rb +683 -0
- data/test/functional/db_api_test.rb +835 -0
- data/test/functional/db_connection_test.rb +25 -0
- data/test/functional/db_test.rb +348 -0
- data/test/functional/grid_file_system_test.rb +285 -0
- data/test/{grid_io_test.rb → functional/grid_io_test.rb} +72 -11
- data/test/{grid_test.rb → functional/grid_test.rb} +88 -15
- data/test/functional/pool_test.rb +136 -0
- data/test/functional/safe_test.rb +98 -0
- data/test/functional/ssl_test.rb +29 -0
- data/test/functional/support_test.rb +62 -0
- data/test/functional/timeout_test.rb +60 -0
- data/test/functional/uri_test.rb +446 -0
- data/test/functional/write_concern_test.rb +118 -0
- data/test/helpers/general.rb +50 -0
- data/test/helpers/test_unit.rb +476 -0
- data/test/replica_set/authentication_test.rb +37 -0
- data/test/replica_set/basic_test.rb +189 -0
- data/test/replica_set/client_test.rb +393 -0
- data/test/replica_set/connection_test.rb +138 -0
- data/test/replica_set/count_test.rb +66 -0
- data/test/replica_set/cursor_test.rb +220 -0
- data/test/replica_set/insert_test.rb +157 -0
- data/test/replica_set/max_values_test.rb +151 -0
- data/test/replica_set/pinning_test.rb +105 -0
- data/test/replica_set/query_test.rb +73 -0
- data/test/replica_set/read_preference_test.rb +219 -0
- data/test/replica_set/refresh_test.rb +211 -0
- data/test/replica_set/replication_ack_test.rb +95 -0
- data/test/replica_set/ssl_test.rb +32 -0
- data/test/sharded_cluster/basic_test.rb +203 -0
- data/test/shared/authentication/basic_auth_shared.rb +260 -0
- data/test/shared/authentication/bulk_api_auth_shared.rb +249 -0
- data/test/shared/authentication/gssapi_shared.rb +176 -0
- data/test/shared/authentication/sasl_plain_shared.rb +96 -0
- data/test/shared/authentication/scram_shared.rb +92 -0
- data/test/shared/ssl_shared.rb +235 -0
- data/test/test_helper.rb +53 -94
- data/test/threading/basic_test.rb +120 -0
- data/test/tools/mongo_config.rb +708 -0
- data/test/tools/mongo_config_test.rb +160 -0
- data/test/unit/client_test.rb +381 -0
- data/test/unit/collection_test.rb +89 -53
- data/test/unit/connection_test.rb +282 -32
- data/test/unit/cursor_test.rb +206 -8
- data/test/unit/db_test.rb +55 -13
- data/test/unit/grid_test.rb +43 -16
- data/test/unit/mongo_sharded_client_test.rb +48 -0
- data/test/unit/node_test.rb +93 -0
- data/test/unit/pool_manager_test.rb +111 -0
- data/test/unit/read_pref_test.rb +406 -0
- data/test/unit/read_test.rb +159 -0
- data/test/unit/safe_test.rb +69 -36
- data/test/unit/sharding_pool_manager_test.rb +84 -0
- data/test/unit/write_concern_test.rb +175 -0
- data.tar.gz.sig +3 -0
- metadata +227 -216
- metadata.gz.sig +0 -0
- data/docs/CREDITS.md +0 -123
- data/docs/FAQ.md +0 -116
- data/docs/GridFS.md +0 -158
- data/docs/HISTORY.md +0 -244
- data/docs/RELEASES.md +0 -33
- data/docs/REPLICA_SETS.md +0 -72
- data/docs/TUTORIAL.md +0 -247
- data/docs/WRITE_CONCERN.md +0 -28
- data/lib/mongo/exceptions.rb +0 -71
- data/lib/mongo/gridfs/grid_io_fix.rb +0 -38
- data/lib/mongo/repl_set_connection.rb +0 -342
- data/lib/mongo/test.rb +0 -20
- data/lib/mongo/util/pool.rb +0 -177
- data/lib/mongo/util/uri_parser.rb +0 -185
- data/test/async/collection_test.rb +0 -224
- data/test/async/connection_test.rb +0 -24
- data/test/async/cursor_test.rb +0 -162
- data/test/async/worker_pool_test.rb +0 -99
- data/test/auxillary/1.4_features.rb +0 -166
- data/test/auxillary/authentication_test.rb +0 -68
- data/test/auxillary/autoreconnect_test.rb +0 -41
- data/test/auxillary/fork_test.rb +0 -30
- data/test/auxillary/repl_set_auth_test.rb +0 -58
- data/test/auxillary/slave_connection_test.rb +0 -36
- data/test/auxillary/threaded_authentication_test.rb +0 -101
- data/test/bson/binary_test.rb +0 -15
- data/test/bson/bson_test.rb +0 -649
- data/test/bson/byte_buffer_test.rb +0 -208
- data/test/bson/hash_with_indifferent_access_test.rb +0 -38
- data/test/bson/json_test.rb +0 -17
- data/test/bson/object_id_test.rb +0 -154
- data/test/bson/ordered_hash_test.rb +0 -204
- data/test/bson/timestamp_test.rb +0 -24
- data/test/collection_test.rb +0 -910
- data/test/connection_test.rb +0 -309
- data/test/cursor_fail_test.rb +0 -75
- data/test/cursor_message_test.rb +0 -43
- data/test/cursor_test.rb +0 -483
- data/test/db_api_test.rb +0 -726
- data/test/db_connection_test.rb +0 -15
- data/test/db_test.rb +0 -287
- data/test/grid_file_system_test.rb +0 -243
- data/test/load/resque/load.rb +0 -21
- data/test/load/resque/processor.rb +0 -26
- data/test/load/thin/load.rb +0 -24
- data/test/load/unicorn/load.rb +0 -23
- data/test/load/unicorn/unicorn.rb +0 -29
- data/test/replica_sets/connect_test.rb +0 -94
- data/test/replica_sets/connection_string_test.rb +0 -32
- data/test/replica_sets/count_test.rb +0 -35
- data/test/replica_sets/insert_test.rb +0 -53
- data/test/replica_sets/pooled_insert_test.rb +0 -55
- data/test/replica_sets/query_secondaries.rb +0 -96
- data/test/replica_sets/query_test.rb +0 -51
- data/test/replica_sets/replication_ack_test.rb +0 -66
- data/test/replica_sets/rs_test_helper.rb +0 -27
- data/test/safe_test.rb +0 -68
- data/test/support/hash_with_indifferent_access.rb +0 -186
- data/test/support/keys.rb +0 -45
- data/test/support_test.rb +0 -18
- data/test/threading/threading_with_large_pool_test.rb +0 -90
- data/test/threading_test.rb +0 -87
- data/test/tools/auth_repl_set_manager.rb +0 -14
- data/test/tools/load.rb +0 -58
- data/test/tools/repl_set_manager.rb +0 -266
- data/test/tools/sharding_manager.rb +0 -202
- data/test/tools/test.rb +0 -4
- data/test/unit/pool_test.rb +0 -9
- data/test/unit/repl_set_connection_test.rb +0 -59
- data/test/uri_test.rb +0 -91
@@ -0,0 +1,683 @@
|
|
1
|
+
# Copyright (C) 2009-2013 MongoDB, Inc.
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
# you may not use this file except in compliance with the License.
|
5
|
+
# You may obtain a copy of the License at
|
6
|
+
#
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
#
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
# See the License for the specific language governing permissions and
|
13
|
+
# limitations under the License.
|
14
|
+
|
15
|
+
require 'test_helper'
|
16
|
+
require 'logger'
|
17
|
+
|
18
|
+
class CursorTest < Test::Unit::TestCase
|
19
|
+
include Mongo
|
20
|
+
include Mongo::Constants
|
21
|
+
|
22
|
+
def setup
|
23
|
+
@connection = standard_connection
|
24
|
+
@db = @connection.db(TEST_DB)
|
25
|
+
@coll = @db.collection('test')
|
26
|
+
@version = @connection.server_version
|
27
|
+
@coll.remove
|
28
|
+
@coll.insert('a' => 1) # collection not created until it's used
|
29
|
+
@coll_full_name = "#{TEST_DB}.test"
|
30
|
+
end
|
31
|
+
|
32
|
+
def test_alive
|
33
|
+
batch = []
|
34
|
+
5000.times do |n|
|
35
|
+
batch << {:a => n}
|
36
|
+
end
|
37
|
+
|
38
|
+
@coll.insert(batch)
|
39
|
+
cursor = @coll.find
|
40
|
+
assert !cursor.alive?
|
41
|
+
cursor.next
|
42
|
+
assert cursor.alive?
|
43
|
+
cursor.close
|
44
|
+
assert !cursor.alive?
|
45
|
+
@coll.remove
|
46
|
+
end
|
47
|
+
|
48
|
+
def test_add_and_remove_options
|
49
|
+
c = @coll.find
|
50
|
+
assert_equal 0, c.options & OP_QUERY_EXHAUST
|
51
|
+
c.add_option(OP_QUERY_EXHAUST)
|
52
|
+
assert_equal OP_QUERY_EXHAUST, c.options & OP_QUERY_EXHAUST
|
53
|
+
c.remove_option(OP_QUERY_EXHAUST)
|
54
|
+
assert_equal 0, c.options & OP_QUERY_EXHAUST
|
55
|
+
|
56
|
+
c.next
|
57
|
+
assert_raise Mongo::InvalidOperation do
|
58
|
+
c.add_option(OP_QUERY_EXHAUST)
|
59
|
+
end
|
60
|
+
|
61
|
+
assert_raise Mongo::InvalidOperation do
|
62
|
+
c.add_option(OP_QUERY_EXHAUST)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def test_exhaust
|
67
|
+
if @version >= "2.0"
|
68
|
+
@coll.remove
|
69
|
+
data = "1" * 10_000
|
70
|
+
5000.times do |n|
|
71
|
+
@coll.insert({:n => n, :data => data})
|
72
|
+
end
|
73
|
+
|
74
|
+
c = Cursor.new(@coll)
|
75
|
+
c.add_option(OP_QUERY_EXHAUST)
|
76
|
+
assert_equal @coll.count, c.to_a.size
|
77
|
+
assert c.closed?
|
78
|
+
|
79
|
+
c = Cursor.new(@coll)
|
80
|
+
c.add_option(OP_QUERY_EXHAUST)
|
81
|
+
4999.times do
|
82
|
+
c.next
|
83
|
+
end
|
84
|
+
assert c.has_next?
|
85
|
+
assert c.next
|
86
|
+
assert !c.has_next?
|
87
|
+
assert c.closed?
|
88
|
+
|
89
|
+
@coll.remove
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
def test_compile_regex_get_more
|
94
|
+
return unless defined?(BSON::BSON_RUBY) && BSON::BSON_CODER == BSON::BSON_RUBY
|
95
|
+
@coll.remove
|
96
|
+
n_docs = 3
|
97
|
+
n_docs.times { |n| @coll.insert({ 'n' => /.*/ }) }
|
98
|
+
cursor = @coll.find({}, :batch_size => (n_docs-1), :compile_regex => false)
|
99
|
+
cursor.expects(:send_get_more)
|
100
|
+
cursor.to_a.each do |doc|
|
101
|
+
assert_kind_of BSON::Regex, doc['n']
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
def test_max_time_ms_error
|
106
|
+
cursor = @coll.find
|
107
|
+
cursor.stubs(:send_initial_query).returns(true)
|
108
|
+
|
109
|
+
cursor.instance_variable_set(:@cache, [{
|
110
|
+
'$err' => 'operation exceeded time limit',
|
111
|
+
'code' => 50
|
112
|
+
}])
|
113
|
+
|
114
|
+
assert_raise ExecutionTimeout do
|
115
|
+
cursor.to_a
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
def test_max_time_ms
|
120
|
+
with_forced_timeout(@connection) do
|
121
|
+
assert_raise ExecutionTimeout do
|
122
|
+
cursor = @coll.find.max_time_ms(100)
|
123
|
+
cursor.to_a
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
def test_exhaust_after_limit_error
|
129
|
+
c = Cursor.new(@coll, :limit => 17)
|
130
|
+
assert_raise MongoArgumentError do
|
131
|
+
c.add_option(OP_QUERY_EXHAUST)
|
132
|
+
end
|
133
|
+
|
134
|
+
assert_raise MongoArgumentError do
|
135
|
+
c.add_option(OP_QUERY_EXHAUST + OP_QUERY_SLAVE_OK)
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
def test_limit_after_exhaust_error
|
140
|
+
c = Cursor.new(@coll)
|
141
|
+
c.add_option(OP_QUERY_EXHAUST)
|
142
|
+
assert_raise MongoArgumentError do
|
143
|
+
c.limit(17)
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
def test_exhaust_with_mongos
|
148
|
+
@connection.expects(:mongos?).returns(:true)
|
149
|
+
c = Cursor.new(@coll)
|
150
|
+
|
151
|
+
assert_raise MongoArgumentError do
|
152
|
+
c.add_option(OP_QUERY_EXHAUST)
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
def test_inspect
|
157
|
+
selector = {:a => 1}
|
158
|
+
cursor = @coll.find(selector)
|
159
|
+
assert_equal "<Mongo::Cursor:0x#{cursor.object_id.to_s(16)} namespace='#{@db.name}.#{@coll.name}' " +
|
160
|
+
"@selector=#{selector.inspect} @cursor_id=#{cursor.cursor_id}>", cursor.inspect
|
161
|
+
end
|
162
|
+
|
163
|
+
def test_explain
|
164
|
+
cursor = @coll.find('a' => 1)
|
165
|
+
explanation = cursor.explain
|
166
|
+
if @version < '2.7'
|
167
|
+
assert_not_nil explanation['cursor']
|
168
|
+
assert_kind_of Numeric, explanation['n']
|
169
|
+
assert_kind_of Numeric, explanation['millis']
|
170
|
+
assert_kind_of Numeric, explanation['nscanned']
|
171
|
+
else
|
172
|
+
cursor = @coll.find('a' => 1)
|
173
|
+
assert_not_nil explanation
|
174
|
+
assert explanation.keys.include?('executionStats')
|
175
|
+
end
|
176
|
+
end
|
177
|
+
|
178
|
+
def test_each_with_no_block
|
179
|
+
assert_kind_of(Enumerator, @coll.find().each) if defined? Enumerator
|
180
|
+
end
|
181
|
+
|
182
|
+
def test_count
|
183
|
+
@coll.remove
|
184
|
+
|
185
|
+
assert_equal 0, @coll.find().count()
|
186
|
+
|
187
|
+
10.times do |i|
|
188
|
+
@coll.save("x" => i)
|
189
|
+
end
|
190
|
+
|
191
|
+
assert_equal 10, @coll.find().count()
|
192
|
+
assert_kind_of Integer, @coll.find().count()
|
193
|
+
assert_equal 10, @coll.find({}, :limit => 5).count()
|
194
|
+
assert_equal 10, @coll.find({}, :skip => 5).count()
|
195
|
+
|
196
|
+
assert_equal 5, @coll.find({}, :limit => 5).count(true)
|
197
|
+
assert_equal 5, @coll.find({}, :skip => 5).count(true)
|
198
|
+
assert_equal 2, @coll.find({}, :skip => 5, :limit => 2).count(true)
|
199
|
+
|
200
|
+
assert_equal 1, @coll.find({"x" => 1}).count()
|
201
|
+
assert_equal 5, @coll.find({"x" => {"$lt" => 5}}).count()
|
202
|
+
|
203
|
+
a = @coll.find()
|
204
|
+
b = a.count()
|
205
|
+
a.each do |doc|
|
206
|
+
break
|
207
|
+
end
|
208
|
+
assert_equal b, a.count()
|
209
|
+
|
210
|
+
assert_equal 0, @db['acollectionthatdoesn'].count()
|
211
|
+
end
|
212
|
+
|
213
|
+
def test_sort
|
214
|
+
@coll.remove
|
215
|
+
5.times{|x| @coll.insert({"age" => x}) }
|
216
|
+
|
217
|
+
assert_kind_of Cursor, @coll.find().sort(:age, 1)
|
218
|
+
|
219
|
+
assert_equal 0, @coll.find().sort(:age, 1).next_document["age"]
|
220
|
+
assert_equal 4, @coll.find().sort(:age, -1).next_document["age"]
|
221
|
+
assert_equal 0, @coll.find().sort([["age", :asc]]).next_document["age"]
|
222
|
+
|
223
|
+
assert_kind_of Cursor, @coll.find().sort([[:age, -1], [:b, 1]])
|
224
|
+
|
225
|
+
assert_equal 4, @coll.find().sort(:age, 1).sort(:age, -1).next_document["age"]
|
226
|
+
assert_equal 0, @coll.find().sort(:age, -1).sort(:age, 1).next_document["age"]
|
227
|
+
|
228
|
+
assert_equal 4, @coll.find().sort([:age, :asc]).sort(:age, -1).next_document["age"]
|
229
|
+
assert_equal 0, @coll.find().sort([:age, :desc]).sort(:age, 1).next_document["age"]
|
230
|
+
|
231
|
+
cursor = @coll.find()
|
232
|
+
cursor.next_document
|
233
|
+
assert_raise InvalidOperation do
|
234
|
+
cursor.sort(["age"])
|
235
|
+
end
|
236
|
+
|
237
|
+
assert_raise InvalidSortValueError do
|
238
|
+
@coll.find().sort(:age, 25).next_document
|
239
|
+
end
|
240
|
+
|
241
|
+
assert_raise InvalidSortValueError do
|
242
|
+
@coll.find().sort(25).next_document
|
243
|
+
end
|
244
|
+
end
|
245
|
+
|
246
|
+
def test_sort_date
|
247
|
+
@coll.remove
|
248
|
+
5.times{|x| @coll.insert({"created_at" => Time.utc(2000 + x)}) }
|
249
|
+
|
250
|
+
assert_equal 2000, @coll.find().sort(:created_at, :asc).next_document["created_at"].year
|
251
|
+
assert_equal 2004, @coll.find().sort(:created_at, :desc).next_document["created_at"].year
|
252
|
+
|
253
|
+
assert_equal 2000, @coll.find().sort([:created_at, :asc]).next_document["created_at"].year
|
254
|
+
assert_equal 2004, @coll.find().sort([:created_at, :desc]).next_document["created_at"].year
|
255
|
+
|
256
|
+
assert_equal 2000, @coll.find().sort([[:created_at, :asc]]).next_document["created_at"].year
|
257
|
+
assert_equal 2004, @coll.find().sort([[:created_at, :desc]]).next_document["created_at"].year
|
258
|
+
end
|
259
|
+
|
260
|
+
def test_sort_min_max_keys
|
261
|
+
@coll.remove
|
262
|
+
@coll.insert({"n" => 1000000})
|
263
|
+
@coll.insert({"n" => -1000000})
|
264
|
+
@coll.insert({"n" => MaxKey.new})
|
265
|
+
@coll.insert({"n" => MinKey.new})
|
266
|
+
|
267
|
+
results = @coll.find.sort([:n, :asc]).to_a
|
268
|
+
|
269
|
+
assert_equal MinKey.new, results[0]['n']
|
270
|
+
assert_equal(-1000000, results[1]['n'])
|
271
|
+
assert_equal 1000000, results[2]['n']
|
272
|
+
assert_equal MaxKey.new, results[3]['n']
|
273
|
+
end
|
274
|
+
|
275
|
+
def test_id_range_queries
|
276
|
+
@coll.remove
|
277
|
+
|
278
|
+
t1 = Time.now
|
279
|
+
t1_id = ObjectId.from_time(t1)
|
280
|
+
@coll.save({:t => 't1'})
|
281
|
+
@coll.save({:t => 't1'})
|
282
|
+
@coll.save({:t => 't1'})
|
283
|
+
sleep(1)
|
284
|
+
t2 = Time.now
|
285
|
+
t2_id = ObjectId.from_time(t2)
|
286
|
+
@coll.save({:t => 't2'})
|
287
|
+
@coll.save({:t => 't2'})
|
288
|
+
@coll.save({:t => 't2'})
|
289
|
+
|
290
|
+
assert_equal 3, @coll.find({'_id' => {'$gt' => t1_id, '$lt' => t2_id}}).count
|
291
|
+
@coll.find({'_id' => {'$gt' => t2_id}}).each do |doc|
|
292
|
+
assert_equal 't2', doc['t']
|
293
|
+
end
|
294
|
+
end
|
295
|
+
|
296
|
+
def test_limit
|
297
|
+
@coll.remove
|
298
|
+
|
299
|
+
10.times do |i|
|
300
|
+
@coll.save("x" => i)
|
301
|
+
end
|
302
|
+
assert_equal 10, @coll.find().count()
|
303
|
+
|
304
|
+
results = @coll.find().limit(5).to_a
|
305
|
+
assert_equal 5, results.length
|
306
|
+
end
|
307
|
+
|
308
|
+
def test_timeout_options
|
309
|
+
cursor = Cursor.new(@coll)
|
310
|
+
assert_equal true, cursor.timeout
|
311
|
+
|
312
|
+
cursor = @coll.find
|
313
|
+
assert_equal true, cursor.timeout
|
314
|
+
|
315
|
+
cursor = @coll.find({}, :timeout => nil)
|
316
|
+
assert_equal true, cursor.timeout
|
317
|
+
|
318
|
+
cursor = Cursor.new(@coll, :timeout => false)
|
319
|
+
assert_equal false, cursor.timeout
|
320
|
+
|
321
|
+
@coll.find({}, :timeout => false) do |c|
|
322
|
+
assert_equal false, c.timeout
|
323
|
+
end
|
324
|
+
end
|
325
|
+
|
326
|
+
def test_timeout
|
327
|
+
opts = Cursor.new(@coll).options
|
328
|
+
assert_equal 0, opts & Mongo::Constants::OP_QUERY_NO_CURSOR_TIMEOUT
|
329
|
+
|
330
|
+
opts = Cursor.new(@coll, :timeout => false).options
|
331
|
+
assert_equal Mongo::Constants::OP_QUERY_NO_CURSOR_TIMEOUT,
|
332
|
+
opts & Mongo::Constants::OP_QUERY_NO_CURSOR_TIMEOUT
|
333
|
+
end
|
334
|
+
|
335
|
+
def test_limit_exceptions
|
336
|
+
cursor = @coll.find()
|
337
|
+
cursor.next_document
|
338
|
+
assert_raise InvalidOperation, "Cannot modify the query once it has been run or closed." do
|
339
|
+
cursor.limit(1)
|
340
|
+
end
|
341
|
+
|
342
|
+
cursor = @coll.find()
|
343
|
+
cursor.close
|
344
|
+
assert_raise InvalidOperation, "Cannot modify the query once it has been run or closed." do
|
345
|
+
cursor.limit(1)
|
346
|
+
end
|
347
|
+
end
|
348
|
+
|
349
|
+
def test_skip
|
350
|
+
@coll.remove
|
351
|
+
|
352
|
+
10.times do |i|
|
353
|
+
@coll.save("x" => i)
|
354
|
+
end
|
355
|
+
assert_equal 10, @coll.find().count()
|
356
|
+
|
357
|
+
all_results = @coll.find().to_a
|
358
|
+
skip_results = @coll.find().skip(2).to_a
|
359
|
+
assert_equal 10, all_results.length
|
360
|
+
assert_equal 8, skip_results.length
|
361
|
+
|
362
|
+
assert_equal all_results.slice(2...10), skip_results
|
363
|
+
end
|
364
|
+
|
365
|
+
def test_skip_exceptions
|
366
|
+
cursor = @coll.find()
|
367
|
+
cursor.next_document
|
368
|
+
assert_raise InvalidOperation, "Cannot modify the query once it has been run or closed." do
|
369
|
+
cursor.skip(1)
|
370
|
+
end
|
371
|
+
|
372
|
+
cursor = @coll.find()
|
373
|
+
cursor.close
|
374
|
+
assert_raise InvalidOperation, "Cannot modify the query once it has been run or closed." do
|
375
|
+
cursor.skip(1)
|
376
|
+
end
|
377
|
+
end
|
378
|
+
|
379
|
+
def test_limit_skip_chaining
|
380
|
+
@coll.remove
|
381
|
+
10.times do |i|
|
382
|
+
@coll.save("x" => i)
|
383
|
+
end
|
384
|
+
|
385
|
+
all_results = @coll.find().to_a
|
386
|
+
limited_skip_results = @coll.find().limit(5).skip(3).to_a
|
387
|
+
|
388
|
+
assert_equal all_results.slice(3...8), limited_skip_results
|
389
|
+
end
|
390
|
+
|
391
|
+
def test_close_no_query_sent
|
392
|
+
begin
|
393
|
+
cursor = @coll.find('a' => 1)
|
394
|
+
cursor.close
|
395
|
+
assert cursor.closed?
|
396
|
+
rescue => ex
|
397
|
+
fail ex.to_s
|
398
|
+
end
|
399
|
+
end
|
400
|
+
|
401
|
+
def test_refill_via_get_more
|
402
|
+
assert_equal 1, @coll.count
|
403
|
+
1000.times { |i|
|
404
|
+
assert_equal 1 + i, @coll.count
|
405
|
+
@coll.insert('a' => i)
|
406
|
+
}
|
407
|
+
|
408
|
+
assert_equal 1001, @coll.count
|
409
|
+
count = 0
|
410
|
+
@coll.find.each { |obj|
|
411
|
+
count += obj['a']
|
412
|
+
}
|
413
|
+
assert_equal 1001, @coll.count
|
414
|
+
|
415
|
+
# do the same thing again for debugging
|
416
|
+
assert_equal 1001, @coll.count
|
417
|
+
count2 = 0
|
418
|
+
@coll.find.each { |obj|
|
419
|
+
count2 += obj['a']
|
420
|
+
}
|
421
|
+
assert_equal 1001, @coll.count
|
422
|
+
|
423
|
+
assert_equal count, count2
|
424
|
+
assert_equal 499501, count
|
425
|
+
end
|
426
|
+
|
427
|
+
def test_refill_via_get_more_alt_coll
|
428
|
+
coll = @db.collection('test-alt-coll')
|
429
|
+
coll.remove
|
430
|
+
coll.insert('a' => 1) # collection not created until it's used
|
431
|
+
assert_equal 1, coll.count
|
432
|
+
|
433
|
+
1000.times { |i|
|
434
|
+
assert_equal 1 + i, coll.count
|
435
|
+
coll.insert('a' => i)
|
436
|
+
}
|
437
|
+
|
438
|
+
assert_equal 1001, coll.count
|
439
|
+
count = 0
|
440
|
+
coll.find.each { |obj|
|
441
|
+
count += obj['a']
|
442
|
+
}
|
443
|
+
assert_equal 1001, coll.count
|
444
|
+
|
445
|
+
# do the same thing again for debugging
|
446
|
+
assert_equal 1001, coll.count
|
447
|
+
count2 = 0
|
448
|
+
coll.find.each { |obj|
|
449
|
+
count2 += obj['a']
|
450
|
+
}
|
451
|
+
assert_equal 1001, coll.count
|
452
|
+
|
453
|
+
assert_equal count, count2
|
454
|
+
assert_equal 499501, count
|
455
|
+
end
|
456
|
+
|
457
|
+
def test_close_after_query_sent
|
458
|
+
begin
|
459
|
+
cursor = @coll.find('a' => 1)
|
460
|
+
cursor.next_document
|
461
|
+
cursor.close
|
462
|
+
assert cursor.closed?
|
463
|
+
rescue => ex
|
464
|
+
fail ex.to_s
|
465
|
+
end
|
466
|
+
end
|
467
|
+
|
468
|
+
def test_kill_cursors
|
469
|
+
@coll.drop
|
470
|
+
|
471
|
+
client_cursors = cursor_count(@db)
|
472
|
+
|
473
|
+
10000.times do |i|
|
474
|
+
@coll.insert("i" => i)
|
475
|
+
end
|
476
|
+
|
477
|
+
assert_equal(client_cursors, cursor_count(@db))
|
478
|
+
|
479
|
+
10.times do |i|
|
480
|
+
@coll.find_one()
|
481
|
+
end
|
482
|
+
|
483
|
+
assert_equal(client_cursors, cursor_count(@db))
|
484
|
+
|
485
|
+
10.times do |i|
|
486
|
+
a = @coll.find()
|
487
|
+
a.next_document
|
488
|
+
a.close()
|
489
|
+
end
|
490
|
+
|
491
|
+
assert_equal(client_cursors, cursor_count(@db))
|
492
|
+
|
493
|
+
a = @coll.find()
|
494
|
+
a.next_document
|
495
|
+
|
496
|
+
assert_not_equal(client_cursors, cursor_count(@db))
|
497
|
+
|
498
|
+
a.close()
|
499
|
+
|
500
|
+
assert_equal(client_cursors, cursor_count(@db))
|
501
|
+
|
502
|
+
a = @coll.find({}, :limit => 10).next_document
|
503
|
+
|
504
|
+
assert_equal(client_cursors, cursor_count(@db))
|
505
|
+
|
506
|
+
@coll.find() do |cursor|
|
507
|
+
cursor.next_document
|
508
|
+
end
|
509
|
+
|
510
|
+
assert_equal(client_cursors, cursor_count(@db))
|
511
|
+
|
512
|
+
@coll.find() { |cursor|
|
513
|
+
cursor.next_document
|
514
|
+
}
|
515
|
+
|
516
|
+
assert_equal(client_cursors, cursor_count(@db))
|
517
|
+
end
|
518
|
+
|
519
|
+
def test_count_with_fields
|
520
|
+
@coll.remove
|
521
|
+
@coll.save("x" => 1)
|
522
|
+
|
523
|
+
if @version < "1.1.3"
|
524
|
+
assert_equal(0, @coll.find({}, :fields => ["a"]).count())
|
525
|
+
else
|
526
|
+
assert_equal(1, @coll.find({}, :fields => ["a"]).count())
|
527
|
+
end
|
528
|
+
end
|
529
|
+
|
530
|
+
def test_count_with_hint
|
531
|
+
@coll.drop
|
532
|
+
@coll.save(:i => 1)
|
533
|
+
@coll.save(:i => 2)
|
534
|
+
assert_equal 2, @coll.find.count
|
535
|
+
|
536
|
+
@coll.ensure_index(BSON::OrderedHash[:i, Mongo::ASCENDING])
|
537
|
+
|
538
|
+
# Check that a named_hint can be specified
|
539
|
+
assert_equal 1, @coll.find({ :i => 1 }, :named_hint => '_id_').count
|
540
|
+
assert_equal 2, @coll.find({ }, :named_hint => '_id_').count
|
541
|
+
|
542
|
+
# Verify that the hint is being sent to the server by providing a bad hint
|
543
|
+
if @version > '2.6'
|
544
|
+
assert_raise Mongo::OperationFailure do
|
545
|
+
@coll.find({ :i => 1 }, :hint => 'bad_hint').count
|
546
|
+
end
|
547
|
+
else
|
548
|
+
assert_equal 1, @coll.find({ :i => 1 }, :hint => 'bad_hint').count
|
549
|
+
end
|
550
|
+
|
551
|
+
# Verify that the named_hint is being sent to the server by providing a bad hint
|
552
|
+
if @version > '2.6'
|
553
|
+
assert_raise Mongo::OperationFailure do
|
554
|
+
@coll.find({ :i => 1 }, :named_hint => 'bad_hint').count
|
555
|
+
end
|
556
|
+
else
|
557
|
+
assert_equal 1, @coll.find({ :i => 1 }, :named_hint => 'bad_hint').count
|
558
|
+
end
|
559
|
+
|
560
|
+
@coll.ensure_index(BSON::OrderedHash[:x, Mongo::ASCENDING], :sparse => true)
|
561
|
+
|
562
|
+
# The sparse index won't have any entries.
|
563
|
+
# Check that count returns 0 when using the hint.
|
564
|
+
expected = @version > '2.6' ? 0 : 1
|
565
|
+
assert_equal expected, @coll.find({ :i => 1 }, :hint => { 'x' => 1 }).count
|
566
|
+
assert_equal expected, @coll.find({ :i => 1 }, :hint => 'x').count
|
567
|
+
assert_equal expected, @coll.find({ :i => 1 }, :named_hint => 'x_1').count
|
568
|
+
|
569
|
+
# Verify that the hint / named hint set on the collection is used.
|
570
|
+
@coll.hint = { 'x' => 1 }
|
571
|
+
assert_equal expected, @coll.find(:i => 1).count
|
572
|
+
|
573
|
+
@coll.hint = 'x'
|
574
|
+
assert_equal expected, @coll.find(:i => 1).count
|
575
|
+
|
576
|
+
@coll.named_hint = 'x_1'
|
577
|
+
assert_equal expected, @coll.find(:i => 1).count
|
578
|
+
|
579
|
+
assert_equal 2, @coll.find({ }, :hint => 'x').count
|
580
|
+
assert_equal 2, @coll.find({ }, :named_hint => 'x_1').count
|
581
|
+
end
|
582
|
+
|
583
|
+
def test_has_next
|
584
|
+
@coll.remove
|
585
|
+
200.times do |n|
|
586
|
+
@coll.save("x" => n)
|
587
|
+
end
|
588
|
+
|
589
|
+
cursor = @coll.find
|
590
|
+
n = 0
|
591
|
+
while cursor.has_next?
|
592
|
+
assert cursor.next
|
593
|
+
n += 1
|
594
|
+
end
|
595
|
+
|
596
|
+
assert_equal n, 200
|
597
|
+
assert_equal false, cursor.has_next?
|
598
|
+
end
|
599
|
+
|
600
|
+
def test_cursor_invalid
|
601
|
+
@coll.remove
|
602
|
+
10000.times do |n|
|
603
|
+
@coll.insert({:a => n})
|
604
|
+
end
|
605
|
+
|
606
|
+
cursor = @coll.find({})
|
607
|
+
|
608
|
+
assert_raise_error Mongo::OperationFailure, "CURSOR_NOT_FOUND" do
|
609
|
+
9999.times do
|
610
|
+
cursor.next_document
|
611
|
+
cursor.instance_variable_set(:@cursor_id, 1234567890)
|
612
|
+
end
|
613
|
+
end
|
614
|
+
end
|
615
|
+
|
616
|
+
def test_enumberables
|
617
|
+
@coll.remove
|
618
|
+
100.times do |n|
|
619
|
+
@coll.insert({:a => n})
|
620
|
+
end
|
621
|
+
|
622
|
+
assert_equal 100, @coll.find.to_a.length
|
623
|
+
assert_equal 100, @coll.find.to_set.length
|
624
|
+
|
625
|
+
cursor = @coll.find
|
626
|
+
50.times { |n| cursor.next_document }
|
627
|
+
assert_equal 50, cursor.to_a.length
|
628
|
+
end
|
629
|
+
|
630
|
+
def test_rewind
|
631
|
+
@coll.remove
|
632
|
+
100.times do |n|
|
633
|
+
@coll.insert({:a => n})
|
634
|
+
end
|
635
|
+
|
636
|
+
cursor = @coll.find
|
637
|
+
cursor.to_a
|
638
|
+
assert_equal [], cursor.map {|doc| doc }
|
639
|
+
|
640
|
+
cursor.rewind!
|
641
|
+
assert_equal 100, cursor.map {|doc| doc }.length
|
642
|
+
|
643
|
+
cursor.rewind!
|
644
|
+
5.times { cursor.next_document }
|
645
|
+
cursor.rewind!
|
646
|
+
assert_equal 100, cursor.map {|doc| doc }.length
|
647
|
+
end
|
648
|
+
|
649
|
+
def test_transformer
|
650
|
+
transformer = Proc.new { |doc| doc }
|
651
|
+
cursor = Cursor.new(@coll, :transformer => transformer)
|
652
|
+
assert_equal(transformer, cursor.transformer)
|
653
|
+
end
|
654
|
+
|
655
|
+
def test_instance_transformation_with_next
|
656
|
+
klass = Struct.new(:id, :a)
|
657
|
+
transformer = Proc.new { |doc| klass.new(doc['_id'], doc['a']) }
|
658
|
+
cursor = Cursor.new(@coll, :transformer => transformer)
|
659
|
+
instance = cursor.next
|
660
|
+
|
661
|
+
assert_instance_of(klass, instance)
|
662
|
+
assert_instance_of(BSON::ObjectId, instance.id)
|
663
|
+
assert_equal(1, instance.a)
|
664
|
+
end
|
665
|
+
|
666
|
+
def test_instance_transformation_with_each
|
667
|
+
klass = Struct.new(:id, :a)
|
668
|
+
transformer = Proc.new { |doc| klass.new(doc['_id'], doc['a']) }
|
669
|
+
cursor = Cursor.new(@coll, :transformer => transformer)
|
670
|
+
|
671
|
+
cursor.each do |instance|
|
672
|
+
assert_instance_of(klass, instance)
|
673
|
+
end
|
674
|
+
end
|
675
|
+
|
676
|
+
def cursor_count(db)
|
677
|
+
if @version > '2.6.0'
|
678
|
+
db.command("serverStatus" => 1)["metrics"]["cursor"]["open"]["total"]
|
679
|
+
else
|
680
|
+
db.command("cursorInfo" => 1)["clientCursors_size"]
|
681
|
+
end
|
682
|
+
end
|
683
|
+
end
|