mongo 1.9.2 → 1.10.0.rc0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (113) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data.tar.gz.sig +0 -0
  4. data/LICENSE +1 -1
  5. data/README.md +94 -334
  6. data/Rakefile +6 -4
  7. data/VERSION +1 -1
  8. data/bin/mongo_console +13 -6
  9. data/lib/mongo.rb +22 -27
  10. data/lib/mongo/bulk_write_collection_view.rb +352 -0
  11. data/lib/mongo/collection.rb +128 -188
  12. data/lib/mongo/collection_writer.rb +348 -0
  13. data/lib/mongo/connection.rb +19 -0
  14. data/lib/mongo/{util → connection}/node.rb +15 -1
  15. data/lib/mongo/{util → connection}/pool.rb +34 -19
  16. data/lib/mongo/{util → connection}/pool_manager.rb +8 -2
  17. data/lib/mongo/{util → connection}/sharding_pool_manager.rb +1 -1
  18. data/lib/mongo/connection/socket.rb +18 -0
  19. data/lib/mongo/{util → connection/socket}/socket_util.rb +5 -2
  20. data/lib/mongo/{util → connection/socket}/ssl_socket.rb +3 -4
  21. data/lib/mongo/{util → connection/socket}/tcp_socket.rb +25 -15
  22. data/lib/mongo/{util → connection/socket}/unix_socket.rb +6 -4
  23. data/lib/mongo/cursor.rb +113 -47
  24. data/lib/mongo/db.rb +203 -131
  25. data/lib/mongo/{exceptions.rb → exception.rb} +7 -1
  26. data/lib/mongo/functional.rb +19 -0
  27. data/lib/mongo/functional/authentication.rb +303 -0
  28. data/lib/mongo/{util → functional}/logging.rb +1 -1
  29. data/lib/mongo/{util → functional}/read_preference.rb +49 -1
  30. data/lib/mongo/{util → functional}/uri_parser.rb +81 -69
  31. data/lib/mongo/{util → functional}/write_concern.rb +2 -1
  32. data/{test/unit/pool_test.rb → lib/mongo/gridfs.rb} +5 -10
  33. data/lib/mongo/gridfs/grid.rb +1 -3
  34. data/lib/mongo/gridfs/grid_ext.rb +1 -1
  35. data/lib/mongo/gridfs/grid_file_system.rb +1 -1
  36. data/lib/mongo/gridfs/grid_io.rb +1 -1
  37. data/lib/mongo/legacy.rb +63 -8
  38. data/lib/mongo/mongo_client.rb +128 -154
  39. data/lib/mongo/mongo_replica_set_client.rb +17 -11
  40. data/lib/mongo/mongo_sharded_client.rb +2 -1
  41. data/lib/mongo/networking.rb +19 -10
  42. data/lib/mongo/utils.rb +19 -0
  43. data/lib/mongo/{util → utils}/conversions.rb +1 -1
  44. data/lib/mongo/{util → utils}/core_ext.rb +1 -1
  45. data/lib/mongo/{util → utils}/server_version.rb +1 -1
  46. data/lib/mongo/{util → utils}/support.rb +10 -57
  47. data/lib/mongo/{util → utils}/thread_local_variable_manager.rb +1 -1
  48. data/test/functional/authentication_test.rb +8 -21
  49. data/test/functional/bulk_write_collection_view_test.rb +782 -0
  50. data/test/functional/{connection_test.rb → client_test.rb} +153 -78
  51. data/test/functional/collection_test.rb +343 -97
  52. data/test/functional/collection_writer_test.rb +83 -0
  53. data/test/functional/conversions_test.rb +1 -3
  54. data/test/functional/cursor_fail_test.rb +3 -3
  55. data/test/functional/cursor_message_test.rb +3 -3
  56. data/test/functional/cursor_test.rb +38 -3
  57. data/test/functional/db_api_test.rb +5 -5
  58. data/test/functional/db_connection_test.rb +2 -2
  59. data/test/functional/db_test.rb +35 -11
  60. data/test/functional/grid_file_system_test.rb +2 -2
  61. data/test/functional/grid_io_test.rb +2 -2
  62. data/test/functional/grid_test.rb +2 -2
  63. data/test/functional/pool_test.rb +2 -3
  64. data/test/functional/safe_test.rb +5 -5
  65. data/test/functional/ssl_test.rb +22 -102
  66. data/test/functional/support_test.rb +1 -1
  67. data/test/functional/timeout_test.rb +6 -22
  68. data/test/functional/uri_test.rb +113 -12
  69. data/test/functional/write_concern_test.rb +6 -6
  70. data/test/helpers/general.rb +50 -0
  71. data/test/helpers/test_unit.rb +309 -0
  72. data/test/replica_set/authentication_test.rb +8 -23
  73. data/test/replica_set/basic_test.rb +41 -14
  74. data/test/replica_set/client_test.rb +179 -117
  75. data/test/replica_set/complex_connect_test.rb +6 -7
  76. data/test/replica_set/connection_test.rb +46 -38
  77. data/test/replica_set/count_test.rb +2 -2
  78. data/test/replica_set/cursor_test.rb +8 -8
  79. data/test/replica_set/insert_test.rb +64 -2
  80. data/test/replica_set/max_values_test.rb +59 -10
  81. data/test/replica_set/pinning_test.rb +2 -2
  82. data/test/replica_set/query_test.rb +2 -2
  83. data/test/replica_set/read_preference_test.rb +6 -6
  84. data/test/replica_set/refresh_test.rb +7 -7
  85. data/test/replica_set/replication_ack_test.rb +5 -5
  86. data/test/replica_set/ssl_test.rb +24 -106
  87. data/test/sharded_cluster/basic_test.rb +43 -15
  88. data/test/shared/authentication/basic_auth_shared.rb +215 -0
  89. data/test/shared/authentication/sasl_plain_shared.rb +96 -0
  90. data/test/shared/ssl_shared.rb +173 -0
  91. data/test/test_helper.rb +31 -199
  92. data/test/threading/basic_test.rb +29 -3
  93. data/test/tools/mongo_config.rb +45 -20
  94. data/test/tools/mongo_config_test.rb +1 -1
  95. data/test/unit/client_test.rb +136 -57
  96. data/test/unit/collection_test.rb +31 -55
  97. data/test/unit/connection_test.rb +135 -72
  98. data/test/unit/cursor_test.rb +2 -2
  99. data/test/unit/db_test.rb +19 -15
  100. data/test/unit/grid_test.rb +2 -2
  101. data/test/unit/mongo_sharded_client_test.rb +17 -15
  102. data/test/unit/node_test.rb +2 -2
  103. data/test/unit/pool_manager_test.rb +7 -5
  104. data/test/unit/read_pref_test.rb +82 -2
  105. data/test/unit/read_test.rb +14 -14
  106. data/test/unit/safe_test.rb +9 -9
  107. data/test/unit/sharding_pool_manager_test.rb +11 -5
  108. data/test/unit/write_concern_test.rb +9 -9
  109. metadata +71 -56
  110. metadata.gz.sig +0 -0
  111. data/test/functional/threading_test.rb +0 -109
  112. data/test/shared/authentication.rb +0 -121
  113. data/test/unit/util_test.rb +0 -69
