mongo 0.1.0 → 0.15
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.
- data/README.rdoc +268 -71
- data/Rakefile +27 -62
- data/bin/bson_benchmark.rb +59 -0
- data/bin/mongo_console +3 -3
- data/bin/run_test_script +19 -0
- data/bin/standard_benchmark +109 -0
- data/examples/admin.rb +41 -0
- data/examples/benchmarks.rb +42 -0
- data/examples/blog.rb +76 -0
- data/examples/capped.rb +23 -0
- data/examples/cursor.rb +47 -0
- data/examples/gridfs.rb +87 -0
- data/examples/index_test.rb +125 -0
- data/examples/info.rb +30 -0
- data/examples/queries.rb +69 -0
- data/examples/simple.rb +23 -0
- data/examples/strict.rb +34 -0
- data/examples/types.rb +35 -0
- data/lib/mongo.rb +9 -2
- data/lib/mongo/admin.rb +65 -68
- data/lib/mongo/collection.rb +379 -117
- data/lib/mongo/connection.rb +151 -0
- data/lib/mongo/cursor.rb +271 -216
- data/lib/mongo/db.rb +500 -315
- data/lib/mongo/errors.rb +26 -0
- data/lib/mongo/gridfs.rb +16 -0
- data/lib/mongo/gridfs/chunk.rb +92 -0
- data/lib/mongo/gridfs/grid_store.rb +464 -0
- data/lib/mongo/message.rb +16 -0
- data/lib/mongo/message/get_more_message.rb +24 -13
- data/lib/mongo/message/insert_message.rb +29 -11
- data/lib/mongo/message/kill_cursors_message.rb +23 -12
- data/lib/mongo/message/message.rb +74 -62
- data/lib/mongo/message/message_header.rb +35 -24
- data/lib/mongo/message/msg_message.rb +21 -9
- data/lib/mongo/message/opcodes.rb +26 -15
- data/lib/mongo/message/query_message.rb +63 -43
- data/lib/mongo/message/remove_message.rb +29 -12
- data/lib/mongo/message/update_message.rb +30 -13
- data/lib/mongo/query.rb +97 -89
- data/lib/mongo/types/binary.rb +25 -21
- data/lib/mongo/types/code.rb +30 -0
- data/lib/mongo/types/dbref.rb +19 -23
- data/lib/mongo/types/objectid.rb +130 -116
- data/lib/mongo/types/regexp_of_holding.rb +27 -31
- data/lib/mongo/util/bson.rb +273 -160
- data/lib/mongo/util/byte_buffer.rb +32 -28
- data/lib/mongo/util/ordered_hash.rb +88 -42
- data/lib/mongo/util/xml_to_ruby.rb +18 -15
- data/mongo-ruby-driver.gemspec +103 -0
- data/test/mongo-qa/_common.rb +8 -0
- data/test/mongo-qa/admin +26 -0
- data/test/mongo-qa/capped +22 -0
- data/test/mongo-qa/count1 +18 -0
- data/test/mongo-qa/dbs +22 -0
- data/test/mongo-qa/find +10 -0
- data/test/mongo-qa/find1 +15 -0
- data/test/mongo-qa/gridfs_in +16 -0
- data/test/mongo-qa/gridfs_out +17 -0
- data/test/mongo-qa/indices +49 -0
- data/test/mongo-qa/remove +25 -0
- data/test/mongo-qa/stress1 +35 -0
- data/test/mongo-qa/test1 +11 -0
- data/test/mongo-qa/update +18 -0
- data/{tests → test}/test_admin.rb +25 -16
- data/test/test_bson.rb +268 -0
- data/{tests → test}/test_byte_buffer.rb +0 -0
- data/test/test_chunk.rb +84 -0
- data/test/test_collection.rb +282 -0
- data/test/test_connection.rb +101 -0
- data/test/test_cursor.rb +321 -0
- data/test/test_db.rb +196 -0
- data/test/test_db_api.rb +798 -0
- data/{tests → test}/test_db_connection.rb +4 -3
- data/test/test_grid_store.rb +284 -0
- data/{tests → test}/test_message.rb +1 -1
- data/test/test_objectid.rb +105 -0
- data/{tests → test}/test_ordered_hash.rb +55 -0
- data/{tests → test}/test_round_trip.rb +13 -9
- data/test/test_threading.rb +37 -0
- metadata +74 -32
- data/bin/validate +0 -51
- data/lib/mongo/mongo.rb +0 -74
- data/lib/mongo/types/undefined.rb +0 -31
- data/tests/test_bson.rb +0 -135
- data/tests/test_cursor.rb +0 -66
- data/tests/test_db.rb +0 -51
- data/tests/test_db_api.rb +0 -349
- data/tests/test_objectid.rb +0 -88
data/test/test_db_api.rb
ADDED
@@ -0,0 +1,798 @@
|
|
1
|
+
$LOAD_PATH[0,0] = File.join(File.dirname(__FILE__), '..', 'lib')
|
2
|
+
require 'mongo'
|
3
|
+
require 'test/unit'
|
4
|
+
|
5
|
+
# NOTE: assumes Mongo is running
|
6
|
+
class DBAPITest < Test::Unit::TestCase
|
7
|
+
include Mongo
|
8
|
+
|
9
|
+
@@db = Connection.new(ENV['MONGO_RUBY_DRIVER_HOST'] || 'localhost',
|
10
|
+
ENV['MONGO_RUBY_DRIVER_PORT'] || Connection::DEFAULT_PORT).db('ruby-mongo-test')
|
11
|
+
@@coll = @@db.collection('test')
|
12
|
+
|
13
|
+
def setup
|
14
|
+
@@coll.clear
|
15
|
+
@r1 = {'a' => 1}
|
16
|
+
@@coll.insert(@r1) # collection not created until it's used
|
17
|
+
@@coll_full_name = 'ruby-mongo-test.test'
|
18
|
+
end
|
19
|
+
|
20
|
+
def teardown
|
21
|
+
@@coll.clear
|
22
|
+
@@db.error
|
23
|
+
end
|
24
|
+
|
25
|
+
def test_clear
|
26
|
+
assert_equal 1, @@coll.count
|
27
|
+
@@coll.clear
|
28
|
+
assert_equal 0, @@coll.count
|
29
|
+
end
|
30
|
+
|
31
|
+
def test_insert
|
32
|
+
assert_kind_of ObjectID, @@coll.insert('a' => 2)
|
33
|
+
assert_kind_of ObjectID, @@coll.insert('b' => 3)
|
34
|
+
|
35
|
+
assert_equal 3, @@coll.count
|
36
|
+
docs = @@coll.find().to_a
|
37
|
+
assert_equal 3, docs.length
|
38
|
+
assert docs.detect { |row| row['a'] == 1 }
|
39
|
+
assert docs.detect { |row| row['a'] == 2 }
|
40
|
+
assert docs.detect { |row| row['b'] == 3 }
|
41
|
+
|
42
|
+
@@coll << {'b' => 4}
|
43
|
+
docs = @@coll.find().to_a
|
44
|
+
assert_equal 4, docs.length
|
45
|
+
assert docs.detect { |row| row['b'] == 4 }
|
46
|
+
end
|
47
|
+
|
48
|
+
def test_save_ordered_hash
|
49
|
+
oh = OrderedHash.new
|
50
|
+
oh['a'] = -1
|
51
|
+
oh['b'] = 'foo'
|
52
|
+
|
53
|
+
oid = @@coll.save(oh)
|
54
|
+
assert_equal 'foo', @@coll.find_one(oid)['b']
|
55
|
+
|
56
|
+
oh = OrderedHash['a' => 1, 'b' => 'foo']
|
57
|
+
oid = @@coll.save(oh)
|
58
|
+
assert_equal 'foo', @@coll.find_one(oid)['b']
|
59
|
+
end
|
60
|
+
|
61
|
+
def test_insert_multiple
|
62
|
+
ids = @@coll.insert([{'a' => 2}, {'b' => 3}])
|
63
|
+
|
64
|
+
ids.each do |i|
|
65
|
+
assert_kind_of ObjectID, i
|
66
|
+
end
|
67
|
+
|
68
|
+
assert_equal 3, @@coll.count
|
69
|
+
docs = @@coll.find().to_a
|
70
|
+
assert_equal 3, docs.length
|
71
|
+
assert docs.detect { |row| row['a'] == 1 }
|
72
|
+
assert docs.detect { |row| row['a'] == 2 }
|
73
|
+
assert docs.detect { |row| row['b'] == 3 }
|
74
|
+
end
|
75
|
+
|
76
|
+
def test_count_on_nonexisting
|
77
|
+
@@db.drop_collection('foo')
|
78
|
+
assert_equal 0, @@db.collection('foo').count()
|
79
|
+
end
|
80
|
+
|
81
|
+
def test_find_simple
|
82
|
+
@r2 = @@coll.insert('a' => 2)
|
83
|
+
@r3 = @@coll.insert('b' => 3)
|
84
|
+
# Check sizes
|
85
|
+
docs = @@coll.find().to_a
|
86
|
+
assert_equal 3, docs.size
|
87
|
+
assert_equal 3, @@coll.count
|
88
|
+
|
89
|
+
# Find by other value
|
90
|
+
docs = @@coll.find('a' => @r1['a']).to_a
|
91
|
+
assert_equal 1, docs.size
|
92
|
+
doc = docs.first
|
93
|
+
# Can't compare _id values because at insert, an _id was added to @r1 by
|
94
|
+
# the database but we don't know what it is without re-reading the record
|
95
|
+
# (which is what we are doing right now).
|
96
|
+
# assert_equal doc['_id'], @r1['_id']
|
97
|
+
assert_equal doc['a'], @r1['a']
|
98
|
+
end
|
99
|
+
|
100
|
+
def test_find_advanced
|
101
|
+
@@coll.insert('a' => 2)
|
102
|
+
@@coll.insert('b' => 3)
|
103
|
+
|
104
|
+
# Find by advanced query (less than)
|
105
|
+
docs = @@coll.find('a' => { '$lt' => 10 }).to_a
|
106
|
+
assert_equal 2, docs.size
|
107
|
+
assert docs.detect { |row| row['a'] == 1 }
|
108
|
+
assert docs.detect { |row| row['a'] == 2 }
|
109
|
+
|
110
|
+
# Find by advanced query (greater than)
|
111
|
+
docs = @@coll.find('a' => { '$gt' => 1 }).to_a
|
112
|
+
assert_equal 1, docs.size
|
113
|
+
assert docs.detect { |row| row['a'] == 2 }
|
114
|
+
|
115
|
+
# Find by advanced query (less than or equal to)
|
116
|
+
docs = @@coll.find('a' => { '$lte' => 1 }).to_a
|
117
|
+
assert_equal 1, docs.size
|
118
|
+
assert docs.detect { |row| row['a'] == 1 }
|
119
|
+
|
120
|
+
# Find by advanced query (greater than or equal to)
|
121
|
+
docs = @@coll.find('a' => { '$gte' => 1 }).to_a
|
122
|
+
assert_equal 2, docs.size
|
123
|
+
assert docs.detect { |row| row['a'] == 1 }
|
124
|
+
assert docs.detect { |row| row['a'] == 2 }
|
125
|
+
|
126
|
+
# Find by advanced query (between)
|
127
|
+
docs = @@coll.find('a' => { '$gt' => 1, '$lt' => 3 }).to_a
|
128
|
+
assert_equal 1, docs.size
|
129
|
+
assert docs.detect { |row| row['a'] == 2 }
|
130
|
+
|
131
|
+
# Find by advanced query (in clause)
|
132
|
+
docs = @@coll.find('a' => {'$in' => [1,2]}).to_a
|
133
|
+
assert_equal 2, docs.size
|
134
|
+
assert docs.detect { |row| row['a'] == 1 }
|
135
|
+
assert docs.detect { |row| row['a'] == 2 }
|
136
|
+
|
137
|
+
# Find by advanced query (regexp)
|
138
|
+
docs = @@coll.find('a' => /[1|2]/).to_a
|
139
|
+
assert_equal 2, docs.size
|
140
|
+
assert docs.detect { |row| row['a'] == 1 }
|
141
|
+
assert docs.detect { |row| row['a'] == 2 }
|
142
|
+
end
|
143
|
+
|
144
|
+
def test_find_sorting
|
145
|
+
@@coll.clear
|
146
|
+
@@coll.insert('a' => 1, 'b' => 2)
|
147
|
+
@@coll.insert('a' => 2, 'b' => 1)
|
148
|
+
@@coll.insert('a' => 3, 'b' => 2)
|
149
|
+
@@coll.insert('a' => 4, 'b' => 1)
|
150
|
+
|
151
|
+
# Sorting (ascending)
|
152
|
+
docs = @@coll.find({'a' => { '$lt' => 10 }}, :sort => {'a' => 1}).to_a
|
153
|
+
assert_equal 4, docs.size
|
154
|
+
assert_equal 1, docs[0]['a']
|
155
|
+
assert_equal 2, docs[1]['a']
|
156
|
+
assert_equal 3, docs[2]['a']
|
157
|
+
assert_equal 4, docs[3]['a']
|
158
|
+
|
159
|
+
# Sorting (descending)
|
160
|
+
docs = @@coll.find({'a' => { '$lt' => 10 }}, :sort => {'a' => -1}).to_a
|
161
|
+
assert_equal 4, docs.size
|
162
|
+
assert_equal 4, docs[0]['a']
|
163
|
+
assert_equal 3, docs[1]['a']
|
164
|
+
assert_equal 2, docs[2]['a']
|
165
|
+
assert_equal 1, docs[3]['a']
|
166
|
+
|
167
|
+
# Sorting using array of names; assumes ascending order.
|
168
|
+
docs = @@coll.find({'a' => { '$lt' => 10 }}, :sort => ['a']).to_a
|
169
|
+
assert_equal 4, docs.size
|
170
|
+
assert_equal 1, docs[0]['a']
|
171
|
+
assert_equal 2, docs[1]['a']
|
172
|
+
assert_equal 3, docs[2]['a']
|
173
|
+
assert_equal 4, docs[3]['a']
|
174
|
+
|
175
|
+
# Sorting using single name; assumes ascending order.
|
176
|
+
docs = @@coll.find({'a' => { '$lt' => 10 }}, :sort => 'a').to_a
|
177
|
+
assert_equal 4, docs.size
|
178
|
+
assert_equal 1, docs[0]['a']
|
179
|
+
assert_equal 2, docs[1]['a']
|
180
|
+
assert_equal 3, docs[2]['a']
|
181
|
+
assert_equal 4, docs[3]['a']
|
182
|
+
|
183
|
+
docs = @@coll.find({'a' => { '$lt' => 10 }}, :sort => ['b', 'a']).to_a
|
184
|
+
assert_equal 4, docs.size
|
185
|
+
assert_equal 2, docs[0]['a']
|
186
|
+
assert_equal 4, docs[1]['a']
|
187
|
+
assert_equal 1, docs[2]['a']
|
188
|
+
assert_equal 3, docs[3]['a']
|
189
|
+
|
190
|
+
# Sorting using empty array; no order guarantee (Mongo bug #898) but
|
191
|
+
# should not blow up.
|
192
|
+
docs = @@coll.find({'a' => { '$lt' => 10 }}, :sort => []).to_a
|
193
|
+
assert_equal 4, docs.size
|
194
|
+
|
195
|
+
# Sorting using array of hashes; no order guarantee (Mongo bug #898) but
|
196
|
+
# should not blow up.
|
197
|
+
docs = @@coll.find({'a' => { '$lt' => 10 }}, :sort => [{'b' => 1}, {'a' => -1}]).to_a
|
198
|
+
assert_equal 4, docs.size
|
199
|
+
|
200
|
+
# Sorting using ordered hash. You can use an unordered one, but then the
|
201
|
+
# order of the keys won't be guaranteed thus your sort won't make sense.
|
202
|
+
oh = OrderedHash.new
|
203
|
+
oh['a'] = -1
|
204
|
+
docs = @@coll.find({'a' => { '$lt' => 10 }}, :sort => oh).to_a
|
205
|
+
assert_equal 4, docs.size
|
206
|
+
assert_equal 4, docs[0]['a']
|
207
|
+
assert_equal 3, docs[1]['a']
|
208
|
+
assert_equal 2, docs[2]['a']
|
209
|
+
assert_equal 1, docs[3]['a']
|
210
|
+
|
211
|
+
# TODO this will not pass due to known Mongo bug #898
|
212
|
+
# oh = OrderedHash.new
|
213
|
+
# oh['b'] = -1
|
214
|
+
# oh['a'] = 1
|
215
|
+
# docs = @@coll.find({'a' => { '$lt' => 10 }}, :sort => oh).to_a
|
216
|
+
# assert_equal 4, docs.size
|
217
|
+
# assert_equal 1, docs[0]['a']
|
218
|
+
# assert_equal 3, docs[1]['a']
|
219
|
+
# assert_equal 2, docs[2]['a']
|
220
|
+
# assert_equal 4, docs[3]['a']
|
221
|
+
end
|
222
|
+
|
223
|
+
def test_find_limits
|
224
|
+
@@coll.insert('b' => 2)
|
225
|
+
@@coll.insert('c' => 3)
|
226
|
+
@@coll.insert('d' => 4)
|
227
|
+
|
228
|
+
docs = @@coll.find({}, :limit => 1).to_a
|
229
|
+
assert_equal 1, docs.size
|
230
|
+
docs = @@coll.find({}, :limit => 2).to_a
|
231
|
+
assert_equal 2, docs.size
|
232
|
+
docs = @@coll.find({}, :limit => 3).to_a
|
233
|
+
assert_equal 3, docs.size
|
234
|
+
docs = @@coll.find({}, :limit => 4).to_a
|
235
|
+
assert_equal 4, docs.size
|
236
|
+
docs = @@coll.find({}).to_a
|
237
|
+
assert_equal 4, docs.size
|
238
|
+
docs = @@coll.find({}, :limit => 99).to_a
|
239
|
+
assert_equal 4, docs.size
|
240
|
+
end
|
241
|
+
|
242
|
+
def test_find_one_no_records
|
243
|
+
@@coll.clear
|
244
|
+
x = @@coll.find_one('a' => 1)
|
245
|
+
assert_nil x
|
246
|
+
end
|
247
|
+
|
248
|
+
def test_drop_collection
|
249
|
+
assert @@db.drop_collection(@@coll.name), "drop of collection #{@@coll.name} failed"
|
250
|
+
assert !@@db.collection_names.include?(@@coll.name)
|
251
|
+
end
|
252
|
+
|
253
|
+
def test_other_drop
|
254
|
+
assert @@db.collection_names.include?(@@coll.name)
|
255
|
+
@@coll.drop
|
256
|
+
assert !@@db.collection_names.include?(@@coll.name)
|
257
|
+
end
|
258
|
+
|
259
|
+
def test_collection_names
|
260
|
+
names = @@db.collection_names
|
261
|
+
assert names.length >= 1
|
262
|
+
assert names.include?(@@coll.name)
|
263
|
+
|
264
|
+
coll2 = @@db.collection('test2')
|
265
|
+
coll2.insert('a' => 1) # collection not created until it's used
|
266
|
+
names = @@db.collection_names
|
267
|
+
assert names.length >= 2
|
268
|
+
assert names.include?(@@coll.name)
|
269
|
+
assert names.include?('ruby-mongo-test.test2')
|
270
|
+
ensure
|
271
|
+
@@db.drop_collection('test2')
|
272
|
+
end
|
273
|
+
|
274
|
+
def test_collections_info
|
275
|
+
cursor = @@db.collections_info
|
276
|
+
rows = cursor.to_a
|
277
|
+
assert rows.length >= 1
|
278
|
+
row = rows.detect { |r| r['name'] == @@coll_full_name }
|
279
|
+
assert_not_nil row
|
280
|
+
end
|
281
|
+
|
282
|
+
def test_collection_options
|
283
|
+
@@db.drop_collection('foobar')
|
284
|
+
@@db.strict = true
|
285
|
+
|
286
|
+
begin
|
287
|
+
coll = @@db.create_collection('foobar', :capped => true, :size => 1024)
|
288
|
+
options = coll.options()
|
289
|
+
assert_equal 'foobar', options['create']
|
290
|
+
assert_equal true, options['capped']
|
291
|
+
assert_equal 1024, options['size']
|
292
|
+
rescue => ex
|
293
|
+
@@db.drop_collection('foobar')
|
294
|
+
fail "did not expect exception \"#{ex}\""
|
295
|
+
ensure
|
296
|
+
@@db.strict = false
|
297
|
+
end
|
298
|
+
end
|
299
|
+
|
300
|
+
def test_index_information
|
301
|
+
assert_equal @@coll.index_information.length, 1
|
302
|
+
|
303
|
+
name = @@db.create_index(@@coll.name, 'a')
|
304
|
+
info = @@db.index_information(@@coll.name)
|
305
|
+
assert_equal name, "a_1"
|
306
|
+
assert_equal @@coll.index_information, info
|
307
|
+
assert_equal 2, info.length
|
308
|
+
|
309
|
+
assert info.has_key?(name)
|
310
|
+
assert_equal info[name], [["a", ASCENDING]]
|
311
|
+
ensure
|
312
|
+
@@db.drop_index(@@coll.name, name)
|
313
|
+
end
|
314
|
+
|
315
|
+
def test_index_create_with_symbol
|
316
|
+
assert_equal @@coll.index_information.length, 1
|
317
|
+
|
318
|
+
name = @@db.create_index(@@coll.name, :a)
|
319
|
+
info = @@db.index_information(@@coll.name)
|
320
|
+
assert_equal name, "a_1"
|
321
|
+
assert_equal @@coll.index_information, info
|
322
|
+
assert_equal 2, info.length
|
323
|
+
|
324
|
+
assert info.has_key?(name)
|
325
|
+
assert_equal info[name], [["a", ASCENDING]]
|
326
|
+
ensure
|
327
|
+
@@db.drop_index(@@coll.name, name)
|
328
|
+
end
|
329
|
+
|
330
|
+
def test_multiple_index_cols
|
331
|
+
name = @@db.create_index(@@coll.name, [['a', DESCENDING], ['b', ASCENDING], ['c', DESCENDING]])
|
332
|
+
info = @@db.index_information(@@coll.name)
|
333
|
+
assert_equal 2, info.length
|
334
|
+
|
335
|
+
assert_equal name, 'a_-1_b_1_c_-1'
|
336
|
+
assert info.has_key?(name)
|
337
|
+
assert_equal [['a', DESCENDING], ['b', ASCENDING], ['c', DESCENDING]], info[name]
|
338
|
+
ensure
|
339
|
+
@@db.drop_index(@@coll.name, name)
|
340
|
+
end
|
341
|
+
|
342
|
+
def test_multiple_index_cols_with_symbols
|
343
|
+
name = @@db.create_index(@@coll.name, [[:a, DESCENDING], [:b, ASCENDING], [:c, DESCENDING]])
|
344
|
+
info = @@db.index_information(@@coll.name)
|
345
|
+
assert_equal 2, info.length
|
346
|
+
|
347
|
+
assert_equal name, 'a_-1_b_1_c_-1'
|
348
|
+
assert info.has_key?(name)
|
349
|
+
assert_equal [['a', DESCENDING], ['b', ASCENDING], ['c', DESCENDING]], info[name]
|
350
|
+
ensure
|
351
|
+
@@db.drop_index(@@coll.name, name)
|
352
|
+
end
|
353
|
+
|
354
|
+
def test_unique_index
|
355
|
+
@@db.drop_collection("blah")
|
356
|
+
test = @@db.collection("blah")
|
357
|
+
test.create_index("hello")
|
358
|
+
|
359
|
+
test.insert("hello" => "world")
|
360
|
+
test.insert("hello" => "mike")
|
361
|
+
test.insert("hello" => "world")
|
362
|
+
assert !@@db.error?
|
363
|
+
|
364
|
+
@@db.drop_collection("blah")
|
365
|
+
test = @@db.collection("blah")
|
366
|
+
test.create_index("hello", unique=true)
|
367
|
+
|
368
|
+
test.insert("hello" => "world")
|
369
|
+
test.insert("hello" => "mike")
|
370
|
+
test.insert("hello" => "world")
|
371
|
+
assert @@db.error?
|
372
|
+
end
|
373
|
+
|
374
|
+
def test_index_on_subfield
|
375
|
+
@@db.drop_collection("blah")
|
376
|
+
test = @@db.collection("blah")
|
377
|
+
|
378
|
+
test.insert("hello" => {"a" => 4, "b" => 5})
|
379
|
+
test.insert("hello" => {"a" => 7, "b" => 2})
|
380
|
+
test.insert("hello" => {"a" => 4, "b" => 10})
|
381
|
+
assert !@@db.error?
|
382
|
+
|
383
|
+
@@db.drop_collection("blah")
|
384
|
+
test = @@db.collection("blah")
|
385
|
+
test.create_index("hello.a", unique=true)
|
386
|
+
|
387
|
+
test.insert("hello" => {"a" => 4, "b" => 5})
|
388
|
+
test.insert("hello" => {"a" => 7, "b" => 2})
|
389
|
+
test.insert("hello" => {"a" => 4, "b" => 10})
|
390
|
+
assert @@db.error?
|
391
|
+
end
|
392
|
+
|
393
|
+
def test_array
|
394
|
+
@@coll << {'b' => [1, 2, 3]}
|
395
|
+
rows = @@coll.find({}, {:fields => ['b']}).to_a
|
396
|
+
assert_equal 1, rows.length
|
397
|
+
assert_equal [1, 2, 3], rows[0]['b']
|
398
|
+
end
|
399
|
+
|
400
|
+
def test_regex
|
401
|
+
regex = /foobar/i
|
402
|
+
@@coll << {'b' => regex}
|
403
|
+
rows = @@coll.find({}, {:fields => ['b']}).to_a
|
404
|
+
assert_equal 1, rows.length
|
405
|
+
assert_equal regex, rows[0]['b']
|
406
|
+
end
|
407
|
+
|
408
|
+
def test_non_oid_id
|
409
|
+
# Note: can't use Time.new because that will include fractional seconds,
|
410
|
+
# which Mongo does not store.
|
411
|
+
t = Time.at(1234567890)
|
412
|
+
@@coll << {'_id' => t}
|
413
|
+
rows = @@coll.find({'_id' => t}).to_a
|
414
|
+
assert_equal 1, rows.length
|
415
|
+
assert_equal t, rows[0]['_id']
|
416
|
+
end
|
417
|
+
|
418
|
+
def test_strict
|
419
|
+
assert !@@db.strict?
|
420
|
+
@@db.strict = true
|
421
|
+
assert @@db.strict?
|
422
|
+
ensure
|
423
|
+
@@db.strict = false
|
424
|
+
end
|
425
|
+
|
426
|
+
def test_strict_access_collection
|
427
|
+
@@db.strict = true
|
428
|
+
begin
|
429
|
+
@@db.collection('does-not-exist')
|
430
|
+
fail "expected exception"
|
431
|
+
rescue => ex
|
432
|
+
assert_equal "Collection does-not-exist doesn't exist. Currently in strict mode.", ex.to_s
|
433
|
+
ensure
|
434
|
+
@@db.strict = false
|
435
|
+
@@db.drop_collection('does-not-exist')
|
436
|
+
end
|
437
|
+
end
|
438
|
+
|
439
|
+
def test_strict_create_collection
|
440
|
+
@@db.drop_collection('foobar')
|
441
|
+
@@db.strict = true
|
442
|
+
|
443
|
+
begin
|
444
|
+
@@db.create_collection('foobar')
|
445
|
+
assert true
|
446
|
+
rescue => ex
|
447
|
+
fail "did not expect exception \"#{ex}\""
|
448
|
+
end
|
449
|
+
|
450
|
+
# Now the collection exists. This time we should see an exception.
|
451
|
+
begin
|
452
|
+
@@db.create_collection('foobar')
|
453
|
+
fail "expected exception"
|
454
|
+
rescue => ex
|
455
|
+
assert_equal "Collection foobar already exists. Currently in strict mode.", ex.to_s
|
456
|
+
ensure
|
457
|
+
@@db.strict = false
|
458
|
+
@@db.drop_collection('foobar')
|
459
|
+
end
|
460
|
+
|
461
|
+
# Now we're not in strict mode - should succeed
|
462
|
+
@@db.create_collection('foobar')
|
463
|
+
@@db.create_collection('foobar')
|
464
|
+
@@db.drop_collection('foobar')
|
465
|
+
end
|
466
|
+
|
467
|
+
def test_to_a
|
468
|
+
cursor = @@coll.find()
|
469
|
+
rows = cursor.to_a
|
470
|
+
|
471
|
+
assert_raise InvalidOperation do
|
472
|
+
cursor.to_a
|
473
|
+
end
|
474
|
+
|
475
|
+
cursor.each { |doc| fail "should be no docs in each now" }
|
476
|
+
end
|
477
|
+
|
478
|
+
def test_to_a_after_each
|
479
|
+
cursor = @@coll.find
|
480
|
+
cursor.each { |row| row }
|
481
|
+
assert_raise InvalidOperation do
|
482
|
+
cursor.to_a
|
483
|
+
end
|
484
|
+
end
|
485
|
+
|
486
|
+
def test_ismaster
|
487
|
+
assert @@db.master?
|
488
|
+
end
|
489
|
+
|
490
|
+
def test_master
|
491
|
+
assert_equal "#{@@db.host}:#{@@db.port}", @@db.master
|
492
|
+
end
|
493
|
+
|
494
|
+
def test_where
|
495
|
+
@@coll.insert('a' => 2)
|
496
|
+
@@coll.insert('a' => 3)
|
497
|
+
|
498
|
+
assert_equal 3, @@coll.count
|
499
|
+
assert_equal 1, @@coll.find('$where' => Code.new('this.a > 2')).count()
|
500
|
+
assert_equal 2, @@coll.find('$where' => Code.new('this.a > i', {'i' => 1})).count()
|
501
|
+
end
|
502
|
+
|
503
|
+
def test_eval
|
504
|
+
assert_equal 3, @@db.eval('function (x) {return x;}', 3)
|
505
|
+
|
506
|
+
assert_equal nil, @@db.eval("function (x) {db.test_eval.save({y:x});}", 5)
|
507
|
+
assert_equal 5, @@db.collection('test_eval').find_one['y']
|
508
|
+
|
509
|
+
assert_equal 5, @@db.eval("function (x, y) {return x + y;}", 2, 3)
|
510
|
+
assert_equal 5, @@db.eval("function () {return 5;}")
|
511
|
+
assert_equal 5, @@db.eval("2 + 3;")
|
512
|
+
|
513
|
+
assert_equal 5, @@db.eval(Code.new("2 + 3;"))
|
514
|
+
assert_equal 2, @@db.eval(Code.new("return i;", {"i" => 2}))
|
515
|
+
assert_equal 5, @@db.eval(Code.new("i + 3;", {"i" => 2}))
|
516
|
+
|
517
|
+
assert_raise OperationFailure do
|
518
|
+
@@db.eval("5 ++ 5;")
|
519
|
+
end
|
520
|
+
end
|
521
|
+
|
522
|
+
def test_hint
|
523
|
+
name = @@coll.create_index('a')
|
524
|
+
begin
|
525
|
+
assert_nil @@coll.hint
|
526
|
+
assert_equal 1, @@coll.find({'a' => 1}, :hint => 'a').to_a.size
|
527
|
+
assert_equal 1, @@coll.find({'a' => 1}, :hint => ['a']).to_a.size
|
528
|
+
assert_equal 1, @@coll.find({'a' => 1}, :hint => {'a' => 1}).to_a.size
|
529
|
+
|
530
|
+
@@coll.hint = 'a'
|
531
|
+
assert_equal({'a' => 1}, @@coll.hint)
|
532
|
+
assert_equal 1, @@coll.find('a' => 1).to_a.size
|
533
|
+
|
534
|
+
@@coll.hint = ['a']
|
535
|
+
assert_equal({'a' => 1}, @@coll.hint)
|
536
|
+
assert_equal 1, @@coll.find('a' => 1).to_a.size
|
537
|
+
|
538
|
+
@@coll.hint = {'a' => 1}
|
539
|
+
assert_equal({'a' => 1}, @@coll.hint)
|
540
|
+
assert_equal 1, @@coll.find('a' => 1).to_a.size
|
541
|
+
|
542
|
+
@@coll.hint = nil
|
543
|
+
assert_nil @@coll.hint
|
544
|
+
assert_equal 1, @@coll.find('a' => 1).to_a.size
|
545
|
+
ensure
|
546
|
+
@@coll.drop_index(name)
|
547
|
+
end
|
548
|
+
end
|
549
|
+
|
550
|
+
def test_hash_default_value_id
|
551
|
+
val = Hash.new(0)
|
552
|
+
val["x"] = 5
|
553
|
+
@@coll.insert val
|
554
|
+
id = @@coll.find_one("x" => 5)["_id"]
|
555
|
+
assert id != 0
|
556
|
+
end
|
557
|
+
|
558
|
+
def test_group
|
559
|
+
@@db.drop_collection("test")
|
560
|
+
test = @@db.collection("test")
|
561
|
+
|
562
|
+
assert_equal [], test.group([], {}, {"count" => 0}, "function (obj, prev) { prev.count++; }")
|
563
|
+
assert_equal [], test.group([], {}, {"count" => 0}, "function (obj, prev) { prev.count++; }", true)
|
564
|
+
|
565
|
+
test.insert("a" => 2)
|
566
|
+
test.insert("b" => 5)
|
567
|
+
test.insert("a" => 1)
|
568
|
+
|
569
|
+
assert_equal 3, test.group([], {}, {"count" => 0}, "function (obj, prev) { prev.count++; }")[0]["count"]
|
570
|
+
assert_equal 3, test.group([], {}, {"count" => 0}, "function (obj, prev) { prev.count++; }", true)[0]["count"]
|
571
|
+
assert_equal 1, test.group([], {"a" => {"$gt" => 1}}, {"count" => 0}, "function (obj, prev) { prev.count++; }")[0]["count"]
|
572
|
+
assert_equal 1, test.group([], {"a" => {"$gt" => 1}}, {"count" => 0}, "function (obj, prev) { prev.count++; }", true)[0]["count"]
|
573
|
+
|
574
|
+
test.insert("a" => 2, "b" => 3)
|
575
|
+
expected = [{"a" => 2, "count" => 2},
|
576
|
+
{"a" => nil, "count" => 1},
|
577
|
+
{"a" => 1, "count" => 1}]
|
578
|
+
assert_equal expected, test.group(["a"], {}, {"count" => 0}, "function (obj, prev) { prev.count++; }")
|
579
|
+
assert_equal expected, test.group(["a"], {}, {"count" => 0}, "function (obj, prev) { prev.count++; }", true)
|
580
|
+
|
581
|
+
assert_raise OperationFailure do
|
582
|
+
test.group([], {}, {}, "5 ++ 5")
|
583
|
+
end
|
584
|
+
assert_raise OperationFailure do
|
585
|
+
test.group([], {}, {}, "5 ++ 5", true)
|
586
|
+
end
|
587
|
+
end
|
588
|
+
|
589
|
+
def test_deref
|
590
|
+
@@coll.clear
|
591
|
+
|
592
|
+
assert_equal nil, @@db.dereference(DBRef.new("test", ObjectID.new))
|
593
|
+
@@coll.insert({"x" => "hello"})
|
594
|
+
key = @@coll.find_one()["_id"]
|
595
|
+
assert_equal "hello", @@db.dereference(DBRef.new("test", key))["x"]
|
596
|
+
|
597
|
+
assert_equal nil, @@db.dereference(DBRef.new("test", 4))
|
598
|
+
obj = {"_id" => 4}
|
599
|
+
@@coll.insert(obj)
|
600
|
+
assert_equal obj, @@db.dereference(DBRef.new("test", 4))
|
601
|
+
|
602
|
+
@@coll.clear
|
603
|
+
@@coll.insert({"x" => "hello"})
|
604
|
+
assert_equal nil, @@db.dereference(DBRef.new("test", nil))
|
605
|
+
end
|
606
|
+
|
607
|
+
def test_save
|
608
|
+
@@coll.clear
|
609
|
+
|
610
|
+
a = {"hello" => "world"}
|
611
|
+
|
612
|
+
id = @@coll.save(a)
|
613
|
+
assert_kind_of ObjectID, id
|
614
|
+
assert_equal 1, @@coll.count
|
615
|
+
|
616
|
+
assert_equal id, @@coll.save(a)
|
617
|
+
assert_equal 1, @@coll.count
|
618
|
+
|
619
|
+
assert_equal "world", @@coll.find_one()["hello"]
|
620
|
+
|
621
|
+
a["hello"] = "mike"
|
622
|
+
@@coll.save(a)
|
623
|
+
assert_equal 1, @@coll.count
|
624
|
+
|
625
|
+
assert_equal "mike", @@coll.find_one()["hello"]
|
626
|
+
|
627
|
+
@@coll.save({"hello" => "world"})
|
628
|
+
assert_equal 2, @@coll.count
|
629
|
+
end
|
630
|
+
|
631
|
+
def test_save_long
|
632
|
+
@@coll.clear
|
633
|
+
@@coll.insert("x" => 9223372036854775807)
|
634
|
+
assert_equal 9223372036854775807, @@coll.find_one()["x"]
|
635
|
+
end
|
636
|
+
|
637
|
+
def test_find_by_oid
|
638
|
+
@@coll.clear
|
639
|
+
|
640
|
+
@@coll.save("hello" => "mike")
|
641
|
+
id = @@coll.save("hello" => "world")
|
642
|
+
assert_kind_of ObjectID, id
|
643
|
+
|
644
|
+
assert_equal "world", @@coll.find_one(:_id => id)["hello"]
|
645
|
+
@@coll.find(:_id => id).to_a.each do |doc|
|
646
|
+
assert_equal "world", doc["hello"]
|
647
|
+
end
|
648
|
+
|
649
|
+
id = ObjectID.from_string(id.to_s)
|
650
|
+
assert_equal "world", @@coll.find_one(:_id => id)["hello"]
|
651
|
+
end
|
652
|
+
|
653
|
+
def test_save_with_object_that_has_id_but_does_not_actually_exist_in_collection
|
654
|
+
@@coll.clear
|
655
|
+
|
656
|
+
a = {'_id' => '1', 'hello' => 'world'}
|
657
|
+
@@coll.save(a)
|
658
|
+
assert_equal(1, @@coll.count)
|
659
|
+
assert_equal("world", @@coll.find_one()["hello"])
|
660
|
+
|
661
|
+
a["hello"] = "mike"
|
662
|
+
@@coll.save(a)
|
663
|
+
assert_equal(1, @@coll.count)
|
664
|
+
assert_equal("mike", @@coll.find_one()["hello"])
|
665
|
+
end
|
666
|
+
|
667
|
+
def test_invalid_key_names
|
668
|
+
@@coll.clear
|
669
|
+
|
670
|
+
@@coll.insert({"hello" => "world"})
|
671
|
+
@@coll.insert({"hello" => {"hello" => "world"}})
|
672
|
+
|
673
|
+
assert_raise InvalidName do
|
674
|
+
@@coll.insert({"$hello" => "world"})
|
675
|
+
end
|
676
|
+
assert_raise InvalidName do
|
677
|
+
@@coll.insert({"hello" => {"$hello" => "world"}})
|
678
|
+
end
|
679
|
+
|
680
|
+
@@coll.insert({"he$llo" => "world"})
|
681
|
+
@@coll.insert({"hello" => {"hell$o" => "world"}})
|
682
|
+
|
683
|
+
assert_raise InvalidName do
|
684
|
+
@@coll.insert({".hello" => "world"})
|
685
|
+
end
|
686
|
+
assert_raise InvalidName do
|
687
|
+
@@coll.insert({"hello" => {".hello" => "world"}})
|
688
|
+
end
|
689
|
+
assert_raise InvalidName do
|
690
|
+
@@coll.insert({"hello." => "world"})
|
691
|
+
end
|
692
|
+
assert_raise InvalidName do
|
693
|
+
@@coll.insert({"hello" => {"hello." => "world"}})
|
694
|
+
end
|
695
|
+
assert_raise InvalidName do
|
696
|
+
@@coll.insert({"hel.lo" => "world"})
|
697
|
+
end
|
698
|
+
assert_raise InvalidName do
|
699
|
+
@@coll.insert({"hello" => {"hel.lo" => "world"}})
|
700
|
+
end
|
701
|
+
end
|
702
|
+
|
703
|
+
def test_collection_names
|
704
|
+
assert_raise TypeError do
|
705
|
+
@@db.collection(5)
|
706
|
+
end
|
707
|
+
assert_raise InvalidName do
|
708
|
+
@@db.collection("")
|
709
|
+
end
|
710
|
+
assert_raise InvalidName do
|
711
|
+
@@db.collection("te$t")
|
712
|
+
end
|
713
|
+
assert_raise InvalidName do
|
714
|
+
@@db.collection(".test")
|
715
|
+
end
|
716
|
+
assert_raise InvalidName do
|
717
|
+
@@db.collection("test.")
|
718
|
+
end
|
719
|
+
assert_raise InvalidName do
|
720
|
+
@@db.collection("tes..t")
|
721
|
+
end
|
722
|
+
end
|
723
|
+
|
724
|
+
def test_rename_collection
|
725
|
+
@@db.drop_collection("foo")
|
726
|
+
@@db.drop_collection("bar")
|
727
|
+
a = @@db.collection("foo")
|
728
|
+
b = @@db.collection("bar")
|
729
|
+
|
730
|
+
assert_raise TypeError do
|
731
|
+
a.rename(5)
|
732
|
+
end
|
733
|
+
assert_raise InvalidName do
|
734
|
+
a.rename("")
|
735
|
+
end
|
736
|
+
assert_raise InvalidName do
|
737
|
+
a.rename("te$t")
|
738
|
+
end
|
739
|
+
assert_raise InvalidName do
|
740
|
+
a.rename(".test")
|
741
|
+
end
|
742
|
+
assert_raise InvalidName do
|
743
|
+
a.rename("test.")
|
744
|
+
end
|
745
|
+
assert_raise InvalidName do
|
746
|
+
a.rename("tes..t")
|
747
|
+
end
|
748
|
+
|
749
|
+
assert_equal 0, a.count()
|
750
|
+
assert_equal 0, b.count()
|
751
|
+
|
752
|
+
a.insert("x" => 1)
|
753
|
+
a.insert("x" => 2)
|
754
|
+
|
755
|
+
assert_equal 2, a.count()
|
756
|
+
|
757
|
+
a.rename("bar")
|
758
|
+
|
759
|
+
assert_equal 0, a.count()
|
760
|
+
assert_equal 2, b.count()
|
761
|
+
|
762
|
+
assert_equal 1, b.find().to_a()[0]["x"]
|
763
|
+
assert_equal 2, b.find().to_a()[1]["x"]
|
764
|
+
|
765
|
+
b.rename(:foo)
|
766
|
+
|
767
|
+
assert_equal 2, a.count()
|
768
|
+
assert_equal 0, b.count()
|
769
|
+
end
|
770
|
+
|
771
|
+
# doesn't really test functionality, just that the option is set correctly
|
772
|
+
def test_snapshot
|
773
|
+
@@db.collection("test").find({}, :snapshot => true).to_a
|
774
|
+
assert_raise RuntimeError do
|
775
|
+
@@db.collection("test").find({}, :snapshot => true, :sort => 'a').to_a
|
776
|
+
end
|
777
|
+
end
|
778
|
+
|
779
|
+
def test_encodings
|
780
|
+
if RUBY_VERSION >= '1.9'
|
781
|
+
ascii = "hello world"
|
782
|
+
utf8 = "hello world".encode("UTF-8")
|
783
|
+
iso8859 = "hello world".encode("ISO-8859-1")
|
784
|
+
|
785
|
+
assert_equal "US-ASCII", ascii.encoding.name
|
786
|
+
assert_equal "UTF-8", utf8.encoding.name
|
787
|
+
assert_equal "ISO-8859-1", iso8859.encoding.name
|
788
|
+
|
789
|
+
@@coll.clear
|
790
|
+
@@coll.save("ascii" => ascii, "utf8" => utf8, "iso8859" => iso8859)
|
791
|
+
doc = @@coll.find_one()
|
792
|
+
|
793
|
+
assert_equal "UTF-8", doc["ascii"].encoding.name
|
794
|
+
assert_equal "UTF-8", doc["utf8"].encoding.name
|
795
|
+
assert_equal "UTF-8", doc["iso8859"].encoding.name
|
796
|
+
end
|
797
|
+
end
|
798
|
+
end
|