mongo-find_replace 0.18.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (68) hide show
  1. data/LICENSE.txt +202 -0
  2. data/README.rdoc +358 -0
  3. data/Rakefile +133 -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.rb +61 -0
  17. data/lib/mongo/admin.rb +95 -0
  18. data/lib/mongo/collection.rb +664 -0
  19. data/lib/mongo/connection.rb +555 -0
  20. data/lib/mongo/cursor.rb +393 -0
  21. data/lib/mongo/db.rb +527 -0
  22. data/lib/mongo/exceptions.rb +60 -0
  23. data/lib/mongo/gridfs.rb +22 -0
  24. data/lib/mongo/gridfs/chunk.rb +90 -0
  25. data/lib/mongo/gridfs/grid_store.rb +555 -0
  26. data/lib/mongo/types/binary.rb +48 -0
  27. data/lib/mongo/types/code.rb +36 -0
  28. data/lib/mongo/types/dbref.rb +38 -0
  29. data/lib/mongo/types/min_max_keys.rb +58 -0
  30. data/lib/mongo/types/objectid.rb +219 -0
  31. data/lib/mongo/types/regexp_of_holding.rb +45 -0
  32. data/lib/mongo/util/bson_c.rb +18 -0
  33. data/lib/mongo/util/bson_ruby.rb +595 -0
  34. data/lib/mongo/util/byte_buffer.rb +222 -0
  35. data/lib/mongo/util/conversions.rb +97 -0
  36. data/lib/mongo/util/ordered_hash.rb +135 -0
  37. data/lib/mongo/util/server_version.rb +69 -0
  38. data/lib/mongo/util/support.rb +26 -0
  39. data/lib/mongo/util/xml_to_ruby.rb +112 -0
  40. data/mongo-ruby-driver.gemspec +28 -0
  41. data/test/replica/count_test.rb +34 -0
  42. data/test/replica/insert_test.rb +50 -0
  43. data/test/replica/pooled_insert_test.rb +54 -0
  44. data/test/replica/query_test.rb +39 -0
  45. data/test/test_admin.rb +67 -0
  46. data/test/test_bson.rb +397 -0
  47. data/test/test_byte_buffer.rb +81 -0
  48. data/test/test_chunk.rb +82 -0
  49. data/test/test_collection.rb +534 -0
  50. data/test/test_connection.rb +160 -0
  51. data/test/test_conversions.rb +120 -0
  52. data/test/test_cursor.rb +386 -0
  53. data/test/test_db.rb +254 -0
  54. data/test/test_db_api.rb +783 -0
  55. data/test/test_db_connection.rb +16 -0
  56. data/test/test_grid_store.rb +306 -0
  57. data/test/test_helper.rb +42 -0
  58. data/test/test_objectid.rb +156 -0
  59. data/test/test_ordered_hash.rb +168 -0
  60. data/test/test_round_trip.rb +114 -0
  61. data/test/test_slave_connection.rb +36 -0
  62. data/test/test_threading.rb +87 -0
  63. data/test/threading/test_threading_large_pool.rb +90 -0
  64. data/test/unit/collection_test.rb +52 -0
  65. data/test/unit/connection_test.rb +59 -0
  66. data/test/unit/cursor_test.rb +94 -0
  67. data/test/unit/db_test.rb +97 -0
  68. metadata +123 -0
