spec/mongo/collection_spec.rb in mongo-2.9.2 vs spec/mongo/collection_spec.rb in mongo-2.10.0.rc0
- old
+ new
@@ -96,14 +96,112 @@
expect(collection).to_not eq('test')
end
end
end
+ describe '#initialize' do
+
+ let(:client) do
+ new_local_client(SpecConfig.instance.addresses,
+ SpecConfig.instance.test_options.merge(monitoring_io: false))
+ end
+
+ let(:database) { client.database }
+
+ context 'write concern given in :write option' do
+ let(:collection) do
+ Mongo::Collection.new(database, 'foo', write: {w: 1})
+ end
+
+ it 'stores write concern' do
+ expect(collection.write_concern).to be_a(Mongo::WriteConcern::Acknowledged)
+ expect(collection.write_concern.options).to eq(w: 1)
+ end
+
+ it 'stores write concern under :write' do
+ expect(collection.options[:write]).to eq(w: 1)
+ expect(collection.options[:write_concern]).to be nil
+ end
+ end
+
+ context 'write concern given in :write_concern option' do
+ let(:collection) do
+ Mongo::Collection.new(database, 'foo', write_concern: {w: 1})
+ end
+
+ it 'stores write concern' do
+ expect(collection.write_concern).to be_a(Mongo::WriteConcern::Acknowledged)
+ expect(collection.write_concern.options).to eq(w: 1)
+ end
+
+ it 'stores write concern under :write_concern' do
+ expect(collection.options[:write_concern]).to eq(w: 1)
+ expect(collection.options[:write]).to be nil
+ end
+ end
+
+ context 'write concern given in both :write and :write_concern options' do
+ context 'identical values' do
+
+ let(:collection) do
+ Mongo::Collection.new(database, 'foo',
+ write: {w: 1}, write_concern: {w: 1})
+ end
+
+ it 'stores write concern' do
+ expect(collection.write_concern).to be_a(Mongo::WriteConcern::Acknowledged)
+ expect(collection.write_concern.options).to eq(w: 1)
+ end
+
+ it 'stores write concern under both options' do
+ expect(collection.options[:write]).to eq(w: 1)
+ expect(collection.options[:write_concern]).to eq(w: 1)
+ end
+ end
+
+ context 'different values' do
+
+ let(:collection) do
+ Mongo::Collection.new(database, 'foo',
+ write: {w: 1}, write_concern: {w: 2})
+ end
+
+ it 'raises an exception' do
+ expect do
+ collection
+ end.to raise_error(ArgumentError, /If :write and :write_concern are both given, they must be identical/)
+ end
+ end
+ end
+
+=begin WriteConcern object support
+ context 'when write concern is provided via a WriteConcern object' do
+
+ let(:collection) do
+ Mongo::Collection.new(database, 'foo', write_concern: wc)
+ end
+
+ let(:wc) { Mongo::WriteConcern.get(w: 2) }
+
+ it 'stores write concern options in collection options' do
+ expect(collection.options[:write_concern]).to eq(w: 2)
+ end
+
+ it 'caches write concern object' do
+ expect(collection.write_concern).to be wc
+ end
+ end
+=end
+ end
+
describe '#with' do
let(:client) do
- new_local_client(SpecConfig.instance.addresses, SpecConfig.instance.test_options)
+ new_local_client_nmio(SpecConfig.instance.addresses,
+ SpecConfig.instance.test_options.merge(
+ SpecConfig.instance.auth_options
+ ))
end
let(:database) do
Mongo::Database.new(client, :test)
end
@@ -131,34 +229,127 @@
end
context 'when the client has a server selection timeout setting' do
let(:client) do
- new_local_client(SpecConfig.instance.addresses, SpecConfig.instance.test_options.merge(server_selection_timeout: 2))
+ new_local_client(SpecConfig.instance.addresses,
+ SpecConfig.instance.test_options.merge(server_selection_timeout: 2, monitoring_io: false))
end
it 'passes the the server_selection_timeout to the cluster' do
expect(client.cluster.options[:server_selection_timeout]).to eq(client.options[:server_selection_timeout])
end
end
context 'when the client has a read preference set' do
+ clean_slate_on_evergreen
let(:client) do
- new_local_client(SpecConfig.instance.addresses, SpecConfig.instance.test_options.merge(read: { mode: :primary_preferred }))
+ authorized_client.with(SpecConfig.instance.auth_options.merge(
+ client_options
+ )).tap do |client|
+ expect(client.options[:read]).to eq(Mongo::Options::Redacted.new(
+ mode: :primary_preferred))
+ end
end
+ let(:client_options) do
+ {
+ read: { mode: :primary_preferred },
+ monitoring_io: false,
+ }
+ end
+
+ let(:new_options) do
+ { read: { mode: :secondary } }
+ end
+
it 'sets the new read options on the new collection' do
- expect(new_collection.read_preference).to eq(new_options[:read])
- expect(new_collection.read_preference).not_to eq(client.read_preference)
+ # This is strictly a Hash, not a BSON::Document like the client's
+ # read preference.
+ expect(new_collection.read_preference).to eq(mode: :secondary)
end
+
+ it 'duplicates the read option' do
+ expect(new_collection.read_preference).not_to eql(client.read_preference)
+ end
+
+ context 'when reading from collection' do
+ # Since we are requesting a secondary read, we need a replica set.
+ require_topology :replica_set
+
+ let(:client_options) do
+ {
+ read: { mode: :primary_preferred },
+ }
+ end
+
+ let(:subscriber) { EventSubscriber.new }
+
+ before do
+ client.subscribe(Mongo::Monitoring::COMMAND, subscriber)
+ end
+
+ shared_examples_for "uses collection's read preference when reading" do
+ it "uses collection's read preference when reading" do
+ expect do
+ new_collection.find.to_a.count
+ end.not_to raise_error
+
+ event = subscriber.started_events.detect do |event|
+ event.command['find']
+ end
+ actual_rp = event.command['$readPreference']
+ expect(actual_rp).to eq(expected_read_preference)
+ end
+ end
+
+ context 'post-OP_MSG server' do
+ min_server_fcv '3.6'
+
+ context 'standalone' do
+ require_topology :single
+
+ let(:expected_read_preference) do
+ nil
+ end
+
+ it_behaves_like "uses collection's read preference when reading"
+ end
+
+ context 'RS, sharded' do
+ require_topology :replica_set, :sharded
+
+ let(:expected_read_preference) do
+ {'mode' => 'secondary'}
+ end
+
+ it_behaves_like "uses collection's read preference when reading"
+ end
+ end
+
+ context 'pre-OP-MSG server' do
+ max_server_version '3.4'
+
+ let(:expected_read_preference) do
+ nil
+ end
+
+ it_behaves_like "uses collection's read preference when reading"
+ end
+ end
end
context 'when the client has a read preference and server selection timeout set' do
let(:client) do
- new_local_client(SpecConfig.instance.addresses, SpecConfig.instance.test_options.merge(read: { mode: :primary_preferred }, server_selection_timeout: 2))
+ new_local_client(SpecConfig.instance.addresses,
+ SpecConfig.instance.test_options.merge(
+ read: { mode: :primary_preferred },
+ server_selection_timeout: 2,
+ monitoring_io: false
+ ))
end
it 'sets the new read options on the new collection' do
expect(new_collection.read_preference).to eq(new_options[:read])
end
@@ -184,16 +375,120 @@
end
context 'when the client has a write concern set' do
let(:client) do
- new_local_client(SpecConfig.instance.addresses, SpecConfig.instance.test_options.merge(write: INVALID_WRITE_CONCERN))
+ new_local_client(SpecConfig.instance.addresses,
+ SpecConfig.instance.test_options.merge(
+ write: INVALID_WRITE_CONCERN,
+ monitoring_io: false,
+ ))
end
it 'sets the new write options on the new collection' do
expect(new_collection.write_concern.options).to eq(Mongo::WriteConcern.get(new_options[:write]).options)
end
+
+ context 'when client uses :write_concern and collection uses :write' do
+
+ let(:client) do
+ new_local_client(SpecConfig.instance.addresses,
+ SpecConfig.instance.test_options.merge(
+ write_concern: {w: 1},
+ monitoring_io: false,
+ ))
+ end
+
+ it 'uses :write from collection options only' do
+ expect(new_collection.options[:write]).to eq(w: 5)
+ expect(new_collection.options[:write_concern]).to be nil
+ end
+ end
+
+ context 'when client uses :write and collection uses :write_concern' do
+
+ let(:client) do
+ new_local_client(SpecConfig.instance.addresses,
+ SpecConfig.instance.test_options.merge(
+ write: {w: 1},
+ monitoring_io: false,
+ ))
+ end
+
+ let(:new_options) do
+ { write_concern: { w: 5 } }
+ end
+
+ it 'uses :write_concern from collection options only' do
+ expect(new_collection.options[:write_concern]).to eq(w: 5)
+ expect(new_collection.options[:write]).to be nil
+ end
+ end
+
+ context 'when collection previously had :wrte_concern and :write is used with a different value' do
+
+ let(:collection) do
+ database.collection(:users, write_concern: {w: 2})
+ end
+
+ let(:new_options) do
+ { write: { w: 5 } }
+ end
+
+ it 'uses the new option' do
+ expect(new_collection.options[:write]).to eq(w: 5)
+ expect(new_collection.options[:write_concern]).to be nil
+ end
+ end
+
+ context 'when collection previously had :wrte and :write_concern is used with a different value' do
+
+ let(:collection) do
+ database.collection(:users, write: {w: 2})
+ end
+
+ let(:new_options) do
+ { write_concern: { w: 5 } }
+ end
+
+ it 'uses the new option' do
+ expect(new_collection.options[:write_concern]).to eq(w: 5)
+ expect(new_collection.options[:write]).to be nil
+ end
+ end
+
+ context 'when collection previously had :wrte_concern and :write is used with the same value' do
+
+ let(:collection) do
+ database.collection(:users, write_concern: {w: 2})
+ end
+
+ let(:new_options) do
+ { write: { w: 2 } }
+ end
+
+ it 'uses the new option' do
+ expect(new_collection.options[:write]).to eq(w: 2)
+ expect(new_collection.options[:write_concern]).to be nil
+ end
+ end
+
+ context 'when collection previously had :wrte and :write_concern is used with the same value' do
+
+ let(:collection) do
+ database.collection(:users, write: {w: 2})
+ end
+
+ let(:new_options) do
+ { write_concern: { w: 2 } }
+ end
+
+ it 'uses the new option' do
+ expect(new_collection.options[:write]).to be nil
+ expect(new_collection.options[:write_concern]).to eq(w: 2)
+ end
+ end
end
end
context 'when new read and write options are provided' do
@@ -217,22 +512,30 @@
end
context 'when the client has a server selection timeout setting' do
let(:client) do
- new_local_client(SpecConfig.instance.addresses, SpecConfig.instance.test_options.merge(server_selection_timeout: 2))
+ new_local_client(SpecConfig.instance.addresses,
+ SpecConfig.instance.test_options.merge(
+ server_selection_timeout: 2,
+ monitoring_io: false,
+ ))
end
it 'passes the server_selection_timeout setting to the cluster' do
expect(client.cluster.options[:server_selection_timeout]).to eq(client.options[:server_selection_timeout])
end
end
context 'when the client has a read preference set' do
let(:client) do
- new_local_client(SpecConfig.instance.addresses, SpecConfig.instance.test_options.merge(read: { mode: :primary_preferred }))
+ new_local_client(SpecConfig.instance.addresses,
+ SpecConfig.instance.test_options.merge(
+ read: { mode: :primary_preferred },
+ monitoring_io: false,
+ ))
end
it 'sets the new read options on the new collection' do
expect(new_collection.read_preference).to eq(new_options[:read])
expect(new_collection.read_preference).not_to be(client.read_preference)
@@ -875,10 +1178,11 @@
end
context 'when provided options' do
context 'when a session is provided' do
+ require_wired_tiger
let(:operation) do
authorized_collection.find({}, session: session).to_a
end
@@ -899,10 +1203,11 @@
end
context 'session id' do
min_server_fcv '3.6'
require_topology :replica_set, :sharded
+ require_wired_tiger
let(:options) do
{ session: session }
end
@@ -927,10 +1232,11 @@
expect(command['lsid']).to eq(session.session_id)
end
end
context 'when a session supporting causal consistency is used' do
+ require_wired_tiger
let(:operation) do
collection.find({}, session: session).to_a
end
@@ -1182,11 +1488,11 @@
custom_collection.insert_many([{ name: 'testing' }])
expect(custom_collection.count).to eq(1)
end
after do
- custom_client.close
+ custom_client.close(true)
end
it 'inserts with the custom id' do
expect(custom_collection.count).to eq(1)
expect(custom_collection.find.first[:_id]).to eq(1)
@@ -1233,11 +1539,11 @@
before do
client[TEST_COLL].insert_many(documents)
end
after do
- client.close
+ client.close(true)
end
let(:insert_events) do
EventSubscriber.started_events.select { |e| e.command_name == 'insert' }
end
@@ -1446,11 +1752,11 @@
custom_collection.delete_many
custom_collection.insert_one({ name: 'testing' })
end
after do
- custom_client.close
+ custom_client.close(true)
end
it 'inserts with the custom id' do
expect(custom_collection.find.first[:_id]).to eq(1)
end
@@ -1539,10 +1845,11 @@
it 'returns a list of indexes' do
expect(index_names).to include(*'name_1', '_id_')
end
context 'when a session is provided' do
+ require_wired_tiger
let(:session) do
authorized_client.start_session
end
@@ -1590,10 +1897,11 @@
it_behaves_like 'an operation updating cluster time'
end
context 'when a session supporting causal consistency is used' do
+ require_wired_tiger
let(:operation) do
collection.aggregate([], session: session).first
end
@@ -1715,10 +2023,11 @@
end
end
describe '#count_documents' do
context 'when transactions are enabled' do
+ require_wired_tiger
require_transaction_support
before do
# Ensure that the collection is created
authorized_collection.insert_one(x: 1)
@@ -1770,10 +2079,11 @@
it 'passes the options to the count' do
expect(authorized_collection.count({}, limit: 5)).to eq(5)
end
context 'when a session is provided' do
+ require_wired_tiger
let(:session) do
authorized_client.start_session
end
@@ -1792,10 +2102,11 @@
it_behaves_like 'an operation using a session'
it_behaves_like 'a failed operation using a session'
end
context 'when a session supporting causal consistency is used' do
+ require_wired_tiger
let(:operation) do
collection.count({}, session: session)
end
@@ -1885,10 +2196,11 @@
it 'passes the options to the distinct command' do
expect(authorized_collection.distinct(:field, {}, max_time_ms: 100).sort).to eq([ 'test1', 'test2', 'test3' ])
end
context 'when a session is provided' do
+ require_wired_tiger
let(:session) do
authorized_client.start_session
end
@@ -1908,10 +2220,11 @@
it_behaves_like 'a failed operation using a session'
end
end
context 'when a session supporting causal consistency is used' do
+ require_wired_tiger
let(:operation) do
collection.distinct(:field, {}, session: session)
end
@@ -2410,10 +2723,11 @@
cursors.reduce(0) { |total, cursor| total + cursor.to_a.size }
).to eq(200)
end
context 'when a session is provided' do
+ require_wired_tiger
let(:cursors) do
authorized_collection.parallel_scan(2, session: session)
end
@@ -2459,10 +2773,11 @@
it_behaves_like 'an operation not using a session'
it_behaves_like 'a failed operation not using a session'
end
context 'when a session supporting causal consistency is used' do
+ require_wired_tiger
let(:cursors) do
collection.parallel_scan(2, session: session)
end
@@ -2479,10 +2794,11 @@
it_behaves_like 'an operation supporting causally consistent reads'
end
context 'when a read concern is provided' do
+ require_wired_tiger
min_server_fcv '3.2'
let(:result) do
authorized_collection.with(options).parallel_scan(2)
end
@@ -2518,11 +2834,11 @@
before do
allow(collection.client.cluster).to receive(:single?).and_return(false)
end
after do
- client.close
+ client.close(true)
end
let(:client) do
authorized_client.with(server_selection_timeout: 0.2)
end
@@ -3670,11 +3986,11 @@
authorized_collection.insert_many([{ field: 'test1' }, { field: 'test1' }])
client[TEST_COLL].update_one({ a: 1 }, {'$set' => { 'name' => '1'*16777149 }})
end
after do
- client.close
+ client.close(true)
end
let(:update_events) do
EventSubscriber.started_events.select { |e| e.command_name == 'update' }
end
@@ -4689,9 +5005,10 @@
end
describe '#watch' do
context 'when change streams can be tested' do
+ require_wired_tiger
min_server_fcv '3.6'
require_topology :replica_set
let(:change_stream) do
authorized_collection.watch