mongo 1.6.1 → 1.6.2

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 (49) hide show
  1. data/README.md +17 -16
  2. data/Rakefile +30 -24
  3. data/docs/HISTORY.md +10 -0
  4. data/docs/RELEASES.md +7 -0
  5. data/docs/REPLICA_SETS.md +2 -2
  6. data/docs/TUTORIAL.md +181 -84
  7. data/lib/mongo.rb +0 -3
  8. data/lib/mongo/collection.rb +1 -1
  9. data/lib/mongo/connection.rb +28 -20
  10. data/lib/mongo/db.rb +5 -3
  11. data/lib/mongo/exceptions.rb +1 -1
  12. data/lib/mongo/gridfs/grid_file_system.rb +1 -1
  13. data/lib/mongo/networking.rb +18 -18
  14. data/lib/mongo/repl_set_connection.rb +24 -3
  15. data/lib/mongo/util/node.rb +6 -16
  16. data/lib/mongo/util/pool.rb +8 -11
  17. data/lib/mongo/util/ssl_socket.rb +34 -12
  18. data/lib/mongo/util/tcp_socket.rb +92 -3
  19. data/lib/mongo/util/uri_parser.rb +2 -2
  20. data/lib/mongo/version.rb +1 -1
  21. data/test/auxillary/repl_set_auth_test.rb +19 -5
  22. data/test/bson/bson_test.rb +23 -21
  23. data/test/bson/json_test.rb +1 -1
  24. data/test/collection_test.rb +14 -4
  25. data/test/connection_test.rb +14 -11
  26. data/test/cursor_test.rb +4 -4
  27. data/test/grid_file_system_test.rb +3 -1
  28. data/test/grid_io_test.rb +2 -2
  29. data/test/grid_test.rb +13 -6
  30. data/test/pool_test.rb +0 -2
  31. data/test/replica_sets/basic_test.rb +1 -1
  32. data/test/replica_sets/complex_connect_test.rb +5 -4
  33. data/test/replica_sets/connect_test.rb +14 -6
  34. data/test/replica_sets/pooled_insert_test.rb +1 -1
  35. data/test/replica_sets/query_test.rb +2 -2
  36. data/test/replica_sets/read_preference_test.rb +1 -2
  37. data/test/replica_sets/refresh_test.rb +4 -2
  38. data/test/replica_sets/refresh_with_threads_test.rb +7 -13
  39. data/test/replica_sets/rs_test_helper.rb +1 -1
  40. data/test/test_helper.rb +6 -4
  41. data/test/threading/threading_with_large_pool_test.rb +1 -1
  42. data/test/threading_test.rb +2 -2
  43. data/test/timeout_test.rb +40 -0
  44. data/test/tools/repl_set_manager.rb +9 -8
  45. data/test/unit/connection_test.rb +6 -7
  46. data/test/unit/node_test.rb +1 -0
  47. data/test/unit/pool_manager_test.rb +2 -1
  48. data/test/uri_test.rb +1 -2
  49. metadata +13 -6
@@ -139,11 +139,11 @@ module Mongo
139
139
  if @connect == 'direct'
140
140
  opts[:slave_ok] = true
141
141
  else
142
- opts[:read_secondary] = true
142
+ opts[:read] = :secondary
143
143
  end
144
144
  end
145
145
 
146
- opts[:rs_name] = @replicaset if @replicaset
146
+ opts[:name] = @replicaset if @replicaset
147
147
 
148
148
  opts
149
149
  end
@@ -1,3 +1,3 @@
1
1
  module Mongo
2
- VERSION = "1.6.1"
2
+ VERSION = "1.6.2"
3
3
  end
@@ -1,21 +1,22 @@
1
1
  $:.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
2
2
  require './test/test_helper'
3
3
  require './test/tools/auth_repl_set_manager'
4
+ require './test/replica_sets/rs_test_helper'
4
5
 
5
6
  class AuthTest < Test::Unit::TestCase
6
7
  include Mongo
7
8
 
8
9
  def setup
9
- @manager = AuthReplSetManager.new(:start_port => 40000)
10
- @manager.start_set
10
+ @rs = AuthReplSetManager.new(:start_port => 40000)
11
+ @rs.start_set
11
12
  end
