end2end_common.rb 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. #!/usr/bin/env ruby
  2. # Copyright 2015 gRPC authors.
  3. #
  4. # Licensed under the Apache License, Version 2.0 (the "License");
  5. # you may not use this file except in compliance with the License.
  6. # You may obtain a copy of the License at
  7. #
  8. # http://www.apache.org/licenses/LICENSE-2.0
  9. #
  10. # Unless required by applicable law or agreed to in writing, software
  11. # distributed under the License is distributed on an "AS IS" BASIS,
  12. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. # See the License for the specific language governing permissions and
  14. # limitations under the License.
  15. this_dir = File.expand_path(File.dirname(__FILE__))
  16. protos_lib_dir = File.join(this_dir, 'lib')
  17. grpc_lib_dir = File.join(File.dirname(this_dir), 'lib')
  18. $LOAD_PATH.unshift(grpc_lib_dir) unless $LOAD_PATH.include?(grpc_lib_dir)
  19. $LOAD_PATH.unshift(protos_lib_dir) unless $LOAD_PATH.include?(protos_lib_dir)
  20. $LOAD_PATH.unshift(this_dir) unless $LOAD_PATH.include?(this_dir)
  21. require 'grpc'
  22. require 'echo_services_pb'
  23. require 'client_control_services_pb'
  24. require 'socket'
  25. require 'optparse'
  26. require 'thread'
  27. require 'timeout'
  28. require 'English' # see https://github.com/bbatsov/rubocop/issues/1747
  29. require_relative '../spec/support/helpers'
  30. include GRPC::Spec::Helpers
  31. # Useful to update a value within a do block
  32. class MutableValue
  33. attr_accessor :value
  34. def initialize(value)
  35. @value = value
  36. end
  37. end
  38. # GreeterServer is simple server that implements the Helloworld Greeter server.
  39. # This service also has a mechanism to wait for a timeout until the first
  40. # RPC has been received, which is useful for synchronizing between parent
  41. # and child processes.
  42. class EchoServerImpl < Echo::EchoServer::Service
  43. def initialize
  44. @first_rpc_received_mu = Mutex.new
  45. @first_rpc_received_cv = ConditionVariable.new
  46. @first_rpc_received = MutableValue.new(false)
  47. end
  48. # say_hello implements the SayHello rpc method.
  49. def echo(echo_req, _)
  50. @first_rpc_received_mu.synchronize do
  51. @first_rpc_received.value = true
  52. @first_rpc_received_cv.broadcast
  53. end
  54. Echo::EchoReply.new(response: echo_req.request)
  55. end
  56. def wait_for_first_rpc_received(timeout_seconds)
  57. Timeout.timeout(timeout_seconds) do
  58. @first_rpc_received_mu.synchronize do
  59. until @first_rpc_received.value
  60. @first_rpc_received_cv.wait(@first_rpc_received_mu)
  61. end
  62. end
  63. end
  64. rescue => e
  65. fail "Received error:|#{e}| while waiting for #{timeout_seconds} " \
  66. 'seconds to receive the first RPC'
  67. end
  68. end
  69. # ServerRunner starts an "echo server" that test clients can make calls to
  70. class ServerRunner
  71. attr_accessor :server_creds
  72. def initialize(service_impl, rpc_server_args: {})
  73. @service_impl = service_impl
  74. @rpc_server_args = rpc_server_args
  75. @server_creds = :this_port_is_insecure
  76. end
  77. def run
  78. @srv = new_rpc_server_for_testing(@rpc_server_args)
  79. port = @srv.add_http2_port('0.0.0.0:0', @server_creds)
  80. @srv.handle(@service_impl)
  81. @thd = Thread.new do
  82. @srv.run
  83. end
  84. @srv.wait_till_running
  85. port
  86. end
  87. def stop
  88. @srv.stop
  89. @thd.join
  90. fail 'server not stopped' unless @srv.stopped?
  91. end
  92. end
  93. def start_client(client_main, server_port)
  94. this_dir = File.expand_path(File.dirname(__FILE__))
  95. tmp_server = TCPServer.new(0)
  96. client_control_port = tmp_server.local_address.ip_port
  97. tmp_server.close
  98. client_path = File.join(this_dir, client_main)
  99. client_pid = Process.spawn(RbConfig.ruby,
  100. client_path,
  101. "--client_control_port=#{client_control_port}",
  102. "--server_port=#{server_port}")
  103. control_stub = ClientControl::ClientController::Stub.new(
  104. "localhost:#{client_control_port}", :this_channel_is_insecure)
  105. [control_stub, client_pid]
  106. end
  107. def cleanup(control_stub, client_pid, server_runner)
  108. control_stub.shutdown(ClientControl::Void.new)
  109. Process.wait(client_pid)
  110. client_exit_code = $CHILD_STATUS
  111. if client_exit_code != 0
  112. fail "term sig test failure: client exit code: #{client_exit_code}"
  113. end
  114. server_runner.stop
  115. end