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