@@ -1,4 +1,4 @@
1
- # Copyright (C) 2013 10gen Inc.
1
+ # Copyright (C) 2009-2013 MongoDB, Inc.
2
2
  #
3
3
  # Licensed under the Apache License, Version 2.0 (the "License");
4
4
  # you may not use this file except in compliance with the License.
@@ -69,7 +69,7 @@ class ReplicaSetRefreshTest < Test::Unit::TestCase
69
69
 
70
70
  old_refresh_version = client.refresh_version
71
71
  # Trigger synchronous refresh
72
- client['foo']['bar'].find_one
72
+ client[TEST_DB]['rs-refresh-test'].find_one
73
73
 
74
74
  assert client.connected?
75
75
  assert client.refresh_version > old_refresh_version
@@ -83,7 +83,7 @@ class ReplicaSetRefreshTest < Test::Unit::TestCase
83
83
 
84
84
  old_refresh_version = client.refresh_version
85
85
  # Trigger synchronous refresh
86
- client['foo']['bar'].find_one
86
+ client[TEST_DB]['rs-refresh-test'].find_one
87
87
 
88
88
  assert client.connected?
89
89
  assert client.refresh_version > old_refresh_version,
@@ -103,7 +103,7 @@ class ReplicaSetRefreshTest < Test::Unit::TestCase
103
103
  threads << Thread.new do
