mongo-lyon 1.2.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (87) hide show
  1. data/LICENSE.txt +190 -0
  2. data/README.md +344 -0
  3. data/Rakefile +202 -0
  4. data/bin/mongo_console +34 -0
  5. data/docs/1.0_UPGRADE.md +21 -0
  6. data/docs/CREDITS.md +123 -0
  7. data/docs/FAQ.md +116 -0
  8. data/docs/GridFS.md +158 -0
  9. data/docs/HISTORY.md +225 -0
  10. data/docs/REPLICA_SETS.md +72 -0
  11. data/docs/TUTORIAL.md +247 -0
  12. data/docs/WRITE_CONCERN.md +28 -0
  13. data/lib/mongo.rb +77 -0
  14. data/lib/mongo/collection.rb +872 -0
  15. data/lib/mongo/connection.rb +875 -0
  16. data/lib/mongo/cursor.rb +449 -0
  17. data/lib/mongo/db.rb +607 -0
  18. data/lib/mongo/exceptions.rb +68 -0
  19. data/lib/mongo/gridfs/grid.rb +106 -0
  20. data/lib/mongo/gridfs/grid_ext.rb +57 -0
  21. data/lib/mongo/gridfs/grid_file_system.rb +145 -0
  22. data/lib/mongo/gridfs/grid_io.rb +394 -0
  23. data/lib/mongo/gridfs/grid_io_fix.rb +38 -0
  24. data/lib/mongo/repl_set_connection.rb +342 -0
  25. data/lib/mongo/util/conversions.rb +89 -0
  26. data/lib/mongo/util/core_ext.rb +60 -0
  27. data/lib/mongo/util/pool.rb +185 -0
  28. data/lib/mongo/util/server_version.rb +71 -0
  29. data/lib/mongo/util/support.rb +82 -0
  30. data/lib/mongo/util/uri_parser.rb +181 -0
  31. data/lib/mongo/version.rb +3 -0
  32. data/mongo.gemspec +34 -0
  33. data/test/auxillary/1.4_features.rb +166 -0
  34. data/test/auxillary/authentication_test.rb +68 -0
  35. data/test/auxillary/autoreconnect_test.rb +41 -0
  36. data/test/auxillary/repl_set_auth_test.rb +58 -0
  37. data/test/auxillary/slave_connection_test.rb +36 -0
  38. data/test/auxillary/threaded_authentication_test.rb +101 -0
  39. data/test/bson/binary_test.rb +15 -0
  40. data/test/bson/bson_test.rb +614 -0
  41. data/test/bson/byte_buffer_test.rb +190 -0
  42. data/test/bson/hash_with_indifferent_access_test.rb +38 -0
  43. data/test/bson/json_test.rb +17 -0
  44. data/test/bson/object_id_test.rb +154 -0
  45. data/test/bson/ordered_hash_test.rb +197 -0
  46. data/test/collection_test.rb +893 -0
  47. data/test/connection_test.rb +303 -0
  48. data/test/conversions_test.rb +120 -0
  49. data/test/cursor_fail_test.rb +75 -0
  50. data/test/cursor_message_test.rb +43 -0
  51. data/test/cursor_test.rb +457 -0
  52. data/test/db_api_test.rb +715 -0
  53. data/test/db_connection_test.rb +15 -0
  54. data/test/db_test.rb +287 -0
  55. data/test/grid_file_system_test.rb +244 -0
  56. data/test/grid_io_test.rb +120 -0
  57. data/test/grid_test.rb +200 -0
  58. data/test/load/thin/load.rb +24 -0
  59. data/test/load/unicorn/load.rb +23 -0
  60. data/test/replica_sets/connect_test.rb +86 -0
  61. data/test/replica_sets/connection_string_test.rb +32 -0
  62. data/test/replica_sets/count_test.rb +35 -0
  63. data/test/replica_sets/insert_test.rb +53 -0
  64. data/test/replica_sets/pooled_insert_test.rb +55 -0
  65. data/test/replica_sets/query_secondaries.rb +96 -0
  66. data/test/replica_sets/query_test.rb +51 -0
  67. data/test/replica_sets/replication_ack_test.rb +66 -0
  68. data/test/replica_sets/rs_test_helper.rb +27 -0
  69. data/test/safe_test.rb +68 -0
  70. data/test/support/hash_with_indifferent_access.rb +199 -0
  71. data/test/support/keys.rb +45 -0
  72. data/test/support_test.rb +19 -0
  73. data/test/test_helper.rb +83 -0
  74. data/test/threading/threading_with_large_pool_test.rb +90 -0
  75. data/test/threading_test.rb +87 -0
  76. data/test/tools/auth_repl_set_manager.rb +14 -0
  77. data/test/tools/repl_set_manager.rb +266 -0
  78. data/test/unit/collection_test.rb +130 -0
  79. data/test/unit/connection_test.rb +98 -0
  80. data/test/unit/cursor_test.rb +99 -0
  81. data/test/unit/db_test.rb +96 -0
  82. data/test/unit/grid_test.rb +49 -0
  83. data/test/unit/pool_test.rb +9 -0
  84. data/test/unit/repl_set_connection_test.rb +72 -0
  85. data/test/unit/safe_test.rb +125 -0
  86. data/test/uri_test.rb +91 -0
  87. metadata +202 -0
