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 20class ChannelTest extends \PHPUnit\Framework\TestCase 21{ 22 public function setUp(): void 23 { 24 } 25 26 public function tearDown(): void 27 { 28 if (!empty($this->channel)) { 29 $this->channel->close(); 30 } 31 } 32 33 public function testInsecureCredentials() 34 { 35 $this->channel = new Grpc\Channel('localhost:50000', 36 ['credentials' => Grpc\ChannelCredentials::createInsecure()]); 37 $this->assertSame('Grpc\Channel', get_class($this->channel)); 38 } 39 40 public function testConstructorCreateSsl() 41 { 42 $channel = new Grpc\Channel('localhost:50033', 43 ['credentials' => \Grpc\ChannelCredentials::createSsl()]); 44 $this->assertNotNull($channel); 45 } 46 47 public function testCreateXdsWithSsl() 48 { 49 $xdsCreds = \Grpc\ChannelCredentials::createXds( 50 \Grpc\ChannelCredentials::createSsl() 51 ); 52 $this->assertNotNull($xdsCreds); 53 } 54 55 public function testCreateXdsWithInsecure() { 56 $xdsCreds = \Grpc\ChannelCredentials::createXds( 57 \Grpc\ChannelCredentials::createInsecure() 58 ); 59 $this->assertNotNull($xdsCreds); 60 } 61 62 public function testCreateXdsWithNull() { 63 $this->expectException(\InvalidArgumentException::class); 64 $xdsCreds = \Grpc\ChannelCredentials::createXds(null); 65 } 66 67 public function testCreateXdsWithInvalidType() { 68 $this->expectException(\TypeError::class); 69 $xdsCreds = \Grpc\ChannelCredentials::createXds("invalid-type"); 70 } 71 72 public function testGetConnectivityState() 73 { 74 $this->channel = new Grpc\Channel('localhost:50001', 75 ['credentials' => Grpc\ChannelCredentials::createInsecure()]); 76 $state = $this->channel->getConnectivityState(); 77 $this->assertEquals(0, $state); 78 } 79 80 public function testGetConnectivityStateWithInt() 81 { 82 $this->channel = new Grpc\Channel('localhost:50002', 83 ['credentials' => Grpc\ChannelCredentials::createInsecure()]); 84 $state = $this->channel->getConnectivityState(123); 85 $this->assertEquals(0, $state); 86 } 87 88 public function testGetConnectivityStateWithString() 89 { 90 $this->channel = new Grpc\Channel('localhost:50003', 91 ['credentials' => Grpc\ChannelCredentials::createInsecure()]); 92 $state = $this->channel->getConnectivityState('hello'); 93 $this->assertEquals(0, $state); 94 } 95 96 public function testGetConnectivityStateWithBool() 97 { 98 $this->channel = new Grpc\Channel('localhost:50004', 99 ['credentials' => Grpc\ChannelCredentials::createInsecure()]); 100 $state = $this->channel->getConnectivityState(true); 101 $this->assertEquals(0, $state); 102 } 103 104 public function testGetTarget() 105 { 106 $this->channel = new Grpc\Channel('localhost:50005', 107 ['credentials' => Grpc\ChannelCredentials::createInsecure()]); 108 $target = $this->channel->getTarget(); 109 $this->assertTrue(is_string($target)); 110 } 111 112 public function testWatchConnectivityState() 113 { 114 $this->channel = new Grpc\Channel('localhost:50006', 115 ['credentials' => Grpc\ChannelCredentials::createInsecure()]); 116 $now = Grpc\Timeval::now(); 117 $deadline = $now->add(new Grpc\Timeval(100*1000)); // 100ms 118 // we act as if 'CONNECTING'(=1) was the last state 119 // we saw, so the default state of 'IDLE' should be delivered instantly 120 $state = $this->channel->watchConnectivityState(1, $deadline); 121 $this->assertTrue($state); 122 unset($now); 123 unset($deadline); 124 } 125 126 public function testClose() 127 { 128 $this->channel = new Grpc\Channel('localhost:50007', 129 ['credentials' => Grpc\ChannelCredentials::createInsecure()]); 130 $this->assertNotNull($this->channel); 131 $this->channel->close(); 132 } 133 134 public function testInvalidConstructorWithNull() 135 { 136 $this->expectException(\InvalidArgumentException::class); 137 $this->channel = new Grpc\Channel(); 138 $this->assertNull($this->channel); 139 } 140 141 public function testInvalidConstructorWith() 142 { 143 $this->expectException(\InvalidArgumentException::class); 144 $this->channel = new Grpc\Channel('localhost:50008', 'invalid'); 145 $this->assertNull($this->channel); 146 } 147 148 public function testInvalidCredentials() 149 { 150 $this->expectException(\InvalidArgumentException::class); 151 $this->channel = new Grpc\Channel('localhost:50009', 152 ['credentials' => new Grpc\Timeval(100)]); 153 } 154 155 public function testInvalidOptionsArray() 156 { 157 $this->expectException(\InvalidArgumentException::class); 158 $this->channel = new Grpc\Channel('localhost:50010', 159 ['abc' => []]); 160 } 161 162 public function testInvalidGetConnectivityStateWithArray() 163 { 164 $this->expectException(\InvalidArgumentException::class); 165 $this->channel = new Grpc\Channel('localhost:50011', 166 ['credentials' => Grpc\ChannelCredentials::createInsecure()]); 167 $this->channel->getConnectivityState([]); 168 } 169 170 public function testInvalidWatchConnectivityState() 171 { 172 $this->expectException(\InvalidArgumentException::class); 173 $this->channel = new Grpc\Channel('localhost:50012', 174 ['credentials' => Grpc\ChannelCredentials::createInsecure()]); 175 $this->channel->watchConnectivityState([]); 176 } 177 178 public function testInvalidWatchConnectivityState2() 179 { 180 $this->expectException(\InvalidArgumentException::class); 181 $this->channel = new Grpc\Channel('localhost:50013', 182 ['credentials' => Grpc\ChannelCredentials::createInsecure()]); 183 $this->channel->watchConnectivityState(1, 'hi'); 184 } 185 186 187 public function assertConnecting($state) { 188 $this->assertTrue($state == GRPC\CHANNEL_CONNECTING || 189 $state == GRPC\CHANNEL_TRANSIENT_FAILURE); 190 } 191 192 public function waitUntilNotIdle($channel) { 193 for ($i = 0; $i < 10; $i++) { 194 $now = Grpc\Timeval::now(); 195 $deadline = $now->add(new Grpc\Timeval(1000)); 196 if ($channel->watchConnectivityState(GRPC\CHANNEL_IDLE, 197 $deadline)) { 198 return true; 199 } 200 } 201 $this->assertTrue(false); 202 } 203 204 public function testPersistentChannelSameHost() 205 { 206 $this->channel1 = new Grpc\Channel('localhost:50014', [ 207 "grpc_target_persist_bound" => 3, 208 ]); 209 // the underlying grpc channel is the same by default 210 // when connecting to the same host 211 $this->channel2 = new Grpc\Channel('localhost:50014', []); 212 213 // both channels should be IDLE 214 $state = $this->channel1->getConnectivityState(); 215 $this->assertEquals(GRPC\CHANNEL_IDLE, $state); 216 $state = $this->channel2->getConnectivityState(); 217 $this->assertEquals(GRPC\CHANNEL_IDLE, $state); 218 219 // try to connect on channel1 220 $state = $this->channel1->getConnectivityState(true); 221 $this->waitUntilNotIdle($this->channel1); 222 223 // both channels should now be in the CONNECTING state 224 $state = $this->channel1->getConnectivityState(); 225 $this->assertConnecting($state); 226 $state = $this->channel2->getConnectivityState(); 227 $this->assertConnecting($state); 228 229 $this->channel1->close(); 230 $this->channel2->close(); 231 } 232 233 public function testPersistentChannelDifferentHost() 234 { 235 // two different underlying channels because different hostname 236 $this->channel1 = new Grpc\Channel('localhost:50015', [ 237 "grpc_target_persist_bound" => 3, 238 ]); 239 $this->channel2 = new Grpc\Channel('localhost:50016', []); 240 241 // both channels should be IDLE 242 $state = $this->channel1->getConnectivityState(); 243 $this->assertEquals(GRPC\CHANNEL_IDLE, $state); 244 $state = $this->channel2->getConnectivityState(); 245 $this->assertEquals(GRPC\CHANNEL_IDLE, $state); 246 247 // try to connect on channel1 248 $state = $this->channel1->getConnectivityState(true); 249 $this->waitUntilNotIdle($this->channel1); 250 251 // channel1 should now be in the CONNECTING state 252 $state = $this->channel1->getConnectivityState(); 253 $this->assertConnecting($state); 254 // channel2 should still be in the IDLE state 255 $state = $this->channel2->getConnectivityState(); 256 $this->assertEquals(GRPC\CHANNEL_IDLE, $state); 257 258 $this->channel1->close(); 259 $this->channel2->close(); 260 } 261 262 public function testPersistentChannelSameArgs() 263 { 264 $this->channel1 = new Grpc\Channel('localhost:50017', [ 265 "grpc_target_persist_bound" => 3, 266 "abc" => "def", 267 ]); 268 $this->channel2 = new Grpc\Channel('localhost:50017', ["abc" => "def"]); 269 270 // try to connect on channel1 271 $state = $this->channel1->getConnectivityState(true); 272 $this->waitUntilNotIdle($this->channel1); 273 274 $state = $this->channel1->getConnectivityState(); 275 $this->assertConnecting($state); 276 $state = $this->channel2->getConnectivityState(); 277 $this->assertConnecting($state); 278 279 $this->channel1->close(); 280 $this->channel2->close(); 281 } 282 283 public function testPersistentChannelDifferentArgs() 284 { 285 $this->channel1 = new Grpc\Channel('localhost:50018', [ 286 "grpc_target_persist_bound" => 3, 287 ]); 288 $this->channel2 = new Grpc\Channel('localhost:50018', ["abc" => "def"]); 289 290 // try to connect on channel1 291 $state = $this->channel1->getConnectivityState(true); 292 $this->waitUntilNotIdle($this->channel1); 293 294 $state = $this->channel1->getConnectivityState(); 295 $this->assertConnecting($state); 296 $state = $this->channel2->getConnectivityState(); 297 $this->assertEquals(GRPC\CHANNEL_IDLE, $state); 298 299 $this->channel1->close(); 300 $this->channel2->close(); 301 } 302 303 public function persistentChannelSameChannelCredentialsProvider(): array 304 { 305 return [ 306 [ 307 Grpc\ChannelCredentials::createSsl(), 308 Grpc\ChannelCredentials::createSsl(), 309 50301, 310 ], 311 [ 312 Grpc\ChannelCredentials::createSsl( 313 file_get_contents(dirname(__FILE__) . '/../data/ca.pem') 314 ), 315 Grpc\ChannelCredentials::createSsl( 316 file_get_contents(dirname(__FILE__) . '/../data/ca.pem') 317 ), 318 50302, 319 ], 320 [ 321 Grpc\ChannelCredentials::createInSecure(), 322 Grpc\ChannelCredentials::createInSecure(), 323 50303, 324 ], 325 [ 326 \Grpc\ChannelCredentials::createXds( 327 \Grpc\ChannelCredentials::createSsl() 328 ), 329 \Grpc\ChannelCredentials::createXds( 330 \Grpc\ChannelCredentials::createSsl() 331 ), 332 50304, 333 ], 334 [ 335 \Grpc\ChannelCredentials::createXds( 336 \Grpc\ChannelCredentials::createSsl() 337 ), 338 \Grpc\ChannelCredentials::createXds( 339 \Grpc\ChannelCredentials::createSsl() 340 ), 341 50305, 342 ], 343 [ 344 \Grpc\ChannelCredentials::createXds( 345 \Grpc\ChannelCredentials::createSsl( 346 file_get_contents(dirname(__FILE__) . '/../data/ca.pem') 347 ) 348 ), 349 \Grpc\ChannelCredentials::createXds( 350 \Grpc\ChannelCredentials::createSsl( 351 file_get_contents(dirname(__FILE__) . '/../data/ca.pem') 352 ) 353 ), 354 50306, 355 ], 356 [ 357 \Grpc\ChannelCredentials::createXds( 358 \Grpc\ChannelCredentials::createInSecure() 359 ), 360 \Grpc\ChannelCredentials::createXds( 361 \Grpc\ChannelCredentials::createInSecure() 362 ), 363 50307, 364 ], 365 ]; 366 } 367 368 /** 369 * @dataProvider persistentChannelSameChannelCredentialsProvider 370 */ 371 public function testPersistentChannelSameChannelCredentials( 372 $creds1, 373 $creds2, 374 $port 375 ) { 376 $this->channel1 = new Grpc\Channel( 377 'localhost:' . $port, 378 [ 379 "credentials" => $creds1, 380 "grpc_target_persist_bound" => 3, 381 ] 382 ); 383 $this->channel2 = new Grpc\Channel( 384 'localhost:' . $port, 385 ["credentials" => $creds2] 386 ); 387 388 // try to connect on channel1 389 $state = $this->channel1->getConnectivityState(true); 390 $this->waitUntilNotIdle($this->channel1); 391 392 $state = $this->channel1->getConnectivityState(); 393 $this->assertConnecting($state); 394 $state = $this->channel2->getConnectivityState(); 395 $this->assertConnecting($state); 396 397 $this->channel1->close(); 398 $this->channel2->close(); 399 } 400 401 public function persistentChannelDifferentChannelCredentialsProvider(): array 402 { 403 return [ 404 [ 405 Grpc\ChannelCredentials::createSsl(), 406 Grpc\ChannelCredentials::createSsl( 407 file_get_contents(dirname(__FILE__) . '/../data/ca.pem') 408 ), 409 50351, 410 ], 411 [ 412 Grpc\ChannelCredentials::createSsl(), 413 Grpc\ChannelCredentials::createInsecure(), 414 50352, 415 ], 416 [ 417 \Grpc\ChannelCredentials::createXds( 418 \Grpc\ChannelCredentials::createSsl() 419 ), 420 \Grpc\ChannelCredentials::createXds( 421 \Grpc\ChannelCredentials::createSsl( 422 file_get_contents(dirname(__FILE__) . '/../data/ca.pem') 423 ) 424 ), 425 50353, 426 ], 427 [ 428 \Grpc\ChannelCredentials::createXds( 429 \Grpc\ChannelCredentials::createSsl() 430 ), 431 \Grpc\ChannelCredentials::createXds( 432 \Grpc\ChannelCredentials::createInsecure() 433 ), 434 50354, 435 ], 436 [ 437 \Grpc\ChannelCredentials::createInsecure(), 438 \Grpc\ChannelCredentials::createXds( 439 \Grpc\ChannelCredentials::createInsecure() 440 ), 441 50355, 442 ], 443 [ 444 \Grpc\ChannelCredentials::createSsl(), 445 \Grpc\ChannelCredentials::createXds( 446 \Grpc\ChannelCredentials::createSsl() 447 ), 448 50356, 449 ], 450 ]; 451 } 452 453 /** 454 * @dataProvider persistentChannelDifferentChannelCredentialsProvider 455 */ 456 public function testPersistentChannelDifferentChannelCredentials( 457 $creds1, 458 $creds2, 459 $port 460 ) { 461 462 $this->channel1 = new Grpc\Channel( 463 'localhost:' . $port, 464 [ 465 "credentials" => $creds1, 466 "grpc_target_persist_bound" => 3, 467 ] 468 ); 469 $this->channel2 = new Grpc\Channel( 470 'localhost:' . $port, 471 ["credentials" => $creds2] 472 ); 473 474 // try to connect on channel1 475 $state = $this->channel1->getConnectivityState(true); 476 $this->waitUntilNotIdle($this->channel1); 477 478 $state = $this->channel1->getConnectivityState(); 479 $this->assertConnecting($state); 480 $state = $this->channel2->getConnectivityState(); 481 $this->assertEquals(GRPC\CHANNEL_IDLE, $state); 482 483 $this->channel1->close(); 484 $this->channel2->close(); 485 } 486 487 public function testPersistentChannelSharedChannelClose1() 488 { 489 // same underlying channel 490 $this->channel1 = new Grpc\Channel('localhost:50123', [ 491 "grpc_target_persist_bound" => 3, 492 ]); 493 $this->channel2 = new Grpc\Channel('localhost:50123', []); 494 495 // close channel1 496 $this->channel1->close(); 497 498 // channel2 can still be use. We need to exclude the possible that 499 // in testPersistentChannelSharedChannelClose2, the exception is thrown 500 // by channel1. 501 $state = $this->channel2->getConnectivityState(); 502 $this->assertEquals(GRPC\CHANNEL_IDLE, $state); 503 } 504 505 public function testPersistentChannelSharedChannelClose2() 506 { 507 $this->expectException(\RuntimeException::class); 508 // same underlying channel 509 $this->channel1 = new Grpc\Channel('localhost:50223', [ 510 "grpc_target_persist_bound" => 3, 511 ]); 512 $this->channel2 = new Grpc\Channel('localhost:50223', []); 513 514 // close channel1 515 $this->channel1->close(); 516 517 // channel2 can still be use 518 $state = $this->channel2->getConnectivityState(); 519 $this->assertEquals(GRPC\CHANNEL_IDLE, $state); 520 521 // channel 1 is closed 522 $state = $this->channel1->getConnectivityState(); 523 } 524 525 public function testPersistentChannelCreateAfterClose() 526 { 527 $this->channel1 = new Grpc\Channel('localhost:50024', [ 528 "grpc_target_persist_bound" => 3, 529 ]); 530 531 $this->channel1->close(); 532 533 $this->channel2 = new Grpc\Channel('localhost:50024', []); 534 $state = $this->channel2->getConnectivityState(); 535 $this->assertEquals(GRPC\CHANNEL_IDLE, $state); 536 537 $this->channel2->close(); 538 } 539 540 public function testPersistentChannelSharedMoreThanTwo() 541 { 542 $this->channel1 = new Grpc\Channel('localhost:50025', [ 543 "grpc_target_persist_bound" => 3, 544 ]); 545 $this->channel2 = new Grpc\Channel('localhost:50025', []); 546 $this->channel3 = new Grpc\Channel('localhost:50025', []); 547 548 // try to connect on channel1 549 $state = $this->channel1->getConnectivityState(true); 550 $this->waitUntilNotIdle($this->channel1); 551 552 // all 3 channels should be in CONNECTING state 553 $state = $this->channel1->getConnectivityState(); 554 $this->assertConnecting($state); 555 $state = $this->channel2->getConnectivityState(); 556 $this->assertConnecting($state); 557 $state = $this->channel3->getConnectivityState(); 558 $this->assertConnecting($state); 559 560 $this->channel1->close(); 561 } 562 563 public function callbackFunc($context) 564 { 565 return []; 566 } 567 568 public function callbackFunc2($context) 569 { 570 return ["k1" => "v1"]; 571 } 572 573 public function testPersistentChannelWithCallCredentials() 574 { 575 $creds = Grpc\ChannelCredentials::createSsl(); 576 $callCreds = Grpc\CallCredentials::createFromPlugin( 577 [$this, 'callbackFunc']); 578 $credsWithCallCreds = Grpc\ChannelCredentials::createComposite( 579 $creds, $callCreds); 580 581 // If a ChannelCredentials object is composed with a 582 // CallCredentials object, the underlying grpc channel will 583 // always be created new and NOT persisted. 584 $this->channel1 = new Grpc\Channel('localhost:50026', 585 ["credentials" => 586 $credsWithCallCreds, 587 "grpc_target_persist_bound" => 3, 588 ]); 589 $this->channel2 = new Grpc\Channel('localhost:50026', 590 ["credentials" => 591 $credsWithCallCreds]); 592 593 // try to connect on channel1 594 $state = $this->channel1->getConnectivityState(true); 595 $this->waitUntilNotIdle($this->channel1); 596 597 $state = $this->channel1->getConnectivityState(); 598 $this->assertConnecting($state); 599 $state = $this->channel2->getConnectivityState(); 600 $this->assertEquals(GRPC\CHANNEL_IDLE, $state); 601 602 $this->channel1->close(); 603 $this->channel2->close(); 604 } 605 606 public function testPersistentChannelWithDifferentCallCredentials() 607 { 608 $callCreds1 = Grpc\CallCredentials::createFromPlugin( 609 [$this, 'callbackFunc']); 610 $callCreds2 = Grpc\CallCredentials::createFromPlugin( 611 [$this, 'callbackFunc2']); 612 613 $creds1 = Grpc\ChannelCredentials::createSsl(); 614 $creds2 = Grpc\ChannelCredentials::createComposite( 615 $creds1, $callCreds1); 616 $creds3 = Grpc\ChannelCredentials::createComposite( 617 $creds1, $callCreds2); 618 619 // Similar to the test above, anytime a ChannelCredentials 620 // object is composed with a CallCredentials object, the 621 // underlying grpc channel will always be separate and not 622 // persisted 623 $this->channel1 = new Grpc\Channel('localhost:50027', 624 ["credentials" => $creds1, 625 "grpc_target_persist_bound" => 3, 626 ]); 627 $this->channel2 = new Grpc\Channel('localhost:50027', 628 ["credentials" => $creds2]); 629 $this->channel3 = new Grpc\Channel('localhost:50027', 630 ["credentials" => $creds3]); 631 632 // try to connect on channel1 633 $state = $this->channel1->getConnectivityState(true); 634 $this->waitUntilNotIdle($this->channel1); 635 636 $state = $this->channel1->getConnectivityState(); 637 $this->assertConnecting($state); 638 $state = $this->channel2->getConnectivityState(); 639 $this->assertEquals(GRPC\CHANNEL_IDLE, $state); 640 $state = $this->channel3->getConnectivityState(); 641 $this->assertEquals(GRPC\CHANNEL_IDLE, $state); 642 643 $this->channel1->close(); 644 $this->channel2->close(); 645 $this->channel3->close(); 646 } 647 648 public function testPersistentChannelForceNew() 649 { 650 $this->channel1 = new Grpc\Channel('localhost:50028', [ 651 "grpc_target_persist_bound" => 2, 652 ]); 653 // even though all the channel params are the same, channel2 654 // has a new and different underlying channel 655 $this->channel2 = new Grpc\Channel('localhost:50028', 656 ["force_new" => true]); 657 658 // try to connect on channel1 659 $state = $this->channel1->getConnectivityState(true); 660 $this->waitUntilNotIdle($this->channel1); 661 662 $state = $this->channel1->getConnectivityState(); 663 $this->assertConnecting($state); 664 $state = $this->channel2->getConnectivityState(); 665 $this->assertEquals(GRPC\CHANNEL_IDLE, $state); 666 667 $this->channel1->close(); 668 $this->channel2->close(); 669 } 670 671 public function testPersistentChannelForceNewOldChannelIdle1() 672 { 673 674 $this->channel1 = new Grpc\Channel('localhost:50029', [ 675 "grpc_target_persist_bound" => 2, 676 ]); 677 $this->channel2 = new Grpc\Channel('localhost:50029', 678 ["force_new" => true]); 679 // channel3 shares with channel1 680 $this->channel3 = new Grpc\Channel('localhost:50029', []); 681 682 // try to connect on channel2 683 $state = $this->channel2->getConnectivityState(true); 684 $this->waitUntilNotIdle($this->channel2); 685 $state = $this->channel1->getConnectivityState(); 686 $this->assertEquals(GRPC\CHANNEL_IDLE, $state); 687 $state = $this->channel2->getConnectivityState(); 688 $this->assertConnecting($state); 689 $state = $this->channel3->getConnectivityState(); 690 $this->assertEquals(GRPC\CHANNEL_IDLE, $state); 691 692 $this->channel1->close(); 693 $this->channel2->close(); 694 } 695 696 public function testPersistentChannelForceNewOldChannelIdle2() 697 { 698 699 $this->channel1 = new Grpc\Channel('localhost:50032', [ 700 "grpc_target_persist_bound" => 2, 701 ]); 702 $this->channel2 = new Grpc\Channel('localhost:50032', []); 703 704 // try to connect on channel2 705 $state = $this->channel1->getConnectivityState(true); 706 $this->waitUntilNotIdle($this->channel2); 707 $state = $this->channel1->getConnectivityState(); 708 $this->assertConnecting($state); 709 $state = $this->channel2->getConnectivityState(); 710 $this->assertConnecting($state); 711 712 $this->channel1->close(); 713 $this->channel2->close(); 714 } 715 716 public function testPersistentChannelForceNewOldChannelClose1() 717 { 718 719 $this->channel1 = new Grpc\Channel('localhost:50130', [ 720 "grpc_target_persist_bound" => 2, 721 ]); 722 $this->channel2 = new Grpc\Channel('localhost:50130', 723 ["force_new" => true]); 724 // channel3 shares with channel1 725 $this->channel3 = new Grpc\Channel('localhost:50130', []); 726 727 $this->channel1->close(); 728 729 $state = $this->channel2->getConnectivityState(); 730 $this->assertEquals(GRPC\CHANNEL_IDLE, $state); 731 732 // channel3 is still usable. We need to exclude the possibility that in 733 // testPersistentChannelForceNewOldChannelClose2, the exception is thrown 734 // by channel1 and channel2. 735 $state = $this->channel3->getConnectivityState(); 736 $this->assertEquals(GRPC\CHANNEL_IDLE, $state); 737 } 738 739 public function testPersistentChannelForceNewOldChannelClose2() 740 { 741 $this->expectException(\RuntimeException::class); 742 $this->channel1 = new Grpc\Channel('localhost:50230', [ 743 "grpc_target_persist_bound" => 2, 744 ]); 745 $this->channel2 = new Grpc\Channel('localhost:50230', 746 ["force_new" => true]); 747 // channel3 shares with channel1 748 $this->channel3 = new Grpc\Channel('localhost:50230', []); 749 750 $this->channel1->close(); 751 752 $state = $this->channel2->getConnectivityState(); 753 $this->assertEquals(GRPC\CHANNEL_IDLE, $state); 754 755 // channel3 is still usable 756 $state = $this->channel3->getConnectivityState(); 757 $this->assertEquals(GRPC\CHANNEL_IDLE, $state); 758 759 // channel 1 is closed 760 $this->channel1->getConnectivityState(); 761 } 762 763 public function testPersistentChannelForceNewNewChannelClose() 764 { 765 766 $this->channel1 = new Grpc\Channel('localhost:50031', [ 767 "grpc_target_persist_bound" => 2, 768 ]); 769 $this->channel2 = new Grpc\Channel('localhost:50031', 770 ["force_new" => true]); 771 $this->channel3 = new Grpc\Channel('localhost:50031', []); 772 773 $this->channel2->close(); 774 775 $state = $this->channel1->getConnectivityState(); 776 $this->assertEquals(GRPC\CHANNEL_IDLE, $state); 777 778 // can still connect on channel1 779 $state = $this->channel1->getConnectivityState(true); 780 $this->waitUntilNotIdle($this->channel1); 781 782 $state = $this->channel1->getConnectivityState(); 783 $this->assertConnecting($state); 784 785 $this->channel1->close(); 786 } 787} 788