grpc 0.13.0.pre1.1-x86-linux
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/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/lib/grpc.rb +44 -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,163 @@
|
|
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
|
+
|
32
|
+
include GRPC::Core::StatusCodes
|
33
|
+
|
34
|
+
describe GRPC::Core::WriteFlags do
|
35
|
+
it 'should define the known write flag values' do
|
36
|
+
m = GRPC::Core::WriteFlags
|
37
|
+
expect(m.const_get(:BUFFER_HINT)).to_not be_nil
|
38
|
+
expect(m.const_get(:NO_COMPRESS)).to_not be_nil
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
describe GRPC::Core::RpcErrors do
|
43
|
+
before(:each) do
|
44
|
+
@known_types = {
|
45
|
+
OK: 0,
|
46
|
+
ERROR: 1,
|
47
|
+
NOT_ON_SERVER: 2,
|
48
|
+
NOT_ON_CLIENT: 3,
|
49
|
+
ALREADY_ACCEPTED: 4,
|
50
|
+
ALREADY_INVOKED: 5,
|
51
|
+
NOT_INVOKED: 6,
|
52
|
+
ALREADY_FINISHED: 7,
|
53
|
+
TOO_MANY_OPERATIONS: 8,
|
54
|
+
INVALID_FLAGS: 9,
|
55
|
+
ErrorMessages: {
|
56
|
+
0 => 'ok',
|
57
|
+
1 => 'unknown error',
|
58
|
+
2 => 'not available on a server',
|
59
|
+
3 => 'not available on a client',
|
60
|
+
4 => 'call is already accepted',
|
61
|
+
5 => 'call is already invoked',
|
62
|
+
6 => 'call is not yet invoked',
|
63
|
+
7 => 'call is already finished',
|
64
|
+
8 => 'outstanding read or write present',
|
65
|
+
9 => 'a bad flag was given'
|
66
|
+
}
|
67
|
+
}
|
68
|
+
end
|
69
|
+
|
70
|
+
it 'should have symbols for all the known error codes' do
|
71
|
+
m = GRPC::Core::RpcErrors
|
72
|
+
syms_and_codes = m.constants.collect { |c| [c, m.const_get(c)] }
|
73
|
+
expect(Hash[syms_and_codes]).to eq(@known_types)
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
describe GRPC::Core::CallOps do
|
78
|
+
before(:each) do
|
79
|
+
@known_types = {
|
80
|
+
SEND_INITIAL_METADATA: 0,
|
81
|
+
SEND_MESSAGE: 1,
|
82
|
+
SEND_CLOSE_FROM_CLIENT: 2,
|
83
|
+
SEND_STATUS_FROM_SERVER: 3,
|
84
|
+
RECV_INITIAL_METADATA: 4,
|
85
|
+
RECV_MESSAGE: 5,
|
86
|
+
RECV_STATUS_ON_CLIENT: 6,
|
87
|
+
RECV_CLOSE_ON_SERVER: 7
|
88
|
+
}
|
89
|
+
end
|
90
|
+
|
91
|
+
it 'should have symbols for all the known operation types' do
|
92
|
+
m = GRPC::Core::CallOps
|
93
|
+
syms_and_codes = m.constants.collect { |c| [c, m.const_get(c)] }
|
94
|
+
expect(Hash[syms_and_codes]).to eq(@known_types)
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
describe GRPC::Core::Call do
|
99
|
+
let(:client_queue) { GRPC::Core::CompletionQueue.new }
|
100
|
+
let(:test_tag) { Object.new }
|
101
|
+
let(:fake_host) { 'localhost:10101' }
|
102
|
+
|
103
|
+
before(:each) do
|
104
|
+
@ch = GRPC::Core::Channel.new(fake_host, nil, :this_channel_is_insecure)
|
105
|
+
end
|
106
|
+
|
107
|
+
describe '#status' do
|
108
|
+
it 'can save the status and read it back' do
|
109
|
+
call = make_test_call
|
110
|
+
sts = Struct::Status.new(OK, 'OK')
|
111
|
+
expect { call.status = sts }.not_to raise_error
|
112
|
+
expect(call.status).to eq(sts)
|
113
|
+
end
|
114
|
+
|
115
|
+
it 'must be set to a status' do
|
116
|
+
call = make_test_call
|
117
|
+
bad_sts = Object.new
|
118
|
+
expect { call.status = bad_sts }.to raise_error(TypeError)
|
119
|
+
end
|
120
|
+
|
121
|
+
it 'can be set to nil' do
|
122
|
+
call = make_test_call
|
123
|
+
expect { call.status = nil }.not_to raise_error
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
describe '#metadata' do
|
128
|
+
it 'can save the metadata hash and read it back' do
|
129
|
+
call = make_test_call
|
130
|
+
md = { 'k1' => 'v1', 'k2' => 'v2' }
|
131
|
+
expect { call.metadata = md }.not_to raise_error
|
132
|
+
expect(call.metadata).to be(md)
|
133
|
+
end
|
134
|
+
|
135
|
+
it 'must be set with a hash' do
|
136
|
+
call = make_test_call
|
137
|
+
bad_md = Object.new
|
138
|
+
expect { call.metadata = bad_md }.to raise_error(TypeError)
|
139
|
+
end
|
140
|
+
|
141
|
+
it 'can be set to nil' do
|
142
|
+
call = make_test_call
|
143
|
+
expect { call.metadata = nil }.not_to raise_error
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
describe '#set_credentials!' do
|
148
|
+
it 'can set a valid CallCredentials object' do
|
149
|
+
call = make_test_call
|
150
|
+
auth_proc = proc { { 'plugin_key' => 'plugin_value' } }
|
151
|
+
creds = GRPC::Core::CallCredentials.new auth_proc
|
152
|
+
expect { call.set_credentials! creds }.not_to raise_error
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
def make_test_call
|
157
|
+
@ch.create_call(client_queue, nil, nil, 'dummy_method', nil, deadline)
|
158
|
+
end
|
159
|
+
|
160
|
+
def deadline
|
161
|
+
Time.now + 2 # in 2 seconds; arbitrary
|
162
|
+
end
|
163
|
+
end
|
@@ -0,0 +1,97 @@
|
|
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
|
+
|
32
|
+
describe GRPC::Core::ChannelCredentials do
|
33
|
+
ChannelCredentials = GRPC::Core::ChannelCredentials
|
34
|
+
CallCredentials = GRPC::Core::CallCredentials
|
35
|
+
|
36
|
+
def load_test_certs
|
37
|
+
test_root = File.join(File.dirname(__FILE__), 'testdata')
|
38
|
+
files = ['ca.pem', 'server1.pem', 'server1.key']
|
39
|
+
files.map { |f| File.open(File.join(test_root, f)).read }
|
40
|
+
end
|
41
|
+
|
42
|
+
describe '#new' do
|
43
|
+
it 'can be constructed with fake inputs' do
|
44
|
+
blk = proc { ChannelCredentials.new('root_certs', 'key', 'cert') }
|
45
|
+
expect(&blk).not_to raise_error
|
46
|
+
end
|
47
|
+
|
48
|
+
it 'it can be constructed using specific test certificates' do
|
49
|
+
certs = load_test_certs
|
50
|
+
expect { ChannelCredentials.new(*certs) }.not_to raise_error
|
51
|
+
end
|
52
|
+
|
53
|
+
it 'can be constructed with server roots certs only' do
|
54
|
+
root_cert, _, _ = load_test_certs
|
55
|
+
expect { ChannelCredentials.new(root_cert) }.not_to raise_error
|
56
|
+
end
|
57
|
+
|
58
|
+
it 'can be constructed with a nil server roots' do
|
59
|
+
_, client_key, client_chain = load_test_certs
|
60
|
+
blk = proc { ChannelCredentials.new(nil, client_key, client_chain) }
|
61
|
+
expect(&blk).not_to raise_error
|
62
|
+
end
|
63
|
+
|
64
|
+
it 'can be constructed with no params' do
|
65
|
+
blk = proc { ChannelCredentials.new(nil) }
|
66
|
+
expect(&blk).not_to raise_error
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
describe '#compose' do
|
71
|
+
it 'can compose with a CallCredentials' do
|
72
|
+
certs = load_test_certs
|
73
|
+
channel_creds = ChannelCredentials.new(*certs)
|
74
|
+
auth_proc = proc { { 'plugin_key' => 'plugin_value' } }
|
75
|
+
call_creds = CallCredentials.new auth_proc
|
76
|
+
expect { channel_creds.compose call_creds }.not_to raise_error
|
77
|
+
end
|
78
|
+
|
79
|
+
it 'can compose with multiple CallCredentials' do
|
80
|
+
certs = load_test_certs
|
81
|
+
channel_creds = ChannelCredentials.new(*certs)
|
82
|
+
auth_proc = proc { { 'plugin_key' => 'plugin_value' } }
|
83
|
+
call_creds1 = CallCredentials.new auth_proc
|
84
|
+
call_creds2 = CallCredentials.new auth_proc
|
85
|
+
expect do
|
86
|
+
channel_creds.compose(call_creds1, call_creds2)
|
87
|
+
end.not_to raise_error
|
88
|
+
end
|
89
|
+
|
90
|
+
it 'cannot compose with ChannelCredentials' do
|
91
|
+
certs = load_test_certs
|
92
|
+
channel_creds1 = ChannelCredentials.new(*certs)
|
93
|
+
channel_creds2 = ChannelCredentials.new(*certs)
|
94
|
+
expect { channel_creds1.compose channel_creds2 }.to raise_error(TypeError)
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
@@ -0,0 +1,177 @@
|
|
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
|
+
|
32
|
+
def load_test_certs
|
33
|
+
test_root = File.join(File.dirname(__FILE__), 'testdata')
|
34
|
+
files = ['ca.pem', 'server1.key', 'server1.pem']
|
35
|
+
files.map { |f| File.open(File.join(test_root, f)).read }
|
36
|
+
end
|
37
|
+
|
38
|
+
describe GRPC::Core::Channel do
|
39
|
+
let(:fake_host) { 'localhost:0' }
|
40
|
+
let(:cq) { GRPC::Core::CompletionQueue.new }
|
41
|
+
|
42
|
+
def create_test_cert
|
43
|
+
GRPC::Core::ChannelCredentials.new(load_test_certs[0])
|
44
|
+
end
|
45
|
+
|
46
|
+
shared_examples '#new' do
|
47
|
+
it 'take a host name without channel args' do
|
48
|
+
blk = proc do
|
49
|
+
GRPC::Core::Channel.new('dummy_host', nil, :this_channel_is_insecure)
|
50
|
+
end
|
51
|
+
expect(&blk).not_to raise_error
|
52
|
+
end
|
53
|
+
|
54
|
+
it 'does not take a hash with bad keys as channel args' do
|
55
|
+
blk = construct_with_args(Object.new => 1)
|
56
|
+
expect(&blk).to raise_error TypeError
|
57
|
+
blk = construct_with_args(1 => 1)
|
58
|
+
expect(&blk).to raise_error TypeError
|
59
|
+
end
|
60
|
+
|
61
|
+
it 'does not take a hash with bad values as channel args' do
|
62
|
+
blk = construct_with_args(symbol: Object.new)
|
63
|
+
expect(&blk).to raise_error TypeError
|
64
|
+
blk = construct_with_args('1' => {})
|
65
|
+
expect(&blk).to raise_error TypeError
|
66
|
+
end
|
67
|
+
|
68
|
+
it 'can take a hash with a symbol key as channel args' do
|
69
|
+
blk = construct_with_args(a_symbol: 1)
|
70
|
+
expect(&blk).to_not raise_error
|
71
|
+
end
|
72
|
+
|
73
|
+
it 'can take a hash with a string key as channel args' do
|
74
|
+
blk = construct_with_args('a_symbol' => 1)
|
75
|
+
expect(&blk).to_not raise_error
|
76
|
+
end
|
77
|
+
|
78
|
+
it 'can take a hash with a string value as channel args' do
|
79
|
+
blk = construct_with_args(a_symbol: '1')
|
80
|
+
expect(&blk).to_not raise_error
|
81
|
+
end
|
82
|
+
|
83
|
+
it 'can take a hash with a symbol value as channel args' do
|
84
|
+
blk = construct_with_args(a_symbol: :another_symbol)
|
85
|
+
expect(&blk).to_not raise_error
|
86
|
+
end
|
87
|
+
|
88
|
+
it 'can take a hash with a numeric value as channel args' do
|
89
|
+
blk = construct_with_args(a_symbol: 1)
|
90
|
+
expect(&blk).to_not raise_error
|
91
|
+
end
|
92
|
+
|
93
|
+
it 'can take a hash with many args as channel args' do
|
94
|
+
args = Hash[127.times.collect { |x| [x.to_s, x] }]
|
95
|
+
blk = construct_with_args(args)
|
96
|
+
expect(&blk).to_not raise_error
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
describe '#new for secure channels' do
|
101
|
+
def construct_with_args(a)
|
102
|
+
proc { GRPC::Core::Channel.new('dummy_host', a, create_test_cert) }
|
103
|
+
end
|
104
|
+
|
105
|
+
it_behaves_like '#new'
|
106
|
+
end
|
107
|
+
|
108
|
+
describe '#new for insecure channels' do
|
109
|
+
it_behaves_like '#new'
|
110
|
+
|
111
|
+
def construct_with_args(a)
|
112
|
+
proc do
|
113
|
+
GRPC::Core::Channel.new('dummy_host', a, :this_channel_is_insecure)
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
describe '#create_call' do
|
119
|
+
it 'creates a call OK' do
|
120
|
+
ch = GRPC::Core::Channel.new(fake_host, nil, :this_channel_is_insecure)
|
121
|
+
|
122
|
+
deadline = Time.now + 5
|
123
|
+
|
124
|
+
blk = proc do
|
125
|
+
ch.create_call(cq, nil, nil, 'dummy_method', nil, deadline)
|
126
|
+
end
|
127
|
+
expect(&blk).to_not raise_error
|
128
|
+
end
|
129
|
+
|
130
|
+
it 'raises an error if called on a closed channel' do
|
131
|
+
ch = GRPC::Core::Channel.new(fake_host, nil, :this_channel_is_insecure)
|
132
|
+
ch.close
|
133
|
+
|
134
|
+
deadline = Time.now + 5
|
135
|
+
blk = proc do
|
136
|
+
ch.create_call(cq, nil, nil, 'dummy_method', nil, deadline)
|
137
|
+
end
|
138
|
+
expect(&blk).to raise_error(RuntimeError)
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
describe '#destroy' do
|
143
|
+
it 'destroys a channel ok' do
|
144
|
+
ch = GRPC::Core::Channel.new(fake_host, nil, :this_channel_is_insecure)
|
145
|
+
blk = proc { ch.destroy }
|
146
|
+
expect(&blk).to_not raise_error
|
147
|
+
end
|
148
|
+
|
149
|
+
it 'can be called more than once without error' do
|
150
|
+
ch = GRPC::Core::Channel.new(fake_host, nil, :this_channel_is_insecure)
|
151
|
+
blk = proc { ch.destroy }
|
152
|
+
blk.call
|
153
|
+
expect(&blk).to_not raise_error
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
describe '::SSL_TARGET' do
|
158
|
+
it 'is a symbol' do
|
159
|
+
expect(GRPC::Core::Channel::SSL_TARGET).to be_a(Symbol)
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
describe '#close' do
|
164
|
+
it 'closes a channel ok' do
|
165
|
+
ch = GRPC::Core::Channel.new(fake_host, nil, :this_channel_is_insecure)
|
166
|
+
blk = proc { ch.close }
|
167
|
+
expect(&blk).to_not raise_error
|
168
|
+
end
|
169
|
+
|
170
|
+
it 'can be called more than once without error' do
|
171
|
+
ch = GRPC::Core::Channel.new(fake_host, nil, :this_channel_is_insecure)
|
172
|
+
blk = proc { ch.close }
|
173
|
+
blk.call
|
174
|
+
expect(&blk).to_not raise_error
|
175
|
+
end
|
176
|
+
end
|
177
|
+
end
|
@@ -0,0 +1,475 @@
|
|
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
|
+
|
32
|
+
include GRPC::Core
|
33
|
+
|
34
|
+
shared_context 'setup: tags' do
|
35
|
+
let(:sent_message) { 'sent message' }
|
36
|
+
let(:reply_text) { 'the reply' }
|
37
|
+
before(:example) do
|
38
|
+
@client_tag = Object.new
|
39
|
+
@server_tag = Object.new
|
40
|
+
end
|
41
|
+
|
42
|
+
def deadline
|
43
|
+
Time.now + 5
|
44
|
+
end
|
45
|
+
|
46
|
+
def server_allows_client_to_proceed
|
47
|
+
recvd_rpc = @server.request_call(@server_queue, @server_tag, deadline)
|
48
|
+
expect(recvd_rpc).to_not eq nil
|
49
|
+
server_call = recvd_rpc.call
|
50
|
+
ops = { CallOps::SEND_INITIAL_METADATA => {} }
|
51
|
+
svr_batch = server_call.run_batch(@server_queue, @server_tag, deadline, ops)
|
52
|
+
expect(svr_batch.send_metadata).to be true
|
53
|
+
server_call
|
54
|
+
end
|
55
|
+
|
56
|
+
def new_client_call
|
57
|
+
@ch.create_call(@client_queue, nil, nil, '/method', nil, deadline)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
shared_examples 'basic GRPC message delivery is OK' do
|
62
|
+
include GRPC::Core
|
63
|
+
include_context 'setup: tags'
|
64
|
+
|
65
|
+
context 'the test channel' do
|
66
|
+
it 'should have a target' do
|
67
|
+
expect(@ch.target).to be_a(String)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
context 'a client call' do
|
72
|
+
it 'should have a peer' do
|
73
|
+
expect(new_client_call.peer).to be_a(String)
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
it 'calls have peer info' do
|
78
|
+
call = new_client_call
|
79
|
+
expect(call.peer).to be_a(String)
|
80
|
+
end
|
81
|
+
|
82
|
+
it 'servers receive requests from clients and can respond' do
|
83
|
+
call = new_client_call
|
84
|
+
server_call = nil
|
85
|
+
|
86
|
+
server_thread = Thread.new do
|
87
|
+
server_call = server_allows_client_to_proceed
|
88
|
+
end
|
89
|
+
|
90
|
+
client_ops = {
|
91
|
+
CallOps::SEND_INITIAL_METADATA => {},
|
92
|
+
CallOps::SEND_MESSAGE => sent_message
|
93
|
+
}
|
94
|
+
batch_result = call.run_batch(@client_queue, @client_tag, deadline,
|
95
|
+
client_ops)
|
96
|
+
expect(batch_result.send_metadata).to be true
|
97
|
+
expect(batch_result.send_message).to be true
|
98
|
+
|
99
|
+
# confirm the server can read the inbound message
|
100
|
+
server_thread.join
|
101
|
+
server_ops = {
|
102
|
+
CallOps::RECV_MESSAGE => nil
|
103
|
+
}
|
104
|
+
svr_batch = server_call.run_batch(@server_queue, @server_tag, deadline,
|
105
|
+
server_ops)
|
106
|
+
expect(svr_batch.message).to eq(sent_message)
|
107
|
+
end
|
108
|
+
|
109
|
+
it 'responses written by servers are received by the client' do
|
110
|
+
call = new_client_call
|
111
|
+
server_call = nil
|
112
|
+
|
113
|
+
server_thread = Thread.new do
|
114
|
+
server_call = server_allows_client_to_proceed
|
115
|
+
end
|
116
|
+
|
117
|
+
client_ops = {
|
118
|
+
CallOps::SEND_INITIAL_METADATA => {},
|
119
|
+
CallOps::SEND_MESSAGE => sent_message
|
120
|
+
}
|
121
|
+
batch_result = call.run_batch(@client_queue, @client_tag, deadline,
|
122
|
+
client_ops)
|
123
|
+
expect(batch_result.send_metadata).to be true
|
124
|
+
expect(batch_result.send_message).to be true
|
125
|
+
|
126
|
+
# confirm the server can read the inbound message
|
127
|
+
server_thread.join
|
128
|
+
server_ops = {
|
129
|
+
CallOps::RECV_MESSAGE => nil,
|
130
|
+
CallOps::SEND_MESSAGE => reply_text
|
131
|
+
}
|
132
|
+
svr_batch = server_call.run_batch(@server_queue, @server_tag, deadline,
|
133
|
+
server_ops)
|
134
|
+
expect(svr_batch.message).to eq(sent_message)
|
135
|
+
expect(svr_batch.send_message).to be true
|
136
|
+
end
|
137
|
+
|
138
|
+
it 'servers can ignore a client write and send a status' do
|
139
|
+
call = new_client_call
|
140
|
+
server_call = nil
|
141
|
+
|
142
|
+
server_thread = Thread.new do
|
143
|
+
server_call = server_allows_client_to_proceed
|
144
|
+
end
|
145
|
+
|
146
|
+
client_ops = {
|
147
|
+
CallOps::SEND_INITIAL_METADATA => {},
|
148
|
+
CallOps::SEND_MESSAGE => sent_message
|
149
|
+
}
|
150
|
+
batch_result = call.run_batch(@client_queue, @client_tag, deadline,
|
151
|
+
client_ops)
|
152
|
+
expect(batch_result.send_metadata).to be true
|
153
|
+
expect(batch_result.send_message).to be true
|
154
|
+
|
155
|
+
# confirm the server can read the inbound message
|
156
|
+
the_status = Struct::Status.new(StatusCodes::OK, 'OK')
|
157
|
+
server_thread.join
|
158
|
+
server_ops = {
|
159
|
+
CallOps::SEND_STATUS_FROM_SERVER => the_status
|
160
|
+
}
|
161
|
+
svr_batch = server_call.run_batch(@server_queue, @server_tag, deadline,
|
162
|
+
server_ops)
|
163
|
+
expect(svr_batch.message).to eq nil
|
164
|
+
expect(svr_batch.send_status).to be true
|
165
|
+
end
|
166
|
+
|
167
|
+
it 'completes calls by sending status to client and server' do
|
168
|
+
call = new_client_call
|
169
|
+
server_call = nil
|
170
|
+
|
171
|
+
server_thread = Thread.new do
|
172
|
+
server_call = server_allows_client_to_proceed
|
173
|
+
end
|
174
|
+
|
175
|
+
client_ops = {
|
176
|
+
CallOps::SEND_INITIAL_METADATA => {},
|
177
|
+
CallOps::SEND_MESSAGE => sent_message
|
178
|
+
}
|
179
|
+
batch_result = call.run_batch(@client_queue, @client_tag, deadline,
|
180
|
+
client_ops)
|
181
|
+
expect(batch_result.send_metadata).to be true
|
182
|
+
expect(batch_result.send_message).to be true
|
183
|
+
|
184
|
+
# confirm the server can read the inbound message and respond
|
185
|
+
the_status = Struct::Status.new(StatusCodes::OK, 'OK', {})
|
186
|
+
server_thread.join
|
187
|
+
server_ops = {
|
188
|
+
CallOps::RECV_MESSAGE => nil,
|
189
|
+
CallOps::SEND_MESSAGE => reply_text,
|
190
|
+
CallOps::SEND_STATUS_FROM_SERVER => the_status
|
191
|
+
}
|
192
|
+
svr_batch = server_call.run_batch(@server_queue, @server_tag, deadline,
|
193
|
+
server_ops)
|
194
|
+
expect(svr_batch.message).to eq sent_message
|
195
|
+
expect(svr_batch.send_status).to be true
|
196
|
+
expect(svr_batch.send_message).to be true
|
197
|
+
|
198
|
+
# confirm the client can receive the server response and status.
|
199
|
+
client_ops = {
|
200
|
+
CallOps::SEND_CLOSE_FROM_CLIENT => nil,
|
201
|
+
CallOps::RECV_MESSAGE => nil,
|
202
|
+
CallOps::RECV_STATUS_ON_CLIENT => nil
|
203
|
+
}
|
204
|
+
batch_result = call.run_batch(@client_queue, @client_tag, deadline,
|
205
|
+
client_ops)
|
206
|
+
expect(batch_result.send_close).to be true
|
207
|
+
expect(batch_result.message).to eq reply_text
|
208
|
+
expect(batch_result.status).to eq the_status
|
209
|
+
|
210
|
+
# confirm the server can receive the client close.
|
211
|
+
server_ops = {
|
212
|
+
CallOps::RECV_CLOSE_ON_SERVER => nil
|
213
|
+
}
|
214
|
+
svr_batch = server_call.run_batch(@server_queue, @server_tag, deadline,
|
215
|
+
server_ops)
|
216
|
+
expect(svr_batch.send_close).to be true
|
217
|
+
end
|
218
|
+
end
|
219
|
+
|
220
|
+
shared_examples 'GRPC metadata delivery works OK' do
|
221
|
+
include_context 'setup: tags'
|
222
|
+
|
223
|
+
describe 'from client => server' do
|
224
|
+
before(:example) do
|
225
|
+
n = 7 # arbitrary number of metadata
|
226
|
+
diff_keys_fn = proc { |i| [format('k%d', i), format('v%d', i)] }
|
227
|
+
diff_keys = Hash[n.times.collect { |x| diff_keys_fn.call x }]
|
228
|
+
null_vals_fn = proc { |i| [format('k%d', i), format('v\0%d', i)] }
|
229
|
+
null_vals = Hash[n.times.collect { |x| null_vals_fn.call x }]
|
230
|
+
same_keys_fn = proc { |i| [format('k%d', i), [format('v%d', i)] * n] }
|
231
|
+
same_keys = Hash[n.times.collect { |x| same_keys_fn.call x }]
|
232
|
+
symbol_key = { a_key: 'a val' }
|
233
|
+
@valid_metadata = [diff_keys, same_keys, null_vals, symbol_key]
|
234
|
+
@bad_keys = []
|
235
|
+
@bad_keys << { Object.new => 'a value' }
|
236
|
+
@bad_keys << { 1 => 'a value' }
|
237
|
+
end
|
238
|
+
|
239
|
+
it 'raises an exception if a metadata key is invalid' do
|
240
|
+
@bad_keys.each do |md|
|
241
|
+
call = new_client_call
|
242
|
+
client_ops = {
|
243
|
+
CallOps::SEND_INITIAL_METADATA => md
|
244
|
+
}
|
245
|
+
blk = proc do
|
246
|
+
call.run_batch(@client_queue, @client_tag, deadline,
|
247
|
+
client_ops)
|
248
|
+
end
|
249
|
+
expect(&blk).to raise_error
|
250
|
+
end
|
251
|
+
end
|
252
|
+
|
253
|
+
it 'sends all the metadata pairs when keys and values are valid' do
|
254
|
+
@valid_metadata.each do |md|
|
255
|
+
recvd_rpc = nil
|
256
|
+
rcv_thread = Thread.new do
|
257
|
+
recvd_rpc = @server.request_call(@server_queue, @server_tag, deadline)
|
258
|
+
end
|
259
|
+
|
260
|
+
call = new_client_call
|
261
|
+
client_ops = {
|
262
|
+
CallOps::SEND_INITIAL_METADATA => md
|
263
|
+
}
|
264
|
+
batch_result = call.run_batch(@client_queue, @client_tag, deadline,
|
265
|
+
client_ops)
|
266
|
+
expect(batch_result.send_metadata).to be true
|
267
|
+
|
268
|
+
# confirm the server can receive the client metadata
|
269
|
+
rcv_thread.join
|
270
|
+
expect(recvd_rpc).to_not eq nil
|
271
|
+
recvd_md = recvd_rpc.metadata
|
272
|
+
replace_symbols = Hash[md.each_pair.collect { |x, y| [x.to_s, y] }]
|
273
|
+
expect(recvd_md).to eq(recvd_md.merge(replace_symbols))
|
274
|
+
end
|
275
|
+
end
|
276
|
+
end
|
277
|
+
|
278
|
+
describe 'from server => client' do
|
279
|
+
before(:example) do
|
280
|
+
n = 7 # arbitrary number of metadata
|
281
|
+
diff_keys_fn = proc { |i| [format('k%d', i), format('v%d', i)] }
|
282
|
+
diff_keys = Hash[n.times.collect { |x| diff_keys_fn.call x }]
|
283
|
+
null_vals_fn = proc { |i| [format('k%d', i), format('v\0%d', i)] }
|
284
|
+
null_vals = Hash[n.times.collect { |x| null_vals_fn.call x }]
|
285
|
+
same_keys_fn = proc { |i| [format('k%d', i), [format('v%d', i)] * n] }
|
286
|
+
same_keys = Hash[n.times.collect { |x| same_keys_fn.call x }]
|
287
|
+
symbol_key = { a_key: 'a val' }
|
288
|
+
@valid_metadata = [diff_keys, same_keys, null_vals, symbol_key]
|
289
|
+
@bad_keys = []
|
290
|
+
@bad_keys << { Object.new => 'a value' }
|
291
|
+
@bad_keys << { 1 => 'a value' }
|
292
|
+
end
|
293
|
+
|
294
|
+
it 'raises an exception if a metadata key is invalid' do
|
295
|
+
@bad_keys.each do |md|
|
296
|
+
recvd_rpc = nil
|
297
|
+
rcv_thread = Thread.new do
|
298
|
+
recvd_rpc = @server.request_call(@server_queue, @server_tag, deadline)
|
299
|
+
end
|
300
|
+
|
301
|
+
call = new_client_call
|
302
|
+
# client signals that it's done sending metadata to allow server to
|
303
|
+
# respond
|
304
|
+
client_ops = {
|
305
|
+
CallOps::SEND_INITIAL_METADATA => nil
|
306
|
+
}
|
307
|
+
call.run_batch(@client_queue, @client_tag, deadline, client_ops)
|
308
|
+
|
309
|
+
# server gets the invocation
|
310
|
+
rcv_thread.join
|
311
|
+
expect(recvd_rpc).to_not eq nil
|
312
|
+
server_ops = {
|
313
|
+
CallOps::SEND_INITIAL_METADATA => md
|
314
|
+
}
|
315
|
+
blk = proc do
|
316
|
+
recvd_rpc.call.run_batch(@server_queue, @server_tag, deadline,
|
317
|
+
server_ops)
|
318
|
+
end
|
319
|
+
expect(&blk).to raise_error
|
320
|
+
end
|
321
|
+
end
|
322
|
+
|
323
|
+
it 'sends an empty hash if no metadata is added' do
|
324
|
+
recvd_rpc = nil
|
325
|
+
rcv_thread = Thread.new do
|
326
|
+
recvd_rpc = @server.request_call(@server_queue, @server_tag, deadline)
|
327
|
+
end
|
328
|
+
|
329
|
+
call = new_client_call
|
330
|
+
# client signals that it's done sending metadata to allow server to
|
331
|
+
# respond
|
332
|
+
client_ops = {
|
333
|
+
CallOps::SEND_INITIAL_METADATA => nil
|
334
|
+
}
|
335
|
+
call.run_batch(@client_queue, @client_tag, deadline, client_ops)
|
336
|
+
|
337
|
+
# server gets the invocation but sends no metadata back
|
338
|
+
rcv_thread.join
|
339
|
+
expect(recvd_rpc).to_not eq nil
|
340
|
+
server_call = recvd_rpc.call
|
341
|
+
server_ops = {
|
342
|
+
CallOps::SEND_INITIAL_METADATA => nil
|
343
|
+
}
|
344
|
+
server_call.run_batch(@server_queue, @server_tag, deadline, server_ops)
|
345
|
+
|
346
|
+
# client receives nothing as expected
|
347
|
+
client_ops = {
|
348
|
+
CallOps::RECV_INITIAL_METADATA => nil
|
349
|
+
}
|
350
|
+
batch_result = call.run_batch(@client_queue, @client_tag, deadline,
|
351
|
+
client_ops)
|
352
|
+
expect(batch_result.metadata).to eq({})
|
353
|
+
end
|
354
|
+
|
355
|
+
it 'sends all the pairs when keys and values are valid' do
|
356
|
+
@valid_metadata.each do |md|
|
357
|
+
recvd_rpc = nil
|
358
|
+
rcv_thread = Thread.new do
|
359
|
+
recvd_rpc = @server.request_call(@server_queue, @server_tag, deadline)
|
360
|
+
end
|
361
|
+
|
362
|
+
call = new_client_call
|
363
|
+
# client signals that it's done sending metadata to allow server to
|
364
|
+
# respond
|
365
|
+
client_ops = {
|
366
|
+
CallOps::SEND_INITIAL_METADATA => nil
|
367
|
+
}
|
368
|
+
call.run_batch(@client_queue, @client_tag, deadline, client_ops)
|
369
|
+
|
370
|
+
# server gets the invocation but sends no metadata back
|
371
|
+
rcv_thread.join
|
372
|
+
expect(recvd_rpc).to_not eq nil
|
373
|
+
server_call = recvd_rpc.call
|
374
|
+
server_ops = {
|
375
|
+
CallOps::SEND_INITIAL_METADATA => md
|
376
|
+
}
|
377
|
+
server_call.run_batch(@server_queue, @server_tag, deadline, server_ops)
|
378
|
+
|
379
|
+
# client receives nothing as expected
|
380
|
+
client_ops = {
|
381
|
+
CallOps::RECV_INITIAL_METADATA => nil
|
382
|
+
}
|
383
|
+
batch_result = call.run_batch(@client_queue, @client_tag, deadline,
|
384
|
+
client_ops)
|
385
|
+
replace_symbols = Hash[md.each_pair.collect { |x, y| [x.to_s, y] }]
|
386
|
+
expect(batch_result.metadata).to eq(replace_symbols)
|
387
|
+
end
|
388
|
+
end
|
389
|
+
end
|
390
|
+
end
|
391
|
+
|
392
|
+
describe 'the http client/server' do
|
393
|
+
before(:example) do
|
394
|
+
server_host = '0.0.0.0:0'
|
395
|
+
@client_queue = GRPC::Core::CompletionQueue.new
|
396
|
+
@server_queue = GRPC::Core::CompletionQueue.new
|
397
|
+
@server = GRPC::Core::Server.new(@server_queue, nil)
|
398
|
+
server_port = @server.add_http2_port(server_host, :this_port_is_insecure)
|
399
|
+
@server.start
|
400
|
+
@ch = Channel.new("0.0.0.0:#{server_port}", nil, :this_channel_is_insecure)
|
401
|
+
end
|
402
|
+
|
403
|
+
after(:example) do
|
404
|
+
@ch.close
|
405
|
+
@server.close(@server_queue, deadline)
|
406
|
+
end
|
407
|
+
|
408
|
+
it_behaves_like 'basic GRPC message delivery is OK' do
|
409
|
+
end
|
410
|
+
|
411
|
+
it_behaves_like 'GRPC metadata delivery works OK' do
|
412
|
+
end
|
413
|
+
end
|
414
|
+
|
415
|
+
describe 'the secure http client/server' do
|
416
|
+
include_context 'setup: tags'
|
417
|
+
|
418
|
+
def load_test_certs
|
419
|
+
test_root = File.join(File.dirname(__FILE__), 'testdata')
|
420
|
+
files = ['ca.pem', 'server1.key', 'server1.pem']
|
421
|
+
files.map { |f| File.open(File.join(test_root, f)).read }
|
422
|
+
end
|
423
|
+
|
424
|
+
before(:example) do
|
425
|
+
certs = load_test_certs
|
426
|
+
server_host = '0.0.0.0:0'
|
427
|
+
@client_queue = GRPC::Core::CompletionQueue.new
|
428
|
+
@server_queue = GRPC::Core::CompletionQueue.new
|
429
|
+
server_creds = GRPC::Core::ServerCredentials.new(
|
430
|
+
nil, [{ private_key: certs[1], cert_chain: certs[2] }], false)
|
431
|
+
@server = GRPC::Core::Server.new(@server_queue, nil)
|
432
|
+
server_port = @server.add_http2_port(server_host, server_creds)
|
433
|
+
@server.start
|
434
|
+
args = { Channel::SSL_TARGET => 'foo.test.google.fr' }
|
435
|
+
@ch = Channel.new("0.0.0.0:#{server_port}", args,
|
436
|
+
GRPC::Core::ChannelCredentials.new(certs[0], nil, nil))
|
437
|
+
end
|
438
|
+
|
439
|
+
after(:example) do
|
440
|
+
@server.close(@server_queue, deadline)
|
441
|
+
end
|
442
|
+
|
443
|
+
it_behaves_like 'basic GRPC message delivery is OK' do
|
444
|
+
end
|
445
|
+
|
446
|
+
it_behaves_like 'GRPC metadata delivery works OK' do
|
447
|
+
end
|
448
|
+
|
449
|
+
it 'modifies metadata with CallCredentials' do
|
450
|
+
auth_proc = proc { { 'k1' => 'updated-v1' } }
|
451
|
+
call_creds = GRPC::Core::CallCredentials.new(auth_proc)
|
452
|
+
md = { 'k2' => 'v2' }
|
453
|
+
expected_md = { 'k1' => 'updated-v1', 'k2' => 'v2' }
|
454
|
+
recvd_rpc = nil
|
455
|
+
rcv_thread = Thread.new do
|
456
|
+
recvd_rpc = @server.request_call(@server_queue, @server_tag, deadline)
|
457
|
+
end
|
458
|
+
|
459
|
+
call = new_client_call
|
460
|
+
call.set_credentials! call_creds
|
461
|
+
client_ops = {
|
462
|
+
CallOps::SEND_INITIAL_METADATA => md
|
463
|
+
}
|
464
|
+
batch_result = call.run_batch(@client_queue, @client_tag, deadline,
|
465
|
+
client_ops)
|
466
|
+
expect(batch_result.send_metadata).to be true
|
467
|
+
|
468
|
+
# confirm the server can receive the client metadata
|
469
|
+
rcv_thread.join
|
470
|
+
expect(recvd_rpc).to_not eq nil
|
471
|
+
recvd_md = recvd_rpc.metadata
|
472
|
+
replace_symbols = Hash[expected_md.each_pair.collect { |x, y| [x.to_s, y] }]
|
473
|
+
expect(recvd_md).to eq(recvd_md.merge(replace_symbols))
|
474
|
+
end
|
475
|
+
end
|