Skip to content

Commit

Permalink
Mutation cleanup
Browse files Browse the repository at this point in the history
  • Loading branch information
danepowell committed Feb 23, 2024
1 parent 3c43872 commit 80c2447
Show file tree
Hide file tree
Showing 10 changed files with 71 additions and 36 deletions.
3 changes: 1 addition & 2 deletions .github/workflows/mutation.yml
Original file line number Diff line number Diff line change
Expand Up @@ -38,5 +38,4 @@ jobs:
if: github.event_name == 'push'
env:
INFECTION_DASHBOARD_API_KEY: ${{ secrets.INFECTION_DASHBOARD_API_KEY }}
run: |
php vendor/bin/infection --threads=max --only-covered
run: composer mutation
4 changes: 2 additions & 2 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -129,8 +129,8 @@
"box-compile": [
"php var/box.phar compile"
],
"infection": [
"php -d pcov.enabled=1 vendor/bin/infection --threads=max"
"mutation": [
"infection --threads=max --only-covered"
],
"cs": "phpcs",
"cbf": "phpcbf",
Expand Down
7 changes: 4 additions & 3 deletions infection.json5
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,11 @@
"logs": {
"stryker": {
"report": "main"
}
},
"html": "var/infection.html"
},
"timeout": 30,
"mutators": {
"@default": true
}
},
"testFrameworkOptions": "--exclude-group=serial"
}
1 change: 1 addition & 0 deletions phpunit.xml.dist
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
convertNoticesToExceptions="true"
convertWarningsToExceptions="true"
convertDeprecationsToExceptions="true"
executionOrder="random"
>
<php>
<env name="AMPLITUDE_KEY" value=""/>
Expand Down
11 changes: 7 additions & 4 deletions src/Command/Api/ApiCommandHelper.php
Original file line number Diff line number Diff line change
Expand Up @@ -277,16 +277,16 @@ private function getParameterSchemaFromSpec(string $paramKey, array $acquiaCloud
return $acquiaCloudSpec['components']['schemas'][$paramKey];
}

