# frozen_string_literal: true # encoding: utf-8 require 'spec_helper' describe Mongo::Operation::Result do let(:description) do Mongo::Server::Description.new( double('description address'), { 'minWireVersion' => 0, 'maxWireVersion' => 2 } ) end let(:result) do described_class.new(reply, description) end let(:cursor_id) { 0 } let(:documents) { [] } let(:flags) { [] } let(:starting_from) { 0 } let(:reply) do Mongo::Protocol::Reply.new.tap do |reply| reply.instance_variable_set(:@flags, flags) reply.instance_variable_set(:@cursor_id, cursor_id) reply.instance_variable_set(:@starting_from, starting_from) reply.instance_variable_set(:@number_returned, documents.size) reply.instance_variable_set(:@documents, documents) end end describe '#acknowledged?' do context 'when the reply is for a read command' do let(:documents) do [{ 'isWritablePrimary' => true, 'ok' => 1.0 }] end it 'returns true' do expect(result).to be_acknowledged end end context 'when the reply is for a write command' do context 'when the command was acknowledged' do let(:documents) do [{ "ok" => 1, "n" => 2 }] end it 'returns true' do expect(result).to be_acknowledged end end context 'when the command was not acknowledged' do let(:reply) { nil } it 'returns false' do expect(result).to_not be_acknowledged end end end end describe '#cursor_id' do context 'when the reply exists' do let(:cursor_id) { 5 } it 'delegates to the reply' do expect(result.cursor_id).to eq(5) end end context 'when the reply does not exist' do let(:reply) { nil } it 'returns zero' do expect(result.cursor_id).to eq(0) end end end describe '#has_cursor_id?' do context 'when the reply exists' do let(:cursor_id) { 5 } it 'returns true' do expect(result).to have_cursor_id end end context 'when the reply does not exist' do let(:reply) { nil } it 'returns false' do expect(result).not_to have_cursor_id end end end describe '#documents' do context 'when the result is for a command' do context 'when a reply is received' do let(:documents) do [{ "ok" => 1, "n" => 2 }] end it 'returns the documents' do expect(result.documents).to eq(documents) end end context 'when a reply is not received' do let(:reply) { nil } it 'returns an empty array' do expect(result.documents).to be_empty end end end end describe '#each' do let(:documents) do [{ "ok" => 1, "n" => 2 }] end context 'when a block is given' do it 'yields to each document' do result.each do |document| expect(document).to eq(documents.first) end end end context 'when no block is given' do it 'returns an enumerator' do expect(result.each).to be_a(Enumerator) end end end describe '#initialize' do it 'sets the replies' do expect(result.replies).to eq([ reply ]) end end describe '#returned_count' do context 'when the reply is for a read command' do let(:documents) do [{ 'hello' => true, 'ok' => 1.0 }] end it 'returns the number returned' do expect(result.returned_count).to eq(1) end end context 'when the reply is for a write command' do context 'when the write is acknowledged' do let(:documents) do [{ "ok" => 1, "n" => 2 }] end it 'returns the number returned' do expect(result.returned_count).to eq(1) end end context 'when the write is not acknowledged' do let(:reply) { nil } it 'returns zero' do expect(result.returned_count).to eq(0) end end end end describe '#successful?' do context 'when the reply is for a read command' do let(:documents) do [{ 'ismaster' => true, 'ok' => 1.0 }] end it 'returns true' do expect(result).to be_successful end end context 'when the reply is for a query' do context 'when the query has no errors' do let(:documents) do [{ 'field' => 'name' }] end it 'returns true' do expect(result).to be_successful end end context 'when the query has errors' do let(:documents) do [{ '$err' => 'not authorized for query on test.system.namespaces', 'code'=> 16550 }] end it 'returns false' do expect(result).to_not be_successful end end context 'when the query reply has the cursor_not_found flag set' do let(:flags) do [ :cursor_not_found ] end let(:documents) do [] end it 'returns false' do expect(result).to_not be_successful end end end context 'when the reply is for a write command' do context 'when the write is acknowledged' do context 'when ok is 1' do let(:documents) do [{ "ok" => 1, "n" => 2 }] end it 'returns true' do expect(result).to be_successful end end context 'when ok is not 1' do let(:documents) do [{ "ok" => 0, "n" => 0 }] end it 'returns false' do expect(result).to_not be_successful end end end context 'when the write is not acknowledged' do let(:reply) { nil } it 'returns true' do expect(result).to be_successful end end end context 'when there is a write concern error' do let(:documents) do [{'ok' => 1.0, 'writeConcernError' => { 'code' => 91, 'errmsg' => 'Replication is being shut down'}}] end it 'is false' do expect(result).not_to be_successful end end end describe '#written_count' do context 'when the reply is for a read command' do let(:documents) do [{ 'ismaster' => true, 'ok' => 1.0 }] end it 'returns the number written' do expect(result.written_count).to eq(0) end end context 'when the reply is for a write command' do let(:documents) do [{ "ok" => 1, "n" => 2 }] end it 'returns the number written' do expect(result.written_count).to eq(2) end end end context 'when there is a top-level Result class defined' do let(:client) do new_local_client(SpecConfig.instance.addresses, SpecConfig.instance.test_options) end before do class Result def get_result(client) client.database.command(:ping => 1) end end end let(:result) do Result.new.get_result(client) end it 'uses the Result class of the operation' do expect(result).to be_a(Mongo::Operation::Result) end end describe '#validate!' do context 'when there is a write concern error' do let(:documents) do [{'ok' => 1.0, 'writeConcernError' => { 'code' => 91, 'errmsg' => 'Replication is being shut down'}}] end it 'raises OperationFailure' do expect do result.validate! end.to raise_error(Mongo::Error::OperationFailure, /\[91\]: Replication is being shut down/) end end end end