xref: /aosp_15_r20/external/grpc-grpc/src/php/tests/unit_tests/EndToEndTest.php (revision cc02d7e222339f7a4f6ba5f422e6413f4bd931f2)
1<?php
2/*
3 *
4 * Copyright 2015 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 */
19class EndToEndTest extends \PHPUnit\Framework\TestCase
20{
21    private $server;
22    private $port;
23    private $channel;
24
25    public function setUp(): void
26    {
27        $this->server = new Grpc\Server([]);
28        $this->port = $this->server->addHttp2Port('0.0.0.0:0');
29        $this->channel = new Grpc\Channel('localhost:'.$this->port, [
30            "force_new" => true,
31        ]);
32        $this->server->start();
33    }
34
35    public function tearDown(): void
36    {
37        $this->channel->close();
38        unset($this->server);
39    }
40
41    public function testSimpleRequestBody()
42    {
43        $deadline = Grpc\Timeval::infFuture();
44        $status_text = 'xyz';
45        $call = new Grpc\Call($this->channel,
46                              'phony_method',
47                              $deadline);
48
49        $event = $call->startBatch([
50            Grpc\OP_SEND_INITIAL_METADATA => [],
51            Grpc\OP_SEND_CLOSE_FROM_CLIENT => true,
52        ]);
53
54        $this->assertTrue($event->send_metadata);
55        $this->assertTrue($event->send_close);
56
57        $event = $this->server->requestCall();
58        $this->assertSame('phony_method', $event->method);
59        $server_call = $event->call;
60
61        $event = $server_call->startBatch([
62            Grpc\OP_SEND_INITIAL_METADATA => [],
63            Grpc\OP_SEND_STATUS_FROM_SERVER => [
64                'metadata' => [],
65                'code' => Grpc\STATUS_OK,
66                'details' => $status_text,
67            ],
68            Grpc\OP_RECV_CLOSE_ON_SERVER => true,
69        ]);
70
71        $this->assertTrue($event->send_metadata);
72        $this->assertTrue($event->send_status);
73        $this->assertFalse($event->cancelled);
74
75        $event = $call->startBatch([
76            Grpc\OP_RECV_INITIAL_METADATA => true,
77            Grpc\OP_RECV_STATUS_ON_CLIENT => true,
78        ]);
79
80        $status = $event->status;
81        $this->assertSame([], $status->metadata);
82        $this->assertSame(Grpc\STATUS_OK, $status->code);
83        $this->assertSame($status_text, $status->details);
84
85        unset($call);
86        unset($server_call);
87    }
88
89    public function testMessageWriteFlags()
90    {
91        $deadline = Grpc\Timeval::infFuture();
92        $req_text = 'message_write_flags_test';
93        $status_text = 'xyz';
94        $call = new Grpc\Call($this->channel,
95                              'phony_method',
96                              $deadline);
97
98        $event = $call->startBatch([
99            Grpc\OP_SEND_INITIAL_METADATA => [],
100            Grpc\OP_SEND_MESSAGE => ['message' => $req_text,
101                                     'flags' => Grpc\WRITE_NO_COMPRESS, ],
102            Grpc\OP_SEND_CLOSE_FROM_CLIENT => true,
103        ]);
104
105        $this->assertTrue($event->send_metadata);
106        $this->assertTrue($event->send_close);
107
108        $event = $this->server->requestCall();
109        $this->assertSame('phony_method', $event->method);
110        $server_call = $event->call;
111
112        $event = $server_call->startBatch([
113            Grpc\OP_SEND_INITIAL_METADATA => [],
114            Grpc\OP_SEND_STATUS_FROM_SERVER => [
115                'metadata' => [],
116                'code' => Grpc\STATUS_OK,
117                'details' => $status_text,
118            ],
119        ]);
120
121        $event = $call->startBatch([
122            Grpc\OP_RECV_INITIAL_METADATA => true,
123            Grpc\OP_RECV_STATUS_ON_CLIENT => true,
124        ]);
125
126        $status = $event->status;
127        $this->assertSame([], $status->metadata);
128        $this->assertSame(Grpc\STATUS_OK, $status->code);
129        $this->assertSame($status_text, $status->details);
130
131        unset($call);
132        unset($server_call);
133    }
134
135    public function testClientServerFullRequestResponse()
136    {
137        $deadline = Grpc\Timeval::infFuture();
138        $req_text = 'client_server_full_request_response';
139        $reply_text = 'reply:client_server_full_request_response';
140        $status_text = 'status:client_server_full_response_text';
141
142        $call = new Grpc\Call($this->channel,
143                              'phony_method',
144                              $deadline);
145
146        $event = $call->startBatch([
147            Grpc\OP_SEND_INITIAL_METADATA => [],
148            Grpc\OP_SEND_CLOSE_FROM_CLIENT => true,
149            Grpc\OP_SEND_MESSAGE => ['message' => $req_text],
150        ]);
151
152        $this->assertTrue($event->send_metadata);
153        $this->assertTrue($event->send_close);
154        $this->assertTrue($event->send_message);
155
156        $event = $this->server->requestCall();
157        $this->assertSame('phony_method', $event->method);
158        $server_call = $event->call;
159
160        $event = $server_call->startBatch([
161            Grpc\OP_RECV_MESSAGE => true,
162        ]);
163        $this->assertSame($req_text, $event->message);
164
165        $event = $server_call->startBatch([
166            Grpc\OP_SEND_MESSAGE => ['message' => $reply_text],
167            Grpc\OP_SEND_INITIAL_METADATA => [],
168            Grpc\OP_SEND_STATUS_FROM_SERVER => [
169                'metadata' => [],
170                'code' => Grpc\STATUS_OK,
171                'details' => $status_text,
172            ],
173            Grpc\OP_RECV_CLOSE_ON_SERVER => true,
174        ]);
175
176        $this->assertTrue($event->send_metadata);
177        $this->assertTrue($event->send_status);
178        $this->assertTrue($event->send_message);
179        $this->assertFalse($event->cancelled);
180
181        $event = $call->startBatch([
182            Grpc\OP_RECV_INITIAL_METADATA => true,
183            Grpc\OP_RECV_MESSAGE => true,
184            Grpc\OP_RECV_STATUS_ON_CLIENT => true,
185        ]);
186
187        $this->assertSame([], $event->metadata);
188        $this->assertSame($reply_text, $event->message);
189        $status = $event->status;
190        $this->assertSame([], $status->metadata);
191        $this->assertSame(Grpc\STATUS_OK, $status->code);
192        $this->assertSame($status_text, $status->details);
193
194        unset($call);
195        unset($server_call);
196    }
197
198    public function testInvalidClientMessageArray()
199    {
200        $this->expectException(\InvalidArgumentException::class);
201        $deadline = Grpc\Timeval::infFuture();
202        $req_text = 'client_server_full_request_response';
203        $reply_text = 'reply:client_server_full_request_response';
204        $status_text = 'status:client_server_full_response_text';
205
206        $call = new Grpc\Call($this->channel,
207                              'phony_method',
208                              $deadline);
209
210        $event = $call->startBatch([
211            Grpc\OP_SEND_INITIAL_METADATA => [],
212            Grpc\OP_SEND_CLOSE_FROM_CLIENT => true,
213            Grpc\OP_SEND_MESSAGE => 'invalid',
214        ]);
215    }
216
217    public function testInvalidClientMessageString()
218    {
219        $this->expectException(\InvalidArgumentException::class);
220        $deadline = Grpc\Timeval::infFuture();
221        $req_text = 'client_server_full_request_response';
222        $reply_text = 'reply:client_server_full_request_response';
223        $status_text = 'status:client_server_full_response_text';
224
225        $call = new Grpc\Call($this->channel,
226                              'phony_method',
227                              $deadline);
228
229        $event = $call->startBatch([
230            Grpc\OP_SEND_INITIAL_METADATA => [],
231            Grpc\OP_SEND_CLOSE_FROM_CLIENT => true,
232            Grpc\OP_SEND_MESSAGE => ['message' => 0],
233        ]);
234    }
235
236    public function testInvalidClientMessageFlags()
237    {
238        $this->expectException(\InvalidArgumentException::class);
239        $deadline = Grpc\Timeval::infFuture();
240        $req_text = 'client_server_full_request_response';
241        $reply_text = 'reply:client_server_full_request_response';
242        $status_text = 'status:client_server_full_response_text';
243
244        $call = new Grpc\Call($this->channel,
245                              'phony_method',
246                              $deadline);
247
248        $event = $call->startBatch([
249            Grpc\OP_SEND_INITIAL_METADATA => [],
250            Grpc\OP_SEND_CLOSE_FROM_CLIENT => true,
251            Grpc\OP_SEND_MESSAGE => ['message' => 'abc',
252                                     'flags' => 'invalid',
253                                     ],
254        ]);
255    }
256
257    public function testInvalidServerStatusMetadata()
258    {
259        $this->expectException(\InvalidArgumentException::class);
260        $deadline = Grpc\Timeval::infFuture();
261        $req_text = 'client_server_full_request_response';
262        $reply_text = 'reply:client_server_full_request_response';
263        $status_text = 'status:client_server_full_response_text';
264
265        $call = new Grpc\Call($this->channel,
266                              'phony_method',
267                              $deadline);
268
269        $event = $call->startBatch([
270            Grpc\OP_SEND_INITIAL_METADATA => [],
271            Grpc\OP_SEND_CLOSE_FROM_CLIENT => true,
272            Grpc\OP_SEND_MESSAGE => ['message' => $req_text],
273        ]);
274
275        $this->assertTrue($event->send_metadata);
276        $this->assertTrue($event->send_close);
277        $this->assertTrue($event->send_message);
278
279        $event = $this->server->requestCall();
280        $this->assertSame('phony_method', $event->method);
281        $server_call = $event->call;
282
283        $event = $server_call->startBatch([
284            Grpc\OP_SEND_INITIAL_METADATA => [],
285            Grpc\OP_SEND_MESSAGE => ['message' => $reply_text],
286            Grpc\OP_SEND_STATUS_FROM_SERVER => [
287                'metadata' => 'invalid',
288                'code' => Grpc\STATUS_OK,
289                'details' => $status_text,
290            ],
291            Grpc\OP_RECV_MESSAGE => true,
292            Grpc\OP_RECV_CLOSE_ON_SERVER => true,
293        ]);
294    }
295
296    public function testInvalidServerStatusCode()
297    {
298        $this->expectException(\InvalidArgumentException::class);
299        $deadline = Grpc\Timeval::infFuture();
300        $req_text = 'client_server_full_request_response';
301        $reply_text = 'reply:client_server_full_request_response';
302        $status_text = 'status:client_server_full_response_text';
303
304        $call = new Grpc\Call($this->channel,
305                              'phony_method',
306                              $deadline);
307
308        $event = $call->startBatch([
309            Grpc\OP_SEND_INITIAL_METADATA => [],
310            Grpc\OP_SEND_CLOSE_FROM_CLIENT => true,
311            Grpc\OP_SEND_MESSAGE => ['message' => $req_text],
312        ]);
313
314        $this->assertTrue($event->send_metadata);
315        $this->assertTrue($event->send_close);
316        $this->assertTrue($event->send_message);
317
318        $event = $this->server->requestCall();
319        $this->assertSame('phony_method', $event->method);
320        $server_call = $event->call;
321
322        $event = $server_call->startBatch([
323            Grpc\OP_SEND_INITIAL_METADATA => [],
324            Grpc\OP_SEND_MESSAGE => ['message' => $reply_text],
325            Grpc\OP_SEND_STATUS_FROM_SERVER => [
326                'metadata' => [],
327                'code' => 'invalid',
328                'details' => $status_text,
329            ],
330            Grpc\OP_RECV_MESSAGE => true,
331            Grpc\OP_RECV_CLOSE_ON_SERVER => true,
332        ]);
333    }
334
335    public function testMissingServerStatusCode()
336    {
337        $this->expectException(\InvalidArgumentException::class);
338        $deadline = Grpc\Timeval::infFuture();
339        $req_text = 'client_server_full_request_response';
340        $reply_text = 'reply:client_server_full_request_response';
341        $status_text = 'status:client_server_full_response_text';
342
343        $call = new Grpc\Call($this->channel,
344                              'phony_method',
345                              $deadline);
346
347        $event = $call->startBatch([
348            Grpc\OP_SEND_INITIAL_METADATA => [],
349            Grpc\OP_SEND_CLOSE_FROM_CLIENT => true,
350            Grpc\OP_SEND_MESSAGE => ['message' => $req_text],
351        ]);
352
353        $this->assertTrue($event->send_metadata);
354        $this->assertTrue($event->send_close);
355        $this->assertTrue($event->send_message);
356
357        $event = $this->server->requestCall();
358        $this->assertSame('phony_method', $event->method);
359        $server_call = $event->call;
360
361        $event = $server_call->startBatch([
362            Grpc\OP_SEND_INITIAL_METADATA => [],
363            Grpc\OP_SEND_MESSAGE => ['message' => $reply_text],
364            Grpc\OP_SEND_STATUS_FROM_SERVER => [
365                'metadata' => [],
366                'details' => $status_text,
367            ],
368            Grpc\OP_RECV_MESSAGE => true,
369            Grpc\OP_RECV_CLOSE_ON_SERVER => true,
370        ]);
371    }
372
373    public function testInvalidServerStatusDetails()
374    {
375        $this->expectException(\InvalidArgumentException::class);
376        $deadline = Grpc\Timeval::infFuture();
377        $req_text = 'client_server_full_request_response';
378        $reply_text = 'reply:client_server_full_request_response';
379        $status_text = 'status:client_server_full_response_text';
380
381        $call = new Grpc\Call($this->channel,
382                              'phony_method',
383                              $deadline);
384
385        $event = $call->startBatch([
386            Grpc\OP_SEND_INITIAL_METADATA => [],
387            Grpc\OP_SEND_CLOSE_FROM_CLIENT => true,
388            Grpc\OP_SEND_MESSAGE => ['message' => $req_text],
389        ]);
390
391        $this->assertTrue($event->send_metadata);
392        $this->assertTrue($event->send_close);
393        $this->assertTrue($event->send_message);
394
395        $event = $this->server->requestCall();
396        $this->assertSame('phony_method', $event->method);
397        $server_call = $event->call;
398
399        $event = $server_call->startBatch([
400            Grpc\OP_SEND_INITIAL_METADATA => [],
401            Grpc\OP_SEND_MESSAGE => ['message' => $reply_text],
402            Grpc\OP_SEND_STATUS_FROM_SERVER => [
403                'metadata' => [],
404                'code' => Grpc\STATUS_OK,
405                'details' => 0,
406            ],
407            Grpc\OP_RECV_MESSAGE => true,
408            Grpc\OP_RECV_CLOSE_ON_SERVER => true,
409        ]);
410    }
411
412    public function testMissingServerStatusDetails()
413    {
414        $this->expectException(\InvalidArgumentException::class);
415        $deadline = Grpc\Timeval::infFuture();
416        $req_text = 'client_server_full_request_response';
417        $reply_text = 'reply:client_server_full_request_response';
418        $status_text = 'status:client_server_full_response_text';
419
420        $call = new Grpc\Call($this->channel,
421                              'phony_method',
422                              $deadline);
423
424        $event = $call->startBatch([
425            Grpc\OP_SEND_INITIAL_METADATA => [],
426            Grpc\OP_SEND_CLOSE_FROM_CLIENT => true,
427            Grpc\OP_SEND_MESSAGE => ['message' => $req_text],
428        ]);
429
430        $this->assertTrue($event->send_metadata);
431        $this->assertTrue($event->send_close);
432        $this->assertTrue($event->send_message);
433
434        $event = $this->server->requestCall();
435        $this->assertSame('phony_method', $event->method);
436        $server_call = $event->call;
437
438        $event = $server_call->startBatch([
439            Grpc\OP_SEND_INITIAL_METADATA => [],
440            Grpc\OP_SEND_MESSAGE => ['message' => $reply_text],
441            Grpc\OP_SEND_STATUS_FROM_SERVER => [
442                'metadata' => [],
443                'code' => Grpc\STATUS_OK,
444            ],
445            Grpc\OP_RECV_MESSAGE => true,
446            Grpc\OP_RECV_CLOSE_ON_SERVER => true,
447        ]);
448    }
449
450    public function testInvalidStartBatchKey()
451    {
452        $this->expectException(\InvalidArgumentException::class);
453        $deadline = Grpc\Timeval::infFuture();
454        $req_text = 'client_server_full_request_response';
455        $reply_text = 'reply:client_server_full_request_response';
456        $status_text = 'status:client_server_full_response_text';
457
458        $call = new Grpc\Call($this->channel,
459                              'phony_method',
460                              $deadline);
461
462        $event = $call->startBatch([
463            9999999 => [],
464        ]);
465    }
466
467    public function testInvalidStartBatch()
468    {
469        $this->expectException(\LogicException::class);
470        $deadline = Grpc\Timeval::infFuture();
471        $req_text = 'client_server_full_request_response';
472        $reply_text = 'reply:client_server_full_request_response';
473        $status_text = 'status:client_server_full_response_text';
474
475        $call = new Grpc\Call($this->channel,
476                              'phony_method',
477                              $deadline);
478
479        $event = $call->startBatch([
480            Grpc\OP_SEND_INITIAL_METADATA => [],
481            Grpc\OP_SEND_CLOSE_FROM_CLIENT => true,
482            Grpc\OP_SEND_MESSAGE => ['message' => $req_text],
483            Grpc\OP_SEND_STATUS_FROM_SERVER => [
484                'metadata' => [],
485                'code' => Grpc\STATUS_OK,
486                'details' => 'abc',
487            ],
488        ]);
489    }
490
491    public function testGetTarget()
492    {
493        $this->assertTrue(is_string($this->channel->getTarget()));
494    }
495
496    public function testGetConnectivityState()
497    {
498        $this->assertTrue($this->channel->getConnectivityState() ==
499                          Grpc\CHANNEL_IDLE);
500    }
501
502    public function testWatchConnectivityStateFailed()
503    {
504        $idle_state = $this->channel->getConnectivityState();
505        $this->assertTrue($idle_state == Grpc\CHANNEL_IDLE);
506
507        $now = Grpc\Timeval::now();
508        $delta = new Grpc\Timeval(50000); // should timeout
509        $deadline = $now->add($delta);
510
511        $this->assertFalse($this->channel->watchConnectivityState(
512        $idle_state, $deadline));
513    }
514
515    public function testWatchConnectivityStateSuccess()
516    {
517        $idle_state = $this->channel->getConnectivityState(true);
518        $this->assertTrue($idle_state == Grpc\CHANNEL_IDLE);
519
520        $now = Grpc\Timeval::now();
521        $delta = new Grpc\Timeval(3000000); // should finish well before
522        $deadline = $now->add($delta);
523
524        $this->assertTrue($this->channel->watchConnectivityState(
525        $idle_state, $deadline));
526
527        $new_state = $this->channel->getConnectivityState();
528        $this->assertTrue($idle_state != $new_state);
529    }
530
531    public function testWatchConnectivityStateDoNothing()
532    {
533        $idle_state = $this->channel->getConnectivityState();
534        $this->assertTrue($idle_state == Grpc\CHANNEL_IDLE);
535
536        $now = Grpc\Timeval::now();
537        $delta = new Grpc\Timeval(50000);
538        $deadline = $now->add($delta);
539
540        $this->assertFalse($this->channel->watchConnectivityState(
541        $idle_state, $deadline));
542
543        $new_state = $this->channel->getConnectivityState();
544        $this->assertTrue($new_state == Grpc\CHANNEL_IDLE);
545    }
546
547    public function testGetConnectivityStateInvalidParam()
548    {
549        $this->expectException(\InvalidArgumentException::class);
550        $this->assertTrue($this->channel->getConnectivityState(
551            new Grpc\Timeval()));
552    }
553
554    public function testWatchConnectivityStateInvalidParam()
555    {
556        $this->expectException(\InvalidArgumentException::class);
557        $this->assertTrue($this->channel->watchConnectivityState(
558            0, 1000));
559    }
560
561    public function testChannelConstructorInvalidParam()
562    {
563        $this->expectException(\InvalidArgumentException::class);
564        $this->channel = new Grpc\Channel('localhost:'.$this->port, null);
565    }
566
567    public function testClose()
568    {
569        $this->assertNull($this->channel->close());
570    }
571}
572