em-mongo 0.3.6 → 0.4.0

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.
@@ -0,0 +1,350 @@
1
+ require File.expand_path('spec_helper', File.dirname(__FILE__) + '/../')
2
+
3
+
4
+
5
+ describe EMMongo::Cursor do
6
+ include EM::Spec
7
+
8
+ it 'should describe itself via inspect' do
9
+ @conn, @coll = connection_and_collection
10
+ cursor = EM::Mongo::Cursor.new( @coll, :selector => {'a' => 1} )
11
+ cursor.inspect.should == "<EM::Mongo::Cursor:0x#{cursor.object_id.to_s} namespace='#{@coll.db.name}.#{@coll.name}' " +
12
+ "@selector=#{cursor.selector.inspect}>"
13
+ done
14
+ end
15
+
16
+ it 'should explain itself' do
17
+ @conn, @coll = connection_and_collection
18
+ cursor = EM::Mongo::Cursor.new(@coll, :selector => {'a' => 1} )
19
+ cursor.explain.callback do |explanation|
20
+ explanation['cursor'].should_not be_nil
21
+ explanation['n'].should be_kind_of Numeric
22
+ explanation['millis'].should be_kind_of Numeric
23
+ explanation['nscanned'].should be_kind_of Numeric
24
+ done
25
+ end
26
+ end
27
+
28
+ it "should allow limit and skip to be chained" do
29
+ @conn, @coll = connection_and_collection
30
+ cursor = EM::Mongo::Cursor.new(@coll)
31
+ all = []
32
+ 10.times do |i|
33
+ all << {"x" => i}
34
+ @coll.save(all[-1])
35
+ end
36
+
37
+ cursor.limit(5).skip(3).sort("x",1).to_a.callback do |results|
38
+ all.slice(3...8).each_with_index do |item,idx|
39
+ results[idx]["x"].should == item["x"]
40
+ end
41
+ done
42
+ end
43
+ end
44
+
45
+ it "should allow a limit larger than the batch size" do
46
+ @conn, @coll = connection_and_collection
47
+ cursor = EM::Mongo::Cursor.new(@coll, :selector => {})
48
+ all = []
49
+ 1501.times do |i|
50
+ @coll.insert(i.to_s => i.to_s)
51
+ end
52
+ cursor.limit(1500).to_a.callback do |docs|
53
+ docs.length.should == 1500
54
+ done
55
+ end
56
+ end
57
+
58
+
59
+
60
+ it "should say if it has next" do
61
+ @conn, @coll = connection_and_collection
62
+ cursor = EM::Mongo::Cursor.new(@coll)
63
+ 1.times do |i|
64
+ @coll.save("x" => 1)
65
+ end
66
+ cursor.has_next?.callback do |result|
67
+ result.should be_true
68
+ cursor.next_document.callback do |doc|
69
+ cursor.has_next?.callback do |result|
70
+ result.should be_false
71
+ done
72
+ end
73
+ end
74
+ end
75
+ end
76
+
77
+ it "should rewind" do
78
+ @conn, @coll = connection_and_collection
79
+ cursor = EM::Mongo::Cursor.new(@coll)
80
+ 100.times do |i|
81
+ @coll.save("x" => 1)
82
+ end
83
+ cursor.to_a.callback do |r1|
84
+ r1.length.should == 100
85
+ cursor.to_a.callback do |r2|
86
+ r2.length.should == 0
87
+ cursor.rewind!
88
+ cursor.to_a.callback do |r3|
89
+ r3.length.should == 100
90
+ done
91
+ end
92
+ end
93
+
94
+ end
95
+ end
96
+
97
+ describe "Get More" do
98
+ it "should refill via get more" do
99
+ @conn, @coll = connection_and_collection
100
+ cursor = EM::Mongo::Cursor.new(@coll)
101
+ 1000.times do |i|
102
+ @coll.save("x" => 1)
103
+ end
104
+ cursor.to_a.callback do |results|
105
+ results.length.should == 1000
106
+ done
107
+ end
108
+ end
109
+ end
110
+
111
+ describe "Count" do
112
+
113
+ it 'should count 0 records in a empty collection' do
114
+ @conn, @coll = connection_and_collection
115
+ cursor = EM::Mongo::Cursor.new(@coll)
116
+ cursor.count.callback do |c|
117
+ c.should == 0
118
+ done
119
+ end
120
+ end
121
+
122
+ it "should count records in a collection" do
123
+ @conn, @coll = connection_and_collection
124
+ cursor = EM::Mongo::Cursor.new(@coll)
125
+ 10.times do |i|
126
+ @coll.save("x" => 1)
127
+ end
128
+
129
+ cursor.count.callback do |c|
130
+ c.should == 10
131
+ done
132
+ end
133
+ end
134
+
135
+ it "should ignore skip and limit by default" do
136
+ @conn, @coll = connection_and_collection
137
+ cursor = EM::Mongo::Cursor.new(@coll).skip(5).limit(5)
138
+ 10.times do |i|
139
+ @coll.save("x" => i)
140
+ end
141
+
142
+ cursor.count.callback do |c|
143
+ c.should == 10
144
+ done
145
+ end
146
+ end
147
+
148
+ it "should account for skip when requested" do
149
+ @conn, @coll = connection_and_collection
150
+ cursor = EM::Mongo::Cursor.new(@coll).limit(5)
151
+ 10.times do |i|
152
+ @coll.save("x" => i)
153
+ end
154
+
155
+ cursor.count(true).callback do |c|
156
+ c.should == 5
157
+ done
158
+ end
159
+ end
160
+
161
+ it "should account for skip when requested" do
162
+ @conn, @coll = connection_and_collection
163
+ cursor = EM::Mongo::Cursor.new(@coll).skip(5)
164
+ 10.times do |i|
165
+ @coll.save("x" => i)
166
+ end
167
+
168
+ cursor.count(true).callback do |c|
169
+ c.should == 5
170
+ done
171
+ end
172
+ end
173
+
174
+ it "should count based on a simple selector" do
175
+ @conn, @coll = connection_and_collection
176
+ cursor = EM::Mongo::Cursor.new(@coll, :selector => {"x"=>1})
177
+ 10.times do |i|
178
+ @coll.save("x" => i)
179
+ end
180
+
181
+ cursor.count(true).callback do |c|
182
+ c.should == 1
183
+ done
184
+ end
185
+ end
186
+
187
+ it "should count based on a selector with an operator" do
188
+ @conn, @coll = connection_and_collection
189
+ cursor = EM::Mongo::Cursor.new(@coll, :selector => {"x"=>{"$lt"=>5}})
190
+ 10.times do |i|
191
+ @coll.save("x" => i)
192
+ end
193
+
194
+ cursor.count(true).callback do |c|
195
+ c.should == 5
196
+ done
197
+ end
198
+ end
199
+
200
+ it "should count a non-existing collection as 0 without vomiting blood" do
201
+ @conn, @coll = connection_and_collection
202
+ @coll = @conn.db.collection('imnotreallyheredontlookatme')
203
+
204
+ cursor = EM::Mongo::Cursor.new(@coll)
205
+
206
+ cursor.count(true).callback do |c|
207
+ c.should == 0
208
+ done
209
+ end
210
+ end
211
+ end
212
+
213
+ describe "Sort" do
214
+ it "should sort ascending" do
215
+ @conn, @coll = connection_and_collection
216
+ 5.times do |i|
217
+ @coll.save("x" => i)
218
+ end
219
+ cursor = EM::Mongo::Cursor.new(@coll).sort(:x, 1)
220
+ cursor.next_document.callback do |first|
221
+ first["x"].should == 0
222
+ done
223
+ end
224
+ end
225
+
226
+ it "should sort descending" do
227
+ @conn, @coll = connection_and_collection
228
+ 5.times do |i|
229
+ @coll.save("x" => i)
230
+ end
231
+ cursor = EM::Mongo::Cursor.new(@coll).sort(:x, -1)
232
+ cursor.next_document.callback do |first|
233
+ first["x"].should == 4
234
+ done
235
+ end
236
+ end
237
+
238
+ it "should sort descending using a symbol sort dir" do
239
+ @conn, @coll = connection_and_collection
240
+ 5.times do |i|
241
+ @coll.save("x" => i)
242
+ end
243
+ cursor = EM::Mongo::Cursor.new(@coll).sort(["x", :desc])
244
+ cursor.next_document.callback do |first|
245
+ first["x"].should == 4
246
+ done
247
+ end
248
+ end
249
+
250
+ it "should not allow sort to be called on an executed cursor" do
251
+ @conn, @coll = connection_and_collection
252
+ 5.times do |i|
253
+ @coll.save("x" => i)
254
+ end
255
+ cursor = EM::Mongo::Cursor.new(@coll).sort(["x", :desc])
256
+ cursor.next_document.callback do |first|
257
+ lambda { cursor.sort("x",1) }.should raise_error EM::Mongo::InvalidOperation
258
+ done
259
+ end
260
+ end
261
+
262
+ it "should sort by dates" do
263
+ @conn, @coll = connection_and_collection
264
+ 5.times do |i|
265
+ @coll.insert("x" => Time.utc(2000 + i))
266
+ end
267
+ cursor = EM::Mongo::Cursor.new(@coll).sort(["x", :desc])
268
+ cursor.next_document.callback do |first|
269
+ first["x"].year.should == 2004
270
+ done
271
+ end
272
+ end
273
+
274
+ describe "Each" do
275
+ it "should iterate through each doc, returning null when done" do
276
+ @conn, @coll = connection_and_collection
277
+ 5.times do |i|
278
+ @coll.insert("x" => i)
279
+ end
280
+ cursor = EM::Mongo::Cursor.new(@coll)
281
+ counter = 0
282
+ cursor.each do |doc|
283
+ if doc
284
+ counter+=1
285
+ else
286
+ counter.should == 5
287
+ done
288
+ end
289
+ end
290
+ end
291
+ end
292
+
293
+ describe "to_a" do
294
+ it "should return an array of all documents in a query" do
295
+ @conn, @coll = connection_and_collection
296
+ 5.times do |i|
297
+ @coll.insert("x" => i)
298
+ end
299
+ cursor = EM::Mongo::Cursor.new(@coll).sort("x",1)
300
+ cursor.to_a.callback do |docs|
301
+ docs.length.should == 5
302
+ 5.times do |i|
303
+ docs[i]["x"].should == i
304
+ end
305
+ done
306
+ end
307
+ end
308
+ end
309
+
310
+ describe "Transformer (a robot in disguise)" do
311
+ it "should set the transformer when passed in the constructor" do
312
+ @conn, @coll = connection_and_collection
313
+ transformer = Proc.new {|doc|doc}
314
+ cursor = EM::Mongo::Cursor.new(@coll, :transformer => transformer)
315
+ cursor.transformer.should == transformer
316
+ done
317
+ end
318
+ it "should transform docs with next" do
319
+ @conn, @coll = connection_and_collection
320
+ @coll.insert({:a=>1})
321
+ klass = Struct.new(:id,:a)
322
+ transformer = Proc.new {|doc|klass.new(doc['_id'],doc['a'])}
323
+ cursor = EM::Mongo::Cursor.new(@coll, :transformer => transformer)
324
+ cursor.next.callback do |doc|
325
+ doc.should be_kind_of klass
326
+ doc.id.should be_kind_of BSON::ObjectId
327
+ doc.a.should == 1
328
+ done
329
+ end
330
+ end
331
+ it "should transform docs with each" do
332
+ @conn, @coll = connection_and_collection
333
+ @coll.insert({:a=>1})
334
+ klass = Struct.new(:id, :a)
335
+ transformer = Proc.new { |doc| klass.new(doc['_id'], doc['a']) }
336
+ cursor = EM::Mongo::Cursor.new(@coll, :transformer => transformer)
337
+
338
+ cursor.each do |doc|
339
+ if doc
340
+ doc.should be_kind_of klass
341
+ doc.id.should be_kind_of BSON::ObjectId
342
+ doc.a.should == 1
343
+ end
344
+ done
345
+ end
346
+ end
347
+ end
348
+ end
349
+
350
+ end
@@ -6,22 +6,76 @@ describe EMMongo::Database do
6
6
  it 'should add a user' do