104
104
  # force a connection failure every couple of threads that causes a refresh
105
105
  if i % factor == 0
106
- cursor = client['foo']['bar'].find
106
+ cursor = client[TEST_DB]['rs-refresh-test'].find
107
107
  cursor.stubs(:checkout_socket_from_connection).raises(ConnectionFailure)
108
108
  begin
109
109
  cursor.next
@@ -113,7 +113,7 @@ class ReplicaSetRefreshTest < Test::Unit::TestCase
113
113
  end
114
114
  else
115
115
  # synchronous refreshes will happen every couple of find_ones
116
- cursor = client['foo']['bar'].find_one
116
+ cursor = client[TEST_DB]['rs-refresh-test'].find_one
117
117
  end
118
118
  end
119
119
  end
@@ -135,7 +135,7 @@ class ReplicaSetRefreshTest < Test::Unit::TestCase
135
135
  sleep(2)
136
136
 
137
137
  rescue_connection_failure do
138
- client['foo']['bar'].find_one
138
+ client[TEST_DB]['rs-refresh-test'].find_one
139
139
  end
140
140
 
141
141
  assert client.refresh_version > old_refresh_version,
@@ -152,7 +152,7 @@ class ReplicaSetRefreshTest < Test::Unit::TestCase
152
152
 
153
153
  @rs.add_node
154
154
  sleep(4)
155
- client['foo']['bar'].find_one
155
+ client[TEST_DB]['rs-refresh-test'].find_one
156
156
 
157
157
  @conn2 = MongoReplicaSetClient.new(build_seeds(3),
158
158
  :refresh_interval => 2, :refresh_mode => :sync)
@@ -1,4 +1,4 @@
1
- # Copyright (C) 2013 10gen Inc.
1
+ # Copyright (C) 2009-2013 MongoDB, Inc.
2
2
  #
3
3
  # Licensed under the Apache License, Version 2.0 (the "License");
4
4
  # you may not use this file except in compliance with the License.
@@ -26,7 +26,7 @@ class ReplicaSetAckTest < Test::Unit::TestCase
26
26
 
27
27
  assert !@slave1.read_primary?
28
28
 
29
- @db = @client.db(MONGO_TEST_DB)
29
+ @db = @client.db(TEST_DB)
30
30
  @db.drop_collection("test-sets")
31
31
  @col = @db.collection("test-sets")
32
32
  end
@@ -54,17 +54,17 @@ class ReplicaSetAckTest < Test::Unit::TestCase
54
54
  @col.insert({:baz => "bar"}, :w => 3, :wtimeout => 5000)
55
55
 
56
56
  assert @col.insert({:foo => "0" * 5000}, :w => 3, :wtimeout => 5000)
57
- assert_equal 2, @slave1[MONGO_TEST_DB]["test-sets"].count
57
+ assert_equal 2, @slave1[TEST_DB]["test-sets"].count
58
58
 
59
59
  assert @col.update({:baz => "bar"}, {:baz => "foo"}, :w => 3, :wtimeout => 5000)
60
- assert @slave1[MONGO_TEST_DB]["test-sets"].find_one({:baz => "foo"})
60
+ assert @slave1[TEST_DB]["test-sets"].find_one({:baz => "foo"})
61
61
 
62
62
  assert @col.insert({:foo => "bar"}, :w => "majority")
63
63
 
64
64
  assert @col.insert({:bar => "baz"}, :w => :majority)
65
65
 
66
66
  assert @col.remove({}, :w => 3, :wtimeout => 5000)
