Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
81 changes: 81 additions & 0 deletions .github/workflows/acceptance.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
---

name: Acceptance Tests

on: # yamllint disable-line rule:truthy
pull_request:
push:
branches: [2.x]
workflow_dispatch:

permissions:
contents: read

concurrency:
group: ${{ github.workflow }}-${{ github.head_ref || github.ref }}
cancel-in-progress: ${{ github.event_name == 'pull_request' }}

jobs:
acceptance:
name: PHP ${{ matrix.php }}, ${{ matrix.os }}
runs-on: ${{ matrix.os }}
timeout-minutes: 15
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, windows-latest]
php: ['8.2', '8.5']
steps:
- name: Checkout
uses: actions/checkout@v7
with:
persist-credentials: false

- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php }}
extensions: sockets
coverage: none

- name: Install Composer dependencies
uses: ramsey/composer-install@v3
with:
dependency-versions: highest

# rr runs against a fake GitHub started by the tests (tests/Acceptance/Server)
- name: Run acceptance tests
run: php vendor/bin/testo --suite=Acceptance

live:
name: Live GitHub, ${{ matrix.os }}
if: github.event_name == 'workflow_dispatch'
runs-on: ${{ matrix.os }}
timeout-minutes: 15
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, windows-latest]
steps:
- name: Checkout
uses: actions/checkout@v7
with:
persist-credentials: false

- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: '8.4'
extensions: sockets
coverage: none

- name: Install Composer dependencies
uses: ramsey/composer-install@v3
with:
dependency-versions: highest