@@ -0,0 +1,82 @@
1
+ require 'test/test_helper'
2
+ require 'mongo/gridfs'
3
+
4
+ class ChunkTest < Test::Unit::TestCase
5
+
6
+ include Mongo
7
+ include GridFS
8
+
9
+ @@db = Connection.new(ENV['MONGO_RUBY_DRIVER_HOST'] || 'localhost',
10
+ ENV['MONGO_RUBY_DRIVER_PORT'] || Connection::DEFAULT_PORT).db('ruby-mongo-utils-test')
11
+ @@files = @@db.collection('gridfs.files')
12
+ @@chunks = @@db.collection('gridfs.chunks')
13
+
14
+ def setup
15
+ @@chunks.remove
16
+ @@files.remove
17
+
18
+ @f = GridStore.new(@@db, 'foobar', 'w')
19
+ @c = @f.instance_variable_get('@curr_chunk')
20
+ end
21
+
22
+ def teardown
23
+ @@chunks.remove
24
+ @@files.remove
25
+ @@db.error
26
+ end
27
+
28
+ def test_pos
29
+ assert_equal 0, @c.pos
30
+ assert @c.eof? # since data is empty
31
+
32
+ b = ByteBuffer.new
33
+ 3.times { |i| b.put(i) }
34
+ c = Chunk.new(@f, 'data' => b)
35
+ assert !c.eof?
36
+ end
37
+
38
+ def test_getc
39
+ b = ByteBuffer.new
40
+ 3.times { |i| b.put(i) }
41
+ c = Chunk.new(@f, 'data' => b)
42
+
43
+ assert !c.eof?
44
+ assert_equal 0, c.getc
45
+ assert !c.eof?
46
+ assert_equal 1, c.getc
47
+ assert !c.eof?
48
+ assert_equal 2, c.getc
49
+ assert c.eof?
50
+ end
51
+
52
+ def test_putc
53
+ 3.times { |i| @c.putc(i) }
54
+ @c.pos = 0
55
+
56
+ assert !@c.eof?
57
+ assert_equal 0, @c.getc
58
+ assert !@c.eof?
59
+ assert_equal 1, @c.getc
60
+ assert !@c.eof?
61
+ assert_equal 2, @c.getc
62
+ assert @c.eof?
63
+ end
64
+
65
+ def test_truncate
66
+ 10.times { |i| @c.putc(i) }
67
+ assert_equal 10, @c.size
68
+ @c.pos = 3
69
+ @c.truncate
70
+ assert_equal 3, @c.size
71
+
72
+ @c.pos = 0
73
+ assert !@c.eof?
74
+ assert_equal 0, @c.getc
75
+ assert !@c.eof?
76
+ assert_equal 1, @c.getc
77
+ assert !@c.eof?
78
+ assert_equal 2, @c.getc
79
+ assert @c.eof?
80
+ end
81
+
82
+ end
@@ -0,0 +1,534 @@
1
+ require 'test/test_helper'
2
+
3
+ class TestCollection < Test::Unit::TestCase
4
+ @@connection = Connection.new(ENV['MONGO_RUBY_DRIVER_HOST'] || 'localhost', ENV['MONGO_RUBY_DRIVER_PORT'] || Connection::DEFAULT_PORT)
5
+ @@db = @@connection.db('ruby-mongo-test')
6
+ @@test = @@db.collection("test")
7
+ @@version = @@connection.server_version
8
+
9
+ def setup
10
+ @@test.drop()
11
+ end
12
+
13
+ def test_optional_pk_factory
14
+ @coll_default_pk = @@db.collection('stuff')
15
+ assert_equal Mongo::ObjectID, @coll_default_pk.pk_factory
16
+ @coll_default_pk = @@db.create_collection('more-stuff')
17
+ assert_equal Mongo::ObjectID, @coll_default_pk.pk_factory
18
+
19
+ # Create a db with a pk_factory.
20
+ @db = Connection.new(ENV['MONGO_RUBY_DRIVER_HOST'] || 'localhost',
21
+ ENV['MONGO_RUBY_DRIVER_PORT'] || Connection::DEFAULT_PORT).db('ruby-mongo-test', :pk => Object.new)
22
+ @coll = @db.collection('coll-with-pk')
23
+ assert @coll.pk_factory.is_a?(Object)
24
+
25
+ @coll = @db.create_collection('created_coll_with_pk')
26
+ assert @coll.pk_factory.is_a?(Object)
27
+ end
28
+
29
+ def test_valid_names
30
+ assert_raise InvalidName do
31
+ @@db["te$t"]
32
+ end
33
+
34
+ assert_raise InvalidName do
35
+ @@db['$main']
36
+ end
37
+
38
+ assert @@db['$cmd']
39
+ assert @@db['oplog.$main']
40
+ end
41
+
42
+ def test_collection
43
+ assert_kind_of Collection, @@db["test"]
44
+ assert_equal @@db["test"].name(), @@db.collection("test").name()
45
+ assert_equal @@db["test"].name(), @@db[:test].name()
46
+
47
+ assert_kind_of Collection, @@db["test"]["foo"]
48
+ assert_equal @@db["test"]["foo"].name(), @@db.collection("test.foo").name()
49
+ assert_equal @@db["test"]["foo"].name(), @@db["test.foo"].name()
50
+
51
+ @@db["test"]["foo"].remove
52
+ @@db["test"]["foo"].insert("x" => 5)
53
+ assert_equal 5, @@db.collection("test.foo").find_one()["x"]
54
+ end
55
+
56
+ def test_nil_id
57
+ assert_equal 5, @@test.insert({"_id" => 5, "foo" => "bar"}, {:safe => true})
58
+ assert_equal 5, @@test.save({"_id" => 5, "foo" => "baz"}, {:safe => true})
59
+ assert_equal nil, @@test.find_one("foo" => "bar")
60
+ assert_equal "baz", @@test.find_one(:_id => 5)["foo"]
61
+ assert_raise OperationFailure do
62
+ @@test.insert({"_id" => 5, "foo" => "bar"}, {:safe => true})
63
+ end
64
+
65
+ assert_equal nil, @@test.insert({"_id" => nil, "foo" => "bar"}, {:safe => true})
66
+ assert_equal nil, @@test.save({"_id" => nil, "foo" => "baz"}, {:safe => true})
67
+ assert_equal nil, @@test.find_one("foo" => "bar")
68
+ assert_equal "baz", @@test.find_one(:_id => nil)["foo"]
69
+ assert_raise OperationFailure do
70
+ @@test.insert({"_id" => nil, "foo" => "bar"}, {:safe => true})
71
+ end
72
+ assert_raise OperationFailure do
73
+ @@test.insert({:_id => nil, "foo" => "bar"}, {:safe => true})
74
+ end
75
+ end
76
+
77
+ if @@version > "1.1"
78
+ context "distinct queries" do
79
+ setup do
80
+ @@test.remove
81
+ @@test.insert([{:a => 0, :b => {:c => "a"}},
82
+ {:a => 1, :b => {:c => "b"}},
83
+ {:a => 1, :b => {:c => "c"}},
84
+ {:a => 2, :b => {:c => "a"}},
85
+ {:a => 3},
86
+ {:a => 3}])
87
+ end
88
+
89
+ should "return distinct values" do
90
+ assert_equal [0, 1, 2, 3], @@test.distinct(:a).sort
91
+ assert_equal ["a", "b", "c"], @@test.distinct("b.c").sort
92
+ end
93
+
94
+ if @@version >= "1.2"
95
+
96
+ should "filter collection with query" do
97
+ assert_equal [2, 3], @@test.distinct(:a, {:a => {"$gt" => 1}}).sort
98
+ end
99
+
100
+ should "filter nested objects" do
101
+ assert_equal ["a", "b"], @@test.distinct("b.c", {"b.c" => {"$ne" => "c"}}).sort
102
+ end
103
+
104
+ end
105
+ end
106
+ end
107
+
108
+ def test_safe_insert
109
+ a = {"hello" => "world"}
110
+ @@test.insert(a)
111
+ @@test.insert(a)
112
+ assert(@@db.error.include?("E11000"))
113
+
114
+ assert_raise OperationFailure do
115
+ @@test.insert(a, :safe => true)
116
+ end
117
+ end
118
+
119
+ def test_update
120
+ id1 = @@test.save("x" => 5)
121
+ @@test.update({}, {"$inc" => {"x" => 1}})
122
+ assert_equal 1, @@test.count()
123
+ assert_equal 6, @@test.find_one(:_id => id1)["x"]
124
+
125
+ id2 = @@test.save("x" => 1)
126
+ @@test.update({"x" => 6}, {"$inc" => {"x" => 1}})
127
+ assert_equal 7, @@test.find_one(:_id => id1)["x"]
128
+ assert_equal 1, @@test.find_one(:_id => id2)["x"]
129
+ end
130
+
131
+ if @@version >= "1.1.3"
132
+ def test_multi_update
133
+ @@test.save("num" => 10)
134
+ @@test.save("num" => 10)
135
+ @@test.save("num" => 10)
136
+ assert_equal 3, @@test.count
137
+
138
+ @@test.update({"num" => 10}, {"$set" => {"num" => 100}}, :multi => true)
139
+ @@test.find.each do |doc|
140
+ assert_equal 100, doc["num"]
141
+ end
142
+ end
143
+ end
144
+
145
+ def test_upsert
146
+ @@test.update({"page" => "/"}, {"$inc" => {"count" => 1}}, :upsert => true)
147
+ @@test.update({"page" => "/"}, {"$inc" => {"count" => 1}}, :upsert => true)
148
+
149
+ assert_equal 1, @@test.count()
150
+ assert_equal 2, @@test.find_one()["count"]
151
+ end
152
+
153
+ if @@version < "1.1.3"
154
+ def test_safe_update
155
+ @@test.create_index("x")
156
+ @@test.insert("x" => 5)
157
+
158
+ @@test.update({}, {"$inc" => {"x" => 1}})
159
+ assert @@db.error?
160
+
161
+ # Can't change an index.
162
+ assert_raise OperationFailure do
163
+ @@test.update({}, {"$inc" => {"x" => 1}}, :safe => true)
164
+ end
165
+ end
166
+ else
167
+ def test_safe_update
168
+ @@test.create_index("x", true)
169
+ @@test.insert("x" => 5)
170
+ @@test.insert("x" => 10)
171
+
172
+ # Can update an indexed collection.
173
+ @@test.update({}, {"$inc" => {"x" => 1}})
174
+ assert !@@db.error?
175
+
176
+ # Can't duplicate an index.
177
+ assert_raise OperationFailure do
178
+ @@test.update({}, {"x" => 10}, :safe => true)
179
+ end
180
+ end
181
+ end
182
+
183
+ def test_safe_save
184
+ @@test.create_index("hello", true)
185
+
186
+ @@test.save("hello" => "world")
187
+ @@test.save("hello" => "world")
188
+
189
+ assert_raise OperationFailure do
190
+ @@test.save({"hello" => "world"}, :safe => true)
191
+ end
192
+ end
193
+
194
+ def test_safe_remove
195
+ @conn = Connection.new
196
+ @db = @conn['mongo-ruby-test']
197
+ @test = @db['test-safe-remove']
198
+ @test.save({:a => 20})
199
+ @conn.stubs(:receive).returns([[{'ok' => 0, 'err' => 'failed'}], 1, 0])
200
+
201
+ assert_raise OperationFailure do
202
+ @test.remove({}, :safe => true)
203
+ end
204
+ @test.drop
205
+ end
206
+
207
+ def test_count
208
+ @@test.drop
209
+
210
+ assert_equal 0, @@test.count
211
+ @@test.save("x" => 1)
212
+ @@test.save("x" => 2)
213
+ assert_equal 2, @@test.count
214
+ end
215
+
216
+ # Note: #size is just an alias for #count.
217
+ def test_size
218
+ @@test.drop
219
+
220
+ assert_equal 0, @@test.count
221
+ assert_equal @@test.size, @@test.count
222
+ @@test.save("x" => 1)
223
+ @@test.save("x" => 2)
224
+ assert_equal @@test.size, @@test.count
225
+ end
226
+
227
+ def test_no_timeout_option
228
+ @@test.drop
229
+
230
+ assert_raise ArgumentError, "Timeout can be set to false only when #find is invoked with a block." do
231
+ @@test.find({}, :timeout => false)
232
+ end
233
+
234
+ @@test.find({}, :timeout => false) do |cursor|
235
+ assert_equal 0, cursor.count
236
+ end
237
+
238
+ @@test.save("x" => 1)
239
+ @@test.save("x" => 2)
240
+ @@test.find({}, :timeout => false) do |cursor|
241
+ assert_equal 2, cursor.count
242
+ end
243
+ end
244
+
245
+ def test_find_one
246
+ id = @@test.save("hello" => "world", "foo" => "bar")
247
+
248
+ assert_equal "world", @@test.find_one()["hello"]
249
+ assert_equal @@test.find_one(id), @@test.find_one()
250
+ assert_equal @@test.find_one(nil), @@test.find_one()
251
+ assert_equal @@test.find_one({}), @@test.find_one()
252
+ assert_equal @@test.find_one("hello" => "world"), @@test.find_one()
253
+ assert_equal @@test.find_one(OrderedHash["hello", "world"]), @@test.find_one()
254
+
255
+ assert @@test.find_one(nil, :fields => ["hello"]).include?("hello")
256
+ assert !@@test.find_one(nil, :fields => ["foo"]).include?("hello")
257
+ assert_equal ["_id"], @@test.find_one(nil, :fields => []).keys()
258
+
259
+ assert_equal nil, @@test.find_one("hello" => "foo")
260
+ assert_equal nil, @@test.find_one(OrderedHash["hello", "foo"])
261
+ assert_equal nil, @@test.find_one(ObjectID.new)
262
+
263
+ assert_raise TypeError do
264
+ @@test.find_one(6)
265
+ end
266
+ end
267
+
268
+ def test_insert_adds_id
269
+ doc = {"hello" => "world"}
270
+ @@test.insert(doc)
271
+ assert(doc.include?(:_id))
272
+
273
+ docs = [{"hello" => "world"}, {"hello" => "world"}]
274
+ @@test.insert(docs)
275
+ docs.each do |doc|
276
+ assert(doc.include?(:_id))
277
+ end
278
+ end
279
+
280
+ def test_save_adds_id
281
+ doc = {"hello" => "world"}
282
+ @@test.save(doc)
283
+ assert(doc.include?(:_id))
284
+ end
285
+
286
+ def test_optional_find_block
287
+ 10.times do |i|
288
+ @@test.save("i" => i)
289
+ end
290
+
291
+ x = nil
292
+ @@test.find("i" => 2) { |cursor|
293
+ x = cursor.count()
294
+ }
295
+ assert_equal 1, x
296
+
297
+ i = 0
298
+ @@test.find({}, :skip => 5) do |cursor|
299
+ cursor.each do |doc|
300
+ i = i + 1
301
+ end
302
+ end
303
+ assert_equal 5, i
304
+
305
+ c = nil
306
+ @@test.find() do |cursor|
307
+ c = cursor
308
+ end
309
+ assert c.closed?
310
+ end
311
+
312
+ if @@version >= "1.3.0"
313
+ def test_find_modify
314
+ @@test << { "job" => "job1", "inprogress" => false, "priority" => 2 }
315
+ @@test << { "job" => "job2", "inprogress" => false, "priority" => 3 }
316
+ @@test << { "job" => "job3", "inprogress" => false, "priority" => 1 }
317
+
318
+ res = @@test.find_modify(:query => {:inprogress => false},
319
+ :sort => [:priority, :desc],
320
+ :update => {'$set' => { :inprogress => true} }
321
+ )
322
+ assert_equal "job2", res['job']
323
+ assert_equal true, @@test.find_one(:job => 'job2')['inprogress']
324
+ end
325
+ end
326
+
327
+ if @@version < "1.1.1"
328
+ def test_map_reduce
329
+ @@test << { "user_id" => 1 }
330
+ @@test << { "user_id" => 2 }
331
+
332
+ m = "function() { emit(this.user_id, 1); }"
333
+ r = "function(k,vals) { return 1; }"
334
+ res = @@test.map_reduce(m, r);
335
+ assert res.find_one({"_id" => 1})
336
+ assert res.find_one({"_id" => 2})
337
+ end
338
+
339
+ def test_map_reduce_with_code_objects
340
+ @@test << { "user_id" => 1 }
341
+ @@test << { "user_id" => 2 }
342
+
343
+ m = Code.new("function() { emit(this.user_id, 1); }")
344
+ r = Code.new("function(k,vals) { return 1; }")
345
+ res = @@test.map_reduce(m, r);
346
+ assert res.find_one({"_id" => 1})
347
+ assert res.find_one({"_id" => 2})
348
+ end
349
+
350
+ def test_map_reduce_with_options
351
+ @@test.remove
352
+ @@test << { "user_id" => 1 }
353
+ @@test << { "user_id" => 2 }
354
+ @@test << { "user_id" => 3 }
355
+
356
+ m = Code.new("function() { emit(this.user_id, 1); }")
357
+ r = Code.new("function(k,vals) { return 1; }")
358
+ res = @@test.map_reduce(m, r, :query => {"user_id" => {"$gt" => 1}});
359
+ assert_equal 2, res.count
360
+ assert res.find_one({"_id" => 2})
361
+ assert res.find_one({"_id" => 3})
362
+ end
363
+ end
364
+
365
+ def test_saving_dates_pre_epoch
366
+ begin
367
+ @@test.save({'date' => Time.utc(1600)})
368
+ assert_in_delta Time.utc(1600), @@test.find_one()["date"], 0.001
369
+ rescue ArgumentError
370
+ # See note in test_date_before_epoch (BSONTest)
371
+ end
372
+ end
373
+
374
+ def test_save_symbol_find_string
375
+ @@test.save(:foo => :mike)
376
+
377
+ assert_equal :mike, @@test.find_one(:foo => :mike)["foo"]
378
+ assert_equal :mike, @@test.find_one("foo" => :mike)["foo"]
379
+
380
+ # TODO enable these tests conditionally based on server version (if >1.0)
381
+ # assert_equal :mike, @@test.find_one(:foo => "mike")["foo"]
382
+ # assert_equal :mike, @@test.find_one("foo" => "mike")["foo"]
383
+ end
384
+
385
+ def test_limit_and_skip
386
+ 10.times do |i|
387
+ @@test.save(:foo => i)
388
+ end
389
+
390
+ assert_equal 5, @@test.find({}, :skip => 5).next_document()["foo"]
391
+ assert_equal nil, @@test.find({}, :skip => 10).next_document()
392
+
393
+ assert_equal 5, @@test.find({}, :limit => 5).to_a.length
394
+
395
+ assert_equal 3, @@test.find({}, :skip => 3, :limit => 5).next_document()["foo"]
396
+ assert_equal 5, @@test.find({}, :skip => 3, :limit => 5).to_a.length
397
+ end
398
+
399
+ def test_large_limit
400
+ 2000.times do |i|
401
+ @@test.insert("x" => i, "y" => "mongomongo" * 1000)
402
+ end
403
+
404
+ assert_equal 2000, @@test.count
405
+
406
+ i = 0
407
+ y = 0
408
+ @@test.find({}, :limit => 1900).each do |doc|
409
+ i += 1
410
+ y += doc["x"]
411
+ end
412
+
413
+ assert_equal 1900, i
414
+ assert_equal 1804050, y
415
+ end
416
+
417
+ def test_small_limit
418
+ @@test.insert("x" => "hello world")
419
+ @@test.insert("x" => "goodbye world")
420
+
421
+ assert_equal 2, @@test.count
422
+
423
+ x = 0
424
+ @@test.find({}, :limit => 1).each do |doc|
425
+ x += 1
426
+ assert_equal "hello world", doc["x"]
427
+ end
428
+
429
+ assert_equal 1, x
430
+ end
431
+
432
+ context "Grouping" do
433
+ setup do
434
+ @@test.remove
435
+ @@test.save("a" => 1)
436
+ @@test.save("b" => 1)
437
+ @initial = {"count" => 0}
438
+ @reduce_function = "function (obj, prev) { prev.count += inc_value; }"
439
+ end
440
+
441
+ should "group results using eval form" do
442
+ assert_equal 1, @@test.group([], {}, @initial, Code.new(@reduce_function, {"inc_value" => 0.5}))[0]["count"]
443
+ assert_equal 2, @@test.group([], {}, @initial, Code.new(@reduce_function, {"inc_value" => 1}))[0]["count"]
444
+ assert_equal 4, @@test.group([], {}, @initial, Code.new(@reduce_function, {"inc_value" => 2}))[0]["count"]
445
+ end
446
+
447
+ should "group results using command form" do
448
+ assert_equal 1, @@test.group([], {}, @initial, Code.new(@reduce_function, {"inc_value" => 0.5}), true)[0]["count"]
449
+ assert_equal 2, @@test.group([], {}, @initial, Code.new(@reduce_function, {"inc_value" => 1}), true)[0]["count"]
450
+ assert_equal 4, @@test.group([], {}, @initial, Code.new(@reduce_function, {"inc_value" => 2}), true)[0]["count"]
451
+ end
452
+
453
+ should "finalize grouped results" do
454
+ @finalize = "function(doc) {doc.f = doc.count + 200; }"
455
+ assert_equal 202, @@test.group([], {}, @initial, Code.new(@reduce_function, {"inc_value" => 1}), true, @finalize)[0]["f"]
456
+ end
457
+ end
458
+
459
+ context "Grouping with a key function" do
460
+ setup do
461
+ @@test.remove
462
+ @@test.save("a" => 1)
463
+ @@test.save("a" => 2)
464
+ @@test.save("a" => 3)
465
+ @@test.save("a" => 4)
466
+ @@test.save("a" => 5)
467
+ @initial = {"count" => 0}
468
+ @keyf = "function (doc) { if(doc.a % 2 == 0) { return {even: true}; } else {return {odd: true}} };"
469
+ @reduce = "function (obj, prev) { prev.count += 1; }"
470
+ end
471
+
472
+ should "group results" do
473
+ results = @@test.group(@keyf, {}, @initial, @reduce, true).sort {|a, b| a['count'] <=> b['count']}
474
+ assert results[0]['even'] && results[0]['count'] == 2.0
475
+ assert results[1]['odd'] && results[1]['count'] == 3.0
476
+ end
477
+
478
+ should "raise an error if trying to use keyf as a group eval" do
479
+ assert_raise OperationFailure do
480
+ @@test.group(@keyf, {}, @initial, @reduce)
481
+ end
482
+ end
483
+ end
484
+
485
+ context "A collection with two records" do
486
+ setup do
487
+ @collection = @@db.collection('test-collection')
488
+ @collection.insert({:name => "Jones"})
489
+ @collection.insert({:name => "Smith"})
490
+ end
491
+
492
+ should "have two records" do
493
+ assert_equal 2, @collection.size
494
+ end
495
+
496
+ should "remove the two records" do
497
+ @collection.remove()
498
+ assert_equal 0, @collection.size
499
+ end
500
+
501
+ should "remove all records if an empty document is specified" do
502
+ @collection.remove({})
503
+ assert_equal 0, @collection.find.count
504
+ end
505
+
506
+ should "remove only matching records" do
507
+ @collection.remove({:name => "Jones"})
508
+ assert_equal 1, @collection.size
509
+ end
510
+ end
511
+
512
+ context "Creating indexes " do
513
+ setup do
514
+ @collection = @@db.collection('test-collection')
515
+ end
516
+
517
+ should "generate indexes in the proper order" do
518
+ @collection.expects(:insert_documents) do |sel, coll, safe|
519
+ assert_equal 'b_1_a_1', sel[:name]
520
+ end
521
+ @collection.create_index([['b', 1], ['a', 1]])
522
+ end
523
+
524
+ context "with an index created" do
525
+ setup do
526
+ @collection.create_index([['b', 1], ['a', 1]])
527
+ end
528
+
529
+ should "return properly ordered index information" do
530
+ assert_equal [['b', 1], ['a', 1]], @collection.index_information["b_1_a_1"]
531
+ end
532
+ end
533
+ end
534
+ end