mongo 1.2.4 → 1.3.0.rc0

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 (46) hide show
  1. data/README.md +13 -25
  2. data/Rakefile +9 -1
  3. data/docs/HISTORY.md +19 -0
  4. data/docs/RELEASES.md +33 -0
  5. data/docs/REPLICA_SETS.md +4 -3
  6. data/lib/mongo.rb +20 -2
  7. data/lib/mongo/collection.rb +15 -2
  8. data/lib/mongo/connection.rb +75 -14
  9. data/lib/mongo/cursor.rb +12 -4
  10. data/lib/mongo/db.rb +3 -3
  11. data/lib/mongo/exceptions.rb +3 -0
  12. data/lib/mongo/gridfs/grid_io.rb +88 -7
  13. data/lib/mongo/repl_set_connection.rb +29 -11
  14. data/lib/mongo/util/pool.rb +15 -6
  15. data/lib/mongo/util/timeout.rb +42 -0
  16. data/lib/mongo/util/uri_parser.rb +5 -1
  17. data/test/auxillary/fork_test.rb +30 -0
  18. data/test/bson/bson_test.rb +68 -27
  19. data/test/bson/byte_buffer_test.rb +11 -0
  20. data/test/bson/object_id_test.rb +14 -1
  21. data/test/bson/ordered_hash_test.rb +7 -0
  22. data/test/bson/timestamp_test.rb +24 -0
  23. data/test/collection_test.rb +41 -24
  24. data/test/connection_test.rb +33 -2
  25. data/test/conversions_test.rb +10 -11
  26. data/test/cursor_fail_test.rb +1 -1
  27. data/test/cursor_message_test.rb +1 -1
  28. data/test/cursor_test.rb +33 -4
  29. data/test/db_api_test.rb +13 -2
  30. data/test/db_test.rb +3 -3
  31. data/test/grid_file_system_test.rb +0 -1
  32. data/test/grid_io_test.rb +72 -1
  33. data/test/grid_test.rb +16 -16
  34. data/test/replica_sets/connect_test.rb +8 -0
  35. data/test/replica_sets/query_test.rb +10 -0
  36. data/test/support/hash_with_indifferent_access.rb +0 -13
  37. data/test/support_test.rb +0 -1
  38. data/test/test_helper.rb +27 -8
  39. data/test/timeout_test.rb +14 -0
  40. data/test/unit/collection_test.rb +1 -1
  41. data/test/unit/connection_test.rb +0 -13
  42. data/test/unit/cursor_test.rb +16 -6
  43. data/test/unit/db_test.rb +9 -11
  44. data/test/unit/repl_set_connection_test.rb +0 -13
  45. data/test/unit/safe_test.rb +1 -1
  46. metadata +15 -23
@@ -186,5 +186,16 @@ class ByteBufferTest < Test::Unit::TestCase
186
186
  @buf.get_int
187
187
  assert !@buf.more?
188
188
  end
189
+
190
+ def test_equality
191
+ @buf = ByteBuffer.new("foo")
192
+ assert_equal @buf, @buf
193
+ assert_equal ByteBuffer.new(""), ByteBuffer.new("")
194
+ assert_equal ByteBuffer.new("123"), ByteBuffer.new("123")
195
+ assert_not_equal ByteBuffer.new("123"), ByteBuffer.new("1234")
196
+ assert_equal @buf, "foo"
197
+ assert_not_equal @buf, 123
198
+ assert_not_equal @buf, nil
199
+ end
189
200
 
190
201
  end
@@ -126,14 +126,27 @@ class ObjectIdTest < Test::Unit::TestCase
126
126
  time = Time.now.utc
127
127
  id = ObjectId.from_time(time)
128
128
 
129
+ assert id.to_a[4, 8].all? {|byte| byte == 0 }
129
130
  assert_equal time.to_i, id.generation_time.to_i
130
131
  end
131
132
 
133
+ def test_from_time_unique
134
+ time = Time.now.utc
135
+ id = ObjectId.from_time(time, :unique => true)
136
+
137
+ mac_id = Digest::MD5.digest(Socket.gethostname)[0, 3].unpack("C3")
138
+ assert_equal id.to_a[4, 3], mac_id
139
+ assert_equal time.to_i, id.generation_time.to_i
140
+
141
+ id2 = ObjectId.new(nil, time)
142
+ assert_equal time.to_i, id2.generation_time.to_i
143
+ end
144
+
132
145
  def test_json
133
146
  id = ObjectId.new
134
147
  assert_equal "{\"$oid\": \"#{id}\"}", id.to_json