- name: Run live tests
run: php vendor/bin/testo --suite=Live
env:
RR_CLI_LIVE_TESTS: '1'
GITHUB_TOKEN: ${{ github.token }}
1 change: 1 addition & 0 deletions .github/workflows/testo.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,4 @@ jobs:
with:
os: >-
['ubuntu-latest']
run: vendor/bin/testo --suite=Unit
1 change: 1 addition & 0 deletions infection.json5
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
"directories": ["src"]
},
"testFramework": "testo",
"testFrameworkOptions": "--suite=Unit",
"tmpDir": "runtime",
"timeout": 10,
"logs": {
Expand Down
26 changes: 20 additions & 6 deletions testo.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,26 @@
use Testo\Application\Config\ApplicationConfig;
use Testo\Application\Config\SuiteConfig;

$suites = [
new SuiteConfig(
name: 'Unit',
location: ['tests/Unit'],
),
new SuiteConfig(
name: 'Acceptance',
location: ['tests/Acceptance'],
),
];

# Downloads real RoadRunner releases from GitHub, so it runs only on request
if (\filter_var(\getenv('RR_CLI_LIVE_TESTS') ?: '0', \FILTER_VALIDATE_BOOLEAN)) {
$suites[] = new SuiteConfig(
name: 'Live',
location: ['tests/Live'],
);
}

return new ApplicationConfig(
src: ['src'],
suites: [
new SuiteConfig(
name: 'Unit',
location: ['tests/Unit'],
),
],
suites: $suites,
);
71 changes: 71 additions & 0 deletions tests/Acceptance/ConfigurationTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
<?php

declare(strict_types=1);

namespace Spiral\RoadRunner\Console\Tests\Acceptance;

use Spiral\RoadRunner\Console\Tests\Acceptance\Support\FakeGitHubCase;
use Testo\Assert;
use Testo\Data\DataSet;
use Testo\Test;

/**
* The `.rr.yaml` that `rr get` writes next to the binary.
*/
#[Test]
final class ConfigurationTest
{
use FakeGitHubCase;

private const ARGS = ['get', '--os=linux', '--arch=amd64'];

public function createsDefaultConfiguration(): void
{
$result = $this->rr()->run(self::ARGS);

Assert::same($result->exitCode, 0, (string) $result);
Assert::array($this->dir->configSections())->contains('version')->contains('server')->contains('http')->contains('kv');
}

public function skipsConfigurationWithNoConfigOption(): void
{
$result = $this->rr()->run([...self::ARGS, '--no-config']);

Assert::same($result->exitCode, 0, (string) $result);
Assert::true($this->dir->has('rr'));
Assert::false($this->dir->has('.rr.yaml'));
}

#[DataSet([['-p', 'http', '-p', 'jobs']], 'plugins')]
#[DataSet([['--preset=web']], 'preset')]
public function generatesConfigurationForSelectedPlugins(array $options): void
{
$result = $this->rr()->run([...self::ARGS, ...$options]);

Assert::same($result->exitCode, 0, (string) $result);
Assert::array($this->dir->configSections())->contains('http')->contains('jobs')->notContains('kv');
}

public function keepsExistingConfiguration(): void
{
$this->dir->write('.rr.yaml', "version: '3'\n# mine\n");

$result = $this->rr()->run(self::ARGS);

Assert::same($result->exitCode, 0, (string) $result);
Assert::true($this->dir->has('rr'));
Assert::same($this->dir->read('.rr.yaml'), "version: '3'\n# mine\n");
}

#[DataSet(['yes', true])]
#[DataSet(['no', false])]
public function asksWhetherToCreateConfiguration(string $answer, bool $created): void
{
$result = $this->rr()->run(self::ARGS, [$answer]);

Assert::same($result->exitCode, 0, (string) $result);
Assert::string($result->output())->matchesRegex('/\.rr\.yaml/');
Assert::true($this->dir->has('rr'));
Assert::same($this->dir->has('.rr.yaml'), $created);
}
}
65 changes: 65 additions & 0 deletions tests/Acceptance/ExistingBinaryTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
<?php

declare(strict_types=1);

namespace Spiral\RoadRunner\Console\Tests\Acceptance;

use Spiral\RoadRunner\Console\Tests\Acceptance\Support\FakeGitHubCase;
use Testo\Assert;
use Testo\Data\DataSet;
use Testo\Skip;
use Testo\Test;

/**
* `rr get` into a directory that already has a RoadRunner binary.
*/
#[Test]
final class ExistingBinaryTest
{
use FakeGitHubCase;

private const ARGS = ['get', '--os=linux', '--arch=amd64', '--no-config'];
private const OLD = "old rr\n";

public function keepsBinaryWithoutInteraction(): void
{
$this->dir->write('rr', self::OLD);

$result = $this->rr()->run(self::ARGS);

Assert::string($result->output())->matchesRegex('/already exists/i');
Assert::same($this->dir->read('rr'), self::OLD);
}

public function keepsBinaryWhenOverwriteIsDeclined(): void
{
$this->dir->write('rr', self::OLD);

$result = $this->rr()->run(self::ARGS, ['no']);

Assert::string($result->output())->matchesRegex('/already exists/i');
Assert::same($this->dir->read('rr'), self::OLD);
}

#[DataSet([null], 'no interaction')]
#[DataSet([['no']], 'declined')]
#[Skip('A kept binary exits with 0 and reports success, see https://github.com/roadrunner-php/cli/issues/69')]
public function failsWhenBinaryIsKept(?array $answers): void
{
$this->dir->write('rr', self::OLD);

$result = $this->rr()->run(self::ARGS, $answers);

Assert::same($result->exitCode, 1, (string) $result);
}

public function overwritesBinaryWhenConfirmed(): void
{
$this->dir->write('rr', self::OLD);

$result = $this->rr()->run(self::ARGS, ['yes']);

Assert::same($result->exitCode, 0, (string) $result);
Assert::same(\trim($this->dir->read('rr')), 'fake rr 3.4.0 linux amd64');
}
}
81 changes: 81 additions & 0 deletions tests/Acceptance/FailureTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
<?php

declare(strict_types=1);

namespace Spiral\RoadRunner\Console\Tests\Acceptance;

use Spiral\RoadRunner\Console\Tests\Acceptance\Support\FakeGitHub;
use Spiral\RoadRunner\Console\Tests\Acceptance\Support\FakeGitHubCase;
use Testo\Assert;
use Testo\Data\DataSet;
use Testo\Skip;
use Testo\Test;

/**
* `rr get` fails without leaving a binary behind.
*/
#[Test]
final class FailureTest
{
use FakeGitHubCase;

private const ARGS = ['get', '--os=linux', '--arch=amd64'];

public function failsWhenRateLimited(): void
{
$result = $this->rr(FakeGitHub::url('rate-limit'))->run(self::ARGS);

Assert::notSame($result->exitCode, 0, (string) $result);
Assert::string($result->output())->matchesRegex('/403|rate limit/i');
Assert::same($this->dir->files(), []);
}

public function failsWhenAssetIsMissing(): void
{
$result = $this->rr(FakeGitHub::url('missing-asset'))->run(self::ARGS);

Assert::notSame($result->exitCode, 0, (string) $result);
Assert::string($result->output())->matchesRegex('/404|not found/i');
Assert::false($this->dir->has('rr'));
}

public function failsWhenGitHubIsUnreachable(): void
{
$result = $this->rr(FakeGitHub::unreachableUrl())->run(self::ARGS);

Assert::notSame($result->exitCode, 0, (string) $result);
Assert::same($this->dir->files(), []);
}

public function rejectsMissingLocationWithoutRequests(): void
{
$result = $this->rr()->run([...self::ARGS, '--location=does-not-exist']);

Assert::notSame($result->exitCode, 0, (string) $result);
Assert::same($this->dir->files(), []);
Assert::same(FakeGitHub::requests(), []);
}

#[DataSet([['--os=plan9']], 'operating system')]
#[DataSet([['--arch=sparc']], 'architecture')]
public function failsForUnknownPlatform(array $options): void
{
$result = $this->rr()->run([...self::ARGS, ...$options]);

Assert::notSame($result->exitCode, 0, (string) $result);
Assert::same($this->dir->files(), []);
Assert::same(FakeGitHub::downloads(), []);
}

#[DataSet([['--os=plan9']], 'operating system')]
#[DataSet([['--arch=sparc']], 'architecture')]
#[Skip('An unknown --os or --arch still fetches the releases, see https://github.com/roadrunner-php/cli/issues/68')]
public function rejectsUnknownPlatformWithoutRequests(array $options): void
{
$result = $this->rr()->run([...self::ARGS, ...$options]);

Assert::notSame($result->exitCode, 0, (string) $result);
Assert::same($this->dir->files(), []);
Assert::same(FakeGitHub::requests(), []);
}
}
Loading
Loading