67
- assert_equal 0, @slave1[MONGO_TEST_DB]["test-sets"].count
67
+ assert_equal 0, @slave1[TEST_DB]["test-sets"].count
68
68
  end
69
69
 
70
70
  def test_last_error_responses
@@ -1,114 +1,32 @@
1
- require 'test_helper'
1
+ # Copyright (C) 2009-2013 MongoDB, Inc.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
2
14
 
3
- # Note: For testing with MongoReplicaSetClient you *MUST* use the
4
- # hostname 'server' for all members of the replica set.
15
+ require 'test_helper'
16
+ require 'shared/ssl_shared'
5
17
 
6
- class ReplicaSetSSLCertValidationTest < Test::Unit::TestCase
18
+ class ReplicaSetSSLTest < Test::Unit::TestCase
7
19
  include Mongo
20
+ include SSLTests
8
21
 
9
- CERT_PATH = "#{Dir.pwd}/test/fixtures/certificates/"
10
- CLIENT_CERT = "#{CERT_PATH}client.pem"
11
- CA_CERT = "#{CERT_PATH}ca.pem"
12
- SEEDS = ['server:3000','server:3001','server:3002']
13
- BAD_SEEDS = ['localhost:3000','localhost:3001','localhost:3002']
14
-
15
- # This test doesn't connect, no server config required
16
- def test_ssl_configuration
17
- # raises when ssl=false and ssl opts specified
18
- assert_raise MongoArgumentError do
19
- MongoReplicaSetClient.new(SEEDS, :connect => false,
20
- :ssl => false,
21
- :ssl_cert => CLIENT_CERT)
22
- end
23
-
24
- # raises when ssl=nil and ssl opts specified
25
- assert_raise MongoArgumentError do
26
- MongoReplicaSetClient.new(SEEDS, :connect => false,
27
- :ssl_key => CLIENT_CERT)
28
- end
29
-
30
- # raises when verify=true and no ca_cert
31
- assert_raise MongoArgumentError do
32
- MongoReplicaSetClient.new(SEEDS, :connect => false,
33
- :ssl => true,
34
- :ssl_key => CLIENT_CERT,
35
- :ssl_cert => CLIENT_CERT,
36
- :ssl_verify => true)
37
- end
38
- end
39
-
40
- # Requires MongoDB built with SSL and the follow options:
41
- #
42
- # mongod --dbpath /path/to/data/directory --sslOnNormalPorts \
43
- # --sslPEMKeyFile /path/to/server.pem \
44
- # --sslCAFile /path/to/ca.pem \
45
- # --sslCRLFile /path/to/crl.pem \
46
- # --sslWeakCertificateValidation
47
- #
48
- # Make sure you have 'server' as an alias for localhost in /etc/hosts
49
- #
50
- def test_ssl_basic
51
- client = MongoReplicaSetClient.new(SEEDS, :connect => false,
52
- :ssl => true)
53
- assert client.connect
54
- end
55
-
56
- # Requires MongoDB built with SSL and the follow options:
57
- #
58
- # mongod --dbpath /path/to/data/directory --sslOnNormalPorts \
59
- # --sslPEMKeyFile /path/to/server.pem \
60
- # --sslCAFile /path/to/ca.pem \
61
- # --sslCRLFile /path/to/crl.pem
62
- #
63
- # Make sure you have 'server' as an alias for localhost in /etc/hosts
64
- #
65
- def test_ssl_with_cert
66
- client = MongoReplicaSetClient.new(SEEDS, :connect => false,
67
- :ssl => true,
68
- :ssl_cert => CLIENT_CERT,
69
- :ssl_key => CLIENT_CERT)
70
- assert client.connect
71
- end
72
-
73
- def test_ssl_with_peer_cert_validation
74
- client = MongoReplicaSetClient.new(SEEDS, :connect => false,
75
- :ssl => true,
76
- :ssl_key => CLIENT_CERT,
77
- :ssl_cert => CLIENT_CERT,
78
- :ssl_verify => true,
79
- :ssl_ca_cert => CA_CERT)
80
- assert client.connect
81
- end
82
-
83
- def test_ssl_peer_cert_validation_hostname_fail
84
- client = MongoReplicaSetClient.new(BAD_SEEDS, :connect => false,
85
- :ssl => true,
86
- :ssl_key => CLIENT_CERT,
87
- :ssl_cert => CLIENT_CERT,
88
- :ssl_verify => true,
89
- :ssl_ca_cert => CA_CERT)
90
- assert_raise ConnectionFailure do
91
- client.connect
92
- end
93
- end
22
+ SEEDS = ['server:3000','server:3001','server:3002']
23
+ BAD_SEEDS = ['localhost:3000','localhost:3001','localhost:3002']
94
24
 
