em-mongo 0.3.6 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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