135
148
  end
136
-
149
+
137
150
  def test_as_json
138
151
  id = ObjectId.new
139
152
  assert_equal({"$oid" => id.to_s}, id.as_json)
@@ -194,4 +194,11 @@ class OrderedHashTest < Test::Unit::TestCase
194
194
  copy[:foo] = 1
195
195
  assert copy.keys != @oh.keys
196
196
  end
197
+
198
+ def test_dup
199
+ oh2 = @oh.dup
200
+ oh2['f'] = 9
201
+ assert_nil @oh['f']
202
+ assert_equal ['c', 'a', 'z'], @oh.keys
203
+ end
197
204
  end
@@ -0,0 +1,24 @@
1
+ require './test/test_helper'
2
+
3
+ class TiumestampTest < Test::Unit::TestCase
4
+ include Mongo
5
+
6
+ def test_timestamp_equality
7
+ t1 = Timestamp.new(5000, 200)
8
+ t2 = Timestamp.new(5000, 200)
9
+ assert_equal t2, t1
10
+ end
11
+
12
+ def test_implements_array_for_backward_compatibility
13
+ ts = Timestamp.new(5000, 200)
14
+ assert_equal 200, ts[0]
15
+ assert_equal 5000, ts[1]
16
+
17
+ array = ts.map {|t| t }
18
+ assert_equal 2, array.length
19
+
20
+ assert_equal 200, array[0]
21
+ assert_equal 5000, array[1]
22
+ end
23
+
24
+ end
@@ -1,7 +1,7 @@
1
1
  require './test/test_helper'
2
2
 
3
3
  class TestCollection < Test::Unit::TestCase
4
- @@connection ||= standard_connection
4
+ @@connection ||= standard_connection(:op_timeout => 2)
5
5
  @@db = @@connection.db(MONGO_TEST_DB)
6
6
  @@test = @@db.collection("test")
7
7
  @@version = @@connection.server_version
@@ -373,8 +373,8 @@ class TestCollection < Test::Unit::TestCase
373
373
 
374
374
  docs = [{"hello" => "world"}, {"hello" => "world"}]
375
375
  @@test.insert(docs)
376
- docs.each do |doc|
377
- assert(doc.include?(:_id))
376
+ docs.each do |d|
377
+ assert(d.include?(:_id))
378
378
  end
379
379
  end
380
380
 
@@ -466,31 +466,34 @@ class TestCollection < Test::Unit::TestCase
466
466
  assert res["timeMillis"]
467
467
  end
468
468
 
469
- def test_map_reduce_with_collection_merge
470
- @@test << {:user_id => 1}
471
- @@test << {:user_id => 2}
472
- output_collection = "test-map-coll"
473
- m = Code.new("function() { emit(this.user_id, {count: 1}); }")
474
- r = Code.new("function(k,vals) { var sum = 0;" +
475
- " vals.forEach(function(v) { sum += v.count;} ); return {count: sum}; }")
476
- res = @@test.map_reduce(m, r, :out => output_collection)
477
469
 
478
- @@test.remove
479
- @@test << {:user_id => 3}
480
- res = @@test.map_reduce(m, r, :out => {:merge => output_collection})
481
- assert res.find.to_a.any? {|doc| doc["_id"] == 3 && doc["value"]["count"] == 1}
470
+ if @@version >= "1.8.0"
471
+ def test_map_reduce_with_collection_merge
472
+ @@test << {:user_id => 1}
473
+ @@test << {:user_id => 2}
474
+ output_collection = "test-map-coll"
475
+ m = Code.new("function() { emit(this.user_id, {count: 1}); }")
476
+ r = Code.new("function(k,vals) { var sum = 0;" +
477
+ " vals.forEach(function(v) { sum += v.count;} ); return {count: sum}; }")
478
+ res = @@test.map_reduce(m, r, :out => output_collection)
482
479
 
483
- @@test.remove
484
- @@test << {:user_id => 3}
485
- res = @@test.map_reduce(m, r, :out => {:reduce => output_collection})
486
- assert res.find.to_a.any? {|doc| doc["_id"] == 3 && doc["value"]["count"] == 2}
480
+ @@test.remove
481
+ @@test << {:user_id => 3}
482
+ res = @@test.map_reduce(m, r, :out => {:merge => output_collection})
483
+ assert res.find.to_a.any? {|doc| doc["_id"] == 3 && doc["value"]["count"] == 1}
487
484
 
