135 lines
4.8 KiB
Ruby
135 lines
4.8 KiB
Ruby
# Copyright 2015 gRPC authors.
|
|
#
|
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
# you may not use this file except in compliance with the License.
|
|
# You may obtain a copy of the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
# See the License for the specific language governing permissions and
|
|
# limitations under the License.
|
|
|
|
require 'spec_helper'
|
|
|
|
TEST_DEBUG_MESSAGE = 'raised by test server'.freeze
|
|
|
|
# a test service that checks the cert of its peer
|
|
class DebugMessageTestService
|
|
include GRPC::GenericService
|
|
rpc :an_rpc_raises_abort, EchoMsg, EchoMsg
|
|
rpc :an_rpc_raises_standarderror, EchoMsg, EchoMsg
|
|
|
|
def an_rpc_raises_abort(_req, _call)
|
|
fail GRPC::Aborted.new(
|
|
'aborted',
|
|
{},
|
|
TEST_DEBUG_MESSAGE)
|
|
end
|
|
|
|
def an_rpc_raises_standarderror(_req, _call)
|
|
fail(StandardError, TEST_DEBUG_MESSAGE)
|
|
end
|
|
end
|
|
|
|
DebugMessageTestServiceStub = DebugMessageTestService.rpc_stub_class
|
|
|
|
describe 'surfacing and transmitting of debug messages' do
|
|
RpcServer = GRPC::RpcServer
|
|
|
|
before(:all) do
|
|
server_opts = {
|
|
poll_period: 1
|
|
}
|
|
@srv = new_rpc_server_for_testing(**server_opts)
|
|
@port = @srv.add_http2_port('0.0.0.0:0', :this_port_is_insecure)
|
|
@srv.handle(DebugMessageTestService)
|
|
@srv_thd = Thread.new { @srv.run }
|
|
@srv.wait_till_running
|
|
end
|
|
|
|
after(:all) do
|
|
expect(@srv.stopped?).to be(false)
|
|
@srv.stop
|
|
@srv_thd.join
|
|
end
|
|
|
|
it 'debug error message is not present BadStatus exceptions that dont set it' do
|
|
exception_message = ''
|
|
begin
|
|
fail GRPC::Unavailable('unavailable', {})
|
|
rescue StandardError => e
|
|
p "Got exception: #{e.message}"
|
|
exception_message = e.message
|
|
end
|
|
expect(exception_message.empty?).to be(false)
|
|
expect(exception_message.include?('debug_error_string')).to be(false)
|
|
end
|
|
|
|
it 'debug error message is present in locally generated errors' do
|
|
# Create a secure channel. This is just one way to force a
|
|
# connection handshake error, which shoud result in C-core
|
|
# generating a status and error message and surfacing them up.
|
|
test_root = File.join(File.dirname(__FILE__), 'testdata')
|
|
files = ['ca.pem', 'client.key', 'client.pem']
|
|
creds = files.map { |f| File.open(File.join(test_root, f)).read }
|
|
creds = GRPC::Core::ChannelCredentials.new(creds[0], creds[1], creds[2])
|
|
stub = DebugMessageTestServiceStub.new(
|
|
"localhost:#{@port}", creds)
|
|
begin
|
|
stub.an_rpc_raises_abort(EchoMsg.new)
|
|
rescue StandardError => e
|
|
p "Got exception: #{e.message}"
|
|
exception_message = e.message
|
|
# check that the RPC did actually result in a BadStatus exception
|
|
expect(e.is_a?(GRPC::BadStatus)).to be(true)
|
|
end
|
|
# just check that the debug_error_string is non-empty (we know that
|
|
# it's a JSON object, so the first character is '{').
|
|
expect(exception_message.include?('. debug_error_string:{')).to be(true)
|
|
end
|
|
|
|
it 'debug message is not transmitted from server to client' do
|
|
# in order to not accidentally leak internal details about a
|
|
# server to untrusted clients, avoid including the debug_error_string
|
|
# field of a BadStatusException raised at a server in the
|
|
# RPC status that it sends to clients.
|
|
stub = DebugMessageTestServiceStub.new(
|
|
"localhost:#{@port}", :this_channel_is_insecure)
|
|
exception_message = ''
|
|
begin
|
|
stub.an_rpc_raises_abort(EchoMsg.new)
|
|
rescue StandardError => e
|
|
p "Got exception: #{e.message}"
|
|
exception_message = e.message
|
|
# check that the status was aborted is an indirect way to
|
|
# tell that the RPC did actually get handled by the server
|
|
expect(e.is_a?(GRPC::Aborted)).to be(true)
|
|
end
|
|
# just assert that the contents of the server-side BadStatus
|
|
# debug_error_string field were *not* propagated to the client.
|
|
expect(exception_message.include?('. debug_error_string:{')).to be(true)
|
|
expect(exception_message.include?(TEST_DEBUG_MESSAGE)).to be(false)
|
|
end
|
|
|
|
it 'standard_error messages are transmitted from server to client' do
|
|
# this test exists mostly in order to understand the test case
|
|
# above, by comparison.
|
|
stub = DebugMessageTestServiceStub.new(
|
|
"localhost:#{@port}", :this_channel_is_insecure)
|
|
exception_message = ''
|
|
begin
|
|
stub.an_rpc_raises_standarderror(EchoMsg.new)
|
|
rescue StandardError => e
|
|
p "Got exception: #{e.message}"
|
|
exception_message = e.message
|
|
expect(e.is_a?(GRPC::BadStatus)).to be(true)
|
|
end
|
|
# assert that the contents of the StandardError exception message
|
|
# are propagated to the client.
|
|
expect(exception_message.include?(TEST_DEBUG_MESSAGE)).to be(true)
|
|
end
|
|
end
|