1# Copyright 2017 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.
14require 'spec_helper'
15
16describe 'Server Interceptors' do
17  let(:interceptor) { TestServerInterceptor.new }
18  let(:request) { EchoMsg.new }
19  let(:trailing_metadata) { {} }
20  let(:service) { EchoService.new(trailing_metadata) }
21  let(:interceptors) { [] }
22
23  before(:each) do
24    build_rpc_server(server_opts: { interceptors: interceptors })
25  end
26
27  context 'when a server interceptor is added' do
28    let(:interceptors) { [interceptor] }
29    let(:client_metadata) { { client_md: 'test' } }
30    let(:client_call_opts) { { metadata: client_metadata, return_op: true } }
31
32    context 'with a request/response call' do
33      let(:trailing_metadata) { { server_om: 'from_request_response' } }
34
35      it 'should be called', server: true do
36        expect(interceptor).to receive(:request_response)
37          .once.and_call_original
38
39        run_services_on_server(@server, services: [service]) do
40          stub = build_insecure_stub(EchoStub)
41          expect(stub.an_rpc(request)).to be_a(EchoMsg)
42        end
43      end
44
45      it 'can modify trailing metadata', server: true do
46        expect(interceptor).to receive(:request_response)
47          .once.and_call_original
48
49        run_services_on_server(@server, services: [service]) do
50          stub = build_insecure_stub(EchoStub)
51          expect_any_instance_of(GRPC::ActiveCall).to(
52            receive(:request_response).with(request, metadata: client_metadata)
53              .once.and_call_original
54          )
55          op = stub.an_rpc(request, client_call_opts)
56          msg = op.execute
57          expect(op.trailing_metadata).to eq(
58            'interc' => 'from_request_response',
59            'server_om' => 'from_request_response'
60          )
61          expect(msg).to be_a(EchoMsg)
62        end
63      end
64    end
65
66    context 'with a client streaming call' do
67      let(:trailing_metadata) { { server_om: 'from_client_streamer' } }
68      let(:requests) { [EchoMsg.new, EchoMsg.new] }
69
70      it 'should be called', server: true do
71        expect(interceptor).to receive(:client_streamer)
72          .once.and_call_original
73
74        run_services_on_server(@server, services: [service]) do
75          stub = build_insecure_stub(EchoStub)
76          expect(stub.a_client_streaming_rpc(requests)).to be_a(EchoMsg)
77        end
78      end
79
80      it 'can modify trailing metadata', server: true do
81        expect(interceptor).to receive(:client_streamer)
82          .once.and_call_original
83
84        run_services_on_server(@server, services: [service]) do
85          stub = build_insecure_stub(EchoStub)
86          expect_any_instance_of(GRPC::ActiveCall).to(
87            receive(:client_streamer).with(requests)
88              .once.and_call_original
89          )
90          op = stub.a_client_streaming_rpc(requests, client_call_opts)
91          msg = op.execute
92          expect(op.trailing_metadata).to eq(
93            'interc' => 'from_client_streamer',
94            'server_om' => 'from_client_streamer'
95          )
96          expect(msg).to be_a(EchoMsg)
97        end
98      end
99    end
100
101    context 'with a server streaming call' do
102      let(:trailing_metadata) { { server_om: 'from_server_streamer' } }
103      let(:request) { EchoMsg.new }
104
105      it 'should be called', server: true do
106        expect(interceptor).to receive(:server_streamer)
107          .once.and_call_original
108
109        run_services_on_server(@server, services: [service]) do
110          stub = build_insecure_stub(EchoStub)
111          responses = stub.a_server_streaming_rpc(request)
112          responses.each do |r|
113            expect(r).to be_a(EchoMsg)
114          end
115        end
116      end
117
118      it 'can modify trailing metadata', server: true do
119        expect(interceptor).to receive(:server_streamer)
120          .once.and_call_original
121
122        run_services_on_server(@server, services: [service]) do
123          stub = build_insecure_stub(EchoStub)
124          expect_any_instance_of(GRPC::ActiveCall).to(
125            receive(:server_streamer).with(request)
126              .once.and_call_original
127          )
128          op = stub.a_server_streaming_rpc(request, client_call_opts)
129          responses = op.execute
130          responses.each do |r|
131            expect(r).to be_a(EchoMsg)
132          end
133          expect(op.trailing_metadata).to eq(
134            'interc' => 'from_server_streamer',
135            'server_om' => 'from_server_streamer'
136          )
137        end
138      end
139    end
140
141    context 'with a bidi call' do
142      let(:trailing_metadata) { { server_om: 'from_bidi_streamer' } }
143      let(:requests) { [EchoMsg.new, EchoMsg.new] }
144
145      it 'should be called', server: true do
146        expect(interceptor).to receive(:bidi_streamer)
147          .once.and_call_original
148
149        run_services_on_server(@server, services: [service]) do
150          stub = build_insecure_stub(EchoStub)
151          responses = stub.a_bidi_rpc(requests)
152          responses.each do |r|
153            expect(r).to be_a(EchoMsg)
154          end
155        end
156      end
157
158      it 'can modify trailing metadata', server: true do
159        expect(interceptor).to receive(:bidi_streamer)
160          .once.and_call_original
161
162        run_services_on_server(@server, services: [service]) do
163          stub = build_insecure_stub(EchoStub)
164          expect_any_instance_of(GRPC::ActiveCall).to(
165            receive(:bidi_streamer).with(requests)
166              .once.and_call_original
167          )
168          op = stub.a_bidi_rpc(requests, client_call_opts)
169          responses = op.execute
170          responses.each do |r|
171            expect(r).to be_a(EchoMsg)
172          end
173          expect(op.trailing_metadata).to eq(
174            'interc' => 'from_bidi_streamer',
175            'server_om' => 'from_bidi_streamer'
176          )
177        end
178      end
179    end
180  end
181
182  context 'when multiple interceptors are added' do
183    let(:interceptor2) { TestServerInterceptor.new }
184    let(:interceptor3) { TestServerInterceptor.new }
185    let(:interceptors) do
186      [
187        interceptor,
188        interceptor2,
189        interceptor3
190      ]
191    end
192
193    it 'each should be called', server: true do
194      expect(interceptor).to receive(:request_response)
195        .once.and_call_original
196      expect(interceptor2).to receive(:request_response)
197        .once.and_call_original
198      expect(interceptor3).to receive(:request_response)
199        .once.and_call_original
200
201      run_services_on_server(@server, services: [service]) do
202        stub = build_insecure_stub(EchoStub)
203        expect(stub.an_rpc(request)).to be_a(EchoMsg)
204      end
205    end
206  end
207
208  context 'when an interceptor is not added' do
209    it 'should not be called', server: true do
210      expect(interceptor).to_not receive(:call)
211
212      run_services_on_server(@server, services: [service]) do
213        stub = build_insecure_stub(EchoStub)
214        expect(stub.an_rpc(request)).to be_a(EchoMsg)
215      end
216    end
217  end
218end
219