mongo 1.3.0 → 1.12.5

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 (185) hide show
  1. checksums.yaml +7 -0
  2. checksums.yaml.gz.sig +0 -0
  3. data/{LICENSE.txt → LICENSE} +1 -1
  4. data/README.md +122 -271
  5. data/Rakefile +25 -209
  6. data/VERSION +1 -0
  7. data/bin/mongo_console +31 -9
  8. data/lib/mongo/bulk_write_collection_view.rb +387 -0
  9. data/lib/mongo/collection.rb +576 -269
  10. data/lib/mongo/collection_writer.rb +364 -0
  11. data/lib/mongo/connection/node.rb +249 -0
  12. data/lib/mongo/connection/pool.rb +340 -0
  13. data/lib/mongo/connection/pool_manager.rb +320 -0
  14. data/lib/mongo/connection/sharding_pool_manager.rb +67 -0
  15. data/lib/mongo/connection/socket/socket_util.rb +37 -0
  16. data/lib/mongo/connection/socket/ssl_socket.rb +95 -0
  17. data/lib/mongo/connection/socket/tcp_socket.rb +87 -0
  18. data/lib/mongo/connection/socket/unix_socket.rb +39 -0
  19. data/lib/mongo/connection/socket.rb +18 -0
  20. data/lib/mongo/connection.rb +7 -875
  21. data/lib/mongo/cursor.rb +403 -117
  22. data/lib/mongo/db.rb +444 -243
  23. data/lib/mongo/exception.rb +145 -0
  24. data/lib/mongo/functional/authentication.rb +455 -0
  25. data/lib/mongo/functional/logging.rb +85 -0
  26. data/lib/mongo/functional/read_preference.rb +183 -0
  27. data/lib/mongo/functional/scram.rb +556 -0
  28. data/lib/mongo/functional/uri_parser.rb +409 -0
  29. data/lib/mongo/functional/write_concern.rb +66 -0
  30. data/lib/mongo/functional.rb +20 -0
  31. data/lib/mongo/gridfs/grid.rb +30 -24
  32. data/lib/mongo/gridfs/grid_ext.rb +6 -10
  33. data/lib/mongo/gridfs/grid_file_system.rb +38 -20
  34. data/lib/mongo/gridfs/grid_io.rb +84 -75
  35. data/lib/mongo/gridfs.rb +18 -0
  36. data/lib/mongo/legacy.rb +140 -0
  37. data/lib/mongo/mongo_client.rb +697 -0
  38. data/lib/mongo/mongo_replica_set_client.rb +535 -0
  39. data/lib/mongo/mongo_sharded_client.rb +159 -0
  40. data/lib/mongo/networking.rb +372 -0
  41. data/lib/mongo/{util → utils}/conversions.rb +29 -8
  42. data/lib/mongo/{util → utils}/core_ext.rb +28 -18
  43. data/lib/mongo/{util → utils}/server_version.rb +4 -6
  44. data/lib/mongo/{util → utils}/support.rb +29 -31
  45. data/lib/mongo/utils/thread_local_variable_manager.rb +25 -0
  46. data/lib/mongo/utils.rb +19 -0
  47. data/lib/mongo.rb +51 -50
  48. data/mongo.gemspec +29 -32
  49. data/test/functional/authentication_test.rb +39 -0
  50. data/test/functional/bulk_api_stress_test.rb +133 -0
  51. data/test/functional/bulk_write_collection_view_test.rb +1198 -0
  52. data/test/functional/client_test.rb +627 -0
  53. data/test/functional/collection_test.rb +2175 -0
  54. data/test/functional/collection_writer_test.rb +83 -0
  55. data/test/{conversions_test.rb → functional/conversions_test.rb} +47 -3
  56. data/test/functional/cursor_fail_test.rb +57 -0
  57. data/test/functional/cursor_message_test.rb +56 -0
  58. data/test/functional/cursor_test.rb +683 -0
  59. data/test/functional/db_api_test.rb +835 -0
  60. data/test/functional/db_connection_test.rb +25 -0
  61. data/test/functional/db_test.rb +348 -0
  62. data/test/functional/grid_file_system_test.rb +285 -0
  63. data/test/{grid_io_test.rb → functional/grid_io_test.rb} +72 -11
  64. data/test/{grid_test.rb → functional/grid_test.rb} +88 -15
  65. data/test/functional/pool_test.rb +136 -0
  66. data/test/functional/safe_test.rb +98 -0
  67. data/test/functional/ssl_test.rb +29 -0
  68. data/test/functional/support_test.rb +62 -0
  69. data/test/functional/timeout_test.rb +60 -0
  70. data/test/functional/uri_test.rb +446 -0
  71. data/test/functional/write_concern_test.rb +118 -0
  72. data/test/helpers/general.rb +50 -0
  73. data/test/helpers/test_unit.rb +476 -0
  74. data/test/replica_set/authentication_test.rb +37 -0
  75. data/test/replica_set/basic_test.rb +189 -0
  76. data/test/replica_set/client_test.rb +393 -0
  77. data/test/replica_set/connection_test.rb +138 -0
  78. data/test/replica_set/count_test.rb +66 -0
  79. data/test/replica_set/cursor_test.rb +220 -0
  80. data/test/replica_set/insert_test.rb +157 -0
  81. data/test/replica_set/max_values_test.rb +151 -0
  82. data/test/replica_set/pinning_test.rb +105 -0
  83. data/test/replica_set/query_test.rb +73 -0
  84. data/test/replica_set/read_preference_test.rb +219 -0
  85. data/test/replica_set/refresh_test.rb +211 -0
  86. data/test/replica_set/replication_ack_test.rb +95 -0
  87. data/test/replica_set/ssl_test.rb +32 -0
  88. data/test/sharded_cluster/basic_test.rb +203 -0
  89. data/test/shared/authentication/basic_auth_shared.rb +260 -0
  90. data/test/shared/authentication/bulk_api_auth_shared.rb +249 -0
  91. data/test/shared/authentication/gssapi_shared.rb +176 -0
  92. data/test/shared/authentication/sasl_plain_shared.rb +96 -0
  93. data/test/shared/authentication/scram_shared.rb +92 -0
  94. data/test/shared/ssl_shared.rb +235 -0
  95. data/test/test_helper.rb +53 -94
  96. data/test/threading/basic_test.rb +120 -0
  97. data/test/tools/mongo_config.rb +708 -0
  98. data/test/tools/mongo_config_test.rb +160 -0
  99. data/test/unit/client_test.rb +381 -0
  100. data/test/unit/collection_test.rb +89 -53
  101. data/test/unit/connection_test.rb +282 -32
  102. data/test/unit/cursor_test.rb +206 -8
  103. data/test/unit/db_test.rb +55 -13
  104. data/test/unit/grid_test.rb +43 -16
  105. data/test/unit/mongo_sharded_client_test.rb +48 -0
  106. data/test/unit/node_test.rb +93 -0
  107. data/test/unit/pool_manager_test.rb +111 -0
  108. data/test/unit/read_pref_test.rb +406 -0
  109. data/test/unit/read_test.rb +159 -0
  110. data/test/unit/safe_test.rb +69 -36
  111. data/test/unit/sharding_pool_manager_test.rb +84 -0
  112. data/test/unit/write_concern_test.rb +175 -0
  113. data.tar.gz.sig +3 -0
  114. metadata +227 -216
  115. metadata.gz.sig +0 -0
  116. data/docs/CREDITS.md +0 -123
  117. data/docs/FAQ.md +0 -116
  118. data/docs/GridFS.md +0 -158
  119. data/docs/HISTORY.md +0 -244
  120. data/docs/RELEASES.md +0 -33
  121. data/docs/REPLICA_SETS.md +0 -72
  122. data/docs/TUTORIAL.md +0 -247
  123. data/docs/WRITE_CONCERN.md +0 -28
  124. data/lib/mongo/exceptions.rb +0 -71
  125. data/lib/mongo/gridfs/grid_io_fix.rb +0 -38
  126. data/lib/mongo/repl_set_connection.rb +0 -342
  127. data/lib/mongo/test.rb +0 -20
  128. data/lib/mongo/util/pool.rb +0 -177
  129. data/lib/mongo/util/uri_parser.rb +0 -185
  130. data/test/async/collection_test.rb +0 -224
  131. data/test/async/connection_test.rb +0 -24
  132. data/test/async/cursor_test.rb +0 -162
  133. data/test/async/worker_pool_test.rb +0 -99
  134. data/test/auxillary/1.4_features.rb +0 -166
  135. data/test/auxillary/authentication_test.rb +0 -68
  136. data/test/auxillary/autoreconnect_test.rb +0 -41
  137. data/test/auxillary/fork_test.rb +0 -30
  138. data/test/auxillary/repl_set_auth_test.rb +0 -58
  139. data/test/auxillary/slave_connection_test.rb +0 -36
  140. data/test/auxillary/threaded_authentication_test.rb +0 -101
  141. data/test/bson/binary_test.rb +0 -15
  142. data/test/bson/bson_test.rb +0 -649
  143. data/test/bson/byte_buffer_test.rb +0 -208
  144. data/test/bson/hash_with_indifferent_access_test.rb +0 -38
  145. data/test/bson/json_test.rb +0 -17
  146. data/test/bson/object_id_test.rb +0 -154
  147. data/test/bson/ordered_hash_test.rb +0 -204
  148. data/test/bson/timestamp_test.rb +0 -24
  149. data/test/collection_test.rb +0 -910
  150. data/test/connection_test.rb +0 -309
  151. data/test/cursor_fail_test.rb +0 -75
  152. data/test/cursor_message_test.rb +0 -43
  153. data/test/cursor_test.rb +0 -483
  154. data/test/db_api_test.rb +0 -726
  155. data/test/db_connection_test.rb +0 -15
  156. data/test/db_test.rb +0 -287
  157. data/test/grid_file_system_test.rb +0 -243
  158. data/test/load/resque/load.rb +0 -21
  159. data/test/load/resque/processor.rb +0 -26
  160. data/test/load/thin/load.rb +0 -24
  161. data/test/load/unicorn/load.rb +0 -23
  162. data/test/load/unicorn/unicorn.rb +0 -29
  163. data/test/replica_sets/connect_test.rb +0 -94
  164. data/test/replica_sets/connection_string_test.rb +0 -32
  165. data/test/replica_sets/count_test.rb +0 -35
  166. data/test/replica_sets/insert_test.rb +0 -53
  167. data/test/replica_sets/pooled_insert_test.rb +0 -55
  168. data/test/replica_sets/query_secondaries.rb +0 -96
  169. data/test/replica_sets/query_test.rb +0 -51
  170. data/test/replica_sets/replication_ack_test.rb +0 -66
  171. data/test/replica_sets/rs_test_helper.rb +0 -27
  172. data/test/safe_test.rb +0 -68
  173. data/test/support/hash_with_indifferent_access.rb +0 -186
  174. data/test/support/keys.rb +0 -45
  175. data/test/support_test.rb +0 -18
  176. data/test/threading/threading_with_large_pool_test.rb +0 -90
  177. data/test/threading_test.rb +0 -87
  178. data/test/tools/auth_repl_set_manager.rb +0 -14
  179. data/test/tools/load.rb +0 -58
  180. data/test/tools/repl_set_manager.rb +0 -266
  181. data/test/tools/sharding_manager.rb +0 -202
  182. data/test/tools/test.rb +0 -4
  183. data/test/unit/pool_test.rb +0 -9
  184. data/test/unit/repl_set_connection_test.rb +0 -59
  185. data/test/uri_test.rb +0 -91
