blob: 2187c9067ebe834d2a228ed28fee399833b90f53 [file] [log] [blame]
<?php
/*
*
* Copyright 2015 gRPC authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
/**
* @group persistent_list_bound_tests
*/
class PersistentChannelTest extends \PHPUnit\Framework\TestCase
{
public function setUp(): void
{
}
public function tearDown(): void
{
$channel_clean_persistent =
new Grpc\Channel('localhost:50010', []);
$plist = $channel_clean_persistent->getPersistentList();
$channel_clean_persistent->cleanPersistentList();
}
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 assertConnecting($state) {
$this->assertTrue($state == GRPC\CHANNEL_CONNECTING ||
$state == GRPC\CHANNEL_TRANSIENT_FAILURE);
}
public function testInitHelper()
{
// PersistentList is not empty at the beginning of the tests
// because phpunit will cache the channels created by other test
// files.
}
public function testChannelNotPersist()
{
$this->channel1 = new Grpc\Channel('localhost:1', ['force_new' => true]);
$channel1_info = $this->channel1->getChannelInfo();
$plist_info = $this->channel1->getPersistentList();
$this->assertEquals($channel1_info['target'], 'localhost:1');
$this->assertEquals($channel1_info['ref_count'], 1);
$this->assertEquals($channel1_info['connectivity_status'],
GRPC\CHANNEL_IDLE);
$this->assertEquals(count($plist_info), 0);
$this->channel1->close();
}
public function testPersistentChannelCreateOneChannel()
{
$this->channel1 = new Grpc\Channel('localhost:1', []);
$channel1_info = $this->channel1->getChannelInfo();
$plist_info = $this->channel1->getPersistentList();
$this->assertEquals($channel1_info['target'], 'localhost:1');
$this->assertEquals($channel1_info['ref_count'], 2);
$this->assertEquals($channel1_info['connectivity_status'],
GRPC\CHANNEL_IDLE);
$this->assertArrayHasKey($channel1_info['key'], $plist_info);
$this->assertEquals(count($plist_info), 1);
$this->channel1->close();
}
public function testPersistentChannelCreateMultipleChannels()
{
$this->channel1 = new Grpc\Channel('localhost:1', []);
$plist_info = $this->channel1->getPersistentList();
$this->assertEquals(count($plist_info), 1);
$this->channel2 = new Grpc\Channel('localhost:2', []);
$plist_info = $this->channel1->getPersistentList();
$this->assertEquals(count($plist_info), 2);
$this->channel3 = new Grpc\Channel('localhost:3', []);
$plist_info = $this->channel1->getPersistentList();
$this->assertEquals(count($plist_info), 3);
}
public function testPersistentChannelStatusChange()
{
$this->channel1 = new Grpc\Channel('localhost:4', []);
$channel1_info = $this->channel1->getChannelInfo();
$this->assertEquals($channel1_info['connectivity_status'],
GRPC\CHANNEL_IDLE);
$this->channel1->getConnectivityState(true);
$this->waitUntilNotIdle($this->channel1);
$channel1_info = $this->channel1->getChannelInfo();
$this->assertConnecting($channel1_info['connectivity_status']);
$this->channel1->close();
}
public function testPersistentChannelCloseChannel()
{
$this->channel1 = new Grpc\Channel('localhost:1', []);
$this->channel2 = new Grpc\Channel('localhost:1', []);
$channel1_info = $this->channel1->getChannelInfo();
$this->assertEquals($channel1_info['ref_count'], 3);
$plist_info = $this->channel1->getPersistentList();
$this->assertEquals($plist_info[$channel1_info['key']]['ref_count'], 3);
$this->channel1->close();
$plist_info = $this->channel1->getPersistentList();
$this->assertEquals($plist_info[$channel1_info['key']]['ref_count'], 2);
$this->channel2->close();
$plist_info = $this->channel1->getPersistentList();
$this->assertEquals($plist_info[$channel1_info['key']]['ref_count'], 1);
}
public function testPersistentChannelSameTarget()
{
$this->channel1 = new Grpc\Channel('localhost:1', []);
$this->channel2 = new Grpc\Channel('localhost:1', []);
$plist = $this->channel2->getPersistentList();
$channel1_info = $this->channel1->getChannelInfo();
$channel2_info = $this->channel2->getChannelInfo();
// $channel1 and $channel2 shares the same channel, thus only 1
// channel should be in the persistent list.
$this->assertEquals($channel1_info['key'], $channel2_info['key']);
$this->assertArrayHasKey($channel1_info['key'], $plist);
$this->assertEquals(count($plist), 1);
$this->channel1->close();
$this->channel2->close();
}
public function testPersistentChannelDifferentTarget()
{
$this->channel1 = new Grpc\Channel('localhost:1', []);
$channel1_info = $this->channel1->getChannelInfo();
$this->channel2 = new Grpc\Channel('localhost:2', []);
$channel2_info = $this->channel1->getChannelInfo();
$plist_info = $this->channel1->getPersistentList();
$this->assertArrayHasKey($channel1_info['key'], $plist_info);
$this->assertArrayHasKey($channel2_info['key'], $plist_info);
$this->assertEquals($plist_info[$channel1_info['key']]['ref_count'], 2);
$this->assertEquals($plist_info[$channel2_info['key']]['ref_count'], 2);
$plist_info = $this->channel1->getPersistentList();
$this->assertEquals(count($plist_info), 2);
$this->channel1->close();
$this->channel2->close();
}
public function testPersistentChannelSharedChannelClose()
{
$this->expectException(\RuntimeException::class);
$this->expectExceptionMessage("startBatch Error. Channel is closed");
// same underlying channel
$this->channel1 = new Grpc\Channel('localhost:10001', [
"grpc_target_persist_bound" => 2,
]);
$this->channel2 = new Grpc\Channel('localhost:10001', []);
$this->server = new Grpc\Server([]);
$this->port = $this->server->addHttp2Port('localhost:10001');
$this->server->start();
// channel2 can still be use
$state = $this->channel2->getConnectivityState();
$this->assertEquals(GRPC\CHANNEL_IDLE, $state);
$call1 = new Grpc\Call($this->channel1,
'/foo',
Grpc\Timeval::infFuture());
$call2 = new Grpc\Call($this->channel2,
'/foo',
Grpc\Timeval::infFuture());
$call3 = new Grpc\Call($this->channel1,
'/foo',
Grpc\Timeval::infFuture());
$call4 = new Grpc\Call($this->channel2,
'/foo',
Grpc\Timeval::infFuture());
$batch = [
Grpc\OP_SEND_INITIAL_METADATA => [],
];
$result = $call1->startBatch($batch);
$this->assertTrue($result->send_metadata);
$result = $call2->startBatch($batch);
$this->assertTrue($result->send_metadata);
$this->channel1->close();
// After closing channel1, channel2 can still be use
$result = $call4->startBatch($batch);
$this->assertTrue($result->send_metadata);
// channel 1 is closed, it will throw an exception.
$result = $call3->startBatch($batch);
}
public function testPersistentChannelTargetDefaultUpperBound()
{
$this->channel1 = new Grpc\Channel('localhost:10002', []);
$channel1_info = $this->channel1->getChannelInfo();
$this->assertEquals($channel1_info['target_upper_bound'], 1);
$this->assertEquals($channel1_info['target_current_size'], 1);
}
public function testPersistentChannelTargetUpperBoundZero()
{
$this->channel1 = new Grpc\Channel('localhost:10002', [
"grpc_target_persist_bound" => 0,
]);
// channel1 will not be persisted.
$channel1_info = $this->channel1->getChannelInfo();
$this->assertEquals($channel1_info['target_upper_bound'], 0);
$this->assertEquals($channel1_info['target_current_size'], 0);
$plist_info = $this->channel1->getPersistentList();
$this->assertEquals(0, count($plist_info));
}
public function testPersistentChannelTargetUpperBoundNotZero()
{
$this->channel1 = new Grpc\Channel('localhost:10003', [
"grpc_target_persist_bound" => 3,
]);
$channel1_info = $this->channel1->getChannelInfo();
$this->assertEquals($channel1_info['target_upper_bound'], 3);
$this->assertEquals($channel1_info['target_current_size'], 1);
// The upper bound should not be changed
$this->channel2 = new Grpc\Channel('localhost:10003', []);
$channel2_info = $this->channel2->getChannelInfo();
$this->assertEquals($channel2_info['target_upper_bound'], 3);
$this->assertEquals($channel2_info['target_current_size'], 1);
// The upper bound should not be changed
$channel_credentials = Grpc\ChannelCredentials::createSsl(null, null,
null);
$this->channel3 = new Grpc\Channel('localhost:10003',
['credentials' => $channel_credentials]);
$channel3_info = $this->channel3->getChannelInfo();
$this->assertEquals($channel3_info['target_upper_bound'], 3);
$this->assertEquals($channel3_info['target_current_size'], 2);
// The upper bound should not be changed
$this->channel4 = new Grpc\Channel('localhost:10003', [
"grpc_target_persist_bound" => 5,
]);
$channel4_info = $this->channel4->getChannelInfo();
$this->assertEquals($channel4_info['target_upper_bound'], 5);
$this->assertEquals($channel4_info['target_current_size'], 2);
}
public function testPersistentChannelDefaultOutBound1()
{
$this->channel1 = new Grpc\Channel('localhost:10004', []);
// Make channel1 not IDLE.
$this->channel1->getConnectivityState(true);
$this->waitUntilNotIdle($this->channel1);
$channel1_info = $this->channel1->getChannelInfo();
$this->assertConnecting($channel1_info['connectivity_status']);
// Since channel1 is CONNECTING, channel 2 will not be persisted
$channel_credentials = Grpc\ChannelCredentials::createSsl(null, null,
null);
$this->channel2 = new Grpc\Channel('localhost:10004',
['credentials' => $channel_credentials]);
$channel2_info = $this->channel2->getChannelInfo();
$this->assertEquals(GRPC\CHANNEL_IDLE, $channel2_info['connectivity_status']);
// By default, target 'localhost:10011' only persist one channel.
// Since channel1 is not Idle channel2 will not be persisted.
$plist_info = $this->channel1->getPersistentList();
$this->assertEquals(1, count($plist_info));
$this->assertArrayHasKey($channel1_info['key'], $plist_info);
$this->assertArrayNotHasKey($channel2_info['key'], $plist_info);
}
public function testPersistentChannelDefaultOutBound2()
{
$this->channel1 = new Grpc\Channel('localhost:10005', []);
$channel1_info = $this->channel1->getChannelInfo();
$this->assertEquals(GRPC\CHANNEL_IDLE, $channel1_info['connectivity_status']);
// Although channel1 is IDLE, channel1 still has reference to the underline
// gRPC channel. channel2 will not be persisted
$channel_credentials = Grpc\ChannelCredentials::createSsl(null, null,
null);
$this->channel2 = new Grpc\Channel('localhost:10005',
['credentials' => $channel_credentials]);
$channel2_info = $this->channel2->getChannelInfo();
$this->assertEquals(GRPC\CHANNEL_IDLE, $channel2_info['connectivity_status']);
// By default, target 'localhost:10011' only persist one channel.
// Since channel1 Idle, channel2 will be persisted.
$plist_info = $this->channel1->getPersistentList();
$this->assertEquals(1, count($plist_info));
$this->assertArrayHasKey($channel1_info['key'], $plist_info);
$this->assertArrayNotHasKey($channel2_info['key'], $plist_info);
}
public function testPersistentChannelDefaultOutBound3()
{
$this->channel1 = new Grpc\Channel('localhost:10006', []);
$channel1_info = $this->channel1->getChannelInfo();
$this->assertEquals(GRPC\CHANNEL_IDLE, $channel1_info['connectivity_status']);
$this->channel1->close();
// channel1 is closed, no reference holds to the underline channel.
// channel2 can be persisted.
$channel_credentials = Grpc\ChannelCredentials::createSsl(null, null,
null);
$this->channel2 = new Grpc\Channel('localhost:10006',
['credentials' => $channel_credentials]);
$channel2_info = $this->channel2->getChannelInfo();
$this->assertEquals(GRPC\CHANNEL_IDLE, $channel2_info['connectivity_status']);
// By default, target 'localhost:10011' only persist one channel.
// Since channel1 Idle, channel2 will be persisted.
$plist_info = $this->channel2->getPersistentList();
$this->assertEquals(1, count($plist_info));
$this->assertArrayHasKey($channel2_info['key'], $plist_info);
$this->assertArrayNotHasKey($channel1_info['key'], $plist_info);
}
public function testPersistentChannelTwoUpperBound()
{
$this->channel1 = new Grpc\Channel('localhost:10007', [
"grpc_target_persist_bound" => 2,
]);
$channel1_info = $this->channel1->getChannelInfo();
$this->assertEquals(GRPC\CHANNEL_IDLE, $channel1_info['connectivity_status']);
// Since channel1 is IDLE, channel 1 will be deleted
$channel_credentials = Grpc\ChannelCredentials::createSsl(null, null,
null);
$this->channel2 = new Grpc\Channel('localhost:10007',
['credentials' => $channel_credentials]);
$channel2_info = $this->channel2->getChannelInfo();
$this->assertEquals(GRPC\CHANNEL_IDLE, $channel2_info['connectivity_status']);
$plist_info = $this->channel1->getPersistentList();
$this->assertEquals(2, count($plist_info));
$this->assertArrayHasKey($channel1_info['key'], $plist_info);
$this->assertArrayHasKey($channel2_info['key'], $plist_info);
}
public function testPersistentChannelTwoUpperBoundOutBound1()
{
$this->channel1 = new Grpc\Channel('localhost:10011', [
"grpc_target_persist_bound" => 2,
]);
$channel1_info = $this->channel1->getChannelInfo();
$channel_credentials = Grpc\ChannelCredentials::createSsl(null, null,
null);
$this->channel2 = new Grpc\Channel('localhost:10011',
['credentials' => $channel_credentials]);
$channel2_info = $this->channel2->getChannelInfo();
// Close channel1, so that new channel can be persisted.
$this->channel1->close();
$channel_credentials = Grpc\ChannelCredentials::createSsl("a", null,
null);
$this->channel3 = new Grpc\Channel('localhost:10011',
['credentials' => $channel_credentials]);
$channel3_info = $this->channel3->getChannelInfo();
$plist_info = $this->channel1->getPersistentList();
$this->assertEquals(2, count($plist_info));
$this->assertArrayNotHasKey($channel1_info['key'], $plist_info);
$this->assertArrayHasKey($channel2_info['key'], $plist_info);
$this->assertArrayHasKey($channel3_info['key'], $plist_info);
}
public function testPersistentChannelTwoUpperBoundOutBound2()
{
$this->channel1 = new Grpc\Channel('localhost:10012', [
"grpc_target_persist_bound" => 2,
]);
$channel1_info = $this->channel1->getChannelInfo();
$channel_credentials = Grpc\ChannelCredentials::createSsl(null, null,
null);
$this->channel2 = new Grpc\Channel('localhost:10012',
['credentials' => $channel_credentials]);
$channel2_info = $this->channel2->getChannelInfo();
// Close channel2, so that new channel can be persisted.
$this->channel2->close();
$channel_credentials = Grpc\ChannelCredentials::createSsl("a", null,
null);
$this->channel3 = new Grpc\Channel('localhost:10012',
['credentials' => $channel_credentials]);
$channel3_info = $this->channel3->getChannelInfo();
$plist_info = $this->channel1->getPersistentList();
$this->assertEquals(2, count($plist_info));
$this->assertArrayHasKey($channel1_info['key'], $plist_info);
$this->assertArrayNotHasKey($channel2_info['key'], $plist_info);
$this->assertArrayHasKey($channel3_info['key'], $plist_info);
}
public function testPersistentChannelTwoUpperBoundOutBound3()
{
$this->channel1 = new Grpc\Channel('localhost:10013', [
"grpc_target_persist_bound" => 2,
]);
$channel1_info = $this->channel1->getChannelInfo();
$channel_credentials = Grpc\ChannelCredentials::createSsl(null, null,
null);
$this->channel2 = new Grpc\Channel('localhost:10013',
['credentials' => $channel_credentials]);
$this->channel2->getConnectivityState(true);
$this->waitUntilNotIdle($this->channel2);
$channel2_info = $this->channel2->getChannelInfo();
$this->assertConnecting($channel2_info['connectivity_status']);
// Only one channel will be deleted
$this->channel1->close();
$this->channel2->close();
$channel_credentials = Grpc\ChannelCredentials::createSsl("a", null,
null);
$this->channel3 = new Grpc\Channel('localhost:10013',
['credentials' => $channel_credentials]);
$channel3_info = $this->channel3->getChannelInfo();
// Only the Idle Channel will be deleted
$plist_info = $this->channel1->getPersistentList();
$this->assertEquals(2, count($plist_info));
$this->assertArrayNotHasKey($channel1_info['key'], $plist_info);
$this->assertArrayHasKey($channel2_info['key'], $plist_info);
$this->assertArrayHasKey($channel3_info['key'], $plist_info);
}
public function testPersistentChannelTwoUpperBoundOutBound4()
{
$this->channel1 = new Grpc\Channel('localhost:10014', [
"grpc_target_persist_bound" => 2,
]);
$this->channel1->getConnectivityState(true);
$this->waitUntilNotIdle($this->channel1);
$channel1_info = $this->channel1->getChannelInfo();
$this->assertConnecting($channel1_info['connectivity_status']);
$channel_credentials = Grpc\ChannelCredentials::createSsl(null, null,
null);
$this->channel2 = new Grpc\Channel('localhost:10014',
['credentials' => $channel_credentials]);
$this->channel2->getConnectivityState(true);
$this->waitUntilNotIdle($this->channel2);
$channel2_info = $this->channel2->getChannelInfo();
$this->assertConnecting($channel2_info['connectivity_status']);
$channel_credentials = Grpc\ChannelCredentials::createSsl("a", null,
null);
$this->channel3 = new Grpc\Channel('localhost:10014',
['credentials' => $channel_credentials]);
$channel3_info = $this->channel3->getChannelInfo();
// Channel3 will not be persisted
$plist_info = $this->channel1->getPersistentList();
$this->assertEquals(2, count($plist_info));
$this->assertArrayHasKey($channel1_info['key'], $plist_info);
$this->assertArrayHasKey($channel2_info['key'], $plist_info);
$this->assertArrayNotHasKey($channel3_info['key'], $plist_info);
}
}