mongo-find_replace 0.18.3

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 (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