• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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