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