12
13
 
13
14
  def teardown
14
- @manager.cleanup_set
15
+ #@rs.cleanup_set
15
16
  end
16
17
 
17
18
  def test_repl_set_auth
18
- @conn = ReplSetConnection.new(build_seeds(3), :name => @manager.name)
19
+ @conn = ReplSetConnection.new(build_seeds(3), :name => @rs.name)
19
20
 
20
21
  # Add an admin user
21
22
  @conn['admin'].add_user("me", "secret")
@@ -51,7 +52,20 @@ class AuthTest < Test::Unit::TestCase
51
52
  end
52
53
 
53
54
  # But not when authenticated
54
- @slave1['admin'].authenticate("me", "secret")
55
+ assert @slave1['admin'].authenticate("me", "secret")
55
56
  assert @slave1['foo']['stuff'].find_one
57
+
58
+ # Same should apply when using :secondary_only
59
+ @second_only = ReplSetConnection.new(build_seeds(3),
60
+ :require_primary => false, :read => :secondary_only)
61
+
62
+ # Find should fail
63
+ assert_raise_error Mongo::OperationFailure, "unauthorized" do
64
+ @second_only['foo']['stuff'].find_one
65
+ end
66
+
67
+ # But not when authenticated
68
+ assert @second_only['admin'].authenticate("me", "secret")
69
+ assert @second_only['foo']['stuff'].find_one
56
70
  end
57
71
  end
@@ -3,19 +3,21 @@ require './test/bson/test_helper'
3
3
  require 'set'
4
4
 
5
5
  if RUBY_VERSION < '1.9'
6
- require 'complex'
7
- require 'rational'
6
+ silently do
7
+ require 'complex'
8
+ require 'rational'
9
+ end
8
10
  end
9
11
  require 'bigdecimal'
10
12
 
11
13
  begin
12
14
  require 'date'
13
15
  require 'tzinfo'
14
- require 'active_support/core_ext'
16
+ require 'active_support/timezone'
15
17
  Time.zone = "Pacific Time (US & Canada)"
16
18
  Zone = Time.zone.now
17
19
  rescue LoadError
18
- warn 'Mocking time with zone'
20
+ #warn 'Mocking time with zone'
19
21
  module ActiveSupport
20
22
  class TimeWithZone
21
23
  def initialize(utc_time, zone)
@@ -74,23 +76,21 @@ class BSONTest < Test::Unit::TestCase
74
76
  end
75
77
 
76
78
  def test_limit_max_bson_size
77
- doc = {'name' => 'a' * BSON_CODER.max_bson_size}
79
+ doc = {'name' => 'a' * BSON::DEFAULT_MAX_BSON_SIZE}
78
80
  assert_raise InvalidDocument do
79
81
  assert @encoder.serialize(doc)
80
82
  end
81
83
  end
82
84
 
83
- def test_max_bson_size
84
- assert BSON_CODER.max_bson_size >= BSON::DEFAULT_MAX_BSON_SIZE
85
- end
86
-
87
85
  def test_update_max_bson_size
88
86
  require 'ostruct'
89
87
  mock_conn = OpenStruct.new
90
88
  size = 7 * 1024 * 1024
91
89
  mock_conn.max_bson_size = size
92
- assert_equal size, BSON_CODER.update_max_bson_size(mock_conn)
93
- assert_equal size, BSON_CODER.max_bson_size
90
+ silently do
91
+ assert_equal size, BSON_CODER.update_max_bson_size(mock_conn)
92
+ assert_equal size, BSON_CODER.max_bson_size
93
+ end
94
94
  end
95
95
 
96
96
  def test_round_trip
@@ -217,10 +217,10 @@ class BSONTest < Test::Unit::TestCase
217
217
  doc = {'doc' => {'age' => 42, 'date' => Time.now.utc, 'shoe_size' => 9.5}}
218
218
  bson = @encoder.serialize(doc)
219
219
  doc2 = @encoder.deserialize(bson)