95
- # Requires mongod built with SSL and the follow options:
96
- #
97
- # mongod --dbpath /path/to/data/directory --sslOnNormalPorts \
98
- # --sslPEMKeyFile /path/to/server.pem \
99
- # --sslCAFile /path/to/ca.pem \
100
- # --sslCRLFile /path/to/crl_client_revoked.pem
101
- #
102
- # Make sure you have 'server' as an alias for localhost in /etc/hosts
103
- #
104
- def test_ssl_with_invalid_cert
105
- assert_raise ConnectionFailure do
106
- MongoReplicaSetClient.new(SEEDS, :ssl => true,
107
- :ssl_key => CLIENT_CERT,
108
- :ssl_cert => CLIENT_CERT,
109
- :ssl_verify => true,
110
- :ssl_ca_cert => CA_CERT)
111
- end
25
+ def setup
26
+ @client_class = MongoReplicaSetClient
27
+ @uri_info = SEEDS.join(',')
28
+ @connect_info = SEEDS
29
+ @bad_connect_info = BAD_SEEDS
112
30
  end
113
31
 
114
32
  end
@@ -1,4 +1,4 @@
1
- # Copyright (C) 2013 10gen Inc.
1
+ # Copyright (C) 2009-2013 MongoDB, Inc.
2
2
  #
3
3
  # Licensed under the Apache License, Version 2.0 (the "License");
4
4
  # you may not use this file except in compliance with the License.
@@ -19,12 +19,12 @@ class Cursor
19
19
  public :construct_query_spec
20
20
  end
21
21
 
22
- class BasicTest < Test::Unit::TestCase
22
+ class ShardedClusterBasicTest < Test::Unit::TestCase
23
23
 
24
24
  def setup
25
25
  ensure_cluster(:sc)
26
26
  @document = { "name" => "test_user" }
27
- @seeds = @sc.mongos_seeds
27
+ @seeds = @sc.mongos_seeds
28
28
  end
29
29
 
30
30
  # TODO member.primary? ==> true
@@ -49,39 +49,39 @@ class BasicTest < Test::Unit::TestCase
49
49
  tags = [{:dc => "mongolia"}]
50
50
  @client = MongoClient.new(host, port, {:read => :secondary, :tag_sets => tags})
51
51
  assert @client.connected?
52
- cursor = Cursor.new(@client[MONGO_TEST_DB]['whatever'], {})
52
+ cursor = Cursor.new(@client[TEST_DB]['whatever'], {})
53
53
  assert_equal cursor.construct_query_spec['$readPreference'], {:mode => 'secondary', :tags => tags}
54
54
  end
55
55
 
56
56
  def test_find_one_with_read_secondary
57
57
  @client = MongoShardedClient.new(@seeds, { :read => :secondary })
58
- @client[MONGO_TEST_DB]["users"].insert([ @document ])
59
- assert_equal @client[MONGO_TEST_DB]['users'].find_one["name"], "test_user"
58
+ @client[TEST_DB]["users"].insert([ @document ])
59
+ assert_equal @client[TEST_DB]['users'].find_one["name"], "test_user"
60
60
  end
61
61
 
62
62
  def test_find_one_with_read_secondary_preferred
63
63
  @client = MongoShardedClient.new(@seeds, { :read => :secondary_preferred })
