| <?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. | |
| * | |
| */ | |
| require_once realpath(dirname(__FILE__).'/../../vendor/autoload.php'); | |
| // The following includes are needed when using protobuf 3.1.0 | |
| // and will suppress warnings when using protobuf 3.2.0+ | |
| @include_once dirname(__FILE__).'/math.pb.php'; | |
| @include_once dirname(__FILE__).'/math_grpc_pb.php'; | |
| abstract class AbstractGeneratedCodeTest extends \PHPUnit\Framework\TestCase | |
| { | |
| /** | |
| * These tests require that a server exporting the math service must be | |
| * running on $GRPC_TEST_HOST. | |
| */ | |
| protected static $client; | |
| protected static $clientOptions = array( | |
| 'grpc.service_config' => '{ | |
| "loadBalancingPolicy": "round_robin", | |
| "methodConfig": [ | |
| { | |
| "name": [ | |
| { | |
| "service": "math.Math" | |
| } | |
| ], | |
| "waitForReady": true, | |
| "retryPolicy": { | |
| "maxAttempts": 2, | |
| "initialBackoff": "0.2s", | |
| "maxBackoff": "4s", | |
| "backoffMultiplier": 2, | |
| "retryableStatusCodes": [ | |
| "UNAVAILABLE", | |
| "RESOURCE_EXHAUSTED", | |
| "DEADLINE_EXCEEDED" | |
| ] | |
| } | |
| } | |
| ] | |
| }', | |
| 'grpc.enable_retries' => 1, | |
| ); | |
| public function testWaitForNotReady() | |
| { | |
| $this->assertFalse(self::$client->waitForReady(1)); | |
| } | |
| public function testWaitForReady() | |
| { | |
| $this->assertTrue(self::$client->waitForReady(250000)); | |
| } | |
| public function testAlreadyReady() | |
| { | |
| $this->assertTrue(self::$client->waitForReady(250000)); | |
| $this->assertTrue(self::$client->waitForReady(100)); | |
| } | |
| public function testGetTarget() | |
| { | |
| $this->assertTrue(is_string(self::$client->getTarget())); | |
| } | |
| public function testClose() | |
| { | |
| $this->expectException(\InvalidArgumentException::class); | |
| self::$client->close(); | |
| $div_arg = new Math\DivArgs(); | |
| $call = self::$client->Div($div_arg); | |
| } | |
| public function testInvalidMetadata() | |
| { | |
| $this->expectException(\InvalidArgumentException::class); | |
| $div_arg = new Math\DivArgs(); | |
| $call = self::$client->Div($div_arg, [' ' => 'abc123']); | |
| } | |
| public function testMetadata() | |
| { | |
| $div_arg = new Math\DivArgs(); | |
| $div_arg->setDividend(7); | |
| $div_arg->setDivisor(4); | |
| $call = self::$client->Div($div_arg, ['somekey' => ['abc123']]); | |
| // $this->assertNotNull($call); | |
| list($response, $status) = $call->wait(); | |
| $this->assertSame(\Grpc\STATUS_OK, $status->code); | |
| } | |
| public function testMetadataKey() | |
| { | |
| $div_arg = new Math\DivArgs(); | |
| $div_arg->setDividend(7); | |
| $div_arg->setDivisor(4); | |
| $call = self::$client->Div($div_arg, ['somekey_-1' => ['abc123']]); | |
| list($response, $status) = $call->wait(); | |
| $this->assertSame(\Grpc\STATUS_OK, $status->code); | |
| } | |
| public function testMetadataKeyWithDot() | |
| { | |
| $div_arg = new Math\DivArgs(); | |
| $div_arg->setDividend(7); | |
| $div_arg->setDivisor(4); | |
| $call = self::$client->Div($div_arg, ['someKEY._-1' => ['abc123']]); | |
| list($response, $status) = $call->wait(); | |
| $this->assertSame(\Grpc\STATUS_OK, $status->code); | |
| } | |
| public function testMetadataInvalidKey() | |
| { | |
| $this->expectException(\InvalidArgumentException::class); | |
| $div_arg = new Math\DivArgs(); | |
| $call = self::$client->Div($div_arg, ['(somekey)' => ['abc123']]); | |
| } | |
| public function testGetCallMetadata() | |
| { | |
| $div_arg = new Math\DivArgs(); | |
| $call = self::$client->Div($div_arg); | |
| $this->assertTrue(is_array($call->getMetadata())); | |
| } | |
| public function testTimeout() | |
| { | |
| $div_arg = new Math\DivArgs(); | |
| $div_arg->setDividend(7); | |
| $div_arg->setDivisor(4); | |
| $call = self::$client->Div($div_arg, [], ['timeout' => 1]); | |
| list($response, $status) = $call->wait(); | |
| $this->assertSame(\Grpc\STATUS_DEADLINE_EXCEEDED, $status->code); | |
| } | |
| public function testCancel() | |
| { | |
| $div_arg = new Math\DivArgs(); | |
| $call = self::$client->Div($div_arg); | |
| $call->cancel(); | |
| list($response, $status) = $call->wait(); | |
| $this->assertSame(\Grpc\STATUS_CANCELLED, $status->code); | |
| } | |
| public function testRetry() | |
| { | |
| $metadata = [ | |
| 'response-unavailable' => [ | |
| 'server response STATUS_UNAVAILABLE so client will retry' | |
| ], | |
| ]; | |
| $div_arg = new Math\DivArgs(); | |
| $div_arg->setDividend(7); | |
| $div_arg->setDivisor(4); | |
| $call = self::$client->Div($div_arg, $metadata); | |
| list($response, $status) = $call->wait(); | |
| $this->assertSame(\Grpc\STATUS_UNAVAILABLE, $status->code); | |
| $this->assertSame('1', $status->metadata['unavailable-retry-attempts'][0]); | |
| } | |
| public function testCallCredentialsCallback() | |
| { | |
| $div_arg = new Math\DivArgs(); | |
| $div_arg->setDividend(7); | |
| $div_arg->setDivisor(4); | |
| $call = self::$client->Div($div_arg, array(), array( | |
| 'call_credentials_callback' => function ($context) { | |
| return array(); | |
| }, | |
| )); | |
| list($response, $status) = $call->wait(); | |
| $this->assertSame(\Grpc\STATUS_OK, $status->code); | |
| } | |
| public function testInsecureChannelCallCredentialsCallback() | |
| { | |
| $div_arg = new Math\DivArgs(); | |
| $div_arg->setDividend(7); | |
| $div_arg->setDivisor(4); | |
| $client = new Math\MathClient( | |
| getenv('GRPC_TEST_INSECURE_HOST'), [ | |
| 'credentials' => Grpc\ChannelCredentials::createInsecure(), | |
| ]); | |
| $call = $client->Div($div_arg, array(), array( | |
| 'call_credentials_callback' => function ($context) { | |
| return array(); | |
| }, | |
| )); | |
| list($response, $status) = $call->wait(); | |
| $this->assertSame(\Grpc\STATUS_OK, $status->code); | |
| } | |
| public function testInvalidMethodName() | |
| { | |
| $this->expectException(\InvalidArgumentException::class); | |
| $invalid_client = new PhonyInvalidClient('host', [ | |
| 'credentials' => Grpc\ChannelCredentials::createInsecure(), | |
| ]); | |
| $div_arg = new Math\DivArgs(); | |
| $invalid_client->InvalidUnaryCall($div_arg); | |
| } | |
| public function testMissingCredentials() | |
| { | |
| $this->expectException(\Exception::class); | |
| $this->expectExceptionMessage("The opts['credentials'] key is now required."); | |
| $invalid_client = new PhonyInvalidClient('host', [ | |
| ]); | |
| } | |
| public function testPrimaryUserAgentString() | |
| { | |
| $invalid_client = new PhonyInvalidClient('host', [ | |
| 'credentials' => Grpc\ChannelCredentials::createInsecure(), | |
| 'grpc.primary_user_agent' => 'testUserAgent', | |
| ]); | |
| $this->assertTrue(TRUE); // to avoid no assert warning | |
| } | |
| public function testWriteFlags() | |
| { | |
| $div_arg = new Math\DivArgs(); | |
| $div_arg->setDividend(7); | |
| $div_arg->setDivisor(4); | |
| $call = self::$client->Div($div_arg, [], | |
| ['flags' => Grpc\WRITE_NO_COMPRESS]); | |
| $this->assertTrue(is_string($call->getPeer())); | |
| list($response, $status) = $call->wait(); | |
| $this->assertSame(1, $response->getQuotient()); | |
| $this->assertSame(3, $response->getRemainder()); | |
| $this->assertSame(\Grpc\STATUS_OK, $status->code); | |
| } | |
| public function testWriteFlagsServerStreaming() | |
| { | |
| $fib_arg = new Math\FibArgs(); | |
| $fib_arg->setLimit(7); | |
| $call = self::$client->Fib($fib_arg, [], | |
| ['flags' => Grpc\WRITE_NO_COMPRESS]); | |
| $result_array = iterator_to_array($call->responses()); | |
| $status = $call->getStatus(); | |
| $this->assertSame(\Grpc\STATUS_OK, $status->code); | |
| } | |
| public function testWriteFlagsClientStreaming() | |
| { | |
| $call = self::$client->Sum(); | |
| $num = new Math\Num(); | |
| $num->setNum(1); | |
| $call->write($num, ['flags' => Grpc\WRITE_NO_COMPRESS]); | |
| list($response, $status) = $call->wait(); | |
| $this->assertSame(\Grpc\STATUS_OK, $status->code); | |
| } | |
| public function testWriteFlagsBidiStreaming() | |
| { | |
| $call = self::$client->DivMany(); | |
| $div_arg = new Math\DivArgs(); | |
| $div_arg->setDividend(7); | |
| $div_arg->setDivisor(4); | |
| $call->write($div_arg, ['flags' => Grpc\WRITE_NO_COMPRESS]); | |
| $response = $call->read(); | |
| $call->writesDone(); | |
| $status = $call->getStatus(); | |
| $this->assertSame(\Grpc\STATUS_OK, $status->code); | |
| } | |
| public function testSimpleRequest() | |
| { | |
| $div_arg = new Math\DivArgs(); | |
| $div_arg->setDividend(7); | |
| $div_arg->setDivisor(4); | |
| $call = self::$client->Div($div_arg); | |
| $this->assertTrue(is_string($call->getPeer())); | |
| list($response, $status) = $call->wait(); | |
| $this->assertSame(1, $response->getQuotient()); | |
| $this->assertSame(3, $response->getRemainder()); | |
| $this->assertSame(\Grpc\STATUS_OK, $status->code); | |
| } | |
| public function testServerStreaming() | |
| { | |
| $fib_arg = new Math\FibArgs(); | |
| $fib_arg->setLimit(7); | |
| $call = self::$client->Fib($fib_arg); | |
| $this->assertTrue(is_string($call->getPeer())); | |
| $result_array = iterator_to_array($call->responses()); | |
| $extract_num = function ($num) { | |
| return $num->getNum(); | |
| }; | |
| $values = array_map($extract_num, $result_array); | |
| $this->assertSame([1, 1, 2, 3, 5, 8, 13], $values); | |
| $status = $call->getStatus(); | |
| $this->assertSame(\Grpc\STATUS_OK, $status->code); | |
| } | |
| public function testClientStreaming() | |
| { | |
| $call = self::$client->Sum(); | |
| $this->assertTrue(is_string($call->getPeer())); | |
| for ($i = 0; $i < 7; ++$i) { | |
| $num = new Math\Num(); | |
| $num->setNum($i); | |
| $call->write($num); | |
| } | |
| list($response, $status) = $call->wait(); | |
| $this->assertSame(21, $response->getNum()); | |
| $this->assertSame(\Grpc\STATUS_OK, $status->code); | |
| } | |
| public function testBidiStreaming() | |
| { | |
| $call = self::$client->DivMany(); | |
| $this->assertTrue(is_string($call->getPeer())); | |
| for ($i = 0; $i < 7; ++$i) { | |
| $div_arg = new Math\DivArgs(); | |
| $div_arg->setDividend(2 * $i + 1); | |
| $div_arg->setDivisor(2); | |
| $call->write($div_arg); | |
| $response = $call->read(); | |
| $this->assertSame($i, $response->getQuotient()); | |
| $this->assertSame(1, $response->getRemainder()); | |
| } | |
| $call->writesDone(); | |
| $status = $call->getStatus(); | |
| $this->assertSame(\Grpc\STATUS_OK, $status->code); | |
| } | |
| public function testReuseCall() | |
| { | |
| $this->expectException(\LogicException::class); | |
| $this->expectExceptionMessage("start_batch was called incorrectly"); | |
| $div_arg = new Math\DivArgs(); | |
| $div_arg->setDividend(7); | |
| $div_arg->setDivisor(4); | |
| $call = self::$client->Div($div_arg, [], ['timeout' => 1000000]); | |
| list($response, $status) = $call->wait(); | |
| $this->assertSame(\Grpc\STATUS_OK, $status->code); | |
| list($response, $status) = $call->wait(); | |
| } | |
| } | |
| class PhonyInvalidClient extends \Grpc\BaseStub | |
| { | |
| public function InvalidUnaryCall(\Math\DivArgs $argument, | |
| $metadata = [], | |
| $options = []) | |
| { | |
| return $this->_simpleRequest('invalidMethodName', | |
| $argument, | |
| function () {}, | |
| $metadata, | |
| $options); | |
| } | |
| } |