1# Copyright 2015 gRPC authors. 2# 3# Licensed under the Apache License, Version 2.0 (the "License"); 4# you may not use this file except in compliance with the License. 5# You may obtain a copy of the License at 6# 7# http://www.apache.org/licenses/LICENSE-2.0 8# 9# Unless required by applicable law or agreed to in writing, software 10# distributed under the License is distributed on an "AS IS" BASIS, 11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12# See the License for the specific language governing permissions and 13# limitations under the License. 14 15require 'spec_helper' 16require 'google/protobuf/well_known_types' 17require 'google/rpc/status_pb' 18require_relative '../pb/src/proto/grpc/testing/messages_pb' 19 20describe GRPC::BadStatus do 21 describe :attributes do 22 it 'has attributes' do 23 code = 1 24 details = 'details' 25 metadata = { 'key' => 'val' } 26 27 exception = GRPC::BadStatus.new(code, details, metadata) 28 29 expect(exception.code).to eq code 30 expect(exception.details).to eq details 31 expect(exception.metadata).to eq metadata 32 end 33 end 34 35 describe :new_status_exception do 36 let(:codes_and_classes) do 37 [ 38 [GRPC::Core::StatusCodes::OK, GRPC::Ok], 39 [GRPC::Core::StatusCodes::CANCELLED, GRPC::Cancelled], 40 [GRPC::Core::StatusCodes::UNKNOWN, GRPC::Unknown], 41 [GRPC::Core::StatusCodes::INVALID_ARGUMENT, GRPC::InvalidArgument], 42 [GRPC::Core::StatusCodes::DEADLINE_EXCEEDED, GRPC::DeadlineExceeded], 43 [GRPC::Core::StatusCodes::NOT_FOUND, GRPC::NotFound], 44 [GRPC::Core::StatusCodes::ALREADY_EXISTS, GRPC::AlreadyExists], 45 [GRPC::Core::StatusCodes::PERMISSION_DENIED, GRPC::PermissionDenied], 46 [GRPC::Core::StatusCodes::UNAUTHENTICATED, GRPC::Unauthenticated], 47 [GRPC::Core::StatusCodes::RESOURCE_EXHAUSTED, GRPC::ResourceExhausted], 48 [GRPC::Core::StatusCodes::FAILED_PRECONDITION, GRPC::FailedPrecondition], 49 [GRPC::Core::StatusCodes::ABORTED, GRPC::Aborted], 50 [GRPC::Core::StatusCodes::OUT_OF_RANGE, GRPC::OutOfRange], 51 [GRPC::Core::StatusCodes::UNIMPLEMENTED, GRPC::Unimplemented], 52 [GRPC::Core::StatusCodes::INTERNAL, GRPC::Internal], 53 [GRPC::Core::StatusCodes::UNAVAILABLE, GRPC::Unavailable], 54 [GRPC::Core::StatusCodes::DATA_LOSS, GRPC::DataLoss], 55 [99, GRPC::BadStatus] # Unknown codes default to BadStatus 56 ] 57 end 58 59 it 'maps codes to the correct error class' do 60 codes_and_classes.each do |code, grpc_error_class| 61 exception = GRPC::BadStatus.new_status_exception(code) 62 63 expect(exception).to be_a grpc_error_class 64 end 65 end 66 end 67 68 describe :to_status do 69 it 'gets status' do 70 code = 1 71 details = 'details' 72 metadata = { 'key' => 'val' } 73 74 exception = GRPC::BadStatus.new(code, details, metadata) 75 status = Struct::Status.new(code, details, metadata) 76 77 expect(exception.to_status).to eq status 78 end 79 end 80 81 describe :to_rpc_status do 82 let(:simple_request_any) do 83 Google::Protobuf::Any.new.tap do |any| 84 any.pack( 85 Grpc::Testing::SimpleRequest.new( 86 payload: Grpc::Testing::Payload.new(body: 'request') 87 ) 88 ) 89 end 90 end 91 let(:simple_response_any) do 92 Google::Protobuf::Any.new.tap do |any| 93 any.pack( 94 Grpc::Testing::SimpleResponse.new( 95 payload: Grpc::Testing::Payload.new(body: 'response') 96 ) 97 ) 98 end 99 end 100 let(:payload_any) do 101 Google::Protobuf::Any.new.tap do |any| 102 any.pack(Grpc::Testing::Payload.new(body: 'payload')) 103 end 104 end 105 106 it 'decodes proto values' do 107 rpc_status = Google::Rpc::Status.new( 108 code: 1, 109 message: 'matching message', 110 details: [simple_request_any, simple_response_any, payload_any] 111 ) 112 rpc_status_proto = Google::Rpc::Status.encode(rpc_status) 113 114 code = 1 115 details = 'details' 116 metadata = { 'grpc-status-details-bin' => rpc_status_proto } 117 118 exception = GRPC::BadStatus.new(code, details, metadata) 119 120 expect(exception.to_rpc_status).to eq rpc_status 121 end 122 123 it 'does not raise when decoding a bad proto' do 124 code = 1 125 details = 'details' 126 metadata = { 'grpc-status-details-bin' => 'notavalidprotostream' } 127 128 exception = GRPC::BadStatus.new(code, details, metadata) 129 130 expect(exception.to_rpc_status).to be nil 131 132 error_msg = 'parse error: to_rpc_status failed' 133 error_desc = '<Google::Protobuf::ParseError> ' \ 134 'Error occurred during parsing' 135 136 # Check that the parse error was logged correctly 137 log_contents = @log_output.read 138 expect(log_contents).to include "WARN GRPC : #{error_msg}" 139 expect(log_contents).to include "WARN GRPC : #{error_desc}" 140 end 141 end 142end 143