grpc 0.13.0.pre1.1-x64-mingw32
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of grpc might be problematic. Click here for more details.
- checksums.yaml +7 -0
- data/etc/roots.pem +5114 -0
- data/grpc_c.32.ruby +0 -0
- data/grpc_c.64.ruby +0 -0
- data/src/ruby/bin/apis/google/protobuf/empty.rb +44 -0
- data/src/ruby/bin/apis/pubsub_demo.rb +256 -0
- data/src/ruby/bin/apis/tech/pubsub/proto/pubsub.rb +174 -0
- data/src/ruby/bin/apis/tech/pubsub/proto/pubsub_services.rb +103 -0
- data/src/ruby/bin/grpc_ruby_interop_client +33 -0
- data/src/ruby/bin/grpc_ruby_interop_server +33 -0
- data/src/ruby/bin/interop/interop_client.rb +51 -0
- data/src/ruby/bin/interop/interop_server.rb +50 -0
- data/src/ruby/bin/math.rb +32 -0
- data/src/ruby/bin/math_client.rb +147 -0
- data/src/ruby/bin/math_server.rb +206 -0
- data/src/ruby/bin/math_services.rb +27 -0
- data/src/ruby/bin/noproto_client.rb +108 -0
- data/src/ruby/bin/noproto_server.rb +112 -0
- data/src/ruby/ext/grpc/extconf.rb +129 -0
- data/src/ruby/ext/grpc/rb_byte_buffer.c +70 -0
- data/src/ruby/ext/grpc/rb_byte_buffer.h +47 -0
- data/src/ruby/ext/grpc/rb_call.c +908 -0
- data/src/ruby/ext/grpc/rb_call.h +66 -0
- data/src/ruby/ext/grpc/rb_call_credentials.c +319 -0
- data/src/ruby/ext/grpc/rb_call_credentials.h +46 -0
- data/src/ruby/ext/grpc/rb_channel.c +432 -0
- data/src/ruby/ext/grpc/rb_channel.h +47 -0
- data/src/ruby/ext/grpc/rb_channel_args.c +169 -0
- data/src/ruby/ext/grpc/rb_channel_args.h +53 -0
- data/src/ruby/ext/grpc/rb_channel_credentials.c +268 -0
- data/src/ruby/ext/grpc/rb_channel_credentials.h +47 -0
- data/src/ruby/ext/grpc/rb_completion_queue.c +183 -0
- data/src/ruby/ext/grpc/rb_completion_queue.h +55 -0
- data/src/ruby/ext/grpc/rb_event_thread.c +158 -0
- data/src/ruby/ext/grpc/rb_event_thread.h +37 -0
- data/src/ruby/ext/grpc/rb_grpc.c +336 -0
- data/src/ruby/ext/grpc/rb_grpc.h +85 -0
- data/src/ruby/ext/grpc/rb_grpc_imports.generated.c +560 -0
- data/src/ruby/ext/grpc/rb_grpc_imports.generated.h +843 -0
- data/src/ruby/ext/grpc/rb_loader.c +72 -0
- data/src/ruby/ext/grpc/rb_loader.h +40 -0
- data/src/ruby/ext/grpc/rb_server.c +400 -0
- data/src/ruby/ext/grpc/rb_server.h +47 -0
- data/src/ruby/ext/grpc/rb_server_credentials.c +284 -0
- data/src/ruby/ext/grpc/rb_server_credentials.h +47 -0
- data/src/ruby/lib/grpc.rb +44 -0
- data/src/ruby/lib/grpc/2.0/grpc_c.so +0 -0
- data/src/ruby/lib/grpc/2.1/grpc_c.so +0 -0
- data/src/ruby/lib/grpc/2.2/grpc_c.so +0 -0
- data/src/ruby/lib/grpc/2.3/grpc_c.so +0 -0
- data/src/ruby/lib/grpc/core/time_consts.rb +71 -0
- data/src/ruby/lib/grpc/errors.rb +62 -0
- data/src/ruby/lib/grpc/generic/active_call.rb +488 -0
- data/src/ruby/lib/grpc/generic/bidi_call.rb +218 -0
- data/src/ruby/lib/grpc/generic/client_stub.rb +471 -0
- data/src/ruby/lib/grpc/generic/rpc_desc.rb +147 -0
- data/src/ruby/lib/grpc/generic/rpc_server.rb +504 -0
- data/src/ruby/lib/grpc/generic/service.rb +234 -0
- data/src/ruby/lib/grpc/grpc.rb +34 -0
- data/src/ruby/lib/grpc/grpc_c.so +0 -0
- data/src/ruby/lib/grpc/logconfig.rb +59 -0
- data/src/ruby/lib/grpc/notifier.rb +60 -0
- data/src/ruby/lib/grpc/version.rb +33 -0
- data/src/ruby/pb/README.md +42 -0
- data/src/ruby/pb/generate_proto_ruby.sh +51 -0
- data/src/ruby/pb/grpc/health/checker.rb +75 -0
- data/src/ruby/pb/grpc/health/v1alpha/health.rb +29 -0
- data/src/ruby/pb/grpc/health/v1alpha/health_services.rb +28 -0
- data/src/ruby/pb/test/client.rb +469 -0
- data/src/ruby/pb/test/proto/empty.rb +15 -0
- data/src/ruby/pb/test/proto/messages.rb +80 -0
- data/src/ruby/pb/test/proto/test.rb +14 -0
- data/src/ruby/pb/test/proto/test_services.rb +64 -0
- data/src/ruby/pb/test/server.rb +253 -0
- data/src/ruby/spec/call_credentials_spec.rb +57 -0
- data/src/ruby/spec/call_spec.rb +163 -0
- data/src/ruby/spec/channel_credentials_spec.rb +97 -0
- data/src/ruby/spec/channel_spec.rb +177 -0
- data/src/ruby/spec/client_server_spec.rb +475 -0
- data/src/ruby/spec/completion_queue_spec.rb +42 -0
- data/src/ruby/spec/generic/active_call_spec.rb +373 -0
- data/src/ruby/spec/generic/client_stub_spec.rb +476 -0
- data/src/ruby/spec/generic/rpc_desc_spec.rb +331 -0
- data/src/ruby/spec/generic/rpc_server_pool_spec.rb +138 -0
- data/src/ruby/spec/generic/rpc_server_spec.rb +576 -0
- data/src/ruby/spec/generic/service_spec.rb +345 -0
- data/src/ruby/spec/pb/health/checker_spec.rb +232 -0
- data/src/ruby/spec/server_credentials_spec.rb +94 -0
- data/src/ruby/spec/server_spec.rb +209 -0
- data/src/ruby/spec/spec_helper.rb +69 -0
- data/src/ruby/spec/testdata/README +1 -0
- data/src/ruby/spec/testdata/ca.pem +15 -0
- data/src/ruby/spec/testdata/server1.key +16 -0
- data/src/ruby/spec/testdata/server1.pem +16 -0
- data/src/ruby/spec/time_consts_spec.rb +89 -0
- metadata +320 -0
@@ -0,0 +1,51 @@
|
|
1
|
+
#!/bin/sh
|
2
|
+
# Copyright 2015, Google Inc.
|
3
|
+
# All rights reserved.
|
4
|
+
#
|
5
|
+
# Redistribution and use in source and binary forms, with or without
|
6
|
+
# modification, are permitted provided that the following conditions are
|
7
|
+
# met:
|
8
|
+
#
|
9
|
+
# * Redistributions of source code must retain the above copyright
|
10
|
+
# notice, this list of conditions and the following disclaimer.
|
11
|
+
# * Redistributions in binary form must reproduce the above
|
12
|
+
# copyright notice, this list of conditions and the following disclaimer
|
13
|
+
# in the documentation and/or other materials provided with the
|
14
|
+
# distribution.
|
15
|
+
# * Neither the name of Google Inc. nor the names of its
|
16
|
+
# contributors may be used to endorse or promote products derived from
|
17
|
+
# this software without specific prior written permission.
|
18
|
+
#
|
19
|
+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
20
|
+
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
21
|
+
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
22
|
+
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
23
|
+
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
24
|
+
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
25
|
+
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
26
|
+
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
27
|
+
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
28
|
+
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
29
|
+
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
30
|
+
|
31
|
+
# Regenerates gRPC service stubs from proto files.
|
32
|
+
set +e
|
33
|
+
cd $(dirname $0)/../../..
|
34
|
+
|
35
|
+
PROTOC=bins/opt/protobuf/protoc
|
36
|
+
PLUGIN=protoc-gen-grpc=bins/opt/grpc_ruby_plugin
|
37
|
+
|
38
|
+
$PROTOC -I src/proto src/proto/grpc/health/v1alpha/health.proto \
|
39
|
+
--grpc_out=src/ruby/pb \
|
40
|
+
--ruby_out=src/ruby/pb \
|
41
|
+
--plugin=$PLUGIN
|
42
|
+
|
43
|
+
$PROTOC -I . test/proto/{messages,test,empty}.proto \
|
44
|
+
--grpc_out=src/ruby/pb \
|
45
|
+
--ruby_out=src/ruby/pb \
|
46
|
+
--plugin=$PLUGIN
|
47
|
+
|
48
|
+
$PROTOC -I src/proto/math src/proto/math/math.proto \
|
49
|
+
--grpc_out=src/ruby/bin \
|
50
|
+
--ruby_out=src/ruby/bin \
|
51
|
+
--plugin=$PLUGIN
|
@@ -0,0 +1,75 @@
|
|
1
|
+
# Copyright 2015, Google Inc.
|
2
|
+
# All rights reserved.
|
3
|
+
#
|
4
|
+
# Redistribution and use in source and binary forms, with or without
|
5
|
+
# modification, are permitted provided that the following conditions are
|
6
|
+
# met:
|
7
|
+
#
|
8
|
+
# * Redistributions of source code must retain the above copyright
|
9
|
+
# notice, this list of conditions and the following disclaimer.
|
10
|
+
# * Redistributions in binary form must reproduce the above
|
11
|
+
# copyright notice, this list of conditions and the following disclaimer
|
12
|
+
# in the documentation and/or other materials provided with the
|
13
|
+
# distribution.
|
14
|
+
# * Neither the name of Google Inc. nor the names of its
|
15
|
+
# contributors may be used to endorse or promote products derived from
|
16
|
+
# this software without specific prior written permission.
|
17
|
+
#
|
18
|
+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
19
|
+
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
20
|
+
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
21
|
+
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
22
|
+
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
23
|
+
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
24
|
+
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
25
|
+
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
26
|
+
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
27
|
+
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
28
|
+
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
29
|
+
|
30
|
+
require 'grpc'
|
31
|
+
require 'grpc/health/v1alpha/health_services'
|
32
|
+
require 'thread'
|
33
|
+
|
34
|
+
module Grpc
|
35
|
+
# Health contains classes and modules that support providing a health check
|
36
|
+
# service.
|
37
|
+
module Health
|
38
|
+
# Checker is implementation of the schema-specified health checking service.
|
39
|
+
class Checker < V1alpha::Health::Service
|
40
|
+
StatusCodes = GRPC::Core::StatusCodes
|
41
|
+
HealthCheckResponse = V1alpha::HealthCheckResponse
|
42
|
+
|
43
|
+
# Initializes the statuses of participating services
|
44
|
+
def initialize
|
45
|
+
@statuses = {}
|
46
|
+
@status_mutex = Mutex.new # guards access to @statuses
|
47
|
+
end
|
48
|
+
|
49
|
+
# Implements the rpc IDL API method
|
50
|
+
def check(req, _call)
|
51
|
+
status = nil
|
52
|
+
@status_mutex.synchronize do
|
53
|
+
status = @statuses["#{req.host}/#{req.service}"]
|
54
|
+
end
|
55
|
+
fail GRPC::BadStatus, StatusCodes::NOT_FOUND if status.nil?
|
56
|
+
HealthCheckResponse.new(status: status)
|
57
|
+
end
|
58
|
+
|
59
|
+
# Adds the health status for a given host and service.
|
60
|
+
def add_status(host, service, status)
|
61
|
+
@status_mutex.synchronize { @statuses["#{host}/#{service}"] = status }
|
62
|
+
end
|
63
|
+
|
64
|
+
# Clears the status for the given host or service.
|
65
|
+
def clear_status(host, service)
|
66
|
+
@status_mutex.synchronize { @statuses.delete("#{host}/#{service}") }
|
67
|
+
end
|
68
|
+
|
69
|
+
# Clears alls the statuses.
|
70
|
+
def clear_all
|
71
|
+
@status_mutex.synchronize { @statuses = {} }
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# Generated by the protocol buffer compiler. DO NOT EDIT!
|
2
|
+
# source: grpc/health/v1alpha/health.proto
|
3
|
+
|
4
|
+
require 'google/protobuf'
|
5
|
+
|
6
|
+
Google::Protobuf::DescriptorPool.generated_pool.build do
|
7
|
+
add_message "grpc.health.v1alpha.HealthCheckRequest" do
|
8
|
+
optional :host, :string, 1
|
9
|
+
optional :service, :string, 2
|
10
|
+
end
|
11
|
+
add_message "grpc.health.v1alpha.HealthCheckResponse" do
|
12
|
+
optional :status, :enum, 1, "grpc.health.v1alpha.HealthCheckResponse.ServingStatus"
|
13
|
+
end
|
14
|
+
add_enum "grpc.health.v1alpha.HealthCheckResponse.ServingStatus" do
|
15
|
+
value :UNKNOWN, 0
|
16
|
+
value :SERVING, 1
|
17
|
+
value :NOT_SERVING, 2
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
module Grpc
|
22
|
+
module Health
|
23
|
+
module V1alpha
|
24
|
+
HealthCheckRequest = Google::Protobuf::DescriptorPool.generated_pool.lookup("grpc.health.v1alpha.HealthCheckRequest").msgclass
|
25
|
+
HealthCheckResponse = Google::Protobuf::DescriptorPool.generated_pool.lookup("grpc.health.v1alpha.HealthCheckResponse").msgclass
|
26
|
+
HealthCheckResponse::ServingStatus = Google::Protobuf::DescriptorPool.generated_pool.lookup("grpc.health.v1alpha.HealthCheckResponse.ServingStatus").enummodule
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# Generated by the protocol buffer compiler. DO NOT EDIT!
|
2
|
+
# Source: grpc/health/v1alpha/health.proto for package 'grpc.health.v1alpha'
|
3
|
+
|
4
|
+
require 'grpc'
|
5
|
+
require 'grpc/health/v1alpha/health'
|
6
|
+
|
7
|
+
module Grpc
|
8
|
+
module Health
|
9
|
+
module V1alpha
|
10
|
+
module Health
|
11
|
+
|
12
|
+
# TODO: add proto service documentation here
|
13
|
+
class Service
|
14
|
+
|
15
|
+
include GRPC::GenericService
|
16
|
+
|
17
|
+
self.marshal_class_method = :encode
|
18
|
+
self.unmarshal_class_method = :decode
|
19
|
+
self.service_name = 'grpc.health.v1alpha.Health'
|
20
|
+
|
21
|
+
rpc :Check, HealthCheckRequest, HealthCheckResponse
|
22
|
+
end
|
23
|
+
|
24
|
+
Stub = Service.rpc_stub_class
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,469 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
# Copyright 2015-2016, Google Inc.
|
4
|
+
# All rights reserved.
|
5
|
+
#
|
6
|
+
# Redistribution and use in source and binary forms, with or without
|
7
|
+
# modification, are permitted provided that the following conditions are
|
8
|
+
# met:
|
9
|
+
#
|
10
|
+
# * Redistributions of source code must retain the above copyright
|
11
|
+
# notice, this list of conditions and the following disclaimer.
|
12
|
+
# * Redistributions in binary form must reproduce the above
|
13
|
+
# copyright notice, this list of conditions and the following disclaimer
|
14
|
+
# in the documentation and/or other materials provided with the
|
15
|
+
# distribution.
|
16
|
+
# * Neither the name of Google Inc. nor the names of its
|
17
|
+
# contributors may be used to endorse or promote products derived from
|
18
|
+
# this software without specific prior written permission.
|
19
|
+
#
|
20
|
+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
21
|
+
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
22
|
+
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
23
|
+
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
24
|
+
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
25
|
+
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
26
|
+
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
27
|
+
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
28
|
+
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
29
|
+
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
30
|
+
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
31
|
+
|
32
|
+
# client is a testing tool that accesses a gRPC interop testing server and runs
|
33
|
+
# a test on it.
|
34
|
+
#
|
35
|
+
# Helps validate interoperation b/w different gRPC implementations.
|
36
|
+
#
|
37
|
+
# Usage: $ path/to/client.rb --server_host=<hostname> \
|
38
|
+
# --server_port=<port> \
|
39
|
+
# --test_case=<testcase_name>
|
40
|
+
|
41
|
+
this_dir = File.expand_path(File.dirname(__FILE__))
|
42
|
+
lib_dir = File.join(File.dirname(File.dirname(this_dir)), 'lib')
|
43
|
+
pb_dir = File.dirname(File.dirname(this_dir))
|
44
|
+
$LOAD_PATH.unshift(lib_dir) unless $LOAD_PATH.include?(lib_dir)
|
45
|
+
$LOAD_PATH.unshift(pb_dir) unless $LOAD_PATH.include?(pb_dir)
|
46
|
+
$LOAD_PATH.unshift(this_dir) unless $LOAD_PATH.include?(this_dir)
|
47
|
+
|
48
|
+
require 'optparse'
|
49
|
+
require 'logger'
|
50
|
+
|
51
|
+
require 'grpc'
|
52
|
+
require 'googleauth'
|
53
|
+
require 'google/protobuf'
|
54
|
+
|
55
|
+
require 'test/proto/empty'
|
56
|
+
require 'test/proto/messages'
|
57
|
+
require 'test/proto/test_services'
|
58
|
+
|
59
|
+
AUTH_ENV = Google::Auth::CredentialsLoader::ENV_VAR
|
60
|
+
|
61
|
+
# RubyLogger defines a logger for gRPC based on the standard ruby logger.
|
62
|
+
module RubyLogger
|
63
|
+
def logger
|
64
|
+
LOGGER
|
65
|
+
end
|
66
|
+
|
67
|
+
LOGGER = Logger.new(STDOUT)
|
68
|
+
LOGGER.level = Logger::INFO
|
69
|
+
end
|
70
|
+
|
71
|
+
# GRPC is the general RPC module
|
72
|
+
module GRPC
|
73
|
+
# Inject the noop #logger if no module-level logger method has been injected.
|
74
|
+
extend RubyLogger
|
75
|
+
end
|
76
|
+
|
77
|
+
# AssertionError is use to indicate interop test failures.
|
78
|
+
class AssertionError < RuntimeError; end
|
79
|
+
|
80
|
+
# Fails with AssertionError if the block does evaluate to true
|
81
|
+
def assert(msg = 'unknown cause')
|
82
|
+
fail 'No assertion block provided' unless block_given?
|
83
|
+
fail AssertionError, msg unless yield
|
84
|
+
end
|
85
|
+
|
86
|
+
# loads the certificates used to access the test server securely.
|
87
|
+
def load_test_certs
|
88
|
+
this_dir = File.expand_path(File.dirname(__FILE__))
|
89
|
+
data_dir = File.join(File.dirname(File.dirname(this_dir)), 'spec/testdata')
|
90
|
+
files = ['ca.pem', 'server1.key', 'server1.pem']
|
91
|
+
files.map { |f| File.open(File.join(data_dir, f)).read }
|
92
|
+
end
|
93
|
+
|
94
|
+
# creates SSL Credentials from the test certificates.
|
95
|
+
def test_creds
|
96
|
+
certs = load_test_certs
|
97
|
+
GRPC::Core::ChannelCredentials.new(certs[0])
|
98
|
+
end
|
99
|
+
|
100
|
+
# creates SSL Credentials from the production certificates.
|
101
|
+
def prod_creds
|
102
|
+
GRPC::Core::ChannelCredentials.new()
|
103
|
+
end
|
104
|
+
|
105
|
+
# creates the SSL Credentials.
|
106
|
+
def ssl_creds(use_test_ca)
|
107
|
+
return test_creds if use_test_ca
|
108
|
+
prod_creds
|
109
|
+
end
|
110
|
+
|
111
|
+
# creates a test stub that accesses host:port securely.
|
112
|
+
def create_stub(opts)
|
113
|
+
address = "#{opts.host}:#{opts.port}"
|
114
|
+
if opts.secure
|
115
|
+
creds = ssl_creds(opts.use_test_ca)
|
116
|
+
stub_opts = {
|
117
|
+
GRPC::Core::Channel::SSL_TARGET => opts.host_override
|
118
|
+
}
|
119
|
+
|
120
|
+
# Add service account creds if specified
|
121
|
+
wants_creds = %w(all compute_engine_creds service_account_creds)
|
122
|
+
if wants_creds.include?(opts.test_case)
|
123
|
+
unless opts.oauth_scope.nil?
|
124
|
+
auth_creds = Google::Auth.get_application_default(opts.oauth_scope)
|
125
|
+
call_creds = GRPC::Core::CallCredentials.new(auth_creds.updater_proc)
|
126
|
+
creds = creds.compose call_creds
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
if opts.test_case == 'oauth2_auth_token'
|
131
|
+
auth_creds = Google::Auth.get_application_default(opts.oauth_scope)
|
132
|
+
kw = auth_creds.updater_proc.call({}) # gives as an auth token
|
133
|
+
|
134
|
+
# use a metadata update proc that just adds the auth token.
|
135
|
+
call_creds = GRPC::Core::CallCredentials.new(proc { |md| md.merge(kw) })
|
136
|
+
creds = creds.compose call_creds
|
137
|
+
end
|
138
|
+
|
139
|
+
if opts.test_case == 'jwt_token_creds' # don't use a scope
|
140
|
+
auth_creds = Google::Auth.get_application_default
|
141
|
+
call_creds = GRPC::Core::CallCredentials.new(auth_creds.updater_proc)
|
142
|
+
creds = creds.compose call_creds
|
143
|
+
end
|
144
|
+
|
145
|
+
GRPC.logger.info("... connecting securely to #{address}")
|
146
|
+
Grpc::Testing::TestService::Stub.new(address, creds, **stub_opts)
|
147
|
+
else
|
148
|
+
GRPC.logger.info("... connecting insecurely to #{address}")
|
149
|
+
Grpc::Testing::TestService::Stub.new(address, :this_channel_is_insecure)
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
# produces a string of null chars (\0) of length l.
|
154
|
+
def nulls(l)
|
155
|
+
fail 'requires #{l} to be +ve' if l < 0
|
156
|
+
[].pack('x' * l).force_encoding('ascii-8bit')
|
157
|
+
end
|
158
|
+
|
159
|
+
# a PingPongPlayer implements the ping pong bidi test.
|
160
|
+
class PingPongPlayer
|
161
|
+
include Grpc::Testing
|
162
|
+
include Grpc::Testing::PayloadType
|
163
|
+
attr_accessor :queue
|
164
|
+
attr_accessor :canceller_op
|
165
|
+
|
166
|
+
# reqs is the enumerator over the requests
|
167
|
+
def initialize(msg_sizes)
|
168
|
+
@queue = Queue.new
|
169
|
+
@msg_sizes = msg_sizes
|
170
|
+
@canceller_op = nil # used to cancel after the first response
|
171
|
+
end
|
172
|
+
|
173
|
+
def each_item
|
174
|
+
return enum_for(:each_item) unless block_given?
|
175
|
+
req_cls, p_cls = StreamingOutputCallRequest, ResponseParameters # short
|
176
|
+
count = 0
|
177
|
+
@msg_sizes.each do |m|
|
178
|
+
req_size, resp_size = m
|
179
|
+
req = req_cls.new(payload: Payload.new(body: nulls(req_size)),
|
180
|
+
response_type: :COMPRESSABLE,
|
181
|
+
response_parameters: [p_cls.new(size: resp_size)])
|
182
|
+
yield req
|
183
|
+
resp = @queue.pop
|
184
|
+
assert('payload type is wrong') { :COMPRESSABLE == resp.payload.type }
|
185
|
+
assert("payload body #{count} has the wrong length") do
|
186
|
+
resp_size == resp.payload.body.length
|
187
|
+
end
|
188
|
+
p "OK: ping_pong #{count}"
|
189
|
+
count += 1
|
190
|
+
unless @canceller_op.nil?
|
191
|
+
canceller_op.cancel
|
192
|
+
break
|
193
|
+
end
|
194
|
+
end
|
195
|
+
end
|
196
|
+
end
|
197
|
+
|
198
|
+
# defines methods corresponding to each interop test case.
|
199
|
+
class NamedTests
|
200
|
+
include Grpc::Testing
|
201
|
+
include Grpc::Testing::PayloadType
|
202
|
+
|
203
|
+
def initialize(stub, args)
|
204
|
+
@stub = stub
|
205
|
+
@args = args
|
206
|
+
end
|
207
|
+
|
208
|
+
def empty_unary
|
209
|
+
resp = @stub.empty_call(Empty.new)
|
210
|
+
assert('empty_unary: invalid response') { resp.is_a?(Empty) }
|
211
|
+
p 'OK: empty_unary'
|
212
|
+
end
|
213
|
+
|
214
|
+
def large_unary
|
215
|
+
perform_large_unary
|
216
|
+
p 'OK: large_unary'
|
217
|
+
end
|
218
|
+
|
219
|
+
def service_account_creds
|
220
|
+
# ignore this test if the oauth options are not set
|
221
|
+
if @args.oauth_scope.nil?
|
222
|
+
p 'NOT RUN: service_account_creds; no service_account settings'
|
223
|
+
return
|
224
|
+
end
|
225
|
+
json_key = File.read(ENV[AUTH_ENV])
|
226
|
+
wanted_email = MultiJson.load(json_key)['client_email']
|
227
|
+
resp = perform_large_unary(fill_username: true,
|
228
|
+
fill_oauth_scope: true)
|
229
|
+
assert("#{__callee__}: bad username") { wanted_email == resp.username }
|
230
|
+
assert("#{__callee__}: bad oauth scope") do
|
231
|
+
@args.oauth_scope.include?(resp.oauth_scope)
|
232
|
+
end
|
233
|
+
p "OK: #{__callee__}"
|
234
|
+
end
|
235
|
+
|
236
|
+
def jwt_token_creds
|
237
|
+
json_key = File.read(ENV[AUTH_ENV])
|
238
|
+
wanted_email = MultiJson.load(json_key)['client_email']
|
239
|
+
resp = perform_large_unary(fill_username: true)
|
240
|
+
assert("#{__callee__}: bad username") { wanted_email == resp.username }
|
241
|
+
p "OK: #{__callee__}"
|
242
|
+
end
|
243
|
+
|
244
|
+
def compute_engine_creds
|
245
|
+
resp = perform_large_unary(fill_username: true,
|
246
|
+
fill_oauth_scope: true)
|
247
|
+
assert("#{__callee__}: bad username") do
|
248
|
+
@args.default_service_account == resp.username
|
249
|
+
end
|
250
|
+
p "OK: #{__callee__}"
|
251
|
+
end
|
252
|
+
|
253
|
+
def oauth2_auth_token
|
254
|
+
resp = perform_large_unary(fill_username: true,
|
255
|
+
fill_oauth_scope: true)
|
256
|
+
json_key = File.read(ENV[AUTH_ENV])
|
257
|
+
wanted_email = MultiJson.load(json_key)['client_email']
|
258
|
+
assert("#{__callee__}: bad username") { wanted_email == resp.username }
|
259
|
+
assert("#{__callee__}: bad oauth scope") do
|
260
|
+
@args.oauth_scope.include?(resp.oauth_scope)
|
261
|
+
end
|
262
|
+
p "OK: #{__callee__}"
|
263
|
+
end
|
264
|
+
|
265
|
+
def per_rpc_creds
|
266
|
+
auth_creds = Google::Auth.get_application_default(@args.oauth_scope)
|
267
|
+
update_metadata = proc do |md|
|
268
|
+
kw = auth_creds.updater_proc.call({})
|
269
|
+
end
|
270
|
+
|
271
|
+
call_creds = GRPC::Core::CallCredentials.new(update_metadata)
|
272
|
+
|
273
|
+
resp = perform_large_unary(fill_username: true,
|
274
|
+
fill_oauth_scope: true,
|
275
|
+
credentials: call_creds)
|
276
|
+
json_key = File.read(ENV[AUTH_ENV])
|
277
|
+
wanted_email = MultiJson.load(json_key)['client_email']
|
278
|
+
assert("#{__callee__}: bad username") { wanted_email == resp.username }
|
279
|
+
assert("#{__callee__}: bad oauth scope") do
|
280
|
+
@args.oauth_scope.include?(resp.oauth_scope)
|
281
|
+
end
|
282
|
+
p "OK: #{__callee__}"
|
283
|
+
end
|
284
|
+
|
285
|
+
def client_streaming
|
286
|
+
msg_sizes = [27_182, 8, 1828, 45_904]
|
287
|
+
wanted_aggregate_size = 74_922
|
288
|
+
reqs = msg_sizes.map do |x|
|
289
|
+
req = Payload.new(body: nulls(x))
|
290
|
+
StreamingInputCallRequest.new(payload: req)
|
291
|
+
end
|
292
|
+
resp = @stub.streaming_input_call(reqs)
|
293
|
+
assert("#{__callee__}: aggregate payload size is incorrect") do
|
294
|
+
wanted_aggregate_size == resp.aggregated_payload_size
|
295
|
+
end
|
296
|
+
p "OK: #{__callee__}"
|
297
|
+
end
|
298
|
+
|
299
|
+
def server_streaming
|
300
|
+
msg_sizes = [31_415, 9, 2653, 58_979]
|
301
|
+
response_spec = msg_sizes.map { |s| ResponseParameters.new(size: s) }
|
302
|
+
req = StreamingOutputCallRequest.new(response_type: :COMPRESSABLE,
|
303
|
+
response_parameters: response_spec)
|
304
|
+
resps = @stub.streaming_output_call(req)
|
305
|
+
resps.each_with_index do |r, i|
|
306
|
+
assert("#{__callee__}: too many responses") { i < msg_sizes.length }
|
307
|
+
assert("#{__callee__}: payload body #{i} has the wrong length") do
|
308
|
+
msg_sizes[i] == r.payload.body.length
|
309
|
+
end
|
310
|
+
assert("#{__callee__}: payload type is wrong") do
|
311
|
+
:COMPRESSABLE == r.payload.type
|
312
|
+
end
|
313
|
+
end
|
314
|
+
p "OK: #{__callee__}"
|
315
|
+
end
|
316
|
+
|
317
|
+
def ping_pong
|
318
|
+
msg_sizes = [[27_182, 31_415], [8, 9], [1828, 2653], [45_904, 58_979]]
|
319
|
+
ppp = PingPongPlayer.new(msg_sizes)
|
320
|
+
resps = @stub.full_duplex_call(ppp.each_item)
|
321
|
+
resps.each { |r| ppp.queue.push(r) }
|
322
|
+
p "OK: #{__callee__}"
|
323
|
+
end
|
324
|
+
|
325
|
+
def timeout_on_sleeping_server
|
326
|
+
msg_sizes = [[27_182, 31_415]]
|
327
|
+
ppp = PingPongPlayer.new(msg_sizes)
|
328
|
+
resps = @stub.full_duplex_call(ppp.each_item, timeout: 0.001)
|
329
|
+
resps.each { |r| ppp.queue.push(r) }
|
330
|
+
fail 'Should have raised GRPC::BadStatus(DEADLINE_EXCEEDED)'
|
331
|
+
rescue GRPC::BadStatus => e
|
332
|
+
assert("#{__callee__}: status was wrong") do
|
333
|
+
e.code == GRPC::Core::StatusCodes::DEADLINE_EXCEEDED
|
334
|
+
end
|
335
|
+
p "OK: #{__callee__}"
|
336
|
+
end
|
337
|
+
|
338
|
+
def empty_stream
|
339
|
+
ppp = PingPongPlayer.new([])
|
340
|
+
resps = @stub.full_duplex_call(ppp.each_item)
|
341
|
+
count = 0
|
342
|
+
resps.each do |r|
|
343
|
+
ppp.queue.push(r)
|
344
|
+
count += 1
|
345
|
+
end
|
346
|
+
assert("#{__callee__}: too many responses expected 0") do
|
347
|
+
count == 0
|
348
|
+
end
|
349
|
+
p "OK: #{__callee__}"
|
350
|
+
end
|
351
|
+
|
352
|
+
def cancel_after_begin
|
353
|
+
msg_sizes = [27_182, 8, 1828, 45_904]
|
354
|
+
reqs = msg_sizes.map do |x|
|
355
|
+
req = Payload.new(body: nulls(x))
|
356
|
+
StreamingInputCallRequest.new(payload: req)
|
357
|
+
end
|
358
|
+
op = @stub.streaming_input_call(reqs, return_op: true)
|
359
|
+
op.cancel
|
360
|
+
op.execute
|
361
|
+
fail 'Should have raised GRPC:Cancelled'
|
362
|
+
rescue GRPC::Cancelled
|
363
|
+
assert("#{__callee__}: call operation should be CANCELLED") { op.cancelled }
|
364
|
+
p "OK: #{__callee__}"
|
365
|
+
end
|
366
|
+
|
367
|
+
def cancel_after_first_response
|
368
|
+
msg_sizes = [[27_182, 31_415], [8, 9], [1828, 2653], [45_904, 58_979]]
|
369
|
+
ppp = PingPongPlayer.new(msg_sizes)
|
370
|
+
op = @stub.full_duplex_call(ppp.each_item, return_op: true)
|
371
|
+
ppp.canceller_op = op # causes ppp to cancel after the 1st message
|
372
|
+
op.execute.each { |r| ppp.queue.push(r) }
|
373
|
+
fail 'Should have raised GRPC:Cancelled'
|
374
|
+
rescue GRPC::Cancelled
|
375
|
+
assert("#{__callee__}: call operation should be CANCELLED") { op.cancelled }
|
376
|
+
op.wait
|
377
|
+
p "OK: #{__callee__}"
|
378
|
+
end
|
379
|
+
|
380
|
+
def all
|
381
|
+
all_methods = NamedTests.instance_methods(false).map(&:to_s)
|
382
|
+
all_methods.each do |m|
|
383
|
+
next if m == 'all' || m.start_with?('assert')
|
384
|
+
p "TESTCASE: #{m}"
|
385
|
+
method(m).call
|
386
|
+
end
|
387
|
+
end
|
388
|
+
|
389
|
+
private
|
390
|
+
|
391
|
+
def perform_large_unary(fill_username: false, fill_oauth_scope: false, **kw)
|
392
|
+
req_size, wanted_response_size = 271_828, 314_159
|
393
|
+
payload = Payload.new(type: :COMPRESSABLE, body: nulls(req_size))
|
394
|
+
req = SimpleRequest.new(response_type: :COMPRESSABLE,
|
395
|
+
response_size: wanted_response_size,
|
396
|
+
payload: payload)
|
397
|
+
req.fill_username = fill_username
|
398
|
+
req.fill_oauth_scope = fill_oauth_scope
|
399
|
+
resp = @stub.unary_call(req, **kw)
|
400
|
+
assert('payload type is wrong') do
|
401
|
+
:COMPRESSABLE == resp.payload.type
|
402
|
+
end
|
403
|
+
assert('payload body has the wrong length') do
|
404
|
+
wanted_response_size == resp.payload.body.length
|
405
|
+
end
|
406
|
+
assert('payload body is invalid') do
|
407
|
+
nulls(wanted_response_size) == resp.payload.body
|
408
|
+
end
|
409
|
+
resp
|
410
|
+
end
|
411
|
+
end
|
412
|
+
|
413
|
+
# Args is used to hold the command line info.
|
414
|
+
Args = Struct.new(:default_service_account, :host, :host_override,
|
415
|
+
:oauth_scope, :port, :secure, :test_case,
|
416
|
+
:use_test_ca)
|
417
|
+
|
418
|
+
# validates the the command line options, returning them as a Hash.
|
419
|
+
def parse_args
|
420
|
+
args = Args.new
|
421
|
+
args.host_override = 'foo.test.google.fr'
|
422
|
+
OptionParser.new do |opts|
|
423
|
+
opts.on('--oauth_scope scope',
|
424
|
+
'Scope for OAuth tokens') { |v| args['oauth_scope'] = v }
|
425
|
+
opts.on('--server_host SERVER_HOST', 'server hostname') do |v|
|
426
|
+
args['host'] = v
|
427
|
+
end
|
428
|
+
opts.on('--default_service_account email_address',
|
429
|
+
'email address of the default service account') do |v|
|
430
|
+
args['default_service_account'] = v
|
431
|
+
end
|
432
|
+
opts.on('--server_host_override HOST_OVERRIDE',
|
433
|
+
'override host via a HTTP header') do |v|
|
434
|
+
args['host_override'] = v
|
435
|
+
end
|
436
|
+
opts.on('--server_port SERVER_PORT', 'server port') { |v| args['port'] = v }
|
437
|
+
# instance_methods(false) gives only the methods defined in that class
|
438
|
+
test_cases = NamedTests.instance_methods(false).map(&:to_s)
|
439
|
+
test_case_list = test_cases.join(',')
|
440
|
+
opts.on('--test_case CODE', test_cases, {}, 'select a test_case',
|
441
|
+
" (#{test_case_list})") { |v| args['test_case'] = v }
|
442
|
+
opts.on('--use_tls USE_TLS', ['false', 'true'],
|
443
|
+
'require a secure connection?') do |v|
|
444
|
+
args['secure'] = v == 'true'
|
445
|
+
end
|
446
|
+
opts.on('--use_test_ca USE_TEST_CA', ['false', 'true'],
|
447
|
+
'if secure, use the test certificate?') do |v|
|
448
|
+
args['use_test_ca'] = v == 'true'
|
449
|
+
end
|
450
|
+
end.parse!
|
451
|
+
_check_args(args)
|
452
|
+
end
|
453
|
+
|
454
|
+
def _check_args(args)
|
455
|
+
%w(host port test_case).each do |a|
|
456
|
+
if args[a].nil?
|
457
|
+
fail(OptionParser::MissingArgument, "please specify --#{a}")
|
458
|
+
end
|
459
|
+
end
|
460
|
+
args
|
461
|
+
end
|
462
|
+
|
463
|
+
def main
|
464
|
+
opts = parse_args
|
465
|
+
stub = create_stub(opts)
|
466
|
+
NamedTests.new(stub, opts).method(opts['test_case']).call
|
467
|
+
end
|
468
|
+
|
469
|
+
main
|