1# Copyright 2017 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
15# GRPC contains the General RPC module.
16module GRPC
17  ##
18  # GRPC RSpec base module
19  #
20  module Spec
21    ##
22    # A module that is used for providing generic helpers across the
23    # GRPC test suite
24    #
25    module Helpers
26      # Shortcut syntax for a GRPC RPC Server
27      RpcServer = GRPC::RpcServer
28
29      ##
30      # Build an RPC server used for testing
31      #
32      def build_rpc_server(server_opts: {},
33                           client_opts: {})
34        @server = new_rpc_server_for_testing({ poll_period: 1 }.merge(server_opts))
35        @port = @server.add_http2_port('0.0.0.0:0', :this_port_is_insecure)
36        @host = "0.0.0.0:#{@port}"
37        @client_opts = client_opts
38        @server
39      end
40
41      ##
42      # Run services on an RPC server, yielding to allow testing within
43      #
44      # @param [RpcServer] server
45      # @param [Array<Class>] services
46      #
47      def run_services_on_server(server, services: [])
48        services.each do |s|
49          server.handle(s)
50        end
51        t = Thread.new { server.run }
52        server.wait_till_running
53
54        yield
55
56        server.stop
57        t.join
58      end
59
60      ##
61      # Build an insecure stub from a given stub class
62      #
63      # @param [Class] klass
64      # @param [String] host
65      #
66      def build_insecure_stub(klass, host: nil, opts: nil)
67        host ||= @host
68        opts ||= @client_opts
69        klass.new(host, :this_channel_is_insecure, **opts)
70      end
71
72      ##
73      # Build an RPCServer for use in tests. Adds args
74      # that are useful for all tests.
75      #
76      # @param [Hash] server_opts
77      #
78      def new_rpc_server_for_testing(server_opts = {})
79        server_opts[:server_args] ||= {}
80        update_server_args_hash(server_opts[:server_args])
81        RpcServer.new(**server_opts)
82      end
83
84      ##
85      # Build an GRPC::Core::Server for use in tests. Adds args
86      # that are useful for all tests.
87      #
88      # @param [Hash] server_args
89      #
90      def new_core_server_for_testing(server_args)
91        server_args.nil? && server_args = {}
92        update_server_args_hash(server_args)
93        GRPC::Core::Server.new(server_args)
94      end
95
96      def update_server_args_hash(server_args)
97        so_reuseport_arg = 'grpc.so_reuseport'
98        unless server_args[so_reuseport_arg].nil?
99          fail 'Unexpected. grpc.so_reuseport already set.'
100        end
101        # Run tests without so_reuseport to eliminate the chance of
102        # cross-talk.
103        server_args[so_reuseport_arg] = 0
104      end
105    end
106  end
107end
108