7
7
  @conn = EM::Mongo::Connection.new
8
8
  @db = @conn.db
9
- @db.add_user('test', 'test') do |res|
9
+ @db.collection(EM::Mongo::Database::SYSTEM_USER_COLLECTION).remove({})
10
+ @db.add_user('test', 'test').callback do |res|
10
11
  res.should_not == nil
11
12
  res.should be_a_kind_of(BSON::ObjectId)
12
13
  done
13
14
  end
14
15
  end
15
16
 
16
- # This test requires the above test.
17
17
  it 'should authenticate a user' do
18
18
  @conn = EM::Mongo::Connection.new
19
19
  @db = @conn.db
20
- @db.authenticate('test', 'test') do |res|
20
+ @db.add_user('test', 'test')
21
+ @db.authenticate('test', 'test').callback do |res|
21
22
  res.should == true
22
23
  done
23
24
  end
24
25
  end
26
+
27
+ it "should create a collection" do
28
+ @conn = EM::Mongo::Connection.new
29
+ @db = @conn.db
30
+ @db.create_collection("a").callback do |col|
31
+ col.should be_kind_of EM::Mongo::Collection
32
+ col.name.should == "a"
33
+ done
34
+ end
35
+ end
36
+
37
+ it "should drop a collection" do
38
+ @conn = EM::Mongo::Connection.new
39
+ @db = @conn.db
40
+ @db.create_collection("a").callback do |col|
41
+ @db.drop_collection("a").callback do
42
+ @db.collection_names.callback do |names|
43
+ names.should_not include "a"
44
+ done
45
+ end
46
+ end
47
+ end
48
+ end
49
+
50
+ it "should provide a list of collection names in the database" do
51
+ @conn = EM::Mongo::Connection.new
52
+ @db = @conn.db
53
+ @db.create_collection "a"
54
+ @db.create_collection("b").callback do
55
+ @db.collection_names.callback do |names|
56
+ names.should include "a"
57
+ names.should include "b"
58
+ done
59
+ end
60
+ end
61
+ end
62
+
63
+ it "should provide a list of collections in the database" do
64
+ @conn = EM::Mongo::Connection.new
65
+ @db = @conn.db
66
+ @db.create_collection "a"
67
+ @db.create_collection("b").callback do
68
+ @db.collection_names.callback do |names|
69
+ @db.collections do |collections|
70
+ collections.length.should == names.length
71
+ collections.each do |col|
72
+ col.should be_kind_of EM::Mongo::Collection
73
+ end
74
+ end
75
+ done
76
+ end
77
+ end
78
+ end
25
79
 
