• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 */
22require_once(dirname(__FILE__).'/../../lib/Grpc/BaseStub.php');
23require_once(dirname(__FILE__).'/../../lib/Grpc/AbstractCall.php');
24require_once(dirname(__FILE__).'/../../lib/Grpc/UnaryCall.php');
25require_once(dirname(__FILE__).'/../../lib/Grpc/ClientStreamingCall.php');
26require_once(dirname(__FILE__).'/../../lib/Grpc/Interceptor.php');
27require_once(dirname(__FILE__).'/../../lib/Grpc/CallInvoker.php');
28require_once(dirname(__FILE__).'/../../lib/Grpc/Internal/InterceptorChannel.php');
29
30class 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
47class 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
94class ChangeMetadataInterceptor extends Grpc\Interceptor
95{
96    public function interceptUnaryUnary($method,
97                                        $argument,
98                                        $deserialize,
99                                        array $metadata = [],
100                                        array $options = [],
101                                        $continuation)
102    {
103        $metadata["foo"] = array('interceptor_from_unary_request');
104        return $continuation($method, $argument, $deserialize, $metadata, $options);
105    }
106    public function interceptStreamUnary($method, $deserialize, array $metadata = [], array $options = [], $continuation)
107    {
108        $metadata["foo"] = array('interceptor_from_stream_request');
109        return $continuation($method, $deserialize, $metadata, $options);
110    }
111}
112
113class ChangeMetadataInterceptor2 extends Grpc\Interceptor
114{
115    public function interceptUnaryUnary($method,
116                                        $argument,
117                                        $deserialize,
118                                        array $metadata = [],
119                                        array $options = [],
120                                        $continuation)
121    {
122        if (array_key_exists('foo', $metadata)) {
123            $metadata['bar'] = array('ChangeMetadataInterceptor should be executed first');
124        } else {
125            $metadata["bar"] = array('interceptor_from_unary_request');
126        }
127        return $continuation($method, $argument, $deserialize, $metadata, $options);
128    }
129    public function interceptStreamUnary($method,
130                                         $deserialize,
131                                         array $metadata = [],
132                                         array $options = [],
133                                         $continuation)
134    {
135        if (array_key_exists('foo', $metadata)) {
136            $metadata['bar'] = array('ChangeMetadataInterceptor should be executed first');
137        } else {
138            $metadata["bar"] = array('interceptor_from_stream_request');
139        }
140        return $continuation($method, $deserialize, $metadata, $options);
141    }
142}
143
144class ChangeRequestCall
145{
146    private $call;
147
148    public function __construct($call)
149    {
150        $this->call = $call;
151    }
152    public function getCall()
153    {
154        return $this->call;
155    }
156
157    public function write($request)
158    {
159        $request->setData('intercepted_stream_request');
160        $this->getCall()->write($request);
161    }
162
163    public function wait()
164    {
165        return $this->getCall()->wait();
166    }
167}
168
169class ChangeRequestInterceptor extends Grpc\Interceptor
170{
171    public function interceptUnaryUnary($method,
172                                        $argument,
173                                        $deserialize,
174                                        array $metadata = [],
175                                        array $options = [],
176                                        $continuation)
177    {
178        $argument->setData('intercepted_unary_request');
179        return $continuation($method, $argument, $deserialize, $metadata, $options);
180    }
181    public function interceptStreamUnary($method, $deserialize, array $metadata = [], array $options = [], $continuation)
182    {
183        return new ChangeRequestCall(
184            $continuation($method, $deserialize, $metadata, $options)
185        );
186    }
187}
188
189class StopCallInterceptor extends Grpc\Interceptor
190{
191    public function interceptUnaryUnary($method,
192                                        $argument,
193                                        array $metadata = [],
194                                        array $options = [],
195                                        $continuation)
196    {
197        $metadata["foo"] = array('interceptor_from_request_response');
198    }
199    public function interceptStreamUnary($method,
200                                         array $metadata = [],
201                                         array $options = [],
202                                         $continuation)
203    {
204        $metadata["foo"] = array('interceptor_from_request_response');
205    }
206}
207
208class InterceptorTest extends PHPUnit_Framework_TestCase
209{
210    public function setUp()
211    {
212        $this->server = new Grpc\Server([]);
213        $this->port = $this->server->addHttp2Port('0.0.0.0:0');
214        $this->channel = new Grpc\Channel('localhost:'.$this->port, [
215            'force_new' => true,
216            'credentials' => Grpc\ChannelCredentials::createInsecure()]);
217        $this->server->start();
218    }
219
220    public function tearDown()
221    {
222        $this->channel->close();
223        unset($this->server);
224    }
225
226
227    public function testClientChangeMetadataOneInterceptor()
228    {
229        $req_text = 'client_request';
230        $channel_matadata_interceptor = new ChangeMetadataInterceptor();
231        $intercept_channel = Grpc\Interceptor::intercept($this->channel, $channel_matadata_interceptor);
232        $client = new InterceptorClient('localhost:'.$this->port, [
233            'force_new' => true,
234            'credentials' => Grpc\ChannelCredentials::createInsecure(),
235        ], $intercept_channel);
236        $req = new SimpleRequest($req_text);
237        $unary_call = $client->UnaryCall($req);
238        $event = $this->server->requestCall();
239        $this->assertSame('/dummy_method', $event->method);
240        $this->assertSame(['interceptor_from_unary_request'], $event->metadata['foo']);
241
242        $stream_call = $client->StreamCall();
243        $stream_call->write($req);
244        $event = $this->server->requestCall();
245        $this->assertSame('/dummy_method', $event->method);
246        $this->assertSame(['interceptor_from_stream_request'], $event->metadata['foo']);
247
248        unset($unary_call);
249        unset($stream_call);
250        unset($server_call);
251    }
252
253    public function testClientChangeMetadataTwoInterceptor()
254    {
255        $req_text = 'client_request';
256        $channel_matadata_interceptor = new ChangeMetadataInterceptor();
257        $channel_matadata_intercepto2 = new ChangeMetadataInterceptor2();
258        // test intercept separately.
259        $intercept_channel1 = Grpc\Interceptor::intercept($this->channel, $channel_matadata_interceptor);
260        $intercept_channel2 = Grpc\Interceptor::intercept($intercept_channel1, $channel_matadata_intercepto2);
261        $client = new InterceptorClient('localhost:'.$this->port, [
262            'force_new' => true,
263            'credentials' => Grpc\ChannelCredentials::createInsecure(),
264        ], $intercept_channel2);
265
266        $req = new SimpleRequest($req_text);
267        $unary_call = $client->UnaryCall($req);
268        $event = $this->server->requestCall();
269        $this->assertSame('/dummy_method', $event->method);
270        $this->assertSame(['interceptor_from_unary_request'], $event->metadata['foo']);
271        $this->assertSame(['interceptor_from_unary_request'], $event->metadata['bar']);
272
273        $stream_call = $client->StreamCall();
274        $stream_call->write($req);
275        $event = $this->server->requestCall();
276        $this->assertSame('/dummy_method', $event->method);
277        $this->assertSame(['interceptor_from_stream_request'], $event->metadata['foo']);
278        $this->assertSame(['interceptor_from_stream_request'], $event->metadata['bar']);
279
280        unset($unary_call);
281        unset($stream_call);
282        unset($server_call);
283
284        // test intercept by array.
285        $intercept_channel3 = Grpc\Interceptor::intercept($this->channel,
286            [$channel_matadata_intercepto2, $channel_matadata_interceptor]);
287        $client = new InterceptorClient('localhost:'.$this->port, [
288            'force_new' => true,
289            'credentials' => Grpc\ChannelCredentials::createInsecure(),
290        ], $intercept_channel3);
291
292        $req = new SimpleRequest($req_text);
293        $unary_call = $client->UnaryCall($req);
294        $event = $this->server->requestCall();
295        $this->assertSame('/dummy_method', $event->method);
296        $this->assertSame(['interceptor_from_unary_request'], $event->metadata['foo']);
297        $this->assertSame(['interceptor_from_unary_request'], $event->metadata['bar']);
298
299        $stream_call = $client->StreamCall();
300        $stream_call->write($req);
301        $event = $this->server->requestCall();
302        $this->assertSame('/dummy_method', $event->method);
303        $this->assertSame(['interceptor_from_stream_request'], $event->metadata['foo']);
304        $this->assertSame(['interceptor_from_stream_request'], $event->metadata['bar']);
305
306        unset($unary_call);
307        unset($stream_call);
308        unset($server_call);
309    }
310
311    public function testClientChangeRequestInterceptor()
312    {
313        $req_text = 'client_request';
314        $change_request_interceptor = new ChangeRequestInterceptor();
315        $intercept_channel = Grpc\Interceptor::intercept($this->channel,
316            $change_request_interceptor);
317        $client = new InterceptorClient('localhost:'.$this->port, [
318            'force_new' => true,
319            'credentials' => Grpc\ChannelCredentials::createInsecure(),
320        ], $intercept_channel);
321
322        $req = new SimpleRequest($req_text);
323        $unary_call = $client->UnaryCall($req);
324
325        $event = $this->server->requestCall();
326        $this->assertSame('/dummy_method', $event->method);
327        $server_call = $event->call;
328        $event = $server_call->startBatch([
329            Grpc\OP_SEND_INITIAL_METADATA => [],
330            Grpc\OP_SEND_STATUS_FROM_SERVER => [
331                'metadata' => [],
332                'code' => Grpc\STATUS_OK,
333                'details' => '',
334            ],
335            Grpc\OP_RECV_MESSAGE => true,
336            Grpc\OP_RECV_CLOSE_ON_SERVER => true,
337        ]);
338        $this->assertSame('intercepted_unary_request', $event->message);
339
340        $stream_call = $client->StreamCall();
341        $stream_call->write($req);
342        $event = $this->server->requestCall();
343        $this->assertSame('/dummy_method', $event->method);
344        $server_call = $event->call;
345        $event = $server_call->startBatch([
346            Grpc\OP_SEND_INITIAL_METADATA => [],
347            Grpc\OP_SEND_STATUS_FROM_SERVER => [
348                'metadata' => [],
349                'code' => Grpc\STATUS_OK,
350                'details' => '',
351            ],
352            Grpc\OP_RECV_MESSAGE => true,
353            Grpc\OP_RECV_CLOSE_ON_SERVER => true,
354        ]);
355        $this->assertSame('intercepted_stream_request', $event->message);
356
357        unset($unary_call);
358        unset($stream_call);
359        unset($server_call);
360    }
361
362    public function testClientChangeStopCallInterceptor()
363    {
364        $req_text = 'client_request';
365        $channel_request_interceptor = new StopCallInterceptor();
366        $intercept_channel = Grpc\Interceptor::intercept($this->channel,
367            $channel_request_interceptor);
368        $client = new InterceptorClient('localhost:'.$this->port, [
369            'force_new' => true,
370            'credentials' => Grpc\ChannelCredentials::createInsecure(),
371        ], $intercept_channel);
372
373        $req = new SimpleRequest($req_text);
374        $unary_call = $client->UnaryCall($req);
375        $this->assertNull($unary_call);
376
377
378        $stream_call = $client->StreamCall();
379        $this->assertNull($stream_call);
380
381        unset($unary_call);
382        unset($stream_call);
383        unset($server_call);
384    }
385
386    public function testGetInterceptorChannelConnectivityState()
387    {
388        $channel = new Grpc\Channel(
389            'localhost:0',
390            [
391                'force_new' => true,
392                'credentials' => Grpc\ChannelCredentials::createInsecure()
393            ]
394        );
395        $interceptor_channel = Grpc\Interceptor::intercept($channel, new Grpc\Interceptor());
396        $state = $interceptor_channel->getConnectivityState();
397        $this->assertEquals(0, $state);
398        $channel->close();
399    }
400
401    public function testInterceptorChannelWatchConnectivityState()
402    {
403        $channel = new Grpc\Channel(
404            'localhost:0',
405            [
406                'force_new' => true,
407                'credentials' => Grpc\ChannelCredentials::createInsecure()
408            ]
409        );
410        $interceptor_channel = Grpc\Interceptor::intercept($channel, new Grpc\Interceptor());
411        $now = Grpc\Timeval::now();
412        $deadline = $now->add(new Grpc\Timeval(100*1000));
413        $state = $interceptor_channel->watchConnectivityState(1, $deadline);
414        $this->assertTrue($state);
415        unset($time);
416        unset($deadline);
417        $channel->close();
418    }
419
420    public function testInterceptorChannelClose()
421    {
422        $channel = new Grpc\Channel(
423            'localhost:0',
424            [
425                'force_new' => true,
426                'credentials' => Grpc\ChannelCredentials::createInsecure()
427            ]
428        );
429        $interceptor_channel = Grpc\Interceptor::intercept($channel, new Grpc\Interceptor());
430        $this->assertNotNull($interceptor_channel);
431        $channel->close();
432    }
433
434    public function testInterceptorChannelGetTarget()
435    {
436        $channel = new Grpc\Channel(
437            'localhost:8888',
438            [
439                'force_new' => true,
440                'credentials' => Grpc\ChannelCredentials::createInsecure()
441            ]
442        );
443        $interceptor_channel = Grpc\Interceptor::intercept($channel, new Grpc\Interceptor());
444        $target = $interceptor_channel->getTarget();
445        $this->assertTrue(is_string($target));
446        $channel->close();
447    }
448}
449