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'
16
17def load_test_certs
18  test_root = File.join(File.dirname(__FILE__), 'testdata')
19  files = ['ca.pem', 'server1.key', 'server1.pem']
20  contents = files.map { |f| File.open(File.join(test_root, f)).read }
21  [contents[0], [{ private_key: contents[1], cert_chain: contents[2] }], false]
22end
23
24Server = GRPC::Core::Server
25
26describe Server do
27  def create_test_cert
28    GRPC::Core::ServerCredentials.new(*load_test_certs)
29  end
30
31  describe '#start' do
32    it 'runs without failing' do
33      blk = proc { new_core_server_for_testing(nil).start }
34      expect(&blk).to_not raise_error
35    end
36
37    it 'fails if the server is closed' do
38      s = new_core_server_for_testing(nil)
39      s.shutdown_and_notify(nil)
40      s.close
41      expect { s.start }.to raise_error(RuntimeError)
42    end
43  end
44
45  describe '#shutdown_and_notify and #destroy' do
46    it 'destroys a server ok' do
47      s = start_a_server
48      blk = proc do
49        s.shutdown_and_notify(nil)
50        s.destroy
51      end
52      expect(&blk).to_not raise_error
53    end
54
55    it 'can be called more than once without error' do
56      s = start_a_server
57      begin
58        blk = proc do
59          s.shutdown_and_notify(nil)
60          s.destroy
61        end
62        expect(&blk).to_not raise_error
63        blk.call
64        expect(&blk).to_not raise_error
65      ensure
66        s.shutdown_and_notify(nil)
67        s.close
68      end
69    end
70  end
71
72  describe '#shutdown_and_notify and #close' do
73    it 'closes a server ok' do
74      s = start_a_server
75      begin
76        blk = proc do
77          s.shutdown_and_notify(nil)
78          s.close
79        end
80        expect(&blk).to_not raise_error
81      ensure
82        s.shutdown_and_notify(nil)
83        s.close
84      end
85    end
86
87    it 'can be called more than once without error' do
88      s = start_a_server
89      blk = proc do
90        s.shutdown_and_notify(nil)
91        s.close
92      end
93      expect(&blk).to_not raise_error
94      blk.call
95      expect(&blk).to_not raise_error
96    end
97  end
98
99  describe '#add_http_port' do
100    describe 'for insecure servers' do
101      it 'runs without failing' do
102        blk = proc do
103          s = new_core_server_for_testing(nil)
104          s.add_http2_port('localhost:0', :this_port_is_insecure)
105          s.shutdown_and_notify(nil)
106          s.close
107        end
108        expect(&blk).to_not raise_error
109      end
110
111      it 'fails if the server is closed' do
112        s = new_core_server_for_testing(nil)
113        s.shutdown_and_notify(nil)
114        s.close
115        blk = proc do
116          s.add_http2_port('localhost:0', :this_port_is_insecure)
117        end
118        expect(&blk).to raise_error(RuntimeError)
119      end
120    end
121
122    describe 'for secure servers' do
123      let(:cert) { create_test_cert }
124      it 'runs without failing' do
125        blk = proc do
126          s = new_core_server_for_testing(nil)
127          s.add_http2_port('localhost:0', cert)
128          s.shutdown_and_notify(nil)
129          s.close
130        end
131        expect(&blk).to_not raise_error
132      end
133
134      it 'fails if the server is closed' do
135        s = new_core_server_for_testing(nil)
136        s.shutdown_and_notify(nil)
137        s.close
138        blk = proc { s.add_http2_port('localhost:0', cert) }
139        expect(&blk).to raise_error(RuntimeError)
140      end
141    end
142  end
143
144  shared_examples '#new' do
145    it 'takes nil channel args' do
146      expect { new_core_server_for_testing(nil) }.to_not raise_error
147    end
148
149    it 'does not take a hash with bad keys as channel args' do
150      blk = construct_with_args(Object.new => 1)
151      expect(&blk).to raise_error TypeError
152      blk = construct_with_args(1 => 1)
153      expect(&blk).to raise_error TypeError
154    end
155
156    it 'does not take a hash with bad values as channel args' do
157      blk = construct_with_args(symbol: Object.new)
158      expect(&blk).to raise_error TypeError
159      blk = construct_with_args('1' => {})
160      expect(&blk).to raise_error TypeError
161    end
162
163    it 'can take a hash with a symbol key as channel args' do
164      blk = construct_with_args(a_symbol: 1)
165      expect(&blk).to_not raise_error
166    end
167
168    it 'can take a hash with a string key as channel args' do
169      blk = construct_with_args('a_symbol' => 1)
170      expect(&blk).to_not raise_error
171    end
172
173    it 'can take a hash with a string value as channel args' do
174      blk = construct_with_args(a_symbol: '1')
175      expect(&blk).to_not raise_error
176    end
177
178    it 'can take a hash with a symbol value as channel args' do
179      blk = construct_with_args(a_symbol: :another_symbol)
180      expect(&blk).to_not raise_error
181    end
182
183    it 'can take a hash with a numeric value as channel args' do
184      blk = construct_with_args(a_symbol: 1)
185      expect(&blk).to_not raise_error
186    end
187
188    it 'can take a hash with many args as channel args' do
189      args = Hash[127.times.collect { |x| [x.to_s, x] }]
190      blk = construct_with_args(args)
191      expect(&blk).to_not raise_error
192    end
193  end
194
195  describe '#new with an insecure channel' do
196    def construct_with_args(a)
197      proc { new_core_server_for_testing(a) }
198    end
199
200    it_behaves_like '#new'
201  end
202
203  def start_a_server
204    s = new_core_server_for_testing(nil)
205    s.add_http2_port('0.0.0.0:0', :this_port_is_insecure)
206    s.start
207    s
208  end
209end
210