kbaum-mongo 0.18.3p

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.
Files changed (72) hide show
  1. data/LICENSE.txt +202 -0
  2. data/README.rdoc +339 -0
  3. data/Rakefile +138 -0
  4. data/bin/bson_benchmark.rb +59 -0
  5. data/bin/fail_if_no_c.rb +11 -0
  6. data/examples/admin.rb +42 -0
  7. data/examples/capped.rb +22 -0
  8. data/examples/cursor.rb +48 -0
  9. data/examples/gridfs.rb +88 -0
  10. data/examples/index_test.rb +126 -0
  11. data/examples/info.rb +31 -0
  12. data/examples/queries.rb +70 -0
  13. data/examples/simple.rb +24 -0
  14. data/examples/strict.rb +35 -0
  15. data/examples/types.rb +36 -0
  16. data/lib/mongo/collection.rb +609 -0
  17. data/lib/mongo/connection.rb +672 -0
  18. data/lib/mongo/cursor.rb +403 -0
  19. data/lib/mongo/db.rb +555 -0
  20. data/lib/mongo/exceptions.rb +66 -0
  21. data/lib/mongo/gridfs/chunk.rb +91 -0
  22. data/lib/mongo/gridfs/grid.rb +79 -0
  23. data/lib/mongo/gridfs/grid_file_system.rb +101 -0
  24. data/lib/mongo/gridfs/grid_io.rb +338 -0
  25. data/lib/mongo/gridfs/grid_store.rb +580 -0
  26. data/lib/mongo/gridfs.rb +25 -0
  27. data/lib/mongo/types/binary.rb +52 -0
  28. data/lib/mongo/types/code.rb +36 -0
  29. data/lib/mongo/types/dbref.rb +40 -0
  30. data/lib/mongo/types/min_max_keys.rb +58 -0
  31. data/lib/mongo/types/objectid.rb +180 -0
  32. data/lib/mongo/types/regexp_of_holding.rb +45 -0
  33. data/lib/mongo/util/bson_c.rb +18 -0
  34. data/lib/mongo/util/bson_ruby.rb +606 -0
  35. data/lib/mongo/util/byte_buffer.rb +222 -0
  36. data/lib/mongo/util/conversions.rb +87 -0
  37. data/lib/mongo/util/ordered_hash.rb +140 -0
  38. data/lib/mongo/util/server_version.rb +69 -0
  39. data/lib/mongo/util/support.rb +26 -0
  40. data/lib/mongo.rb +63 -0
  41. data/mongo-ruby-driver.gemspec +28 -0
  42. data/test/auxillary/autoreconnect_test.rb +42 -0
  43. data/test/binary_test.rb +15 -0
  44. data/test/bson_test.rb +427 -0
  45. data/test/byte_buffer_test.rb +81 -0
  46. data/test/chunk_test.rb +82 -0
  47. data/test/collection_test.rb +515 -0
  48. data/test/connection_test.rb +160 -0
  49. data/test/conversions_test.rb +120 -0
  50. data/test/cursor_test.rb +379 -0
  51. data/test/db_api_test.rb +780 -0
  52. data/test/db_connection_test.rb +16 -0
  53. data/test/db_test.rb +272 -0
  54. data/test/grid_file_system_test.rb +210 -0
  55. data/test/grid_io_test.rb +78 -0
  56. data/test/grid_store_test.rb +334 -0
  57. data/test/grid_test.rb +87 -0
  58. data/test/objectid_test.rb +125 -0
  59. data/test/ordered_hash_test.rb +172 -0
  60. data/test/replica/count_test.rb +34 -0
  61. data/test/replica/insert_test.rb +50 -0
  62. data/test/replica/pooled_insert_test.rb +54 -0
  63. data/test/replica/query_test.rb +39 -0
  64. data/test/slave_connection_test.rb +36 -0
  65. data/test/test_helper.rb +42 -0
  66. data/test/threading/test_threading_large_pool.rb +90 -0
  67. data/test/threading_test.rb +87 -0
  68. data/test/unit/collection_test.rb +61 -0
  69. data/test/unit/connection_test.rb +117 -0
  70. data/test/unit/cursor_test.rb +93 -0
  71. data/test/unit/db_test.rb +98 -0
  72. metadata +127 -0
