mongo 0.1.0 → 0.15

Sign up to get free protection for your applications and to get access to all the features.
Files changed (89) hide show
  1. data/README.rdoc +268 -71
  2. data/Rakefile +27 -62
  3. data/bin/bson_benchmark.rb +59 -0
  4. data/bin/mongo_console +3 -3
  5. data/bin/run_test_script +19 -0
  6. data/bin/standard_benchmark +109 -0
  7. data/examples/admin.rb +41 -0
  8. data/examples/benchmarks.rb +42 -0
  9. data/examples/blog.rb +76 -0
  10. data/examples/capped.rb +23 -0
  11. data/examples/cursor.rb +47 -0
  12. data/examples/gridfs.rb +87 -0
  13. data/examples/index_test.rb +125 -0
  14. data/examples/info.rb +30 -0
  15. data/examples/queries.rb +69 -0
  16. data/examples/simple.rb +23 -0
  17. data/examples/strict.rb +34 -0
  18. data/examples/types.rb +35 -0
  19. data/lib/mongo.rb +9 -2
  20. data/lib/mongo/admin.rb +65 -68
  21. data/lib/mongo/collection.rb +379 -117
  22. data/lib/mongo/connection.rb +151 -0
  23. data/lib/mongo/cursor.rb +271 -216
  24. data/lib/mongo/db.rb +500 -315
  25. data/lib/mongo/errors.rb +26 -0
  26. data/lib/mongo/gridfs.rb +16 -0
  27. data/lib/mongo/gridfs/chunk.rb +92 -0
  28. data/lib/mongo/gridfs/grid_store.rb +464 -0
  29. data/lib/mongo/message.rb +16 -0
  30. data/lib/mongo/message/get_more_message.rb +24 -13
  31. data/lib/mongo/message/insert_message.rb +29 -11
  32. data/lib/mongo/message/kill_cursors_message.rb +23 -12
  33. data/lib/mongo/message/message.rb +74 -62
  34. data/lib/mongo/message/message_header.rb +35 -24
  35. data/lib/mongo/message/msg_message.rb +21 -9
  36. data/lib/mongo/message/opcodes.rb +26 -15
  37. data/lib/mongo/message/query_message.rb +63 -43
  38. data/lib/mongo/message/remove_message.rb +29 -12
  39. data/lib/mongo/message/update_message.rb +30 -13
  40. data/lib/mongo/query.rb +97 -89
  41. data/lib/mongo/types/binary.rb +25 -21
  42. data/lib/mongo/types/code.rb +30 -0
  43. data/lib/mongo/types/dbref.rb +19 -23
  44. data/lib/mongo/types/objectid.rb +130 -116
  45. data/lib/mongo/types/regexp_of_holding.rb +27 -31
  46. data/lib/mongo/util/bson.rb +273 -160
  47. data/lib/mongo/util/byte_buffer.rb +32 -28
  48. data/lib/mongo/util/ordered_hash.rb +88 -42
  49. data/lib/mongo/util/xml_to_ruby.rb +18 -15
  50. data/mongo-ruby-driver.gemspec +103 -0
  51. data/test/mongo-qa/_common.rb +8 -0
  52. data/test/mongo-qa/admin +26 -0
  53. data/test/mongo-qa/capped +22 -0
  54. data/test/mongo-qa/count1 +18 -0
  55. data/test/mongo-qa/dbs +22 -0
  56. data/test/mongo-qa/find +10 -0
  57. data/test/mongo-qa/find1 +15 -0
  58. data/test/mongo-qa/gridfs_in +16 -0
  59. data/test/mongo-qa/gridfs_out +17 -0
  60. data/test/mongo-qa/indices +49 -0
  61. data/test/mongo-qa/remove +25 -0
  62. data/test/mongo-qa/stress1 +35 -0
  63. data/test/mongo-qa/test1 +11 -0
  64. data/test/mongo-qa/update +18 -0
  65. data/{tests → test}/test_admin.rb +25 -16
  66. data/test/test_bson.rb +268 -0
  67. data/{tests → test}/test_byte_buffer.rb +0 -0
  68. data/test/test_chunk.rb +84 -0
  69. data/test/test_collection.rb +282 -0
  70. data/test/test_connection.rb +101 -0
  71. data/test/test_cursor.rb +321 -0
  72. data/test/test_db.rb +196 -0
  73. data/test/test_db_api.rb +798 -0
  74. data/{tests → test}/test_db_connection.rb +4 -3
  75. data/test/test_grid_store.rb +284 -0
  76. data/{tests → test}/test_message.rb +1 -1
  77. data/test/test_objectid.rb +105 -0
  78. data/{tests → test}/test_ordered_hash.rb +55 -0
  79. data/{tests → test}/test_round_trip.rb +13 -9
  80. data/test/test_threading.rb +37 -0
  81. metadata +74 -32
  82. data/bin/validate +0 -51
  83. data/lib/mongo/mongo.rb +0 -74
  84. data/lib/mongo/types/undefined.rb +0 -31
  85. data/tests/test_bson.rb +0 -135
  86. data/tests/test_cursor.rb +0 -66
  87. data/tests/test_db.rb +0 -51
  88. data/tests/test_db_api.rb +0 -349
  89. data/tests/test_objectid.rb +0 -88
@@ -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