Home | History | Annotate | Download | only in PersistentChannelTests
      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  */
     19 
     20 /**
     21  * @group persistent_list_bound_tests
     22  */
     23 class PersistentListTest extends PHPUnit_Framework_TestCase
     24 {
     25   public function setUp()
     26   {
     27   }
     28 
     29   public function tearDown()
     30   {
     31     $channel_clean_persistent =
     32         new Grpc\Channel('localhost:50010', []);
     33     $plist = $channel_clean_persistent->getPersistentList();
     34     $channel_clean_persistent->cleanPersistentList();
     35   }
     36 
     37   public function waitUntilNotIdle($channel) {
     38       for ($i = 0; $i < 10; $i++) {
     39           $now = Grpc\Timeval::now();
     40           $deadline = $now->add(new Grpc\Timeval(1000));
     41           if ($channel->watchConnectivityState(GRPC\CHANNEL_IDLE,
     42               $deadline)) {
     43               return true;
     44           }
     45       }
     46       $this->assertTrue(false);
     47   }
     48 
     49   public function assertConnecting($state) {
     50       $this->assertTrue($state == GRPC\CHANNEL_CONNECTING ||
     51       $state == GRPC\CHANNEL_TRANSIENT_FAILURE);
     52   }
     53 
     54   public function testInitHelper()
     55   {
     56       // PersistentList is not empty at the beginning of the tests
     57       // because phpunit will cache the channels created by other test
     58       // files.
     59   }
     60 
     61 
     62   public function testChannelNotPersist()
     63   {
     64       $this->channel1 = new Grpc\Channel('localhost:1', ['force_new' => true]);
     65       $channel1_info = $this->channel1->getChannelInfo();
     66       $plist_info = $this->channel1->getPersistentList();
     67       $this->assertEquals($channel1_info['target'], 'localhost:1');
     68       $this->assertEquals($channel1_info['ref_count'], 1);
     69       $this->assertEquals($channel1_info['connectivity_status'],
     70           GRPC\CHANNEL_IDLE);
     71       $this->assertEquals(count($plist_info), 0);
     72       $this->channel1->close();
     73   }
     74 
     75   public function testPersistentChannelCreateOneChannel()
     76   {
     77       $this->channel1 = new Grpc\Channel('localhost:1', []);
     78       $channel1_info = $this->channel1->getChannelInfo();
     79       $plist_info = $this->channel1->getPersistentList();
     80       $this->assertEquals($channel1_info['target'], 'localhost:1');
     81       $this->assertEquals($channel1_info['ref_count'], 2);
     82       $this->assertEquals($channel1_info['connectivity_status'],
     83                           GRPC\CHANNEL_IDLE);
     84       $this->assertArrayHasKey($channel1_info['key'], $plist_info);
     85       $this->assertEquals(count($plist_info), 1);
     86       $this->channel1->close();
     87   }
     88 
     89   public function testPersistentChannelCreateMultipleChannels()
     90   {
     91       $this->channel1 = new Grpc\Channel('localhost:1', []);
     92       $plist_info = $this->channel1->getPersistentList();
     93       $this->assertEquals(count($plist_info), 1);
     94 
     95       $this->channel2 = new Grpc\Channel('localhost:2', []);
     96       $plist_info = $this->channel1->getPersistentList();
     97       $this->assertEquals(count($plist_info), 2);
     98 
     99       $this->channel3 = new Grpc\Channel('localhost:3', []);
    100       $plist_info = $this->channel1->getPersistentList();
    101       $this->assertEquals(count($plist_info), 3);
    102   }
    103 
    104   public function testPersistentChannelStatusChange()
    105   {
    106       $this->channel1 = new Grpc\Channel('localhost:4', []);
    107       $channel1_info = $this->channel1->getChannelInfo();
    108       $this->assertEquals($channel1_info['connectivity_status'],
    109                           GRPC\CHANNEL_IDLE);
    110 
    111       $this->channel1->getConnectivityState(true);
    112       $this->waitUntilNotIdle($this->channel1);
    113       $channel1_info = $this->channel1->getChannelInfo();
    114       $this->assertConnecting($channel1_info['connectivity_status']);
    115       $this->channel1->close();
    116   }
    117 
    118   public function testPersistentChannelCloseChannel()
    119   {
    120       $this->channel1 = new Grpc\Channel('localhost:1', []);
    121       $this->channel2 = new Grpc\Channel('localhost:1', []);
    122 
    123       $channel1_info = $this->channel1->getChannelInfo();
    124       $this->assertEquals($channel1_info['ref_count'], 3);
    125       $plist_info = $this->channel1->getPersistentList();
    126       $this->assertEquals($plist_info[$channel1_info['key']]['ref_count'], 3);
    127 
    128       $this->channel1->close();
    129       $plist_info = $this->channel1->getPersistentList();
    130       $this->assertEquals($plist_info[$channel1_info['key']]['ref_count'], 2);
    131 
    132       $this->channel2->close();
    133       $plist_info = $this->channel1->getPersistentList();
    134       $this->assertEquals($plist_info[$channel1_info['key']]['ref_count'], 1);
    135   }
    136 
    137   public function testPersistentChannelSameTarget()
    138   {
    139       $this->channel1 = new Grpc\Channel('localhost:1', []);
    140       $this->channel2 = new Grpc\Channel('localhost:1', []);
    141       $plist = $this->channel2->getPersistentList();
    142       $channel1_info = $this->channel1->getChannelInfo();
    143       $channel2_info = $this->channel2->getChannelInfo();
    144       // $channel1 and $channel2 shares the same channel, thus only 1
    145       // channel should be in the persistent list.
    146       $this->assertEquals($channel1_info['key'], $channel2_info['key']);
    147       $this->assertArrayHasKey($channel1_info['key'], $plist);
    148       $this->assertEquals(count($plist), 1);
    149       $this->channel1->close();
    150       $this->channel2->close();
    151   }
    152 
    153   public function testPersistentChannelDifferentTarget()
    154   {
    155       $this->channel1 = new Grpc\Channel('localhost:1', []);
    156       $channel1_info = $this->channel1->getChannelInfo();
    157       $this->channel2 = new Grpc\Channel('localhost:2', []);
    158       $channel2_info = $this->channel1->getChannelInfo();
    159       $plist_info = $this->channel1->getPersistentList();
    160       $this->assertArrayHasKey($channel1_info['key'], $plist_info);
    161       $this->assertArrayHasKey($channel2_info['key'], $plist_info);
    162       $this->assertEquals($plist_info[$channel1_info['key']]['ref_count'], 2);
    163       $this->assertEquals($plist_info[$channel2_info['key']]['ref_count'], 2);
    164       $plist_info = $this->channel1->getPersistentList();
    165       $this->assertEquals(count($plist_info), 2);
    166       $this->channel1->close();
    167       $this->channel2->close();
    168   }
    169 
    170   /**
    171    * @expectedException RuntimeException
    172    * @expectedExceptionMessage startBatch Error. Channel is closed
    173    */
    174   public function testPersistentChannelSharedChannelClose()
    175   {
    176       // same underlying channel
    177       $this->channel1 = new Grpc\Channel('localhost:10001', [
    178           "grpc_target_persist_bound" => 2,
    179       ]);
    180       $this->channel2 = new Grpc\Channel('localhost:10001', []);
    181       $this->server = new Grpc\Server([]);
    182       $this->port = $this->server->addHttp2Port('localhost:10001');
    183 
    184       // channel2 can still be use
    185       $state = $this->channel2->getConnectivityState();
    186       $this->assertEquals(GRPC\CHANNEL_IDLE, $state);
    187 
    188       $call1 = new Grpc\Call($this->channel1,
    189           '/foo',
    190           Grpc\Timeval::infFuture());
    191       $call2 = new Grpc\Call($this->channel2,
    192           '/foo',
    193           Grpc\Timeval::infFuture());
    194       $call3 = new Grpc\Call($this->channel1,
    195           '/foo',
    196           Grpc\Timeval::infFuture());
    197       $call4 = new Grpc\Call($this->channel2,
    198           '/foo',
    199           Grpc\Timeval::infFuture());
    200       $batch = [
    201           Grpc\OP_SEND_INITIAL_METADATA => [],
    202       ];
    203 
    204       $result = $call1->startBatch($batch);
    205       $this->assertTrue($result->send_metadata);
    206       $result = $call2->startBatch($batch);
    207       $this->assertTrue($result->send_metadata);
    208 
    209       $this->channel1->close();
    210       // After closing channel1, channel2 can still be use
    211       $result = $call4->startBatch($batch);
    212       $this->assertTrue($result->send_metadata);
    213       // channel 1 is closed, it will throw an exception.
    214       $result = $call3->startBatch($batch);
    215   }
    216 
    217   public function testPersistentChannelTargetDefaultUpperBound()
    218   {
    219       $this->channel1 = new Grpc\Channel('localhost:10002', []);
    220       $channel1_info = $this->channel1->getChannelInfo();
    221       $this->assertEquals($channel1_info['target_upper_bound'], 1);
    222       $this->assertEquals($channel1_info['target_current_size'], 1);
    223   }
    224 
    225   public function testPersistentChannelTargetUpperBoundZero()
    226   {
    227       $this->channel1 = new Grpc\Channel('localhost:10002', [
    228           "grpc_target_persist_bound" => 0,
    229       ]);
    230       // channel1 will not be persisted.
    231       $channel1_info = $this->channel1->getChannelInfo();
    232       $this->assertEquals($channel1_info['target_upper_bound'], 0);
    233       $this->assertEquals($channel1_info['target_current_size'], 0);
    234       $plist_info = $this->channel1->getPersistentList();
    235       $this->assertEquals(0, count($plist_info));
    236   }
    237 
    238   public function testPersistentChannelTargetUpperBoundNotZero()
    239   {
    240       $this->channel1 = new Grpc\Channel('localhost:10003', [
    241           "grpc_target_persist_bound" => 3,
    242       ]);
    243       $channel1_info = $this->channel1->getChannelInfo();
    244       $this->assertEquals($channel1_info['target_upper_bound'], 3);
    245       $this->assertEquals($channel1_info['target_current_size'], 1);
    246 
    247       // The upper bound should not be changed
    248       $this->channel2 = new Grpc\Channel('localhost:10003', []);
    249       $channel2_info = $this->channel2->getChannelInfo();
    250       $this->assertEquals($channel2_info['target_upper_bound'], 3);
    251       $this->assertEquals($channel2_info['target_current_size'], 1);
    252 
    253       // The upper bound should not be changed
    254       $channel_credentials = Grpc\ChannelCredentials::createSsl(null, null,
    255           null);
    256       $this->channel3 = new Grpc\Channel('localhost:10003',
    257           ['credentials' => $channel_credentials]);
    258       $channel3_info = $this->channel3->getChannelInfo();
    259       $this->assertEquals($channel3_info['target_upper_bound'], 3);
    260       $this->assertEquals($channel3_info['target_current_size'], 2);
    261 
    262       // The upper bound should not be changed
    263       $this->channel4 = new Grpc\Channel('localhost:10003', [
    264           "grpc_target_persist_bound" => 5,
    265       ]);
    266       $channel4_info = $this->channel4->getChannelInfo();
    267       $this->assertEquals($channel4_info['target_upper_bound'], 5);
    268       $this->assertEquals($channel4_info['target_current_size'], 2);
    269   }
    270 
    271   public function testPersistentChannelDefaultOutBound1()
    272   {
    273       $this->channel1 = new Grpc\Channel('localhost:10004', []);
    274       // Make channel1 not IDLE.
    275       $this->channel1->getConnectivityState(true);
    276       $this->waitUntilNotIdle($this->channel1);
    277       $channel1_info = $this->channel1->getChannelInfo();
    278       $this->assertConnecting($channel1_info['connectivity_status']);
    279 
    280       // Since channel1 is CONNECTING, channel 2 will not be persisted
    281       $channel_credentials = Grpc\ChannelCredentials::createSsl(null, null,
    282         null);
    283       $this->channel2 = new Grpc\Channel('localhost:10004',
    284           ['credentials' => $channel_credentials]);
    285       $channel2_info = $this->channel2->getChannelInfo();
    286       $this->assertEquals(GRPC\CHANNEL_IDLE, $channel2_info['connectivity_status']);
    287 
    288       // By default, target 'localhost:10011' only persist one channel.
    289       // Since channel1 is not Idle channel2 will not be persisted.
    290       $plist_info = $this->channel1->getPersistentList();
    291       $this->assertEquals(1, count($plist_info));
    292       $this->assertArrayHasKey($channel1_info['key'], $plist_info);
    293       $this->assertArrayNotHasKey($channel2_info['key'], $plist_info);
    294   }
    295 
    296   public function testPersistentChannelDefaultOutBound2()
    297   {
    298       $this->channel1 = new Grpc\Channel('localhost:10005', []);
    299       $channel1_info = $this->channel1->getChannelInfo();
    300       $this->assertEquals(GRPC\CHANNEL_IDLE, $channel1_info['connectivity_status']);
    301 
    302       // Although channel1 is IDLE, channel1 still has reference to the underline
    303       // gRPC channel. channel2 will not be persisted
    304       $channel_credentials = Grpc\ChannelCredentials::createSsl(null, null,
    305         null);
    306       $this->channel2 = new Grpc\Channel('localhost:10005',
    307           ['credentials' => $channel_credentials]);
    308       $channel2_info = $this->channel2->getChannelInfo();
    309       $this->assertEquals(GRPC\CHANNEL_IDLE, $channel2_info['connectivity_status']);
    310 
    311       // By default, target 'localhost:10011' only persist one channel.
    312       // Since channel1 Idle, channel2 will be persisted.
    313       $plist_info = $this->channel1->getPersistentList();
    314       $this->assertEquals(1, count($plist_info));
    315       $this->assertArrayHasKey($channel1_info['key'], $plist_info);
    316       $this->assertArrayNotHasKey($channel2_info['key'], $plist_info);
    317   }
    318 
    319   public function testPersistentChannelDefaultOutBound3()
    320   {
    321       $this->channel1 = new Grpc\Channel('localhost:10006', []);
    322       $channel1_info = $this->channel1->getChannelInfo();
    323       $this->assertEquals(GRPC\CHANNEL_IDLE, $channel1_info['connectivity_status']);
    324 
    325       $this->channel1->close();
    326       // channel1 is closed, no reference holds to the underline channel.
    327       // channel2 can be persisted.
    328       $channel_credentials = Grpc\ChannelCredentials::createSsl(null, null,
    329         null);
    330       $this->channel2 = new Grpc\Channel('localhost:10006',
    331         ['credentials' => $channel_credentials]);
    332       $channel2_info = $this->channel2->getChannelInfo();
    333       $this->assertEquals(GRPC\CHANNEL_IDLE, $channel2_info['connectivity_status']);
    334 
    335       // By default, target 'localhost:10011' only persist one channel.
    336       // Since channel1 Idle, channel2 will be persisted.
    337       $plist_info = $this->channel2->getPersistentList();
    338       $this->assertEquals(1, count($plist_info));
    339       $this->assertArrayHasKey($channel2_info['key'], $plist_info);
    340       $this->assertArrayNotHasKey($channel1_info['key'], $plist_info);
    341   }
    342 
    343   public function testPersistentChannelTwoUpperBound()
    344   {
    345       $this->channel1 = new Grpc\Channel('localhost:10007', [
    346           "grpc_target_persist_bound" => 2,
    347       ]);
    348       $channel1_info = $this->channel1->getChannelInfo();
    349       $this->assertEquals(GRPC\CHANNEL_IDLE, $channel1_info['connectivity_status']);
    350 
    351       // Since channel1 is IDLE, channel 1 will be deleted
    352       $channel_credentials = Grpc\ChannelCredentials::createSsl(null, null,
    353           null);
    354       $this->channel2 = new Grpc\Channel('localhost:10007',
    355           ['credentials' => $channel_credentials]);
    356       $channel2_info = $this->channel2->getChannelInfo();
    357       $this->assertEquals(GRPC\CHANNEL_IDLE, $channel2_info['connectivity_status']);
    358 
    359       $plist_info = $this->channel1->getPersistentList();
    360       $this->assertEquals(2, count($plist_info));
    361       $this->assertArrayHasKey($channel1_info['key'], $plist_info);
    362       $this->assertArrayHasKey($channel2_info['key'], $plist_info);
    363   }
    364 
    365   public function testPersistentChannelTwoUpperBoundOutBound1()
    366   {
    367       $this->channel1 = new Grpc\Channel('localhost:10011', [
    368           "grpc_target_persist_bound" => 2,
    369       ]);
    370       $channel1_info = $this->channel1->getChannelInfo();
    371 
    372       $channel_credentials = Grpc\ChannelCredentials::createSsl(null, null,
    373         null);
    374       $this->channel2 = new Grpc\Channel('localhost:10011',
    375           ['credentials' => $channel_credentials]);
    376       $channel2_info = $this->channel2->getChannelInfo();
    377 
    378       // Close channel1, so that new channel can be persisted.
    379       $this->channel1->close();
    380 
    381       $channel_credentials = Grpc\ChannelCredentials::createSsl("a", null,
    382         null);
    383       $this->channel3 = new Grpc\Channel('localhost:10011',
    384           ['credentials' => $channel_credentials]);
    385       $channel3_info = $this->channel3->getChannelInfo();
    386 
    387       $plist_info = $this->channel1->getPersistentList();
    388       $this->assertEquals(2, count($plist_info));
    389       $this->assertArrayNotHasKey($channel1_info['key'], $plist_info);
    390       $this->assertArrayHasKey($channel2_info['key'], $plist_info);
    391       $this->assertArrayHasKey($channel3_info['key'], $plist_info);
    392   }
    393 
    394   public function testPersistentChannelTwoUpperBoundOutBound2()
    395   {
    396       $this->channel1 = new Grpc\Channel('localhost:10012', [
    397           "grpc_target_persist_bound" => 2,
    398       ]);
    399       $channel1_info = $this->channel1->getChannelInfo();
    400 
    401       $channel_credentials = Grpc\ChannelCredentials::createSsl(null, null,
    402         null);
    403       $this->channel2 = new Grpc\Channel('localhost:10012',
    404         ['credentials' => $channel_credentials]);
    405       $channel2_info = $this->channel2->getChannelInfo();
    406 
    407       // Close channel2, so that new channel can be persisted.
    408       $this->channel2->close();
    409 
    410       $channel_credentials = Grpc\ChannelCredentials::createSsl("a", null,
    411         null);
    412       $this->channel3 = new Grpc\Channel('localhost:10012',
    413         ['credentials' => $channel_credentials]);
    414       $channel3_info = $this->channel3->getChannelInfo();
    415 
    416       $plist_info = $this->channel1->getPersistentList();
    417       $this->assertEquals(2, count($plist_info));
    418       $this->assertArrayHasKey($channel1_info['key'], $plist_info);
    419       $this->assertArrayNotHasKey($channel2_info['key'], $plist_info);
    420       $this->assertArrayHasKey($channel3_info['key'], $plist_info);
    421   }
    422 
    423   public function testPersistentChannelTwoUpperBoundOutBound3()
    424   {
    425       $this->channel1 = new Grpc\Channel('localhost:10013', [
    426           "grpc_target_persist_bound" => 2,
    427       ]);
    428       $channel1_info = $this->channel1->getChannelInfo();
    429 
    430       $channel_credentials = Grpc\ChannelCredentials::createSsl(null, null,
    431           null);
    432       $this->channel2 = new Grpc\Channel('localhost:10013',
    433           ['credentials' => $channel_credentials]);
    434       $this->channel2->getConnectivityState(true);
    435       $this->waitUntilNotIdle($this->channel2);
    436       $channel2_info = $this->channel2->getChannelInfo();
    437       $this->assertConnecting($channel2_info['connectivity_status']);
    438 
    439       // Only one channel will be deleted
    440       $this->channel1->close();
    441       $this->channel2->close();
    442 
    443       $channel_credentials = Grpc\ChannelCredentials::createSsl("a", null,
    444         null);
    445       $this->channel3 = new Grpc\Channel('localhost:10013',
    446           ['credentials' => $channel_credentials]);
    447       $channel3_info = $this->channel3->getChannelInfo();
    448 
    449       // Only the Idle Channel will be deleted
    450       $plist_info = $this->channel1->getPersistentList();
    451       $this->assertEquals(2, count($plist_info));
    452       $this->assertArrayNotHasKey($channel1_info['key'], $plist_info);
    453       $this->assertArrayHasKey($channel2_info['key'], $plist_info);
    454       $this->assertArrayHasKey($channel3_info['key'], $plist_info);
    455   }
    456 
    457   public function testPersistentChannelTwoUpperBoundOutBound4()
    458   {
    459       $this->channel1 = new Grpc\Channel('localhost:10014', [
    460           "grpc_target_persist_bound" => 2,
    461       ]);
    462       $this->channel1->getConnectivityState(true);
    463       $this->waitUntilNotIdle($this->channel1);
    464       $channel1_info = $this->channel1->getChannelInfo();
    465       $this->assertConnecting($channel1_info['connectivity_status']);
    466 
    467       $channel_credentials = Grpc\ChannelCredentials::createSsl(null, null,
    468           null);
    469       $this->channel2 = new Grpc\Channel('localhost:10014',
    470           ['credentials' => $channel_credentials]);
    471       $this->channel2->getConnectivityState(true);
    472       $this->waitUntilNotIdle($this->channel2);
    473       $channel2_info = $this->channel2->getChannelInfo();
    474       $this->assertConnecting($channel2_info['connectivity_status']);
    475 
    476       $channel_credentials = Grpc\ChannelCredentials::createSsl("a", null,
    477           null);
    478       $this->channel3 = new Grpc\Channel('localhost:10014',
    479           ['credentials' => $channel_credentials]);
    480       $channel3_info = $this->channel3->getChannelInfo();
    481 
    482       // Channel3 will not be persisted
    483       $plist_info = $this->channel1->getPersistentList();
    484       $this->assertEquals(2, count($plist_info));
    485       $this->assertArrayHasKey($channel1_info['key'], $plist_info);
    486       $this->assertArrayHasKey($channel2_info['key'], $plist_info);
    487       $this->assertArrayNotHasKey($channel3_info['key'], $plist_info);
    488   }
    489 }
    490