debug_message_spec.rb 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  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. require 'spec_helper'
  15. TEST_DEBUG_MESSAGE = 'raised by test server'.freeze
  16. # a test service that checks the cert of its peer
  17. class DebugMessageTestService
  18. include GRPC::GenericService
  19. rpc :an_rpc_raises_abort, EchoMsg, EchoMsg
  20. rpc :an_rpc_raises_standarderror, EchoMsg, EchoMsg
  21. def an_rpc_raises_abort(_req, _call)
  22. fail GRPC::Aborted.new(
  23. 'aborted',
  24. {},
  25. TEST_DEBUG_MESSAGE)
  26. end
  27. def an_rpc_raises_standarderror(_req, _call)
  28. fail(StandardError, TEST_DEBUG_MESSAGE)
  29. end
  30. end
  31. DebugMessageTestServiceStub = DebugMessageTestService.rpc_stub_class
  32. describe 'surfacing and transmitting of debug messages' do
  33. RpcServer = GRPC::RpcServer
  34. before(:all) do
  35. server_opts = {
  36. poll_period: 1
  37. }
  38. @srv = new_rpc_server_for_testing(**server_opts)
  39. @port = @srv.add_http2_port('0.0.0.0:0', :this_port_is_insecure)
  40. @srv.handle(DebugMessageTestService)
  41. @srv_thd = Thread.new { @srv.run }
  42. @srv.wait_till_running
  43. end
  44. after(:all) do
  45. expect(@srv.stopped?).to be(false)
  46. @srv.stop
  47. @srv_thd.join
  48. end
  49. it 'debug error message is not present BadStatus exceptions that dont set it' do
  50. exception_message = ''
  51. begin
  52. fail GRPC::Unavailable('unavailable', {})
  53. rescue StandardError => e
  54. p "Got exception: #{e.message}"
  55. exception_message = e.message
  56. end
  57. expect(exception_message.empty?).to be(false)
  58. expect(exception_message.include?('debug_error_string')).to be(false)
  59. end
  60. it 'debug error message is present in locally generated errors' do
  61. # Create a secure channel. This is just one way to force a
  62. # connection handshake error, which shoud result in C-core
  63. # generating a status and error message and surfacing them up.
  64. test_root = File.join(File.dirname(__FILE__), 'testdata')
  65. files = ['ca.pem', 'client.key', 'client.pem']
  66. creds = files.map { |f| File.open(File.join(test_root, f)).read }
  67. creds = GRPC::Core::ChannelCredentials.new(creds[0], creds[1], creds[2])
  68. stub = DebugMessageTestServiceStub.new(
  69. "localhost:#{@port}", creds)
  70. begin
  71. stub.an_rpc_raises_abort(EchoMsg.new)
  72. rescue StandardError => e
  73. p "Got exception: #{e.message}"
  74. exception_message = e.message
  75. # check that the RPC did actually result in a BadStatus exception
  76. expect(e.is_a?(GRPC::BadStatus)).to be(true)
  77. end
  78. # just check that the debug_error_string is non-empty (we know that
  79. # it's a JSON object, so the first character is '{').
  80. expect(exception_message.include?('. debug_error_string:{')).to be(true)
  81. end
  82. it 'debug message is not transmitted from server to client' do
  83. # in order to not accidentally leak internal details about a
  84. # server to untrusted clients, avoid including the debug_error_string
  85. # field of a BadStatusException raised at a server in the
  86. # RPC status that it sends to clients.
  87. stub = DebugMessageTestServiceStub.new(
  88. "localhost:#{@port}", :this_channel_is_insecure)
  89. exception_message = ''
  90. begin
  91. stub.an_rpc_raises_abort(EchoMsg.new)
  92. rescue StandardError => e
  93. p "Got exception: #{e.message}"
  94. exception_message = e.message
  95. # check that the status was aborted is an indirect way to
  96. # tell that the RPC did actually get handled by the server
  97. expect(e.is_a?(GRPC::Aborted)).to be(true)
  98. end
  99. # just assert that the contents of the server-side BadStatus
  100. # debug_error_string field were *not* propagated to the client.
  101. expect(exception_message.include?('. debug_error_string:{')).to be(true)
  102. expect(exception_message.include?(TEST_DEBUG_MESSAGE)).to be(false)
  103. end
  104. it 'standard_error messages are transmitted from server to client' do
  105. # this test exists mostly in order to understand the test case
  106. # above, by comparison.
  107. stub = DebugMessageTestServiceStub.new(
  108. "localhost:#{@port}", :this_channel_is_insecure)
  109. exception_message = ''
  110. begin
  111. stub.an_rpc_raises_standarderror(EchoMsg.new)
  112. rescue StandardError => e
  113. p "Got exception: #{e.message}"
  114. exception_message = e.message
  115. expect(e.is_a?(GRPC::BadStatus)).to be(true)
  116. end
  117. # assert that the contents of the StandardError exception message
  118. # are propagated to the client.
  119. expect(exception_message.include?(TEST_DEBUG_MESSAGE)).to be(true)
  120. end
  121. end