@@ -0,0 +1,780 @@
1
+ require 'test/test_helper'
2
+
3
+ # NOTE: assumes Mongo is running
4
+ class DBAPITest < Test::Unit::TestCase
5
+ include Mongo
6
+
7
+ @@conn = Connection.new(ENV['MONGO_RUBY_DRIVER_HOST'] || 'localhost',
8
+ ENV['MONGO_RUBY_DRIVER_PORT'] || Connection::DEFAULT_PORT)
9
+ @@db = @@conn.db("ruby-mongo-test")
10
+ @@coll = @@db.collection('test')
11
+ @@version = @@conn.server_version
12
+
13
+ def setup
14
+ @@coll.remove
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.remove
22
+ @@db.error
23
+ end
24
+
25
+ def test_clear
26
+ assert_equal 1, @@coll.count
27
+ @@coll.remove
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.remove
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', 'asc'], ['a', 'asc']]).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 should not blow up.
191
+ docs = @@coll.find({'a' => { '$lt' => 10 }}, :sort => []).to_a
192
+ assert_equal 4, docs.size
193
+
194
+ # Sorting using ordered hash. You can use an unordered one, but then the
195
+ # order of the keys won't be guaranteed thus your sort won't make sense.
196
+ oh = OrderedHash.new
197
+ oh['a'] = -1
198
+ assert_raise InvalidSortValueError do
199
+ docs = @@coll.find({'a' => { '$lt' => 10 }}, :sort => oh).to_a
200
+ end
201
+ end
202
+
203
+ def test_find_limits
204
+ @@coll.insert('b' => 2)
205
+ @@coll.insert('c' => 3)
206
+ @@coll.insert('d' => 4)
207
+
208
+ docs = @@coll.find({}, :limit => 1).to_a
209
+ assert_equal 1, docs.size
210
+ docs = @@coll.find({}, :limit => 2).to_a
211
+ assert_equal 2, docs.size
212
+ docs = @@coll.find({}, :limit => 3).to_a
213
+ assert_equal 3, docs.size
214
+ docs = @@coll.find({}, :limit => 4).to_a
215
+ assert_equal 4, docs.size
216
+ docs = @@coll.find({}).to_a
217
+ assert_equal 4, docs.size
218
+ docs = @@coll.find({}, :limit => 99).to_a
219
+ assert_equal 4, docs.size
220
+ end
221
+
222
+ def test_find_one_no_records
223
+ @@coll.remove
224
+ x = @@coll.find_one('a' => 1)
225
+ assert_nil x
226
+ end
227
+
228
+ def test_drop_collection
229
+ assert @@db.drop_collection(@@coll.name), "drop of collection #{@@coll.name} failed"
230
+ assert !@@db.collection_names.include?(@@coll.name)
231
+ end
232
+
233
+ def test_other_drop
234
+ assert @@db.collection_names.include?(@@coll.name)
235
+ @@coll.drop
236
+ assert !@@db.collection_names.include?(@@coll.name)
237
+ end
238
+
239
+ def test_collection_names
240
+ names = @@db.collection_names
241
+ assert names.length >= 1
242
+ assert names.include?(@@coll.name)
243
+
244
+ coll2 = @@db.collection('test2')
245
+ coll2.insert('a' => 1) # collection not created until it's used
246
+ names = @@db.collection_names
247
+ assert names.length >= 2
248
+ assert names.include?(@@coll.name)
249
+ assert names.include?('ruby-mongo-test.test2')
250
+ ensure
251
+ @@db.drop_collection('test2')
252
+ end
253
+
254
+ def test_collections_info
255
+ cursor = @@db.collections_info
256
+ rows = cursor.to_a
257
+ assert rows.length >= 1
258
+ row = rows.detect { |r| r['name'] == @@coll_full_name }
259
+ assert_not_nil row
260
+ end
261
+
262
+ def test_collection_options
263
+ @@db.drop_collection('foobar')
264
+ @@db.strict = true
265
+
266
+ begin
267
+ coll = @@db.create_collection('foobar', :capped => true, :size => 1024)
268
+ options = coll.options()
269
+ assert_equal 'foobar', options['create']
270
+ assert_equal true, options['capped']
271
+ assert_equal 1024, options['size']
272
+ rescue => ex
273
+ @@db.drop_collection('foobar')
274
+ fail "did not expect exception \"#{ex}\""
275
+ ensure
276
+ @@db.strict = false
277
+ end
278
+ end
279
+
280
+ def test_index_information
281
+ assert_equal @@coll.index_information.length, 1
282
+
283
+ name = @@db.create_index(@@coll.name, 'a')
284
+ info = @@db.index_information(@@coll.name)
285
+ assert_equal name, "a_1"
286
+ assert_equal @@coll.index_information, info
287
+ assert_equal 2, info.length
288
+
289
+ assert info.has_key?(name)
290
+ assert_equal info[name], [["a", ASCENDING]]
291
+ ensure
292
+ @@db.drop_index(@@coll.name, name)
293
+ end
294
+
295
+ def test_index_create_with_symbol
296
+ assert_equal @@coll.index_information.length, 1
297
+
298
+ name = @@db.create_index(@@coll.name, :a)
299
+ info = @@db.index_information(@@coll.name)
300
+ assert_equal name, "a_1"
301
+ assert_equal @@coll.index_information, info
302
+ assert_equal 2, info.length
303
+
304
+ assert info.has_key?(name)
305
+ assert_equal info[name], [["a", ASCENDING]]
306
+ ensure
307
+ @@db.drop_index(@@coll.name, name)
308
+ end
309
+
310
+ def test_multiple_index_cols
311
+ name = @@db.create_index(@@coll.name, [['a', DESCENDING], ['b', ASCENDING], ['c', DESCENDING]])
312
+ info = @@db.index_information(@@coll.name)
313
+ assert_equal 2, info.length
314
+
315
+ assert_equal name, 'a_-1_b_1_c_-1'
316
+ assert info.has_key?(name)
317
+ assert_equal [['a', DESCENDING], ['b', ASCENDING], ['c', DESCENDING]], info[name]
318
+ ensure
319
+ @@db.drop_index(@@coll.name, name)
320
+ end
321
+
322
+ def test_multiple_index_cols_with_symbols
323
+ name = @@db.create_index(@@coll.name, [[:a, DESCENDING], [:b, ASCENDING], [:c, DESCENDING]])
324
+ info = @@db.index_information(@@coll.name)
325
+ assert_equal 2, info.length
326
+
327
+ assert_equal name, 'a_-1_b_1_c_-1'
328
+ assert info.has_key?(name)
329
+ assert_equal [['a', DESCENDING], ['b', ASCENDING], ['c', DESCENDING]], info[name]
330
+ ensure
331
+ @@db.drop_index(@@coll.name, name)
332
+ end
333
+
334
+ def test_unique_index
335
+ @@db.drop_collection("blah")
336
+ test = @@db.collection("blah")
337
+ test.create_index("hello")
338
+
339
+ test.insert("hello" => "world")
340
+ test.insert("hello" => "mike")
341
+ test.insert("hello" => "world")
342
+ assert !@@db.error?
343
+
344
+ @@db.drop_collection("blah")
345
+ test = @@db.collection("blah")
346
+ test.create_index("hello", unique=true)
347
+
348
+ test.insert("hello" => "world")
349
+ test.insert("hello" => "mike")
350
+ test.insert("hello" => "world")
351
+ assert @@db.error?
352
+ end
353
+
354
+ def test_index_on_subfield
355
+ @@db.drop_collection("blah")
356
+ test = @@db.collection("blah")
357
+
358
+ test.insert("hello" => {"a" => 4, "b" => 5})
359
+ test.insert("hello" => {"a" => 7, "b" => 2})
360
+ test.insert("hello" => {"a" => 4, "b" => 10})
361
+ assert !@@db.error?
362
+
363
+ @@db.drop_collection("blah")
364
+ test = @@db.collection("blah")
365
+ test.create_index("hello.a", unique=true)
366
+
367
+ test.insert("hello" => {"a" => 4, "b" => 5})
368
+ test.insert("hello" => {"a" => 7, "b" => 2})
369
+ test.insert("hello" => {"a" => 4, "b" => 10})
370
+ assert @@db.error?
371
+ end
372
+
373
+ def test_array
374
+ @@coll << {'b' => [1, 2, 3]}
375
+ rows = @@coll.find({}, {:fields => ['b']}).to_a
376
+ if @@version < "1.1.3"
377
+ assert_equal 1, rows.length
378
+ assert_equal [1, 2, 3], rows[0]['b']
379
+ else
380
+ assert_equal 2, rows.length
381
+ assert_equal [1, 2, 3], rows[1]['b']
382
+ end
383
+ end
384
+
385
+ def test_regex
386
+ regex = /foobar/i
387
+ @@coll << {'b' => regex}
388
+ rows = @@coll.find({}, {:fields => ['b']}).to_a
389
+ if @@version < "1.1.3"
390
+ assert_equal 1, rows.length
391
+ assert_equal regex, rows[0]['b']
392
+ else
393
+ assert_equal 2, rows.length
394
+ assert_equal regex, rows[1]['b']
395
+ end
396
+ end
397
+
398
+ def test_non_oid_id
399
+ # Note: can't use Time.new because that will include fractional seconds,
400
+ # which Mongo does not store.
401
+ t = Time.at(1234567890)
402
+ @@coll << {'_id' => t}
403
+ rows = @@coll.find({'_id' => t}).to_a
404
+ assert_equal 1, rows.length
405
+ assert_equal t, rows[0]['_id']
406
+ end
407
+
408
+ def test_strict
409
+ assert !@@db.strict?
410
+ @@db.strict = true
411
+ assert @@db.strict?
412
+ ensure
413
+ @@db.strict = false
414
+ end
415
+
416
+ def test_strict_access_collection
417
+ @@db.strict = true
418
+ begin
419
+ @@db.collection('does-not-exist')
420
+ fail "expected exception"
421
+ rescue => ex
422
+ assert_equal MongoDBError, ex.class
423
+ assert_equal "Collection does-not-exist doesn't exist. Currently in strict mode.", ex.to_s
424
+ ensure
425
+ @@db.strict = false
426
+ @@db.drop_collection('does-not-exist')
427
+ end
428
+ end
429
+
430
+ def test_strict_create_collection
431
+ @@db.drop_collection('foobar')
432
+ @@db.strict = true
433
+
434
+ begin
435
+ @@db.create_collection('foobar')
436
+ assert true
437
+ rescue => ex
438
+ fail "did not expect exception \"#{ex}\""
439
+ end
440
+
441
+ # Now the collection exists. This time we should see an exception.
442
+ assert_raise MongoDBError do
443
+ @@db.create_collection('foobar')
444
+ end
445
+ @@db.strict = false
446
+ @@db.drop_collection('foobar')
447
+
448
+ # Now we're not in strict mode - should succeed
449
+ @@db.create_collection('foobar')
450
+ @@db.create_collection('foobar')
451
+ @@db.drop_collection('foobar')
452
+ end
453
+
454
+ def test_to_a
455
+ cursor = @@coll.find()
456
+ rows = cursor.to_a
457
+
458
+ assert_raise InvalidOperation do
459
+ cursor.to_a
460
+ end
461
+
462
+ cursor.each { |doc| fail "should be no docs in each now" }
463
+ end
464
+
465
+ def test_to_a_after_each
466
+ cursor = @@coll.find
467
+ cursor.each { |row| row }
468
+ assert_raise InvalidOperation do
469
+ cursor.to_a
470
+ end
471
+ end
472
+
473
+ def test_where
474
+ @@coll.insert('a' => 2)
475
+ @@coll.insert('a' => 3)
476
+
477
+ assert_equal 3, @@coll.count
478
+ assert_equal 1, @@coll.find('$where' => Code.new('this.a > 2')).count()
479
+ assert_equal 2, @@coll.find('$where' => Code.new('this.a > i', {'i' => 1})).count()
480
+ end
481
+
482
+ def test_eval
483
+ assert_equal 3, @@db.eval('function (x) {return x;}', 3)
484
+
485
+ assert_equal nil, @@db.eval("function (x) {db.test_eval.save({y:x});}", 5)
486
+ assert_equal 5, @@db.collection('test_eval').find_one['y']
487
+
488
+ assert_equal 5, @@db.eval("function (x, y) {return x + y;}", 2, 3)
489
+ assert_equal 5, @@db.eval("function () {return 5;}")
490
+ assert_equal 5, @@db.eval("2 + 3;")
491
+
492
+ assert_equal 5, @@db.eval(Code.new("2 + 3;"))
493
+ assert_equal 2, @@db.eval(Code.new("return i;", {"i" => 2}))
494
+ assert_equal 5, @@db.eval(Code.new("i + 3;", {"i" => 2}))
495
+
496
+ assert_raise OperationFailure do
497
+ @@db.eval("5 ++ 5;")
498
+ end
499
+ end
500
+
501
+ def test_hint
502
+ name = @@coll.create_index('a')
503
+ begin
504
+ assert_nil @@coll.hint
505
+ assert_equal 1, @@coll.find({'a' => 1}, :hint => 'a').to_a.size
506
+ assert_equal 1, @@coll.find({'a' => 1}, :hint => ['a']).to_a.size
507
+ assert_equal 1, @@coll.find({'a' => 1}, :hint => {'a' => 1}).to_a.size
508
+
509
+ @@coll.hint = 'a'
510
+ assert_equal({'a' => 1}, @@coll.hint)
511
+ assert_equal 1, @@coll.find('a' => 1).to_a.size
512
+
513
+ @@coll.hint = ['a']
514
+ assert_equal({'a' => 1}, @@coll.hint)
515
+ assert_equal 1, @@coll.find('a' => 1).to_a.size
516
+
517
+ @@coll.hint = {'a' => 1}
518
+ assert_equal({'a' => 1}, @@coll.hint)
519
+ assert_equal 1, @@coll.find('a' => 1).to_a.size
520
+
521
+ @@coll.hint = nil
522
+ assert_nil @@coll.hint
523
+ assert_equal 1, @@coll.find('a' => 1).to_a.size
524
+ ensure
525
+ @@coll.drop_index(name)
526
+ end
527
+ end
528
+
529
+ def test_hash_default_value_id
530
+ val = Hash.new(0)
531
+ val["x"] = 5
532
+ @@coll.insert val
533
+ id = @@coll.find_one("x" => 5)["_id"]
534
+ assert id != 0
535
+ end
536
+
537
+ def test_group
538
+ @@db.drop_collection("test")
539
+ test = @@db.collection("test")
540
+
541
+ assert_equal [], test.group([], {}, {"count" => 0}, "function (obj, prev) { prev.count++; }")
542
+ assert_equal [], test.group([], {}, {"count" => 0}, "function (obj, prev) { prev.count++; }")
543
+
544
+ test.insert("a" => 2)
545
+ test.insert("b" => 5)
546
+ test.insert("a" => 1)
547
+
548
+ assert_equal 3, test.group([], {}, {"count" => 0}, "function (obj, prev) { prev.count++; }")[0]["count"]
549
+ assert_equal 3, test.group([], {}, {"count" => 0}, "function (obj, prev) { prev.count++; }")[0]["count"]
550
+ assert_equal 1, test.group([], {"a" => {"$gt" => 1}}, {"count" => 0}, "function (obj, prev) { prev.count++; }")[0]["count"]
551
+ assert_equal 1, test.group([], {"a" => {"$gt" => 1}}, {"count" => 0}, "function (obj, prev) { prev.count++; }")[0]["count"]
552
+
553
+ finalize = "function (obj) { obj.f = obj.count - 1; }"
554
+ assert_equal 2, test.group([], {}, {"count" => 0}, "function (obj, prev) { prev.count++; }", true, finalize)[0]["f"]
555
+
556
+ test.insert("a" => 2, "b" => 3)
557
+ expected = [{"a" => 2, "count" => 2},
558
+ {"a" => nil, "count" => 1},
559
+ {"a" => 1, "count" => 1}]
560
+ assert_equal expected, test.group(["a"], {}, {"count" => 0}, "function (obj, prev) { prev.count++; }")
561
+ assert_equal expected, test.group(["a"], {}, {"count" => 0}, "function (obj, prev) { prev.count++; }", true)
562
+
563
+ assert_raise OperationFailure do
564
+ test.group([], {}, {}, "5 ++ 5")
565
+ end
566
+ assert_raise OperationFailure do
567
+ test.group([], {}, {}, "5 ++ 5", true)
568
+ end
569
+ end
570
+
571
+ def test_deref
572
+ @@coll.remove
573
+
574
+ assert_equal nil, @@db.dereference(DBRef.new("test", ObjectID.new))
575
+ @@coll.insert({"x" => "hello"})
576
+ key = @@coll.find_one()["_id"]
577
+ assert_equal "hello", @@db.dereference(DBRef.new("test", key))["x"]
578
+
579
+ assert_equal nil, @@db.dereference(DBRef.new("test", 4))
580
+ obj = {"_id" => 4}
581
+ @@coll.insert(obj)
582
+ assert_equal obj, @@db.dereference(DBRef.new("test", 4))
583
+
584
+ @@coll.remove
585
+ @@coll.insert({"x" => "hello"})
586
+ assert_equal nil, @@db.dereference(DBRef.new("test", nil))
587
+ end
588
+
589
+ def test_save
590
+ @@coll.remove
591
+
592
+ a = {"hello" => "world"}
593
+
594
+ id = @@coll.save(a)
595
+ assert_kind_of ObjectID, id
596
+ assert_equal 1, @@coll.count
597
+
598
+ assert_equal id, @@coll.save(a)
599
+ assert_equal 1, @@coll.count
600
+
601
+ assert_equal "world", @@coll.find_one()["hello"]
602
+
603
+ a["hello"] = "mike"
604
+ @@coll.save(a)
605
+ assert_equal 1, @@coll.count
606
+
607
+ assert_equal "mike", @@coll.find_one()["hello"]
608
+
609
+ @@coll.save({"hello" => "world"})
610
+ assert_equal 2, @@coll.count
611
+ end
612
+
613
+ def test_save_long
614
+ @@coll.remove
615
+ @@coll.insert("x" => 9223372036854775807)
616
+ assert_equal 9223372036854775807, @@coll.find_one()["x"]
617
+ end
618
+
619
+ def test_find_by_oid
620
+ @@coll.remove
621
+
622
+ @@coll.save("hello" => "mike")
623
+ id = @@coll.save("hello" => "world")
624
+ assert_kind_of ObjectID, id
625
+
626
+ assert_equal "world", @@coll.find_one(:_id => id)["hello"]
627
+ @@coll.find(:_id => id).to_a.each do |doc|
628
+ assert_equal "world", doc["hello"]
629
+ end
630
+
631
+ id = ObjectID.from_string(id.to_s)
632
+ assert_equal "world", @@coll.find_one(:_id => id)["hello"]
633
+ end
634
+
635
+ def test_save_with_object_that_has_id_but_does_not_actually_exist_in_collection
636
+ @@coll.remove
637
+
638
+ a = {'_id' => '1', 'hello' => 'world'}
639
+ @@coll.save(a)
640
+ assert_equal(1, @@coll.count)
641
+ assert_equal("world", @@coll.find_one()["hello"])
642
+
643
+ a["hello"] = "mike"
644
+ @@coll.save(a)
645
+ assert_equal(1, @@coll.count)
646
+ assert_equal("mike", @@coll.find_one()["hello"])
647
+ end
648
+
649
+ def test_invalid_key_names
650
+ @@coll.remove
651
+
652
+ @@coll.insert({"hello" => "world"})
653
+ @@coll.insert({"hello" => {"hello" => "world"}})
654
+
655
+ assert_raise InvalidName do
656
+ @@coll.insert({"$hello" => "world"})
657
+ end
658
+ assert_raise InvalidName do
659
+ @@coll.insert({"hello" => {"$hello" => "world"}})
660
+ end
661
+
662
+ @@coll.insert({"he$llo" => "world"})
663
+ @@coll.insert({"hello" => {"hell$o" => "world"}})
664
+
665
+ assert_raise InvalidName do
666
+ @@coll.insert({".hello" => "world"})
667
+ end
668
+ assert_raise InvalidName do
669
+ @@coll.insert({"hello" => {".hello" => "world"}})
670
+ end
671
+ assert_raise InvalidName do
672
+ @@coll.insert({"hello." => "world"})
673
+ end
674
+ assert_raise InvalidName do
675
+ @@coll.insert({"hello" => {"hello." => "world"}})
676
+ end
677
+ assert_raise InvalidName do
678
+ @@coll.insert({"hel.lo" => "world"})
679
+ end
680
+ assert_raise InvalidName do
681
+ @@coll.insert({"hello" => {"hel.lo" => "world"}})
682
+ end
683
+ end
684
+
685
+ def test_collection_names
686
+ assert_raise TypeError do
687
+ @@db.collection(5)
688
+ end
689
+ assert_raise InvalidName do
690
+ @@db.collection("")
691
+ end
692
+ assert_raise InvalidName do
693
+ @@db.collection("te$t")
694
+ end
695
+ assert_raise InvalidName do
696
+ @@db.collection(".test")
697
+ end
698
+ assert_raise InvalidName do
699
+ @@db.collection("test.")
700
+ end
701
+ assert_raise InvalidName do
702
+ @@db.collection("tes..t")
703
+ end
704
+ end
705
+
706
+ def test_rename_collection
707
+ @@db.drop_collection("foo")
708
+ @@db.drop_collection("bar")
709
+ a = @@db.collection("foo")
710
+ b = @@db.collection("bar")
711
+
712
+ assert_raise TypeError do
713
+ a.rename(5)
714
+ end
715
+ assert_raise InvalidName do
716
+ a.rename("")
717
+ end
718
+ assert_raise InvalidName do
719
+ a.rename("te$t")
720
+ end
721
+ assert_raise InvalidName do
722
+ a.rename(".test")
723
+ end
724
+ assert_raise InvalidName do
725
+ a.rename("test.")
726
+ end
727
+ assert_raise InvalidName do
728
+ a.rename("tes..t")
729
+ end
730
+
731
+ assert_equal 0, a.count()
732
+ assert_equal 0, b.count()
733
+
734
+ a.insert("x" => 1)
735
+ a.insert("x" => 2)
736
+
737
+ assert_equal 2, a.count()
738
+
739
+ a.rename("bar")
740
+
741
+ assert_equal 0, a.count()
742
+ assert_equal 2, b.count()
743
+
744
+ assert_equal 1, b.find().to_a()[0]["x"]
745
+ assert_equal 2, b.find().to_a()[1]["x"]
746
+
747
+ b.rename(:foo)
748
+
749
+ assert_equal 2, a.count()
750
+ assert_equal 0, b.count()
751
+ end
752
+
753
+ # doesn't really test functionality, just that the option is set correctly
754
+ def test_snapshot
755
+ @@db.collection("test").find({}, :snapshot => true).to_a
756
+ assert_raise OperationFailure do
757
+ @@db.collection("test").find({}, :snapshot => true, :sort => 'a').to_a
758
+ end
759
+ end
760
+
761
+ def test_encodings
762
+ if RUBY_VERSION >= '1.9'
763
+ ascii = "hello world"
764
+ utf8 = "hello world".encode("UTF-8")
765
+ iso8859 = "hello world".encode("ISO-8859-1")
766
+
767
+ assert_equal "US-ASCII", ascii.encoding.name
768
+ assert_equal "UTF-8", utf8.encoding.name
769
+ assert_equal "ISO-8859-1", iso8859.encoding.name
770
+
771
+ @@coll.remove
772
+ @@coll.save("ascii" => ascii, "utf8" => utf8, "iso8859" => iso8859)
773
+ doc = @@coll.find_one()
774
+
775
+ assert_equal "UTF-8", doc["ascii"].encoding.name
776
+ assert_equal "UTF-8", doc["utf8"].encoding.name
777
+ assert_equal "UTF-8", doc["iso8859"].encoding.name
778
+ end
779
+ end
780
+ end