220
- assert doc['doc']
221
- assert_equal 42, doc['doc']['age']
222
- assert_equal 9.5, doc['doc']['shoe_size']
223
- assert_in_delta Time.now, doc['doc']['date'], 1
220
+ assert doc2['doc']
221
+ assert_equal 42, doc2['doc']['age']
222
+ assert_equal 9.5, doc2['doc']['shoe_size']
223
+ assert_in_delta Time.now, doc2['doc']['date'], 1
224
224
  end
225
225
 
226
226
  def test_oid
@@ -269,6 +269,7 @@ class BSONTest < Test::Unit::TestCase
269
269
  doc = {'date' => [Time.now.utc]}
270
270
  bson = @encoder.serialize(doc)
271
271
  doc2 = @encoder.deserialize(bson)
272
+ assert doc2
272
273
  end
273
274
 
274
275
  def test_date_returns_as_utc
@@ -279,6 +280,7 @@ class BSONTest < Test::Unit::TestCase
279
280
  end
280
281
 
281
282
  def test_date_before_epoch
283
+ if RbConfig::CONFIG['host_os'] =~ /mswin|mingw|cygwin/ then return true end
282
284
  begin
283
285
  doc = {'date' => Time.utc(1600)}
284
286
  bson = @encoder.serialize(doc)
@@ -297,7 +299,7 @@ class BSONTest < Test::Unit::TestCase
297
299
  [DateTime.now, Date.today, Zone].each do |invalid_date|
298
300
  doc = {:date => invalid_date}
299
301
  begin
300
- bson = BSON::BSON_CODER.serialize(doc)
302
+ BSON::BSON_CODER.serialize(doc)
301
303
  rescue => e
302
304
  ensure
303
305
  if !invalid_date.is_a? Time
@@ -431,7 +433,7 @@ class BSONTest < Test::Unit::TestCase
431
433
 
432
434
  if !(RUBY_PLATFORM =~ /java/)
433
435
  def test_timestamp
