From 5b3dc4aa75c296aec6d77b1927399720b87bb83f Mon Sep 17 00:00:00 2001 From: Stanley Cheung Date: Thu, 3 Aug 2017 18:00:25 -0700 Subject: PHP: persistent channel --- src/php/tests/unit_tests/CallTest.php | 3 +- src/php/tests/unit_tests/ChannelTest.php | 457 ++++++++++++++++++++++-- src/php/tests/unit_tests/EndToEndTest.php | 7 +- src/php/tests/unit_tests/SecureEndToEndTest.php | 3 +- 4 files changed, 442 insertions(+), 28 deletions(-) (limited to 'src/php/tests') diff --git a/src/php/tests/unit_tests/CallTest.php b/src/php/tests/unit_tests/CallTest.php index 3270e73f82..c5e1890a98 100644 --- a/src/php/tests/unit_tests/CallTest.php +++ b/src/php/tests/unit_tests/CallTest.php @@ -37,8 +37,7 @@ class CallTest extends PHPUnit_Framework_TestCase public function tearDown() { - unset($this->call); - unset($this->channel); + $this->channel->close(); } public function testConstructor() diff --git a/src/php/tests/unit_tests/ChannelTest.php b/src/php/tests/unit_tests/ChannelTest.php index 34e6185031..400df0fb66 100644 --- a/src/php/tests/unit_tests/ChannelTest.php +++ b/src/php/tests/unit_tests/ChannelTest.php @@ -25,17 +25,15 @@ class ChannelTest extends PHPUnit_Framework_TestCase public function tearDown() { - unset($this->channel); + if (!empty($this->channel)) { + $this->channel->close(); + } } public function testInsecureCredentials() { - $this->channel = new Grpc\Channel( - 'localhost:0', - [ - 'credentials' => Grpc\ChannelCredentials::createInsecure(), - ] - ); + $this->channel = new Grpc\Channel('localhost:0', + ['credentials' => Grpc\ChannelCredentials::createInsecure()]); $this->assertSame('Grpc\Channel', get_class($this->channel)); } @@ -111,7 +109,7 @@ class ChannelTest extends PHPUnit_Framework_TestCase */ public function testInvalidConstructorWith() { - $this->channel = new Grpc\Channel('localhost', 'invalid'); + $this->channel = new Grpc\Channel('localhost:0', 'invalid'); $this->assertNull($this->channel); } @@ -120,12 +118,8 @@ class ChannelTest extends PHPUnit_Framework_TestCase */ public function testInvalidCredentials() { - $this->channel = new Grpc\Channel( - 'localhost:0', - [ - 'credentials' => new Grpc\Timeval(100), - ] - ); + $this->channel = new Grpc\Channel('localhost:0', + ['credentials' => new Grpc\Timeval(100)]); } /** @@ -133,12 +127,8 @@ class ChannelTest extends PHPUnit_Framework_TestCase */ public function testInvalidOptionsArray() { - $this->channel = new Grpc\Channel( - 'localhost:0', - [ - 'abc' => [], - ] - ); + $this->channel = new Grpc\Channel('localhost:0', + ['abc' => []]); } /** @@ -170,4 +160,431 @@ class ChannelTest extends PHPUnit_Framework_TestCase ['credentials' => Grpc\ChannelCredentials::createInsecure()]); $this->channel->watchConnectivityState(1, 'hi'); } + + + public function assertConnecting($state) { + $this->assertTrue($state == GRPC\CHANNEL_CONNECTING || + $state == GRPC\CHANNEL_TRANSIENT_FAILURE); + } + + public function waitUntilNotIdle($channel) { + for ($i = 0; $i < 10; $i++) { + $now = Grpc\Timeval::now(); + $deadline = $now->add(new Grpc\Timeval(1000)); + if ($channel->watchConnectivityState(GRPC\CHANNEL_IDLE, + $deadline)) { + return true; + } + } + $this->assertTrue(false); + } + + public function testPersistentChannelSameHost() + { + $this->channel1 = new Grpc\Channel('localhost:1', []); + // the underlying grpc channel is the same by default + // when connecting to the same host + $this->channel2 = new Grpc\Channel('localhost:1', []); + + // both channels should be IDLE + $state = $this->channel1->getConnectivityState(); + $this->assertEquals(GRPC\CHANNEL_IDLE, $state); + $state = $this->channel2->getConnectivityState(); + $this->assertEquals(GRPC\CHANNEL_IDLE, $state); + + // try to connect on channel1 + $state = $this->channel1->getConnectivityState(true); + $this->waitUntilNotIdle($this->channel1); + + // both channels should now be in the CONNECTING state + $state = $this->channel1->getConnectivityState(); + $this->assertConnecting($state); + $state = $this->channel2->getConnectivityState(); + $this->assertConnecting($state); + + $this->channel1->close(); + $this->channel2->close(); + } + + public function testPersistentChannelDifferentHost() + { + // two different underlying channels because different hostname + $this->channel1 = new Grpc\Channel('localhost:1', []); + $this->channel2 = new Grpc\Channel('localhost:2', []); + + // both channels should be IDLE + $state = $this->channel1->getConnectivityState(); + $this->assertEquals(GRPC\CHANNEL_IDLE, $state); + $state = $this->channel2->getConnectivityState(); + $this->assertEquals(GRPC\CHANNEL_IDLE, $state); + + // try to connect on channel1 + $state = $this->channel1->getConnectivityState(true); + $this->waitUntilNotIdle($this->channel1); + + // channel1 should now be in the CONNECTING state + $state = $this->channel1->getConnectivityState(); + $this->assertConnecting($state); + // channel2 should still be in the IDLE state + $state = $this->channel2->getConnectivityState(); + $this->assertEquals(GRPC\CHANNEL_IDLE, $state); + + $this->channel1->close(); + $this->channel2->close(); + } + + public function testPersistentChannelSameArgs() + { + $this->channel1 = new Grpc\Channel('localhost:1', ["abc" => "def"]); + $this->channel2 = new Grpc\Channel('localhost:1', ["abc" => "def"]); + + // try to connect on channel1 + $state = $this->channel1->getConnectivityState(true); + $this->waitUntilNotIdle($this->channel1); + + $state = $this->channel1->getConnectivityState(); + $this->assertConnecting($state); + $state = $this->channel2->getConnectivityState(); + $this->assertConnecting($state); + + $this->channel1->close(); + $this->channel2->close(); + } + + public function testPersistentChannelDifferentArgs() + { + $this->channel1 = new Grpc\Channel('localhost:1', []); + $this->channel2 = new Grpc\Channel('localhost:1', ["abc" => "def"]); + + // try to connect on channel1 + $state = $this->channel1->getConnectivityState(true); + $this->waitUntilNotIdle($this->channel1); + + $state = $this->channel1->getConnectivityState(); + $this->assertConnecting($state); + $state = $this->channel2->getConnectivityState(); + $this->assertEquals(GRPC\CHANNEL_IDLE, $state); + + $this->channel1->close(); + $this->channel2->close(); + } + + public function testPersistentChannelSameChannelCredentials() + { + $creds1 = Grpc\ChannelCredentials::createSsl(); + $creds2 = Grpc\ChannelCredentials::createSsl(); + + $this->channel1 = new Grpc\Channel('localhost:1', + ["credentials" => $creds1]); + $this->channel2 = new Grpc\Channel('localhost:1', + ["credentials" => $creds2]); + + // try to connect on channel1 + $state = $this->channel1->getConnectivityState(true); + $this->waitUntilNotIdle($this->channel1); + + $state = $this->channel1->getConnectivityState(); + $this->assertConnecting($state); + $state = $this->channel2->getConnectivityState(); + $this->assertConnecting($state); + + $this->channel1->close(); + $this->channel2->close(); + } + + public function testPersistentChannelDifferentChannelCredentials() + { + $creds1 = Grpc\ChannelCredentials::createSsl(); + $creds2 = Grpc\ChannelCredentials::createSsl( + file_get_contents(dirname(__FILE__).'/../data/ca.pem')); + + $this->channel1 = new Grpc\Channel('localhost:1', + ["credentials" => $creds1]); + $this->channel2 = new Grpc\Channel('localhost:1', + ["credentials" => $creds2]); + + // try to connect on channel1 + $state = $this->channel1->getConnectivityState(true); + $this->waitUntilNotIdle($this->channel1); + + $state = $this->channel1->getConnectivityState(); + $this->assertConnecting($state); + $state = $this->channel2->getConnectivityState(); + $this->assertEquals(GRPC\CHANNEL_IDLE, $state); + + $this->channel1->close(); + $this->channel2->close(); + } + + public function testPersistentChannelSameChannelCredentialsRootCerts() + { + $creds1 = Grpc\ChannelCredentials::createSsl( + file_get_contents(dirname(__FILE__).'/../data/ca.pem')); + $creds2 = Grpc\ChannelCredentials::createSsl( + file_get_contents(dirname(__FILE__).'/../data/ca.pem')); + + $this->channel1 = new Grpc\Channel('localhost:1', + ["credentials" => $creds1]); + $this->channel2 = new Grpc\Channel('localhost:1', + ["credentials" => $creds2]); + + // try to connect on channel1 + $state = $this->channel1->getConnectivityState(true); + $this->waitUntilNotIdle($this->channel1); + + $state = $this->channel1->getConnectivityState(); + $this->assertConnecting($state); + $state = $this->channel2->getConnectivityState(); + $this->assertConnecting($state); + + $this->channel1->close(); + $this->channel2->close(); + } + + public function testPersistentChannelDifferentSecureChannelCredentials() + { + $creds1 = Grpc\ChannelCredentials::createSsl(); + $creds2 = Grpc\ChannelCredentials::createInsecure(); + + $this->channel1 = new Grpc\Channel('localhost:1', + ["credentials" => $creds1]); + $this->channel2 = new Grpc\Channel('localhost:1', + ["credentials" => $creds2]); + + // try to connect on channel1 + $state = $this->channel1->getConnectivityState(true); + $this->waitUntilNotIdle($this->channel1); + + $state = $this->channel1->getConnectivityState(); + $this->assertConnecting($state); + $state = $this->channel2->getConnectivityState(); + $this->assertEquals(GRPC\CHANNEL_IDLE, $state); + + $this->channel1->close(); + $this->channel2->close(); + } + + /** + * @expectedException RuntimeException + */ + public function testPersistentChannelSharedChannelClose() + { + // same underlying channel + $this->channel1 = new Grpc\Channel('localhost:1', []); + $this->channel2 = new Grpc\Channel('localhost:1', []); + + // close channel1 + $this->channel1->close(); + + // channel2 is now in SHUTDOWN state + $state = $this->channel2->getConnectivityState(); + $this->assertEquals(GRPC\CHANNEL_FATAL_FAILURE, $state); + + // calling it again will result in an exception because the + // channel is already closed + $state = $this->channel2->getConnectivityState(); + } + + public function testPersistentChannelCreateAfterClose() + { + $this->channel1 = new Grpc\Channel('localhost:1', []); + + $this->channel1->close(); + + $this->channel2 = new Grpc\Channel('localhost:1', []); + $state = $this->channel2->getConnectivityState(); + $this->assertEquals(GRPC\CHANNEL_IDLE, $state); + + $this->channel2->close(); + } + + public function testPersistentChannelSharedMoreThanTwo() + { + $this->channel1 = new Grpc\Channel('localhost:1', []); + $this->channel2 = new Grpc\Channel('localhost:1', []); + $this->channel3 = new Grpc\Channel('localhost:1', []); + + // try to connect on channel1 + $state = $this->channel1->getConnectivityState(true); + $this->waitUntilNotIdle($this->channel1); + + // all 3 channels should be in CONNECTING state + $state = $this->channel1->getConnectivityState(); + $this->assertConnecting($state); + $state = $this->channel2->getConnectivityState(); + $this->assertConnecting($state); + $state = $this->channel3->getConnectivityState(); + $this->assertConnecting($state); + + $this->channel1->close(); + } + + public function callbackFunc($context) + { + return []; + } + + public function callbackFunc2($context) + { + return ["k1" => "v1"]; + } + + public function testPersistentChannelWithCallCredentials() + { + $creds = Grpc\ChannelCredentials::createSsl(); + $callCreds = Grpc\CallCredentials::createFromPlugin( + [$this, 'callbackFunc']); + $credsWithCallCreds = Grpc\ChannelCredentials::createComposite( + $creds, $callCreds); + + // If a ChannelCredentials object is composed with a + // CallCredentials object, the underlying grpc channel will + // always be created new and NOT persisted. + $this->channel1 = new Grpc\Channel('localhost:1', + ["credentials" => + $credsWithCallCreds]); + $this->channel2 = new Grpc\Channel('localhost:1', + ["credentials" => + $credsWithCallCreds]); + + // try to connect on channel1 + $state = $this->channel1->getConnectivityState(true); + $this->waitUntilNotIdle($this->channel1); + + $state = $this->channel1->getConnectivityState(); + $this->assertConnecting($state); + $state = $this->channel2->getConnectivityState(); + $this->assertEquals(GRPC\CHANNEL_IDLE, $state); + + $this->channel1->close(); + $this->channel2->close(); + } + + public function testPersistentChannelWithDifferentCallCredentials() + { + $callCreds1 = Grpc\CallCredentials::createFromPlugin( + [$this, 'callbackFunc']); + $callCreds2 = Grpc\CallCredentials::createFromPlugin( + [$this, 'callbackFunc2']); + + $creds1 = Grpc\ChannelCredentials::createSsl(); + $creds2 = Grpc\ChannelCredentials::createComposite( + $creds1, $callCreds1); + $creds3 = Grpc\ChannelCredentials::createComposite( + $creds1, $callCreds2); + + // Similar to the test above, anytime a ChannelCredentials + // object is composed with a CallCredentials object, the + // underlying grpc channel will always be separate and not + // persisted + $this->channel1 = new Grpc\Channel('localhost:1', + ["credentials" => $creds1]); + $this->channel2 = new Grpc\Channel('localhost:1', + ["credentials" => $creds2]); + $this->channel3 = new Grpc\Channel('localhost:1', + ["credentials" => $creds3]); + + // try to connect on channel1 + $state = $this->channel1->getConnectivityState(true); + $this->waitUntilNotIdle($this->channel1); + + $state = $this->channel1->getConnectivityState(); + $this->assertConnecting($state); + $state = $this->channel2->getConnectivityState(); + $this->assertEquals(GRPC\CHANNEL_IDLE, $state); + $state = $this->channel3->getConnectivityState(); + $this->assertEquals(GRPC\CHANNEL_IDLE, $state); + + $this->channel1->close(); + $this->channel2->close(); + $this->channel3->close(); + } + + public function testPersistentChannelForceNew() + { + $this->channel1 = new Grpc\Channel('localhost:1', []); + // even though all the channel params are the same, channel2 + // has a new and different underlying channel + $this->channel2 = new Grpc\Channel('localhost:1', + ["force_new" => true]); + + // try to connect on channel1 + $state = $this->channel1->getConnectivityState(true); + $this->waitUntilNotIdle($this->channel1); + + $state = $this->channel1->getConnectivityState(); + $this->assertConnecting($state); + $state = $this->channel2->getConnectivityState(); + $this->assertEquals(GRPC\CHANNEL_IDLE, $state); + + // any dangling old connection to the same host must be + // manually closed + $this->channel1->close(); + $this->channel2->close(); + } + + public function testPersistentChannelForceNewOldChannelIdle() + { + + $this->channel1 = new Grpc\Channel('localhost:1', []); + $this->channel2 = new Grpc\Channel('localhost:1', + ["force_new" => true]); + $this->channel3 = new Grpc\Channel('localhost:1', []); + + // try to connect on channel2 + $state = $this->channel2->getConnectivityState(true); + $this->waitUntilNotIdle($this->channel2); + + $state = $this->channel1->getConnectivityState(); + $this->assertEquals(GRPC\CHANNEL_IDLE, $state); + $state = $this->channel2->getConnectivityState(); + $this->assertConnecting($state); + $state = $this->channel3->getConnectivityState(); + $this->assertConnecting($state); + + $this->channel1->close(); + $this->channel2->close(); + } + + public function testPersistentChannelForceNewOldChannelClose() + { + + $this->channel1 = new Grpc\Channel('localhost:1', []); + $this->channel2 = new Grpc\Channel('localhost:1', + ["force_new" => true]); + $this->channel3 = new Grpc\Channel('localhost:1', []); + + $this->channel1->close(); + + $state = $this->channel2->getConnectivityState(); + $this->assertEquals(GRPC\CHANNEL_IDLE, $state); + $state = $this->channel3->getConnectivityState(); + $this->assertEquals(GRPC\CHANNEL_IDLE, $state); + + $this->channel2->close(); + $this->channel3->close(); + } + + public function testPersistentChannelForceNewNewChannelClose() + { + + $this->channel1 = new Grpc\Channel('localhost:1', []); + $this->channel2 = new Grpc\Channel('localhost:1', + ["force_new" => true]); + $this->channel3 = new Grpc\Channel('localhost:1', []); + + $this->channel2->close(); + + $state = $this->channel1->getConnectivityState(); + $this->assertEquals(GRPC\CHANNEL_IDLE, $state); + + // can still connect on channel1 + $state = $this->channel1->getConnectivityState(true); + $this->waitUntilNotIdle($this->channel1); + + $state = $this->channel1->getConnectivityState(); + $this->assertConnecting($state); + + $this->channel1->close(); + } } diff --git a/src/php/tests/unit_tests/EndToEndTest.php b/src/php/tests/unit_tests/EndToEndTest.php index 43d54d9ee6..b54f1d87c9 100644 --- a/src/php/tests/unit_tests/EndToEndTest.php +++ b/src/php/tests/unit_tests/EndToEndTest.php @@ -28,8 +28,7 @@ class EndToEndTest extends PHPUnit_Framework_TestCase public function tearDown() { - unset($this->channel); - unset($this->server); + $this->channel->close(); } public function testSimpleRequestBody() @@ -516,7 +515,7 @@ class EndToEndTest extends PHPUnit_Framework_TestCase $this->assertTrue($idle_state == Grpc\CHANNEL_IDLE); $now = Grpc\Timeval::now(); - $delta = new Grpc\Timeval(500000); // should timeout + $delta = new Grpc\Timeval(50000); // should timeout $deadline = $now->add($delta); $this->assertFalse($this->channel->watchConnectivityState( @@ -545,7 +544,7 @@ class EndToEndTest extends PHPUnit_Framework_TestCase $this->assertTrue($idle_state == Grpc\CHANNEL_IDLE); $now = Grpc\Timeval::now(); - $delta = new Grpc\Timeval(100000); + $delta = new Grpc\Timeval(50000); $deadline = $now->add($delta); $this->assertFalse($this->channel->watchConnectivityState( diff --git a/src/php/tests/unit_tests/SecureEndToEndTest.php b/src/php/tests/unit_tests/SecureEndToEndTest.php index 0fecbfb3dd..dff4e878ea 100644 --- a/src/php/tests/unit_tests/SecureEndToEndTest.php +++ b/src/php/tests/unit_tests/SecureEndToEndTest.php @@ -43,8 +43,7 @@ class SecureEndToEndTest extends PHPUnit_Framework_TestCase public function tearDown() { - unset($this->channel); - unset($this->server); + $this->channel->close(); } public function testSimpleRequestBody() -- cgit v1.2.3