64
- @client[MONGO_TEST_DB]["users"].insert([ @document ])
65
- assert_equal @client[MONGO_TEST_DB]['users'].find_one["name"], "test_user"
64
+ @client[TEST_DB]["users"].insert([ @document ])
65
+ assert_equal @client[TEST_DB]['users'].find_one["name"], "test_user"
66
66
  end
67
67
 
68
68
  def test_find_one_with_read_primary
69
69
  @client = MongoShardedClient.new(@seeds, { :read => :primary })
70
- @client[MONGO_TEST_DB]["users"].insert([ @document ])
71
- assert_equal @client[MONGO_TEST_DB]['users'].find_one["name"], "test_user"
70
+ @client[TEST_DB]["users"].insert([ @document ])
71
+ assert_equal @client[TEST_DB]['users'].find_one["name"], "test_user"
72
72
  end
73
73
 
74
74
  def test_find_one_with_read_primary_preferred
75
75
  @client = MongoShardedClient.new(@seeds, { :read => :primary_preferred })
76
- @client[MONGO_TEST_DB]["users"].insert([ @document ])
77
- assert_equal @client[MONGO_TEST_DB]['users'].find_one["name"], "test_user"
76
+ @client[TEST_DB]["users"].insert([ @document ])
77
+ assert_equal @client[TEST_DB]['users'].find_one["name"], "test_user"
78
78
  end
79
79
 
80
80
  def test_read_from_sharded_client
81
81
  tags = [{:dc => "mongolia"}]
82
82
  @client = MongoShardedClient.new(@seeds, {:read => :secondary, :tag_sets => tags})
83
83
  assert @client.connected?
84
- cursor = Cursor.new(@client[MONGO_TEST_DB]['whatever'], {})
84
+ cursor = Cursor.new(@client[TEST_DB]['whatever'], {})
85
85
  assert_equal cursor.construct_query_spec['$readPreference'], {:mode => 'secondary', :tags => tags}
86
86
  end
87
87
 
@@ -107,13 +107,13 @@ class BasicTest < Test::Unit::TestCase
107
107
  @client = MongoShardedClient.new(@seeds, :refresh_interval => 5, :refresh_mode => :sync)
108
108
  assert @client.connected?
109
109
  # do a find to pin a pool
110
- @client['MONGO_TEST_DB']['test'].find_one
110
+ @client[TEST_DB]['test'].find_one
111
111
  original_primary = @client.manager.primary
112
112
  # stop the pinned member
113
113
  @sc.member_by_name("#{original_primary[0]}:#{original_primary[1]}").stop
114
114
  # assert that the client fails over to the next available mongos
115
115
  assert_nothing_raised do
116
- @client['MONGO_TEST_DB']['test'].find_one
116
+ @client[TEST_DB]['test'].find_one
117
117
  end
118
118
 
119
119
  assert_not_equal original_primary, @client.manager.primary
@@ -161,6 +161,34 @@ class BasicTest < Test::Unit::TestCase
161
161
  @client.close
162
162
  end
163
163
 
164
+ def test_wire_version_not_in_range
165
+ [
166
+ [Mongo::MongoClient::MAX_WIRE_VERSION+1, Mongo::MongoClient::MAX_WIRE_VERSION+1],
167
+ [Mongo::MongoClient::MIN_WIRE_VERSION-1, Mongo::MongoClient::MIN_WIRE_VERSION-1]
168
+ ].each do |min_wire_version_value, max_wire_version_value|
169
+ Mongo.module_eval <<-EVAL
170
+ class ShardingPoolManager
171
+ def max_wire_version
172
+ return #{max_wire_version_value}
173
+ end
174
+ def min_wire_version
175
+ return #{min_wire_version_value}
176
+ end
177
+ end
178
+ EVAL
179
+ @client = MongoShardedClient.new(@seeds, :connect => false)
180
+ assert !@client.connected?
181
+ assert_raises Mongo::ConnectionFailure do
182
+ @client.connect
183
+ end
184
+ end
185
+ Mongo.module_eval <<-EVAL
186
+ class ShardingPoolManager
187
+ attr_reader :max_wire_version, :min_wire_version
188
+ end
189
+ EVAL
190
+ end
191
+
164
192
  private