488
- assert_raise ArgumentError do
489
- @@test.map_reduce(m, r, :out => {:inline => 1})
490
- end
485
+ @@test.remove
486
+ @@test << {:user_id => 3}
487
+ res = @@test.map_reduce(m, r, :out => {:reduce => output_collection})
488
+ assert res.find.to_a.any? {|doc| doc["_id"] == 3 && doc["value"]["count"] == 2}
491
489
 
492
- @@test.map_reduce(m, r, :raw => true, :out => {:inline => 1})
493
- assert res["results"]
490
+ assert_raise ArgumentError do
491
+ @@test.map_reduce(m, r, :out => {:inline => 1})
492
+ end
493
+
494
+ @@test.map_reduce(m, r, :raw => true, :out => {:inline => 1})
495
+ assert res["results"]
496
+ end
494
497
  end
495
498
  end
496
499
 
@@ -592,6 +595,20 @@ class TestCollection < Test::Unit::TestCase
592
595
  assert_equal 1, x
593
596
  end
594
597
 
598
+ def test_find_with_transformer
599
+ klass = Struct.new(:id, :a)
600
+ transformer = Proc.new { |doc| klass.new(doc['_id'], doc['a']) }
601
+ cursor = @@test.find({}, :transformer => transformer)
602
+ assert_equal(transformer, cursor.transformer)
603
+ end
604
+
605
+ def test_find_one_with_transformer
606
+ klass = Struct.new(:id, :a)
607
+ transformer = Proc.new { |doc| klass.new(doc['_id'], doc['a']) }
608
+ id = @@test.insert('a' => 1)
609
+ doc = @@test.find_one(id, :transformer => transformer)
610
+ assert_instance_of(klass, doc)
611
+ end
595
612
 
596
613
  def test_ensure_index
597
614
  @@test.drop_indexes
@@ -22,12 +22,22 @@ class TestConnection < Test::Unit::TestCase
22
22
  end
23
23
  end
24
24
 
25
+ def test_host_port_accessors
26
+ assert_equal @conn.host, TEST_HOST
27
+ assert_equal @conn.port, TEST_PORT
28
+ end
29
+
25
30
  def test_server_info
26
31
  server_info = @conn.server_info
27
32
  assert server_info.keys.include?("version")
28
33
  assert Mongo::Support.ok?(server_info)
29
34
  end
30
35
 
36
+ def test_ping
37
+ ping = @conn.ping
38
+ assert ping['ok']
39
+ end
40
+
31
41
  def test_connection_uri
32
42
  con = Connection.from_uri("mongodb://#{host_port}")
33
43
  assert_equal mongo_host, con.primary_pool.host
@@ -35,7 +45,7 @@ class TestConnection < Test::Unit::TestCase
35
45
  end
36
46
 
37
47
  def test_server_version
38
- assert_match /\d\.\d+(\.\d+)?/, @conn.server_version.to_s
48
+ assert_match(/\d\.\d+(\.\d+)?/, @conn.server_version.to_s)
39
49
  end
40
50
 
41
51
  def test_invalid_database_names
@@ -149,7 +159,7 @@ class TestConnection < Test::Unit::TestCase
149
159
  @conn.lock!
150
160
  assert @conn.locked?
151
161
  assert_equal 1, @conn['admin']['$cmd.sys.inprog'].find_one['fsyncLock'], "Not fsync-locked"
152
- assert_equal "unlock requested", @conn.unlock!['info']
162
+ assert_match(/unlock/, @conn.unlock!['info'])
153
163
  unlocked = false
154
164
  counter = 0
155
165
  while counter < 5
@@ -200,6 +210,27 @@ class TestConnection < Test::Unit::TestCase
200
210
  assert_equal Mongo::DEFAULT_MAX_BSON_SIZE, BSON::BSON_CODER.max_bson_size
201
211
  end
202
212
 
213
+ def test_connection_activity
214
+ conn = standard_connection
215
+ assert conn.active?
216
+
217
+ conn.primary_pool.close
218
+ assert !conn.active?
219
+
220
+ # Simulate a dropped connection.
221
+ dropped_socket = Mocha::Mock.new
222
+ dropped_socket.stubs(:read).raises(Errno::ECONNRESET)
223
+ dropped_socket.stubs(:send).raises(Errno::ECONNRESET)
224
+ dropped_socket.stub_everything
225
+
226
+ conn.primary_pool.host = 'localhost'
227
+ conn.primary_pool.port = Mongo::Connection::DEFAULT_PORT
228
+ conn.primary_pool.instance_variable_set("@pids", {dropped_socket => Process.pid})
229
+ conn.primary_pool.instance_variable_set("@sockets", [dropped_socket])
230
+
231
+ assert !conn.active?
232
+ end
233
+
203
234
  context "Saved authentications" do