/** @infection-ignore-all */
private function isApiSpecChecksumCacheValid(\Symfony\Component\Cache\CacheItem $cacheItem, string $acquiaCloudSpecFileChecksum): bool {
// If the spec file doesn't exist, assume cache is valid.
if ($cacheItem->isHit() && !$acquiaCloudSpecFileChecksum) {
if (!$acquiaCloudSpecFileChecksum && $cacheItem->isHit()) {
return TRUE;
}
// If there's an invalid entry OR there's no entry, return false.
if (!$cacheItem->isHit() || ($cacheItem->isHit() && $cacheItem->get() !== $acquiaCloudSpecFileChecksum)) {
if (!$cacheItem->isHit() || $cacheItem->get() !== $acquiaCloudSpecFileChecksum) {
return FALSE;
}

return TRUE;
}

Expand All @@ -296,6 +296,7 @@ private function isApiSpecChecksumCacheValid(\Symfony\Component\Cache\CacheItem
private function getCloudApiSpec(string $specFilePath): array {
$cacheKey = basename($specFilePath);
$cache = new PhpArrayAdapter(__DIR__ . '/../../../var/cache/' . $cacheKey . '.cache', new NullAdapter());
/** @infection-ignore-all */
$cacheItemChecksum = $cache->getItem($cacheKey . '.checksum');
$cacheItemSpec = $cache->getItem($cacheKey);

Expand All @@ -306,6 +307,7 @@ private function getCloudApiSpec(string $specFilePath): array {

// Otherwise, only use cache when it is valid.
$checksum = md5_file($specFilePath);
/** @infection-ignore-all */
if ($this->useCloudApiSpecCache()
&& $this->isApiSpecChecksumCacheValid($cacheItemChecksum, $checksum) && $cacheItemSpec->isHit()
) {
Expand All @@ -325,13 +327,13 @@ private function getCloudApiSpec(string $specFilePath): array {
}

/**
* @param array $acquiaCloudSpec
* @return ApiBaseCommand[]
*/
private function generateApiCommandsFromSpec(array $acquiaCloudSpec, string $commandPrefix, CommandFactoryInterface $commandFactory): array {
$apiCommands = [];
foreach ($acquiaCloudSpec['paths'] as $path => $endpoint) {
// Skip internal endpoints. These shouldn't actually be in the spec.
/** @infection-ignore-all */
if (array_key_exists('x-internal', $endpoint) && $endpoint['x-internal']) {
continue;
}
Expand All @@ -346,6 +348,7 @@ private function generateApiCommandsFromSpec(array $acquiaCloudSpec, string $com
}

// Skip deprecated endpoints.
/** @infection-ignore-all */
if (array_key_exists('deprecated', $schema) && $schema['deprecated']) {
continue;
}
Expand Down
1 change: 1 addition & 0 deletions src/Command/CommandBase.php
Original file line number Diff line number Diff line change
Expand Up @@ -1749,6 +1749,7 @@ protected function waitForNotificationToComplete(Client $acquiaCloudClient, stri
$notification = NULL;
$checkNotificationStatus = static function () use ($notificationsResource, &$notification, $uuid): bool {
$notification = $notificationsResource->get($uuid);
/** @infection-ignore-all */
return $notification->status !== 'in-progress';
};
if ($success === NULL) {
Expand Down
1 change: 1 addition & 0 deletions src/Command/Email/ConfigurePlatformEmailCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -305,6 +305,7 @@ private function checkIfDomainVerified(
return TRUE;
}

/** @infection-ignore-all */
if (isset($response->health) && str_starts_with($response->health->code, "4")) {
$this->io->error($response->health->details);
if ($this->io->confirm('Would you like to refresh?')) {
Expand Down
45 changes: 30 additions & 15 deletions src/Command/Ide/IdeCreateCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,22 @@

namespace Acquia\Cli\Command\Ide;

use Acquia\Cli\ApiCredentialsInterface;
use Acquia\Cli\Attribute\RequireAuth;
use Acquia\Cli\CloudApi\ClientService;
use Acquia\Cli\DataStore\AcquiaCliDatastore;
use Acquia\Cli\DataStore\CloudDataStore;
use Acquia\Cli\Helpers\LocalMachineHelper;
use Acquia\Cli\Helpers\LoopHelper;
use Acquia\Cli\Helpers\SshHelper;
use Acquia\Cli\Helpers\TelemetryHelper;
use Acquia\Cli\Output\Checklist;
use AcquiaCloudApi\Endpoints\Account;
use AcquiaCloudApi\Endpoints\Ides;
use AcquiaCloudApi\Response\IdeResponse;
use AcquiaCloudApi\Response\OperationResponse;
use GuzzleHttp\Client;
use Psr\Log\LoggerInterface;
use Symfony\Component\Console\Attribute\AsCommand;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
Expand All @@ -27,7 +35,21 @@ final class IdeCreateCommand extends IdeCommandBase {

private IdeResponse $ide;

private Client $client;
public function __construct(
public LocalMachineHelper $localMachineHelper,
protected CloudDataStore $datastoreCloud,
protected AcquiaCliDatastore $datastoreAcli,
protected ApiCredentialsInterface $cloudCredentials,
protected TelemetryHelper $telemetryHelper,
protected string $projectDir,
protected ClientService $cloudApiClientService,
public SshHelper $sshHelper,
protected string $sshDir,
LoggerInterface $logger,
protected Client $httpClient
) {
parent::__construct($this->localMachineHelper, $this->datastoreCloud, $this->datastoreAcli, $this->cloudCredentials, $this->telemetryHelper, $this->projectDir, $this->cloudApiClientService, $this->sshHelper, $this->sshDir, $logger);
}

protected function configure(): void {
$this->acceptApplicationUuid();
Expand Down Expand Up @@ -76,13 +98,14 @@ public function validateIdeLabel(string $label): string {
return $label;
}

private function waitForDnsPropagation(mixed $ideUrl): int {
private function waitForDnsPropagation(string $ideUrl): int {
$ideCreated = FALSE;
if (!$this->getClient()) {
$this->setClient(new Client(['base_uri' => $ideUrl]));
}
$checkIdeStatus = function () use (&$ideCreated) {
$response = $this->client->request('GET', '/health');
$checkIdeStatus = function () use (&$ideCreated, $ideUrl) {
// Ideally we'd set $ideUrl as the Guzzle base_url, but that requires creating a client factory.
// @see https://stackoverflow.com/questions/28277889/guzzlehttp-client-change-base-url-dynamically
$response = $this->httpClient->request('GET', "$ideUrl/health");
// Mutating this will result in an infinite loop and timeout.
/** @infection-ignore-all */
if ($response->getStatusCode() === 200) {
$ideCreated = TRUE;
}
Expand Down Expand Up @@ -111,14 +134,6 @@ private function writeIdeLinksToScreen(): void {
// @todo Prompt to open browser.
}

private function getClient(): ?Client {
return $this->client ?? NULL;
}

public function setClient(Client $client): void {
$this->client = $client;
}

private function getIdeFromResponse(
OperationResponse $response,
\AcquiaCloudApi\Connector\Client $acquiaCloudClient
Expand Down
2 changes: 2 additions & 0 deletions src/Helpers/LoopHelper.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,14 @@ public static function getLoopy(OutputInterface $output, SymfonyStyle $io, Logge
$spinner->start();

$cancelTimers = static function () use (&$timers, $spinner): void {
/** @infection-ignore-all */
array_map('\React\EventLoop\Loop::cancelTimer', $timers);
$timers = [];
$spinner->finish();
};
$periodicCallback = static function () use ($logger, $statusCallback, $doneCallback, $cancelTimers): void {
try {
/** @infection-ignore-all */
if ($statusCallback()) {
$cancelTimers();
$doneCallback();
Expand Down
32 changes: 22 additions & 10 deletions tests/phpunit/src/Commands/Ide/IdeCreateCommandTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,33 @@
use Acquia\Cli\Tests\CommandTestBase;
use GuzzleHttp\Client;
use GuzzleHttp\Psr7\Response;
use Prophecy\Prophecy\ObjectProphecy;

/**
* @property IdeCreateCommand $command
*/
class IdeCreateCommandTest extends CommandTestBase {

protected Client|ObjectProphecy $httpClientProphecy;

protected function createCommand(): CommandBase {
$this->httpClientProphecy = $this->prophet->prophesize(Client::class);

return new IdeCreateCommand(
$this->localMachineHelper,
$this->datastoreCloud,
$this->datastoreAcli,
$this->cloudCredentials,
$this->telemetryHelper,
$this->acliRepoRoot,
$this->clientServiceProphecy->reveal(),
$this->sshHelper,
$this->sshDir,
$this->logger,
$this->httpClientProphecy->reveal()
);
}

/**
* @group brokenProphecy
*/
Expand All @@ -34,9 +55,7 @@ public function testCreate(): void {
/** @var \Prophecy\Prophecy\ObjectProphecy|\GuzzleHttp\Psr7\Response $guzzleResponse */
$guzzleResponse = $this->prophet->prophesize(Response::class);
$guzzleResponse->getStatusCode()->willReturn(200);
$guzzleClient = $this->prophet->prophesize(Client::class);
$guzzleClient->request('GET', '/health')->willReturn($guzzleResponse->reveal())->shouldBeCalled();
$this->command->setClient($guzzleClient->reveal());
$this->httpClientProphecy->request('GET', 'https://215824ff-272a-4a8c-9027-df32ed1d68a9.ides.acquia.com/health')->willReturn($guzzleResponse->reveal())->shouldBeCalled();

$inputs = [
// Would you like Acquia CLI to search for a Cloud application that matches your local git config?
Expand All @@ -61,11 +80,4 @@ public function testCreate(): void {
$this->assertStringContainsString('Your Drupal Site URL: https://ide-215824ff-272a-4a8c-9027-df32ed1d68a9.prod.acquia-sites.com', $output);
}

/**
* @return \Acquia\Cli\Command\Ide\IdeCreateCommand
*/
protected function createCommand(): CommandBase {
return $this->injectCommand(IdeCreateCommand::class);
}

}

0 comments on commit 80c2447

Please sign in to comment.