@@ -0,0 +1,220 @@
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
+ require 'test_helper'
16
+
17
+ class ReplicaSetCursorTest < Test::Unit::TestCase
18
+
19
+ def setup
20
+ ensure_cluster(:rs)
21
+ end
22
+
23
+ def test_get_more_primary
24
+ setup_client(:primary)
25
+ cursor_get_more_test(:primary)
26
+ end
27
+
28
+ def test_get_more_secondary
29
+ setup_client(:secondary)
30
+ cursor_get_more_test(:secondary)
31
+ end
32
+
33
+ def test_close_primary
34
+ setup_client(:primary)
35
+ kill_cursor_test(:primary)
36
+ end
37
+
38
+ def test_close_secondary
39
+ setup_client(:secondary)
40
+ kill_cursor_test(:secondary)
41
+ end
42
+
43
+ def test_cursors_get_closed
44
+ setup_client
45
+ assert_cursors_on_members
46
+ end
47
+
48
+ def test_cursors_get_closed_secondary
49
+ setup_client(:secondary)
50
+ assert_cursors_on_members(:secondary)
51
+ end
52
+
53
+ def test_cursors_get_closed_secondary_query
54
+ setup_client(:primary)
55
+ assert_cursors_on_members(:secondary)
56
+ end
57
+
58
+ def test_intervening_query_secondary
59
+ setup_client(:primary)
60
+ refresh_while_iterating(:secondary)
61
+ end
62
+
63
+ private
64
+
65
+ def setup_client(read=:primary)
66
+ route_read ||= read
67
+ # Setup ReplicaSet Connection
68
+ @client = MongoReplicaSetClient.new(@rs.repl_set_seeds, :read => read, :op_timeout => TEST_OP_TIMEOUT)
69
+ authenticate_client(@client)
70
+
71
+ @db = @client.db(TEST_DB)
72
+ @db.drop_collection("cursor_tests")
73
+ @coll = @db.collection("cursor_tests")
74
+ insert_docs
75
+
76
+ # Setup Direct Connections
77
+ @primary = Mongo::MongoClient.new(*@client.manager.primary)
78
+ authenticate_client(@primary)
79
+ end
80
+
81
+ def insert_docs
82
+ @n_docs = 102 # batch size is 101
83
+ @n_docs.times do |i|
84
+ @coll.insert({ "x" => i }, :w => 3)
85
+ end
86
+ end
87
+
88
+ def set_read_client_and_tag(read)
89
+ read_opts = {:read => read}
90
+ @tag = (0...3).map{|i|i.to_s}.detect do |tag|
91
+ begin
92
+ read_opts[:tag_sets] = [{:node => tag}] unless read == :primary
93
+ cursor = @coll.find({}, read_opts)
94
+ cursor.next
95
+ pool = cursor.instance_variable_get(:@pool)
96
+ cursor.close
97
+ @read = Mongo::MongoClient.new(pool.host, pool.port, :slave_ok => true)
98
+ authenticate_client(@read)
99
+ tag
100
+ rescue Mongo::ConnectionFailure
101
+ false
102
+ end
103
+ end
104
+ end
105
+
106
+ def route_query(read)
107
+ read_opts = {:read => read}
108
+ read_opts[:tag_sets] = [{:node => @tag}] unless read == :primary
109
+ object_id = BSON::ObjectId.new
110
+ read_opts[:comment] = object_id
111
+
112
+ # set profiling level to 2 on client and member to which the query will be routed
113
+ @client.db(TEST_DB).profiling_level = :all
114
+ @client.secondaries.each do |node|
115
+ node = Mongo::MongoClient.new(node[0], node[1], :slave_ok => true)
116
+ authenticate_client(node)
117
+ node.db(TEST_DB).profiling_level = :all
118
+ end
119
+
120
+ @cursor = @coll.find({}, read_opts)
121
+ @cursor.next
122
+
123
+ # on client and other members set profiling level to 0
124
+ @client.db(TEST_DB).profiling_level = :off
125
+ @client.secondaries.each do |node|
126
+ node = Mongo::MongoClient.new(node[0], node[1], :slave_ok => true)
127
+ authenticate_client(node)
128
+ node.db(TEST_DB).profiling_level = :off
129
+ end
130
+ # do a query on system.profile of the reader to see if it was used for the query
131
+ profiled_queries = @read.db(TEST_DB).collection('system.profile').find({
132
+ 'ns' => "#{TEST_DB}.cursor_tests", "query.$comment" => object_id })
133
+
134
+ assert_equal 1, profiled_queries.count
135
+ end
136
+
137
+ # batch from send_initial_query is 101 documents
138
+ # check that you get n_docs back from the query, with the same port
139
+ def cursor_get_more_test(read=:primary)
140
+ return if subject_to_server_4754?(@client)
141
+ set_read_client_and_tag(read)
142
+ 10.times do
143
+ # assert that the query went to the correct member
144
+ route_query(read)
145
+ docs_count = 1
146
+ port = @cursor.instance_variable_get(:@pool).port
147
+ assert @cursor.alive?
148
+ while @cursor.has_next?
149
+ docs_count += 1
150
+ @cursor.next
151
+ assert_equal port, @cursor.instance_variable_get(:@pool).port
152
+ end
153
+ assert !@cursor.alive?
154
+ assert_equal @n_docs, docs_count
155
+ @cursor.close #cursor is already closed
156
+ end
157
+ end
158
+
159
+ # batch from get_more can be huge, so close after send_initial_query
160
+ def kill_cursor_test(read=:primary)
161
+ return if subject_to_server_4754?(@client)
162
+ set_read_client_and_tag(read)
163
+ 10.times do
164
+ # assert that the query went to the correct member
165
+ route_query(read)
166
+ cursor_id = @cursor.cursor_id
167
+ cursor_clone = @cursor.clone
168
+ assert_equal cursor_id, cursor_clone.cursor_id
169
+ assert @cursor.instance_variable_get(:@pool)
170
+ # .next was called once already and leave one for get more
171
+ (@n_docs-2).times { @cursor.next }
172
+ @cursor.close
173
+ # an exception confirms the cursor has indeed been closed
174
+ assert_raise Mongo::OperationFailure do
175
+ cursor_clone.next
176
+ end
177
+ end
178
+ end
179
+
180
+ def assert_cursors_on_members(read=:primary)
181
+ return if subject_to_server_4754?(@client)
182
+ set_read_client_and_tag(read)
183
+ # assert that the query went to the correct member
184
+ route_query(read)
185
+ cursor_id = @cursor.cursor_id
186
+ cursor_clone = @cursor.clone
187
+ assert_equal cursor_id, cursor_clone.cursor_id
188
+ assert @cursor.instance_variable_get(:@pool)
189
+ port = @cursor.instance_variable_get(:@pool).port
190
+ while @cursor.has_next?
191
+ @cursor.next
192
+ assert_equal port, @cursor.instance_variable_get(:@pool).port
193
+ end
194
+ # an exception confirms the cursor has indeed been closed after query
195
+ assert_raise Mongo::OperationFailure do
196
+ cursor_clone.next
197
+ end
198
+ end
199
+
200
+ def refresh_while_iterating(read)
201
+ set_read_client_and_tag(read)
202
+
203
+ read_opts = {:read => read}
204
+ read_opts[:tag_sets] = [{:node => @tag}]
205
+ read_opts[:batch_size] = 2
206
+ cursor = @coll.find({}, read_opts)
207
+
208
+ 2.times { cursor.next }
209
+ port = cursor.instance_variable_get(:@pool).port
210
+ host = cursor.instance_variable_get(:@pool).host
211
+ # Refresh connection
212
+ @client.refresh
213
+ assert_nothing_raised do
214
+ cursor.next
215
+ end
216
+
217
+ assert_equal port, cursor.instance_variable_get(:@pool).port
218
+ assert_equal host, cursor.instance_variable_get(:@pool).host
219
+ end
220
+ end
@@ -0,0 +1,157 @@
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
+ require 'test_helper'
16
+
17
+ class ReplicaSetInsertTest < Test::Unit::TestCase
18
+
19
+ def setup
20
+ ensure_cluster(:rs)
21
+ @client = MongoReplicaSetClient.from_uri(@uri, :op_timeout => TEST_OP_TIMEOUT)
22
+ @version = @client.server_version
23
+ @db = @client.db(TEST_DB)
24
+ @db.drop_collection("test-sets")
25
+ @coll = @db.collection("test-sets")
26
+ end
27
+
28
+ def teardown
29
+ @client.close if @conn
30
+ end
31
+
32
+ def test_insert
33
+ @coll.save({:a => 20}, :w => 3)
34
+
35
+ @rs.primary.stop
36
+
37
+ rescue_connection_failure do
38
+ @coll.save({:a => 30}, :w => 1)
39
+ end
40
+
41
+ @coll.save({:a => 40}, :w => 1)
42
+ @coll.save({:a => 50}, :w => 1)
43
+ @coll.save({:a => 60}, :w => 1)
44
+ @coll.save({:a => 70}, :w => 1)
45
+
46
+ # Restart the old master and wait for sync
47
+ @rs.start
48
+ sleep(5)
49
+ results = []
50
+
51
+ rescue_connection_failure do
52
+ @coll.find.each {|r| results << r}
53
+ [20, 30, 40, 50, 60, 70].each do |a|
54
+ assert results.any? {|r| r['a'] == a}, "Could not find record for a => #{a}"
55
+ end
56
+ end
57
+
58
+ @coll.save({:a => 80}, :w => 3)
59
+ @coll.find.each {|r| results << r}
60
+ [20, 30, 40, 50, 60, 70, 80].each do |a|
61
+ assert results.any? {|r| r['a'] == a}, "Could not find record for a => #{a} on second find"
62
+ end
63
+ end
64
+
65
+ context "Bulk API CollectionView" do
66
+ setup do
67
+ setup
68
+ end
69
+
70
+ should "handle error with deferred write concern error - spec Merging Results" do
71
+ if @client.wire_version_feature?(MongoClient::MONGODB_3_0)
72
+ @coll.remove
73
+ @coll.ensure_index(BSON::OrderedHash[:a, Mongo::ASCENDING], {:unique => true})
74
+ bulk = @coll.initialize_ordered_bulk_op
75
+ bulk.insert({:a => 1})
76
+ bulk.find({:a => 2}).upsert.update({'$set' => {:a => 2}})
77
+ bulk.insert({:a => 1})
78
+ secondary = MongoClient.new(@rs.secondaries.first.host, @rs.secondaries.first.port)
79
+ cmd = BSON::OrderedHash[:configureFailPoint, 'rsSyncApplyStop', :mode, 'alwaysOn']
80
+ secondary['admin'].command(cmd)
81
+ ex = assert_raise BulkWriteError do
82
+ bulk.execute({:w => @rs.servers.size, :wtimeout => 1})
83
+ end
84
+ cmd = BSON::OrderedHash[:configureFailPoint, 'rsSyncApplyStop', :mode, 'off']
85
+ secondary['admin'].command(cmd)
86
+ else
87
+ with_write_commands_and_operations(@db.connection) do |wire_version|
88
+ @coll.remove
89
+ @coll.ensure_index(BSON::OrderedHash[:a, Mongo::ASCENDING], {:unique => true})
90
+ bulk = @coll.initialize_ordered_bulk_op
91
+ bulk.insert({:a => 1})
92
+ bulk.find({:a => 2}).upsert.update({'$set' => {:a => 2}})
93
+ bulk.insert({:a => 1})
94
+ ex = assert_raise BulkWriteError do
95
+ bulk.execute({:w => 5, :wtimeout => 1})
96
+ end
97
+ end
98
+ end
99
+ result = ex.result
100
+ assert_match_document(
101
+ {
102
+ "ok" => 1,
103
+ "n" => 2,
104
+ "writeErrors" => [
105
+ {
106
+ "index" => 2,
107
+ "code" => 11000,
108
+ "errmsg" => /duplicate key error/,
109
+ }
110
+ ],
111
+ "writeConcernError" => [
112
+ {
113
+ "errmsg" => /waiting for replication timed out|timed out waiting for slaves|timeout/,
114
+ "code" => 64,
115
+ "errInfo" => {"wtimeout" => true},
116
+ "index" => 0
117
+ },
118
+ {
119
+ "errmsg" => /waiting for replication timed out|timed out waiting for slaves|timeout/,
120
+ "code" => 64,
121
+ "errInfo" => {"wtimeout" => true},
122
+ "index" => 1
123
+ }
124
+ ],
125
+ "code" => 65,
126
+ "errmsg" => "batch item errors occurred",
127
+ "nInserted" => 1
128
+ }, result)
129
+ assert_equal 2, @coll.find.to_a.size
130
+ end
131
+
132
+ should "handle unordered errors with deferred write concern error - spec Merging Results" do # TODO - spec review
133
+ with_write_commands_and_operations(@db.connection) do |wire_version|
134
+ @coll.remove
135
+ @coll.ensure_index(BSON::OrderedHash[:a, Mongo::ASCENDING], {:unique => true})
136
+ bulk = @coll.initialize_unordered_bulk_op
137
+ bulk.insert({:a => 1})
138
+ bulk.find({:a => 2}).upsert.update({'$set' => {:a => 1}})
139
+ bulk.insert({:a => 3})
140
+ ex = assert_raise BulkWriteError do
141
+ bulk.execute({:w => 5, :wtimeout => 1})
142
+ end
143
+ result = ex.result # unordered varies, don't use assert_bulk_exception
144
+ assert_equal(1, result["ok"], "wire_version:#{wire_version}")
145
+ assert_equal(2, result["n"], "wire_version:#{wire_version}")
146
+ assert(result["nInserted"] >= 1, "wire_version:#{wire_version}")
147
+ assert_equal(65, result["code"], "wire_version:#{wire_version}")
148
+ assert_equal("batch item errors occurred", result["errmsg"], "wire_version:#{wire_version}")
149
+ assert(result["writeErrors"].size >= 1, "wire_version:#{wire_version}")
150
+ assert(result["writeConcernError"].size >= 1, "wire_version:#{wire_version}") if wire_version >= 2
151
+ assert(@coll.size >= 1, "wire_version:#{wire_version}")
152
+ end
153
+ end
154
+
155
+ end
156
+
157
+ end
@@ -0,0 +1,151 @@
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
+ require 'test_helper'
16
+
17
+ class MaxValuesTest < Test::Unit::TestCase
18
+
19
+ include Mongo
20
+
21
+ def setup
22
+ ensure_cluster(:rs)
23
+ @client = MongoReplicaSetClient.from_uri(@uri, :op_timeout => TEST_OP_TIMEOUT)
24
+ @db = new_mock_db
25
+ @client.stubs(:[]).returns(@db)
26
+ @ismaster = {
27
+ 'hosts' => @client.local_manager.hosts.to_a,
28
+ 'arbiters' => @client.local_manager.arbiters
29
+ }
30
+ end
31
+
32
+ def test_initial_max_and_min_values
33
+ assert @client.max_bson_size
34
+ assert @client.max_message_size
35
+ assert @client.max_wire_version
36
+ assert @client.min_wire_version
37
+ end
38
+
39
+ def test_updated_max_and_min_sizes_after_node_config_change
40
+ @db.stubs(:command).returns(
41
+ @ismaster.merge({'ismaster' => true}),
42
+ @ismaster.merge({'secondary' => true, 'maxMessageSizeBytes' => 1024 * MESSAGE_SIZE_FACTOR}),
43
+ @ismaster.merge({'secondary' => true, 'maxBsonObjectSize' => 1024}),
44
+ @ismaster.merge({'secondary' => true, 'maxWireVersion' => 0}),
45
+ @ismaster.merge({'secondary' => true, 'minWireVersion' => 0})
46
+ )
47
+ @client.local_manager.stubs(:refresh_required?).returns(true)
48
+ @client.refresh
49
+
50
+ assert_equal 1024, @client.max_bson_size
51
+ assert_equal 1024 * MESSAGE_SIZE_FACTOR, @client.max_message_size
52
+ assert_equal 0, @client.max_wire_version
53
+ assert_equal 0, @client.min_wire_version
54
+ end
55
+
56
+ def test_no_values_in_config
57
+ @db.stubs(:command).returns(
58
+ @ismaster.merge({'ismaster' => true}),
59
+ @ismaster.merge({'secondary' => true}),
60
+ @ismaster.merge({'secondary' => true})
61
+ )
62
+ @client.local_manager.stubs(:refresh_required?).returns(true)
63
+ @client.refresh
64
+
65
+ assert_equal DEFAULT_MAX_BSON_SIZE, @client.max_bson_size
66
+ assert_equal DEFAULT_MAX_BSON_SIZE * MESSAGE_SIZE_FACTOR, @client.max_message_size
67
+ assert_equal 0, @client.max_wire_version
68
+ assert_equal 0, @client.min_wire_version
69
+ end
70
+
71
+ def test_only_bson_size_in_config
72
+ @db.stubs(:command).returns(
73
+ @ismaster.merge({'ismaster' => true}),
74
+ @ismaster.merge({'secondary' => true}),
75
+ @ismaster.merge({'secondary' => true, 'maxBsonObjectSize' => 1024})
76
+ )
77
+ @client.local_manager.stubs(:refresh_required?).returns(true)
78
+ @client.refresh
79
+
80
+ assert_equal 1024, @client.max_bson_size
81
+ assert_equal 1024 * MESSAGE_SIZE_FACTOR, @client.max_message_size
82
+ assert_equal 0, @client.max_wire_version
83
+ assert_equal 0, @client.min_wire_version
84
+ end
85
+
86
+ def test_values_in_config
87
+ #ismaster is called three times on the first node
88
+ @db.stubs(:command).returns(
89
+ @ismaster.merge({'ismaster' => true, 'maxMessageSizeBytes' => 1024 * 2 * MESSAGE_SIZE_FACTOR,
90
+ 'maxBsonObjectSize' => 1024, 'maxWireVersion' => 2, 'minWireVersion' => 1}),
91
+ @ismaster.merge({'ismaster' => true, 'maxMessageSizeBytes' => 1024 * 2 * MESSAGE_SIZE_FACTOR,
92
+ 'maxBsonObjectSize' => 1024, 'maxWireVersion' => 2, 'minWireVersion' => 1}),
93
+ @ismaster.merge({'ismaster' => true, 'maxMessageSizeBytes' => 1024 * 2 * MESSAGE_SIZE_FACTOR,
94
+ 'maxBsonObjectSize' => 1024, 'maxWireVersion' => 2, 'minWireVersion' => 1}),
95
+ @ismaster.merge({'secondary' => true, 'maxMessageSizeBytes' => 1024 * 2 * MESSAGE_SIZE_FACTOR,
96
+ 'maxBsonObjectSize' => 1024, 'maxWireVersion' => 2, 'minWireVersion' => 0}),
97
+ @ismaster.merge({'secondary' => true, 'maxMessageSizeBytes' => 1024 * 2 * MESSAGE_SIZE_FACTOR,
98
+ 'maxBsonObjectSize' => 1024, 'maxWireVersion' => 1, 'minWireVersion' => 0})
99
+ )
100
+ @client.local_manager.stubs(:refresh_required?).returns(true)
101
+ @client.refresh
102
+
103
+ assert_equal 1024, @client.max_bson_size
104
+ assert_equal 1024 * 2 * MESSAGE_SIZE_FACTOR, @client.max_message_size
105
+ assert_equal 1, @client.max_wire_version # minimum of all max_wire_version
106
+ assert_equal 1, @client.min_wire_version # maximum of all min_wire_version
107
+ end
108
+
109
+ def test_wire_version_not_in_range
110
+ min_wire_version, max_wire_version = [Mongo::MongoClient::MIN_WIRE_VERSION-1, Mongo::MongoClient::MIN_WIRE_VERSION-1]
111
+ #ismaster is called three times on the first node
112
+ @db.stubs(:command).returns(
113
+ @ismaster.merge({'ismaster' => true, 'maxWireVersion' => max_wire_version, 'minWireVersion' => min_wire_version}),
114
+ @ismaster.merge({'ismaster' => true, 'maxWireVersion' => max_wire_version, 'minWireVersion' => min_wire_version}),
115
+ @ismaster.merge({'ismaster' => true, 'maxWireVersion' => max_wire_version, 'minWireVersion' => min_wire_version}),
116
+ @ismaster.merge({'secondary' => true, 'maxWireVersion' => max_wire_version, 'minWireVersion' => min_wire_version}),
117
+ @ismaster.merge({'secondary' => true, 'maxWireVersion' => max_wire_version, 'minWireVersion' => min_wire_version})
118
+ )
119
+ @client.local_manager.stubs(:refresh_required?).returns(true)
120
+ assert_raises Mongo::ConnectionFailure do
121
+ @client.refresh
122
+ end
123
+ end
124
+
125
+ def test_use_write_command
126
+ with_write_commands(@client) do
127
+ assert_true @client.use_write_command?({:w => 1})
128
+ assert_false @client.use_write_command?({:w => 0})
129
+ end
130
+ with_write_operations(@client) do
131
+ assert_false @client.use_write_command?({:w => 1})
132
+ assert_false @client.use_write_command?({:w => 0})
133
+ end
134
+ @client.local_manager.primary_pool.node.expects(:wire_version_feature?).at_least_once.returns(true)
135
+ assert_true @client.use_write_command?({:w => 1})
136
+ assert_false @client.use_write_command?({:w => 0})
137
+ end
138
+
139
+ def test_max_write_batch_size
140
+ assert_equal Mongo::MongoClient::DEFAULT_MAX_WRITE_BATCH_SIZE, @client.max_write_batch_size
141
+ @client.local_manager.primary_pool.node.stubs(:max_write_batch_size).returns(999)
142
+ assert_equal 999, @client.max_write_batch_size
143
+ end
144
+
145
+ def test_max_write_batch_size_no_manager
146
+ # Simulate no local manager being set yet - RUBY-759
147
+ @client.stubs(:local_manager).returns(nil)
148
+ assert_equal Mongo::MongoClient::DEFAULT_MAX_WRITE_BATCH_SIZE, @client.max_write_batch_size
149
+ end
150
+ end
151
+
@@ -0,0 +1,105 @@
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
+ require 'test_helper'
16
+
17
+ class ReplicaSetPinningTest < Test::Unit::TestCase
18
+ def setup
19
+ ensure_cluster(:rs)
20
+ @client = MongoReplicaSetClient.from_uri(@uri, :op_timeout => TEST_OP_TIMEOUT)
21
+ @db = @client.db(TEST_DB)
22
+ @coll = @db.collection("test-sets")
23
+ @coll.insert({:a => 1})
24
+ end
25
+
26
+ def test_unpinning
27
+ # pin primary
28
+ @coll.find_one
29
+ assert_equal @client.pinned_pool[:pool], @client.primary_pool
30
+
31
+ # pin secondary
32
+ @coll.find_one({}, :read => :secondary_preferred)
33
+ assert @client.secondary_pools.include? @client.pinned_pool[:pool]
34
+
35
+ # repin primary
36
+ @coll.find_one({}, :read => :primary_preferred)
37
+ assert_equal @client.pinned_pool[:pool], @client.primary_pool
38
+ end
39
+
40
+ def test_pinned_pool_is_local_to_thread
41
+ threads = []
42
+ 30.times do |i|
43
+ threads << Thread.new do
44
+ if i % 2 == 0
45
+ @coll.find_one({}, :read => :secondary_preferred)
46
+ assert @client.secondary_pools.include? @client.pinned_pool[:pool]
47
+ else
48
+ @coll.find_one({}, :read => :primary_preferred)
49
+ assert_equal @client.pinned_pool[:pool], @client.primary_pool
50
+ end
51
+ end
52
+ end
53
+ threads.each(&:join)
54
+ end
55
+
56
+ def test_aggregation_cursor_pinning
57
+ return unless @client.server_version >= '2.5.1'
58
+ @coll.drop
59
+
60
+ [10, 1000].each do |size|
61
+ @coll.drop
62
+ size.times {|i| @coll.insert({ :_id => i }) }
63
+ expected_sum = size.times.reduce(:+)
64
+
65
+ cursor = @coll.aggregate(
66
+ [{ :$project => {:_id => '$_id'}} ],
67
+ :cursor => { :batchSize => 1 }
68
+ )
69
+
70
+ assert_equal Mongo::Cursor, cursor.class
71
+
72
+ cursor_sum = cursor.reduce(0) do |sum, doc|
73
+ sum += doc['_id']
74
+ end
75
+
76
+ assert_equal expected_sum, cursor_sum
77
+ end
78
+ @coll.drop
79
+ end
80
+
81
+ def test_parallel_scan_pinning
82
+ return unless @client.server_version >= '2.5.5'
83
+ @coll.drop
84
+
85
+ 8000.times { |i| @coll.insert({ :_id => i }) }
86
+
87
+ lock = Mutex.new
88
+ doc_ids = Set.new
89
+ threads = []
90
+ cursors = @coll.parallel_scan(3)
91
+ cursors.each_with_index do |cursor, i|
92
+ threads << Thread.new do
93
+ docs = cursor.to_a
94
+ lock.synchronize do
95
+ docs.each do |doc|
96
+ doc_ids << doc['_id']
97
+ end
98
+ end
99
+ end
100
+ end
101
+ threads.each(&:join)
102
+ assert_equal 8000, doc_ids.count
103
+ @coll.drop
104
+ end
105
+ end