204
235
  setup do
205
236
  @conn = standard_connection
@@ -1,7 +1,6 @@
1
1
  require './test/test_helper'
2
2
  require 'mongo/exceptions'
3
3
  require 'mongo/util/conversions'
4
- require 'bson/ordered_hash'
5
4
 
6
5
  class ConversionsTest < Test::Unit::TestCase
7
6
  include Mongo::Conversions
@@ -40,11 +39,11 @@ class ConversionsTest < Test::Unit::TestCase
40
39
  end
41
40
 
42
41
  def test_sort_value_when_value_is_negative_one
43
- assert_equal -1, sort_value(-1)
42
+ assert_equal(-1, sort_value(-1))
44
43
  end
45
44
 
46
45
  def test_sort_value_when_value_is_negative_one_as_a_string
47
- assert_equal -1, sort_value("-1")
46
+ assert_equal(-1, sort_value("-1"))
48
47
  end
49
48
 
50
49
  def test_sort_value_when_value_is_ascending
@@ -80,35 +79,35 @@ class ConversionsTest < Test::Unit::TestCase
80
79
  end
81
80
 
82
81
  def test_sort_value_when_value_is_descending
83
- assert_equal -1, sort_value("descending")
82
+ assert_equal(-1, sort_value("descending"))
84
83
  end
85
84
 
86
85
  def test_sort_value_when_value_is_desc
87
- assert_equal -1, sort_value("desc")
86
+ assert_equal(-1, sort_value("desc"))
88
87
  end
89
88
 
90
89
  def test_sort_value_when_value_is_uppercase_descending
91
- assert_equal -1, sort_value("DESCENDING")
90
+ assert_equal(-1, sort_value("DESCENDING"))
92
91
  end
93
92
 
94
93
  def test_sort_value_when_value_is_uppercase_desc
95
- assert_equal -1, sort_value("DESC")
94
+ assert_equal(-1, sort_value("DESC"))
96
95
  end
97
96
 
98
97
  def test_sort_value_when_value_is_symbol_descending
99
- assert_equal -1, sort_value(:descending)
98
+ assert_equal(-1, sort_value(:descending))
100
99
  end
101
100
 
102
101
  def test_sort_value_when_value_is_symbol_desc
103
- assert_equal -1, sort_value(:desc)
102
+ assert_equal(-1, sort_value(:desc))
104
103
  end
105
104
 
106
105
  def test_sort_value_when_value_is_uppercase_symbol_descending
107
- assert_equal -1, sort_value(:DESCENDING)
106
+ assert_equal(-1, sort_value(:DESCENDING))
108
107
  end
109
108
 
110
109
  def test_sort_value_when_value_is_uppercase_symbol_desc
111
- assert_equal -1, sort_value(:DESC)
110
+ assert_equal(-1, sort_value(:DESC))
112
111
  end
113
112
 
114
113
  def test_sort_value_when_value_is_invalid
@@ -1,7 +1,7 @@
1
1
  require './test/test_helper'
2
2
  require 'logger'
3
3
 
4
- class CursorTest < Test::Unit::TestCase
4
+ class CursorFailTest < Test::Unit::TestCase
5
5
 
6
6
  include Mongo
7
7
 
@@ -1,7 +1,7 @@
1
1
  require './test/test_helper'
2
2
  require 'logger'
3
3
 
4
- class CursorTest < Test::Unit::TestCase
4
+ class CursorMessageTest < Test::Unit::TestCase
5
5
 
6
6
  include Mongo
7
7
 
@@ -120,7 +120,7 @@ class CursorTest < Test::Unit::TestCase
120
120
  results = @@coll.find.sort([:n, :asc]).to_a
121
121
 
122
122
  assert_equal MinKey.new, results[0]['n']
123
- assert_equal -1000000, results[1]['n']
123
+ assert_equal(-1000000, results[1]['n'])
124
124
  assert_equal 1000000, results[2]['n']
125
125
  assert_equal MaxKey.new, results[3]['n']
126
126
  end
@@ -171,8 +171,8 @@ class CursorTest < Test::Unit::TestCase
171
171
  cursor = Cursor.new(@@coll, :timeout => false)
172
172
  assert_equal false, cursor.timeout
173
173
 
174
- @@coll.find({}, :timeout => false) do |cursor|
175
- assert_equal false, cursor.timeout
174
+ @@coll.find({}, :timeout => false) do |c|
175
+ assert_equal false, c.timeout
176
176
  end
