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