@@ -0,0 +1,3 @@
1
+ module Mongo
2
+ VERSION = "1.2.4"
3
+ end
data/mongo.gemspec ADDED
@@ -0,0 +1,34 @@
1
+ require "./lib/mongo/version"
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = 'mongo-lyon'
5
+
6
+ s.version = Mongo::VERSION
7
+
8
+ s.platform = Gem::Platform::RUBY
9
+ s.summary = 'Ruby driver for the MongoDB'
10
+ s.description = 'A Ruby driver for MongoDB. For more information about Mongo, see http://www.mongodb.org.'
11
+
12
+ s.require_paths = ['lib']
13
+
14
+ s.files = ['README.md', 'Rakefile', 'mongo.gemspec', 'LICENSE.txt']
15
+ s.files += ['lib/mongo.rb'] + Dir['lib/mongo/**/*.rb']
16
+ s.files += Dir['docs/**/*.md'] + Dir['examples/**/*.rb'] + Dir['bin/**/*.rb']
17
+ s.files += Dir['bin/mongo_console']
18
+ s.test_files = Dir['test/**/*.rb']
19
+
20
+ s.executables = ['mongo_console']
21
+
22
+ s.has_rdoc = true
23
+ s.test_files = Dir['test/**/*.rb']
24
+
25
+ s.has_rdoc = true
26
+ s.rdoc_options = ['--main', 'README.md', '--inline-source']
27
+ s.extra_rdoc_files = ['README.md']
28
+
29
+ s.authors = ['Jim Menard', 'Mike Dirolf', 'Kyle Banker']
30
+ s.email = 'mongodb-dev@googlegroups.com'
31
+ s.homepage = 'http://www.mongodb.org'
32
+
33
+ s.add_dependency(%q<bson>, [">= #{Mongo::VERSION}"])
34
+ end
@@ -0,0 +1,166 @@
1
+ $:.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
2
+ require 'mongo'
3
+ require 'test/unit'
4
+ require './test/test_helper'
5
+
6
+ # Demonstrate features in MongoDB 1.4
7
+ class Features14Test < Test::Unit::TestCase
8
+
9
+ context "MongoDB 1.4" do
10
+ setup do
11
+ @con = Mongo::Connection.new
12
+ @db = @con['mongo-ruby-test']
13
+ @col = @db['new-features']
14
+ end
15
+
16
+ teardown do
17
+ @col.drop
18
+ end
19
+
20
+ context "new query operators: " do
21
+
22
+ context "$elemMatch: " do
23
+ setup do
24
+ @col.save({:user => 'bob', :updates => [{:date => Time.now.utc, :body => 'skiing', :n => 1},
25
+ {:date => Time.now.utc, :body => 'biking', :n => 2}]})
26
+
27
+ @col.save({:user => 'joe', :updates => [{:date => Time.now.utc, :body => 'skiing', :n => 2},
28
+ {:date => Time.now.utc, :body => 'biking', :n => 10}]})
29
+ end
30
+
31
+ should "match a document with a matching object element in an array" do
32
+ doc = @col.find_one({"updates" => {"$elemMatch" => {"body" => "skiing", "n" => 2}}})
33
+ assert_equal 'joe', doc['user']
34
+ end
35
+
36
+ should "$elemMatch with a conditional operator" do
37
+ doc1 = @col.find_one({"updates" => {"$elemMatch" => {"body" => "biking", "n" => {"$gt" => 5}}}})
38
+ assert_equal 'joe', doc1['user']
39
+ end
40
+
41
+ should "note the difference between $elemMatch and a traditional match" do
42
+ doc = @col.find({"updates.body" => "skiing", "updates.n" => 2}).to_a
43
+ assert_equal 2, doc.size
44
+ end
45
+ end
46
+
47
+ context "$all with regexes" do
48
+ setup do
49
+ @col.save({:n => 1, :a => 'whale'})
50
+ @col.save({:n => 2, :a => 'snake'})
51
+ end
52
+
53
+ should "match multiple regexes" do
54
+ doc = @col.find({:a => {'$all' => [/ha/, /le/]}}).to_a
55
+ assert_equal 1, doc.size
56
+ assert_equal 1, doc.first['n']
57
+ end
58
+
59
+ should "not match if not every regex matches" do
60
+ doc = @col.find({:a => {'$all' => [/ha/, /sn/]}}).to_a
61
+ assert_equal 0, doc.size
62
+ end
63
+ end
64
+
65
+ context "the $not operator" do
66
+ setup do
67
+ @col.save({:a => ['x']})
68
+ @col.save({:a => ['x', 'y']})
69
+ @col.save({:a => ['x', 'y', 'z']})
70
+ end
71
+
72
+ should "negate a standard operator" do
73
+ results = @col.find({:a => {'$not' => {'$size' => 2}}}).to_a
74
+ assert_equal 2, results.size
75
+ results = results.map {|r| r['a']}
76
+ assert_equal ['x'], results.sort.first
77
+ assert_equal ['x', 'y', 'z'], results.sort.last
78
+ end
79
+ end
80
+ end
81
+
82
+ context "new update operators: " do
83
+
84
+ context "$addToSet (pushing a unique value)" do
85
+ setup do
86
+ @col.save({:username => 'bob', :interests => ['skiing', 'guitar']})
87
+ end
88
+
89
+ should "add an item to a set uniquely ($addToSet)" do
90
+ @col.update({:username => 'bob'}, {'$addToSet' => {'interests' => 'skiing'}})
91
+ @col.update({:username => 'bob'}, {'$addToSet' => {'interests' => 'kayaking'}})
92
+ document = @col.find_one({:username => 'bob'})
93
+ assert_equal ['guitar', 'kayaking', 'skiing'], document['interests'].sort
94
+ end
95
+
96
+ should "add an array of items uniquely ($addToSet with $each)" do
97
+ @col.update({:username => 'bob'}, {'$addToSet' => {'interests' => {'$each' => ['skiing', 'kayaking', 'biking']}}})
98
+ document = @col.find_one({:username => 'bob'})
99
+ assert_equal ['biking', 'guitar', 'kayaking', 'skiing'], document['interests'].sort
100
+ end
101
+ end
102
+
103
+ context "the positional operator ($)" do
104
+ setup do
105
+ @id1 = @col.insert({:text => 'hello',
106
+ :comments => [{'by' => 'bob',
107
+ 'text' => 'lol!'},
108
+ {'by' => 'susie',
109
+ 'text' => 'bye bye!'}]})
110
+ @id2 = @col.insert({:text => 'goodbye',
111
+ :comments => [{'by' => 'bob',
112
+ 'text' => 'au revoir'},
113
+ {'by' => 'susie',
114
+ 'text' => 'bye bye!'}]})
115
+ end
116
+
117
+ should "update a matching array item" do
118
+ @col.update({"_id" => @id1, "comments.by" => 'bob'}, {'$set' => {'comments.$.text' => 'lmao!'}}, :multi => true)
119
+ result = @col.find_one({"_id" => @id1})
120
+ assert_equal 'lmao!', result['comments'][0]['text']
121
+ end
122
+ end
123
+ end
124
+
125
+ context "Geoindexing" do
126
+ setup do
127
+ @places = @db['places']
128
+ @places.create_index([['loc', Mongo::GEO2D]])
129
+
130
+ @empire_state = ([40.748371, -73.985031])
131
+ @jfk = ([40.643711, -73.790009])
132
+
133
+ @places.insert({'name' => 'Empire State Building', 'loc' => ([40.748371, -73.985031])})
134
+ @places.insert({'name' => 'Flatiron Building', 'loc' => ([40.741581, -73.987549])})
135
+ @places.insert({'name' => 'Grand Central', 'loc' => ([40.751678, -73.976562])})
136
+ @places.insert({'name' => 'Columbia University', 'loc' => ([40.808922, -73.961617])})
137
+ @places.insert({'name' => 'NYSE', 'loc' => ([40.71455, -74.007124])})
138
+ @places.insert({'name' => 'JFK', 'loc' => ([40.643711, -73.790009])})
139
+ end
140
+
141
+ teardown do
142
+ @places.drop
143
+ end
144
+
145
+ should "find the nearest addresses" do
146
+ results = @places.find({'loc' => {'$near' => @empire_state}}).limit(2).to_a
147
+ assert_equal 2, results.size
148
+ assert_equal 'Empire State Building', results[0]['name']
149
+ assert_equal 'Flatiron Building', results[1]['name']
150
+ end
151
+
152
+ should "use geoNear command to return distances from a point" do
153
+ cmd = BSON::OrderedHash.new
154
+ cmd['geoNear'] = 'places'
155
+ cmd['near'] = @empire_state
156
+ cmd['num'] = 6
157
+ r = @db.command(cmd)
158
+
159
+ assert_equal 6, r['results'].length
160
+ r['results'].each do |result|
161
+ puts result.inspect
162
+ end
163
+ end
164
+ end
165
+ end
166
+ end
@@ -0,0 +1,68 @@
1
+ $:.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
2
+ require 'mongo'
3
+ require 'test/unit'
4
+ require './test/test_helper'
5
+
6
+ # NOTE: This test requires bouncing the server.
7
+ # It also requires that a user exists on the admin database.
8
+ class AuthenticationTest < Test::Unit::TestCase
9
+ include Mongo
10
+
11
+ def setup
12
+ @conn = Mongo::Connection.new
13
+ @db1 = @conn.db('mongo-ruby-test-auth1')
14
+ @db2 = @conn.db('mongo-ruby-test-auth2')
15
+ @admin = @conn.db('admin')
16
+ end
17
+
18
+ def teardown
19
+ @db1.authenticate('user1', 'secret')
20
+ @db2.authenticate('user2', 'secret')
21
+ @conn.drop_database('mongo-ruby-test-auth1')
22
+ @conn.drop_database('mongo-ruby-test-auth2')
23
+ end
24
+
25
+ def test_authenticate
26
+ @admin.authenticate('bob', 'secret')
27
+ @db1.add_user('user1', 'secret')
28
+ @db2.add_user('user2', 'secret')
29
+ @admin.logout
30
+
31
+ assert_raise Mongo::OperationFailure do
32
+ @db1['stuff'].insert({:a => 2}, :safe => true)
33
+ end
34
+
35
+ assert_raise Mongo::OperationFailure do
36
+ @db2['stuff'].insert({:a => 2}, :safe => true)
37
+ end
38
+
39
+ @db1.authenticate('user1', 'secret')
40
+ @db2.authenticate('user2', 'secret')
41
+
42
+ assert @db1['stuff'].insert({:a => 2}, :safe => true)
43
+ assert @db2['stuff'].insert({:a => 2}, :safe => true)
44
+
45
+ puts "Please bounce the server."
46
+ gets
47
+
48
+ # Here we reconnect.
49
+ begin
50
+ @db1['stuff'].find.to_a
51
+ rescue Mongo::ConnectionFailure
52
+ end
53
+
54
+ assert @db1['stuff'].insert({:a => 2}, :safe => true)
55
+ assert @db2['stuff'].insert({:a => 2}, :safe => true)
56
+
57
+ @db1.logout
58
+ assert_raise Mongo::OperationFailure do
59
+ @db1['stuff'].insert({:a => 2}, :safe => true)
60
+ end
61
+
62
+ @db2.logout
63
+ assert_raise Mongo::OperationFailure do
64
+ assert @db2['stuff'].insert({:a => 2}, :safe => true)
65
+ end
66
+ end
67
+
68
+ end
@@ -0,0 +1,41 @@
1
+ $:.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
2
+ require 'mongo'
3
+ require 'test/unit'
4
+ require './test/test_helper'
5
+
6
+ # NOTE: This test requires bouncing the server
7
+ class AutoreconnectTest < Test::Unit::TestCase
8
+ include Mongo
9
+
10
+ def setup
11
+ @conn = Mongo::Connection.new
12
+ @db = @conn.db('mongo-ruby-test')
13
+ @db.drop_collection("test-connect")
14
+ @coll = @db.collection("test-connect")
15
+ end
16
+
17
+ def test_query
18
+ @coll.save({:a => 20})
19
+ @coll.save({:a => 30})
20
+ @coll.save({:a => 40})
21
+ results = []
22
+ @coll.find.each {|r| results << r}
23
+ [20, 30, 40].each do |a|
24
+ assert results.any? {|r| r['a'] == a}, "Could not find record for a => #{a}"
25
+ end
26
+
27
+ puts "Please disconnect and then reconnect the current master."
28
+ gets
29
+
30
+ begin
31
+ @coll.find.to_a
32
+ rescue Mongo::ConnectionFailure
33
+ end
34
+
35
+ results = []
36
+ @coll.find.each {|r| results << r}
37
+ [20, 30, 40].each do |a|
38
+ assert results.any? {|r| r['a'] == a}, "Could not find record for a => #{a}"
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,58 @@
1
+ $:.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
2
+ require './test/test_helper'
3
+ require './test/tools/auth_repl_set_manager'
4
+
5
+ class AuthTest < Test::Unit::TestCase
6
+ include Mongo
7
+
8
+ def setup
9
+ @manager = AuthReplSetManager.new(:start_port => 40000)
10
+ @manager.start_set
11
+ end
12
+
13
+ def teardown
14
+ @manager.cleanup_set
15
+ end
16
+
17
+ def test_repl_set_auth
18
+ @conn = ReplSetConnection.new([@manager.host, @manager.ports[0]], [@manager.host, @manager.ports[1]],
19
+ [@manager.host, @manager.ports[2]], :name => @manager.name)
20
+
21
+ # Add an admin user
22
+ @conn['admin'].add_user("me", "secret")
23
+
24
+ # Ensure that insert fails
25
+ assert_raise_error Mongo::OperationFailure, "unauthorized" do
26
+ @conn['foo']['stuff'].insert({:a => 2}, :safe => {:w => 3})
27
+ end
28
+
29
+ # Then authenticate
30
+ assert @conn['admin'].authenticate("me", "secret")
31
+
32
+ # Insert should succeed now
33
+ assert @conn['foo']['stuff'].insert({:a => 2}, :safe => {:w => 3})
34
+
35
+ # So should a query
36
+ assert @conn['foo']['stuff'].find_one
37
+
38
+ # But not when we logout
39
+ @conn['admin'].logout
40
+
41
+ assert_raise_error Mongo::OperationFailure, "unauthorized" do
42
+ @conn['foo']['stuff'].find_one
43
+ end
44
+
45
+ # Same should apply to a random secondary
46
+ @slave1 = Connection.new(@conn.secondary_pools[0].host,
47
+ @conn.secondary_pools[0].port, :slave_ok => true)
48
+
49
+ # Find should fail
50
+ assert_raise_error Mongo::OperationFailure, "unauthorized" do
51
+ @slave1['foo']['stuff'].find_one
52
+ end
53
+
54
+ # But not when authenticated
55
+ @slave1['admin'].authenticate("me", "secret")
56
+ assert @slave1['foo']['stuff'].find_one
57
+ end
58
+ end
@@ -0,0 +1,36 @@
1
+ require './test/test_helper'
2
+
3
+ # NOTE: these tests are run only if we can connect to a single MongoDB in slave mode.
4
+ class SlaveConnectionTest < Test::Unit::TestCase
5
+ include Mongo
6
+
7
+ def self.connect_to_slave
8
+ @@host = ENV['MONGO_RUBY_DRIVER_HOST'] || 'localhost'
9
+ @@port = ENV['MONGO_RUBY_DRIVER_PORT'] || Connection::DEFAULT_PORT
10
+ conn = Connection.new(@@host, @@port, :slave_ok => true)
11
+ response = conn['admin'].command(:ismaster => 1)
12
+ Mongo::Support.ok?(response) && response['ismaster'] != 1
13
+ end
14
+
15
+ if self.connect_to_slave
16
+ puts "Connected to slave; running slave tests."
17
+
18
+ def test_connect_to_slave
19
+ assert_raise Mongo::ConnectionFailure do
20
+ @db = Connection.new(@@host, @@port, :slave_ok => false).db('ruby-mongo-demo')
21
+ end
22
+ end
23
+
24
+ def test_slave_ok_sent_to_queries
25
+ @con = Connection.new(@@host, @@port, :slave_ok => true)
26
+ assert_equal true, @con.slave_ok?
27
+ end
28
+ else
29
+ puts "Not connected to slave; skipping slave connection tests."
30
+
31
+ def test_slave_ok_false_on_queries
32
+ @conn = Connection.new(@@host, @@port)
33
+ assert !@conn.slave_ok?
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,101 @@
1
+ $:.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
2
+ require 'mongo'
3
+ require 'thread'
4
+ require 'test/unit'
5
+ require './test/test_helper'
6
+
7
+ # NOTE: This test requires bouncing the server.
8
+ # It also requires that a user exists on the admin database.
9
+ class AuthenticationTest < Test::Unit::TestCase
10
+ include Mongo
11
+
12
+ def setup
13
+ @conn = standard_connection(:pool_size => 10)
14
+ @db1 = @conn.db('mongo-ruby-test-auth1')
15
+ @db2 = @conn.db('mongo-ruby-test-auth2')
16
+ @admin = @conn.db('admin')
17
+ end
18
+
19
+ def teardown
20
+ @db1.authenticate('user1', 'secret')
21
+ @db2.authenticate('user2', 'secret')
22
+ @conn.drop_database('mongo-ruby-test-auth1')
23
+ @conn.drop_database('mongo-ruby-test-auth2')
24
+ end
25
+
26
+ def threaded_exec
27
+ threads = []
28
+
29
+ 100.times do
30
+ threads << Thread.new do
31
+ yield
32
+ end
33
+ end
34
+
35
+ 100.times do |n|
36
+ threads[n].join
37
+ end
38
+ end
39
+
40
+ def test_authenticate
41
+ @admin.authenticate('bob', 'secret')
42
+ @db1.add_user('user1', 'secret')
43
+ @db2.add_user('user2', 'secret')
44
+ @admin.logout
45
+
46
+ threaded_exec do
47
+ assert_raise Mongo::OperationFailure do
48
+ @db1['stuff'].insert({:a => 2}, :safe => true)
49
+ end
50
+ end
51
+
52
+ threaded_exec do
53
+ assert_raise Mongo::OperationFailure do
54
+ @db2['stuff'].insert({:a => 2}, :safe => true)
55
+ end
56
+ end
57
+
58
+ @db1.authenticate('user1', 'secret')
59
+ @db2.authenticate('user2', 'secret')
60
+
61
+ threaded_exec do
62
+ assert @db1['stuff'].insert({:a => 2}, :safe => true)
63
+ end
64
+
65
+ threaded_exec do
66
+ assert @db2['stuff'].insert({:a => 2}, :safe => true)
67
+ end
68
+
69
+ puts "Please bounce the server."
70
+ gets
71
+
72
+ # Here we reconnect.
73
+ begin
74
+ @db1['stuff'].find.to_a
75
+ rescue Mongo::ConnectionFailure
76
+ end
77
+
78
+ threaded_exec do
79
+ assert @db1['stuff'].insert({:a => 2}, :safe => true)
80
+ end
81
+
82
+ threaded_exec do
83
+ assert @db2['stuff'].insert({:a => 2}, :safe => true)
84
+ end
85
+
86
+ @db1.logout
87
+ threaded_exec do
88
+ assert_raise Mongo::OperationFailure do
89
+ @db1['stuff'].insert({:a => 2}, :safe => true)
90
+ end
91
+ end
92
+
93
+ @db2.logout
94
+ threaded_exec do
95
+ assert_raise Mongo::OperationFailure do
96
+ assert @db2['stuff'].insert({:a => 2}, :safe => true)
97
+ end
98
+ end
99
+ end
100
+
101
+ end