From 736561356e2f1d00f859b246ef0ec09e045aced8 Mon Sep 17 00:00:00 2001 From: Brent Shaffer Date: Fri, 24 Sep 2021 11:26:01 -0700 Subject: [PATCH] feat: add TypedItem to allow for psr/cache:3 --- .github/CONTRIBUTING.md | 2 +- .github/actions/docs/sami.php | 2 +- .github/actions/unittest/entrypoint.sh | 19 - .github/actions/unittest/retry.php | 24 -- .github/workflows/docs.yml | 8 +- .github/workflows/tests.yml | 91 +---- CHANGELOG.md | 2 +- README.md | 16 +- composer.json | 14 +- src/AccessToken.php | 4 +- src/Cache/Item.php | 7 - src/Cache/MemoryCacheItemPool.php | 58 ++- src/Cache/SysVCacheItemPool.php | 34 +- src/Cache/TypedItem.php | 187 ++++++++++ src/OAuth2.php | 23 +- src/Subscriber/AuthTokenSubscriber.php | 136 ------- .../ScopedAccessTokenSubscriber.php | 180 ---------- src/Subscriber/SimpleSubscriber.php | 93 ----- tests/AccessTokenTest.php | 44 +-- tests/ApplicationDefaultCredentialsTest.php | 183 +++------- tests/BaseTest.php | 23 +- tests/Cache/ItemTest.php | 5 + tests/Cache/MemoryCacheItemPoolTest.php | 27 +- tests/Cache/SysVCacheItemPoolTest.php | 12 +- tests/Cache/sysv_cache_creator.php | 7 +- tests/CacheTraitTest.php | 9 +- .../AppIdentityCredentialsTest.php | 15 +- tests/Credentials/GCECredentialsTest.php | 26 +- tests/Credentials/IAMCredentialsTest.php | 13 +- .../ServiceAccountCredentialsTest.php | 148 ++++---- .../UserRefreshCredentialsTest.php | 46 +-- tests/CredentialsLoaderTest.php | 26 +- tests/FetchAuthTokenCacheTest.php | 48 +-- tests/GCECacheTest.php | 14 +- tests/HttpHandler/Guzzle5HttpHandlerTest.php | 240 ------------- tests/HttpHandler/Guzzle6HttpHandlerTest.php | 2 +- tests/HttpHandler/Guzzle7HttpHandlerTest.php | 2 +- tests/HttpHandler/HttpHandlerFactoryTest.php | 9 - tests/Middleware/AuthTokenMiddlewareTest.php | 17 +- .../ProxyAuthTokenMiddlewareTest.php | 4 +- .../ScopedAccessTokenMiddlewareTest.php | 20 +- tests/Middleware/SimpleMiddlewareTest.php | 35 +- tests/OAuth2Test.php | 162 +++------ tests/Subscriber/AuthTokenSubscriberTest.php | 335 ------------------ .../ScopedAccessTokenSubscriberTest.php | 256 ------------- tests/Subscriber/SimpleSubscriberTest.php | 76 ---- 46 files changed, 678 insertions(+), 2026 deletions(-) delete mode 100755 .github/actions/unittest/entrypoint.sh delete mode 100644 .github/actions/unittest/retry.php create mode 100644 src/Cache/TypedItem.php delete mode 100644 src/Subscriber/AuthTokenSubscriber.php delete mode 100644 src/Subscriber/ScopedAccessTokenSubscriber.php delete mode 100644 src/Subscriber/SimpleSubscriber.php delete mode 100644 tests/HttpHandler/Guzzle5HttpHandlerTest.php delete mode 100644 tests/Subscriber/AuthTokenSubscriberTest.php delete mode 100644 tests/Subscriber/ScopedAccessTokenSubscriberTest.php delete mode 100644 tests/Subscriber/SimpleSubscriberTest.php diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index 0cfb74b63..5cb644f2d 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -23,7 +23,7 @@ accept your pull requests. * Check that the issue has not already been reported. * Check that the issue has not already been fixed in the latest code - (a.k.a. `master`). + (a.k.a. `main`). * Be clear, concise and precise in your description of the problem. * Open an issue with a descriptive title and a summary in grammatically correct, complete sentences. diff --git a/.github/actions/docs/sami.php b/.github/actions/docs/sami.php index 5e5326622..df537ceef 100644 --- a/.github/actions/docs/sami.php +++ b/.github/actions/docs/sami.php @@ -16,7 +16,7 @@ $versions = GitVersionCollection::create($projectRoot) ->addFromTags('v1.*') - ->add('master', 'master branch'); + ->add('main', 'main branch'); return new Sami($iterator, [ 'title' => 'Google Auth Library for PHP API Reference', diff --git a/.github/actions/unittest/entrypoint.sh b/.github/actions/unittest/entrypoint.sh deleted file mode 100755 index a300c131c..000000000 --- a/.github/actions/unittest/entrypoint.sh +++ /dev/null @@ -1,19 +0,0 @@ -#!/bin/sh -l - -apt-get update && \ -apt-get install -y --no-install-recommends \ - git \ - zip \ - curl \ - unzip \ - wget - -curl --silent --show-error https://getcomposer.org/installer | php -php composer.phar self-update - -echo "---Installing dependencies ---" -echo "${composerargs}" -php $(dirname $0)/retry.php "php composer.phar update $composerargs" - -echo "---Running unit tests ---" -vendor/bin/phpunit diff --git a/.github/actions/unittest/retry.php b/.github/actions/unittest/retry.php deleted file mode 100644 index c6525abe8..000000000 --- a/.github/actions/unittest/retry.php +++ /dev/null @@ -1,24 +0,0 @@ - 0) { - sleep($delay); - return retry($f, $delay, $retries - 1); - } else { - throw $e; - } - } -} - -retry(function () { - global $argv; - passthru($argv[1], $ret); - - if ($ret != 0) { - throw new \Exception('err'); - } -}, 1); diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index d508d6773..908440591 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -2,24 +2,24 @@ name: Generate Documentation on: push: branches: - - master + - main tags: - "*" jobs: docs: name: "Generate Project Documentation" - runs-on: ubuntu-16.04 + runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v2 + uses: actions/checkout@v3 - run: git fetch --depth=1 origin +refs/tags/*:refs/tags/* - name: Setup PHP uses: shivammathur/setup-php@v2 with: php-version: 7.3 - name: Install Dependencies - uses: nick-invision/retry@v1 + uses: nick-invision/retry@v2 with: timeout_minutes: 10 max_attempts: 3 diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 284d3c045..c1f2b3f3c 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -1,57 +1,44 @@ name: Test Suite on: push: - branches: - - master + branches: [ main ] pull_request: jobs: test: - runs-on: ${{matrix.operating-system}} + runs-on: ubuntu-latest strategy: matrix: - operating-system: [ ubuntu-latest ] - php: [ "5.6", "7.0", "7.1", "7.2", "7.3", "7.4", "8.0" ] + php: [ "7.1", "7.2", "7.3", "7.4", "8.0", "8.1" ] name: PHP ${{matrix.php }} Unit Test steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Setup PHP uses: shivammathur/setup-php@v2 with: php-version: ${{ matrix.php }} - - if: ${{ matrix.php != '8.0' }} - name: Install Dependencies - uses: nick-invision/retry@v1 + - name: Install Dependencies + uses: nick-invision/retry@v2 with: timeout_minutes: 10 max_attempts: 3 command: composer install - - if: ${{ matrix.php == '8.0' }} - name: Install Dependencies (PHP 8.0) - uses: nick-invision/retry@v1 - with: - timeout_minutes: 10 - max_attempts: 3 - command: | - composer remove --dev --ignore-platform-reqs phpunit/phpunit - composer require --dev --ignore-platform-reqs --update-with-all-dependencies phpunit/phpunit:^7 - name: Run Script run: vendor/bin/phpunit test_lowest: - runs-on: ${{matrix.operating-system}} + runs-on: ubuntu-latest strategy: matrix: - operating-system: [ ubuntu-latest ] - php: [ "5.6", "7.0", "7.1", "7.2" ] + php: [ "7.1", "7.2" ] name: PHP ${{matrix.php }} Unit Test Prefer Lowest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Setup PHP uses: shivammathur/setup-php@v2 with: php-version: ${{ matrix.php }} - name: Install Dependencies - uses: nick-invision/retry@v1 + uses: nick-invision/retry@v2 with: timeout_minutes: 10 max_attempts: 3 @@ -62,79 +49,33 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - operating-system: [ ubuntu-latest ] - php: [ "5.6", "7.2" ] + php: [ "7.2" ] name: PHP ${{ matrix.php }} Unit Test Guzzle 6 steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Setup PHP uses: shivammathur/setup-php@v2 with: php-version: ${{ matrix.php }} - name: Install Dependencies - uses: nick-invision/retry@v1 + uses: nick-invision/retry@v2 with: timeout_minutes: 10 max_attempts: 3 command: composer require guzzlehttp/guzzle:^6 && composer update - name: Run Script run: vendor/bin/phpunit - # use dockerfiles for oooooolllllldddd versions of php, setup-php times out for those. - test_php55: - name: "PHP 5.5 Unit Test" - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@v2 - - name: Run Unit Tests - uses: docker://php:5.5-cli - with: - entrypoint: ./.github/actions/unittest/entrypoint.sh - test_php55_lowest: - name: "PHP 5.5 Unit Test Prefer Lowest" - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@v2 - - name: Run Unit Tests - uses: docker://php:5.5-cli - env: - composerargs: "--prefer-lowest" - with: - entrypoint: ./.github/actions/unittest/entrypoint.sh - test_php54: - name: "PHP 5.4 Unit Test" - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@v2 - - name: Run Unit Tests - uses: docker://php:5.4-cli - with: - entrypoint: ./.github/actions/unittest/entrypoint.sh - test_php54_lowest: - name: "PHP 5.4 Unit Test Prefer Lowest" - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@v2 - - name: Run Unit Tests - uses: docker://php:5.4-cli - env: - composerargs: "--prefer-lowest" - with: - entrypoint: ./.github/actions/unittest/entrypoint.sh style: runs-on: ubuntu-latest name: PHP Style Check steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Setup PHP uses: shivammathur/setup-php@v2 with: - php-version: "7.4" + php-version: "8.0" - name: Install Dependencies - uses: nick-invision/retry@v1 + uses: nick-invision/retry@v2 with: timeout_minutes: 10 max_attempts: 3 diff --git a/CHANGELOG.md b/CHANGELOG.md index 556b1870d..e4584d937 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -56,7 +56,7 @@ ## 1.11.1 (7/27/2020) * [fix]: catch ConnectException in GCE check (#294) -* [docs]: Adds [reference docs](https://googleapis.github.io/google-auth-library-php/master) +* [docs]: Adds [reference docs](https://googleapis.github.io/google-auth-library-php/main) ## 1.11.0 (7/22/2020) diff --git a/README.md b/README.md index 3b1dc21ee..91f12b2db 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@
Homepage
http://www.github.com/google/google-auth-library-php
-
Reference Docs
https://googleapis.github.io/google-auth-library-php/master/
+
Reference Docs
https://googleapis.github.io/google-auth-library-php/main/
Authors
Tim Emiola
Stanley Cheung
@@ -175,7 +175,7 @@ used when you set up your protected resource as the target audience. See how to #### Call using a specific JSON key If you want to use a specific JSON key instead of using `GOOGLE_APPLICATION_CREDENTIALS` environment variable, you can do this: - + ```php use Google\Auth\CredentialsLoader; use Google\Auth\Middleware\AuthTokenMiddleware; @@ -216,10 +216,10 @@ print_r((string) $response->getBody()); #### Call using Proxy-Authorization Header If your application is behind a proxy such as [Google Cloud IAP][iap-proxy-header], -and your application occupies the `Authorization` request header, -you can include the ID token in a `Proxy-Authorization: Bearer` -header instead. If a valid ID token is found in a `Proxy-Authorization` header, -IAP authorizes the request with it. After authorizing the request, IAP passes +and your application occupies the `Authorization` request header, +you can include the ID token in a `Proxy-Authorization: Bearer` +header instead. If a valid ID token is found in a `Proxy-Authorization` header, +IAP authorizes the request with it. After authorizing the request, IAP passes the Authorization header to your application without processing the content. For this, use the static method `getProxyIdTokenMiddleware` on `ApplicationDefaultCredentials`. @@ -305,8 +305,8 @@ about the client or APIs on [StackOverflow](http://stackoverflow.com). [google-apis-php-client]: https://github.com/google/google-api-php-client [application default credentials]: https://developers.google.com/accounts/docs/application-default-credentials -[contributing]: https://github.com/google/google-auth-library-php/tree/master/.github/CONTRIBUTING.md -[copying]: https://github.com/google/google-auth-library-php/tree/master/COPYING +[contributing]: https://github.com/google/google-auth-library-php/tree/main/.github/CONTRIBUTING.md +[copying]: https://github.com/google/google-auth-library-php/tree/main/COPYING [Guzzle]: https://github.com/guzzle/guzzle [Guzzle 5]: http://docs.guzzlephp.org/en/5.3 [developer console]: https://console.developers.google.com diff --git a/composer.json b/composer.json index 28b36a472..974c1f274 100644 --- a/composer.json +++ b/composer.json @@ -6,19 +6,21 @@ "homepage": "http://github.com/google/google-auth-library-php", "license": "Apache-2.0", "support": { - "docs": "https://googleapis.github.io/google-auth-library-php/master/" + "docs": "https://googleapis.github.io/google-auth-library-php/main/" }, "require": { - "php": ">=5.4", - "firebase/php-jwt": "~2.0|~3.0|~4.0|~5.0", - "guzzlehttp/guzzle": "^5.3.1|^6.2.1|^7.0", + "php": "^7.1||^8.0", + "firebase/php-jwt": "~5.0", + "guzzlehttp/guzzle": "^6.2.1|^7.0", "guzzlehttp/psr7": "^1.7|^2.0", "psr/http-message": "^1.0", - "psr/cache": "^1.0|^2.0" + "psr/cache": "^1.0|^2.0|^3.0" }, "require-dev": { "guzzlehttp/promises": "0.1.1|^1.3", - "phpunit/phpunit": "^4.8.36|^5.7", + "squizlabs/php_codesniffer": "^3.5", + "phpunit/phpunit": "^7.5||^8.5", + "phpspec/prophecy-phpunit": "^1.1", "sebastian/comparator": ">=1.2.3", "phpseclib/phpseclib": "^2.0.31", "kelvinmo/simplejwt": "^0.2.5|^0.5.1" diff --git a/src/AccessToken.php b/src/AccessToken.php index 1ab9b1517..99d208ce4 100644 --- a/src/AccessToken.php +++ b/src/AccessToken.php @@ -444,9 +444,7 @@ private function setPhpsecConstants() */ protected function callJwtStatic($method, array $args = []) { - $class = class_exists('Firebase\JWT\JWT') - ? 'Firebase\JWT\JWT' - : 'JWT'; + $class = 'Firebase\JWT\JWT'; return call_user_func_array([$class, $method], $args); } diff --git a/src/Cache/Item.php b/src/Cache/Item.php index 069eafc32..5d8ab7ecd 100644 --- a/src/Cache/Item.php +++ b/src/Cache/Item.php @@ -169,17 +169,10 @@ private function isValidExpiration($expiration) return true; } - // We test for two types here due to the fact the DateTimeInterface - // was not introduced until PHP 5.5. Checking for the DateTime type as - // well allows us to support 5.4. if ($expiration instanceof \DateTimeInterface) { return true; } - if ($expiration instanceof \DateTime) { - return true; - } - return false; } diff --git a/src/Cache/MemoryCacheItemPool.php b/src/Cache/MemoryCacheItemPool.php index 0af293043..701dac3cc 100644 --- a/src/Cache/MemoryCacheItemPool.php +++ b/src/Cache/MemoryCacheItemPool.php @@ -37,21 +37,36 @@ final class MemoryCacheItemPool implements CacheItemPoolInterface /** * {@inheritdoc} + * + * @return CacheItemInterface + * The corresponding Cache Item. */ - public function getItem($key) + public function getItem($key): CacheItemInterface { return current($this->getItems([$key])); } /** * {@inheritdoc} + * + * @return array + * A traversable collection of Cache Items keyed by the cache keys of + * each item. A Cache item will be returned for each key, even if that + * key is not found. However, if no keys are specified then an empty + * traversable MUST be returned instead. */ - public function getItems(array $keys = []) + public function getItems(array $keys = []): iterable { $items = []; - foreach ($keys as $key) { - $items[$key] = $this->hasItem($key) ? clone $this->items[$key] : new Item($key); + if (\PHP_VERSION_ID >= 80000) { + foreach ($keys as $key) { + $items[$key] = $this->hasItem($key) ? clone $this->items[$key] : new TypedItem($key); + } + } else { + foreach ($keys as $key) { + $items[$key] = $this->hasItem($key) ? clone $this->items[$key] : new Item($key); + } } return $items; @@ -59,8 +74,11 @@ public function getItems(array $keys = []) /** * {@inheritdoc} + * + * @return bool + * True if item exists in the cache, false otherwise. */ - public function hasItem($key) + public function hasItem($key): bool { $this->isValidKey($key); @@ -69,8 +87,11 @@ public function hasItem($key) /** * {@inheritdoc} + * + * @return bool + * True if the pool was successfully cleared. False if there was an error. */ - public function clear() + public function clear(): bool { $this->items = []; $this->deferredItems = []; @@ -80,16 +101,22 @@ public function clear() /** * {@inheritdoc} + * + * @return bool + * True if the item was successfully removed. False if there was an error. */ - public function deleteItem($key) + public function deleteItem($key): bool { return $this->deleteItems([$key]); } /** * {@inheritdoc} + * + * @return bool + * True if the items were successfully removed. False if there was an error. */ - public function deleteItems(array $keys) + public function deleteItems(array $keys): bool { array_walk($keys, [$this, 'isValidKey']); @@ -102,8 +129,11 @@ public function deleteItems(array $keys) /** * {@inheritdoc} + * + * @return bool + * True if the item was successfully persisted. False if there was an error. */ - public function save(CacheItemInterface $item) + public function save(CacheItemInterface $item): bool { $this->items[$item->getKey()] = $item; @@ -112,8 +142,11 @@ public function save(CacheItemInterface $item) /** * {@inheritdoc} + * + * @return bool + * False if the item could not be queued or if a commit was attempted and failed. True otherwise. */ - public function saveDeferred(CacheItemInterface $item) + public function saveDeferred(CacheItemInterface $item): bool { $this->deferredItems[$item->getKey()] = $item; @@ -122,8 +155,11 @@ public function saveDeferred(CacheItemInterface $item) /** * {@inheritdoc} + * + * @return bool + * True if all not-yet-saved items were successfully saved or there were none. False otherwise. */ - public function commit() + public function commit(): bool { foreach ($this->deferredItems as $item) { $this->save($item); diff --git a/src/Cache/SysVCacheItemPool.php b/src/Cache/SysVCacheItemPool.php index 1834cf1b3..12e547de2 100644 --- a/src/Cache/SysVCacheItemPool.php +++ b/src/Cache/SysVCacheItemPool.php @@ -90,7 +90,7 @@ public function __construct($options = []) $this->sysvKey = ftok(__FILE__, $this->options['proj']); } - public function getItem($key) + public function getItem($key): CacheItemInterface { $this->loadItems(); return current($this->getItems([$key])); @@ -99,14 +99,22 @@ public function getItem($key) /** * {@inheritdoc} */ - public function getItems(array $keys = []) + public function getItems(array $keys = []): iterable { $this->loadItems(); $items = []; - foreach ($keys as $key) { - $items[$key] = $this->hasItem($key) ? - clone $this->items[$key] : - new Item($key); + if (\PHP_VERSION_ID >= 80000) { + foreach ($keys as $key) { + $items[$key] = $this->hasItem($key) ? + clone $this->items[$key] : + new TypedItem($key); + } + } else { + foreach ($keys as $key) { + $items[$key] = $this->hasItem($key) ? + clone $this->items[$key] : + new Item($key); + } } return $items; } @@ -114,7 +122,7 @@ public function getItems(array $keys = []) /** * {@inheritdoc} */ - public function hasItem($key) + public function hasItem($key): bool { $this->loadItems(); return isset($this->items[$key]) && $this->items[$key]->isHit(); @@ -123,7 +131,7 @@ public function hasItem($key) /** * {@inheritdoc} */ - public function clear() + public function clear(): bool { $this->items = []; $this->deferredItems = []; @@ -133,7 +141,7 @@ public function clear() /** * {@inheritdoc} */ - public function deleteItem($key) + public function deleteItem($key): bool { return $this->deleteItems([$key]); } @@ -141,7 +149,7 @@ public function deleteItem($key) /** * {@inheritdoc} */ - public function deleteItems(array $keys) + public function deleteItems(array $keys): bool { if (!$this->hasLoadedItems) { $this->loadItems(); @@ -156,7 +164,7 @@ public function deleteItems(array $keys) /** * {@inheritdoc} */ - public function save(CacheItemInterface $item) + public function save(CacheItemInterface $item): bool { if (!$this->hasLoadedItems) { $this->loadItems(); @@ -169,7 +177,7 @@ public function save(CacheItemInterface $item) /** * {@inheritdoc} */ - public function saveDeferred(CacheItemInterface $item) + public function saveDeferred(CacheItemInterface $item): bool { $this->deferredItems[$item->getKey()] = $item; return true; @@ -178,7 +186,7 @@ public function saveDeferred(CacheItemInterface $item) /** * {@inheritdoc} */ - public function commit() + public function commit(): bool { foreach ($this->deferredItems as $item) { if ($this->save($item) === false) { diff --git a/src/Cache/TypedItem.php b/src/Cache/TypedItem.php new file mode 100644 index 000000000..b0d6f2f40 --- /dev/null +++ b/src/Cache/TypedItem.php @@ -0,0 +1,187 @@ +key = $key; + $this->expiration = null; + } + + /** + * {@inheritdoc} + */ + public function getKey(): string + { + return $this->key; + } + + /** + * {@inheritdoc} + */ + public function get(): mixed + { + return $this->isHit() ? $this->value : null; + } + + /** + * {@inheritdoc} + */ + public function isHit(): bool + { + if (!$this->isHit) { + return false; + } + + if ($this->expiration === null) { + return true; + } + + return $this->currentTime()->getTimestamp() < $this->expiration->getTimestamp(); + } + + /** + * {@inheritdoc} + */ + public function set(mixed $value): static + { + $this->isHit = true; + $this->value = $value; + + return $this; + } + + /** + * {@inheritdoc} + */ + public function expiresAt($expiration): static + { + if ($this->isValidExpiration($expiration)) { + $this->expiration = $expiration; + + return $this; + } + + $implementationMessage = interface_exists('DateTimeInterface') + ? 'implement interface DateTimeInterface' + : 'be an instance of DateTime'; + + $error = sprintf( + 'Argument 1 passed to %s::expiresAt() must %s, %s given', + get_class($this), + $implementationMessage, + gettype($expiration) + ); + + $this->handleError($error); + } + + /** + * {@inheritdoc} + */ + public function expiresAfter($time): static + { + if (is_int($time)) { + $this->expiration = $this->currentTime()->add(new \DateInterval("PT{$time}S")); + } elseif ($time instanceof \DateInterval) { + $this->expiration = $this->currentTime()->add($time); + } elseif ($time === null) { + $this->expiration = $time; + } else { + $message = 'Argument 1 passed to %s::expiresAfter() must be an ' . + 'instance of DateInterval or of the type integer, %s given'; + $error = sprintf($message, get_class($this), gettype($time)); + + $this->handleError($error); + } + + return $this; + } + + /** + * Handles an error. + * + * @param string $error + * @throws \TypeError + */ + private function handleError($error) + { + if (class_exists('TypeError')) { + throw new \TypeError($error); + } + + trigger_error($error, \E_USER_ERROR); + } + + /** + * Determines if an expiration is valid based on the rules defined by PSR6. + * + * @param mixed $expiration + * @return bool + */ + private function isValidExpiration($expiration) + { + if ($expiration === null) { + return true; + } + + // We test for two types here due to the fact the DateTimeInterface + // was not introduced until PHP 5.5. Checking for the DateTime type as + // well allows us to support 5.4. + if ($expiration instanceof \DateTimeInterface) { + return true; + } + + if ($expiration instanceof \DateTime) { + return true; + } + + return false; + } + + protected function currentTime() + { + return new \DateTime('now', new \DateTimeZone('UTC')); + } +} diff --git a/src/OAuth2.php b/src/OAuth2.php index 9c7c659ed..5b6b4ec74 100644 --- a/src/OAuth2.php +++ b/src/OAuth2.php @@ -17,6 +17,7 @@ namespace Google\Auth; +use Firebase\JWT\JWT; use Google\Auth\HttpHandler\HttpClientCache; use Google\Auth\HttpHandler\HttpHandlerFactory; use GuzzleHttp\Psr7\Query; @@ -1381,25 +1382,17 @@ private function coerceUri($uri) */ private function jwtDecode($idToken, $publicKey, $allowedAlgs) { - if (class_exists('Firebase\JWT\JWT')) { - return \Firebase\JWT\JWT::decode($idToken, $publicKey, $allowedAlgs); - } - - return \JWT::decode($idToken, $publicKey, $allowedAlgs); + return JWT::decode($idToken, $publicKey, $allowedAlgs); } private function jwtEncode($assertion, $signingKey, $signingAlgorithm, $signingKeyId = null) { - if (class_exists('Firebase\JWT\JWT')) { - return \Firebase\JWT\JWT::encode( - $assertion, - $signingKey, - $signingAlgorithm, - $signingKeyId - ); - } - - return \JWT::encode($assertion, $signingKey, $signingAlgorithm, $signingKeyId); + return JWT::encode( + $assertion, + $signingKey, + $signingAlgorithm, + $signingKeyId + ); } /** diff --git a/src/Subscriber/AuthTokenSubscriber.php b/src/Subscriber/AuthTokenSubscriber.php deleted file mode 100644 index bc529d22b..000000000 --- a/src/Subscriber/AuthTokenSubscriber.php +++ /dev/null @@ -1,136 +0,0 @@ -' - */ -class AuthTokenSubscriber implements SubscriberInterface -{ - /** - * @var callable - */ - private $httpHandler; - - /** - * @var FetchAuthTokenInterface - */ - private $fetcher; - - /** - * @var callable - */ - private $tokenCallback; - - /** - * Creates a new AuthTokenSubscriber. - * - * @param FetchAuthTokenInterface $fetcher is used to fetch the auth token - * @param callable $httpHandler (optional) http client to fetch the token. - * @param callable $tokenCallback (optional) function to be called when a new token is fetched. - */ - public function __construct( - FetchAuthTokenInterface $fetcher, - callable $httpHandler = null, - callable $tokenCallback = null - ) { - $this->fetcher = $fetcher; - $this->httpHandler = $httpHandler; - $this->tokenCallback = $tokenCallback; - } - - /** - * @return array - */ - public function getEvents() - { - return ['before' => ['onBefore', RequestEvents::SIGN_REQUEST]]; - } - - /** - * Updates the request with an Authorization header when auth is 'fetched_auth_token'. - * - * Example: - * ``` - * use GuzzleHttp\Client; - * use Google\Auth\OAuth2; - * use Google\Auth\Subscriber\AuthTokenSubscriber; - * - * $config = [...]; - * $oauth2 = new OAuth2($config) - * $subscriber = new AuthTokenSubscriber($oauth2); - * - * $client = new Client([ - * 'base_url' => 'https://www.googleapis.com/taskqueue/v1beta2/projects/', - * 'defaults' => ['auth' => 'google_auth'] - * ]); - * $client->getEmitter()->attach($subscriber); - * - * $res = $client->get('myproject/taskqueues/myqueue'); - * ``` - * - * @param BeforeEvent $event - */ - public function onBefore(BeforeEvent $event) - { - // Requests using "auth"="google_auth" will be authorized. - $request = $event->getRequest(); - if ($request->getConfig()['auth'] != 'google_auth') { - return; - } - - // Fetch the auth token. - $auth_tokens = $this->fetcher->fetchAuthToken($this->httpHandler); - if (array_key_exists('access_token', $auth_tokens)) { - $request->setHeader('authorization', 'Bearer ' . $auth_tokens['access_token']); - - // notify the callback if applicable - if ($this->tokenCallback) { - call_user_func($this->tokenCallback, $this->fetcher->getCacheKey(), $auth_tokens['access_token']); - } - } - - if ($quotaProject = $this->getQuotaProject()) { - $request->setHeader( - GetQuotaProjectInterface::X_GOOG_USER_PROJECT_HEADER, - $quotaProject - ); - } - } - - private function getQuotaProject() - { - if ($this->fetcher instanceof GetQuotaProjectInterface) { - return $this->fetcher->getQuotaProject(); - } - } -} diff --git a/src/Subscriber/ScopedAccessTokenSubscriber.php b/src/Subscriber/ScopedAccessTokenSubscriber.php deleted file mode 100644 index a52dccefd..000000000 --- a/src/Subscriber/ScopedAccessTokenSubscriber.php +++ /dev/null @@ -1,180 +0,0 @@ -' - */ -class ScopedAccessTokenSubscriber implements SubscriberInterface -{ - use CacheTrait; - - const DEFAULT_CACHE_LIFETIME = 1500; - - /** - * @var CacheItemPoolInterface - */ - private $cache; - - /** - * @var callable The access token generator function - */ - private $tokenFunc; - - /** - * @var array|string The scopes used to generate the token - */ - private $scopes; - - /** - * @var array - */ - private $cacheConfig; - - /** - * Creates a new ScopedAccessTokenSubscriber. - * - * @param callable $tokenFunc a token generator function - * @param array|string $scopes the token authentication scopes - * @param array $cacheConfig configuration for the cache when it's present - * @param CacheItemPoolInterface $cache an implementation of CacheItemPoolInterface - */ - public function __construct( - callable $tokenFunc, - $scopes, - array $cacheConfig = null, - CacheItemPoolInterface $cache = null - ) { - $this->tokenFunc = $tokenFunc; - if (!(is_string($scopes) || is_array($scopes))) { - throw new \InvalidArgumentException( - 'wants scope should be string or array' - ); - } - $this->scopes = $scopes; - - if (!is_null($cache)) { - $this->cache = $cache; - $this->cacheConfig = array_merge([ - 'lifetime' => self::DEFAULT_CACHE_LIFETIME, - 'prefix' => '', - ], $cacheConfig); - } - } - - /** - * @return array - */ - public function getEvents() - { - return ['before' => ['onBefore', RequestEvents::SIGN_REQUEST]]; - } - - /** - * Updates the request with an Authorization header when auth is 'scoped'. - * - * E.g this could be used to authenticate using the AppEngine AppIdentityService. - * - * Example: - * ``` - * use google\appengine\api\app_identity\AppIdentityService; - * use Google\Auth\Subscriber\ScopedAccessTokenSubscriber; - * use GuzzleHttp\Client; - * - * $scope = 'https://www.googleapis.com/auth/taskqueue' - * $subscriber = new ScopedAccessToken( - * 'AppIdentityService::getAccessToken', - * $scope, - * ['prefix' => 'Google\Auth\ScopedAccessToken::'], - * $cache = new Memcache() - * ); - * - * $client = new Client([ - * 'base_url' => 'https://www.googleapis.com/taskqueue/v1beta2/projects/', - * 'defaults' => ['auth' => 'scoped'] - * ]); - * $client->getEmitter()->attach($subscriber); - * - * $res = $client->get('myproject/taskqueues/myqueue'); - * ``` - * - * @param BeforeEvent $event - */ - public function onBefore(BeforeEvent $event) - { - // Requests using "auth"="scoped" will be authorized. - $request = $event->getRequest(); - if ($request->getConfig()['auth'] != 'scoped') { - return; - } - $auth_header = 'Bearer ' . $this->fetchToken(); - $request->setHeader('authorization', $auth_header); - } - - /** - * @return string - */ - private function getCacheKey() - { - $key = null; - - if (is_string($this->scopes)) { - $key .= $this->scopes; - } elseif (is_array($this->scopes)) { - $key .= implode(':', $this->scopes); - } - - return $key; - } - - /** - * Determine if token is available in the cache, if not call tokenFunc to - * fetch it. - * - * @return string - */ - private function fetchToken() - { - $cacheKey = $this->getCacheKey(); - $cached = $this->getCachedValue($cacheKey); - - if (!empty($cached)) { - return $cached; - } - - $token = call_user_func($this->tokenFunc, $this->scopes); - $this->setCachedValue($cacheKey, $token); - - return $token; - } -} diff --git a/src/Subscriber/SimpleSubscriber.php b/src/Subscriber/SimpleSubscriber.php deleted file mode 100644 index a881eb19d..000000000 --- a/src/Subscriber/SimpleSubscriber.php +++ /dev/null @@ -1,93 +0,0 @@ -config = array_merge([], $config); - } - - /** - * @return array - */ - public function getEvents() - { - return ['before' => ['onBefore', RequestEvents::SIGN_REQUEST]]; - } - - /** - * Updates the request query with the developer key if auth is set to simple. - * - * Example: - * ``` - * use Google\Auth\Subscriber\SimpleSubscriber; - * use GuzzleHttp\Client; - * - * $my_key = 'is not the same as yours'; - * $subscriber = new SimpleSubscriber(['key' => $my_key]); - * - * $client = new Client([ - * 'base_url' => 'https://www.googleapis.com/discovery/v1/', - * 'defaults' => ['auth' => 'simple'] - * ]); - * $client->getEmitter()->attach($subscriber); - * - * $res = $client->get('drive/v2/rest'); - * ``` - * - * @param BeforeEvent $event - */ - public function onBefore(BeforeEvent $event) - { - // Requests using "auth"="simple" with the developer key. - $request = $event->getRequest(); - if ($request->getConfig()['auth'] != 'simple') { - return; - } - $request->getQuery()->overwriteWith($this->config); - } -} diff --git a/tests/AccessTokenTest.php b/tests/AccessTokenTest.php index 12a56567c..5a0b07858 100644 --- a/tests/AccessTokenTest.php +++ b/tests/AccessTokenTest.php @@ -18,9 +18,11 @@ use Google\Auth\AccessToken; use GuzzleHttp\Psr7\Response; +use InvalidArgumentException; use PHPUnit\Framework\TestCase; use Prophecy\Argument; use Psr\Http\Message\RequestInterface; +use RuntimeException; use SimpleJWT\JWT as SimpleJWT; /** @@ -35,7 +37,7 @@ class AccessTokenTest extends TestCase private $publicKey; private $allowedAlgs; - public function setUp() + public function setUp(): void { $this->cache = $this->prophesize('Psr\Cache\CacheItemPoolInterface'); $this->jwt = $this->prophesize('Firebase\JWT\JWT'); @@ -281,9 +283,11 @@ public function testRetrieveCertsFromLocationLocalFile() ->shouldBeCalledTimes(1) ->willReturn(null); $item->set($certsData) - ->shouldBeCalledTimes(1); + ->shouldBeCalledTimes(1) + ->willReturn($item->reveal()); $item->expiresAt(Argument::type('\DateTime')) - ->shouldBeCalledTimes(1); + ->shouldBeCalledTimes(1) + ->willReturn($item->reveal()); $this->cache->getItem('google_auth_certs_cache|' . sha1($certsLocation)) ->shouldBeCalledTimes(1) @@ -309,12 +313,11 @@ public function testRetrieveCertsFromLocationLocalFile() ]); } - /** - * @expectedException InvalidArgumentException - * @expectedExceptionMessage Failed to retrieve verification certificates from path - */ public function testRetrieveCertsFromLocationLocalFileInvalidFilePath() { + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage('Failed to retrieve verification certificates from path'); + $certsLocation = __DIR__ . '/fixtures/federated-certs-does-not-exist.json'; $item = $this->prophesize('Psr\Cache\CacheItemInterface'); @@ -336,12 +339,11 @@ public function testRetrieveCertsFromLocationLocalFileInvalidFilePath() ]); } - /** - * @expectedException InvalidArgumentException - * @expectedExceptionMessage federated sign-on certs expects "keys" to be set - */ public function testRetrieveCertsInvalidData() { + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage('federated sign-on certs expects "keys" to be set'); + $item = $this->prophesize('Psr\Cache\CacheItemInterface'); $item->get() ->shouldBeCalledTimes(1) @@ -359,12 +361,11 @@ public function testRetrieveCertsInvalidData() $token->verify($this->token); } - /** - * @expectedException InvalidArgumentException - * @expectedExceptionMessage federated sign-on certs expects "keys" to be set - */ public function testRetrieveCertsFromLocationLocalFileInvalidFileData() { + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage('federated sign-on certs expects "keys" to be set'); + $temp = tmpfile(); fwrite($temp, '{}'); $certsLocation = stream_get_meta_data($temp)['uri']; @@ -406,9 +407,11 @@ public function testRetrieveCertsFromLocationRemote() ->shouldBeCalledTimes(1) ->willReturn(null); $item->set($certsData) - ->shouldBeCalledTimes(1); + ->shouldBeCalledTimes(1) + ->willReturn($item->reveal()); $item->expiresAt(Argument::type('\DateTime')) - ->shouldBeCalledTimes(1); + ->shouldBeCalledTimes(1) + ->willReturn($item->reveal()); $this->cache->getItem('google_auth_certs_cache|federated_signon_certs_v3') ->shouldBeCalledTimes(1) @@ -432,12 +435,11 @@ public function testRetrieveCertsFromLocationRemote() $token->verify($this->token); } - /** - * @expectedException RuntimeException - * @expectedExceptionMessage bad news guys - */ public function testRetrieveCertsFromLocationRemoteBadRequest() { + $this->expectException(RuntimeException::class); + $this->expectExceptionMessage('bad news guys'); + $badBody = 'bad news guys'; $httpHandler = function (RequestInterface $request) use ($badBody) { diff --git a/tests/ApplicationDefaultCredentialsTest.php b/tests/ApplicationDefaultCredentialsTest.php index 67f9c7a72..75b50697b 100644 --- a/tests/ApplicationDefaultCredentialsTest.php +++ b/tests/ApplicationDefaultCredentialsTest.php @@ -17,6 +17,7 @@ namespace Google\Auth\Tests; +use DomainException; use Google\Auth\ApplicationDefaultCredentials; use Google\Auth\Credentials\GCECredentials; use Google\Auth\Credentials\ServiceAccountCredentials; @@ -30,12 +31,12 @@ class ADCGetTest extends TestCase { private $originalHome; - protected function setUp() + protected function setUp(): void { $this->originalHome = getenv('HOME'); } - protected function tearDown() + protected function tearDown(): void { if ($this->originalHome != getenv('HOME')) { putenv('HOME=' . $this->originalHome); @@ -43,11 +44,10 @@ protected function tearDown() putenv(ServiceAccountCredentials::ENV_VAR); // removes it from } - /** - * @expectedException DomainException - */ public function testIsFailsEnvSpecifiesNonExistentFile() { + $this->expectException(DomainException::class); + $keyFile = __DIR__ . '/fixtures' . '/does-not-exist-private.json'; putenv(ServiceAccountCredentials::ENV_VAR . '=' . $keyFile); ApplicationDefaultCredentials::getCredentials('a scope'); @@ -70,11 +70,10 @@ public function testLoadsDefaultFileIfPresentAndEnvVarIsNotSet() ); } - /** - * @expectedException DomainException - */ public function testFailsIfNotOnGceAndNoDefaultFileFound() { + $this->expectException(DomainException::class); + putenv('HOME=' . __DIR__ . '/not_exist_fixtures'); // simulate not being GCE and retry attempts by returning multiple 500s $httpHandler = getHandler([ @@ -141,7 +140,7 @@ public function testGceCredentials() // used default scope $tokenUri = $uriProperty->getValue($creds); - $this->assertContains('a+default+scope', $tokenUri); + $this->assertStringContainsString('a+default+scope', $tokenUri); $creds = ApplicationDefaultCredentials::getCredentials( 'a+user+scope', // $scope @@ -157,7 +156,7 @@ public function testGceCredentials() // did not use default scope $tokenUri = $uriProperty->getValue($creds); - $this->assertContains('a+user+scope', $tokenUri); + $this->assertStringContainsString('a+user+scope', $tokenUri); } /** @runInSeparateProcess */ @@ -267,12 +266,12 @@ class ADCGetMiddlewareTest extends TestCase { private $originalHome; - protected function setUp() + protected function setUp(): void { $this->originalHome = getenv('HOME'); } - protected function tearDown() + protected function tearDown(): void { if ($this->originalHome != getenv('HOME')) { putenv('HOME=' . $this->originalHome); @@ -280,11 +279,10 @@ protected function tearDown() putenv(ServiceAccountCredentials::ENV_VAR); // removes it if assigned } - /** - * @expectedException DomainException - */ public function testIsFailsEnvSpecifiesNonExistentFile() { + $this->expectException(DomainException::class); + $keyFile = __DIR__ . '/fixtures' . '/does-not-exist-private.json'; putenv(ServiceAccountCredentials::ENV_VAR . '=' . $keyFile); ApplicationDefaultCredentials::getMiddleware('a scope'); @@ -303,11 +301,10 @@ public function testLoadsDefaultFileIfPresentAndEnvVarIsNotSet() $this->assertNotNull(ApplicationDefaultCredentials::getMiddleware('a scope')); } - /** - * @expectedException DomainException - */ public function testFailsIfNotOnGceAndNoDefaultFileFound() { + $this->expectException(DomainException::class); + putenv('HOME=' . __DIR__ . '/not_exist_fixtures'); // simulate not being GCE and retry attempts by returning multiple 500s @@ -338,6 +335,8 @@ public function testWithCacheOptions() $cacheOptions, $cachePool->reveal() ); + + $this->assertNotNull($middleware); } public function testSuccedsIfNoDefaultFilesButIsOnGCE() @@ -358,11 +357,10 @@ public function testSuccedsIfNoDefaultFilesButIsOnGCE() $this->assertNotNull(ApplicationDefaultCredentials::getMiddleware('a scope', $httpHandler)); } - /** - * @expectedException DomainException - */ public function testOnGceCacheWithHit() { + $this->expectException(DomainException::class); + putenv('HOME=' . __DIR__ . '/not_exist_fixtures'); $mockCacheItem = $this->prophesize('Psr\Cache\CacheItemInterface'); @@ -398,9 +396,11 @@ public function testOnGceCacheWithoutHit() $mockCacheItem->isHit() ->willReturn(false); $mockCacheItem->set(true) - ->shouldBeCalledTimes(1); + ->shouldBeCalledTimes(1) + ->willReturn($mockCacheItem->reveal()); $mockCacheItem->expiresAfter(1500) - ->shouldBeCalledTimes(1); + ->shouldBeCalledTimes(1) + ->willReturn($mockCacheItem->reveal()); $mockCache = $this->prophesize('Psr\Cache\CacheItemPoolInterface'); $mockCache->getItem(GCECache::GCE_CACHE_KEY) @@ -435,9 +435,11 @@ public function testOnGceCacheWithOptions() $mockCacheItem->isHit() ->willReturn(false); $mockCacheItem->set(true) - ->shouldBeCalledTimes(1); + ->shouldBeCalledTimes(1) + ->willReturn($mockCacheItem->reveal()); $mockCacheItem->expiresAfter($lifetime) - ->shouldBeCalledTimes(1); + ->shouldBeCalledTimes(1) + ->willReturn($mockCacheItem->reveal()); $mockCache = $this->prophesize('Psr\Cache\CacheItemPoolInterface'); $mockCache->getItem($prefix . GCECache::GCE_CACHE_KEY) @@ -462,12 +464,12 @@ class ADCGetCredentialsWithTargetAudienceTest extends TestCase private $originalHome; private $targetAudience = 'a target audience'; - protected function setUp() + protected function setUp(): void { $this->originalHome = getenv('HOME'); } - protected function tearDown() + protected function tearDown(): void { if ($this->originalHome != getenv('HOME')) { putenv('HOME=' . $this->originalHome); @@ -475,11 +477,10 @@ protected function tearDown() putenv(ServiceAccountCredentials::ENV_VAR); // removes environment variable } - /** - * @expectedException DomainException - */ public function testIsFailsEnvSpecifiesNonExistentFile() { + $this->expectException(DomainException::class); + $keyFile = __DIR__ . '/fixtures' . '/does-not-exist-private.json'; putenv(ServiceAccountCredentials::ENV_VAR . '=' . $keyFile); ApplicationDefaultCredentials::getIdTokenCredentials($this->targetAudience); @@ -489,20 +490,23 @@ public function testLoadsOKIfEnvSpecifiedIsValid() { $keyFile = __DIR__ . '/fixtures' . '/private.json'; putenv(ServiceAccountCredentials::ENV_VAR . '=' . $keyFile); - ApplicationDefaultCredentials::getIdTokenCredentials($this->targetAudience); + + $creds = ApplicationDefaultCredentials::getIdTokenCredentials($this->targetAudience); + + $this->assertNotNull($creds); } public function testLoadsDefaultFileIfPresentAndEnvVarIsNotSet() { putenv('HOME=' . __DIR__ . '/fixtures'); - ApplicationDefaultCredentials::getIdTokenCredentials($this->targetAudience); + $creds = ApplicationDefaultCredentials::getIdTokenCredentials($this->targetAudience); + $this->assertNotNull($creds); } - /** - * @expectedException DomainException - */ public function testFailsIfNotOnGceAndNoDefaultFileFound() { + $this->expectException(DomainException::class); + putenv('HOME=' . __DIR__ . '/not_exist_fixtures'); // simulate not being GCE and retry attempts by returning multiple 500s @@ -512,10 +516,12 @@ public function testFailsIfNotOnGceAndNoDefaultFileFound() buildResponse(500) ]); - ApplicationDefaultCredentials::getIdTokenCredentials( + $creds = ApplicationDefaultCredentials::getIdTokenCredentials( $this->targetAudience, $httpHandler ); + + $this->assertNotNull($creds); } public function testWithCacheOptions() @@ -573,12 +579,12 @@ class ADCGetCredentialsWithQuotaProjectTest extends TestCase private $originalHome; private $quotaProject = 'a-quota-project'; - protected function setUp() + protected function setUp(): void { $this->originalHome = getenv('HOME'); } - protected function tearDown() + protected function tearDown(): void { if ($this->originalHome != getenv('HOME')) { putenv('HOME=' . $this->originalHome); @@ -693,7 +699,7 @@ class ADCGetCredentialsAppEngineTest extends BaseTest private $originalServiceAccount; private $targetAudience = 'a target audience'; - protected function setUp() + protected function setUp(): void { // set home to be somewhere else $this->originalHome = getenv('HOME'); @@ -704,7 +710,7 @@ protected function setUp() putenv(ServiceAccountCredentials::ENV_VAR); } - protected function tearDown() + protected function tearDown(): void { // removes it if assigned putenv('HOME=' . $this->originalHome); @@ -760,100 +766,3 @@ public function testAppEngineFlexibleIdToken() ); } } - -// @todo consider a way to DRY this and above class up -class ADCGetSubscriberTest extends BaseTest -{ - private $originalHome; - - protected function setUp() - { - $this->onlyGuzzle5(); - - $this->originalHome = getenv('HOME'); - } - - protected function tearDown() - { - if ($this->originalHome != getenv('HOME')) { - putenv('HOME=' . $this->originalHome); - } - putenv(ServiceAccountCredentials::ENV_VAR); // removes it if assigned - } - - /** - * @expectedException DomainException - */ - public function testIsFailsEnvSpecifiesNonExistentFile() - { - $keyFile = __DIR__ . '/fixtures' . '/does-not-exist-private.json'; - putenv(ServiceAccountCredentials::ENV_VAR . '=' . $keyFile); - ApplicationDefaultCredentials::getSubscriber('a scope'); - } - - public function testLoadsOKIfEnvSpecifiedIsValid() - { - $keyFile = __DIR__ . '/fixtures' . '/private.json'; - putenv(ServiceAccountCredentials::ENV_VAR . '=' . $keyFile); - $this->assertNotNull(ApplicationDefaultCredentials::getSubscriber('a scope')); - } - - public function testLoadsDefaultFileIfPresentAndEnvVarIsNotSet() - { - putenv('HOME=' . __DIR__ . '/fixtures'); - $this->assertNotNull(ApplicationDefaultCredentials::getSubscriber('a scope')); - } - - /** - * @expectedException DomainException - */ - public function testFailsIfNotOnGceAndNoDefaultFileFound() - { - putenv('HOME=' . __DIR__ . '/not_exist_fixtures'); - - // simulate not being GCE by return 500 - $httpHandler = getHandler([ - buildResponse(500), - ]); - - ApplicationDefaultCredentials::getSubscriber('a scope', $httpHandler); - } - - public function testWithCacheOptions() - { - $keyFile = __DIR__ . '/fixtures' . '/private.json'; - putenv(ServiceAccountCredentials::ENV_VAR . '=' . $keyFile); - - $httpHandler = getHandler([ - buildResponse(200), - ]); - - $cacheOptions = []; - $cachePool = $this->prophesize('Psr\Cache\CacheItemPoolInterface'); - - $subscriber = ApplicationDefaultCredentials::getSubscriber( - 'a scope', - $httpHandler, - $cacheOptions, - $cachePool->reveal() - ); - } - - public function testSuccedsIfNoDefaultFilesButIsOnGCE() - { - $wantedTokens = [ - 'access_token' => '1/abdef1234567890', - 'expires_in' => '57', - 'token_type' => 'Bearer', - ]; - $jsonTokens = json_encode($wantedTokens); - - // simulate the response from GCE. - $httpHandler = getHandler([ - buildResponse(200, [GCECredentials::FLAVOR_HEADER => 'Google']), - buildResponse(200, [], Utils::streamFor($jsonTokens)), - ]); - - $this->assertNotNull(ApplicationDefaultCredentials::getSubscriber('a scope', $httpHandler)); - } -} diff --git a/tests/BaseTest.php b/tests/BaseTest.php index 550c2cfee..e38e3edf1 100644 --- a/tests/BaseTest.php +++ b/tests/BaseTest.php @@ -7,13 +7,6 @@ abstract class BaseTest extends TestCase { - protected function onlyGuzzle5() - { - if ($this->getGuzzleMajorVersion() !== 5) { - $this->markTestSkipped('Guzzle 5 only'); - } - } - protected function onlyGuzzle6() { if ($this->getGuzzleMajorVersion() !== 6) { @@ -21,13 +14,6 @@ protected function onlyGuzzle6() } } - protected function onlyGuzzle6And7() - { - if (!in_array($this->getGuzzleMajorVersion(), [6, 7])) { - $this->markTestSkipped('Guzzle 6 and 7 only'); - } - } - protected function onlyGuzzle7() { if ($this->getGuzzleMajorVersion() !== 7) { @@ -55,4 +41,13 @@ public function getValidKeyName($key) { return preg_replace('|[^a-zA-Z0-9_\.! ]|', '', $key); } + + protected function getCacheItemClass() + { + if (\PHP_VERSION_ID >= 80000) { + return 'Google\Auth\Cache\TypedItem'; + } + + return 'Google\Auth\Cache\Item'; + } } diff --git a/tests/Cache/ItemTest.php b/tests/Cache/ItemTest.php index 9312d82ad..8917f8b32 100644 --- a/tests/Cache/ItemTest.php +++ b/tests/Cache/ItemTest.php @@ -18,12 +18,17 @@ namespace Google\Auth\Tests\Cache; use Google\Auth\Cache\Item; +use Google\Auth\Cache\TypedItem; use PHPUnit\Framework\TestCase; class ItemTest extends TestCase { public function getItem($key) { + if (\PHP_VERSION_ID >= 80000) { + return new TypedItem($key); + } + return new Item($key); } diff --git a/tests/Cache/MemoryCacheItemPoolTest.php b/tests/Cache/MemoryCacheItemPoolTest.php index b0942e861..6a8aff038 100644 --- a/tests/Cache/MemoryCacheItemPoolTest.php +++ b/tests/Cache/MemoryCacheItemPoolTest.php @@ -18,14 +18,14 @@ namespace Google\Auth\Tests\Cache; use Google\Auth\Cache\MemoryCacheItemPool; -use PHPUnit\Framework\TestCase; +use Google\Auth\Tests\BaseTest; use Psr\Cache\InvalidArgumentException; -class MemoryCacheItemPoolTest extends TestCase +class MemoryCacheItemPoolTest extends BaseTest { private $pool; - public function setUp() + public function setUp(): void { $this->pool = new MemoryCacheItemPool(); } @@ -43,7 +43,7 @@ public function testGetsFreshItem() { $item = $this->pool->getItem('item'); - $this->assertInstanceOf('Google\Auth\Cache\Item', $item); + $this->assertInstanceOf($this->getCacheItemClass(), $item); $this->assertNull($item->get()); $this->assertFalse($item->isHit()); } @@ -55,7 +55,7 @@ public function testGetsExistingItem() $this->saveItem($key, $value); $item = $this->pool->getItem($key); - $this->assertInstanceOf('Google\Auth\Cache\Item', $item); + $this->assertInstanceOf($this->getCacheItemClass(), $item); $this->assertEquals($value, $item->get()); $this->assertTrue($item->isHit()); } @@ -66,7 +66,7 @@ public function testGetsMultipleItems() $items = $this->pool->getItems($keys); $this->assertEquals($keys, array_keys($items)); - $this->assertContainsOnlyInstancesOf('Google\Auth\Cache\Item', $items); + $this->assertContainsOnlyInstancesOf($this->getCacheItemClass(), $items); } public function testHasItem() @@ -157,47 +157,52 @@ public function testCommitsDeferredItems() } /** - * @expectedException \Psr\Cache\InvalidArgumentException * @dataProvider invalidKeys */ public function testCheckInvalidKeysOnGetItem($key) { + $this->expectException(InvalidArgumentException::class); + $this->pool->getItem($key); } /** - * @expectedException \Psr\Cache\InvalidArgumentException * @dataProvider invalidKeys */ public function testCheckInvalidKeysOnGetItems($key) { + $this->expectException(InvalidArgumentException::class); + $this->pool->getItems([$key]); } /** - * @expectedException \Psr\Cache\InvalidArgumentException * @dataProvider invalidKeys */ public function testCheckInvalidKeysOnHasItem($key) { + $this->expectException(InvalidArgumentException::class); + $this->pool->hasItem($key); } /** - * @expectedException \Psr\Cache\InvalidArgumentException * @dataProvider invalidKeys */ public function testCheckInvalidKeysOnDeleteItem($key) { + $this->expectException(InvalidArgumentException::class); + $this->pool->deleteItem($key); } /** - * @expectedException \Psr\Cache\InvalidArgumentException * @dataProvider invalidKeys */ public function testCheckInvalidKeysOnDeleteItems($key) { + $this->expectException(InvalidArgumentException::class); + $this->pool->deleteItems([$key]); } diff --git a/tests/Cache/SysVCacheItemPoolTest.php b/tests/Cache/SysVCacheItemPoolTest.php index 8fa056270..46f7812c1 100644 --- a/tests/Cache/SysVCacheItemPoolTest.php +++ b/tests/Cache/SysVCacheItemPoolTest.php @@ -18,13 +18,13 @@ namespace Google\Auth\Tests\Cache; use Google\Auth\Cache\SysVCacheItemPool; -use PHPUnit\Framework\TestCase; +use Google\Auth\Tests\BaseTest; -class SysVCacheItemPoolTest extends TestCase +class SysVCacheItemPoolTest extends BaseTest { private $pool; - public function setUp() + public function setUp(): void { if (! extension_loaded('sysvshm')) { $this->markTestSkipped( @@ -48,7 +48,7 @@ public function testGetsFreshItem() { $item = $this->pool->getItem('item'); - $this->assertInstanceOf('Google\Auth\Cache\Item', $item); + $this->assertInstanceOf($this->getCacheItemClass(), $item); $this->assertNull($item->get()); $this->assertFalse($item->isHit()); } @@ -70,7 +70,7 @@ public function testGetsExistingItem() $this->saveItem($key, $value); $item = $this->pool->getItem($key); - $this->assertInstanceOf('Google\Auth\Cache\Item', $item); + $this->assertInstanceOf($this->getCacheItemClass(), $item); $this->assertEquals($value, $item->get()); $this->assertTrue($item->isHit()); } @@ -81,7 +81,7 @@ public function testGetsMultipleItems() $items = $this->pool->getItems($keys); $this->assertEquals($keys, array_keys($items)); - $this->assertContainsOnlyInstancesOf('Google\Auth\Cache\Item', $items); + $this->assertContainsOnlyInstancesOf($this->getCacheItemClass(), $items); } public function testHasItem() diff --git a/tests/Cache/sysv_cache_creator.php b/tests/Cache/sysv_cache_creator.php index 618097d23..3231c4301 100644 --- a/tests/Cache/sysv_cache_creator.php +++ b/tests/Cache/sysv_cache_creator.php @@ -21,10 +21,15 @@ use Google\Auth\Cache\Item; use Google\Auth\Cache\SysVCacheItemPool; +use Google\Auth\Cache\TypedItem; $value = $argv[1]; // Use the same variableKey in the test. $pool = new SysVCacheItemPool(['variableKey' => 99]); -$item = new Item('separate-process-item'); +if (\PHP_VERSION_ID >= 80000) { + $item = new TypedItem('separate-process-item'); +} else { + $item = new Item('separate-process-item'); +} $item->set($value); $pool->save($item); diff --git a/tests/CacheTraitTest.php b/tests/CacheTraitTest.php index 583beea98..ac93eb5de 100644 --- a/tests/CacheTraitTest.php +++ b/tests/CacheTraitTest.php @@ -27,7 +27,7 @@ class CacheTraitTest extends TestCase private $mockCacheItem; private $mockCache; - public function setUp() + public function setUp(): void { $this->mockFetcher = $this->prophesize('Google\Auth\FetchAuthTokenInterface'); $this->mockCacheItem = $this->prophesize('Psr\Cache\CacheItemInterface'); @@ -121,15 +121,18 @@ public function testFailsPullFromCacheWithoutKey() ]); $cachedValue = $implementation->gCachedValue(); + $this->assertEquals(null, $cachedValue); } public function testSuccessfullySetsToCache() { $value = '1234'; $this->mockCacheItem->set($value) - ->shouldBeCalled(); + ->shouldBeCalled() + ->willReturn($this->mockCacheItem->reveal()); $this->mockCacheItem->expiresAfter(Argument::any()) - ->shouldBeCalled(); + ->shouldBeCalled() + ->willReturn($this->mockCacheItem->reveal()); $this->mockCache->getItem('key') ->willReturn($this->mockCacheItem->reveal()); $this->mockCache->save(Argument::type('Psr\Cache\CacheItemInterface')) diff --git a/tests/Credentials/AppIdentityCredentialsTest.php b/tests/Credentials/AppIdentityCredentialsTest.php index 104e0a4fb..0f515bd72 100644 --- a/tests/Credentials/AppIdentityCredentialsTest.php +++ b/tests/Credentials/AppIdentityCredentialsTest.php @@ -75,13 +75,6 @@ public function testFetchAuthTokenShouldBeEmptyIfNotOnAppEngine() $this->assertEquals(array(), $g->fetchAuthToken()); } - /* @expectedException */ - public function testThrowsExceptionIfClassDoesntExist() - { - $_SERVER['SERVER_SOFTWARE'] = 'Google App Engine'; - $g = new AppIdentityCredentials(); - } - /** * @runInSeparateProcess */ @@ -131,17 +124,13 @@ public function testScopeIsAlwaysArray() public function testMethodsFailWhenNotInAppEngine($method, $args = [], $expected = null) { if ($expected === null) { - if (method_exists($this, 'expectException')) { - $this->expectException('\Exception'); - } else { - $this->setExpectedException('\Exception'); - } + $this->expectException(\Exception::class); } $creds = new AppIdentityCredentials(); $res = call_user_func_array([$creds, $method], $args); - if ($expected) { + if ($expected !== null) { $this->assertEquals($expected, $res); } } diff --git a/tests/Credentials/GCECredentialsTest.php b/tests/Credentials/GCECredentialsTest.php index 87e5743f3..065bae047 100644 --- a/tests/Credentials/GCECredentialsTest.php +++ b/tests/Credentials/GCECredentialsTest.php @@ -17,11 +17,13 @@ namespace Google\Auth\Tests\Credentials; +use Exception; use Google\Auth\Credentials\GCECredentials; use Google\Auth\HttpHandler\HttpClientCache; use Google\Auth\Tests\BaseTest; use GuzzleHttp\Psr7; use GuzzleHttp\Psr7\Utils; +use InvalidArgumentException; use Prophecy\Argument; /** @@ -112,12 +114,11 @@ public function testFetchAuthTokenShouldBeEmptyIfNotOnGCE() $this->assertEquals(array(), $g->fetchAuthToken($httpHandler)); } - /** - * @expectedException Exception - * @expectedExceptionMessage Invalid JSON response - */ public function testFetchAuthTokenShouldFailIfResponseIsNotJson() { + $this->expectException(Exception::class); + $this->expectExceptionMessage('Invalid JSON response'); + $notJson = '{"foo": , this is cannot be passed as json" "bar"}'; $httpHandler = getHandler([ buildResponse(200, [GCECredentials::FLAVOR_HEADER => 'Google']), @@ -173,12 +174,11 @@ public function testFetchAuthTokenShouldBeIdTokenWhenTargetAudienceIsSet() $this->assertEquals(2, $timesCalled); } - /** - * @expectedException InvalidArgumentException - * @expectedExceptionMessage Scope and targetAudience cannot both be supplied - */ public function testSettingBothScopeAndTargetAudienceThrowsException() { + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage('Scope and targetAudience cannot both be supplied'); + $g = new GCECredentials(null, 'a-scope', 'a+target+audience'); } @@ -187,8 +187,6 @@ public function testSettingBothScopeAndTargetAudienceThrowsException() */ public function testFetchAuthTokenCustomScope($scope, $expected) { - $this->onlyGuzzle6And7(); - $uri = null; $client = $this->prophesize('GuzzleHttp\ClientInterface'); $client->send(Argument::any(), Argument::any()) @@ -260,8 +258,6 @@ public function testGetClientNameShouldBeEmptyIfNotOnGCE() public function testSignBlob() { - $this->onlyGuzzle6And7(); - $expectedEmail = 'test@test.com'; $expectedAccessToken = 'token'; $stringToSign = 'inputString'; @@ -293,8 +289,6 @@ public function testSignBlob() public function testSignBlobWithLastReceivedAccessToken() { - $this->onlyGuzzle6And7(); - $expectedEmail = 'test@test.com'; $expectedAccessToken = 'token'; $notExpectedAccessToken = 'othertoken'; @@ -336,8 +330,6 @@ public function testSignBlobWithLastReceivedAccessToken() public function testGetProjectId() { - $this->onlyGuzzle6And7(); - $expected = 'foobar'; $client = $this->prophesize('GuzzleHttp\ClientInterface'); @@ -359,8 +351,6 @@ public function testGetProjectId() public function testGetProjectIdShouldBeEmptyIfNotOnGCE() { - $this->onlyGuzzle6And7(); - // simulate retry attempts by returning multiple 500s $client = $this->prophesize('GuzzleHttp\ClientInterface'); $client->send(Argument::any(), Argument::any()) diff --git a/tests/Credentials/IAMCredentialsTest.php b/tests/Credentials/IAMCredentialsTest.php index 12c05cb0a..0edb5f1bd 100644 --- a/tests/Credentials/IAMCredentialsTest.php +++ b/tests/Credentials/IAMCredentialsTest.php @@ -18,6 +18,7 @@ namespace Google\Auth\Tests\Credentials; use Google\Auth\Credentials\IAMCredentials; +use InvalidArgumentException; use PHPUnit\Framework\TestCase; /** @@ -26,11 +27,10 @@ */ class IAMConstructorTest extends TestCase { - /** - * @expectedException InvalidArgumentException - */ public function testShouldFailIfSelectorIsNotString() { + $this->expectException(InvalidArgumentException::class); + $notAString = new \stdClass(); $iam = new IAMCredentials( $notAString, @@ -38,11 +38,10 @@ public function testShouldFailIfSelectorIsNotString() ); } - /** - * @expectedException InvalidArgumentException - */ public function testShouldFailIfTokenIsNotString() { + $this->expectException(InvalidArgumentException::class); + $notAString = new \stdClass(); $iam = new IAMCredentials( '', @@ -70,7 +69,7 @@ public function testUpdateMetadataFunc() ); $update_metadata = $iam->getUpdateMetadataFunc(); - $this->assertInternalType('callable', $update_metadata); + $this->assertTrue(is_callable($update_metadata)); $actual_metadata = call_user_func( $update_metadata, diff --git a/tests/Credentials/ServiceAccountCredentialsTest.php b/tests/Credentials/ServiceAccountCredentialsTest.php index 41eb65811..9546ee5d7 100644 --- a/tests/Credentials/ServiceAccountCredentialsTest.php +++ b/tests/Credentials/ServiceAccountCredentialsTest.php @@ -17,6 +17,8 @@ namespace Google\Auth\Tests\Credentials; +use DomainException; +use Firebase\JWT\JWT; use Google\Auth\ApplicationDefaultCredentials; use Google\Auth\Credentials\ServiceAccountCredentials; use Google\Auth\Credentials\ServiceAccountJwtAccessCredentials; @@ -24,7 +26,10 @@ use Google\Auth\OAuth2; use GuzzleHttp\Psr7; use GuzzleHttp\Psr7\Utils; +use InvalidArgumentException; +use LogicException; use PHPUnit\Framework\TestCase; +use UnexpectedValueException; // Creates a standard JSON auth object for testing. function createTestJson() @@ -95,11 +100,10 @@ public function testShouldBeTheSameAsOAuth2WithTheSameScopeWithSubAddedLater() class SACConstructorTest extends TestCase { - /** - * @expectedException InvalidArgumentException - */ public function testShouldFailIfScopeIsNotAValidType() { + $this->expectexception(InvalidArgumentException::class); + $testJson = createTestJson(); $notAnArrayOrString = new \stdClass(); $sa = new ServiceAccountCredentials( @@ -108,11 +112,10 @@ public function testShouldFailIfScopeIsNotAValidType() ); } - /** - * @expectedException InvalidArgumentException - */ public function testShouldFailIfJsonDoesNotHaveClientEmail() { + $this->expectException(InvalidArgumentException::class); + $testJson = createTestJson(); unset($testJson['client_email']); $scope = ['scope/1', 'scope/2']; @@ -122,11 +125,10 @@ public function testShouldFailIfJsonDoesNotHaveClientEmail() ); } - /** - * @expectedException InvalidArgumentException - */ public function testShouldFailIfJsonDoesNotHavePrivateKey() { + $this->expectException(InvalidArgumentException::class); + $testJson = createTestJson(); unset($testJson['private_key']); $scope = ['scope/1', 'scope/2']; @@ -136,11 +138,10 @@ public function testShouldFailIfJsonDoesNotHavePrivateKey() ); } - /** - * @expectedException InvalidArgumentException - */ public function testFailsToInitalizeFromANonExistentFile() { + $this->expectException(InvalidArgumentException::class); + $keyFile = __DIR__ . '/../fixtures' . '/does-not-exist-private.json'; new ServiceAccountCredentials('scope/1', $keyFile); } @@ -153,11 +154,10 @@ public function testInitalizeFromAFile() ); } - /** - * @expectedException LogicException - */ public function testFailsToInitializeFromInvalidJsonData() { + $this->expectException(LogicException::class); + $tmp = tmpfile(); fwrite($tmp, '{'); @@ -174,7 +174,7 @@ public function testFailsToInitializeFromInvalidJsonData() class SACFromEnvTest extends TestCase { - protected function tearDown() + protected function tearDown(): void { putenv(ServiceAccountCredentials::ENV_VAR); // removes it from } @@ -184,11 +184,9 @@ public function testIsNullIfEnvVarIsNotSet() $this->assertNull(ServiceAccountCredentials::fromEnv()); } - /** - * @expectedException DomainException - */ public function testFailsIfEnvSpecifiesNonExistentFile() { + $this->expectException(DomainException::class); $keyFile = __DIR__ . '/../fixtures' . '/does-not-exist-private.json'; putenv(ServiceAccountCredentials::ENV_VAR . '=' . $keyFile); ApplicationDefaultCredentials::getCredentials('a scope'); @@ -206,12 +204,12 @@ class SACFromWellKnownFileTest extends TestCase { private $originalHome; - protected function setUp() + protected function setUp(): void { $this->originalHome = getenv('HOME'); } - protected function tearDown() + protected function tearDown(): void { if ($this->originalHome != getenv('HOME')) { putenv('HOME=' . $this->originalHome); @@ -239,7 +237,7 @@ class SACFetchAuthTokenTest extends TestCase { private $privateKey; - public function setUp() + public function setUp(): void { $this->privateKey = file_get_contents(__DIR__ . '/../fixtures' . '/private.pem'); @@ -253,11 +251,10 @@ private function createTestJson() return $testJson; } - /** - * @expectedException GuzzleHttp\Exception\ClientException - */ public function testFailsOnClientErrors() { + $this->expectException(\GuzzleHttp\Exception\ClientException::class); + $testJson = $this->createTestJson(); $scope = ['scope/1', 'scope/2']; $httpHandler = getHandler([ @@ -270,11 +267,10 @@ public function testFailsOnClientErrors() $sa->fetchAuthToken($httpHandler); } - /** - * @expectedException GuzzleHttp\Exception\ServerException - */ public function testFailsOnServerErrors() { + $this->expectException(\GuzzleHttp\Exception\ServerException::class); + $testJson = $this->createTestJson(); $scope = ['scope/1', 'scope/2']; $httpHandler = getHandler([ @@ -317,7 +313,7 @@ public function testUpdateMetadataFunc() $testJson ); $update_metadata = $sa->getUpdateMetadataFunc(); - $this->assertInternalType('callable', $update_metadata); + $this->assertTrue(is_callable($update_metadata)); $actual_metadata = call_user_func( $update_metadata, @@ -356,12 +352,11 @@ public function testShouldBeIdTokenWhenTargetAudienceIsSet() $this->assertEquals(1, $timesCalled); } - /** - * @expectedException InvalidArgumentException - * @expectedExceptionMessage Scope and targetAudience cannot both be supplied - */ public function testSettingBothScopeAndTargetAudienceThrowsException() { + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage('Scope and targetAudience cannot both be supplied'); + $testJson = $this->createTestJson(); $sa = new ServiceAccountCredentials( 'a-scope', @@ -406,7 +401,7 @@ class SACJwtAccessTest extends TestCase { private $privateKey; - public function setUp() + public function setUp(): void { $this->privateKey = file_get_contents(__DIR__ . '/../fixtures' . '/private.pem'); @@ -420,11 +415,10 @@ private function createTestJson() return $testJson; } - /** - * @expectedException InvalidArgumentException - */ public function testFailsToInitalizeFromANonExistentFile() { + $this->expectException(InvalidArgumentException::class); + $keyFile = __DIR__ . '/../fixtures' . '/does-not-exist-private.json'; new ServiceAccountJwtAccessCredentials($keyFile); } @@ -437,11 +431,9 @@ public function testInitalizeFromAFile() ); } - /** - * @expectedException LogicException - */ public function testFailsToInitializeFromInvalidJsonData() { + $this->expectException(LogicException::class); $tmp = tmpfile(); fwrite($tmp, '{'); @@ -455,11 +447,10 @@ public function testFailsToInitializeFromInvalidJsonData() } } - /** - * @expectedException InvalidArgumentException - */ public function testFailsOnMissingClientEmail() { + $this->expectException(InvalidArgumentException::class); + $testJson = $this->createTestJson(); unset($testJson['client_email']); $sa = new ServiceAccountJwtAccessCredentials( @@ -467,11 +458,10 @@ public function testFailsOnMissingClientEmail() ); } - /** - * @expectedException InvalidArgumentException - */ public function testFailsOnMissingPrivateKey() { + $this->expectException(InvalidArgumentException::class); + $testJson = $this->createTestJson(); unset($testJson['private_key']); $sa = new ServiceAccountJwtAccessCredentials( @@ -479,12 +469,11 @@ public function testFailsOnMissingPrivateKey() ); } - /** - * @expectedException UnexpectedValueException - * @expectedExceptionMessage Cannot sign both audience and scope in JwtAccess - */ public function testFailsWithBothAudienceAndScope() { + $this->expectException(UnexpectedValueException::class); + $this->expectExceptionMessage('Cannot sign both audience and scope in JwtAccess'); + $scope = 'scope/1'; $audience = 'https://example.com/service'; $testJson = $this->createTestJson(); @@ -525,7 +514,7 @@ public function testAuthUriIsNotSet() $this->assertNotNull($sa); $update_metadata = $sa->getUpdateMetadataFunc(); - $this->assertInternalType('callable', $update_metadata); + $this->assertTrue(is_callable($update_metadata)); $actual_metadata = call_user_func( $update_metadata, @@ -555,7 +544,7 @@ public function testUpdateMetadataFunc() $this->assertNotNull($sa); $update_metadata = $sa->getUpdateMetadataFunc(); - $this->assertInternalType('callable', $update_metadata); + $this->assertTrue(is_callable($update_metadata)); $actual_metadata = call_user_func( $update_metadata, @@ -568,10 +557,10 @@ public function testUpdateMetadataFunc() ); $authorization = $actual_metadata[CredentialsLoader::AUTH_METADATA_KEY]; - $this->assertInternalType('array', $authorization); + $this->assertTrue(is_array($authorization)); $bearer_token = current($authorization); - $this->assertInternalType('string', $bearer_token); + $this->assertTrue(is_string($bearer_token)); $this->assertEquals(0, strpos($bearer_token, 'Bearer ')); $this->assertGreaterThan(30, strlen($bearer_token)); @@ -586,10 +575,10 @@ public function testUpdateMetadataFunc() ); $authorization2 = $actual_metadata2[CredentialsLoader::AUTH_METADATA_KEY]; - $this->assertInternalType('array', $authorization2); + $this->assertTrue(is_array($authorization2)); $bearer_token2 = current($authorization2); - $this->assertInternalType('string', $bearer_token2); + $this->assertTrue(is_string($bearer_token2)); $this->assertEquals(0, strpos($bearer_token2, 'Bearer ')); $this->assertGreaterThan(30, strlen($bearer_token2)); $this->assertNotEquals($bearer_token2, $bearer_token); @@ -600,7 +589,7 @@ class SACJwtAccessComboTest extends TestCase { private $privateKey; - public function setUp() + public function setUp(): void { $this->privateKey = file_get_contents(__DIR__ . '/../fixtures' . '/private.pem'); @@ -627,7 +616,7 @@ public function testNoScopeUseJwtAccess() $this->assertNotNull($sa); $update_metadata = $sa->getUpdateMetadataFunc(); - $this->assertInternalType('callable', $update_metadata); + $this->assertTrue(is_callable($update_metadata)); $actual_metadata = call_user_func( $update_metadata, @@ -640,10 +629,10 @@ public function testNoScopeUseJwtAccess() ); $authorization = $actual_metadata[CredentialsLoader::AUTH_METADATA_KEY]; - $this->assertInternalType('array', $authorization); + $this->assertTrue(is_array($authorization)); $bearer_token = current($authorization); - $this->assertInternalType('string', $bearer_token); + $this->assertTrue(is_string($bearer_token)); $this->assertEquals(0, strpos($bearer_token, 'Bearer ')); $this->assertGreaterThan(30, strlen($bearer_token)); } @@ -671,10 +660,10 @@ public function testUpdateMetadataWithScopeAndUseJwtAccessWithScopeParameter() ); $authorization = $actual_metadata[CredentialsLoader::AUTH_METADATA_KEY]; - $this->assertInternalType('array', $authorization); + $this->assertTrue(is_array($authorization)); $bearer_token = current($authorization); - $this->assertInternalType('string', $bearer_token); + $this->assertTrue(is_string($bearer_token)); $this->assertEquals(0, strpos($bearer_token, 'Bearer ')); // Ensure scopes are signed inside @@ -682,7 +671,7 @@ public function testUpdateMetadataWithScopeAndUseJwtAccessWithScopeParameter() $this->assertEquals(2, substr_count($token, '.')); list($header, $payload, $sig) = explode('.', $bearer_token); $json = json_decode(base64_decode($payload), true); - $this->assertInternalType('array', $json); + $this->assertTrue(is_array($json)); $this->assertArrayHasKey('scope', $json); $this->assertEquals($json['scope'], $scope); } @@ -710,10 +699,10 @@ public function testUpdateMetadataWithScopeAndUseJwtAccessWithScopeParameterAndA ); $authorization = $actual_metadata[CredentialsLoader::AUTH_METADATA_KEY]; - $this->assertInternalType('array', $authorization); + $this->assertTrue(is_array($authorization)); $bearer_token = current($authorization); - $this->assertInternalType('string', $bearer_token); + $this->assertTrue(is_string($bearer_token)); $this->assertEquals(0, strpos($bearer_token, 'Bearer ')); // Ensure scopes are signed inside @@ -721,13 +710,13 @@ public function testUpdateMetadataWithScopeAndUseJwtAccessWithScopeParameterAndA $this->assertEquals(2, substr_count($token, '.')); list($header, $payload, $sig) = explode('.', $bearer_token); $json = json_decode(base64_decode($payload), true); - $this->assertInternalType('array', $json); + $this->assertTrue(is_array($json)); $this->assertArrayHasKey('scope', $json); $this->assertEquals($json['scope'], implode(' ', $scope)); // Test last received token $cachedToken = $sa->getLastReceivedToken(); - $this->assertInternalType('array', $cachedToken); + $this->assertTrue(is_array($cachedToken)); $this->assertArrayHasKey('access_token', $cachedToken); $this->assertEquals($token, $cachedToken['access_token']); } @@ -745,7 +734,7 @@ public function testFetchAuthTokenWithScopeAndUseJwtAccessWithScopeParameter() $sa->useJwtAccessWithScope(); $access_token = $sa->fetchAuthToken(); - $this->assertInternalType('array', $access_token); + $this->assertTrue(is_array($access_token)); $this->assertArrayHasKey('access_token', $access_token); $token = $access_token['access_token']; @@ -753,7 +742,7 @@ public function testFetchAuthTokenWithScopeAndUseJwtAccessWithScopeParameter() $this->assertEquals(2, substr_count($token, '.')); list($header, $payload, $sig) = explode('.', $token); $json = json_decode(base64_decode($payload), true); - $this->assertInternalType('array', $json); + $this->assertTrue(is_array($json)); $this->assertArrayHasKey('scope', $json); $this->assertEquals($json['scope'], $scope); } @@ -771,7 +760,7 @@ public function testFetchAuthTokenWithScopeAndUseJwtAccessWithScopeParameterAndA $sa->useJwtAccessWithScope(); $access_token = $sa->fetchAuthToken(); - $this->assertInternalType('array', $access_token); + $this->assertTrue(is_array($access_token)); $this->assertArrayHasKey('access_token', $access_token); $token = $access_token['access_token']; @@ -779,13 +768,13 @@ public function testFetchAuthTokenWithScopeAndUseJwtAccessWithScopeParameterAndA $this->assertEquals(2, substr_count($token, '.')); list($header, $payload, $sig) = explode('.', $token); $json = json_decode(base64_decode($payload), true); - $this->assertInternalType('array', $json); + $this->assertTrue(is_array($json)); $this->assertArrayHasKey('scope', $json); $this->assertEquals($json['scope'], implode(' ', $scope)); // Test last received token $cachedToken = $sa->getLastReceivedToken(); - $this->assertInternalType('array', $cachedToken); + $this->assertTrue(is_array($cachedToken)); $this->assertArrayHasKey('access_token', $cachedToken); $this->assertEquals($token, $cachedToken['access_token']); } @@ -811,12 +800,7 @@ public function testJwtAccessFromApplicationDefault() $token = str_replace('Bearer ', '', $metadata['authorization'][0]); $key = file_get_contents(__DIR__ . '/../fixtures3/key.pub'); - $class = 'JWT'; - if (class_exists('Firebase\JWT\JWT')) { - $class = 'Firebase\JWT\JWT'; - } - $jwt = new $class(); - $result = $jwt::decode($token, $key, ['RS256']); + $result = JWT::decode($token, $key, ['RS256']); $this->assertEquals($authUri, $result->aud); } @@ -834,7 +818,7 @@ public function testNoScopeAndNoAuthUri() $this->assertNotNull($sa); $update_metadata = $sa->getUpdateMetadataFunc(); - $this->assertInternalType('callable', $update_metadata); + $this->assertTrue(is_callable($update_metadata)); $actual_metadata = call_user_func( $update_metadata, @@ -843,7 +827,7 @@ public function testNoScopeAndNoAuthUri() ); // no access_token is added to the metadata hash // but also, no error should be thrown - $this->assertInternalType('array', $actual_metadata); + $this->assertTrue(is_array($actual_metadata)); $this->assertArrayNotHasKey( CredentialsLoader::AUTH_METADATA_KEY, $actual_metadata @@ -871,10 +855,10 @@ public function testUpdateMetadataJwtAccess() ); $authorization = $metadata[CredentialsLoader::AUTH_METADATA_KEY]; - $this->assertInternalType('array', $authorization); + $this->assertTrue(is_array($authorization)); $bearerToken = current($authorization); - $this->assertInternalType('string', $bearerToken); + $this->assertTrue(is_string($bearerToken)); $this->assertEquals(0, strpos($bearerToken, 'Bearer ')); $token = str_replace('Bearer ', '', $bearerToken); diff --git a/tests/Credentials/UserRefreshCredentialsTest.php b/tests/Credentials/UserRefreshCredentialsTest.php index b9024f07b..fd4649d5c 100644 --- a/tests/Credentials/UserRefreshCredentialsTest.php +++ b/tests/Credentials/UserRefreshCredentialsTest.php @@ -17,10 +17,13 @@ namespace Google\Auth\Tests\Credentials; +use DomainException; use Google\Auth\ApplicationDefaultCredentials; use Google\Auth\Credentials\UserRefreshCredentials; use Google\Auth\OAuth2; use GuzzleHttp\Psr7\Utils; +use InvalidArgumentException; +use LogicException; use PHPUnit\Framework\TestCase; // Creates a standard JSON auth object for testing. @@ -54,11 +57,9 @@ public function testShouldBeTheSameAsOAuth2WithTheSameScope() class URCConstructorTest extends TestCase { - /** - * @expectedException InvalidArgumentException - */ public function testShouldFailIfScopeIsNotAValidType() { + $this->expectException(InvalidArgumentException::class); $testJson = createURCTestJson(); $notAnArrayOrString = new \stdClass(); $sa = new UserRefreshCredentials( @@ -67,11 +68,9 @@ public function testShouldFailIfScopeIsNotAValidType() ); } - /** - * @expectedException InvalidArgumentException - */ public function testShouldFailIfJsonDoesNotHaveClientSecret() { + $this->expectException(InvalidArgumentException::class); $testJson = createURCTestJson(); unset($testJson['client_secret']); $scope = ['scope/1', 'scope/2']; @@ -81,11 +80,9 @@ public function testShouldFailIfJsonDoesNotHaveClientSecret() ); } - /** - * @expectedException InvalidArgumentException - */ public function testShouldFailIfJsonDoesNotHaveRefreshToken() { + $this->expectException(InvalidArgumentException::class); $testJson = createURCTestJson(); unset($testJson['refresh_token']); $scope = ['scope/1', 'scope/2']; @@ -95,11 +92,9 @@ public function testShouldFailIfJsonDoesNotHaveRefreshToken() ); } - /** - * @expectedException InvalidArgumentException - */ public function testShouldFailIfJsonDoesNotHaveClientId() { + $this->expectException(InvalidArgumentException::class); $testJson = createURCTestJson(); unset($testJson['client_id']); $scope = ['scope/1', 'scope/2']; @@ -109,11 +104,9 @@ public function testShouldFailIfJsonDoesNotHaveClientId() ); } - /** - * @expectedException InvalidArgumentException - */ public function testFailsToInitalizeFromANonExistentFile() { + $this->expectException(InvalidArgumentException::class); $keyFile = __DIR__ . '/../fixtures/does-not-exist-private.json'; new UserRefreshCredentials('scope/1', $keyFile); } @@ -126,11 +119,10 @@ public function testInitalizeFromAFile() ); } - /** - * @expectedException LogicException - */ public function testFailsToInitializeFromInvalidJsonData() { + $this->expectException(LogicException::class); + $tmp = tmpfile(); fwrite($tmp, '{'); @@ -155,7 +147,7 @@ public function testValid3LOauthCreds() class URCFromEnvTest extends TestCase { - protected function tearDown() + protected function tearDown(): void { putenv(UserRefreshCredentials::ENV_VAR); // removes it from } @@ -165,11 +157,9 @@ public function testIsNullIfEnvVarIsNotSet() $this->assertNull(UserRefreshCredentials::fromEnv('a scope')); } - /** - * @expectedException DomainException - */ public function testFailsIfEnvSpecifiesNonExistentFile() { + $this->expectException(DomainException::class); $keyFile = __DIR__ . '/../fixtures/does-not-exist-private.json'; putenv(UserRefreshCredentials::ENV_VAR . '=' . $keyFile); UserRefreshCredentials::fromEnv('a scope'); @@ -187,12 +177,12 @@ class URCFromWellKnownFileTest extends TestCase { private $originalHome; - protected function setUp() + protected function setUp(): void { $this->originalHome = getenv('HOME'); } - protected function tearDown() + protected function tearDown(): void { if ($this->originalHome != getenv('HOME')) { putenv('HOME=' . $this->originalHome); @@ -218,11 +208,9 @@ public function testSucceedIfFileIsPresent() class URCFetchAuthTokenTest extends TestCase { - /** - * @expectedException GuzzleHttp\Exception\ClientException - */ public function testFailsOnClientErrors() { + $this->expectException(\GuzzleHttp\Exception\ClientException::class); $testJson = createURCTestJson(); $scope = ['scope/1', 'scope/2']; $httpHandler = getHandler([ @@ -235,11 +223,9 @@ public function testFailsOnClientErrors() $sa->fetchAuthToken($httpHandler); } - /** - * @expectedException GuzzleHttp\Exception\ServerException - */ public function testFailsOnServerErrors() { + $this->expectException(\GuzzleHttp\Exception\ServerException::class); $testJson = createURCTestJson(); $scope = ['scope/1', 'scope/2']; $httpHandler = getHandler([ diff --git a/tests/CredentialsLoaderTest.php b/tests/CredentialsLoaderTest.php index 27d1c3e25..770d9195a 100644 --- a/tests/CredentialsLoaderTest.php +++ b/tests/CredentialsLoaderTest.php @@ -19,6 +19,8 @@ use Google\Auth\CredentialsLoader; use PHPUnit\Framework\TestCase; +use RuntimeException; +use UnexpectedValueException; class CredentialsLoaderTest extends TestCase { @@ -53,11 +55,12 @@ public function testNonExistantDefaultClientCertSource() /** * @runInSeparateProcess - * @expectedException UnexpectedValueException - * @expectedExceptionMessage Invalid client cert source JSON */ public function testDefaultClientCertSourceInvalidJsonThrowsException() { + $this->expectException(UnexpectedValueException::class); + $this->expectExceptionMessage('Invalid client cert source JSON'); + putenv('HOME=' . __DIR__ . '/fixtures4/invalidjson'); CredentialsLoader::getDefaultClientCertSource(); @@ -65,11 +68,12 @@ public function testDefaultClientCertSourceInvalidJsonThrowsException() /** * @runInSeparateProcess - * @expectedException UnexpectedValueException - * @expectedExceptionMessage cert source requires "cert_provider_command" */ public function testDefaultClientCertSourceInvalidKeyThrowsException() { + $this->expectException(UnexpectedValueException::class); + $this->expectExceptionMessage('cert source requires "cert_provider_command"'); + putenv('HOME=' . __DIR__ . '/fixtures4/invalidkey'); CredentialsLoader::getDefaultClientCertSource(); @@ -77,11 +81,12 @@ public function testDefaultClientCertSourceInvalidKeyThrowsException() /** * @runInSeparateProcess - * @expectedException UnexpectedValueException - * @expectedExceptionMessage cert source expects "cert_provider_command" to be an array */ public function testDefaultClientCertSourceInvalidValueThrowsException() { + $this->expectException(UnexpectedValueException::class); + $this->expectExceptionMessage('cert source expects "cert_provider_command" to be an array'); + putenv('HOME=' . __DIR__ . '/fixtures4/invalidvalue'); CredentialsLoader::getDefaultClientCertSource(); @@ -98,17 +103,18 @@ public function testActualDefaultClientCertSource() } $creds = $clientCertSource(); $this->assertTrue(is_string($creds)); - $this->assertContains('-----BEGIN CERTIFICATE-----', $creds); - $this->assertContains('-----BEGIN PRIVATE KEY-----', $creds); + $this->assertStringContainsString('-----BEGIN CERTIFICATE-----', $creds); + $this->assertStringContainsString('-----BEGIN PRIVATE KEY-----', $creds); } /** * @runInSeparateProcess - * @expectedException RuntimeException - * @expectedExceptionMessage "cert_provider_command" failed with a nonzero exit code */ public function testDefaultClientCertSourceInvalidCmdThrowsException() { + $this->expectException(RuntimeException::class); + $this->expectExceptionMessage('"cert_provider_command" failed with a nonzero exit code'); + putenv('HOME=' . __DIR__ . '/fixtures4/invalidcmd'); $callback = CredentialsLoader::getDefaultClientCertSource(); diff --git a/tests/FetchAuthTokenCacheTest.php b/tests/FetchAuthTokenCacheTest.php index 48f2e038f..088540d34 100644 --- a/tests/FetchAuthTokenCacheTest.php +++ b/tests/FetchAuthTokenCacheTest.php @@ -22,6 +22,7 @@ use Google\Auth\CredentialsLoader; use Google\Auth\FetchAuthTokenCache; use Prophecy\Argument; +use RuntimeException; class FetchAuthTokenCacheTest extends BaseTest { @@ -30,7 +31,7 @@ class FetchAuthTokenCacheTest extends BaseTest private $mockCache; private $mockSigner; - protected function setUp() + protected function setUp(): void { $this->mockFetcher = $this->prophesize(); $this->mockFetcher->willImplement('Google\Auth\FetchAuthTokenInterface'); @@ -156,9 +157,11 @@ public function testUpdateMetadataWithoutCache() ->shouldBeCalled() ->willReturn($value); $this->mockCacheItem->set($value) - ->shouldBeCalledTimes(1); + ->shouldBeCalledTimes(1) + ->willReturn($this->mockCacheItem->reveal()); $this->mockCacheItem->expiresAfter(1500) - ->shouldBeCalledTimes(1); + ->shouldBeCalledTimes(1) + ->willReturn($this->mockCacheItem->reveal()); $this->mockCache->save($this->mockCacheItem) ->shouldBeCalledTimes(1); $this->mockFetcher->updateMetadata(Argument::type('array'), null, null) @@ -208,10 +211,10 @@ public function testUpdateMetadataWithJwtAccess() ); $authorization = $metadata[CredentialsLoader::AUTH_METADATA_KEY]; - $this->assertInternalType('array', $authorization); + $this->assertTrue(is_array($authorization)); $bearerToken = current($authorization); - $this->assertInternalType('string', $bearerToken); + $this->assertTrue(is_string($bearerToken)); $this->assertEquals(0, strpos($bearerToken, 'Bearer ')); $token = str_replace('Bearer ', '', $bearerToken); @@ -228,12 +231,11 @@ public function testUpdateMetadataWithJwtAccess() $this->assertNotEquals($metadata, $metadata3); } - /** - * @expectedException RuntimeException - * @expectedExceptionMessage Credentials fetcher does not implement Google\Auth\UpdateMetadataInterface - */ public function testUpdateMetadataWithInvalidFetcher() { + $this->expectException(RuntimeException::class); + $this->expectExceptionMessage('Credentials fetcher does not implement Google\Auth\UpdateMetadataInterface'); + $mockFetcher = $this->prophesize('Google\Auth\FetchAuthTokenInterface'); // Run the test. @@ -299,9 +301,11 @@ public function testShouldNotReturnValueWhenExpired() ->shouldBeCalledTimes(1) ->willReturn($cachedValue); $this->mockCacheItem->set($newToken) - ->shouldBeCalledTimes(1); + ->shouldBeCalledTimes(1) + ->willReturn($this->mockCacheItem->reveal()); $this->mockCacheItem->expiresAfter(1500) - ->shouldBeCalledTimes(1); + ->shouldBeCalledTimes(1) + ->willReturn($this->mockCacheItem->reveal()); $this->mockCache->getItem($cacheKey) ->shouldBeCalledTimes(2) ->willReturn($this->mockCacheItem->reveal()); @@ -368,9 +372,10 @@ public function testShouldSaveValueInCacheWithCacheOptions() ->willReturn(false); $this->mockCacheItem->set($cachedValue) ->shouldBeCalledTimes(1) - ->willReturn(false); + ->willReturn($this->mockCacheItem->reveal()); $this->mockCacheItem->expiresAfter($lifetime) - ->shouldBeCalledTimes(1); + ->shouldBeCalledTimes(1) + ->willReturn($this->mockCacheItem->reveal()); $this->mockCache->getItem($prefix . $cacheKey) ->shouldBeCalledTimes(2) ->willReturn($this->mockCacheItem->reveal()); @@ -429,12 +434,11 @@ public function testGetClientName() $this->assertEquals($name, $fetcher->getClientName()); } - /** - * @expectedException RuntimeException - * @expectedExceptionMessage Credentials fetcher does not implement Google\Auth\SignBlobInterface - */ public function testGetClientNameWithInvalidFetcher() { + $this->expectException(RuntimeException::class); + $this->expectExceptionMessage('Credentials fetcher does not implement Google\Auth\SignBlobInterface'); + $mockFetcher = $this->prophesize('Google\Auth\FetchAuthTokenInterface'); // Run the test. @@ -500,11 +504,10 @@ public function testGCECredentialsSignBlob() $this->assertEquals($signature, $fetcher->signBlob($stringToSign, true)); } - /** - * @expectedException RuntimeException - */ public function testSignBlobInvalidFetcher() { + $this->expectException(RuntimeException::class); + $this->mockFetcher->signBlob('test') ->shouldNotbeCalled(); @@ -536,11 +539,10 @@ public function testGetProjectId() $this->assertEquals($projectId, $fetcher->getProjectId()); } - /** - * @expectedException RuntimeException - */ public function testGetProjectIdInvalidFetcher() { + $this->expectException(RuntimeException::class); + $mockFetcher = $this->prophesize('Google\Auth\FetchAuthTokenInterface'); $mockFetcher->getProjectId() ->shouldNotbeCalled(); diff --git a/tests/GCECacheTest.php b/tests/GCECacheTest.php index 1ddc2ff13..d91804013 100644 --- a/tests/GCECacheTest.php +++ b/tests/GCECacheTest.php @@ -26,7 +26,7 @@ class GCECacheTest extends BaseTest private $mockCacheItem; private $mockCache; - protected function setUp() + protected function setUp(): void { $this->mockCacheItem = $this->prophesize('Psr\Cache\CacheItemInterface'); $this->mockCache = $this->prophesize('Psr\Cache\CacheItemPoolInterface'); @@ -86,9 +86,11 @@ public function testUncached() ->shouldBeCalledTimes(1) ->willReturn(false); $this->mockCacheItem->set(true) - ->shouldBeCalledTimes(1); + ->shouldBeCalledTimes(1) + ->willReturn($this->mockCacheItem->reveal()); $this->mockCacheItem->expiresAfter(1500) - ->shouldBeCalledTimes(1); + ->shouldBeCalledTimes(1) + ->willReturn($this->mockCacheItem->reveal()); $this->mockCache->getItem(GCECache::GCE_CACHE_KEY) ->shouldBeCalledTimes(2) ->willReturn($this->mockCacheItem->reveal()); @@ -139,9 +141,11 @@ public function testShouldSaveValueInCacheWithCacheOptions() $this->mockCacheItem->isHit() ->willReturn(false); $this->mockCacheItem->set(true) - ->shouldBeCalledTimes(1); + ->shouldBeCalledTimes(1) + ->willReturn($this->mockCacheItem->reveal()); $this->mockCacheItem->expiresAfter($lifetime) - ->shouldBeCalledTimes(1); + ->shouldBeCalledTimes(1) + ->willReturn($this->mockCacheItem->reveal()); $this->mockCache->getItem($prefix . GCECache::GCE_CACHE_KEY) ->shouldBeCalledTimes(2) ->willReturn($this->mockCacheItem->reveal()); diff --git a/tests/HttpHandler/Guzzle5HttpHandlerTest.php b/tests/HttpHandler/Guzzle5HttpHandlerTest.php deleted file mode 100644 index f2e0e4d59..000000000 --- a/tests/HttpHandler/Guzzle5HttpHandlerTest.php +++ /dev/null @@ -1,240 +0,0 @@ -onlyGuzzle5(); - - $uri = $this->prophesize('Psr\Http\Message\UriInterface'); - $body = $this->prophesize('Psr\Http\Message\StreamInterface'); - - $this->mockPsr7Request = $this->prophesize('Psr\Http\Message\RequestInterface'); - $this->mockPsr7Request->getMethod()->willReturn('GET'); - $this->mockPsr7Request->getUri()->willReturn($uri->reveal()); - $this->mockPsr7Request->getHeaders()->willReturn([]); - $this->mockPsr7Request->getBody()->willReturn($body->reveal()); - - $this->mockRequest = $this->prophesize('GuzzleHttp\Message\RequestInterface'); - $this->mockClient = $this->prophesize('GuzzleHttp\Client'); - $this->mockFuture = $this->prophesize('GuzzleHttp\Ring\Future\FutureInterface'); - } - - public function testSuccessfullySendsRealRequest() - { - $request = new \GuzzleHttp\Psr7\Request('get', 'https://httpbin.org/get'); - $client = new \GuzzleHttp\Client(); - $handler = new Guzzle5HttpHandler($client); - $response = $handler($request); - $this->assertInstanceOf('Psr\Http\Message\ResponseInterface', $response); - $this->assertEquals(200, $response->getStatusCode()); - $json = json_decode((string) $response->getBody(), true); - $this->assertArrayHasKey('url', $json); - $this->assertEquals((string) $request->getUri(), $json['url']); - } - - public function testSuccessfullySendsMockRequest() - { - $response = new Response( - 200, - [], - Stream::factory('Body Text') - ); - $this->mockClient->send(Argument::type('GuzzleHttp\Message\RequestInterface')) - ->willReturn($response); - $this->mockClient->createRequest( - 'GET', - Argument::type('Psr\Http\Message\UriInterface'), - Argument::type('array') - )->willReturn($this->mockRequest->reveal()); - - $handler = new Guzzle5HttpHandler($this->mockClient->reveal()); - $response = $handler($this->mockPsr7Request->reveal()); - $this->assertInstanceOf('Psr\Http\Message\ResponseInterface', $response); - $this->assertEquals(200, $response->getStatusCode()); - $this->assertEquals('Body Text', (string) $response->getBody()); - } - - public function testAsyncWithoutGuzzlePromiseThrowsException() - { - // Pretend the promise library doesn't exist - foreach (spl_autoload_functions() as $function) { - if ($function[0] instanceof ClassLoader) { - $newAutoloader = clone $function[0]; - $newAutoloader->setPsr4('GuzzleHttp\\Promise\\', '/tmp'); - spl_autoload_register($newAutoloadFunc = [$newAutoloader, 'loadClass']); - spl_autoload_unregister($previousAutoloadFunc = $function); - } - } - - $this->mockClient->send(Argument::type('GuzzleHttp\Message\RequestInterface')) - ->willReturn(new FutureResponse($this->mockFuture->reveal())); - $this->mockClient->createRequest('GET', Argument::type('Psr\Http\Message\UriInterface'), Argument::allOf( - Argument::withEntry('headers', []), - Argument::withEntry('future', true), - Argument::that(function ($arg) { - return $arg['body'] instanceof StreamInterface; - }) - ))->willReturn($this->mockRequest->reveal()); - - $handler = new Guzzle5HttpHandler($this->mockClient->reveal()); - $errorThrown = false; - try { - $handler->async($this->mockPsr7Request->reveal()); - } catch (Exception $e) { - $this->assertEquals( - 'Install guzzlehttp/promises to use async with Guzzle 5', - $e->getMessage() - ); - $errorThrown = true; - } - - // Restore autoloader before assertion (in case it fails) - spl_autoload_register($previousAutoloadFunc); - spl_autoload_unregister($newAutoloadFunc); - - $this->assertTrue($errorThrown); - } - - public function testSuccessfullySendsRequestAsync() - { - $response = new Response( - 200, - [], - Stream::factory('Body Text') - ); - $this->mockClient->send(Argument::type('GuzzleHttp\Message\RequestInterface')) - ->willReturn(new FutureResponse( - new CompletedFutureValue($response) - )); - $this->mockClient->createRequest('GET', Argument::type('Psr\Http\Message\UriInterface'), Argument::allOf( - Argument::withEntry('headers', []), - Argument::withEntry('future', true), - Argument::that(function ($arg) { - return $arg['body'] instanceof StreamInterface; - }) - ))->willReturn($this->mockRequest->reveal()); - - $handler = new Guzzle5HttpHandler($this->mockClient->reveal()); - $promise = $handler->async($this->mockPsr7Request->reveal()); - $this->assertInstanceOf('Psr\Http\Message\ResponseInterface', $promise->wait()); - $this->assertEquals(200, $response->getStatusCode()); - $this->assertEquals('Body Text', (string) $response->getBody()); - } - - /** - * @expectedException Exception - * @expectedExceptionMessage This is a test rejection message - */ - public function testPromiseHandlesException() - { - $this->mockClient->send(Argument::type('GuzzleHttp\Message\RequestInterface')) - ->willReturn(new FutureResponse( - (new CompletedFutureValue(new Response(200)))->then(function () { - throw new Exception('This is a test rejection message'); - }) - )); - $this->mockClient->createRequest('GET', Argument::type('Psr\Http\Message\UriInterface'), Argument::allOf( - Argument::withEntry('headers', []), - Argument::withEntry('future', true), - Argument::that(function ($arg) { - return $arg['body'] instanceof StreamInterface; - }) - ))->willReturn($this->mockRequest->reveal()); - - $handler = new Guzzle5HttpHandler($this->mockClient->reveal()); - $promise = $handler->async($this->mockPsr7Request->reveal()); - $promise->wait(); - } - - public function testCreateGuzzle5Request() - { - $requestHeaders = [ - 'header1' => 'value1', - 'header2' => 'value2', - ]; - $this->mockPsr7Request->getHeaders() - ->shouldBeCalledTimes(1) - ->willReturn($requestHeaders); - $mockBody = $this->prophesize('Psr\Http\Message\StreamInterface'); - $this->mockPsr7Request->getBody() - ->shouldBeCalledTimes(1) - ->willReturn($mockBody->reveal()); - - $mockGuzzleRequest = $this->prophesize('GuzzleHttp\Message\RequestInterface'); - $this->mockClient->createRequest( - 'GET', - Argument::type('Psr\Http\Message\UriInterface'), - [ - 'headers' => $requestHeaders + ['header3' => 'value3'], - 'body' => $mockBody->reveal(), - ] - )->shouldBeCalledTimes(1)->willReturn( - $mockGuzzleRequest->reveal() - ); - - $this->mockClient->send(Argument::type('GuzzleHttp\Message\RequestInterface')) - ->shouldBeCalledTimes(1) - ->willReturn($this->getGuzzle5ResponseMock()->reveal()); - - $handler = new Guzzle5HttpHandler($this->mockClient->reveal()); - $handler($this->mockPsr7Request->reveal(), [ - 'headers' => [ - 'header3' => 'value3' - ] - ]); - } - - private function getGuzzle5ResponseMock() - { - $responseMock = $this->prophesize('GuzzleHttp\Message\ResponseInterface'); - $responseMock->getStatusCode()->willReturn(200); - $responseMock->getHeaders()->willReturn([]); - $responseMock->getProtocolVersion()->willReturn(''); - $responseMock->getReasonPhrase()->willReturn(''); - - $res = $this->prophesize('GuzzleHttp\Stream\StreamInterface'); - $res->__toString()->willReturn(''); - $responseMock->getBody()->willReturn( - $res->reveal() - ); - - return $responseMock; - } -} diff --git a/tests/HttpHandler/Guzzle6HttpHandlerTest.php b/tests/HttpHandler/Guzzle6HttpHandlerTest.php index b86d94d68..715da29c8 100644 --- a/tests/HttpHandler/Guzzle6HttpHandlerTest.php +++ b/tests/HttpHandler/Guzzle6HttpHandlerTest.php @@ -31,7 +31,7 @@ class Guzzle6HttpHandlerTest extends BaseTest protected $client; protected $handler; - public function setUp() + public function setUp(): void { $this->onlyGuzzle6(); diff --git a/tests/HttpHandler/Guzzle7HttpHandlerTest.php b/tests/HttpHandler/Guzzle7HttpHandlerTest.php index f6eaa6360..375f72cbf 100644 --- a/tests/HttpHandler/Guzzle7HttpHandlerTest.php +++ b/tests/HttpHandler/Guzzle7HttpHandlerTest.php @@ -24,7 +24,7 @@ */ class Guzzle7HttpHandlerTest extends Guzzle6HttpHandlerTest { - public function setUp() + public function setUp(): void { $this->onlyGuzzle7(); diff --git a/tests/HttpHandler/HttpHandlerFactoryTest.php b/tests/HttpHandler/HttpHandlerFactoryTest.php index f0673f819..ba076053f 100644 --- a/tests/HttpHandler/HttpHandlerFactoryTest.php +++ b/tests/HttpHandler/HttpHandlerFactoryTest.php @@ -23,15 +23,6 @@ class HttpHandlerFactoryTest extends BaseTest { - public function testBuildsGuzzle5Handler() - { - $this->onlyGuzzle5(); - - HttpClientCache::setHttpClient(null); - $handler = HttpHandlerFactory::build(); - $this->assertInstanceOf('Google\Auth\HttpHandler\Guzzle5HttpHandler', $handler); - } - public function testBuildsGuzzle6Handler() { $this->onlyGuzzle6(); diff --git a/tests/Middleware/AuthTokenMiddlewareTest.php b/tests/Middleware/AuthTokenMiddlewareTest.php index 6692804bc..a9e7aa6ec 100644 --- a/tests/Middleware/AuthTokenMiddlewareTest.php +++ b/tests/Middleware/AuthTokenMiddlewareTest.php @@ -31,10 +31,8 @@ class AuthTokenMiddlewareTest extends BaseTest private $mockCache; private $mockRequest; - protected function setUp() + protected function setUp(): void { - $this->onlyGuzzle6And7(); - $this->mockFetcher = $this->prophesize('Google\Auth\FetchAuthTokenInterface'); $this->mockCacheItem = $this->prophesize('Psr\Cache\CacheItemInterface'); $this->mockCache = $this->prophesize('Psr\Cache\CacheItemPoolInterface'); @@ -91,8 +89,10 @@ public function testUsesIdTokenWhenAccessTokenDoesNotExist() $token = 'idtoken12345'; $authResult = ['id_token' => $token]; $this->mockFetcher->fetchAuthToken(Argument::any()) + ->shouldBeCalledTimes(1) ->willReturn($authResult); $this->mockRequest->withHeader('authorization', 'Bearer ' . $token) + ->shouldBeCalledTimes(1) ->willReturn($this->mockRequest); $middleware = new AuthTokenMiddleware($this->mockFetcher->reveal()); @@ -220,9 +220,10 @@ public function testShouldSaveValueInCacheWithSpecifiedPrefix() ->willReturn(false); $this->mockCacheItem->set($cachedValue) ->shouldBeCalledTimes(1) - ->willReturn(false); + ->willReturn($this->mockCacheItem->reveal()); $this->mockCacheItem->expiresAfter($lifetime) - ->shouldBeCalledTimes(1); + ->shouldBeCalledTimes(1) + ->willReturn($this->mockCacheItem->reveal()); $this->mockCache->getItem($prefix . $cacheKey) ->shouldBeCalled() ->willReturn($this->mockCacheItem->reveal()); @@ -264,9 +265,11 @@ public function testShouldNotifyTokenCallback(callable $tokenCallback) $this->mockCacheItem->isHit() ->willReturn(false); $this->mockCacheItem->set($cachedValue) - ->shouldBeCalled(); + ->shouldBeCalled() + ->willReturn($this->mockCacheItem->reveal()); $this->mockCacheItem->expiresAfter(Argument::any()) - ->shouldBeCalled(); + ->shouldBeCalled() + ->willReturn($this->mockCacheItem->reveal()); $this->mockCache->getItem($prefix . $cacheKey) ->willReturn($this->mockCacheItem->reveal()); $this->mockCache->save(Argument::type('Psr\Cache\CacheItemInterface')) diff --git a/tests/Middleware/ProxyAuthTokenMiddlewareTest.php b/tests/Middleware/ProxyAuthTokenMiddlewareTest.php index 1a94b5b9d..138bccab7 100644 --- a/tests/Middleware/ProxyAuthTokenMiddlewareTest.php +++ b/tests/Middleware/ProxyAuthTokenMiddlewareTest.php @@ -29,10 +29,8 @@ class ProxyAuthTokenMiddlewareTest extends BaseTest private $mockFetcher; private $mockRequest; - protected function setUp() + protected function setUp(): void { - $this->onlyGuzzle6And7(); - $this->mockFetcher = $this->prophesize('Google\Auth\FetchAuthTokenInterface'); $this->mockRequest = $this->prophesize('GuzzleHttp\Psr7\Request'); } diff --git a/tests/Middleware/ScopedAccessTokenMiddlewareTest.php b/tests/Middleware/ScopedAccessTokenMiddlewareTest.php index 174efbf11..a7b31650a 100644 --- a/tests/Middleware/ScopedAccessTokenMiddlewareTest.php +++ b/tests/Middleware/ScopedAccessTokenMiddlewareTest.php @@ -21,6 +21,7 @@ use Google\Auth\Tests\BaseTest; use GuzzleHttp\Handler\MockHandler; use GuzzleHttp\Psr7\Response; +use InvalidArgumentException; use Prophecy\Argument; class ScopedAccessTokenMiddlewareTest extends BaseTest @@ -31,20 +32,17 @@ class ScopedAccessTokenMiddlewareTest extends BaseTest private $mockCache; private $mockRequest; - protected function setUp() + protected function setUp(): void { - $this->onlyGuzzle6And7(); - $this->mockCacheItem = $this->prophesize('Psr\Cache\CacheItemInterface'); $this->mockCache = $this->prophesize('Psr\Cache\CacheItemPoolInterface'); $this->mockRequest = $this->prophesize('GuzzleHttp\Psr7\Request'); } - /** - * @expectedException InvalidArgumentException - */ public function testRequiresScopeAsAStringOrArray() { + $this->expectException(InvalidArgumentException::class); + $fakeAuthFunc = function ($unused_scopes) { return '1/abcdef1234567890'; }; @@ -142,9 +140,10 @@ public function testShouldSaveValueInCache() ->willReturn(false); $this->mockCacheItem->set($token) ->shouldBeCalledTimes(1) - ->willReturn(false); + ->willReturn($this->mockCacheItem->reveal()); $this->mockCacheItem->expiresAfter(Argument::any()) - ->shouldBeCalledTimes(1); + ->shouldBeCalledTimes(1) + ->willReturn($this->mockCacheItem->reveal()); $this->mockCache->getItem($this->getValidKeyName(self::TEST_SCOPE)) ->shouldBeCalledTimes(2) ->willReturn($this->mockCacheItem->reveal()); @@ -180,9 +179,10 @@ public function testShouldSaveValueInCacheWithCacheOptions() ->willReturn(false); $this->mockCacheItem->set($token) ->shouldBeCalledTimes(1) - ->willReturn(false); + ->willReturn($this->mockCacheItem->reveal()); $this->mockCacheItem->expiresAfter($lifetime) - ->shouldBeCalledTimes(1); + ->shouldBeCalledTimes(1) + ->willReturn($this->mockCacheItem->reveal()); $this->mockCache->getItem($prefix . $this->getValidKeyName(self::TEST_SCOPE)) ->shouldBeCalledTimes(2) ->willReturn($this->mockCacheItem->reveal()); diff --git a/tests/Middleware/SimpleMiddlewareTest.php b/tests/Middleware/SimpleMiddlewareTest.php index ab34ff739..65e974a86 100644 --- a/tests/Middleware/SimpleMiddlewareTest.php +++ b/tests/Middleware/SimpleMiddlewareTest.php @@ -17,7 +17,13 @@ namespace Google\Auth\Tests\Middleware; +use Google\Auth\Middleware\SimpleMiddleware; use Google\Auth\Tests\BaseTest; +use GuzzleHttp\Handler\MockHandler; +use GuzzleHttp\Psr7\Query; +use GuzzleHttp\Psr7\Request; +use GuzzleHttp\Psr7\Response; +use Psr\Http\Message\UriInterface; class SimpleMiddlewareTest extends BaseTest { @@ -26,14 +32,33 @@ class SimpleMiddlewareTest extends BaseTest /** * @todo finish */ - protected function setUp() + protected function setUp(): void { - $this->onlyGuzzle6And7(); - - $this->mockRequest = $this->prophesize('GuzzleHttp\Psr7\Request'); + $this->mockRequest = $this->prophesize(Request::class); } - public function testTest() + public function testApiKey() { + $testKey = 'foo'; + $params = Query::build(['key' => $testKey]); + + $mockUri = $this->prophesize(UriInterface::class); + $mockUri->getQuery() + ->shouldBeCalledTimes(1) + ->willReturn(''); + $mockUri->withQuery($params) + ->shouldBeCalledTimes(1) + ->willReturn($mockUri->reveal()); + $this->mockRequest->getUri() + ->shouldBeCalledTimes(2) + ->willReturn($mockUri->reveal()); + $this->mockRequest->withUri($mockUri->reveal()) + ->shouldBeCalledTimes(1) + ->willReturn($this->mockRequest->reveal()); + + $middleware = new SimpleMiddleware(['key' => $testKey]); + $mock = new MockHandler([new Response(200)]); + $callable = $middleware($mock); + $callable($this->mockRequest->reveal(), ['auth' => 'simple']); } } diff --git a/tests/OAuth2Test.php b/tests/OAuth2Test.php index 30fafcd58..5b9719279 100644 --- a/tests/OAuth2Test.php +++ b/tests/OAuth2Test.php @@ -17,10 +17,14 @@ namespace Google\Auth\Tests; +use DomainException; +use Firebase\JWT\JWT; use Google\Auth\OAuth2; use GuzzleHttp\Psr7\Query; use GuzzleHttp\Psr7\Utils; +use InvalidArgumentException; use PHPUnit\Framework\TestCase; +use UnexpectedValueException; class OAuth2AuthorizationUriTest extends TestCase { @@ -30,20 +34,18 @@ class OAuth2AuthorizationUriTest extends TestCase 'clientId' => 'aClientID', ]; - /** - * @expectedException InvalidArgumentException - */ public function testIsNullIfAuthorizationUriIsNull() { + $this->expectException(InvalidArgumentException::class); + $o = new OAuth2([]); $this->assertNull($o->buildFullAuthorizationUri()); } - /** - * @expectedException InvalidArgumentException - */ public function testRequiresTheClientId() { + $this->expectException(InvalidArgumentException::class); + $o = new OAuth2([ 'authorizationUri' => 'https://accounts.test.org/auth/url', 'redirectUri' => 'https://accounts.test.org/redirect/url', @@ -51,11 +53,10 @@ public function testRequiresTheClientId() $o->buildFullAuthorizationUri(); } - /** - * @expectedException InvalidArgumentException - */ public function testRequiresTheRedirectUri() { + $this->expectException(InvalidArgumentException::class); + $o = new OAuth2([ 'authorizationUri' => 'https://accounts.test.org/auth/url', 'clientId' => 'aClientID', @@ -63,11 +64,10 @@ public function testRequiresTheRedirectUri() $o->buildFullAuthorizationUri(); } - /** - * @expectedException InvalidArgumentException - */ public function testCannotHavePromptAndApprovalPrompt() { + $this->expectException(InvalidArgumentException::class); + $o = new OAuth2([ 'authorizationUri' => 'https://accounts.test.org/auth/url', 'clientId' => 'aClientID', @@ -78,11 +78,10 @@ public function testCannotHavePromptAndApprovalPrompt() ]); } - /** - * @expectedException InvalidArgumentException - */ public function testCannotHaveInsecureAuthorizationUri() { + $this->expectException(InvalidArgumentException::class); + $o = new OAuth2([ 'authorizationUri' => 'http://accounts.test.org/insecure/url', 'redirectUri' => 'https://accounts.test.org/redirect/url', @@ -91,11 +90,10 @@ public function testCannotHaveInsecureAuthorizationUri() $o->buildFullAuthorizationUri(); } - /** - * @expectedException InvalidArgumentException - */ public function testCannotHaveRelativeRedirectUri() { + $this->expectException(InvalidArgumentException::class); + $o = new OAuth2([ 'authorizationUri' => 'http://accounts.test.org/insecure/url', 'redirectUri' => '/redirect/url', @@ -104,12 +102,10 @@ public function testCannotHaveRelativeRedirectUri() $o->buildFullAuthorizationUri(); } - /** - * @expectedException DomainException - * @expectedExceptionMessage one of scope or aud should not be null - */ public function testAudOrScopeIsRequiredForJwt() { + $this->expectException(DomainException::class); + $this->expectExceptionMessage('one of scope or aud should not be null'); $o = new OAuth2([]); $o->setSigningKey('a key'); $o->setSigningAlgorithm('RS256'); @@ -351,11 +347,10 @@ class OAuth2GeneralTest extends TestCase 'clientId' => 'aClientID', ]; - /** - * @expectedException InvalidArgumentException - */ public function testFailsOnUnknownSigningAlgorithm() { + $this->expectException(InvalidArgumentException::class); + $o = new OAuth2($this->minimal); $o->setSigningAlgorithm('this is definitely not an algorithm name'); } @@ -369,11 +364,10 @@ public function testAllowsKnownSigningAlgorithms() } } - /** - * @expectedException InvalidArgumentException - */ public function testFailsOnRelativeRedirectUri() { + $this->expectException(InvalidArgumentException::class); + $o = new OAuth2($this->minimal); $o->setRedirectUri('/relative/url'); } @@ -398,11 +392,9 @@ class OAuth2JwtTest extends TestCase 'clientId' => 'aClientID', ]; - /** - * @expectedException DomainException - */ public function testFailsWithMissingAudience() { + $this->expectException(DomainException::class); $testConfig = $this->signingMinimal; unset($testConfig['audience']); unset($testConfig['scope']); @@ -410,43 +402,37 @@ public function testFailsWithMissingAudience() $o->toJwt(); } - /** - * @expectedException DomainException - */ public function testFailsWithMissingIssuer() { + $this->expectException(DomainException::class); $testConfig = $this->signingMinimal; unset($testConfig['issuer']); $o = new OAuth2($testConfig); $o->toJwt(); } - /** - */ public function testCanHaveNoScope() { $testConfig = $this->signingMinimal; unset($testConfig['scope']); $o = new OAuth2($testConfig); - $o->toJwt(); + $jwt = $o->toJwt(); + $this->assertTrue(is_string($jwt)); } - /** - * @expectedException DomainException - */ public function testFailsWithMissingSigningKey() { + $this->expectException(DomainException::class); + $testConfig = $this->signingMinimal; unset($testConfig['signingKey']); $o = new OAuth2($testConfig); $o->toJwt(); } - /** - * @expectedException DomainException - */ public function testFailsWithMissingSigningAlgorithm() { + $this->expectException(DomainException::class); $testConfig = $this->signingMinimal; unset($testConfig['signingAlgorithm']); $o = new OAuth2($testConfig); @@ -464,7 +450,7 @@ public function testCanHS256EncodeAValidPayloadWithSigningKeyId() $testConfig['signingKeyId'] = 'example_key_id2'; $o = new OAuth2($testConfig); $payload = $o->toJwt(); - $roundTrip = $this->jwtDecode($payload, $keys, array('HS256')); + $roundTrip = JWT::decode($payload, $keys, array('HS256')); $this->assertEquals($roundTrip->iss, $testConfig['issuer']); $this->assertEquals($roundTrip->aud, $testConfig['audience']); $this->assertEquals($roundTrip->scope, $testConfig['scope']); @@ -482,14 +468,14 @@ public function testFailDecodeWithoutSigningKeyId() $payload = $o->toJwt(); try { - $this->jwtDecode($payload, $keys, array('HS256')); + JWT::decode($payload, $keys, array('HS256')); } catch (\Exception $e) { - if (($e instanceof \DomainException || $e instanceof \UnexpectedValueException) && - $e->getMessage() === '"kid" empty, unable to lookup correct key') { - // Workaround: In old JWT versions throws DomainException - return; - } - throw $e; + // Workaround: In old JWT versions throws DomainException + $this->assertTrue( + ($e instanceof \DomainException || $e instanceof \UnexpectedValueException) + && $e->getMessage() === '"kid" empty, unable to lookup correct key' + ); + return; } $this->fail("Expected exception about problem with decode"); } @@ -499,7 +485,7 @@ public function testCanHS256EncodeAValidPayload() $testConfig = $this->signingMinimal; $o = new OAuth2($testConfig); $payload = $o->toJwt(); - $roundTrip = $this->jwtDecode($payload, $testConfig['signingKey'], array('HS256')); + $roundTrip = JWT::decode($payload, $testConfig['signingKey'], array('HS256')); $this->assertEquals($roundTrip->iss, $testConfig['issuer']); $this->assertEquals($roundTrip->aud, $testConfig['audience']); $this->assertEquals($roundTrip->scope, $testConfig['scope']); @@ -514,7 +500,7 @@ public function testCanRS256EncodeAValidPayload() $o->setSigningAlgorithm('RS256'); $o->setSigningKey($privateKey); $payload = $o->toJwt(); - $roundTrip = $this->jwtDecode($payload, $publicKey, array('RS256')); + $roundTrip = JWT::decode($payload, $publicKey, array('RS256')); $this->assertEquals($roundTrip->iss, $testConfig['issuer']); $this->assertEquals($roundTrip->aud, $testConfig['audience']); $this->assertEquals($roundTrip->scope, $testConfig['scope']); @@ -531,20 +517,9 @@ public function testCanHaveAdditionalClaims() $o->setSigningAlgorithm('RS256'); $o->setSigningKey($privateKey); $payload = $o->toJwt(); - $roundTrip = $this->jwtDecode($payload, $publicKey, array('RS256')); + $roundTrip = JWT::decode($payload, $publicKey, array('RS256')); $this->assertEquals($roundTrip->target_audience, $targetAud); } - - private function jwtDecode() - { - $args = func_get_args(); - $class = 'JWT'; - if (class_exists('Firebase\JWT\JWT')) { - $class = 'Firebase\JWT\JWT'; - } - - return call_user_func_array("$class::decode", $args); - } } class OAuth2GenerateAccessTokenRequestTest extends TestCase @@ -557,22 +532,18 @@ class OAuth2GenerateAccessTokenRequestTest extends TestCase 'clientId' => 'aClientID', ]; - /** - * @expectedException DomainException - */ public function testFailsIfNoTokenCredentialUri() { + $this->expectException(DomainException::class); $testConfig = $this->tokenRequestMinimal; unset($testConfig['tokenCredentialUri']); $o = new OAuth2($testConfig); $o->generateCredentialsRequest(); } - /** - * @expectedException DomainException - */ public function testFailsIfAuthorizationCodeIsMissing() { + $this->expectException(DomainException::class); $testConfig = $this->tokenRequestMinimal; $testConfig['redirectUri'] = 'https://has/redirect/uri'; $o = new OAuth2($testConfig); @@ -707,11 +678,10 @@ class OAuth2FetchAuthTokenTest extends TestCase 'clientId' => 'aClientID', ]; - /** - * @expectedException GuzzleHttp\Exception\ClientException - */ public function testFailsOn400() { + $this->expectException(\GuzzleHttp\Exception\ClientException::class); + $testConfig = $this->fetchAuthTokenMinimal; $httpHandler = getHandler([ buildResponse(400), @@ -720,11 +690,10 @@ public function testFailsOn400() $o->fetchAuthToken($httpHandler); } - /** - * @expectedException GuzzleHttp\Exception\ServerException - */ public function testFailsOn500() { + $this->expectException(\GuzzleHttp\Exception\ServerException::class); + $testConfig = $this->fetchAuthTokenMinimal; $httpHandler = getHandler([ buildResponse(500), @@ -733,12 +702,11 @@ public function testFailsOn500() $o->fetchAuthToken($httpHandler); } - /** - * @expectedException Exception - * @expectedExceptionMessage Invalid JSON response - */ public function testFailsOnNoContentTypeIfResponseIsNotJSON() { + $this->expectException(\Exception::class); + $this->expectExceptionMessage('Invalid JSON response'); + $testConfig = $this->fetchAuthTokenMinimal; $notJson = '{"foo": , this is cannot be passed as json" "bar"}'; $httpHandler = getHandler([ @@ -923,7 +891,7 @@ class OAuth2VerifyIdTokenTest extends TestCase 'clientId' => 'myaccount.on.host.issuer.com', ]; - public function setUp() + public function setUp(): void { $this->publicKey = file_get_contents(__DIR__ . '/fixtures' . '/public.pem'); @@ -931,11 +899,10 @@ public function setUp() file_get_contents(__DIR__ . '/fixtures' . '/private.pem'); } - /** - * @expectedException UnexpectedValueException - */ public function testFailsIfIdTokenIsInvalid() { + $this->expectException(UnexpectedValueException::class); + $testConfig = $this->verifyIdTokenMinimal; $not_a_jwt = 'not a jot'; $o = new OAuth2($testConfig); @@ -943,11 +910,9 @@ public function testFailsIfIdTokenIsInvalid() $o->verifyIdToken($this->publicKey); } - /** - * @expectedException DomainException - */ public function testFailsIfAudienceIsMissing() { + $this->expectException(DomainException::class); $testConfig = $this->verifyIdTokenMinimal; $now = time(); $origIdToken = [ @@ -956,16 +921,14 @@ public function testFailsIfAudienceIsMissing() 'iat' => $now, ]; $o = new OAuth2($testConfig); - $jwtIdToken = $this->jwtEncode($origIdToken, $this->privateKey, 'RS256'); + $jwtIdToken = JWT::encode($origIdToken, $this->privateKey, 'RS256'); $o->setIdToken($jwtIdToken); $o->verifyIdToken($this->publicKey, ['RS256']); } - /** - * @expectedException DomainException - */ public function testFailsIfAudienceIsWrong() { + $this->expectException(DomainException::class); $now = time(); $testConfig = $this->verifyIdTokenMinimal; $origIdToken = [ @@ -975,7 +938,7 @@ public function testFailsIfAudienceIsWrong() 'iat' => $now, ]; $o = new OAuth2($testConfig); - $jwtIdToken = $this->jwtEncode($origIdToken, $this->privateKey, 'RS256'); + $jwtIdToken = JWT::encode($origIdToken, $this->privateKey, 'RS256'); $o->setIdToken($jwtIdToken); $o->verifyIdToken($this->publicKey, ['RS256']); } @@ -992,20 +955,9 @@ public function testShouldReturnAValidIdToken() ]; $o = new OAuth2($testConfig); $alg = 'RS256'; - $jwtIdToken = $this->jwtEncode($origIdToken, $this->privateKey, $alg); + $jwtIdToken = JWT::encode($origIdToken, $this->privateKey, $alg); $o->setIdToken($jwtIdToken); $roundTrip = $o->verifyIdToken($this->publicKey, array($alg)); $this->assertEquals($origIdToken['aud'], $roundTrip->aud); } - - private function jwtEncode() - { - $args = func_get_args(); - $class = 'JWT'; - if (class_exists('Firebase\JWT\JWT')) { - $class = 'Firebase\JWT\JWT'; - } - - return call_user_func_array("$class::encode", $args); - } } diff --git a/tests/Subscriber/AuthTokenSubscriberTest.php b/tests/Subscriber/AuthTokenSubscriberTest.php deleted file mode 100644 index 1604207f4..000000000 --- a/tests/Subscriber/AuthTokenSubscriberTest.php +++ /dev/null @@ -1,335 +0,0 @@ -onlyGuzzle5(); - - $this->mockFetcher = $this->prophesize('Google\Auth\FetchAuthTokenInterface'); - $this->mockCacheItem = $this->prophesize('Psr\Cache\CacheItemInterface'); - $this->mockCache = $this->prophesize('Psr\Cache\CacheItemPoolInterface'); - } - - public function testSubscribesToEvents() - { - $a = new AuthTokenSubscriber($this->mockFetcher->reveal()); - $this->assertArrayHasKey('before', $a->getEvents()); - } - - public function testOnlyTouchesWhenAuthConfigScoped() - { - $s = new AuthTokenSubscriber($this->mockFetcher->reveal()); - $client = new Client(); - $request = $client->createRequest( - 'GET', - 'http://testing.org', - ['auth' => 'not_google_auth'] - ); - $before = new BeforeEvent(new Transaction($client, $request)); - $s->onBefore($before); - $this->assertSame($request->getHeader('authorization'), ''); - } - - public function testAddsTheTokenAsAnAuthorizationHeader() - { - $authResult = ['access_token' => '1/abcdef1234567890']; - $this->mockFetcher->fetchAuthToken(Argument::any()) - ->shouldBeCalledTimes(1) - ->willReturn($authResult); - - // Run the test. - $a = new AuthTokenSubscriber($this->mockFetcher->reveal()); - $client = new Client(); - $request = $client->createRequest( - 'GET', - 'http://testing.org', - ['auth' => 'google_auth'] - ); - $before = new BeforeEvent(new Transaction($client, $request)); - $a->onBefore($before); - $this->assertSame( - $request->getHeader('authorization'), - 'Bearer 1/abcdef1234567890' - ); - } - - public function testDoesNotAddAnAuthorizationHeaderOnNoAccessToken() - { - $authResult = ['not_access_token' => '1/abcdef1234567890']; - $this->mockFetcher->fetchAuthToken(Argument::any()) - ->shouldBeCalledTimes(1) - ->willReturn($authResult); - - // Run the test. - $a = new AuthTokenSubscriber($this->mockFetcher->reveal()); - $client = new Client(); - $request = $client->createRequest( - 'GET', - 'http://testing.org', - ['auth' => 'google_auth'] - ); - $before = new BeforeEvent(new Transaction($client, $request)); - $a->onBefore($before); - $this->assertSame($request->getHeader('authorization'), ''); - } - - public function testUsesCachedAuthToken() - { - $cacheKey = 'myKey'; - $token = '2/abcdef1234567890'; - $cachedValue = ['access_token' => $token]; - $this->mockCacheItem->isHit() - ->shouldBeCalledTimes(1) - ->willReturn(true); - $this->mockCacheItem->get() - ->shouldBeCalledTimes(1) - ->willReturn($cachedValue); - $this->mockCache->getItem($cacheKey) - ->shouldBeCalledTimes(1) - ->willReturn($this->mockCacheItem->reveal()); - $this->mockFetcher->fetchAuthToken() - ->shouldNotBeCalled(); - $this->mockFetcher->getCacheKey() - ->willReturn($cacheKey); - - // Run the test. - $cachedFetcher = new FetchAuthTokenCache( - $this->mockFetcher->reveal(), - null, - $this->mockCache->reveal() - ); - $a = new AuthTokenSubscriber($cachedFetcher); - $client = new Client(); - $request = $client->createRequest( - 'GET', - 'http://testing.org', - ['auth' => 'google_auth'] - ); - $before = new BeforeEvent(new Transaction($client, $request)); - $a->onBefore($before); - $this->assertSame( - $request->getHeader('authorization'), - 'Bearer ' . $token - ); - } - - public function testGetsCachedAuthTokenUsingCachePrefix() - { - $prefix = 'test_prefix_'; - $cacheKey = 'myKey'; - $token = '2/abcdef1234567890'; - $cachedValue = ['access_token' => $token]; - $this->mockCacheItem->isHit() - ->shouldBeCalledTimes(1) - ->willReturn(true); - $this->mockCacheItem->get() - ->shouldBeCalledTimes(1) - ->willReturn($cachedValue); - $this->mockCache->getItem($prefix . $cacheKey) - ->shouldBeCalledTimes(1) - ->willReturn($this->mockCacheItem->reveal()); - $this->mockFetcher->fetchAuthToken() - ->shouldNotBeCalled(); - $this->mockFetcher->getCacheKey() - ->willReturn($cacheKey); - - // Run the test - $cachedFetcher = new FetchAuthTokenCache( - $this->mockFetcher->reveal(), - ['prefix' => $prefix], - $this->mockCache->reveal() - ); - $a = new AuthTokenSubscriber($cachedFetcher); - $client = new Client(); - $request = $client->createRequest( - 'GET', - 'http://testing.org', - ['auth' => 'google_auth'] - ); - $before = new BeforeEvent(new Transaction($client, $request)); - $a->onBefore($before); - $this->assertSame( - $request->getHeader('authorization'), - 'Bearer ' . $token - ); - } - - public function testShouldSaveValueInCacheWithCacheOptions() - { - $prefix = 'test_prefix_'; - $lifetime = '70707'; - $cacheKey = 'myKey'; - $token = '2/abcdef1234567890'; - $cachedValue = ['access_token' => $token]; - $this->mockCacheItem->get() - ->willReturn(null); - $this->mockCacheItem->set($cachedValue) - ->shouldBeCalledTimes(1) - ->willReturn(false); - $this->mockCacheItem->isHit() - ->willReturn(false); - $this->mockCacheItem->expiresAfter($lifetime) - ->shouldBeCalledTimes(1); - $this->mockCache->getItem($prefix . $cacheKey) - ->shouldBeCalledTimes(2) - ->willReturn($this->mockCacheItem->reveal()); - $this->mockCache->save(Argument::type('Psr\Cache\CacheItemInterface')) - ->willReturn(null); - $this->mockFetcher->getCacheKey() - ->willReturn($cacheKey); - $this->mockFetcher->fetchAuthToken(Argument::any()) - ->willReturn($cachedValue); - - // Run the test - $cachedFetcher = new FetchAuthTokenCache( - $this->mockFetcher->reveal(), - ['prefix' => $prefix, 'lifetime' => $lifetime], - $this->mockCache->reveal() - ); - $a = new AuthTokenSubscriber($cachedFetcher); - $client = new Client(); - $request = $client->createRequest( - 'GET', - 'http://testing.org', - ['auth' => 'google_auth'] - ); - $before = new BeforeEvent(new Transaction($client, $request)); - $a->onBefore($before); - $this->assertSame( - $request->getHeader('authorization'), - 'Bearer ' . $token - ); - } - - /** - * @dataProvider provideShouldNotifyTokenCallback - */ - public function testShouldNotifyTokenCallback(callable $tokenCallback) - { - $prefix = 'test_prefix_'; - $cacheKey = 'myKey'; - $token = '1/abcdef1234567890'; - $cachedValue = ['access_token' => $token]; - $this->mockCacheItem->get() - ->willReturn(null); - $this->mockCacheItem->isHit() - ->willReturn(false); - $this->mockCacheItem->set($cachedValue) - ->willReturn(false); - $this->mockCacheItem->expiresAfter(Argument::any()) - ->willReturn(null); - $this->mockCache->getItem($prefix . $cacheKey) - ->willReturn($this->mockCacheItem->reveal()); - $this->mockCache->save(Argument::type('Psr\Cache\CacheItemInterface')) - ->willReturn(null); - $this->mockFetcher->getCacheKey() - ->willReturn($cacheKey); - $this->mockFetcher->fetchAuthToken(Argument::any()) - ->shouldBeCalledTimes(1) - ->willReturn($cachedValue); - - SubscriberCallback::$expectedKey = $this->getValidKeyName($prefix . $cacheKey); - SubscriberCallback::$expectedValue = $token; - SubscriberCallback::$called = false; - - // Run the test - $cachedFetcher = new FetchAuthTokenCache( - $this->mockFetcher->reveal(), - ['prefix' => $prefix], - $this->mockCache->reveal() - ); - $a = new AuthTokenSubscriber( - $cachedFetcher, - null, - $tokenCallback - ); - - $client = new Client(); - $request = $client->createRequest( - 'GET', - 'http://testing.org', - ['auth' => 'google_auth'] - ); - $before = new BeforeEvent(new Transaction($client, $request)); - $a->onBefore($before); - $this->assertTrue(SubscriberCallback::$called); - } - - public function provideShouldNotifyTokenCallback() - { - SubscriberCallback::$phpunit = $this; - $anonymousFunc = function ($key, $value) { - SubscriberCallback::staticInvoke($key, $value); - }; - return [ - ['Google\Auth\Tests\Subscriber\SubscriberCallbackFunction'], - ['Google\Auth\Tests\Subscriber\SubscriberCallback::staticInvoke'], - [['Google\Auth\Tests\Subscriber\SubscriberCallback', 'staticInvoke']], - [$anonymousFunc], - [[new SubscriberCallback(), 'staticInvoke']], - [[new SubscriberCallback(), 'methodInvoke']], - [new SubscriberCallback()], - ]; - } -} - -class SubscriberCallback -{ - public static $phpunit; - public static $expectedKey; - public static $expectedValue; - public static $called = false; - - public function __invoke($key, $value) - { - self::$phpunit->assertEquals(self::$expectedKey, $key); - self::$phpunit->assertEquals(self::$expectedValue, $value); - self::$called = true; - } - - public function methodInvoke($key, $value) - { - return $this($key, $value); - } - - public static function staticInvoke($key, $value) - { - $instance = new self(); - return $instance($key, $value); - } -} - -function SubscriberCallbackFunction($key, $value) -{ - return SubscriberCallback::staticInvoke($key, $value); -} diff --git a/tests/Subscriber/ScopedAccessTokenSubscriberTest.php b/tests/Subscriber/ScopedAccessTokenSubscriberTest.php deleted file mode 100644 index e64e22508..000000000 --- a/tests/Subscriber/ScopedAccessTokenSubscriberTest.php +++ /dev/null @@ -1,256 +0,0 @@ -onlyGuzzle5(); - - $this->mockCacheItem = $this->prophesize('Psr\Cache\CacheItemInterface'); - $this->mockCache = $this->prophesize('Psr\Cache\CacheItemPoolInterface'); - $this->mockRequest = $this->prophesize('GuzzleHttp\Psr7\Request'); - } - - /** - * @expectedException InvalidArgumentException - */ - public function testRequiresScopeAsAStringOrArray() - { - $fakeAuthFunc = function ($unused_scopes) { - return '1/abcdef1234567890'; - }; - new ScopedAccessTokenSubscriber($fakeAuthFunc, new \stdClass(), array()); - } - - public function testSubscribesToEvents() - { - $fakeAuthFunc = function ($unused_scopes) { - return '1/abcdef1234567890'; - }; - $s = new ScopedAccessTokenSubscriber($fakeAuthFunc, self::TEST_SCOPE, array()); - $this->assertArrayHasKey('before', $s->getEvents()); - } - - public function testAddsTheTokenAsAnAuthorizationHeader() - { - $fakeAuthFunc = function ($unused_scopes) { - return '1/abcdef1234567890'; - }; - $s = new ScopedAccessTokenSubscriber($fakeAuthFunc, self::TEST_SCOPE, array()); - $client = new Client(); - $request = $client->createRequest( - 'GET', - 'http://testing.org', - ['auth' => 'scoped'] - ); - $before = new BeforeEvent(new Transaction($client, $request)); - $s->onBefore($before); - $this->assertSame( - 'Bearer 1/abcdef1234567890', - $request->getHeader('authorization') - ); - } - - public function testUsesCachedAuthToken() - { - $cachedValue = '2/abcdef1234567890'; - $fakeAuthFunc = function ($unused_scopes) { - return ''; - }; - $this->mockCacheItem->isHit() - ->shouldBeCalledTimes(1) - ->willReturn(true); - $this->mockCacheItem->get() - ->shouldBeCalledTimes(1) - ->willReturn($cachedValue); - $this->mockCache->getItem($this->getValidKeyName(self::TEST_SCOPE)) - ->shouldBeCalledTimes(1) - ->willReturn($this->mockCacheItem->reveal()); - - // Run the test - $s = new ScopedAccessTokenSubscriber( - $fakeAuthFunc, - self::TEST_SCOPE, - [], - $this->mockCache->reveal() - ); - $client = new Client(); - $request = $client->createRequest( - 'GET', - 'http://testing.org', - ['auth' => 'scoped'] - ); - $before = new BeforeEvent(new Transaction($client, $request)); - $s->onBefore($before); - $this->assertSame( - 'Bearer 2/abcdef1234567890', - $request->getHeader('authorization') - ); - } - - public function testGetsCachedAuthTokenUsingCachePrefix() - { - $prefix = 'test_prefix_'; - $cachedValue = '2/abcdef1234567890'; - $fakeAuthFunc = function ($unused_scopes) { - return ''; - }; - $this->mockCacheItem->isHit() - ->shouldBeCalledTimes(1) - ->willReturn(true); - $this->mockCacheItem->get() - ->shouldBeCalledTimes(1) - ->willReturn($cachedValue); - $this->mockCache->getItem($prefix . $this->getValidKeyName(self::TEST_SCOPE)) - ->shouldBeCalledTimes(1) - ->willReturn($this->mockCacheItem->reveal()); - - // Run the test - $s = new ScopedAccessTokenSubscriber( - $fakeAuthFunc, - self::TEST_SCOPE, - ['prefix' => $prefix], - $this->mockCache->reveal() - ); - $client = new Client(); - $request = $client->createRequest( - 'GET', - 'http://testing.org', - ['auth' => 'scoped'] - ); - $before = new BeforeEvent(new Transaction($client, $request)); - $s->onBefore($before); - $this->assertSame( - 'Bearer 2/abcdef1234567890', - $request->getHeader('authorization') - ); - } - - public function testShouldSaveValueInCache() - { - $token = '2/abcdef1234567890'; - $fakeAuthFunc = function ($unused_scopes) { - return '2/abcdef1234567890'; - }; - $this->mockCacheItem->isHit() - ->shouldBeCalledTimes(1) - ->willReturn(false); - $this->mockCacheItem->set($token) - ->shouldBeCalledTimes(1) - ->willReturn(false); - $this->mockCacheItem->expiresAfter(Argument::any()) - ->shouldBeCalledTimes(1); - $this->mockCache->getItem($this->getValidKeyName(self::TEST_SCOPE)) - ->shouldBeCalledTimes(2) - ->willReturn($this->mockCacheItem->reveal()); - $this->mockCache->save(Argument::type('Psr\Cache\CacheItemInterface')) - ->shouldBeCalledTimes(1); - - $s = new ScopedAccessTokenSubscriber( - $fakeAuthFunc, - self::TEST_SCOPE, - [], - $this->mockCache->reveal() - ); - $client = new Client(); - $request = $client->createRequest( - 'GET', - 'http://testing.org', - ['auth' => 'scoped'] - ); - $before = new BeforeEvent(new Transaction($client, $request)); - $s->onBefore($before); - $this->assertSame( - 'Bearer 2/abcdef1234567890', - $request->getHeader('authorization') - ); - } - - public function testShouldSaveValueInCacheWithCacheOptions() - { - $token = '2/abcdef1234567890'; - $prefix = 'test_prefix_'; - $lifetime = '70707'; - $fakeAuthFunc = function ($unused_scopes) { - return '2/abcdef1234567890'; - }; - $this->mockCacheItem->isHit() - ->shouldBeCalledTimes(1) - ->willReturn(false); - $this->mockCacheItem->set($token) - ->shouldBeCalledTimes(1); - $this->mockCacheItem->expiresAfter($lifetime) - ->shouldBeCalledTimes(1); - $this->mockCache->getItem($prefix . $this->getValidKeyName(self::TEST_SCOPE)) - ->willReturn($this->mockCacheItem->reveal()); - $this->mockCache->save(Argument::type('Psr\Cache\CacheItemInterface')) - ->shouldBeCalledTimes(1); - - // Run the test - $s = new ScopedAccessTokenSubscriber( - $fakeAuthFunc, - self::TEST_SCOPE, - ['prefix' => $prefix, 'lifetime' => $lifetime], - $this->mockCache->reveal() - ); - $client = new Client(); - $request = $client->createRequest( - 'GET', - 'http://testing.org', - ['auth' => 'scoped'] - ); - $before = new BeforeEvent(new Transaction($client, $request)); - $s->onBefore($before); - $this->assertSame( - 'Bearer 2/abcdef1234567890', - $request->getHeader('authorization') - ); - } - - public function testOnlyTouchesWhenAuthConfigScoped() - { - $fakeAuthFunc = function ($unused_scopes) { - return '1/abcdef1234567890'; - }; - $s = new ScopedAccessTokenSubscriber($fakeAuthFunc, self::TEST_SCOPE, []); - $client = new Client(); - $request = $client->createRequest( - 'GET', - 'http://testing.org', - ['auth' => 'notscoped'] - ); - $before = new BeforeEvent(new Transaction($client, $request)); - $s->onBefore($before); - $this->assertSame('', $request->getHeader('authorization')); - } -} diff --git a/tests/Subscriber/SimpleSubscriberTest.php b/tests/Subscriber/SimpleSubscriberTest.php deleted file mode 100644 index 2cb7abf7e..000000000 --- a/tests/Subscriber/SimpleSubscriberTest.php +++ /dev/null @@ -1,76 +0,0 @@ -onlyGuzzle5(); - } - - /** - * @expectedException InvalidArgumentException - */ - public function testRequiresADeveloperKey() - { - new SimpleSubscriber(['not_key' => 'a test key']); - } - - public function testSubscribesToEvents() - { - $events = (new SimpleSubscriber(['key' => 'a test key']))->getEvents(); - $this->assertArrayHasKey('before', $events); - } - - public function testAddsTheKeyToTheQuery() - { - $s = new SimpleSubscriber(['key' => 'test_key']); - $client = new Client(); - $request = $client->createRequest( - 'GET', - 'http://testing.org', - ['auth' => 'simple'] - ); - $before = new BeforeEvent(new Transaction($client, $request)); - $s->onBefore($before); - $this->assertCount(1, $request->getQuery()); - $this->assertTrue($request->getQuery()->hasKey('key')); - $this->assertSame($request->getQuery()->get('key'), 'test_key'); - } - - public function testOnlyTouchesWhenAuthConfigIsSimple() - { - $s = new SimpleSubscriber(['key' => 'test_key']); - $client = new Client(); - $request = $client->createRequest( - 'GET', - 'http://testing.org', - ['auth' => 'notsimple'] - ); - $before = new BeforeEvent(new Transaction($client, $request)); - $s->onBefore($before); - $this->assertCount(0, $request->getQuery()); - } -}