spec/mongo/collection_spec.rb in mongo-2.1.2 vs spec/mongo/collection_spec.rb in mongo-2.2.0.rc0

- old
+ new

@@ -2,15 +2,22 @@ describe Mongo::Collection do after do authorized_collection.delete_many + collection_with_validator.drop() end let(:collection_invalid_write_concern) do authorized_collection.client.with(write: { w: (WRITE_CONCERN[:w] + 1) })[authorized_collection.name] end + let(:collection_with_validator) do + authorized_client[:validating, + :validator => { :a => { '$exists' => true } }].tap do |c| + c.create + end + end describe '#==' do let(:database) do Mongo::Database.new(authorized_client, :test) @@ -338,10 +345,14 @@ let!(:response) do collection.create end + let(:options) do + { :capped => true, :size => 1024 } + end + after do collection.drop end it 'executes the command' do @@ -355,26 +366,66 @@ it 'creates the collection in the database' do expect(database.collection_names).to include('specs') end end + shared_examples 'a validated collection command' do + + let!(:response) do + collection.create + end + + let(:options) do + { :validator => { fieldName: { '$gte' => 1024 } }, + :validationLevel => 'strict' } + end + + let(:collection_info) do + database.list_collections.find { |i| i['name'] == 'specs' } + end + + after do + collection.drop + end + + it 'executes the command' do + expect(response).to be_successful + end + + it 'sets the collection with validators' do + expect(collection_info['options']['validator']).to eq({ 'fieldName' => { '$gte' => 1024 } }) + end + + it 'creates the collection in the database' do + expect(database.collection_names).to include('specs') + end + end + context 'when instantiating a collection directly' do let(:collection) do - described_class.new(database, :specs, :capped => true, :size => 1024) + described_class.new(database, :specs, options) end it_behaves_like 'a capped collection command' + + context 'when validators can be set', if: find_command_enabled? do + it_behaves_like 'a validated collection command' + end end context 'when instantiating a collection through the database' do let(:collection) do - authorized_client[:specs, :capped => true, :size => 1024] + authorized_client[:specs, options] end it_behaves_like 'a capped collection command' + + context 'when validators can be set', if: find_command_enabled? do + it_behaves_like 'a validated collection command' + end end end end end @@ -412,33 +463,33 @@ end end describe '#find' do - context 'when provided a selector' do + context 'when provided a filter' do let(:view) do authorized_collection.find(name: 1) end - it 'returns a authorized_collection view for the selector' do - expect(view.selector).to eq(name: 1) + it 'returns a authorized_collection view for the filter' do + expect(view.filter).to eq('name' => 1) end end - context 'when provided no selector' do + context 'when provided no filter' do let(:view) do authorized_collection.find end - it 'returns a authorized_collection view with an empty selector' do - expect(view.selector).to be_empty + it 'returns a authorized_collection view with an empty filter' do + expect(view.filter).to be_empty end end - context 'when providing a bad selector' do + context 'when providing a bad filter' do let(:view) do authorized_collection.find('$or' => []) end @@ -578,11 +629,11 @@ end context 'when provided :modifiers' do let(:options) do - { modifiers: { :$orderby => Mongo::Index::ASCENDING } } + { modifiers: { '$orderby' => Mongo::Index::ASCENDING } } end it 'returns a view with modifiers set' do expect(view.modifiers).to eq(options[:modifiers]) end @@ -651,10 +702,11 @@ describe '#insert_many' do after do authorized_collection.delete_many + collection_with_validator.delete_many end let(:result) do authorized_collection.insert_many([{ name: 'test1' }, { name: 'test2' }]) end @@ -665,10 +717,41 @@ it 'contains the ids in the result' do expect(result.inserted_ids.size).to eq(2) end + context 'when the client has a custom id generator' do + + let(:generator) do + Class.new do + def generate + 1 + end + end.new + end + + let(:custom_client) do + authorized_client.with(id_generator: generator) + end + + let(:custom_collection) do + custom_client[TEST_COLL] + end + + before do + custom_collection.insert_many([{ name: 'testing' }]) + end + + after do + custom_client.close + end + + it 'inserts with the custom id' do + expect(custom_collection.find.first[:_id]).to eq(1) + end + end + context 'when the inserts fail' do let(:result) do authorized_collection.insert_many([{ _id: 1 }, { _id: 1 }]) end @@ -677,16 +760,72 @@ expect { result }.to raise_exception(Mongo::Error::BulkWriteError) end end + + context "when the documents exceed the max bson size" do + + let(:documents) do + [{ '_id' => 1, 'name' => '1'*17000000 }] + end + + it 'raises a MaxBSONSize error' do + expect { + authorized_collection.insert_many(documents) + }.to raise_error(Mongo::Error::MaxBSONSize) + end + end + + context 'when collection has a validator', if: find_command_enabled? do + + context 'when the document is valid' do + + let(:result) do + collection_with_validator.insert_many([{ a: 1 }, { a: 2 }]) + end + + it 'inserts successfully' do + expect(result.inserted_count).to eq(2) + end + end + + context 'when the document is invalid' do + + context 'when bypass_document_validation is not set' do + + let(:result2) do + collection_with_validator.insert_many([{ x: 1 }, { x: 2 }]) + end + + it 'raises a BulkWriteError' do + expect { + result2 + }.to raise_exception(Mongo::Error::BulkWriteError) + end + end + + context 'when bypass_document_validation is true' do + + let(:result3) do + collection_with_validator.insert_many( + [{ x: 1 }, { x: 2 }], :bypass_document_validation => true) + end + + it 'inserts successfully' do + expect(result3.inserted_count).to eq(2) + end + end + end + end end describe '#insert_one' do after do authorized_collection.delete_many + collection_with_validator.delete_many end let(:result) do authorized_collection.insert_one({ name: 'testing' }) end @@ -714,10 +853,83 @@ expect { result }.to raise_exception(Mongo::Error::OperationFailure) end end + + context 'when the client has a custom id generator' do + + let(:generator) do + Class.new do + def generate + 1 + end + end.new + end + + let(:custom_client) do + authorized_client.with(id_generator: generator) + end + + let(:custom_collection) do + custom_client[TEST_COLL] + end + + before do + custom_collection.insert_one({ name: 'testing' }) + end + + after do + custom_client.close + end + + it 'inserts with the custom id' do + expect(custom_collection.find.first[:_id]).to eq(1) + end + end + + context 'when collection has a validator', if: find_command_enabled? do + + context 'when the document is valid' do + + let(:result) do + collection_with_validator.insert_one({ a: 1 }) + end + + it 'inserts successfully' do + expect(result.written_count).to eq(1) + end + end + + context 'when the document is invalid' do + + context 'when bypass_document_validation is not set' do + + let(:result2) do + collection_with_validator.insert_one({ x: 1 }) + end + + it 'raises a OperationFailure' do + expect { + result2 + }.to raise_exception(Mongo::Error::OperationFailure) + end + end + + context 'when bypass_document_validation is true' do + + let(:result3) do + collection_with_validator.insert_one( + { x: 1 }, :bypass_document_validation => true) + end + + it 'inserts successfully' do + expect(result3.written_count).to eq(1) + end + end + end + end end describe '#inspect' do it 'includes the object id' do @@ -770,11 +982,11 @@ end context 'when options are provided' do let(:options) do - { :allow_disk_use => true } + { :allow_disk_use => true, :bypass_document_validation => true } end it 'sets the options on the Aggregation object' do expect(authorized_collection.aggregate([], options).options).to eq(options) end @@ -971,10 +1183,41 @@ it 'raises an error', unless: write_command_enabled? do expect { cursors }.to raise_error(Mongo::Error::OperationFailure) end + + context 'when a read concern is provided', if: find_command_enabled? do + + let(:result) do + authorized_collection.with(options).parallel_scan(2) + end + + context 'when the read concern is valid' do + + let(:options) do + { read_concern: { level: 'local' }} + end + + it 'sends the read concern' do + expect { result }.to_not raise_error + end + end + + context 'when the read concern is not valid' do + + let(:options) do + { read_concern: { level: 'idontknow' }} + end + + it 'raises an exception' do + expect { + result + }.to raise_error(Mongo::Error::OperationFailure) + end + end + end end describe '#replace_one' do let(:selector) do @@ -1079,10 +1322,60 @@ expect { result }.to raise_exception(Mongo::Error::OperationFailure) end end + + context 'when collection has a validator', if: find_command_enabled? do + + before do + collection_with_validator.insert_one({ a: 1 }) + end + + after do + collection_with_validator.delete_many + end + + context 'when the document is valid' do + + let(:result) do + collection_with_validator.replace_one({ a: 1 }, { a: 5 }) + end + + it 'replaces successfully' do + expect(result.modified_count).to eq(1) + end + end + + context 'when the document is invalid' do + + context 'when bypass_document_validation is not set' do + + let(:result2) do + collection_with_validator.replace_one({ a: 1 }, { x: 5 }) + end + + it 'raises OperationFailure' do + expect { + result2 + }.to raise_exception(Mongo::Error::OperationFailure) + end + end + + context 'when bypass_document_validation is true' do + + let(:result3) do + collection_with_validator.replace_one( + { a: 1 }, { x: 1 }, :bypass_document_validation => true) + end + + it 'replaces successfully' do + expect(result3.written_count).to eq(1) + end + end + end + end end describe '#update_many' do let(:selector) do @@ -1185,10 +1478,63 @@ expect { result }.to raise_exception(Mongo::Error::OperationFailure) end end + + context 'when collection has a validator', if: find_command_enabled? do + + before do + collection_with_validator.insert_many([{ a: 1 }, { a: 2 }]) + end + + after do + collection_with_validator.delete_many + end + + context 'when the document is valid' do + + let(:result) do + collection_with_validator.update_many( + { :a => { '$gt' => 0 } }, '$inc' => { :a => 1 } ) + end + + it 'updates successfully' do + expect(result.modified_count).to eq(2) + end + end + + context 'when the document is invalid' do + + context 'when bypass_document_validation is not set' do + + let(:result2) do + collection_with_validator.update_many( + { :a => { '$gt' => 0 } }, '$unset' => { :a => '' }) + end + + it 'raises OperationFailure' do + expect { + result2 + }.to raise_exception(Mongo::Error::OperationFailure) + end + end + + context 'when bypass_document_validation is true' do + + let(:result3) do + collection_with_validator.update_many( + { :a => { '$gt' => 0 } }, { '$unset' => { :a => '' } }, + :bypass_document_validation => true) + end + + it 'updates successfully' do + expect(result3.written_count).to eq(2) + end + end + end + end end describe '#update_one' do let(:selector) do @@ -1287,10 +1633,63 @@ expect { result }.to raise_exception(Mongo::Error::OperationFailure) end end + + context 'when collection has a validator', if: find_command_enabled? do + + before do + collection_with_validator.insert_one({ a: 1 }) + end + + after do + collection_with_validator.delete_many + end + + context 'when the document is valid' do + + let(:result) do + collection_with_validator.update_one( + { :a => { '$gt' => 0 } }, '$inc' => { :a => 1 } ) + end + + it 'updates successfully' do + expect(result.modified_count).to eq(1) + end + end + + context 'when the document is invalid' do + + context 'when bypass_document_validation is not set' do + + let(:result2) do + collection_with_validator.update_one( + { :a => { '$gt' => 0 } }, '$unset' => { :a => '' }) + end + + it 'raises OperationFailure' do + expect { + result2 + }.to raise_exception(Mongo::Error::OperationFailure) + end + end + + context 'when bypass_document_validation is true' do + + let(:result3) do + collection_with_validator.update_one( + { :a => { '$gt' => 0 } }, { '$unset' => { :a => '' } }, + :bypass_document_validation => true) + end + + it 'updates successfully' do + expect(result3.written_count).to eq(1) + end + end + end + end end describe '#find_one_and_delete' do before do @@ -1384,10 +1783,34 @@ expect { result }.to raise_exception(Mongo::Error::OperationFailure) end end + + context 'when write_concern is provided', if: find_command_enabled? && standalone? do + + it 'uses the write concern' do + expect { + authorized_collection.find_one_and_delete(selector, + write_concern: { w: 2 }) + }.to raise_error(Mongo::Error::OperationFailure) + end + end + + context 'when the collection has a write concern', if: find_command_enabled? && standalone? do + + let(:collection) do + authorized_collection.with(write: { w: 2 }) + end + + it 'uses the write concern' do + expect { + collection.find_one_and_delete(selector, + write_concern: { w: 2 }) + }.to raise_error(Mongo::Error::OperationFailure) + end + end end describe '#find_one_and_update' do let(:selector) do @@ -1538,10 +1961,90 @@ expect { result }.to raise_exception(Mongo::Error::OperationFailure) end end + + context 'when collection has a validator', if: find_command_enabled? do + + before do + collection_with_validator.insert_one({ a: 1 }) + end + + after do + collection_with_validator.delete_many + end + + context 'when the document is valid' do + + let(:result) do + collection_with_validator.find_one_and_update( + { a: 1 }, { '$inc' => { :a => 1 } }, :return_document => :after) + end + + it 'updates successfully' do + expect(result['a']).to eq(2) + end + end + + context 'when the document is invalid' do + + context 'when bypass_document_validation is not set' do + + let(:result2) do + collection_with_validator.find_one_and_update( + { a: 1 }, { '$unset' => { :a => '' } }, :return_document => :after) + end + + it 'raises OperationFailure' do + expect { + result2 + }.to raise_exception(Mongo::Error::OperationFailure) + end + end + + context 'when bypass_document_validation is true' do + + let(:result3) do + collection_with_validator.find_one_and_update( + { a: 1 }, { '$unset' => { :a => '' } }, + :bypass_document_validation => true, + :return_document => :after) + end + + it 'updates successfully' do + expect(result3['a']).to be_nil + end + end + end + end + + context 'when write_concern is provided', if: find_command_enabled? && standalone? do + + it 'uses the write concern' do + expect { + authorized_collection.find_one_and_update(selector, + { '$set' => { field: 'testing' }}, + write_concern: { w: 2 }) + }.to raise_error(Mongo::Error::OperationFailure) + end + end + + context 'when the collection has a write concern', if: find_command_enabled? && standalone? do + + let(:collection) do + authorized_collection.with(write: { w: 2 }) + end + + it 'uses the write concern' do + expect { + collection.find_one_and_update(selector, + { '$set' => { field: 'testing' }}, + write_concern: { w: 2 }) + }.to raise_error(Mongo::Error::OperationFailure) + end + end end describe '#find_one_and_replace' do before do @@ -1664,9 +2167,89 @@ it 'raises an OperationFailure' do expect { result }.to raise_exception(Mongo::Error::OperationFailure) + end + end + + context 'when collection has a validator', if: find_command_enabled? do + + before do + collection_with_validator.insert_one({ a: 1 }) + end + + after do + collection_with_validator.delete_many + end + + context 'when the document is valid' do + + let(:result) do + collection_with_validator.find_one_and_replace( + { a: 1 }, { a: 5 }, :return_document => :after) + end + + it 'replaces successfully when document is valid' do + expect(result[:a]).to eq(5) + end + end + + context 'when the document is invalid' do + + context 'when bypass_document_validation is not set' do + + let(:result2) do + collection_with_validator.find_one_and_replace( + { a: 1 }, { x: 5 }, :return_document => :after) + end + + it 'raises OperationFailure' do + expect { + result2 + }.to raise_exception(Mongo::Error::OperationFailure) + end + end + + context 'when bypass_document_validation is true' do + + let(:result3) do + collection_with_validator.find_one_and_replace( + { a: 1 }, { x: 1 }, :bypass_document_validation => true, + :return_document => :after) + end + + it 'replaces successfully' do + expect(result3[:x]).to eq(1) + expect(result3[:a]).to be_nil + end + end + end + end + + context 'when write_concern is provided', if: find_command_enabled? && standalone? do + + it 'uses the write concern' do + expect { + authorized_collection.find_one_and_replace(selector, + { field: 'testing' }, + write_concern: { w: 2 }) + }.to raise_error(Mongo::Error::OperationFailure) + end + end + + context 'when the collection has a write concern', if: find_command_enabled? && standalone? do + + let(:collection) do + authorized_collection.with(write: { w: 2 }) + end + + it 'uses the write concern' do + expect { + collection.find_one_and_replace(selector, + { field: 'testing' }, + write_concern: { w: 2 }) + }.to raise_error(Mongo::Error::OperationFailure) end end end end