434
- val = {"test" => [4, 20]}
436
+ # val = {"test" => [4, 20]}
435
437
  result = @encoder.deserialize([0x13, 0x00, 0x00, 0x00,
436
438
  0x11, 0x74, 0x65, 0x73,
437
439
  0x74, 0x00, 0x04, 0x00,
@@ -455,7 +457,7 @@ class BSONTest < Test::Unit::TestCase
455
457
  def test_overflow
456
458
  doc = {"x" => 2**75}
457
459
  assert_raise RangeError do
458
- bson = @encoder.serialize(doc)
460
+ @encoder.serialize(doc)
459
461
  end
460
462
 
461
463
  doc = {"x" => 9223372036854775}
@@ -466,7 +468,7 @@ class BSONTest < Test::Unit::TestCase
466
468
 
467
469
  doc["x"] = doc["x"] + 1
468
470
  assert_raise RangeError do
469
- bson = @encoder.serialize(doc)
471
+ @encoder.serialize(doc)
470
472
  end
471
473
 
472
474
  doc = {"x" => -9223372036854775}
@@ -477,7 +479,7 @@ class BSONTest < Test::Unit::TestCase
477
479
 
478
480
  doc["x"] = doc["x"] - 1
479
481
  assert_raise RangeError do
480
- bson = BSON::BSON_CODER.serialize(doc)
482
+ BSON::BSON_CODER.serialize(doc)
481
483
  end
482
484
  end
483
485
 
@@ -529,7 +531,7 @@ class BSONTest < Test::Unit::TestCase
529
531
  #one = {"_foo" => "foo"}
530
532
 
531
533
  #assert_equal @encoder.serialize(one).to_a, @encoder.serialize(dup).to_a
532
- warn "Pending test for duplicate keys"
534
+ #warn "Pending test for duplicate keys"
533
535
  end
534
536
 
535
537
  def test_no_duplicate_id_when_moving_id
@@ -7,7 +7,7 @@ class JSONTest < Test::Unit::TestCase
7
7
  # This test passes when run by itself but fails
8
8
  # when run as part of the whole test suite.
9
9
  def test_object_id_as_json
10
- warn "Pending test object id as json"
10
+ #warn "Pending test object id as json"
11
11
  #id = BSON::ObjectId.new
12
12
 
13
13
  #obj = {'_id' => id}
@@ -1,4 +1,5 @@
1
1
  require './test/test_helper'
2
+ require 'rbconfig'
2
3
 
3
4
  class TestCollection < Test::Unit::TestCase
4
5
  @@connection ||= standard_connection(:op_timeout => 10)
@@ -42,8 +43,10 @@ class TestCollection < Test::Unit::TestCase
42
43
  end
43
44
 
44
45
  def test_pk_factory_on_collection
45
- @coll = Collection.new('foo', @@db, TestPK)
46
- assert_equal TestPK, @coll.pk_factory
46
+ silently do
47
+ @coll = Collection.new('foo', @@db, TestPK)
48
+ assert_equal TestPK, @coll.pk_factory
49
+ end
47
50
 
48
51
 
49
52
  @coll2 = Collection.new('foo', @@db, :pk => TestPK)
@@ -197,6 +200,7 @@ class TestCollection < Test::Unit::TestCase
197
200
  docs << {:bar => 1}
198
201
  doc_ids, error_docs = @@test.insert(docs, :collect_on_error => true)
199
202
  assert_equal 2, @@test.count
203
+ assert_equal 2, doc_ids.count
200
204
  assert_equal error_docs, []
201
205
  end
202
206
 
@@ -215,16 +219,20 @@ class TestCollection < Test::Unit::TestCase
215
219
 
216
220
  doc_ids, error_docs = @@test.insert(docs, :collect_on_error => true)
217
221
  assert_equal 2, @@test.count
222
+ assert_equal 2, doc_ids.count
218
223
  assert_equal error_docs, invalid_docs
219
224
  end
220
225
 
221
226
  def test_bson_invalid_encoding_serialize_error_with_collect_on_error
227
+ # Broken for current JRuby
228
+ if RUBY_PLATFORM == 'java' then return end
222
229
  docs = []
223
230
  docs << {:foo => 1}
224
231
  docs << {:bar => 1}
225
232
  invalid_docs = []
226
- invalid_docs << {"\223\372\226{" => 1} # non utf8 encoding
227
- docs += invalid_docs
233
+ invalid_docs << {"\223\372\226}" => 1} # non utf8 encoding
234
+ docs += invalid_docs
235
+
228
236
  assert_raise BSON::InvalidStringEncoding do
229
237
  @@test.insert(docs, :collect_on_error => false)
230
238
  end
@@ -232,6 +240,7 @@ class TestCollection < Test::Unit::TestCase
232
240
 
233
241
  doc_ids, error_docs = @@test.insert(docs, :collect_on_error => true)
234
242
  assert_equal 2, @@test.count
243
+ assert_equal 2, doc_ids.count
235
244
  assert_equal error_docs, invalid_docs
236
245
  end
237
246
 
@@ -652,6 +661,7 @@ class TestCollection < Test::Unit::TestCase
652
661
  end
653
662
 
654
663
  def test_saving_dates_pre_epoch
664
+ if RbConfig::CONFIG['host_os'] =~ /mswin|mingw|cygwin/ then return true end
655
665
  begin
656
666
  @@test.save({'date' => Time.utc(1600)})
657
667
  assert_in_delta Time.utc(1600), @@test.find_one()["date"], 2
@@ -133,7 +133,7 @@ class TestConnection < Test::Unit::TestCase
133
133
  output = StringIO.new
134
134
  logger = Logger.new(output)
135
135
  logger.level = Logger::DEBUG
136
- connection = standard_connection(:logger => logger).db(MONGO_TEST_DB)
136
+ standard_connection(:logger => logger).db(MONGO_TEST_DB)
137
137
  assert output.string.include?("admin['$cmd'].find")
138
138
  end
139
139
 
@@ -141,8 +141,8 @@ class TestConnection < Test::Unit::TestCase
141
141
  output = StringIO.new
142
142
  logger = Logger.new(output)
143
143
  logger.level = Logger::DEBUG
144
- connection = standard_connection(:logger => logger).db(MONGO_TEST_DB)
145
- assert_match /\(\d+ms\)/, output.string
144
+ standard_connection(:logger => logger).db(MONGO_TEST_DB)
145
+ assert_match(/\(\d+ms\)/, output.string)
146
146
  assert output.string.include?("admin['$cmd'].find")
147
147
  end
148
148
 
@@ -170,11 +170,13 @@ class TestConnection < Test::Unit::TestCase
170
170
  end
171
171
 
172
172
  def test_nodes
173
- conn = Connection.multi([['foo', 27017], ['bar', 27018]], :connect => false)
174
- nodes = conn.nodes
175
- assert_equal 2, nodes.length
176
- assert_equal ['foo', 27017], nodes[0]
177
- assert_equal ['bar', 27018], nodes[1]
173
+ silently do
174
+ @conn = Connection.multi([['foo', 27017], ['bar', 27018]], :connect => false)
175
+ end
176
+ seeds = @conn.seeds
177
+ assert_equal 2, seeds.length
178
+ assert_equal ['foo', 27017], seeds[0]
179
+ assert_equal ['bar', 27018], seeds[1]
178
180
  end
179
181
 
180
182
  def test_fsync_lock
@@ -227,7 +229,7 @@ class TestConnection < Test::Unit::TestCase
227
229
  conn.expects(:[]).with('admin').returns(admin_db)
228
230
 
229
231
  conn.connect
230
- assert_equal Mongo::DEFAULT_MAX_BSON_SIZE, BSON::BSON_CODER.max_bson_size
232
+ assert_equal Mongo::DEFAULT_MAX_BSON_SIZE, conn.max_bson_size
231
233
  end
232
234
 
233
235
  def test_connection_activity
@@ -290,7 +292,7 @@ class TestConnection < Test::Unit::TestCase
290
292
  context "Socket pools" do
291
293
  context "checking out writers" do
292
294
  setup do
293
- @con = standard_connection(:pool_size => 10, :timeout => 10)
295
+ @con = standard_connection(:pool_size => 10, :pool_timeout => 10)
294
296
  @coll = @con[MONGO_TEST_DB]['test-connection-exceptions']
295
297
  end
296
298
 
@@ -325,7 +327,7 @@ class TestConnection < Test::Unit::TestCase
325
327
 
326
328
  context "Connection exceptions" do
327
329
  setup do
328
- @con = standard_connection(:pool_size => 10, :timeout => 10)
330
+ @con = standard_connection(:pool_size => 10, :pool_timeout => 10)
329
331
  @coll = @con[MONGO_TEST_DB]['test-connection-exceptions']
330
332
  end
331
333
 
@@ -363,6 +365,7 @@ class TestConnection < Test::Unit::TestCase
363
365
  TCPSocket.stubs(:new).returns(fake_socket)
364
366
 
365
367
  @con.primary_pool.checkout_new_socket
368
+ @con.primary_pool.expects(:warn)
366
369
  assert @con.primary_pool.close
367
370
  end
368
371
  end
@@ -238,17 +238,17 @@ class CursorTest < Test::Unit::TestCase
238
238
  end
239
239
 
240
240
  def test_timeout
241
- opts = Cursor.new(@@coll).query_opts
241
+ opts = Cursor.new(@@coll).options
242
242
  assert_equal 0, opts & Mongo::Constants::OP_QUERY_NO_CURSOR_TIMEOUT
243
243
 
244
- opts = Cursor.new(@@coll, :timeout => false).query_opts
244
+ opts = Cursor.new(@@coll, :timeout => false).options
245
245
  assert_equal Mongo::Constants::OP_QUERY_NO_CURSOR_TIMEOUT,
246
246
  opts & Mongo::Constants::OP_QUERY_NO_CURSOR_TIMEOUT
247
247
  end
248
248
 
249
249
  def test_limit_exceptions
250
250
  cursor = @@coll.find()
251
- firstResult = cursor.next_document
251
+ cursor.next_document
252
252
  assert_raise InvalidOperation, "Cannot modify the query once it has been run or closed." do
253
253
  cursor.limit(1)
254
254
  end
@@ -278,7 +278,7 @@ class CursorTest < Test::Unit::TestCase
278
278
 
279
279
  def test_skip_exceptions
280
280
  cursor = @@coll.find()
281
- firstResult = cursor.next_document
281
+ cursor.next_document
282
282
  assert_raise InvalidOperation, "Cannot modify the query once it has been run or closed." do
283
283
  cursor.skip(1)
284
284
  end
@@ -263,7 +263,9 @@ class GridFileSystemTest < Test::Unit::TestCase
263
263
 
264
264
  should "seek only in read mode" do
265
265
  assert_raise GridError do
266
- @grid.open('hello', 'w') {|f| f.seek(0) }
266
+ silently do
267
+ @grid.open('hello', 'w') { |f| f.seek(0) }
268
+ end
267
269
  end
268
270
  end
269
271
  end
@@ -45,7 +45,7 @@ class GridIOTest < Test::Unit::TestCase
45
45
  should "read data character by character using" do
46
46
  bytes = 0
47
47
  file = GridIO.new(@files, @chunks, nil, "r", :query => {:_id => @file.files_id})
48
- while char = file.getc
48
+ while file.getc
49
49
  bytes += 1
50
50
  end
51
51
  assert_equal bytes, 1_000_000
@@ -111,7 +111,7 @@ class GridIOTest < Test::Unit::TestCase
111
111
 
112
112
  should "tell position, eof, and rewind" do
113
113
  file = GridIO.new(@files, @chunks, nil, "r", :query => {:_id => @file.files_id})
114
- string = file.read(1000)
114
+ file.read(1000)
115
115
  assert_equal 1000, file.pos
116
116
  assert !file.eof?
117
117
  file.read
@@ -2,7 +2,7 @@ require './test/test_helper'
2
2
  include Mongo
3
3
 
4
4
  def read_and_write_stream(filename, read_length, opts={})
5
- io = File.open(File.join(File.dirname(__FILE__), 'data', filename), 'r')
5
+ io = File.open(File.join(File.dirname(__FILE__), 'data', filename), 'r+b')
6
6
  id = @grid.put(io, opts.merge!(:filename => filename + read_length.to_s))
7
7
  file = @grid.get(id)
8
8
  io.rewind
@@ -142,7 +142,9 @@ class GridTest < Test::Unit::TestCase
142
142
  end
143
143
 
144
144
  should "ignore special keys" do
145
- id = @grid.put(@data, :file_length => 100, :phrase => "blimey")
145
+ id = silently do
146
+ @grid.put(@data, :file_length => 100, :phrase => "blimey")
147
+ end
146
148
  file = @grid.get(id)
147
149
 
148
150
  assert_equal "blimey", file['phrase']
@@ -153,8 +155,9 @@ class GridTest < Test::Unit::TestCase
153
155
  context "Storing data with a length of zero" do
154
156
  setup do
155
157
  @grid = Grid.new(@db, 'test-fs')
156
- @id = @grid.put('', :filename => 'sample',
157
- :metadata => {'app' => 'photos'})
158
+ @id = silently do
159
+ @grid.put('', :filename => 'sample', :metadata => {'app' => 'photos'})
160
+ end
158
161
  end
159
162
 
160
163
  should "return the zero length" do
@@ -201,7 +204,9 @@ class GridTest < Test::Unit::TestCase
201
204
  @grid = Grid.new(@db, 'test-fs')
202
205
  filename = 'empty_data'
203
206
  @io = File.open(File.join(File.dirname(__FILE__), 'data', filename), 'r')
204
- id = @grid.put(@io, :filename => filename)
207
+ id = silently do
208
+ @grid.put(@io, :filename => filename)
209
+ end
205
210
  @file = @grid.get(id)
206
211
  @io.rewind
207
212
  @data = @io.read
@@ -239,7 +244,9 @@ class GridTest < Test::Unit::TestCase
239
244
  end
240
245
 
241
246
  should "put and get an empty io object" do
242
- read_and_write_stream('empty_data', 1)
247
+ silently do
248
+ read_and_write_stream('empty_data', 1)
249
+ end
243
250
  end
244
251
 
245
252
  should "put and get a small io object" do