• 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 'grpc/generic/rpc_desc'
17require 'grpc/generic/service'
18
19# A test message that encodes/decodes using marshal/marshal.
20class GoodMsg
21  def self.marshal(_o)
22    ''
23  end
24
25  def self.unmarshal(_o)
26    GoodMsg.new
27  end
28end
29
30# A test message that encodes/decodes using encode/decode.
31class EncodeDecodeMsg
32  def self.encode(_o)
33    ''
34  end
35
36  def self.decode(_o)
37    GoodMsg.new
38  end
39end
40
41GenericService = GRPC::GenericService
42Dsl = GenericService::Dsl
43
44describe Dsl do
45  it 'can be included in new classes' do
46    blk = proc { Class.new { include Dsl } }
47    expect(&blk).to_not raise_error
48  end
49end
50
51describe GenericService do
52  context '#underscore' do
53    it 'should convert CamelCase to underscore separated' do
54      expect(GenericService.underscore('AnRPC')).to eq('an_rpc')
55      expect(GenericService.underscore('AMethod')).to eq('a_method')
56      expect(GenericService.underscore('PrintHTML')).to eq('print_html')
57      expect(GenericService.underscore('SeeHTMLBooks')).to eq('see_html_books')
58    end
59  end
60
61  describe 'including it' do
62    it 'adds a class method, rpc' do
63      c = Class.new do
64        include GenericService
65      end
66      expect(c.methods).to include(:rpc)
67    end
68
69    it 'adds rpc descs using the added class method, #rpc' do
70      c = Class.new do
71        include GenericService
72        rpc :AnRpc, GoodMsg, GoodMsg
73      end
74
75      expect(c.rpc_descs).to include(:AnRpc)
76      expect(c.rpc_descs[:AnRpc]).to be_a(GRPC::RpcDesc)
77    end
78
79    it 'give subclasses access to #rpc_descs' do
80      base = Class.new do
81        include GenericService
82        rpc :AnRpc, GoodMsg, GoodMsg
83      end
84      c = Class.new(base) do
85      end
86      expect(c.rpc_descs).to include(:AnRpc)
87      expect(c.rpc_descs[:AnRpc]).to be_a(GRPC::RpcDesc)
88    end
89
90    it 'adds a default service name' do
91      c = Class.new do
92        include GenericService
93      end
94      expect(c.service_name).to eq('GenericService')
95    end
96
97    it 'adds a default service name to subclasses' do
98      base = Class.new do
99        include GenericService
100      end
101      c = Class.new(base) do
102      end
103      expect(c.service_name).to eq('GenericService')
104    end
105
106    it 'adds the specified service name' do
107      c = Class.new do
108        include GenericService
109        self.service_name = 'test.service.TestService'
110      end
111      expect(c.service_name).to eq('test.service.TestService')
112    end
113
114    it 'adds the specified service name to subclasses' do
115      base = Class.new do
116        include GenericService
117        self.service_name = 'test.service.TestService'
118      end
119      c = Class.new(base) do
120      end
121      expect(c.service_name).to eq('test.service.TestService')
122    end
123  end
124
125  describe '#include' do
126    it 'raises if #rpc is missing an arg' do
127      blk = proc do
128        Class.new do
129          include GenericService
130          rpc :AnRpc, GoodMsg
131        end
132      end
133      expect(&blk).to raise_error ArgumentError
134
135      blk = proc do
136        Class.new do
137          include GenericService
138          rpc :AnRpc
139        end
140      end
141      expect(&blk).to raise_error ArgumentError
142    end
143
144    describe 'when #rpc args are incorrect' do
145      it 'raises if an arg does not have the marshal or unmarshal methods' do
146        blk = proc do
147          Class.new do
148            include GenericService
149            rpc :AnRpc, GoodMsg, Object
150          end
151        end
152        expect(&blk).to raise_error ArgumentError
153      end
154
155      it 'raises if a type arg only has the marshal method' do
156        # a bad message type with only a marshal method
157        class OnlyMarshal
158          def marshal(o)
159            o
160          end
161        end
162
163        blk = proc do
164          Class.new do
165            include GenericService
166            rpc :AnRpc, OnlyMarshal, GoodMsg
167          end
168        end
169        expect(&blk).to raise_error ArgumentError
170      end
171
172      it 'raises if a type arg only has the unmarshal method' do
173        # a bad message type with only an unmarshal method
174        class OnlyUnmarshal
175          def self.ummarshal(o)
176            o
177          end
178        end
179        blk = proc do
180          Class.new do
181            include GenericService
182            rpc :AnRpc, GoodMsg, OnlyUnmarshal
183          end
184        end
185        expect(&blk).to raise_error ArgumentError
186      end
187    end
188
189    it 'is ok for services that expect the default {un,}marshal methods' do
190      blk = proc do
191        Class.new do
192          include GenericService
193          rpc :AnRpc, GoodMsg, GoodMsg
194        end
195      end
196      expect(&blk).not_to raise_error
197    end
198
199    it 'is ok for services that override the default {un,}marshal methods' do
200      blk = proc do
201        Class.new do
202          include GenericService
203          self.marshal_class_method = :encode
204          self.unmarshal_class_method = :decode
205          rpc :AnRpc, EncodeDecodeMsg, EncodeDecodeMsg
206        end
207      end
208      expect(&blk).not_to raise_error
209    end
210  end
211
212  describe '#rpc_stub_class' do
213    it 'generates a client class that defines any of the rpc methods' do
214      s = Class.new do
215        include GenericService
216        rpc :AnRpc, GoodMsg, GoodMsg
217        rpc :AServerStreamer, GoodMsg, stream(GoodMsg)
218        rpc :AClientStreamer, stream(GoodMsg), GoodMsg
219        rpc :ABidiStreamer, stream(GoodMsg), stream(GoodMsg)
220      end
221      client_class = s.rpc_stub_class
222      expect(client_class.instance_methods).to include(:an_rpc)
223      expect(client_class.instance_methods).to include(:a_server_streamer)
224      expect(client_class.instance_methods).to include(:a_client_streamer)
225      expect(client_class.instance_methods).to include(:a_bidi_streamer)
226    end
227
228    describe 'the generated instances' do
229      it 'can be instanciated with just a hostname and credentials' do
230        s = Class.new do
231          include GenericService
232          rpc :AnRpc, GoodMsg, GoodMsg
233          rpc :AServerStreamer, GoodMsg, stream(GoodMsg)
234          rpc :AClientStreamer, stream(GoodMsg), GoodMsg
235          rpc :ABidiStreamer, stream(GoodMsg), stream(GoodMsg)
236        end
237        client_class = s.rpc_stub_class
238        blk = proc do
239          client_class.new('fakehostname', :this_channel_is_insecure)
240        end
241        expect(&blk).not_to raise_error
242      end
243
244      it 'has the methods defined in the service' do
245        s = Class.new do
246          include GenericService
247          rpc :AnRpc, GoodMsg, GoodMsg
248          rpc :AServerStreamer, GoodMsg, stream(GoodMsg)
249          rpc :AClientStreamer, stream(GoodMsg), GoodMsg
250          rpc :ABidiStreamer, stream(GoodMsg), stream(GoodMsg)
251        end
252        client_class = s.rpc_stub_class
253        o = client_class.new('fakehostname', :this_channel_is_insecure)
254        expect(o.methods).to include(:an_rpc)
255        expect(o.methods).to include(:a_bidi_streamer)
256        expect(o.methods).to include(:a_client_streamer)
257        expect(o.methods).to include(:a_bidi_streamer)
258      end
259    end
260  end
261end
262