165
193
 
166
194
  def probe(size)
@@ -0,0 +1,215 @@
1
+ # Copyright (C) 2009-2013 MongoDB, Inc.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ module BasicAuthTests
16
+
17
+ def init_auth
18
+ # enable authentication by creating and logging in as admin user
19
+ @admin = @client['admin']
20
+ @admin.add_user('admin', 'password', nil, :roles => ['readAnyDatabase',
21
+ 'readWriteAnyDatabase',
22
+ 'userAdminAnyDatabase',
23
+ 'dbAdminAnyDatabase',
24
+ 'clusterAdmin'])
25
+ @admin.authenticate('admin', 'password')
26
+
27
+ # db user for cleanup (for pre-2.4)
28
+ @db.add_user('admin', 'cleanup', nil, :roles => [])
29
+ end
30
+
31
+ def teardown
32
+ remove_all_users(@db, 'admin', 'cleanup')
33
+ remove_all_users(@admin, 'admin', 'password') if has_auth?(@admin.name)
34
+ end
35
+
36
+ def remove_all_users(database, username, password)
37
+ database.authenticate(username, password) unless has_auth?(database.name)
38
+ if @client.server_version < '2.5'
39
+ database['system.users'].remove
40
+ else
41
+ database.command(:dropAllUsersFromDatabase => 1)
42
+ end
43
+ database.logout
44
+ end
45
+
46
+ def has_auth?(db_name)
47
+ @client.auths.any? { |a| a[:source] == db_name }
48
+ end
49
+
50
+ def test_add_remove_user
51
+ # add user
52
+ silently { @db.add_user('bob','user') }
53
+ assert @db.authenticate('bob', 'user')
54
+
55
+ # remove user
56
+ assert @db.remove_user('bob')
57
+ end
58
+
59
+ def test_update_user
60
+ # add user
61
+ silently { @db.add_user('bob', 'user') }
62
+ assert @db.authenticate('bob', 'user')
63
+ @db.logout
64
+
65
+ # update user
66
+ silently { @db.add_user('bob', 'updated') }
67
+ assert_raise Mongo::AuthenticationError do
68
+ @db.authenticate('bob', 'user')
69
+ end
70
+ assert @db.authenticate('bob', 'updated')
71
+ end
72
+
73
+ def test_remove_non_existent_user
74
+ if @client.server_version < '2.5'
75
+ assert_equal false, @db.remove_user('joe')
76
+ else
77
+ assert_raise Mongo::OperationFailure do
78
+ assert @db.remove_user('joe')
79
+ end
80
+ end
81
+ end
82
+
83
+ def test_authenticate
84
+ silently { @db.add_user('peggy', 'user') }
85
+ assert @db.authenticate('peggy', 'user')
86
+ @db.remove_user('peggy')
87
+ end
88
+
89
+ def test_authenticate_non_existent_user
90
+ assert_raise Mongo::AuthenticationError do
91
+ @db.authenticate('frank', 'thetank')
92
+ end
93
+ end
94
+
95
+ def test_logout
96
+ silently { @db.add_user('peggy', 'user') }
97
+ assert @db.authenticate('peggy', 'user')
98
+ assert @db.logout
99
+ end
100
+
101
+ def test_authenticate_with_special_characters
102
+ silently { assert @db.add_user('foo:bar','@foo') }
103
+ assert @db.authenticate('foo:bar','@foo')
104
+ end
105
+
106
+ def test_authenticate_read_only
107
+ silently { @db.add_user('randy', 'readonly', true) }
108
+ assert @db.authenticate('randy', 'readonly')
109
+ end
110
+
111
+ def test_authenticate_with_connection_uri
112
+ silently { @db.add_user('eunice', 'uritest') }
113
+
114
+ uri = "mongodb://eunice:uritest@#{@host_info}/#{@db.name}"
115
+ client = Mongo::URIParser.new(uri).connection
116
+
117
+ assert client
118
+ assert_equal client.auths.size, 1
119
+ assert client[TEST_DB]['auth_test'].count
120
+
121
+ auth = client.auths.first
122
+ assert_equal @db.name, auth[:db_name]
123
+ assert_equal 'eunice', auth[:username]
124
+ assert_equal 'uritest', auth[:password]
125
+ end
126
+
127
+ def test_socket_auths
128
+ # setup
129
+ db_a = @client[TEST_DB + '_a']
130
+ silently { db_a.add_user('user_a', 'password') }
131
+ assert db_a.authenticate('user_a', 'password')
132
+
133
+ db_b = @client[TEST_DB + '_b']
134
+ silently { db_b.add_user('user_b', 'password') }
135
+ assert db_b.authenticate('user_b', 'password')
136
+
137
+ db_c = @client[TEST_DB + '_c']
138
+ silently { db_c.add_user('user_c', 'password') }
139
+ assert db_c.authenticate('user_c', 'password')
140
+
141
+ # client auths should be applied to socket on checkout
142
+ socket = @client.checkout_reader(:mode => :primary)
143
+ assert_equal 4, socket.auths.size
144
+ assert_equal @client.auths, socket.auths
145
+ @client.checkin(socket)
146
+
147
+ # logout should remove saved auth on socket and client
148
+ assert db_b.logout
149
+ socket = @client.checkout_reader(:mode => :primary)
150
+ assert_equal 3, socket.auths.size
151
+ assert_equal @client.auths, socket.auths
152
+ @client.checkin(socket)
153
+
154
+ # clean-up
155
+ db_b.authenticate('user_b', 'password')
156
+ remove_all_users(db_a, 'user_a', 'password')
157
+ remove_all_users(db_b, 'user_b', 'password')
158
+ remove_all_users(db_c, 'user_c', 'password')
159
+ end
160
+
161
+ def test_delegated_authentication
162
+ return unless @client.server_version >= '2.4' && @client.server_version < '2.5'
163
+
164
+ # create user in test databases
165
+ accounts = @client[TEST_DB + '_accounts']
166
+ silently do
167
+ accounts.add_user('debbie', 'delegate')
168
+ @db.add_user('debbie', nil, nil, :roles => ['read'], :userSource => accounts.name)
169
+ end
170
+ @admin.logout
171
+
172
+ # validate that direct authentication is not allowed
173
+ assert_raise Mongo::AuthenticationError do
174
+ @db.authenticate('debbie', 'delegate')
175
+ end
176
+
177
+ # validate delegated authentication
178
+ assert accounts.authenticate('debbie', 'delegate')
179
+ assert @db.collection_names
180
+ accounts.logout
181
+ assert_raise Mongo::OperationFailure do
182
+ @db.collection_names
183
+ end
184
+
185
+ # validate auth using source database
186
+ @db.authenticate('debbie', 'delegate', nil, accounts.name)
187
+ assert @db.collection_names
188
+ accounts.logout
189
+ assert_raise Mongo::OperationFailure do
190
+ @db.collection_names
191
+ end
192
+
193
+ # clean-up
194
+ @admin.authenticate('admin', 'password')
195
+ remove_all_users(accounts, 'debbie', 'delegate')
196
+ end
197
+
198
+ def test_non_admin_default_roles
199
+ return if @client.server_version < '2.5'
200
+
201
+ # add read-only user and verify that role is 'read'
202
+ @db.add_user('randy', 'password', nil, :roles => ['read'])
203
+ @db.authenticate('randy', 'password')
204
+ users = @db.command(:usersInfo => 'randy')['users']
205
+ assert_equal 'read', users.first['roles'].first['role']
206
+ @db.logout
207
+
208
+ # add dbOwner (default) user and verify role
209
+ silently { @db.add_user('emily', 'password') }
210
+ @db.authenticate('emily', 'password')
211
+ users = @db.command(:usersInfo => 'emily')['users']
212
+ assert_equal 'dbOwner', users.first['roles'].first['role']
213
+ end
214
+
215
+ end