177
177
  end
178
178
 
@@ -395,10 +395,13 @@ class CursorTest < Test::Unit::TestCase
395
395
  end
396
396
 
397
397
  cursor = @@coll.find
398
+ n = 0
398
399
  while cursor.has_next?
399
- assert cursor.next_document
400
+ assert cursor.next
401
+ n += 1
400
402
  end
401
403
 
404
+ assert_equal n, 200
402
405
  assert_equal false, cursor.has_next?
403
406
  end
404
407
 
@@ -451,4 +454,30 @@ class CursorTest < Test::Unit::TestCase
451
454
  assert_equal 100, cursor.map {|doc| doc }.length
452
455
  end
453
456
 
457
+ def test_transformer
458
+ transformer = Proc.new { |doc| doc }
459
+ cursor = Cursor.new(@@coll, :transformer => transformer)
460
+ assert_equal(transformer, cursor.transformer)
454
461
  end
462
+
463
+ def test_instance_transformation_with_next
464
+ klass = Struct.new(:id, :a)
465
+ transformer = Proc.new { |doc| klass.new(doc['_id'], doc['a']) }
466
+ cursor = Cursor.new(@@coll, :transformer => transformer)
467
+ instance = cursor.next
468
+
469
+ assert_instance_of(klass, instance)
470
+ assert_instance_of(BSON::ObjectId, instance.id)
471
+ assert_equal(1, instance.a)
472
+ end
473
+
474
+ def test_instance_transformation_with_each
475
+ klass = Struct.new(:id, :a)
476
+ transformer = Proc.new { |doc| klass.new(doc['_id'], doc['a']) }
477
+ cursor = Cursor.new(@@coll, :transformer => transformer)
478
+
479
+ cursor.each do |instance|
480
+ assert_instance_of(klass, instance)
481
+ end
482
+ end
483
+ end
@@ -239,7 +239,7 @@ class DBAPITest < Test::Unit::TestCase
239
239
  names = @@db.collection_names
240
240
  assert names.length >= 2
241
241
  assert names.include?(@@coll.name)
242
- assert names.include?('mongo-ruby-test.test2')
242
+ assert names.include?('test2')
243
243
  ensure
244
244
  @@db.drop_collection('test2')
245
245
  end
@@ -270,6 +270,17 @@ class DBAPITest < Test::Unit::TestCase
270
270
  end
271
271
  end
272
272
 
273
+ def test_collection_options_are_passed_to_the_existing_ones
274
+ @@db.drop_collection('foobar')
275
+
276
+ @@db.create_collection('foobar')
277
+
278
+ opts = {:safe => true}
279
+ coll = @@db.create_collection('foobar', opts)
280
+ assert_equal true, coll.safe
281
+ end
282
+
283
+
273
284
  def test_index_information
274
285
  assert_equal @@coll.index_information.length, 1
275
286
 
@@ -621,7 +632,7 @@ class DBAPITest < Test::Unit::TestCase
621
632
  assert_equal("mike", @@coll.find_one()["hello"])
622
633
  end
623
634
 
624
- def test_collection_names
635
+ def test_collection_names_errors
625
636
  assert_raise TypeError do
626
637
  @@db.collection(5)
627
638
  end
@@ -26,7 +26,7 @@ class DBTest < Test::Unit::TestCase
26
26
  @@db.collection('test').insert('a' => 1)
27
27
  fail "expected 'NilClass' exception"
28
28
  rescue => ex
29
- assert_match /NilClass/, ex.to_s
29
+ assert_match(/NilClass/, ex.to_s)
30
30
  ensure
31
31
  @@db = standard_connection.db(MONGO_TEST_DB)
32
32
  @@users = @@db.collection('system.users')
@@ -104,7 +104,7 @@ class DBTest < Test::Unit::TestCase
104
104
  db.pk_factory = Object.new
105
105
  fail "error: expected exception"
106
106
  rescue => ex
107
- assert_match /Cannot change/, ex.to_s
107
+ assert_match(/Cannot change/, ex.to_s)
108
108
  ensure
109
109
  conn.close
110
110
  end
@@ -280,7 +280,7 @@ class DBTest < Test::Unit::TestCase
280
280
  assert_not_nil doc
281
281
  result = doc['result']
282
282
  assert_not_nil result
283
- assert_match /firstExtent/, result
283
+ assert_match(/firstExtent/, result)
284
284
  end
285
285
 
286
286
  end