• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Copyright 2015 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
15require 'spec_helper'
16require 'English'
17
18def load_test_certs
19  test_root = File.join(File.dirname(__FILE__), 'testdata')
20  files = ['ca.pem', 'server1.key', 'server1.pem']
21  files.map { |f| File.open(File.join(test_root, f)).read }
22end
23
24describe GRPC::Core::Channel do
25  let(:fake_host) { 'localhost:0' }
26
27  def create_test_cert
28    GRPC::Core::ChannelCredentials.new(load_test_certs[0])
29  end
30
31  def fork_with_propagated_error_message
32    pipe_read, pipe_write = IO.pipe
33    pid = fork do
34      pipe_read.close
35      begin
36        yield
37      rescue => exc
38        pipe_write.syswrite(exc.message)
39      end
40      pipe_write.close
41    end
42    pipe_write.close
43
44    exc_message = pipe_read.read
45    Process.wait(pid)
46
47    unless $CHILD_STATUS.success?
48      raise "forked process failed with #{$CHILD_STATUS}"
49    end
50    raise exc_message unless exc_message.empty?
51  end
52
53  shared_examples '#new' do
54    it 'take a host name without channel args' do
55      blk = proc do
56        GRPC::Core::Channel.new('dummy_host', nil, :this_channel_is_insecure)
57      end
58      expect(&blk).not_to raise_error
59    end
60
61    it 'does not take a hash with bad keys as channel args' do
62      blk = construct_with_args(Object.new => 1)
63      expect(&blk).to raise_error TypeError
64      blk = construct_with_args(1 => 1)
65      expect(&blk).to raise_error TypeError
66    end
67
68    it 'does not take a hash with bad values as channel args' do
69      blk = construct_with_args(symbol: Object.new)
70      expect(&blk).to raise_error TypeError
71      blk = construct_with_args('1' => {})
72      expect(&blk).to raise_error TypeError
73    end
74
75    it 'can take a hash with a symbol key as channel args' do
76      blk = construct_with_args(a_symbol: 1)
77      expect(&blk).to_not raise_error
78    end
79
80    it 'can take a hash with a string key as channel args' do
81      blk = construct_with_args('a_symbol' => 1)
82      expect(&blk).to_not raise_error
83    end
84
85    it 'can take a hash with a string value as channel args' do
86      blk = construct_with_args(a_symbol: '1')
87      expect(&blk).to_not raise_error
88    end
89
90    it 'can take a hash with a symbol value as channel args' do
91      blk = construct_with_args(a_symbol: :another_symbol)
92      expect(&blk).to_not raise_error
93    end
94
95    it 'can take a hash with a numeric value as channel args' do
96      blk = construct_with_args(a_symbol: 1)
97      expect(&blk).to_not raise_error
98    end
99
100    it 'can take a hash with many args as channel args' do
101      args = Hash[127.times.collect { |x| [x.to_s, x] }]
102      blk = construct_with_args(args)
103      expect(&blk).to_not raise_error
104    end
105
106    it 'raises if grpc was initialized in another process' do
107      blk = construct_with_args({})
108      expect(&blk).not_to raise_error
109      expect do
110        fork_with_propagated_error_message(&blk)
111      end.to raise_error(RuntimeError, 'grpc cannot be used before and after forking')
112    end
113  end
114
115  describe '#new for secure channels' do
116    def construct_with_args(a)
117      proc { GRPC::Core::Channel.new('dummy_host', a, create_test_cert) }
118    end
119
120    it_behaves_like '#new'
121  end
122
123  describe '#new for insecure channels' do
124    it_behaves_like '#new'
125
126    def construct_with_args(a)
127      proc do
128        GRPC::Core::Channel.new('dummy_host', a, :this_channel_is_insecure)
129      end
130    end
131  end
132
133  describe '#create_call' do
134    it 'creates a call OK' do
135      ch = GRPC::Core::Channel.new(fake_host, nil, :this_channel_is_insecure)
136
137      deadline = Time.now + 5
138
139      blk = proc do
140        ch.create_call(nil, nil, 'dummy_method', nil, deadline)
141      end
142      expect(&blk).to_not raise_error
143    end
144
145    it 'raises an error if called on a closed channel' do
146      ch = GRPC::Core::Channel.new(fake_host, nil, :this_channel_is_insecure)
147      ch.close
148
149      deadline = Time.now + 5
150      blk = proc do
151        ch.create_call(nil, nil, 'dummy_method', nil, deadline)
152      end
153      expect(&blk).to raise_error(RuntimeError)
154    end
155
156    it 'raises if grpc was initialized in another process' do
157      ch = GRPC::Core::Channel.new(fake_host, nil, :this_channel_is_insecure)
158
159      deadline = Time.now + 5
160
161      blk = proc do
162        fork_with_propagated_error_message do
163          ch.create_call(nil, nil, 'dummy_method', nil, deadline)
164        end
165      end
166      expect(&blk).to raise_error(RuntimeError, 'grpc cannot be used before and after forking')
167    end
168  end
169
170  describe '#destroy' do
171    it 'destroys a channel ok' do
172      ch = GRPC::Core::Channel.new(fake_host, nil, :this_channel_is_insecure)
173      blk = proc { ch.destroy }
174      expect(&blk).to_not raise_error
175    end
176
177    it 'can be called more than once without error' do
178      ch = GRPC::Core::Channel.new(fake_host, nil, :this_channel_is_insecure)
179      blk = proc { ch.destroy }
180      blk.call
181      expect(&blk).to_not raise_error
182    end
183  end
184
185  describe '#connectivity_state' do
186    it 'returns an enum' do
187      ch = GRPC::Core::Channel.new(fake_host, nil, :this_channel_is_insecure)
188      valid_states = [
189        GRPC::Core::ConnectivityStates::IDLE,
190        GRPC::Core::ConnectivityStates::CONNECTING,
191        GRPC::Core::ConnectivityStates::READY,
192        GRPC::Core::ConnectivityStates::TRANSIENT_FAILURE,
193        GRPC::Core::ConnectivityStates::FATAL_FAILURE
194      ]
195
196      expect(valid_states).to include(ch.connectivity_state)
197    end
198
199    it 'returns an enum when trying to connect' do
200      ch = GRPC::Core::Channel.new(fake_host, nil, :this_channel_is_insecure)
201      ch.connectivity_state(true)
202      valid_states = [
203        GRPC::Core::ConnectivityStates::IDLE,
204        GRPC::Core::ConnectivityStates::CONNECTING,
205        GRPC::Core::ConnectivityStates::READY,
206        GRPC::Core::ConnectivityStates::TRANSIENT_FAILURE,
207        GRPC::Core::ConnectivityStates::FATAL_FAILURE
208      ]
209
210      expect(valid_states).to include(ch.connectivity_state)
211    end
212  end
213
214  describe '::SSL_TARGET' do
215    it 'is a symbol' do
216      expect(GRPC::Core::Channel::SSL_TARGET).to be_a(Symbol)
217    end
218  end
219
220  describe '#close' do
221    it 'closes a channel ok' do
222      ch = GRPC::Core::Channel.new(fake_host, nil, :this_channel_is_insecure)
223      blk = proc { ch.close }
224      expect(&blk).to_not raise_error
225    end
226
227    it 'can be called more than once without error' do
228      ch = GRPC::Core::Channel.new(fake_host, nil, :this_channel_is_insecure)
229      blk = proc { ch.close }
230      blk.call
231      expect(&blk).to_not raise_error
232    end
233  end
234end
235