end2end_common.rb 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  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. class EchoServerImpl < Echo::EchoServer::Service
  40. # say_hello implements the SayHello rpc method.
  41. def echo(echo_req, _)
  42. Echo::EchoReply.new(response: echo_req.request)
  43. end
  44. end
  45. # ServerRunner starts an "echo server" that test clients can make calls to
  46. class ServerRunner
  47. attr_accessor :server_creds
  48. def initialize(service_impl, rpc_server_args: {})
  49. @service_impl = service_impl
  50. @rpc_server_args = rpc_server_args
  51. @server_creds = :this_port_is_insecure
  52. end
  53. def run
  54. @srv = new_rpc_server_for_testing(@rpc_server_args)
  55. port = @srv.add_http2_port('0.0.0.0:0', @server_creds)
  56. @srv.handle(@service_impl)
  57. @thd = Thread.new do
  58. @srv.run
  59. end
  60. @srv.wait_till_running
  61. port
  62. end
  63. def stop
  64. @srv.stop
  65. @thd.join
  66. fail 'server not stopped' unless @srv.stopped?
  67. end
  68. end
  69. # ClientController is used to start a child process and communicate
  70. # with it for test orchestration purposes via RPCs.
  71. class ClientController < ClientControl::ParentController::Service
  72. attr_reader :stub, :client_pid
  73. def initialize(client_main, server_port)
  74. this_dir = File.expand_path(File.dirname(__FILE__))
  75. client_path = File.join(this_dir, client_main)
  76. @server = new_rpc_server_for_testing(poll_period: 3)
  77. port = @server.add_http2_port('localhost:0', :this_port_is_insecure)
  78. server_thread = Thread.new do
  79. @server.handle(self)
  80. @server.run
  81. end
  82. @server.wait_till_running
  83. @client_controller_port_mu = Mutex.new
  84. @client_controller_port_cv = ConditionVariable.new
  85. @client_controller_port = nil
  86. @client_pid = Process.spawn(RbConfig.ruby,
  87. client_path,
  88. "--parent_controller_port=#{port}",
  89. "--server_port=#{server_port}")
  90. begin
  91. Timeout.timeout(10) do
  92. @client_controller_port_mu.synchronize do
  93. while @client_controller_port.nil?
  94. @client_controller_port_cv.wait(@client_controller_port_mu)
  95. end
  96. end
  97. end
  98. rescue => e
  99. fail "timeout waiting for child process to report port. error: #{e}"
  100. end
  101. @server.stop
  102. server_thread.join
  103. @stub = ClientControl::ClientController::Stub.new(
  104. "localhost:#{@client_controller_port}", :this_channel_is_insecure)
  105. end
  106. def set_client_controller_port(req, _)
  107. @client_controller_port_mu.synchronize do
  108. unless @client_controller_port.nil?
  109. fail 'client controller port already set'
  110. end
  111. @client_controller_port = req.port
  112. @client_controller_port_cv.broadcast
  113. end
  114. ClientControl::Void.new
  115. end
  116. end
  117. def report_controller_port_to_parent(parent_controller_port, client_controller_port)
  118. unless parent_controller_port.to_i > 0
  119. fail "bad parent control port: |#{parent_controller_port}|"
  120. end
  121. stub = ClientControl::ParentController::Stub.new(
  122. "localhost:#{parent_controller_port.to_i}", :this_channel_is_insecure)
  123. m = ClientControl::Port.new
  124. m.port = client_controller_port.to_i
  125. stub.set_client_controller_port(m, deadline: Time.now + 10)
  126. end