26
80
  it 'should cache collections correctly' do
27
81
  @conn = EM::Mongo::Connection.new
@@ -34,4 +88,96 @@ describe EMMongo::Database do
34
88
  done
35
89
  end
36
90
 
91
+ describe "Errors" do
92
+ describe "when there are no errors" do
93
+ it "should return a nil 'err' from get_last_error" do
94
+ @conn = EM::Mongo::Connection.new
95
+ @db = @conn.db
96
+ @db.reset_error_history.callback do
97
+ @db.get_last_error.callback do |doc|
98
+ doc['err'].should be_nil
99
+ done
100
+ end
101
+ end
102
+ end
103
+ it "should have a false error?" do
104
+ @conn = EM::Mongo::Connection.new
105
+ @db = @conn.db
106
+ @db.reset_error_history.callback do
107
+ @db.error?.callback do |result|
108
+ result.should == false
109
+ done
110
+ end
111
+ end
112
+ end
113
+ end
114
+ describe "when there are errors" do
115
+ it "should return a value for 'err' from get_last_error" do
116
+ @conn = EM::Mongo::Connection.new
117
+ @db = @conn.db
118
+ @db.command({:forceerror=>1}, :check_response => false).callback do
119
+ @db.get_last_error.callback do |doc|
120
+ doc['err'].should_not be_nil
121
+ done
122
+ end
123
+ end
124
+ end
125
+ it "should have a true error?" do
126
+ @conn = EM::Mongo::Connection.new
127
+ @db = @conn.db
128
+ @db.command({:forceerror=>1}, :check_response => false).callback do
129
+ @db.error?.callback do |result|
130
+ result.should == true
131
+ done
132
+ end
133
+ end
134
+ end
135
+ end
136
+ it "should be able to reset the error history" do
137
+ @conn = EM::Mongo::Connection.new
138
+ @db = @conn.db
139
+ @db.command({:forceerror=>1}, :check_response => false).callback do
140
+ @db.reset_error_history.callback do
141
+ @db.error?.callback do |result|
142
+ result.should == false
143
+ done
144
+ end
145
+ end
146
+ end
147
+ end
148
+ end
149
+
150
+ describe "Command" do
151
+ it "should fail when the database returns an error" do
152
+ @conn = EM::Mongo::Connection.new
153
+ @db = @conn.db
154
+ @db.command({:non_command => 1}, :check_response => true).errback do
155
+ done
156
+ end
157
+ end
158
+ it "should not fail when checkresponse is false" do
159
+ @conn = EM::Mongo::Connection.new
160
+ @db = @conn.db
161
+ @db.command({:non_command => 1}, :check_response => false).callback do
162
+ done
163
+ end
164
+ end
165
+ it "should succesfully execute a valid command" do
166
+ @conn, @coll = connection_and_collection
167
+ @db = @conn.db
168
+ @coll.insert( {:col => {:easy => "andy" } } )
169
+ @db.command({:collstats => @coll.name}).callback do |doc|
170
+ doc.should_not be_nil
171
+ doc["count"].should == 1
172
+ done
173
+ end
174
+ end
175
+ end
176
+
177
+ describe "Indexes" do
178
+ #Index functions are integration tested via the collection specs. Maybe the wrong order,
179
+ #but the collection index functions all call down to the database index functions, and the
180
+ #tests would simply duplicate eachother
181
+ end
182
+
37
183
  end