require 'spec_helper' describe Mongo::Operation::Insert do let(:documents) do [{ '_id' => 1, 'name' => 'test' }] end let(:spec) do { :documents => documents, :db_name => TEST_DB, :coll_name => TEST_COLL, :write_concern => Mongo::WriteConcern.get(:w => 1) } end after do authorized_collection.delete_many end let(:insert) do described_class.new(spec) end describe '#initialize' do context 'spec' do it 'sets the spec' do expect(insert.spec).to eq(spec) end end end describe '#==' do context 'spec' do context 'when two inserts have the same specs' do let(:other) do described_class.new(spec) end it 'returns true' do expect(insert).to eq(other) end end context 'when two inserts have different specs' do let(:other_docs) do [{ :bar => 1 }] end let(:other_spec) do { :documents => other_docs, :db_name => 'test', :coll_name => 'test_coll', :write_concern => { 'w' => 1 } } end let(:other) do described_class.new(other_spec) end it 'returns false' do expect(insert).not_to eq(other) end end end end describe 'document ids' do context 'when documents do not contain an id' do let(:documents) do [{ 'field' => 'test' }, { 'field' => 'test' }] end let(:inserted_ids) do insert.execute(authorized_primary).inserted_ids end let(:collection_ids) do authorized_collection.find(field: 'test').collect { |d| d['_id'] } end it 'adds an id to the documents' do expect(inserted_ids).to eq(collection_ids) end end end describe '#execute' do before do authorized_collection.indexes.create_one({ name: 1 }, { unique: true }) end after do authorized_collection.delete_many authorized_collection.indexes.drop_one('name_1') end context 'when inserting a single document' do context 'when the insert succeeds' do let!(:response) do insert.execute(authorized_primary) end it 'reports the correct written count' do expect(response.written_count).to eq(1) end it 'inserts the document into the collection' do expect(authorized_collection.find(_id: 1).to_a). to eq(documents) end end context 'when the insert fails' do let(:documents) do [{ name: 'test' }] end let(:spec) do { :documents => documents, :db_name => TEST_DB, :coll_name => TEST_COLL, :write_concern => Mongo::WriteConcern.get(:w => 1) } end let(:failing_insert) do described_class.new(spec) end it 'raises an error' do expect { failing_insert.execute(authorized_primary) failing_insert.execute(authorized_primary) }.to raise_error(Mongo::Error::OperationFailure) end end end context 'when inserting multiple documents' do context 'when the insert succeeds' do let(:documents) do [{ '_id' => 1, 'name' => 'test1' }, { '_id' => 2, 'name' => 'test2' }] end let!(:response) do insert.execute(authorized_primary) end it 'reports the correct written count' do expect(response.written_count).to eq(2) end it 'inserts the documents into the collection' do expect(authorized_collection.find.to_a). to eq(documents) end end context 'when the insert fails on the last document' do let(:documents) do [{ name: 'test3' }, { name: 'test' }] end let(:spec) do { :documents => documents, :db_name => TEST_DB, :coll_name => TEST_COLL, :write_concern => Mongo::WriteConcern.get(:w => 1) } end let(:failing_insert) do described_class.new(spec) end it 'raises an error' do expect { failing_insert.execute(authorized_primary) failing_insert.execute(authorized_primary) }.to raise_error(Mongo::Error::OperationFailure) end end context 'when the insert fails on the first document' do let(:documents) do [{ name: 'test' }, { name: 'test4' }] end let(:spec) do { :documents => documents, :db_name => TEST_DB, :coll_name => TEST_COLL, :write_concern => Mongo::WriteConcern.get(:w => 1) } end let(:failing_insert) do described_class.new(spec) end it 'raises an error' do expect { failing_insert.execute(authorized_primary) failing_insert.execute(authorized_primary) }.to raise_error(Mongo::Error::OperationFailure) end end context 'when a document exceeds max bson size' do let(:documents) do [{ :x => 'y'* 17000000 }] end it 'raises an error' do expect { insert.execute(authorized_primary) }.to raise_error(Mongo::Error::MaxBSONSize) end it 'does not insert the document' do expect { insert.execute(authorized_primary) }.to raise_error(Mongo::Error::MaxBSONSize) expect(authorized_collection.find.count).to eq(0) end end end context 'when write concern { w: 0 } is used', unless: op_msg_enabled? do let(:spec) do { :documents => documents, :db_name => TEST_DB, :coll_name => TEST_COLL, :write_concern => Mongo::WriteConcern.get(:w => 0) } end let(:documents) do [{ '_id' => 1 }] end let(:op) do described_class.new(spec) end before do expect(Mongo::Operation::Insert::Legacy).to receive(:new).and_call_original end let(:response) do op.execute(authorized_primary) end it 'uses op codes instead of write commands' do expect(response.written_count).to eq(0) end end end end