diff --git a/.gitattributes b/.gitattributes
index 0acb7092c..f37a3882a 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -1,8 +1,5 @@
.gitattributes export-ignore
.gitignore export-ignore
.github export-ignore
-dev export-ignore
tests export-ignore
-codecov.yml export-ignore
-ruleset.xml export-ignore
-.travis.yml export-ignore
+/*.dist export-ignore
diff --git a/README.md b/README.md
index 6a6c01760..19f92ec0d 100644
--- a/README.md
+++ b/README.md
@@ -73,21 +73,13 @@ be found for Mac or Windows.
3. Run tests.
```sh
- > composer test
+ > vendor/bin/phpunit
```
-4. Updating dependencies after changing `composer.json`:
+4. Run static analysis tools
```sh
- > composer update
- `
- ```
-
-5. Formatting source:
-
- ```sh
- > composer cs-lint
- > composer cs-fix
+ > phpstan -c phpstan.neon.dist
```
## License
diff --git a/codecov.yml b/codecov.yml
deleted file mode 100644
index 972f1e6bd..000000000
--- a/codecov.yml
+++ /dev/null
@@ -1,3 +0,0 @@
-ignore:
- - "metadata"
- - "src/Testing"
diff --git a/composer.json b/composer.json
index 9d46994c8..48cdbfc22 100644
--- a/composer.json
+++ b/composer.json
@@ -34,17 +34,9 @@
},
"autoload-dev": {
"psr-4": {
- "Google\\ApiCore\\Dev\\": "dev/src",
"Google\\ApiCore\\Tests\\": "tests",
- "GPBMetadata\\Google\\": "metadata/Google",
"Google\\Showcase\\": "tests/Conformance/src",
"GPBMetadata\\Google\\Showcase\\": "tests/Conformance/metadata"
}
- },
- "scripts": {
- "regenerate-test-protos": "dev/sh/regenerate-test-protos.sh",
- "test": "./vendor/bin/phpunit",
- "cs-lint": "vendor/bin/php-tools cs-fixer googleapis/gax-php --ref $(git rev-parse --abbrev-ref HEAD) --flags \"\\-n --dry-run\"",
- "cs-fix": "vendor/bin/php-tools cs-fixer googleapis/gax-php --ref $(git rev-parse --abbrev-ref HEAD) --flags \"\\-n\""
}
}
diff --git a/dev/sh/build-protobuf-docs.sh b/dev/sh/build-protobuf-docs.sh
deleted file mode 100644
index 1e0213024..000000000
--- a/dev/sh/build-protobuf-docs.sh
+++ /dev/null
@@ -1,57 +0,0 @@
-#!/bin/bash
-
-# Script to build docs for PHP Protobuf. To be run locally and submitted
-# manually when an update is desired.
-# The Protobuf team does not maintain the reference documentation for PHP at
-# this time and rely on the Core Client Libraries team to do so.
-# Docs are deployed to developers.google.com, but soon will be deployed to
-# protobuf.dev.
-# @see https://developers.google.com/protocol-buffers/docs/reference/overview
-
-# This script expects to be invoked from the gax-php root. It requires a git tag
-# of a valid protobuf-php releas eas the first argument.
-# @see https://github.com/protocolbuffers/protobuf-php/tags
-
-# Once ran, copy the "api-docs" directory to the protocolbuffers.github.io repo:
-# https://github.com/protocolbuffers/protocolbuffers.github.io/tree/main/content/reference/php/api-docs
-
-set -ev
-
-if [ "$#" -ne 1 ]; then
- echo "Usage: $0 TAG"
- exit 1
-fi
-GIT_TAG_NAME=$1
-ROOT_DIR=$(pwd)
-DOC_OUTPUT_DIR=${ROOT_DIR}/api-docs
-DOCTUM_EXECUTABLE=${ROOT_DIR}/doctum.phar
-
-function downloadDoctum() {
- # Download the latest (5.1.x) release
- # You can fetch the latest (5.1.x) version code here:
- # https://doctum.long-term.support/releases/5.1/VERSION
- rm -f "${DOCTUM_EXECUTABLE}"
- rm -f "${DOCTUM_EXECUTABLE}.sha256"
- curl -# https://doctum.long-term.support/releases/5.5/doctum.phar -o "${DOCTUM_EXECUTABLE}"
- curl -# https://doctum.long-term.support/releases/5.5/doctum.phar.sha256 -o "${DOCTUM_EXECUTABLE}.sha256"
- sha256sum --strict --check "${DOCTUM_EXECUTABLE}.sha256"
- rm -f "${DOCTUM_EXECUTABLE}.sha256"
-}
-
-function buildDocs() {
- DOCTUM_CONFIG=${ROOT_DIR}/dev/src/Docs/doctum-protobuf-config.php
- PROTOBUF_DOCS_VERSION=${GIT_TAG_NAME} php ${DOCTUM_EXECUTABLE} update ${DOCTUM_CONFIG} -v
-}
-# ensure we have the correct version of protobuf
-composer update google/protobuf:$GIT_TAG_NAME
-# download doctum.phar
-downloadDoctum
-# build the docs
-buildDocs ${GIT_TAG_NAME}
-
-# Construct the base index file to redirect to the Protobuf namespace
-UPDATED_INDEX_FILE=$(cat << EndOfMessage
-
-EndOfMessage
-)
-echo ${UPDATED_INDEX_FILE} > ${DOC_OUTPUT_DIR}/index.html
diff --git a/dev/sh/regenerate-test-protos.sh b/dev/sh/regenerate-test-protos.sh
deleted file mode 100755
index b22338f88..000000000
--- a/dev/sh/regenerate-test-protos.sh
+++ /dev/null
@@ -1,15 +0,0 @@
-#!/bin/bash
-
-# Run this script whenever changes are made to mocks.proto to regenerate the
-# PHP protobuf message classes.
-#
-# This script expected to be invoked from the gax-php root using:
-# $ composer regenerate-test-protos
-
-echo ${pwd}
-cd src
-protoc --php_out . ./Testing/mocks.proto
-cp -r ./GPBMetadata/* ../metadata/
-cp -r ./Google/ApiCore/* ./
-rm -r ./GPBMetadata
-rm -r ./Google
diff --git a/dev/sh/test-composer-conflict.sh b/dev/sh/test-composer-conflict.sh
deleted file mode 100755
index b4f5434f4..000000000
--- a/dev/sh/test-composer-conflict.sh
+++ /dev/null
@@ -1,14 +0,0 @@
-#!/bin/bash
-
-# Try to run `composer install`, with the expectation that it will FAIL!
-# This is to test that the 'conflict' clause of the composer.json file
-# is correctly blocking installation when an incompatible protobuf
-# extension is present.
-
-if composer install ; then
- echo "Expected 'composer install' to fail, but it succeeded!"
- exit 1
-else
- echo "'composer install' failed, as expected"
-fi
-
diff --git a/dev/src/Docs/doctum-protobuf-config.php b/dev/src/Docs/doctum-protobuf-config.php
deleted file mode 100644
index e0efa81bd..000000000
--- a/dev/src/Docs/doctum-protobuf-config.php
+++ /dev/null
@@ -1,59 +0,0 @@
-= 7.1 to build docs, found version ' . phpversion());
-}
-
-$version = getenv('PROTOBUF_DOCS_VERSION');
-
-$gaxRootDir = realpath(__DIR__ . '/../../../');
-$protobufRootDir = realpath($gaxRootDir . '/vendor/google/protobuf');
-$iterator = Finder::create()
- ->files()
- ->name('*.php')
- ->exclude('GPBMetadata')
- ->in("$protobufRootDir/src")
-;
-
-return new Doctum($iterator, [
- 'title' => "Google Protobuf - $version",
- 'version' => $version,
- 'build_dir' => "$gaxRootDir/api-docs",
- 'cache_dir' => "$gaxRootDir/cache/%version%",
- 'remote_repository' => new GitHubRemoteRepository('protocolbuffers/protobuf-php', $protobufRootDir),
- 'default_opened_level' => 1,
-]);
diff --git a/metadata/ApiCore/Testing/Mocks.php b/metadata/ApiCore/Testing/Mocks.php
index 5dcb11f0c..924dae47f 100644
Binary files a/metadata/ApiCore/Testing/Mocks.php and b/metadata/ApiCore/Testing/Mocks.php differ
diff --git a/phpunit.xml.dist b/phpunit.xml.dist
index 825f7f706..4a40d8366 100644
--- a/phpunit.xml.dist
+++ b/phpunit.xml.dist
@@ -1,8 +1,5 @@
-
-
-
src/ApiCore
diff --git a/src/ClientOptionsTrait.php b/src/ClientOptionsTrait.php
index 5def36e9e..f5fbafdd4 100644
--- a/src/ClientOptionsTrait.php
+++ b/src/ClientOptionsTrait.php
@@ -152,8 +152,7 @@ private function buildClientOptions(array|ClientOptions $options)
$options['logger'] = ApplicationDefaultCredentials::getDefaultLogger();
}
- if (
- $options['logger'] !== null
+ if ($options['logger'] !== null
&& $options['logger'] !== false
&& !$options['logger'] instanceof LoggerInterface
) {
diff --git a/src/OperationResponse.php b/src/OperationResponse.php
index 8e58c810e..9dfeb0a73 100644
--- a/src/OperationResponse.php
+++ b/src/OperationResponse.php
@@ -101,7 +101,7 @@ class OperationResponse
* OperationResponse constructor.
*
* @param string $operationName
- * @param object $operationsClient
+ * @param object|null $operationsClient
* @param array $options {
* Optional. Options for configuring the operation response object.
*
diff --git a/src/ResourceTemplate/AbsoluteResourceTemplate.php b/src/ResourceTemplate/AbsoluteResourceTemplate.php
index e6cb49231..7f2425f2e 100644
--- a/src/ResourceTemplate/AbsoluteResourceTemplate.php
+++ b/src/ResourceTemplate/AbsoluteResourceTemplate.php
@@ -54,7 +54,7 @@
class AbsoluteResourceTemplate implements ResourceTemplateInterface
{
private RelativeResourceTemplate $resourceTemplate;
- /** @var string|bool */
+ /** @var string */
private $verb;
/**
diff --git a/src/ResourceTemplate/Segment.php b/src/ResourceTemplate/Segment.php
index fb9dc6d43..cee08f015 100644
--- a/src/ResourceTemplate/Segment.php
+++ b/src/ResourceTemplate/Segment.php
@@ -51,8 +51,8 @@ class Segment
private ?string $value;
private ?string $key;
private ?RelativeResourceTemplate $template;
- private ?string $stringRepr;
- private ?string $separator;
+ private string $stringRepr;
+ private string $separator;
/**
* Segment constructor.
diff --git a/src/Serializer.php b/src/Serializer.php
index 1af6764dd..b9e1aa1de 100644
--- a/src/Serializer.php
+++ b/src/Serializer.php
@@ -37,6 +37,17 @@
use Google\Protobuf\DescriptorPool;
use Google\Protobuf\FieldDescriptor;
use Google\Protobuf\Internal\Message;
+use Google\Rpc\BadRequest;
+use Google\Rpc\DebugInfo;
+use Google\Rpc\ErrorInfo;
+use Google\Rpc\Help;
+use Google\Rpc\LocalizedMessage;
+use Google\Rpc\PreconditionFailure;
+use Google\Rpc\QuotaFailure;
+use Google\Rpc\RequestInfo;
+use Google\Rpc\ResourceInfo;
+use Google\Rpc\RetryInfo;
+use Google\Rpc\Status;
use RuntimeException;
/**
@@ -180,7 +191,7 @@ public static function decodeMetadata(array $metadata, ?array &$errors = null)
$result = [];
// If metadata contains a "status" bin, use that instead
if (isset($metadata['grpc-status-details-bin'])) {
- $status = new \Google\Rpc\Status();
+ $status = new Status();
$status->mergeFromString($metadata['grpc-status-details-bin'][0]);
foreach ($status->getDetails() as $any) {
if (isset(KnownTypes::TYPE_URLS[$any->getTypeUrl()])) {
@@ -212,7 +223,18 @@ public static function decodeMetadata(array $metadata, ?array &$errors = null)
if (self::hasBinaryHeaderSuffix($key)) {
if (isset(KnownTypes::BIN_TYPES[$key])) {
$class = KnownTypes::BIN_TYPES[$key];
- /** @var Message $message */
+ /**
+ * @var BadRequest
+ * | DebugInfo
+ * | ErrorInfo
+ * | Help
+ * | LocalizedMessage
+ * | PreconditionFailure
+ * | QuotaFailure
+ * | RequestInfo
+ * | ResourceInfo
+ * | RetryInfo $message
+ */
$message = new $class();
try {
$message->mergeFromString($value);
@@ -470,12 +492,10 @@ private function checkFieldRepeated(FieldDescriptor $field): bool
if (method_exists($field, 'isRepeated')) {
return $field->isRepeated();
}
-
if (method_exists($field, 'getLabel')) {
return $field->getLabel() === GPBLabel::REPEATED;
}
-
- throw new \Exception('No field repeated method avaialble');
+ throw new \LogicException('unable to check field repeated');
}
/**
diff --git a/src/Testing/MockRequest.php b/src/Testing/MockRequest.php
index f7a23a30e..be0099103 100644
--- a/src/Testing/MockRequest.php
+++ b/src/Testing/MockRequest.php
@@ -82,5 +82,4 @@ public function setPageSize($var)
return $this;
}
-
}
diff --git a/src/Testing/MockRequestBody.php b/src/Testing/MockRequestBody.php
index 7d877d809..6039f8569 100644
--- a/src/Testing/MockRequestBody.php
+++ b/src/Testing/MockRequestBody.php
@@ -643,5 +643,4 @@ public function getOneofField()
{
return $this->whichOneof('oneof_field');
}
-
}
diff --git a/src/Testing/MockResponse.php b/src/Testing/MockResponse.php
index 6d93ad96c..c9135ce4e 100644
--- a/src/Testing/MockResponse.php
+++ b/src/Testing/MockResponse.php
@@ -162,5 +162,4 @@ public function setResourcesMap($var)
return $this;
}
-
}
diff --git a/src/Transport/Rest/JsonStreamDecoder.php b/src/Transport/Rest/JsonStreamDecoder.php
index c01f21135..90aba0680 100644
--- a/src/Transport/Rest/JsonStreamDecoder.php
+++ b/src/Transport/Rest/JsonStreamDecoder.php
@@ -92,7 +92,7 @@ public function __construct(StreamInterface $stream, string $decodeType, array $
public function decode()
{
try {
- foreach ($this->_decode() as $response) {
+ foreach ($this->doDecode() as $response) {
yield $response;
}
} catch (RuntimeException $re) {
@@ -112,7 +112,7 @@ public function decode()
/**
* @return \Generator
*/
- private function _decode()
+ private function doDecode()
{
$decodeType = $this->decodeType;
$str = false;
diff --git a/src/Transport/Rest/RestServerStreamingCall.php b/src/Transport/Rest/RestServerStreamingCall.php
index 35d796199..80d5e3e3c 100644
--- a/src/Transport/Rest/RestServerStreamingCall.php
+++ b/src/Transport/Rest/RestServerStreamingCall.php
@@ -55,7 +55,7 @@ class RestServerStreamingCall implements ServerStreamingCallInterface
private array $decoderOptions;
private RequestInterface $originalRequest;
- private ?JsonStreamDecoder $decoder;
+ private JsonStreamDecoder $decoder;
private string $decodeType;
private ?ResponseInterface $response;
private stdClass $status;
@@ -181,7 +181,7 @@ public function getPeer()
*/
public function cancel()
{
- if (!is_null($this->decoder)) {
+ if (isset($this->decoder)) {
$this->decoder->close();
}
}
diff --git a/src/Transport/RestTransport.php b/src/Transport/RestTransport.php
index 296937fa4..aab687182 100644
--- a/src/Transport/RestTransport.php
+++ b/src/Transport/RestTransport.php
@@ -200,7 +200,7 @@ public function startServerStreamingCall(Call $call, array $options)
$request = $this->requestBuilder->build(
$call->getMethod(),
$call->getMessage()
- // Exclude headers here because they will be added in _serverStreamRequest().
+ // Exclude headers here because they will be added in doServerStreamRequest().
);
$decoderOptions = [];
@@ -209,7 +209,7 @@ public function startServerStreamingCall(Call $call, array $options)
}
return new ServerStream(
- $this->_serverStreamRequest(
+ $this->doServerStreamRequest(
$this->httpHandler,
$request,
$headers,
@@ -233,7 +233,7 @@ public function startServerStreamingCall(Call $call, array $options)
*
* @return RestServerStreamingCall
*/
- private function _serverStreamRequest(
+ private function doServerStreamRequest(
$httpHandler,
$request,
$headers,
diff --git a/tests/Unit/AgentHeaderTest.php b/tests/Unit/AgentHeaderTest.php
index 27e7399ef..69dc6c74b 100644
--- a/tests/Unit/AgentHeaderTest.php
+++ b/tests/Unit/AgentHeaderTest.php
@@ -113,9 +113,9 @@ public function testWithNullVersionInput()
public function testGetGapicVersionWithVersionFile()
{
- require_once __DIR__ . '/testdata/src/GapicClientStub.php';
+ require_once __DIR__ . '/testdata/mocks/src/GapicClientStub.php';
$expectedVersion = '1.2.3-dev';
- $actualVersion = AgentHeader::readGapicVersionFromFile(\GapicClientStub::class);
+ $actualVersion = AgentHeader::readGapicVersionFromFile(GapicClientStub::class);
$this->assertEquals($expectedVersion, $actualVersion);
}
diff --git a/tests/Unit/ApiExceptionTest.php b/tests/Unit/ApiExceptionTest.php
index 645023769..b4ce68be5 100644
--- a/tests/Unit/ApiExceptionTest.php
+++ b/tests/Unit/ApiExceptionTest.php
@@ -98,7 +98,7 @@ public function testWithMetadataWithoutErrorInfo($metadata, $metadataArray, $uns
$this->assertSame(Code::OK, $apiException->getCode());
$this->assertSame($expectedMessageWithoutErrorDetails, $apiException->getMessage());
$this->assertSame($metadata, $apiException->getMetadata());
- $this->assertCount($unserializedErrorsCount ,$apiException->getErrorDetails());
+ $this->assertCount($unserializedErrorsCount, $apiException->getErrorDetails());
}
/**
@@ -123,7 +123,7 @@ public function testCreateFromApiResponse($metadata, $metadataArray, $unserializ
$this->assertSame(Code::OK, $apiException->getCode());
$this->assertSame($expectedMessage, $apiException->getMessage());
$this->assertSame($metadata, $apiException->getMetadata());
- $this->assertCount($unserializedErrorsCount ,$apiException->getErrorDetails());
+ $this->assertCount($unserializedErrorsCount, $apiException->getErrorDetails());
}
public function getMetadata()
@@ -242,7 +242,7 @@ public function testWithMetadataWithErrorInfo($metadata, $metadataArray)
'code' => Code::OK,
'status' => 'OK',
'details' => $metadataArray,
- ],
+ ],
JSON_PRETTY_PRINT
);
diff --git a/tests/Unit/ArrayTraitTest.php b/tests/Unit/ArrayTraitTest.php
index fe31e8fca..c11da2613 100644
--- a/tests/Unit/ArrayTraitTest.php
+++ b/tests/Unit/ArrayTraitTest.php
@@ -42,7 +42,16 @@ class ArrayTraitTest extends TestCase
public function setUp(): void
{
- $this->implementation = new ArrayTraitStub();
+ $this->implementation = new class() {
+ use ArrayTrait {
+ arrayFilterRemoveNull as public;
+ isAssoc as public;
+ pluck as public;
+ pluckArray as public;
+ subsetArray as public;
+ arrayMergeRecursive as public;
+ }
+ };
}
public function testPluck()
@@ -182,15 +191,3 @@ public function testArrayMergeRecursive()
$this->assertEquals($expected, $res);
}
}
-
-class ArrayTraitStub
-{
- use ArrayTrait {
- arrayFilterRemoveNull as public;
- isAssoc as public;
- pluck as public;
- pluckArray as public;
- subsetArray as public;
- arrayMergeRecursive as public;
- }
-}
diff --git a/tests/Unit/BidiStreamTest.php b/tests/Unit/BidiStreamTest.php
index 58089b05b..d9453e578 100644
--- a/tests/Unit/BidiStreamTest.php
+++ b/tests/Unit/BidiStreamTest.php
@@ -373,6 +373,7 @@ public function testReadCallsLogger()
$stream->writeAll($requests);
- foreach ($stream->closeWriteAndReadAll() as $_) {}
+ foreach ($stream->closeWriteAndReadAll() as $_) {
+ }
}
}
diff --git a/tests/Unit/ClientOptionsTraitTest.php b/tests/Unit/ClientOptionsTraitTest.php
index 5dbea3a87..a5c9d964a 100644
--- a/tests/Unit/ClientOptionsTraitTest.php
+++ b/tests/Unit/ClientOptionsTraitTest.php
@@ -52,34 +52,84 @@ class ClientOptionsTraitTest extends TestCase
use ProphecyTrait;
use TestTrait;
+ private $clientStub;
+ private $universeDomainClientStub;
+
+ public function setUp(): void
+ {
+ $this->clientStub = new class() {
+ use ClientOptionsTrait {
+ buildClientOptions as public;
+ createCredentialsWrapper as public;
+ determineMtlsEndpoint as public;
+ getGapicVersion as public;
+ shouldUseMtlsEndpoint as public;
+ }
+
+ private const SERVICE_NAME = 'TEST_SERVICE_NAME';
+
+ public function set($name, $val, $static = false)
+ {
+ if (!property_exists($this, $name)) {
+ throw new \InvalidArgumentException("Property not found: $name");
+ }
+ if ($static) {
+ $this::$$name = $val;
+ } else {
+ $this->$name = $val;
+ }
+ }
+
+ public static function getClientDefaults()
+ {
+ return [
+ 'apiEndpoint' => 'test.address.com:443',
+ 'gcpApiConfigPath' => __DIR__ . '/testdata/resources/test_service_grpc_config.json',
+ ];
+ }
+ };
+
+ $this->universeDomainClientStub = new class() {
+ use ClientOptionsTrait {
+ buildClientOptions as public;
+ }
+
+ private const SERVICE_ADDRESS_TEMPLATE = 'stub.UNIVERSE_DOMAIN';
+
+ public static function getClientDefaults()
+ {
+ return [
+ 'apiEndpoint' => 'test.address.com:443',
+ ];
+ }
+ };
+ }
+
public function tearDown(): void
{
// Reset the static gapicVersion field between tests
- $client = new StubClientOptionsClient();
- $client->set('gapicVersionFromFile', null, true);
+ $this->clientStub->set('gapicVersionFromFile', null, true);
}
public function testGetGapicVersionWithVersionFile()
{
- require_once __DIR__ . '/testdata/src/GapicClientStub.php';
+ require_once __DIR__ . '/testdata/mocks/src/GapicClientStub.php';
$version = '1.2.3-dev';
- $client = new \GapicClientStub();
+ $client = new GapicClientStub();
$this->assertEquals($version, $client::getGapicVersion([]));
}
public function testGetGapicVersionWithNoAvailableVersion()
{
- $client = new StubClientOptionsClient();
- $this->assertSame('', $client::getGapicVersion([]));
+ $this->assertSame('', $this->clientStub::getGapicVersion([]));
}
public function testGetGapicVersionWithLibVersion()
{
$version = '1.2.3-dev';
- $client = new StubClientOptionsClient();
- $client->set('gapicVersionFromFile', $version, true);
+ $this->clientStub->set('gapicVersionFromFile', $version, true);
$options = ['libVersion' => $version];
- $this->assertEquals($version, $client::getGapicVersion(
+ $this->assertEquals($version, $this->clientStub::getGapicVersion(
$options
));
}
@@ -89,8 +139,7 @@ public function testGetGapicVersionWithLibVersion()
*/
public function testCreateCredentialsWrapper($auth, $authConfig, $expectedCredentialsWrapper)
{
- $client = new StubClientOptionsClient();
- $actualCredentialsWrapper = $client->createCredentialsWrapper(
+ $actualCredentialsWrapper = $this->clientStub->createCredentialsWrapper(
$auth,
$authConfig,
GetUniverseDomainInterface::DEFAULT_UNIVERSE_DOMAIN
@@ -101,12 +150,13 @@ public function testCreateCredentialsWrapper($auth, $authConfig, $expectedCreden
public function createCredentialsWrapperData()
{
- $keyFilePath = __DIR__ . '/testdata/json-key-file.json';
+ $keyFilePath = __DIR__ . '/testdata/creds/json-key-file.json';
$keyFile = json_decode(file_get_contents($keyFilePath), true);
+
$fetcher = $this->prophesize(FetchAuthTokenInterface::class)->reveal();
$credentialsWrapper = new CredentialsWrapper($fetcher);
+
return [
- [null, [], CredentialsWrapper::build()],
[$keyFilePath, [], CredentialsWrapper::build(['keyFile' => $keyFile])],
[$keyFile, [], CredentialsWrapper::build(['keyFile' => $keyFile])],
[$fetcher, [], new CredentialsWrapper($fetcher)],
@@ -114,16 +164,34 @@ public function createCredentialsWrapperData()
];
}
+ /**
+ * @runInSeparateProcess
+ */
+ public function testCreateCredentialsWrapperFromEnv()
+ {
+ $keyFilePath = __DIR__ . '/testdata/creds/json-key-file.json';
+ putenv('GOOGLE_APPLICATION_CREDENTIALS=' . $keyFilePath);
+
+ $expectedCredentialsWrapper = CredentialsWrapper::build();
+ $actualCredentialsWrapper = $this->clientStub->createCredentialsWrapper(
+ null,
+ [],
+ GetUniverseDomainInterface::DEFAULT_UNIVERSE_DOMAIN
+ );
+
+ $this->assertEquals($expectedCredentialsWrapper, $actualCredentialsWrapper);
+ }
+
+
/**
* @dataProvider createCredentialsWrapperValidationExceptionData
*/
public function testCreateCredentialsWrapperValidationException($auth, $authConfig)
{
- $client = new StubClientOptionsClient();
$this->expectException(ValidationException::class);
- $client->createCredentialsWrapper(
+ $this->clientStub->createCredentialsWrapper(
$auth,
$authConfig,
''
@@ -143,11 +211,10 @@ public function createCredentialsWrapperValidationExceptionData()
*/
public function testCreateCredentialsWrapperInvalidArgumentException($auth, $authConfig)
{
- $client = new StubClientOptionsClient();
$this->expectException(InvalidArgumentException::class);
- $client->createCredentialsWrapper(
+ $this->clientStub->createCredentialsWrapper(
$auth,
$authConfig,
''
@@ -169,8 +236,7 @@ public function testBuildClientOptions($options, $expectedUpdatedOptions)
if (!extension_loaded('sysvshm')) {
$this->markTestSkipped('The sysvshm extension must be installed to execute this test.');
}
- $client = new StubClientOptionsClient();
- $updatedOptions = $client->buildClientOptions($options);
+ $updatedOptions = $this->clientStub->buildClientOptions($options);
$this->assertEquals($expectedUpdatedOptions, $updatedOptions);
}
@@ -178,13 +244,13 @@ public function buildClientOptionsProvider()
{
$apiConfig = new ApiConfig();
$apiConfig->mergeFromJsonString(
- file_get_contents(__DIR__ . '/testdata/test_service_grpc_config.json')
+ file_get_contents(__DIR__ . '/testdata/resources/test_service_grpc_config.json')
);
$grpcGcpConfig = new Config('test.address.com:443', $apiConfig);
$defaultOptions = [
'apiEndpoint' => 'test.address.com:443',
- 'gcpApiConfigPath' => __DIR__ . '/testdata/test_service_grpc_config.json',
+ 'gcpApiConfigPath' => __DIR__ . '/testdata/resources/test_service_grpc_config.json',
'disableRetries' => false,
'transport' => null,
'transportConfig' => [
@@ -253,8 +319,22 @@ public function testBuildClientOptionsRestOnly($options, $expectedUpdatedOptions
if (!extension_loaded('sysvshm')) {
$this->markTestSkipped('The sysvshm extension must be installed to execute this test.');
}
- $client = new RestOnlyClient();
- $updatedOptions = $client->buildClientOptions($options);
+ $restOnlyClient = new class() {
+ use ClientOptionsTrait {
+ buildClientOptions as public;
+ }
+
+ private static function supportedTransports()
+ {
+ return ['rest', 'fake-transport'];
+ }
+
+ private static function defaultTransport()
+ {
+ return 'rest';
+ }
+ };
+ $updatedOptions = $restOnlyClient->buildClientOptions($options);
$this->assertEquals($expectedUpdatedOptions, $updatedOptions);
}
@@ -314,24 +394,44 @@ public function buildClientOptionsProviderRestOnly()
public function testDefaultScopes()
{
- $client = new DefaultScopeAndAudienceClientOptionsClient();
+ $defaultScopeClient = new class() {
+ use ClientOptionsTrait {
+ buildClientOptions as public;
+ }
+
+ const SERVICE_ADDRESS = 'service-address';
+
+ public static $serviceScopes = [
+ 'default-scope-1',
+ 'default-scope-2',
+ ];
+
+ public static function getClientDefaults()
+ {
+ return [
+ 'credentialsConfig' => [
+ 'defaultScopes' => self::$serviceScopes,
+ ],
+ ];
+ }
+ };
// verify scopes are not set by default
- $defaultOptions = $client->buildClientOptions([]);
+ $defaultOptions = $defaultScopeClient->buildClientOptions([]);
$this->assertArrayNotHasKey('scopes', $defaultOptions['credentialsConfig']);
// verify scopes are set when a custom api endpoint is used
- $defaultOptions = $client->buildClientOptions([
+ $defaultOptions = $defaultScopeClient->buildClientOptions([
'apiEndpoint' => 'www.someotherendpoint.com',
]);
$this->assertArrayHasKey('scopes', $defaultOptions['credentialsConfig']);
$this->assertEquals(
- $client::$serviceScopes,
+ $defaultScopeClient::$serviceScopes,
$defaultOptions['credentialsConfig']['scopes']
);
// verify user-defined scopes override default scopes
- $defaultOptions = $client->buildClientOptions([
+ $defaultOptions = $defaultScopeClient->buildClientOptions([
'credentialsConfig' => ['scopes' => ['user-scope-1']],
'apiEndpoint' => 'www.someotherendpoint.com',
]);
@@ -342,8 +442,8 @@ public function testDefaultScopes()
);
// verify empty default scopes has no effect
- $client::$serviceScopes = null;
- $defaultOptions = $client->buildClientOptions([
+ $defaultScopeClient::$serviceScopes = null;
+ $defaultOptions = $defaultScopeClient->buildClientOptions([
'apiEndpoint' => 'www.someotherendpoint.com',
]);
$this->assertArrayNotHasKey('scopes', $defaultOptions['credentialsConfig']);
@@ -352,11 +452,9 @@ public function testDefaultScopes()
/** @dataProvider provideDetermineMtlsEndpoint */
public function testDetermineMtlsEndpoint($apiEndpoint, $expected)
{
- $client = new StubClientOptionsClient();
-
$this->assertEquals(
$expected,
- $client::determineMtlsEndpoint($apiEndpoint)
+ $this->clientStub::determineMtlsEndpoint($apiEndpoint)
);
}
@@ -382,12 +480,11 @@ public function provideDetermineMtlsEndpoint()
*/
public function testShouldUseMtlsEndpoint($envVarValue, $options, $expected)
{
- $client = new StubClientOptionsClient();
putenv('GOOGLE_API_USE_MTLS_ENDPOINT=' . $envVarValue);
$this->assertEquals(
$expected,
- $client->shouldUseMtlsEndpoint($options)
+ $this->clientStub->shouldUseMtlsEndpoint($options)
);
}
@@ -414,8 +511,7 @@ public function testMtlsClientOptions($envVars, $options, $expected)
putenv($envVar);
}
- $client = new StubClientOptionsClient();
- $options = $client->buildClientOptions($options);
+ $options = $this->clientStub->buildClientOptions($options);
// Only check the keys we care about
$options = array_intersect_key(
@@ -430,6 +526,8 @@ public function provideMtlsClientOptions()
{
$defaultEndpoint = 'test.address.com:443';
$mtlsEndpoint = 'test.mtls.address.com:443';
+ $homeDir = PHP_OS_FAMILY === 'Windows' ? 'APPDATA' : 'HOME';
+
return [
[
[],
@@ -460,7 +558,7 @@ public function provideMtlsClientOptions()
],
[
[
- 'HOME=' . __DIR__ . '/testdata/nonexistant',
+ $homeDir . '=' . __DIR__ . '/testdata/nonexistant',
'GOOGLE_API_USE_MTLS_ENDPOINT', // no env var
CredentialsLoader::MTLS_CERT_ENV_VAR . '=true',
],
@@ -475,12 +573,12 @@ public function provideMtlsClientOptions()
*/
public function testMtlsClientOptionWithDefaultClientCertSource()
{
- putenv('HOME=' . __DIR__ . '/testdata/mtls');
+ $homeDir = PHP_OS_FAMILY === 'Windows' ? 'APPDATA' : 'HOME';
+ putenv($homeDir . '=' . __DIR__ . '/testdata/creds/mtls');
putenv('GOOGLE_API_USE_MTLS_ENDPOINT=auto');
putenv(CredentialsLoader::MTLS_CERT_ENV_VAR . '=true');
- $client = new StubClientOptionsClient();
- $options = $client->buildClientOptions([]);
+ $options = $this->clientStub->buildClientOptions([]);
$this->assertSame('test.mtls.address.com:443', $options['apiEndpoint']);
$this->assertTrue(is_callable($options['clientCertSource']));
@@ -496,8 +594,7 @@ public function testServiceAddressTemplate(array $options, string $expectedEndpo
if ($envVar) {
putenv($envVar);
}
- $client = new UniverseDomainStubClientOptionsClient();
- $updatedOptions = $client->buildClientOptions($options);
+ $updatedOptions = $this->universeDomainClientStub->buildClientOptions($options);
$this->assertEquals($expectedEndpoint, $updatedOptions['apiEndpoint']);
}
@@ -544,27 +641,26 @@ public function testMtlsWithUniverseDomainThrowsException()
$this->expectException(ValidationException::class);
$this->expectExceptionMessage('mTLS is not supported outside the "googleapis.com" universe');
- $client = new UniverseDomainStubClientOptionsClient();
- $client->buildClientOptions([
+ $this->universeDomainClientStub->buildClientOptions([
'universeDomain' => 'foo.com',
- 'clientCertSource' => function () { $this->fail('this should not be called');},
+ 'clientCertSource' => function () {
+ $this->fail('this should not be called');
+ },
]);
}
public function testBuildClientOptionsTwice()
{
- $client = new StubClientOptionsClient();
- $options = $client->buildClientOptions([]);
- $options2 = $client->buildClientOptions($options);
+ $options = $this->clientStub->buildClientOptions([]);
+ $options2 = $this->clientStub->buildClientOptions($options);
$this->assertEquals($options, $options2);
}
public function testBuildClientOptionsWithClientOptions()
{
- $client = new StubClientOptionsClient();
$clientOptions = new ClientOptions([]);
$clientOptions->setApiEndpoint('TestEndpoint.com');
- $builtOptions = $client->buildClientOptions($clientOptions);
+ $builtOptions = $this->clientStub->buildClientOptions($clientOptions);
$this->assertEquals($clientOptions['apiEndpoint'], $builtOptions['apiEndpoint']);
}
@@ -576,11 +672,10 @@ public function testLoggerIsNullWhenFalseIsPassed()
{
putenv('GOOGLE_SDK_PHP_LOGGING=true');
- $client = new StubClientOptionsClient();
$optionsArray = [
'logger' => false,
];
- $options = $client->buildClientOptions($optionsArray);
+ $options = $this->clientStub->buildClientOptions($optionsArray);
$this->assertFalse($options['transportConfig']['rest']['logger']);
$this->assertFalse($options['transportConfig']['grpc']['logger']);
@@ -594,9 +689,8 @@ public function testLoggerIsNotNullIfFlagIsEmptyAndEnvVarSet()
{
putenv('GOOGLE_SDK_PHP_LOGGING=true');
- $client = new StubClientOptionsClient();
$optionsArray = [];
- $options = $client->buildClientOptions($optionsArray);
+ $options = $this->clientStub->buildClientOptions($optionsArray);
$this->assertInstanceOf(StdOutLogger::class, $options['transportConfig']['rest']['logger']);
$this->assertInstanceOf(StdOutLogger::class, $options['transportConfig']['grpc']['logger']);
@@ -609,8 +703,7 @@ public function testLogConfiguration()
{
putenv('GOOGLE_SDK_PHP_LOGGING=true');
- $client = new StubClientOptionsClient();
- $options = $client->buildClientOptions([
+ $options = $this->clientStub->buildClientOptions([
'apiEndpoint' => 'test'
]);
$parsedOutput = json_decode($this->getActualOutputForAssertion(), true);
@@ -623,9 +716,8 @@ public function testLogConfiguration()
public function testLoggerIsNullIfFlagIsEmptyAndNoEnvVar()
{
- $client = new StubClientOptionsClient();
$optionsArray = [];
- $options = $client->buildClientOptions($optionsArray);
+ $options = $this->clientStub->buildClientOptions($optionsArray);
$this->assertNull($options['transportConfig']['rest']['logger']);
$this->assertNull($options['transportConfig']['grpc']['logger']);
@@ -633,12 +725,11 @@ public function testLoggerIsNullIfFlagIsEmptyAndNoEnvVar()
public function testLoggerIsSetWhenALoggerIsPassed()
{
- $client = new StubClientOptionsClient();
$logger = new StdOutLogger();
$optionsArray = [
'logger' => $logger
];
- $options = $client->buildClientOptions($optionsArray);
+ $options = $this->clientStub->buildClientOptions($optionsArray);
$this->assertEquals($options['transportConfig']['rest']['logger'], $logger);
$this->assertEquals($options['transportConfig']['grpc']['logger'], $logger);
@@ -651,99 +742,9 @@ public function testExceptionIsRaisedIfOptionsIsInvalid()
'The "logger" option in the options array should be PSR-3 LoggerInterface compatible'
);
- $client = new StubClientOptionsClient();
$optionsArray = [
'logger' => 'nonValidOption'
];
- $client->buildClientOptions($optionsArray);
- }
-}
-
-class StubClientOptionsClient
-{
- use ClientOptionsTrait {
- buildClientOptions as public;
- createCredentialsWrapper as public;
- determineMtlsEndpoint as public;
- getGapicVersion as public;
- shouldUseMtlsEndpoint as public;
- }
-
- private const SERVICE_NAME = 'TEST_SERVICE_NAME';
-
- public function set($name, $val, $static = false)
- {
- if (!property_exists($this, $name)) {
- throw new \InvalidArgumentException("Property not found: $name");
- }
- if ($static) {
- $this::$$name = $val;
- } else {
- $this->$name = $val;
- }
- }
-
- public static function getClientDefaults()
- {
- return [
- 'apiEndpoint' => 'test.address.com:443',
- 'gcpApiConfigPath' => __DIR__ . '/testdata/test_service_grpc_config.json',
- ];
- }
-}
-
-class RestOnlyClient
-{
- use ClientOptionsTrait {
- buildClientOptions as public;
- }
-
- private static function supportedTransports()
- {
- return ['rest', 'fake-transport'];
- }
-
- private static function defaultTransport()
- {
- return 'rest';
- }
-}
-
-class DefaultScopeAndAudienceClientOptionsClient
-{
- use ClientOptionsTrait {
- buildClientOptions as public;
- }
-
- const SERVICE_ADDRESS = 'service-address';
-
- public static $serviceScopes = [
- 'default-scope-1',
- 'default-scope-2',
- ];
-
- public static function getClientDefaults()
- {
- return [
- 'credentialsConfig' => [
- 'defaultScopes' => self::$serviceScopes,
- ],
- ];
- }
-}
-
-class UniverseDomainStubClientOptionsClient
-{
- use ClientOptionsTrait {
- buildClientOptions as public;
- }
-
- private const SERVICE_ADDRESS_TEMPLATE = 'stub.UNIVERSE_DOMAIN';
-
- public static function getClientDefaults()
- {
- return [
- 'apiEndpoint' => 'test.address.com:443',
- ];
+ $this->clientStub->buildClientOptions($optionsArray);
}
}
diff --git a/tests/Unit/CredentialsWrapperTest.php b/tests/Unit/CredentialsWrapperTest.php
index 9c4da6b1f..d7d5a1c09 100644
--- a/tests/Unit/CredentialsWrapperTest.php
+++ b/tests/Unit/CredentialsWrapperTest.php
@@ -61,7 +61,7 @@ class CredentialsWrapperTest extends TestCase
public function testBuildWithoutExplicitKeyFile($args, $expectedCredentialsWrapper)
{
$appDefaultCreds = getenv('GOOGLE_APPLICATION_CREDENTIALS');
- $this->setEnv('GOOGLE_APPLICATION_CREDENTIALS', __DIR__ . '/testdata/json-key-file.json');
+ $this->setEnv('GOOGLE_APPLICATION_CREDENTIALS', __DIR__ . '/testdata/creds/json-key-file.json');
$actualCredentialsWrapper = CredentialsWrapper::build($args);
$this->assertEquals($expectedCredentialsWrapper, $actualCredentialsWrapper);
@@ -81,7 +81,7 @@ public function testBuildWithKeyFile($args, $expectedCredentialsWrapper)
public function buildDataWithoutExplicitKeyFile()
{
$appDefaultCreds = getenv('GOOGLE_APPLICATION_CREDENTIALS');
- $this->setEnv('GOOGLE_APPLICATION_CREDENTIALS', __DIR__ . '/testdata/json-key-file.json');
+ $this->setEnv('GOOGLE_APPLICATION_CREDENTIALS', __DIR__ . '/testdata/creds/json-key-file.json');
$scopes = ['myscope'];
$authHttpHandler = HttpHandlerFactory::build();
$asyncAuthHttpHandler = function ($request, $options) use ($authHttpHandler) {
@@ -95,31 +95,55 @@ public function buildDataWithoutExplicitKeyFile()
$testData = [
[
[],
- new CredentialsWrapper(ApplicationDefaultCredentials::getCredentials(null, $authHttpHandler, null, $defaultAuthCache)),
+ new CredentialsWrapper(ApplicationDefaultCredentials::getCredentials(
+ httpHandler: $authHttpHandler,
+ cache: $defaultAuthCache
+ )),
],
[
['scopes' => $scopes],
- new CredentialsWrapper(ApplicationDefaultCredentials::getCredentials($scopes, $authHttpHandler, null, $defaultAuthCache)),
+ new CredentialsWrapper(ApplicationDefaultCredentials::getCredentials(
+ scope: $scopes,
+ httpHandler: $authHttpHandler,
+ cache: $defaultAuthCache
+ )),
],
[
['scopes' => $scopes, 'authHttpHandler' => $asyncAuthHttpHandler],
- new CredentialsWrapper(ApplicationDefaultCredentials::getCredentials($scopes, $asyncAuthHttpHandler, null, $defaultAuthCache), $asyncAuthHttpHandler),
+ new CredentialsWrapper(ApplicationDefaultCredentials::getCredentials(
+ $scopes,
+ $asyncAuthHttpHandler,
+ cache: $defaultAuthCache
+ ), $asyncAuthHttpHandler),
],
[
['enableCaching' => false],
- new CredentialsWrapper(ApplicationDefaultCredentials::getCredentials(null, $authHttpHandler, null, null)),
+ new CredentialsWrapper(ApplicationDefaultCredentials::getCredentials(
+ httpHandler: $authHttpHandler
+ )),
],
[
['authCacheOptions' => $authCacheOptions],
- new CredentialsWrapper(ApplicationDefaultCredentials::getCredentials(null, $authHttpHandler, $authCacheOptions, $defaultAuthCache)),
+ new CredentialsWrapper(ApplicationDefaultCredentials::getCredentials(
+ httpHandler: $authHttpHandler,
+ cacheConfig: $authCacheOptions,
+ cache: $defaultAuthCache
+ )),
],
[
['authCache' => $authCache],
- new CredentialsWrapper(ApplicationDefaultCredentials::getCredentials(null, $authHttpHandler, null, $authCache)),
+ new CredentialsWrapper(ApplicationDefaultCredentials::getCredentials(
+ httpHandler: $authHttpHandler,
+ cache: $authCache
+ )),
],
[
['quotaProject' => $quotaProject],
- new CredentialsWrapper(ApplicationDefaultCredentials::getCredentials(null, $authHttpHandler, null, $defaultAuthCache, $quotaProject)),
+ new CredentialsWrapper(ApplicationDefaultCredentials::getCredentials(
+ httpHandler: $authHttpHandler,
+ cache: $defaultAuthCache,
+ quotaProject: $quotaProject
+ )),
],
];
@@ -130,11 +154,12 @@ public function buildDataWithoutExplicitKeyFile()
public function buildDataWithKeyFile()
{
- $keyFilePath = __DIR__ . '/testdata/json-key-file.json';
+ $keyFilePath = __DIR__ . '/testdata/creds/json-key-file.json';
$keyFile = json_decode(file_get_contents($keyFilePath), true);
$scopes = ['myscope'];
- $authHttpHandler = function () {};
+ $authHttpHandler = function () {
+ };
$defaultAuthCache = new MemoryCacheItemPool();
$authCache = new SysVCacheItemPool();
$authCacheOptions = ['lifetime' => 600];
@@ -193,8 +218,11 @@ private function makeExpectedKeyFileCreds($keyFile, $scopes, $cache, $cacheConfi
/**
* @dataProvider provideCheckUniverseDomainFails
*/
- public function testCheckUniverseDomainFails(?string $universeDomain, ?string $credentialsUniverse, ?string $message = null)
- {
+ public function testCheckUniverseDomainFails(
+ ?string $universeDomain,
+ ?string $credentialsUniverse,
+ ?string $message = null
+ ) {
$this->expectException(ValidationException::class);
$this->expectExceptionMessage($message ?: sprintf(
'The configured universe domain (%s) does not match the credential universe domain (%s)',
@@ -259,7 +287,7 @@ public function provideCheckUniverseDomainFails()
['googleapis.com', ''],
['', 'googleapis.com', 'The universe domain cannot be empty'],
[null, 'foo.com'], // null in CredentialsWrapper will default to "googleapis.com"
- ['foo.com', null], // Credentials not implementing GetUniverseDomainInterface will default to "googleapis.com"
+ ['foo.com', null], // Credentials not implementing GetUniverseDomainInterface will default to googleapis.com
];
}
@@ -318,9 +346,11 @@ public function testCheckUniverseDomainOnGceCredentialsDoesNotCheck()
/**
* @dataProvider getBearerStringData
+ * @runInSeparateProcess
*/
- public function testGetBearerString($fetcher, $expectedBearerString)
+ public function testGetBearerString(string $fetcherFunc, $expectedBearerString)
{
+ $fetcher = $this->$fetcherFunc();
$credentialsWrapper = new CredentialsWrapper($fetcher);
$bearerString = $credentialsWrapper->getBearerString();
$this->assertSame($expectedBearerString, $bearerString);
@@ -328,61 +358,24 @@ public function testGetBearerString($fetcher, $expectedBearerString)
public function getBearerStringData()
{
- $expiredFetcher = $this->prophesize(FetchAuthTokenInterface::class);
- $expiredFetcher->getLastReceivedToken()
- ->willReturn([
- 'access_token' => 123,
- 'expires_at' => time() - 1
- ]);
- $expiredFetcher->fetchAuthToken(Argument::any())
- ->willReturn([
- 'access_token' => 456,
- 'expires_at' => time() + 1000
- ]);
- $eagerExpiredFetcher = $this->prophesize(FetchAuthTokenInterface::class);
- $eagerExpiredFetcher->getLastReceivedToken()
- ->willReturn([
- 'access_token' => 123,
- 'expires_at' => time() + 1
- ]);
- $eagerExpiredFetcher->fetchAuthToken(Argument::any())
- ->willReturn([
- 'access_token' => 456,
- 'expires_at' => time() + 10 // within 10 second eager threshold
- ]);
- $unexpiredFetcher = $this->prophesize(FetchAuthTokenInterface::class);
- $unexpiredFetcher->getLastReceivedToken()
- ->willReturn([
- 'access_token' => 123,
- 'expires_at' => time() + 100,
- ]);
- $insecureFetcher = $this->prophesize(FetchAuthTokenInterface::class);
- $insecureFetcher->getLastReceivedToken()->willReturn(null);
- $insecureFetcher->fetchAuthToken(Argument::any())
- ->willReturn([
- 'access_token' => '',
- ]);
- $nullFetcher = $this->prophesize(FetchAuthTokenInterface::class);
- $nullFetcher->getLastReceivedToken()->willReturn(null);
- $nullFetcher->fetchAuthToken(Argument::any())
- ->willReturn([
- 'access_token' => null,
- ]);
return [
- [$expiredFetcher->reveal(), 'Bearer 456'],
- [$eagerExpiredFetcher->reveal(), 'Bearer 456'],
- [$unexpiredFetcher->reveal(), 'Bearer 123'],
- [$insecureFetcher->reveal(), ''],
- [$nullFetcher->reveal(), '']
+ ['getExpiredFetcher', 'Bearer 456'],
+ ['getEagerExpiredFetcher', 'Bearer 456'],
+ ['getUnexpiredFetcher', 'Bearer 123'],
+ ['getInsecureFetcher', ''],
+ ['getNullFetcher', ''],
];
}
/**
* @dataProvider getAuthorizationHeaderCallbackData
+ * @runInSeparateProcess
*/
- public function testGetAuthorizationHeaderCallback($fetcher, $expectedCallbackResponse)
+ public function testGetAuthorizationHeaderCallback(string $fetcherFunc, $expectedCallbackResponse)
{
- $httpHandler = function () {};
+ $fetcher = $this->$fetcherFunc();
+ $httpHandler = function () {
+ };
$credentialsWrapper = new CredentialsWrapper($fetcher, $httpHandler);
$callback = $credentialsWrapper->getAuthorizationHeaderCallback('audience');
$actualResponse = $callback();
@@ -391,16 +384,34 @@ public function testGetAuthorizationHeaderCallback($fetcher, $expectedCallbackRe
public function getAuthorizationHeaderCallbackData()
{
- $expiredFetcher = $this->prophesize();
- $expiredFetcher->willImplement(FetchAuthTokenInterface::class);
- $expiredFetcher->willImplement(UpdateMetadataInterface::class);
+ return [
+ ['getExpiredFetcher', ['authorization' => ['Bearer 456']]],
+ ['getExpiredInvalidFetcher', []],
+ ['getUnexpiredFetcher', ['authorization' => ['Bearer 123']]],
+ ['getInsecureFetcher', []],
+ ['getNullFetcher', []],
+ ['getCustomFetcher', ['authorization' => ['Bearer 123']]],
+ ];
+ }
+
+ private function getExpiredFetcher()
+ {
+ $expiredFetcher = $this->prophesize(FetchAuthTokenInterface::class);
$expiredFetcher->getLastReceivedToken()
->willReturn([
'access_token' => 123,
'expires_at' => time() - 1
]);
- $expiredFetcher->updateMetadata(Argument::any(), 'audience', Argument::type('callable'))
- ->willReturn(['authorization' => ['Bearer 456']]);
+ $expiredFetcher->fetchAuthToken(Argument::any())
+ ->willReturn([
+ 'access_token' => 456,
+ 'expires_at' => time() + 1000
+ ]);
+ return $expiredFetcher->reveal();
+ }
+
+ private function getExpiredInvalidFetcher()
+ {
$expiredInvalidFetcher = $this->prophesize(FetchAuthTokenInterface::class);
$expiredInvalidFetcher->getLastReceivedToken()
->willReturn([
@@ -409,44 +420,70 @@ public function getAuthorizationHeaderCallbackData()
]);
$expiredInvalidFetcher->fetchAuthToken(Argument::any())
->willReturn(['not-a' => 'valid-token']);
- $unexpiredFetcher = $this->prophesize();
- $unexpiredFetcher->willImplement(FetchAuthTokenInterface::class);
+ return $expiredInvalidFetcher->reveal();
+ }
+
+ private function getEagerExpiredFetcher()
+ {
+ $eagerExpiredFetcher = $this->prophesize(FetchAuthTokenInterface::class);
+ $eagerExpiredFetcher->getLastReceivedToken()
+ ->willReturn([
+ 'access_token' => 123,
+ 'expires_at' => time() + 1
+ ]);
+ $eagerExpiredFetcher->fetchAuthToken(Argument::any())
+ ->willReturn([
+ 'access_token' => 456,
+ 'expires_at' => time() + 10 // within 10 second eager threshold
+ ]);
+ return $eagerExpiredFetcher->reveal();
+ }
+
+ private function getUnexpiredFetcher()
+ {
+ $unexpiredFetcher = $this->prophesize(FetchAuthTokenInterface::class);
$unexpiredFetcher->getLastReceivedToken()
->willReturn([
'access_token' => 123,
'expires_at' => time() + 100,
]);
+ $unexpiredFetcher->fetchAuthToken(Argument::any())
+ ->shouldNotBeCalled();
+ return $unexpiredFetcher->reveal();
+ }
+ private function getInsecureFetcher()
+ {
$insecureFetcher = $this->prophesize(FetchAuthTokenInterface::class);
$insecureFetcher->getLastReceivedToken()->willReturn(null);
$insecureFetcher->fetchAuthToken(Argument::any())
->willReturn([
'access_token' => '',
]);
+ return $insecureFetcher->reveal();
+ }
+
+ private function getNullFetcher()
+ {
$nullFetcher = $this->prophesize(FetchAuthTokenInterface::class);
$nullFetcher->getLastReceivedToken()->willReturn(null);
$nullFetcher->fetchAuthToken(Argument::any())
->willReturn([
'access_token' => null,
]);
+ return $nullFetcher->reveal();
+ }
- $customFetcher = $this->prophesize();
- $customFetcher->willImplement(FetchAuthTokenInterface::class);
+ private function getCustomFetcher()
+ {
+ $customFetcher = $this->prophesize(FetchAuthTokenInterface::class);
$customFetcher->getLastReceivedToken()->willReturn(null);
$customFetcher->fetchAuthToken(Argument::any())
->willReturn([
'access_token' => 123,
'expires_at' => time() + 100,
]);
-
- return [
- [$expiredFetcher->reveal(), ['authorization' => ['Bearer 456']]],
- [$expiredInvalidFetcher->reveal(), []],
- [$unexpiredFetcher->reveal(), ['authorization' => ['Bearer 123']]],
- [$insecureFetcher->reveal(), []],
- [$nullFetcher->reveal(), []],
- [$customFetcher->reveal(), ['authorization' => ['Bearer 123']]],
- ];
+ return $customFetcher->reveal();
}
/**
@@ -572,7 +609,7 @@ public function testGetProjectIdWithFetchAuthTokenCache()
public function testSerializeCredentialsWrapper()
{
$credentialsWrapper = CredentialsWrapper::build([
- 'keyFile' => __DIR__ . '/testdata/json-key-file.json',
+ 'keyFile' => __DIR__ . '/testdata/creds/json-key-file.json',
]);
$serialized = serialize($credentialsWrapper);
$this->assertIsString($serialized);
diff --git a/tests/Unit/FixedSizeCollectionTest.php b/tests/Unit/FixedSizeCollectionTest.php
index dade34d7b..00771d074 100644
--- a/tests/Unit/FixedSizeCollectionTest.php
+++ b/tests/Unit/FixedSizeCollectionTest.php
@@ -194,7 +194,9 @@ public function testInvalidPageCount()
->willReturn(2);
$this->expectException(InvalidArgumentException::class);
- $this->expectExceptionMessage('collectionSize must be greater than or equal to the number of elements in initialPage');
+ $this->expectExceptionMessage(
+ 'collectionSize must be greater than or equal to the number of elements in initialPage'
+ );
new FixedSizeCollection($page->reveal(), $collectionSize);
}
diff --git a/tests/Unit/GapicClientTraitTest.php b/tests/Unit/GapicClientTraitTest.php
index 8f702c57c..ae62e7539 100644
--- a/tests/Unit/GapicClientTraitTest.php
+++ b/tests/Unit/GapicClientTraitTest.php
@@ -68,11 +68,18 @@ class GapicClientTraitTest extends TestCase
use ProphecyTrait;
use TestTrait;
+ public function setUp(): void
+ {
+ $keyFilePath = __DIR__ . '/testdata/creds/json-key-file.json';
+ putenv('GOOGLE_APPLICATION_CREDENTIALS=' . $keyFilePath);
+ }
+
public function tearDown(): void
{
// Reset the static gapicVersion field between tests
$client = new StubGapicClient();
$client->set('gapicVersionFromFile', null, true);
+ putenv('GOOGLE_APPLICATION_CREDENTIALS=');
}
public function testHeadersOverwriteBehavior()
@@ -108,7 +115,7 @@ public function testHeadersOverwriteBehavior()
];
$transport = $this->prophesize(TransportInterface::class);
$credentialsWrapper = CredentialsWrapper::build([
- 'keyFile' => __DIR__ . '/testdata/json-key-file.json'
+ 'keyFile' => __DIR__ . '/testdata/creds/json-key-file.json'
]);
$transport->startUnaryCall(
Argument::type(Call::class),
@@ -170,7 +177,7 @@ public function testVersionedHeadersOverwriteBehavior()
];
$transport = $this->prophesize(TransportInterface::class);
$credentialsWrapper = CredentialsWrapper::build([
- 'keyFile' => __DIR__ . '/testdata/json-key-file.json'
+ 'keyFile' => __DIR__ . '/testdata/creds/json-key-file.json'
]);
$transport->startUnaryCall(
Argument::type(Call::class),
@@ -668,7 +675,7 @@ public function createTransportData()
: 'rest';
$transportConfig = [
'rest' => [
- 'restClientConfigPath' => __DIR__ . '/testdata/test_service_rest_client_config.php',
+ 'restClientConfigPath' => __DIR__ . '/testdata/resources/test_service_rest_client_config.php',
],
];
return [
@@ -700,7 +707,7 @@ public function createTransportDataInvalid()
$apiEndpoint = 'address:443';
$transportConfig = [
'rest' => [
- 'restConfigPath' => __DIR__ . '/testdata/test_service_rest_client_config.php',
+ 'restConfigPath' => __DIR__ . '/testdata/resources/test_service_rest_client_config.php',
],
];
return [
@@ -944,7 +951,7 @@ private function buildClientToTestModifyCallMethods($clientClass = null)
];
$transport = $this->prophesize(TransportInterface::class);
$credentialsWrapper = CredentialsWrapper::build([
- 'keyFile' => __DIR__ . '/testdata/json-key-file.json'
+ 'keyFile' => __DIR__ . '/testdata/creds/json-key-file.json'
]);
$clientClass = $clientClass ?: StubGapicClientExtension::class;
$client = new $clientClass();
@@ -977,7 +984,7 @@ public function testModifyUnaryCallFromStartCall()
],
'headers' => AgentHeader::buildAgentHeader([]),
'credentialsWrapper' => CredentialsWrapper::build([
- 'keyFile' => __DIR__ . '/testdata/json-key-file.json'
+ 'keyFile' => __DIR__ . '/testdata/creds/json-key-file.json'
])
]
)
@@ -1003,7 +1010,7 @@ public function testModifyUnaryCallFromOperationsCall()
],
'headers' => AgentHeader::buildAgentHeader([]),
'credentialsWrapper' => CredentialsWrapper::build([
- 'keyFile' => __DIR__ . '/testdata/json-key-file.json'
+ 'keyFile' => __DIR__ . '/testdata/creds/json-key-file.json'
]),
'metadataReturnType' => 'metadataType'
]
@@ -1031,7 +1038,7 @@ public function testModifyUnaryCallFromGetPagedListResponse()
],
'headers' => AgentHeader::buildAgentHeader([]),
'credentialsWrapper' => CredentialsWrapper::build([
- 'keyFile' => __DIR__ . '/testdata/json-key-file.json'
+ 'keyFile' => __DIR__ . '/testdata/creds/json-key-file.json'
])
]
)
@@ -1059,7 +1066,7 @@ public function testModifyStreamingCallFromStartCall($callArgs, $expectedMethod,
],
'headers' => AgentHeader::buildAgentHeader([]),
'credentialsWrapper' => CredentialsWrapper::build([
- 'keyFile' => __DIR__ . '/testdata/json-key-file.json'
+ 'keyFile' => __DIR__ . '/testdata/creds/json-key-file.json'
])
]
)
@@ -1376,7 +1383,7 @@ public function __invoke(Call $call, array $options)
],
'headers' => AgentHeader::buildAgentHeader([]),
'credentialsWrapper' => CredentialsWrapper::build([
- 'keyFile' => __DIR__ . '/testdata/json-key-file.json'
+ 'keyFile' => __DIR__ . '/testdata/creds/json-key-file.json'
])
]
)
@@ -1446,7 +1453,7 @@ public function __invoke(Call $call, array $options)
],
'headers' => AgentHeader::buildAgentHeader([]),
'credentialsWrapper' => CredentialsWrapper::build([
- 'keyFile' => __DIR__ . '/testdata/json-key-file.json'
+ 'keyFile' => __DIR__ . '/testdata/creds/json-key-file.json'
])
]
)
@@ -1463,7 +1470,7 @@ public function __invoke(Call $call, array $options)
$this->assertEquals(['middleware1', 'middleware2'], $callOrder);
}
- public function testPrependMiddlewareOrder()
+ public function testPrependMiddlewareOrder()
{
list($client, $transport) = $this->buildClientToTestModifyCallMethods();
@@ -1486,42 +1493,42 @@ public function __invoke(Call $call, array $options)
}
};
};
- $middleware2 = function (callable $handler) use (&$callOrder) {
- return new class($handler, $callOrder) implements MiddlewareInterface {
- private $handler;
- private array $callOrder;
- public function __construct(
- callable $handler,
- array &$callOrder
- ) {
- $this->handler = $handler;
- $this->callOrder = &$callOrder;
- }
- public function __invoke(Call $call, array $options)
- {
- $this->callOrder[] = 'middleware2';
- return ($this->handler)($call, $options);
- }
+ $middleware2 = function (callable $handler) use (&$callOrder) {
+ return new class($handler, $callOrder) implements MiddlewareInterface {
+ private $handler;
+ private array $callOrder;
+ public function __construct(
+ callable $handler,
+ array &$callOrder
+ ) {
+ $this->handler = $handler;
+ $this->callOrder = &$callOrder;
+ }
+ public function __invoke(Call $call, array $options)
+ {
+ $this->callOrder[] = 'middleware2';
+ return ($this->handler)($call, $options);
+ }
+ };
};
- };
- $client->prependMiddleware($middleware1);
- $client->prependMiddleware($middleware2);
+ $client->prependMiddleware($middleware1);
+ $client->prependMiddleware($middleware2);
- $transport->startUnaryCall(
- Argument::type(Call::class),
- [
+ $transport->startUnaryCall(
+ Argument::type(Call::class),
+ [
'transportOptions' => [
- 'custom' => ['addModifyUnaryCallableOption' => true]
+ 'custom' => ['addModifyUnaryCallableOption' => true]
],
'headers' => AgentHeader::buildAgentHeader([]),
'credentialsWrapper' => CredentialsWrapper::build([
- 'keyFile' => __DIR__ . '/testdata/json-key-file.json'
+ 'keyFile' => __DIR__ . '/testdata/creds/json-key-file.json'
])
- ]
- )
- ->shouldBeCalledOnce()
- ->willReturn(new FulfilledPromise(new Operation()));
+ ]
+ )
+ ->shouldBeCalledOnce()
+ ->willReturn(new FulfilledPromise(new Operation()));
$client->startCall(
'simpleMethod',
@@ -1563,7 +1570,7 @@ public function testCallOptionsForV2Surface()
[
'headers' => AgentHeader::buildAgentHeader([]) + ['Foo' => 'Bar'],
'credentialsWrapper' => CredentialsWrapper::build([
- 'keyFile' => __DIR__ . '/testdata/json-key-file.json'
+ 'keyFile' => __DIR__ . '/testdata/creds/json-key-file.json'
]),
'timeoutMillis' => null, // adds null timeoutMillis,
'transportOptions' => [],
@@ -1594,7 +1601,7 @@ public function testInvalidCallOptionsTypeForV1SurfaceDoesNotThrowException()
'transportOptions' => ['custom' => ['addModifyUnaryCallableOption' => true]],
'headers' => AgentHeader::buildAgentHeader([]),
'credentialsWrapper' => CredentialsWrapper::build([
- 'keyFile' => __DIR__ . '/testdata/json-key-file.json'
+ 'keyFile' => __DIR__ . '/testdata/creds/json-key-file.json'
]),
'timeoutMillis' => 'blue', // invalid type, this is ignored
]
@@ -1696,13 +1703,12 @@ public function testKeyFileIsIgnoredWhenApiKeyOptionIsSupplied()
$client = new GapicV2SurfaceClient([
'apiKey' => 'abc-123',
'credentialsConfig' => [
- 'keyFile' => __DIR__ . '/testdata/json-key-file.json',
+ 'keyFile' => __DIR__ . '/testdata/creds/json-key-file.json',
],
]);
$prop = new \ReflectionProperty($client, 'credentialsWrapper');
$this->assertInstanceOf(ApiKeyHeaderCredentials::class, $prop->getValue($client));
-
}
public function testApiKeyOptionAndQuotaProject()
@@ -1802,15 +1808,15 @@ public static function getClientDefaults()
return [
'apiEndpoint' => 'test.address.com:443',
'serviceName' => 'test.interface.v1.api',
- 'clientConfig' => __DIR__ . '/testdata/test_service_client_config.json',
- 'descriptorsConfigPath' => __DIR__ . '/testdata/test_service_descriptor_config.php',
+ 'clientConfig' => __DIR__ . '/testdata/resources/test_service_client_config.json',
+ 'descriptorsConfigPath' => __DIR__ . '/testdata/resources/test_service_descriptor_config.php',
'disableRetries' => false,
'auth' => null,
'authConfig' => null,
'transport' => null,
'transportConfig' => [
'rest' => [
- 'restClientConfigPath' => __DIR__ . '/testdata/test_service_rest_client_config.php',
+ 'restClientConfigPath' => __DIR__ . '/testdata/resources/test_service_rest_client_config.php',
]
],
];
diff --git a/tests/Unit/InsecureCredentialsWrapperTest.php b/tests/Unit/InsecureCredentialsWrapperTest.php
index ce0af535c..556ed69cd 100644
--- a/tests/Unit/InsecureCredentialsWrapperTest.php
+++ b/tests/Unit/InsecureCredentialsWrapperTest.php
@@ -80,5 +80,4 @@ public function testInsecureCredentialsWrapperWithGrpcTransport()
$this->assertInstanceOf(Promise::class, $response);
}
-
}
diff --git a/tests/Unit/InsecureRequestBuilderTest.php b/tests/Unit/InsecureRequestBuilderTest.php
index e3cd70885..084ad3f70 100644
--- a/tests/Unit/InsecureRequestBuilderTest.php
+++ b/tests/Unit/InsecureRequestBuilderTest.php
@@ -15,6 +15,8 @@
* limitations under the License.
*/
+namespace Google\ApiCore\Tests\Unit;
+
use Google\ApiCore\InsecureRequestBuilder;
use Google\ApiCore\Testing\MockRequestBody;
use PHPUnit\Framework\TestCase;
@@ -32,7 +34,7 @@ public function setUp(): void
{
$this->builder = new InsecureRequestBuilder(
'www.example.com',
- __DIR__ . '/testdata/test_service_rest_client_config.php'
+ __DIR__ . '/testdata/resources/test_service_rest_client_config.php'
);
}
diff --git a/tests/Unit/Middleware/RetryMiddlewareTest.php b/tests/Unit/Middleware/RetryMiddlewareTest.php
index 256f91fa9..f9e07853e 100644
--- a/tests/Unit/Middleware/RetryMiddlewareTest.php
+++ b/tests/Unit/Middleware/RetryMiddlewareTest.php
@@ -399,7 +399,7 @@ public function testRetriesAreIncludedInTheOptionsArray()
]);
$callCount = 0;
- $handler = function(Call $call, $options) use (&$callCount, &$reportedRetries) {
+ $handler = function (Call $call, $options) use (&$callCount, &$reportedRetries) {
$promise = new Promise(function () use (&$callCount, &$reportedRetries, $options, &$promise) {
if ($callCount === 0) {
++$callCount;
@@ -526,4 +526,4 @@ public function testUnlimitedMaxRetries()
$middleware($call->reveal(), [])->wait();
}
-}
\ No newline at end of file
+}
diff --git a/tests/Unit/OperationResponseTest.php b/tests/Unit/OperationResponseTest.php
index a4697579a..43ab160a4 100644
--- a/tests/Unit/OperationResponseTest.php
+++ b/tests/Unit/OperationResponseTest.php
@@ -31,6 +31,13 @@
*/
namespace Google\ApiCore\Tests\Unit;
+use Google\CustomOperation\Client\NewSurfaceCustomOperationClient;
+use Google\CustomOperation\CancelOperationRequest as CustomCancelOperationRequest;
+use Google\CustomOperation\CustomOperation;
+use Google\CustomOperation\CustomOperationClient;
+use Google\CustomOperation\CustomOperationWithErrorAnnotations;
+use Google\CustomOperation\DeleteOperationRequest as CustomDeleteOperationRequest;
+use Google\CustomOperation\GetOperationRequest as CustomGetOperationRequest;
use Google\ApiCore\LongRunning\OperationsClient;
use Google\ApiCore\OperationResponse;
use Google\LongRunning\CancelOperationRequest;
@@ -50,6 +57,16 @@ class OperationResponseTest extends TestCase
use ProphecyTrait;
use TestTrait;
+ public static function setUpBeforeClass(): void
+ {
+ self::autoloadTestdata('mocks', 'Google');
+ }
+
+ public static function tearDownAfterClass(): void
+ {
+ putenv('GOOGLE_APPLICATION_CREDENTIALS=');
+ }
+
/**
* @dataProvider provideOperationsClients
*/
@@ -64,6 +81,9 @@ public function testBasic($opClient)
public function provideOperationsClients()
{
+ $keyFilePath = __DIR__ . '/testdata/creds/json-key-file.json';
+ putenv('GOOGLE_APPLICATION_CREDENTIALS=' . $keyFilePath);
+
return [
[$this->createOperationsClient()],
[$this->prophesize(LROOperationsClient::class)->reveal()],
@@ -261,13 +281,10 @@ public function testCustomOperation()
public function testNewSurfaceCustomOperation()
{
- // This mock requires a specific namespace, so it must be defined in a separate file
- require_once __DIR__ . '/testdata/src/CustomOperationClient.php';
-
$phpunit = $this;
$operationName = 'test-123';
- $operationClient = $this->prophesize(Client\NewSurfaceCustomOperationClient::class);
- $operationClient->getNewSurfaceOperation(Argument::type(Client\GetOperationRequest::class))
+ $operationClient = $this->prophesize(NewSurfaceCustomOperationClient::class);
+ $operationClient->getNewSurfaceOperation(Argument::type(CustomGetOperationRequest::class))
->shouldBeCalledOnce()
->will(function ($args) use ($phpunit) {
list($request) = $args;
@@ -275,15 +292,17 @@ public function testNewSurfaceCustomOperation()
$phpunit->assertEquals('arg2', $request->arg2);
$phpunit->assertEquals('arg3', $request->arg3);
return new class {
- public function getDone() {
+ public function getDone()
+ {
return true;
}
- public function getError() {
+ public function getError()
+ {
return false;
}
};
});
- $operationClient->cancelNewSurfaceOperation(Argument::type(Client\CancelOperationRequest::class))
+ $operationClient->cancelNewSurfaceOperation(Argument::type(CustomCancelOperationRequest::class))
->shouldBeCalledOnce()
->will(function ($args) use ($phpunit) {
list($request) = $args;
@@ -292,7 +311,7 @@ public function getError() {
$phpunit->assertEquals('arg3', $request->arg3);
return true;
});
- $operationClient->deleteNewSurfaceOperation(Argument::type(Client\DeleteOperationRequest::class))
+ $operationClient->deleteNewSurfaceOperation(Argument::type(CustomDeleteOperationRequest::class))
->shouldBeCalledOnce()
->will(function ($args) use ($phpunit) {
list($request) = $args;
@@ -309,9 +328,9 @@ public function getError() {
'setArgumentTwo' => 'arg2',
'setArgumentThree' => 'arg3'
],
- 'getOperationRequest' => Client\GetOperationRequest::class,
- 'cancelOperationRequest' => Client\CancelOperationRequest::class,
- 'deleteOperationRequest' => Client\DeleteOperationRequest::class,
+ 'getOperationRequest' => CustomGetOperationRequest::class,
+ 'cancelOperationRequest' => CustomCancelOperationRequest::class,
+ 'deleteOperationRequest' => CustomDeleteOperationRequest::class,
];
$operationResponse = new OperationResponse($operationName, $operationClient->reveal(), $options);
@@ -335,10 +354,7 @@ public function testRequestClassWithoutBuildThrowsException()
$this->expectException(LogicException::class);
$this->expectExceptionMessage('Request class must support the static build method');
- // This mock requires a specific namespace, so it must be defined in a separate file
- require_once __DIR__ . '/testdata/src/CustomOperationClient.php';
-
- $operationClient = $this->prophesize(Client\NewSurfaceCustomOperationClient::class);
+ $operationClient = $this->prophesize(NewSurfaceCustomOperationClient::class);
$options = [
'getOperationRequest' => \stdClass::class, // a class that does not have a "build" method.
];
@@ -510,7 +526,31 @@ public function testDeleteWithLROOperationsClient()
private function createOperationResponse($options, $reloadCount)
{
$opName = 'operations/opname';
- return new FakeOperationResponse($opName, $this->createOperationClient($reloadCount), $options);
+ return new class($opName, $this->createOperationClient($reloadCount), $options) extends OperationResponse {
+ private $currentTime = 0;
+ private $sleeps;
+
+ public function getSleeps()
+ {
+ return $this->sleeps;
+ }
+
+ public function sleepMillis(int $millis)
+ {
+ $this->currentTime += $millis;
+ $this->sleeps[] = $millis;
+ }
+
+ public function setTimes($times)
+ {
+ $this->times = $times;
+ }
+
+ public function getCurrentTimeMillis()
+ {
+ return $this->currentTime;
+ }
+ };
}
private function createOperationClient($reloadCount)
@@ -530,50 +570,3 @@ private function createOperationClient($reloadCount)
return $opClient->reveal();
}
}
-
-class FakeOperationResponse extends OperationResponse
-{
- private $currentTime = 0;
- private $sleeps;
-
- public function getSleeps()
- {
- return $this->sleeps;
- }
-
- public function sleepMillis(int $millis)
- {
- $this->currentTime += $millis;
- $this->sleeps[] = $millis;
- }
-
- public function setTimes($times)
- {
- $this->times = $times;
- }
-
- public function getCurrentTimeMillis()
- {
- return $this->currentTime;
- }
-}
-
-interface CustomOperationClient
-{
- public function getMyOperationPlease($name, $requiredArg1, $requiredArg2);
- public function cancelMyOperationPlease($name, $requiredArg1, $requiredArg2);
- public function deleteMyOperationPlease($name, $requiredArg1, $requiredArg2);
-}
-
-interface CustomOperation
-{
- public function isThisOperationDoneOrWhat();
- public function getError();
-}
-
-interface CustomOperationWithErrorAnnotations
-{
- public function isThisOperationDoneOrWhat();
- public function getTheErrorCode();
- public function getTheErrorMessage();
-}
diff --git a/tests/Unit/Options/OptionsTraitTest.php b/tests/Unit/Options/OptionsTraitTest.php
index ae784a7a3..1e24517ba 100644
--- a/tests/Unit/Options/OptionsTraitTest.php
+++ b/tests/Unit/Options/OptionsTraitTest.php
@@ -46,7 +46,7 @@ class OptionsTraitTest extends TestCase
public function testDefaultOptionsExistAndUnrecognizedOptionsAreIgnored()
{
- $options = new OptionsTraitStub([
+ $options = $this->newStub([
'option3' => 'foo',
'option4' => 'bar',
]);
@@ -60,13 +60,9 @@ public function testDefaultOptionsExistAndUnrecognizedOptionsAreIgnored()
public function testInvalidTypesThrowException()
{
$this->expectException(TypeError::class);
- $this->expectExceptionMessage(
- PHP_MAJOR_VERSION < 8
- ? 'Google\ApiCore\Tests\Unit\Options\OptionsTraitStub::$option2 must be int or null, string used'
- : 'Cannot assign string to property Google\ApiCore\Tests\Unit\Options\OptionsTraitStub::$option2 of type ?int'
- );
+ $this->expectExceptionMessage('Cannot assign string to property ArrayAccess@anonymous::$option2 of type ?int');
- $options = new OptionsTraitStub([
+ $this->newStub([
'option1' => 123, // this is okay because it is cast to a string
'option2' => 'bar', // this will throw an exception
]);
@@ -74,13 +70,13 @@ public function testInvalidTypesThrowException()
public function testArrayGet()
{
- $options = new OptionsTraitStub(['option1' => 'abc']);
+ $options = $this->newStub(['option1' => 'abc']);
$this->assertEquals('abc', $options['option1']);
}
public function testArrayIsset()
{
- $options = new OptionsTraitStub(['option1' => 'abc']);
+ $options = $this->newStub(['option1' => 'abc']);
$this->assertTrue(isset($options['option1']));
$this->assertFalse(isset($options['option2'])); // valid option
$this->assertFalse(isset($options['option3'])); // invalid option
@@ -89,14 +85,14 @@ public function testArrayIsset()
public function testArraySetThrowsException()
{
$this->expectException(BadMethodCallException::class);
- $options = new OptionsTraitStub([]);
+ $options = $this->newStub([]);
$options['option1'] = 'abc';
}
public function testArrayUnsetThrowsException()
{
$this->expectException(BadMethodCallException::class);
- $options = new OptionsTraitStub([]);
+ $options = $this->newStub([]);
unset($options['option1']);
}
@@ -104,36 +100,38 @@ public function testInvalidFilePathThrowsException()
{
$this->expectException(ValidationException::class);
$this->expectExceptionMessage('Could not find specified file: does/not/exist.php');
- new OptionsTraitStub(['file' => 'does/not/exist.php']);
+ $this->newStub(['file' => 'does/not/exist.php']);
}
public function testValidateFileExists()
{
- $options = new OptionsTraitStub(['option1' => 'foo', 'file' => __FILE__]);
+ $options = $this->newStub(['option1' => 'foo', 'file' => __FILE__]);
$this->assertEquals(__FILE__, $options['file']);
}
-}
-
-class OptionsTraitStub implements ArrayAccess
-{
- use OptionsTrait;
-
- private ?string $option1;
- private ?int $option2;
- private ?string $file;
-
- public function __construct(array $options)
- {
- $this->option1 = $options['option1'] ?? null;
- $this->option2 = $options['option2'] ?? null;
- $this->setFile($options['file'] ?? null);
- }
- private function setFile(?string $file)
+ private function newStub(array $options)
{
- if (!is_null($file)) {
- self::validateFileExists($file);
- }
- $this->file = $file;
+ return new class($options) implements ArrayAccess {
+ use OptionsTrait;
+
+ private ?string $option1;
+ private ?int $option2;
+ private ?string $file;
+
+ public function __construct(array $options)
+ {
+ $this->option1 = $options['option1'] ?? null;
+ $this->option2 = $options['option2'] ?? null;
+ $this->setFile($options['file'] ?? null);
+ }
+
+ private function setFile(?string $file)
+ {
+ if (!is_null($file)) {
+ self::validateFileExists($file);
+ }
+ $this->file = $file;
+ }
+ };
}
}
diff --git a/tests/Unit/ProtobufBandaidTest.php b/tests/Unit/ProtobufBandaidTest.php
index 7b8f955e6..866623570 100644
--- a/tests/Unit/ProtobufBandaidTest.php
+++ b/tests/Unit/ProtobufBandaidTest.php
@@ -21,6 +21,8 @@
class ProtobufBandaidTest extends GeneratedTest
{
+ use TestTrait;
+
/**
* @dataProvider protobufMessageProvider
*/
@@ -31,6 +33,9 @@ public function testCompare($expected, $actual)
public function protobufMessageProvider()
{
+ $this->autoloadTestdata('generated');
+ $this->autoloadTestdata('generated/metadata', 'GPBMetadata\\' . __NAMESPACE__);
+
$msg1 = new MyMessage();
$msg2 = new Mymessage();
return [
diff --git a/tests/Unit/RequestBuilderTest.php b/tests/Unit/RequestBuilderTest.php
index 42b7ac241..a587be4f8 100644
--- a/tests/Unit/RequestBuilderTest.php
+++ b/tests/Unit/RequestBuilderTest.php
@@ -46,11 +46,11 @@ public function setUp(): void
{
$this->builder = new RequestBuilder(
'www.example.com',
- __DIR__ . '/testdata/test_service_rest_client_config.php'
+ __DIR__ . '/testdata/resources/test_service_rest_client_config.php'
);
$this->numericEnumsBuilder = new RequestBuilder(
'www.example.com',
- __DIR__ . '/testdata/test_numeric_enums_rest_client_config.php'
+ __DIR__ . '/testdata/resources/test_numeric_enums_rest_client_config.php'
);
}
@@ -447,7 +447,10 @@ public function testMethodWithOneOfInQueryString()
public function testMethodWithNumericEnumsQueryParam()
{
- $request = $this->numericEnumsBuilder->build(self::SERVICE_NAME . '/MethodWithNumericEnumsQueryParam', new MockRequestBody());
+ $request = $this->numericEnumsBuilder->build(
+ self::SERVICE_NAME . '/MethodWithNumericEnumsQueryParam',
+ new MockRequestBody()
+ );
$query = Query::parse($request->getUri()->getQuery());
$this->assertEquals('json;enum-encoding=int', $query['$alt']);
@@ -459,7 +462,9 @@ public function testThrowsExceptionWithNonMatchingFormat()
$message->setName('invalid/name/format');
$this->expectException(ValidationException::class);
- $this->expectExceptionMessage('Could not map bindings for test.interface.v1.api/MethodWithAdditionalBindings to any Uri template.');
+ $this->expectExceptionMessage(
+ 'Could not map bindings for test.interface.v1.api/MethodWithAdditionalBindings to any Uri template.'
+ );
$this->builder->build(self::SERVICE_NAME . '/MethodWithAdditionalBindings', $message);
}
@@ -469,7 +474,9 @@ public function testThrowsExceptionWithNonExistantMethod()
$message = new MockRequestBody();
$this->expectException(ValidationException::class);
- $this->expectExceptionMessage('Failed to build request, as the provided path (myResource/doesntExist) was not found in the configuration.');
+ $this->expectExceptionMessage(
+ 'Failed to build request, as the provided path (myResource/doesntExist) was not found in the configuration.'
+ );
$this->builder->build('myResource/doesntExist', $message);
}
diff --git a/tests/Unit/ResourceHelperTraitTest.php b/tests/Unit/ResourceHelperTraitTest.php
index ce2bd1981..612356167 100644
--- a/tests/Unit/ResourceHelperTraitTest.php
+++ b/tests/Unit/ResourceHelperTraitTest.php
@@ -38,29 +38,61 @@
class ResourceHelperTraitTest extends TestCase
{
+ private $stub;
+
+ public function setUp(): void
+ {
+ $this->stub = new class() {
+ use ResourceHelperTrait;
+
+ const CONFIG_PATH = __DIR__ . '/testdata/resources/test_service_descriptor_config.php';
+ const SERVICE_NAME = 'test.interface.v1.api';
+
+ private static function getClientDefaults()
+ {
+ return ['descriptorsConfigPath' => self::CONFIG_PATH];
+ }
+
+ public static function parseName($formattedName, $template = null)
+ {
+ return self::parseFormattedName($formattedName, $template);
+ }
+
+ public static function testRegisterPathTemplates()
+ {
+ self::registerPathTemplates();
+ return self::$templateMap;
+ }
+
+ public static function testGetPathTemplate($key)
+ {
+ return self::getPathTemplate($key);
+ }
+ };
+ }
public function testRegisterPathTemplates()
{
- $got = ResourceHelperTraitStub::testRegisterPathTemplates();
+ $got = $this->stub::testRegisterPathTemplates();
$this->assertEquals(count($got), 4);
$this->assertTrue($got['project'] instanceof PathTemplate);
}
public function testGetPathTemplate()
{
- $got = ResourceHelperTraitStub::testGetPathTemplate('project');
+ $got = $this->stub::testGetPathTemplate('project');
$this->assertNotNull($got);
$this->assertTrue($got instanceof PathTemplate);
}
public function testGetPathTemplateNull()
{
- $got = ResourceHelperTraitStub::testGetPathTemplate('does_not_exist');
+ $got = $this->stub::testGetPathTemplate('does_not_exist');
$this->assertNull($got);
}
public function testParseName()
{
- $got = ResourceHelperTraitStub::parseName('projects/abc123', 'project');
+ $got = $this->stub::parseName('projects/abc123', 'project');
$this->assertEquals(count($got), 1);
$this->assertEquals($got['project'], 'abc123');
}
@@ -70,7 +102,7 @@ public function testParseNameInvalidTemplate()
$this->expectException(ValidationException::class);
$this->expectExceptionMessage('Template name does_not_exist does not exist');
- ResourceHelperTraitStub::parseName('projects/abc123', 'does_not_exist');
+ $this->stub::parseName('projects/abc123', 'does_not_exist');
}
public function testParseNameNoMatchingPattern()
@@ -78,36 +110,6 @@ public function testParseNameNoMatchingPattern()
$this->expectException(ValidationException::class);
$this->expectExceptionMessage('Input did not match any known format. Input: no/matching/pattern');
- ResourceHelperTraitStub::parseName('no/matching/pattern');
- }
-
-}
-
-class ResourceHelperTraitStub
-{
- use ResourceHelperTrait;
-
- const CONFIG_PATH = __DIR__ . '/testdata/test_service_descriptor_config.php';
- const SERVICE_NAME = 'test.interface.v1.api';
-
- private static function getClientDefaults()
- {
- return ['descriptorsConfigPath' => self::CONFIG_PATH];
- }
-
- public static function parseName($formattedName, $template = null)
- {
- return self::parseFormattedName($formattedName, $template);
- }
-
- public static function testRegisterPathTemplates()
- {
- self::registerPathTemplates();
- return self::$templateMap;
- }
-
- public static function testGetPathTemplate($key)
- {
- return self::getPathTemplate($key);
+ $this->stub::parseName('no/matching/pattern');
}
}
diff --git a/tests/Unit/ResourceTemplate/ParserTest.php b/tests/Unit/ResourceTemplate/ParserTest.php
index 6452af987..e3a479fef 100644
--- a/tests/Unit/ResourceTemplate/ParserTest.php
+++ b/tests/Unit/ResourceTemplate/ParserTest.php
@@ -75,16 +75,16 @@ public function testParseBasicSegments()
$this->testParseSegments(
'foo/bar/baz',
[self::literalSegment('foo'),
- self::literalSegment('bar'),
- self::literalSegment('baz')]
+ self::literalSegment('bar'),
+ self::literalSegment('baz')]
);
$this->testParseSegments(
'foos/{foo}/bars/{bar}',
[self::literalSegment('foos'),
- self::variableSegment('foo', new RelativeResourceTemplate('*')),
- self::literalSegment('bars'),
- self::variableSegment('bar', new RelativeResourceTemplate('*'))]
+ self::variableSegment('foo', new RelativeResourceTemplate('*')),
+ self::literalSegment('bars'),
+ self::variableSegment('bar', new RelativeResourceTemplate('*'))]
);
}
@@ -93,29 +93,29 @@ public function testParseBasicNonSlashSeparators()
$this->testParseSegments(
'foos/{foo}_{oof}',
[self::literalSegment('foos'),
- self::variableSegment('foo', new RelativeResourceTemplate('*'), '_'),
- self::variableSegment('oof', new RelativeResourceTemplate('*'))]
+ self::variableSegment('foo', new RelativeResourceTemplate('*'), '_'),
+ self::variableSegment('oof', new RelativeResourceTemplate('*'))]
);
$this->testParseSegments(
'foos/{foo}-{oof}',
[self::literalSegment('foos'),
- self::variableSegment('foo', new RelativeResourceTemplate('*'), '-'),
- self::variableSegment('oof', new RelativeResourceTemplate('*'))]
+ self::variableSegment('foo', new RelativeResourceTemplate('*'), '-'),
+ self::variableSegment('oof', new RelativeResourceTemplate('*'))]
);
$this->testParseSegments(
'foos/{foo}~{oof}',
[self::literalSegment('foos'),
- self::variableSegment('foo', new RelativeResourceTemplate('*'), '~'),
- self::variableSegment('oof', new RelativeResourceTemplate('*'))]
+ self::variableSegment('foo', new RelativeResourceTemplate('*'), '~'),
+ self::variableSegment('oof', new RelativeResourceTemplate('*'))]
);
$this->testParseSegments(
'foos/{foo}.{oof}',
[self::literalSegment('foos'),
- self::variableSegment('foo', new RelativeResourceTemplate('*'), '.'),
- self::variableSegment('oof', new RelativeResourceTemplate('*'))]
+ self::variableSegment('foo', new RelativeResourceTemplate('*'), '.'),
+ self::variableSegment('oof', new RelativeResourceTemplate('*'))]
);
}
@@ -124,29 +124,29 @@ public function testParseMultipleNonSlashSeparators()
$this->testParseSegments(
'foos/{foo}_{oof}-{bar}.{baz}~{car}',
[self::literalSegment('foos'),
- self::variableSegment('foo', new RelativeResourceTemplate('*'), '_'),
- self::variableSegment('oof', new RelativeResourceTemplate('*'), '-'),
- self::variableSegment('bar', new RelativeResourceTemplate('*'), '.'),
- self::variableSegment('baz', new RelativeResourceTemplate('*'), '~'),
- self::variableSegment('car', new RelativeResourceTemplate('*'))]
+ self::variableSegment('foo', new RelativeResourceTemplate('*'), '_'),
+ self::variableSegment('oof', new RelativeResourceTemplate('*'), '-'),
+ self::variableSegment('bar', new RelativeResourceTemplate('*'), '.'),
+ self::variableSegment('baz', new RelativeResourceTemplate('*'), '~'),
+ self::variableSegment('car', new RelativeResourceTemplate('*'))]
);
$this->testParseSegments(
'foos/{foo}.{oof}_{bar}.{car}',
[self::literalSegment('foos'),
- self::variableSegment('foo', new RelativeResourceTemplate('*'), '.'),
- self::variableSegment('oof', new RelativeResourceTemplate('*'), '_'),
- self::variableSegment('bar', new RelativeResourceTemplate('*'), '.'),
- self::variableSegment('car', new RelativeResourceTemplate('*'))]
+ self::variableSegment('foo', new RelativeResourceTemplate('*'), '.'),
+ self::variableSegment('oof', new RelativeResourceTemplate('*'), '_'),
+ self::variableSegment('bar', new RelativeResourceTemplate('*'), '.'),
+ self::variableSegment('car', new RelativeResourceTemplate('*'))]
);
$this->testParseSegments(
'foos/{foo}-{oof}.{bar}~{car}',
[self::literalSegment('foos'),
- self::variableSegment('foo', new RelativeResourceTemplate('*'), '-'),
- self::variableSegment('oof', new RelativeResourceTemplate('*'), '.'),
- self::variableSegment('bar', new RelativeResourceTemplate('*'), '~'),
- self::variableSegment('car', new RelativeResourceTemplate('*'))]
+ self::variableSegment('foo', new RelativeResourceTemplate('*'), '-'),
+ self::variableSegment('oof', new RelativeResourceTemplate('*'), '.'),
+ self::variableSegment('bar', new RelativeResourceTemplate('*'), '~'),
+ self::variableSegment('car', new RelativeResourceTemplate('*'))]
);
}
@@ -155,26 +155,26 @@ public function testParseNonSlashSeparatorsWithParents()
$this->testParseSegments(
'foos/{foo}_{oof}-{bar}.{baz}~{car}/projects/{project}/locations/{state}~{city}.{cell}',
[self::literalSegment('foos'),
- self::variableSegment('foo', new RelativeResourceTemplate('*'), '_'),
- self::variableSegment('oof', new RelativeResourceTemplate('*'), '-'),
- self::variableSegment('bar', new RelativeResourceTemplate('*'), '.'),
- self::variableSegment('baz', new RelativeResourceTemplate('*'), '~'),
- self::variableSegment('car', new RelativeResourceTemplate('*')),
- self::literalSegment('projects'),
- self::variableSegment('project', new RelativeResourceTemplate('*')),
- self::literalSegment('locations'),
- self::variableSegment('state', new RelativeResourceTemplate('*'), '~'),
- self::variableSegment('city', new RelativeResourceTemplate('*'), '.'),
- self::variableSegment('cell', new RelativeResourceTemplate('*'))]
+ self::variableSegment('foo', new RelativeResourceTemplate('*'), '_'),
+ self::variableSegment('oof', new RelativeResourceTemplate('*'), '-'),
+ self::variableSegment('bar', new RelativeResourceTemplate('*'), '.'),
+ self::variableSegment('baz', new RelativeResourceTemplate('*'), '~'),
+ self::variableSegment('car', new RelativeResourceTemplate('*')),
+ self::literalSegment('projects'),
+ self::variableSegment('project', new RelativeResourceTemplate('*')),
+ self::literalSegment('locations'),
+ self::variableSegment('state', new RelativeResourceTemplate('*'), '~'),
+ self::variableSegment('city', new RelativeResourceTemplate('*'), '.'),
+ self::variableSegment('cell', new RelativeResourceTemplate('*'))]
);
$this->testParseSegments(
'customers/{customer_id}/userLocationViews/{country_criterion_id}~{is_targeting_location}',
[self::literalSegment('customers'),
- self::variableSegment('customer_id', new RelativeResourceTemplate('*')),
- self::literalSegment('userLocationViews'),
- self::variableSegment('country_criterion_id', new RelativeResourceTemplate('*'), '~'),
- self::variableSegment('is_targeting_location', new RelativeResourceTemplate('*'))]
+ self::variableSegment('customer_id', new RelativeResourceTemplate('*')),
+ self::literalSegment('userLocationViews'),
+ self::variableSegment('country_criterion_id', new RelativeResourceTemplate('*'), '~'),
+ self::variableSegment('is_targeting_location', new RelativeResourceTemplate('*'))]
);
}
diff --git a/tests/Unit/ResourceTemplate/RelativeResourceTemplateTest.php b/tests/Unit/ResourceTemplate/RelativeResourceTemplateTest.php
index 31d48d663..d29142eb8 100644
--- a/tests/Unit/ResourceTemplate/RelativeResourceTemplateTest.php
+++ b/tests/Unit/ResourceTemplate/RelativeResourceTemplateTest.php
@@ -205,19 +205,29 @@ public function matchData()
['$0' => '{}!@#$%^&*()+=[]\|`~-_'],
],
[
- 'foos/{foo}_{oof}',
- 'foos/imafoo_thisisanoof',
- ['foo' => 'imafoo', 'oof' => 'thisisanoof'],
- ],
- [
- 'foos/{foo}.{oof}_{bar}.{car}',
- 'foos/food.doof_mars.porsche',
- ['foo' => 'food', 'oof' => 'doof', 'bar' => 'mars', 'car' => 'porsche'],
- ],
- [
- 'foos/{foo}_{oof}-{bar}.{baz}~{car}/projects/{project}/locations/{state}~{city}.{cell}',
- 'foos/food_doof-mars.bazz~porsche/projects/someProject/locations/wa~sea.fre3',
- ['foo' => 'food', 'oof' => 'doof', 'bar' => 'mars', 'baz' => 'bazz', 'car' => 'porsche', 'project' => 'someProject', 'state' => 'wa', 'city' => 'sea', 'cell' => 'fre3'],
+ 'foos/{foo}_{oof}',
+ 'foos/imafoo_thisisanoof',
+ ['foo' => 'imafoo', 'oof' => 'thisisanoof'],
+ ],
+ [
+ 'foos/{foo}.{oof}_{bar}.{car}',
+ 'foos/food.doof_mars.porsche',
+ ['foo' => 'food', 'oof' => 'doof', 'bar' => 'mars', 'car' => 'porsche'],
+ ],
+ [
+ 'foos/{foo}_{oof}-{bar}.{baz}~{car}/projects/{project}/locations/{state}~{city}.{cell}',
+ 'foos/food_doof-mars.bazz~porsche/projects/someProject/locations/wa~sea.fre3',
+ [
+ 'foo' => 'food',
+ 'oof' => 'doof',
+ 'bar' => 'mars',
+ 'baz' => 'bazz',
+ 'car' => 'porsche',
+ 'project' => 'someProject',
+ 'state' => 'wa',
+ 'city' => 'sea',
+ 'cell' => 'fre3'
+ ],
],
];
}
@@ -325,8 +335,8 @@ public function invalidRenderData()
[
'buckets/{hello=*}',
['hello' => ''], // Invalid binding
- "Error rendering 'buckets/{hello=*}': expected binding 'hello' to match segment '{hello=*}', instead got ''\n" .
- "Provided bindings: Array\n" .
+ "Error rendering 'buckets/{hello=*}': expected binding 'hello' to match segment '{hello=*}', instead " .
+ "got ''\nProvided bindings: Array\n" .
"(\n" .
" [hello] => \n" .
")\n",
@@ -334,8 +344,8 @@ public function invalidRenderData()
[
'buckets/{hello=*}',
['hello' => null], // Invalid binding
- "Error rendering 'buckets/{hello=*}': expected binding 'hello' to match segment '{hello=*}', instead got null\n" .
- "Provided bindings: Array\n" .
+ "Error rendering 'buckets/{hello=*}': expected binding 'hello' to match segment '{hello=*}', instead " .
+ "got null\nProvided bindings: Array\n" .
"(\n" .
" [hello] => \n" .
")\n",
@@ -343,8 +353,8 @@ public function invalidRenderData()
[
'buckets/*/objects/**',
['$0' => 'foo', '$1' => ''], // Invalid binding
- "Error rendering 'buckets/*/objects/**': expected binding '$1' to match segment '**', instead got ''\n" .
- "Provided bindings: Array\n" .
+ "Error rendering 'buckets/*/objects/**': expected binding '$1' to match segment '**', instead got " .
+ "''\nProvided bindings: Array\n" .
"(\n" .
" [$0] => foo\n" .
" [$1] => \n" .
@@ -353,8 +363,8 @@ public function invalidRenderData()
[
'buckets/*/objects/**',
['$0' => 'foo', '$1' => null], // Invalid binding
- "Error rendering 'buckets/*/objects/**': expected binding '$1' to match segment '**', instead got null\n" .
- "Provided bindings: Array\n" .
+ "Error rendering 'buckets/*/objects/**': expected binding '$1' to match segment '**', instead got " .
+ "null\nProvided bindings: Array\n" .
"(\n" .
" [$0] => foo\n" .
" [$1] => \n" .
diff --git a/tests/Unit/RetrySettingsTest.php b/tests/Unit/RetrySettingsTest.php
index 986f7c542..4d44ca373 100644
--- a/tests/Unit/RetrySettingsTest.php
+++ b/tests/Unit/RetrySettingsTest.php
@@ -41,13 +41,13 @@ class RetrySettingsTest extends TestCase
private static function buildInputConfig()
{
- $contents = file_get_contents(__DIR__ . '/testdata/test_service_client_config.json');
+ $contents = file_get_contents(__DIR__ . '/testdata/resources/test_service_client_config.json');
return json_decode($contents, true);
}
private static function buildInvalidInputConfig()
{
- $contents = file_get_contents(__DIR__ . '/testdata/test_service_invalid_client_config.json');
+ $contents = file_get_contents(__DIR__ . '/testdata/resources/test_service_invalid_client_config.json');
return json_decode($contents, true);
}
@@ -274,10 +274,14 @@ public function retrySettingsProvider()
[
// Test with a custom retry function
[
- 'retryFunction' => function ($ex, $options) {return true;}
+ 'retryFunction' => function ($ex, $options) {
+ return true;
+ }
] + $defaultSettings,
[
- 'retryFunction' => function ($ex, $options) {return true;}
+ 'retryFunction' => function ($ex, $options) {
+ return true;
+ }
] + $defaultExpectedValues
],
[
@@ -369,10 +373,14 @@ public function withRetrySettingsProvider()
// Test with a custom retry function
$defaultSettings,
[
- 'retryFunction' => function ($ex, $options) {return true;}
+ 'retryFunction' => function ($ex, $options) {
+ return true;
+ }
],
[
- 'retryFunction' => function ($ex, $options) {return true;}
+ 'retryFunction' => function ($ex, $options) {
+ return true;
+ }
] + $defaultExpectedValues
],
[
diff --git a/tests/Unit/ServerStreamTest.php b/tests/Unit/ServerStreamTest.php
index 30b90baea..a792563d1 100644
--- a/tests/Unit/ServerStreamTest.php
+++ b/tests/Unit/ServerStreamTest.php
@@ -230,6 +230,7 @@ public function testReadCallsLogger()
$stream = new ServerStream($call, logger: $logger->reveal());
// Loop to read the responses
- foreach ($stream->readAll() as $response) {}
+ foreach ($stream->readAll() as $response) {
+ }
}
}
diff --git a/tests/Unit/TestTrait.php b/tests/Unit/TestTrait.php
index 34ab0c10b..82132a51b 100644
--- a/tests/Unit/TestTrait.php
+++ b/tests/Unit/TestTrait.php
@@ -36,6 +36,7 @@
use Google\ApiCore\Testing\MockResponse;
use Google\Protobuf\Any;
use Google\Rpc\Status;
+use PDO;
trait TestTrait
{
@@ -126,10 +127,19 @@ public static function requiresGrpcExtension()
}
}
- public static function requiresPhp7()
+ private static function autoloadTestdata(string $dir, string $namespace = __NAMESPACE__)
{
- if (version_compare(phpversion(), '7.0', '<')) {
- self::markTestSkipped('This test requires PHP 7.0 or above.');
+ // This is required for tests to pass on Windows with PHP 8.1
+ // @TODO remove this once we drop PHP 8.1 support
+ if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN' && PHP_VERSION_ID < 80200) {
+ self::markTestSkipped('Skip on Windows + PHP 8.1 to avoid gRPC shutdown crash');
}
+
+ // add mocks to autoloader
+ $loader = file_exists(__DIR__ . '/../../../vendor/autoload.php')
+ ? require __DIR__ . '/../../../vendor/autoload.php'
+ : require __DIR__ . '/../../vendor/autoload.php';
+
+ $loader->addPsr4($namespace . '\\', __DIR__ . '/testdata/' . $dir);
}
}
diff --git a/tests/Unit/Transport/GrpcFallbackTransportTest.php b/tests/Unit/Transport/GrpcFallbackTransportTest.php
index 96a2000fa..205f26ab5 100644
--- a/tests/Unit/Transport/GrpcFallbackTransportTest.php
+++ b/tests/Unit/Transport/GrpcFallbackTransportTest.php
@@ -91,7 +91,7 @@ public function testStartUnaryCall($apiEndpoint, $requestMessage)
->setName('hello')
->setNumber(15);
- $httpHandler = function (RequestInterface $request, array $options = []) use ($expectedResponse, $expectedRequest) {
+ $httpHandler = function (RequestInterface $request) use ($expectedResponse, $expectedRequest) {
$this->assertEquals($expectedRequest, $request);
return Create::promiseFor(
diff --git a/tests/Unit/Transport/GrpcTransportTest.php b/tests/Unit/Transport/GrpcTransportTest.php
index 53ef2a1d3..6eafcb667 100644
--- a/tests/Unit/Transport/GrpcTransportTest.php
+++ b/tests/Unit/Transport/GrpcTransportTest.php
@@ -50,6 +50,7 @@
use Grpc\CallInvoker;
use Grpc\ChannelCredentials;
use Grpc\ClientStreamingCall;
+use Grpc\Interceptor;
use Grpc\ServerStreamingCall;
use Grpc\UnaryCall;
use GuzzleHttp\Promise\Promise;
@@ -443,7 +444,7 @@ public function testAudienceOption()
public function testClientCertSourceOptionValid()
{
$mockClientCertSource = function () {
- return 'MOCK_CERT_SOURCE';
+ return ['MOCK_KEY', 'MOCK_CERT'];
};
$transport = GrpcTransport::build(
'address.com:123',
@@ -455,8 +456,6 @@ public function testClientCertSourceOptionValid()
public function testClientCertSourceOptionInvalid()
{
- self::requiresPhp7();
-
$mockClientCertSource = 'foo';
$this->expectException(TypeError::class);
@@ -544,6 +543,48 @@ public function buildInvalidData()
*/
public function testExperimentalInterceptors($callType, $interceptor)
{
+ $mockCallInvoker = new class($this->buildMockCallForInterceptor($callType)) {
+ private $called = false;
+ private $mockCall;
+
+ public function __construct($mockCall)
+ {
+ $this->mockCall = $mockCall;
+ }
+
+ public function createChannelFactory($hostname, $opts)
+ {
+ // no-op
+ }
+
+ public function UnaryCall($channel, $method, $deserialize, $options)
+ {
+ $this->called = true;
+ return $this->mockCall;
+ }
+
+ public function ServerStreamingCall($channel, $method, $deserialize, $options)
+ {
+ $this->called = true;
+ return $this->mockCall;
+ }
+
+ public function ClientStreamingCall($channel, $method, $deserialize, $options)
+ {
+ // no-op
+ }
+
+ public function BidiStreamingCall($channel, $method, $deserialize, $options)
+ {
+ // no-op
+ }
+
+ public function wasCalled()
+ {
+ return $this->called;
+ }
+ };
+
$transport = new GrpcTransport(
'example.com',
[
@@ -553,8 +594,6 @@ public function testExperimentalInterceptors($callType, $interceptor)
[$interceptor]
);
- $mockCallInvoker = new MockCallInvoker($this->buildMockCallForInterceptor($callType));
-
$r = new \ReflectionProperty(BaseStub::class, 'call_invoker');
$r->setValue(
$transport,
@@ -577,18 +616,28 @@ public function testExperimentalInterceptors($callType, $interceptor)
public function interceptorDataProvider()
{
+ $this->autoloadTestdata('mocks', __NAMESPACE__);
+
+ $deprecatedInterceptors = (new \ReflectionClass(Interceptor::class))
+ ->getMethod('interceptUnaryUnary')
+ ->getParameters()[3]
+ ->getName() === 'metadata';
+
+ $interceptor = $deprecatedInterceptors ? new DeprecatedTestInterceptor(): new TestInterceptor();
+ $unaryInterceptor = $deprecatedInterceptors ? new DeprecatedTestUnaryInterceptor(): new TestUnaryInterceptor();
+
return [
[
UnaryCall::class,
- new TestUnaryInterceptor()
+ $unaryInterceptor
],
[
UnaryCall::class,
- new TestInterceptor()
+ $interceptor
],
[
ServerStreamingCall::class,
- new TestInterceptor()
+ $interceptor
]
];
}
@@ -616,46 +665,3 @@ private function buildMockCallForInterceptor($callType)
return $mockCall->reveal();
}
}
-
-class MockCallInvoker implements CallInvoker
-{
- private $called = false;
- private $mockCall;
-
- public function __construct($mockCall)
- {
- $this->mockCall = $mockCall;
- }
-
- public function createChannelFactory($hostname, $opts)
- {
- // no-op
- }
-
- public function UnaryCall($channel, $method, $deserialize, $options)
- {
- $this->called = true;
- return $this->mockCall;
- }
-
- public function ServerStreamingCall($channel, $method, $deserialize, $options)
- {
- $this->called = true;
- return $this->mockCall;
- }
-
- public function ClientStreamingCall($channel, $method, $deserialize, $options)
- {
- // no-op
- }
-
- public function BidiStreamingCall($channel, $method, $deserialize, $options)
- {
- // no-op
- }
-
- public function wasCalled()
- {
- return $this->called;
- }
-}
diff --git a/tests/Unit/Transport/Rest/JsonStreamDecoderTest.php b/tests/Unit/Transport/Rest/JsonStreamDecoderTest.php
index 4b6e25b19..04a761940 100644
--- a/tests/Unit/Transport/Rest/JsonStreamDecoderTest.php
+++ b/tests/Unit/Transport/Rest/JsonStreamDecoderTest.php
@@ -115,7 +115,9 @@ public function buildResponseStreams()
]),
];
- $stream = function ($data) {return $this->messagesToStream($data);};
+ $stream = function ($data) {
+ return $this->messagesToStream($data);
+ };
return [
[$operations, Operation::class, $stream($operations), /*readChunkSizeBytes*/ 10],
[$operations, Operation::class, $stream($operations), /*readChunkSizeBytes*/ 1024],
@@ -178,7 +180,6 @@ public function testJsonStreamDecoderBadClose($payload)
try {
// Just iterating the stream will throw the exception
foreach ($decoder->decode() as $op) {
-
}
} finally {
$stream->close();
diff --git a/tests/Unit/Transport/RestTransportTest.php b/tests/Unit/Transport/RestTransportTest.php
index 2a659473e..b4daa40c6 100644
--- a/tests/Unit/Transport/RestTransportTest.php
+++ b/tests/Unit/Transport/RestTransportTest.php
@@ -428,7 +428,7 @@ public function buildDataRest()
{
$uri = 'address.com';
$apiEndpoint = "$uri:443";
- $restConfigPath = __DIR__ . '/../testdata/test_service_rest_client_config.php';
+ $restConfigPath = __DIR__ . '/../testdata/resources/test_service_rest_client_config.php';
$requestBuilder = new RequestBuilder($apiEndpoint, $restConfigPath);
$httpHandler = [HttpHandlerFactory::build(), 'async'];
return [
@@ -454,7 +454,7 @@ public function testClientCertSourceOptionValid()
};
$transport = RestTransport::build(
'address.com:123',
- __DIR__ . '/../testdata/test_service_rest_client_config.php',
+ __DIR__ . '/../testdata/resources/test_service_rest_client_config.php',
['clientCertSource' => $mockClientCertSource]
);
@@ -467,8 +467,6 @@ public function testClientCertSourceOptionValid()
public function testClientCertSourceOptionInvalid()
{
- self::requiresPhp7();
-
$mockClientCertSource = 'foo';
$this->expectException(TypeError::class);
@@ -476,7 +474,7 @@ public function testClientCertSourceOptionInvalid()
RestTransport::build(
'address.com:123',
- __DIR__ . '/../testdata/test_service_rest_client_config.php',
+ __DIR__ . '/../testdata/resources/test_service_rest_client_config.php',
['clientCertSource' => $mockClientCertSource]
);
}
@@ -493,7 +491,7 @@ public function testBuildInvalid($apiEndpoint, $restConfigPath, $args)
public function buildInvalidData()
{
- $restConfigPath = __DIR__ . '/../testdata/test_service_rest_client_config.php';
+ $restConfigPath = __DIR__ . '/../testdata/resources/test_service_rest_client_config.php';
return [
[
'addresswithtoo:many:segments',
diff --git a/tests/Unit/ValidationTraitTest.php b/tests/Unit/ValidationTraitTest.php
index 310d57757..869316a3d 100644
--- a/tests/Unit/ValidationTraitTest.php
+++ b/tests/Unit/ValidationTraitTest.php
@@ -27,7 +27,9 @@ class ValidationTraitTest extends TestCase
public function setUp(): void
{
- $this->stub = new ValidationTraitStub();
+ $this->stub = new class () {
+ use ValidationTrait;
+ };
}
public function testValidateMissingRequiredKey()
@@ -79,8 +81,3 @@ public function testValidateValidArrayWithNotNull()
$this->assertEquals($input, $arr);
}
}
-
-class ValidationTraitStub
-{
- use ValidationTrait;
-}
diff --git a/tests/Unit/testdata/json-key-file.json b/tests/Unit/testdata/creds/json-key-file.json
similarity index 100%
rename from tests/Unit/testdata/json-key-file.json
rename to tests/Unit/testdata/creds/json-key-file.json
diff --git a/tests/Unit/testdata/mtls/.secureConnect/context_aware_metadata.json b/tests/Unit/testdata/creds/mtls/.secureConnect/context_aware_metadata.json
similarity index 100%
rename from tests/Unit/testdata/mtls/.secureConnect/context_aware_metadata.json
rename to tests/Unit/testdata/creds/mtls/.secureConnect/context_aware_metadata.json
diff --git a/tests/Unit/MyMessage.php b/tests/Unit/testdata/generated/MyMessage.php
similarity index 100%
rename from tests/Unit/MyMessage.php
rename to tests/Unit/testdata/generated/MyMessage.php
diff --git a/metadata/Google/ApiCore/Tests/Unit/Example.php b/tests/Unit/testdata/generated/metadata/Example.php
similarity index 100%
rename from metadata/Google/ApiCore/Tests/Unit/Example.php
rename to tests/Unit/testdata/generated/metadata/Example.php
diff --git a/tests/Unit/testdata/mocks/CustomOperation/CancelOperationRequest.php b/tests/Unit/testdata/mocks/CustomOperation/CancelOperationRequest.php
new file mode 100644
index 000000000..f0b168fae
--- /dev/null
+++ b/tests/Unit/testdata/mocks/CustomOperation/CancelOperationRequest.php
@@ -0,0 +1,20 @@
+name = $name;
+ $request->arg2 = $arg2;
+ $request->arg3 = $arg3;
+
+ return $request;
+ }
+}
diff --git a/tests/Unit/testdata/mocks/CustomOperation/Client/NewSurfaceCustomOperationClient.php b/tests/Unit/testdata/mocks/CustomOperation/Client/NewSurfaceCustomOperationClient.php
new file mode 100644
index 000000000..8128fc840
--- /dev/null
+++ b/tests/Unit/testdata/mocks/CustomOperation/Client/NewSurfaceCustomOperationClient.php
@@ -0,0 +1,23 @@
+name = $name;
+ $request->arg2 = $arg2;
+ $request->arg3 = $arg3;
+
+ return $request;
+ }
+}
diff --git a/tests/Unit/testdata/mocks/CustomOperation/GetOperationRequest.php b/tests/Unit/testdata/mocks/CustomOperation/GetOperationRequest.php
new file mode 100644
index 000000000..7e2783ccb
--- /dev/null
+++ b/tests/Unit/testdata/mocks/CustomOperation/GetOperationRequest.php
@@ -0,0 +1,20 @@
+name = $name;
+ $request->arg2 = $arg2;
+ $request->arg3 = $arg3;
+
+ return $request;
+ }
+}
diff --git a/tests/bootstrap_deprecated_grpc_interceptors.php b/tests/Unit/testdata/mocks/DeprecatedTestInterceptor.php
similarity index 56%
rename from tests/bootstrap_deprecated_grpc_interceptors.php
rename to tests/Unit/testdata/mocks/DeprecatedTestInterceptor.php
index 3d7b2eec7..cc625ae44 100644
--- a/tests/bootstrap_deprecated_grpc_interceptors.php
+++ b/tests/Unit/testdata/mocks/DeprecatedTestInterceptor.php
@@ -2,25 +2,9 @@
namespace Google\ApiCore\Tests\Unit\Transport;
-use Google\ApiCore\Transport\Grpc\UnaryInterceptorInterface;
use Grpc\Interceptor;
-class TestUnaryInterceptor implements UnaryInterceptorInterface
-{
- public function interceptUnaryUnary(
- $method,
- $argument,
- $deserialize,
- array $metadata,
- array $options,
- callable $continuation
- ) {
- $options['test-interceptor-insert'] = 'inserted-value';
- return $continuation($method, $argument, $deserialize, $metadata, $options);
- }
-}
-
-class TestInterceptor extends Interceptor
+class DeprecatedTestInterceptor extends Interceptor
{
public function interceptUnaryUnary(
$method,
@@ -28,7 +12,7 @@ public function interceptUnaryUnary(
$deserialize,
array $metadata = [],
array $options = [],
- $continuation
+ $continuation = null
) {
$options['test-interceptor-insert'] = 'inserted-value';
return $continuation($method, $argument, $deserialize, $metadata, $options);
@@ -40,7 +24,7 @@ public function interceptUnaryStream(
$deserialize,
array $metadata = [],
array $options = [],
- $continuation
+ $continuation = null
) {
$options['test-interceptor-insert'] = 'inserted-value';
return $continuation($method, $argument, $deserialize, $metadata, $options);
diff --git a/tests/Unit/testdata/mocks/DeprecatedTestUnaryInterceptor.php b/tests/Unit/testdata/mocks/DeprecatedTestUnaryInterceptor.php
new file mode 100644
index 000000000..0f89fc2a0
--- /dev/null
+++ b/tests/Unit/testdata/mocks/DeprecatedTestUnaryInterceptor.php
@@ -0,0 +1,20 @@
+name = $name;
- $request->arg2 = $arg2;
- $request->arg3 = $arg3;
-
- return $request;
- }
-}
-
-class GetOperationRequest extends BaseOperationRequest
-{
-}
-
-class CancelOperationRequest extends BaseOperationRequest
-{
-}
-
-class DeleteOperationRequest extends BaseOperationRequest
-{
-}
diff --git a/tests/bootstrap.php b/tests/bootstrap.php
index 56c6f4c44..b1110074e 100644
--- a/tests/bootstrap.php
+++ b/tests/bootstrap.php
@@ -35,19 +35,6 @@
use Google\ApiCore\Testing\MessageAwareArrayComparator;
use Google\ApiCore\Testing\ProtobufGPBEmptyComparator;
use Google\ApiCore\Testing\ProtobufMessageComparator;
-use Grpc\Interceptor;
-
-// This is a long line, but better not set some temporary variables that get picked up by something later
-if (
- (new \ReflectionClass(Interceptor::class))
- ->getMethod('interceptUnaryUnary')
- ->getParameters()[3]
- ->getName() === 'metadata'
-) {
- require_once __DIR__ . '/bootstrap_deprecated_grpc_interceptors.php';
-} else {
- require_once __DIR__ . '/bootstrap_grpc_interceptors.php';
-}
date_default_timezone_set('UTC');
ini_set('error_reporting', E_ALL);