Imported Upstream version 1.36.0
[platform/upstream/grpc.git] / src / php / tests / unit_tests / InterceptorTest.php
1 <?php
2 /*
3  *
4  * Copyright 2018 gRPC authors.
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  *     http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  *
18  */
19 /**
20  * Interface exported by the server.
21  */
22 require_once(dirname(__FILE__).'/../../lib/Grpc/BaseStub.php');
23 require_once(dirname(__FILE__).'/../../lib/Grpc/AbstractCall.php');
24 require_once(dirname(__FILE__).'/../../lib/Grpc/UnaryCall.php');
25 require_once(dirname(__FILE__).'/../../lib/Grpc/ClientStreamingCall.php');
26 require_once(dirname(__FILE__).'/../../lib/Grpc/Interceptor.php');
27 require_once(dirname(__FILE__).'/../../lib/Grpc/CallInvoker.php');
28 require_once(dirname(__FILE__).'/../../lib/Grpc/Internal/InterceptorChannel.php');
29
30 class SimpleRequest
31 {
32     private $data;
33     public function __construct($data)
34     {
35         $this->data = $data;
36     }
37     public function setData($data)
38     {
39         $this->data = $data;
40     }
41     public function serializeToString()
42     {
43         return $this->data;
44     }
45 }
46
47 class InterceptorClient extends Grpc\BaseStub
48 {
49
50     /**
51      * @param string $hostname hostname
52      * @param array $opts channel options
53      * @param Channel|InterceptorChannel $channel (optional) re-use channel object
54      */
55     public function __construct($hostname, $opts, $channel = null)
56     {
57         parent::__construct($hostname, $opts, $channel);
58     }
59
60     /**
61      * A simple RPC.
62      * @param SimpleRequest $argument input argument
63      * @param array $metadata metadata
64      * @param array $options call options
65      */
66     public function UnaryCall(
67         SimpleRequest $argument,
68         $metadata = [],
69         $options = []
70     ) {
71         return $this->_simpleRequest(
72             '/dummy_method',
73             $argument,
74             [],
75             $metadata,
76             $options
77         );
78     }
79
80     /**
81      * A client-to-server streaming RPC.
82      * @param array $metadata metadata
83      * @param array $options call options
84      */
85     public function StreamCall(
86         $metadata = [],
87         $options = []
88     ) {
89         return $this->_clientStreamRequest('/dummy_method', [], $metadata, $options);
90     }
91 }
92
93
94 class ChangeMetadataInterceptor extends Grpc\Interceptor
95 {
96     public function interceptUnaryUnary($method,
97                                         $argument,
98                                         $deserialize,
99                                         $continuation,
100                                         array $metadata = [],
101                                         array $options = [])
102     {
103         $metadata["foo"] = array('interceptor_from_unary_request');
104         return $continuation($method, $argument, $deserialize, $metadata, $options);
105     }
106     public function interceptStreamUnary($method,
107                                          $deserialize,
108                                          $continuation,
109                                          array $metadata = [],
110                                          array $options = [])
111     {
112         $metadata["foo"] = array('interceptor_from_stream_request');
113         return $continuation($method, $deserialize, $metadata, $options);
114     }
115 }
116
117 class ChangeMetadataInterceptor2 extends Grpc\Interceptor
118 {
119     public function interceptUnaryUnary($method,
120                                         $argument,
121                                         $deserialize,
122                                         $continuation,
123                                         array $metadata = [],
124                                         array $options = [])
125     {
126         if (array_key_exists('foo', $metadata)) {
127             $metadata['bar'] = array('ChangeMetadataInterceptor should be executed first');
128         } else {
129             $metadata["bar"] = array('interceptor_from_unary_request');
130         }
131         return $continuation($method, $argument, $deserialize, $metadata, $options);
132     }
133     public function interceptStreamUnary($method,
134                                          $deserialize,
135                                          $continuation,
136                                          array $metadata = [],
137                                          array $options = [])
138     {
139         if (array_key_exists('foo', $metadata)) {
140             $metadata['bar'] = array('ChangeMetadataInterceptor should be executed first');
141         } else {
142             $metadata["bar"] = array('interceptor_from_stream_request');
143         }
144         return $continuation($method, $deserialize, $metadata, $options);
145     }
146 }
147
148 class ChangeRequestCall
149 {
150     private $call;
151
152     public function __construct($call)
153     {
154         $this->call = $call;
155     }
156     public function getCall()
157     {
158         return $this->call;
159     }
160
161     public function write($request)
162     {
163         $request->setData('intercepted_stream_request');
164         $this->getCall()->write($request);
165     }
166
167     public function wait()
168     {
169         return $this->getCall()->wait();
170     }
171 }
172
173 class ChangeRequestInterceptor extends Grpc\Interceptor
174 {
175     public function interceptUnaryUnary($method,
176                                         $argument,
177                                         $deserialize,
178                                         $continuation,
179                                         array $metadata = [],
180                                         array $options = [])
181     {
182         $argument->setData('intercepted_unary_request');
183         return $continuation($method, $argument, $deserialize, $metadata, $options);
184     }
185     public function interceptStreamUnary($method,
186                                          $deserialize,
187                                          $continuation,
188                                          array $metadata = [],
189                                          array $options = [])
190     {
191         return new ChangeRequestCall(
192             $continuation($method, $deserialize, $metadata, $options)
193         );
194     }
195 }
196
197 class StopCallInterceptor extends Grpc\Interceptor
198 {
199     public function interceptUnaryUnary($method,
200                                         $argument,
201                                         $deserialize,
202                                         $continuation,
203                                         array $metadata = [],
204                                         array $options = [])
205     {
206         $metadata["foo"] = array('interceptor_from_request_response');
207     }
208     public function interceptStreamUnary($method,
209                                          $deserialize,
210                                          $continuation,
211                                          array $metadata = [],
212                                          array $options = [])
213     {
214         $metadata["foo"] = array('interceptor_from_request_response');
215     }
216 }
217
218 class InterceptorTest extends \PHPUnit\Framework\TestCase
219 {
220     public function setUp(): void
221     {
222         $this->server = new Grpc\Server([]);
223         $this->port = $this->server->addHttp2Port('0.0.0.0:0');
224         $this->channel = new Grpc\Channel('localhost:'.$this->port, [
225             'force_new' => true,
226             'credentials' => Grpc\ChannelCredentials::createInsecure()]);
227         $this->server->start();
228     }
229
230     public function tearDown(): void
231     {
232         $this->channel->close();
233         unset($this->server);
234     }
235
236
237     public function testClientChangeMetadataOneInterceptor()
238     {
239         $req_text = 'client_request';
240         $channel_matadata_interceptor = new ChangeMetadataInterceptor();
241         $intercept_channel = Grpc\Interceptor::intercept($this->channel, $channel_matadata_interceptor);
242         $client = new InterceptorClient('localhost:'.$this->port, [
243             'force_new' => true,
244             'credentials' => Grpc\ChannelCredentials::createInsecure(),
245         ], $intercept_channel);
246         $req = new SimpleRequest($req_text);
247         $unary_call = $client->UnaryCall($req);
248         $event = $this->server->requestCall();
249         $this->assertSame('/dummy_method', $event->method);
250         $this->assertSame(['interceptor_from_unary_request'], $event->metadata['foo']);
251
252         $stream_call = $client->StreamCall();
253         $stream_call->write($req);
254         $event = $this->server->requestCall();
255         $this->assertSame('/dummy_method', $event->method);
256         $this->assertSame(['interceptor_from_stream_request'], $event->metadata['foo']);
257
258         unset($unary_call);
259         unset($stream_call);
260         unset($server_call);
261     }
262
263     public function testClientChangeMetadataTwoInterceptor()
264     {
265         $req_text = 'client_request';
266         $channel_matadata_interceptor = new ChangeMetadataInterceptor();
267         $channel_matadata_intercepto2 = new ChangeMetadataInterceptor2();
268         // test intercept separately.
269         $intercept_channel1 = Grpc\Interceptor::intercept($this->channel, $channel_matadata_interceptor);
270         $intercept_channel2 = Grpc\Interceptor::intercept($intercept_channel1, $channel_matadata_intercepto2);
271         $client = new InterceptorClient('localhost:'.$this->port, [
272             'force_new' => true,
273             'credentials' => Grpc\ChannelCredentials::createInsecure(),
274         ], $intercept_channel2);
275
276         $req = new SimpleRequest($req_text);
277         $unary_call = $client->UnaryCall($req);
278         $event = $this->server->requestCall();
279         $this->assertSame('/dummy_method', $event->method);
280         $this->assertSame(['interceptor_from_unary_request'], $event->metadata['foo']);
281         $this->assertSame(['interceptor_from_unary_request'], $event->metadata['bar']);
282
283         $stream_call = $client->StreamCall();
284         $stream_call->write($req);
285         $event = $this->server->requestCall();
286         $this->assertSame('/dummy_method', $event->method);
287         $this->assertSame(['interceptor_from_stream_request'], $event->metadata['foo']);
288         $this->assertSame(['interceptor_from_stream_request'], $event->metadata['bar']);
289
290         unset($unary_call);
291         unset($stream_call);
292         unset($server_call);
293
294         // test intercept by array.
295         $intercept_channel3 = Grpc\Interceptor::intercept($this->channel,
296             [$channel_matadata_intercepto2, $channel_matadata_interceptor]);
297         $client = new InterceptorClient('localhost:'.$this->port, [
298             'force_new' => true,
299             'credentials' => Grpc\ChannelCredentials::createInsecure(),
300         ], $intercept_channel3);
301
302         $req = new SimpleRequest($req_text);
303         $unary_call = $client->UnaryCall($req);
304         $event = $this->server->requestCall();
305         $this->assertSame('/dummy_method', $event->method);
306         $this->assertSame(['interceptor_from_unary_request'], $event->metadata['foo']);
307         $this->assertSame(['interceptor_from_unary_request'], $event->metadata['bar']);
308
309         $stream_call = $client->StreamCall();
310         $stream_call->write($req);
311         $event = $this->server->requestCall();
312         $this->assertSame('/dummy_method', $event->method);
313         $this->assertSame(['interceptor_from_stream_request'], $event->metadata['foo']);
314         $this->assertSame(['interceptor_from_stream_request'], $event->metadata['bar']);
315
316         unset($unary_call);
317         unset($stream_call);
318         unset($server_call);
319     }
320
321     public function testClientChangeRequestInterceptor()
322     {
323         $req_text = 'client_request';
324         $change_request_interceptor = new ChangeRequestInterceptor();
325         $intercept_channel = Grpc\Interceptor::intercept($this->channel,
326             $change_request_interceptor);
327         $client = new InterceptorClient('localhost:'.$this->port, [
328             'force_new' => true,
329             'credentials' => Grpc\ChannelCredentials::createInsecure(),
330         ], $intercept_channel);
331
332         $req = new SimpleRequest($req_text);
333         $unary_call = $client->UnaryCall($req);
334
335         $event = $this->server->requestCall();
336         $this->assertSame('/dummy_method', $event->method);
337         $server_call = $event->call;
338         $event = $server_call->startBatch([
339             Grpc\OP_SEND_INITIAL_METADATA => [],
340             Grpc\OP_SEND_STATUS_FROM_SERVER => [
341                 'metadata' => [],
342                 'code' => Grpc\STATUS_OK,
343                 'details' => '',
344             ],
345             Grpc\OP_RECV_MESSAGE => true,
346             Grpc\OP_RECV_CLOSE_ON_SERVER => true,
347         ]);
348         $this->assertSame('intercepted_unary_request', $event->message);
349
350         $stream_call = $client->StreamCall();
351         $stream_call->write($req);
352         $event = $this->server->requestCall();
353         $this->assertSame('/dummy_method', $event->method);
354         $server_call = $event->call;
355         $event = $server_call->startBatch([
356             Grpc\OP_SEND_INITIAL_METADATA => [],
357             Grpc\OP_SEND_STATUS_FROM_SERVER => [
358                 'metadata' => [],
359                 'code' => Grpc\STATUS_OK,
360                 'details' => '',
361             ],
362             Grpc\OP_RECV_MESSAGE => true,
363             Grpc\OP_RECV_CLOSE_ON_SERVER => true,
364         ]);
365         $this->assertSame('intercepted_stream_request', $event->message);
366
367         unset($unary_call);
368         unset($stream_call);
369         unset($server_call);
370     }
371
372     public function testClientChangeStopCallInterceptor()
373     {
374         $req_text = 'client_request';
375         $channel_request_interceptor = new StopCallInterceptor();
376         $intercept_channel = Grpc\Interceptor::intercept($this->channel,
377             $channel_request_interceptor);
378         $client = new InterceptorClient('localhost:'.$this->port, [
379             'force_new' => true,
380             'credentials' => Grpc\ChannelCredentials::createInsecure(),
381         ], $intercept_channel);
382
383         $req = new SimpleRequest($req_text);
384         $unary_call = $client->UnaryCall($req);
385         $this->assertNull($unary_call);
386
387
388         $stream_call = $client->StreamCall();
389         $this->assertNull($stream_call);
390
391         unset($unary_call);
392         unset($stream_call);
393         unset($server_call);
394     }
395
396     public function testGetInterceptorChannelConnectivityState()
397     {
398         $channel = new Grpc\Channel(
399             'localhost:0',
400             [
401                 'force_new' => true,
402                 'credentials' => Grpc\ChannelCredentials::createInsecure()
403             ]
404         );
405         $interceptor_channel = Grpc\Interceptor::intercept($channel, new Grpc\Interceptor());
406         $state = $interceptor_channel->getConnectivityState();
407         $this->assertEquals(0, $state);
408         $channel->close();
409     }
410
411     public function testInterceptorChannelWatchConnectivityState()
412     {
413         $channel = new Grpc\Channel(
414             'localhost:0',
415             [
416                 'force_new' => true,
417                 'credentials' => Grpc\ChannelCredentials::createInsecure()
418             ]
419         );
420         $interceptor_channel = Grpc\Interceptor::intercept($channel, new Grpc\Interceptor());
421         $now = Grpc\Timeval::now();
422         $deadline = $now->add(new Grpc\Timeval(100*1000));
423         $state = $interceptor_channel->watchConnectivityState(1, $deadline);
424         $this->assertTrue($state);
425         unset($time);
426         unset($deadline);
427         $channel->close();
428     }
429
430     public function testInterceptorChannelClose()
431     {
432         $channel = new Grpc\Channel(
433             'localhost:0',
434             [
435                 'force_new' => true,
436                 'credentials' => Grpc\ChannelCredentials::createInsecure()
437             ]
438         );
439         $interceptor_channel = Grpc\Interceptor::intercept($channel, new Grpc\Interceptor());
440         $this->assertNotNull($interceptor_channel);
441         $channel->close();
442     }
443
444     public function testInterceptorChannelGetTarget()
445     {
446         $channel = new Grpc\Channel(
447             'localhost:8888',
448             [
449                 'force_new' => true,
450                 'credentials' => Grpc\ChannelCredentials::createInsecure()
451             ]
452         );
453         $interceptor_channel = Grpc\Interceptor::intercept($channel, new Grpc\Interceptor());
454         $target = $interceptor_channel->getTarget();
455         $this->assertTrue(is_string($target));
456         $channel->close();
457     }
458 }