Skip to content

Commit

Permalink
feat: first
Browse files Browse the repository at this point in the history
  • Loading branch information
nunomaduro committed Oct 23, 2023
1 parent 555279f commit 6b46023
Show file tree
Hide file tree
Showing 21 changed files with 773 additions and 68 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/bin/summary.json
.idea/*
.idea/codeStyleSettings.xml
composer.lock
Expand Down
13 changes: 13 additions & 0 deletions bin/run.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import http from 'k6/http';

export const options = JSON.parse(__ENV.PEST_STRESS_TEST_OPTIONS);

export default () => {
const result = http.get(__ENV.PEST_STRESS_TEST_URL);
}

export function handleSummary(data) {
return {
'summary.json': JSON.stringify(data),
};
}
21 changes: 14 additions & 7 deletions composer.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "pestphp/pest-plugin-template",
"description": "My awesome plugin",
"name": "pestphp/pest-plugin-stressless",
"description": "Stressless plugin for Pest",
"keywords": [
"php",
"framework",
Expand All @@ -12,20 +12,27 @@
],
"license": "MIT",
"require": {
"php": "^8.1",
"pestphp/pest": "^2.5",
"pestphp/pest-plugin": "^2.0.1"
"php": "^8.2",
"pestphp/pest": "@dev",
"pestphp/pest-plugin": "^2.1.1",
"ext-curl": "*"
},
"repositories": [
{
"type": "path",
"url": "../pest"
}
],
"autoload": {
"psr-4": {
"Pest\\PluginName\\": "src/"
"Pest\\Stressless\\": "src/"
},
"files": [
"src/Autoload.php"
]
},
"require-dev": {
"pestphp/pest-dev-tools": "^2.9"
"pestphp/pest-dev-tools": "^2.16"
},
"minimum-stability": "dev",
"prefer-stable": true,
Expand Down
1 change: 1 addition & 0 deletions phpstan.neon
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ parameters:
level: max
paths:
- src
- tests

checkMissingIterableValueType: true
checkGenericClassInNonGenericObjectType: false
Expand Down
14 changes: 3 additions & 11 deletions src/Autoload.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,9 @@

declare(strict_types=1);

namespace Pest\PluginName;
namespace Pest\Stressless;

use Pest\Plugin;
use PHPUnit\Framework\TestCase;

Plugin::uses(Example::class);

/**
* @return TestCase
*/
function example(string $argument)
function stress(string $url): Factory
{
return test()->example(...func_get_args()); // @phpstan-ignore-line
return Factory::make($url);
}
52 changes: 52 additions & 0 deletions src/Binary.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
<?php

declare(strict_types=1);

namespace Pest\Stressless;

use RuntimeException;
use Stringable;

/**
* @internal
*/
final readonly class Binary implements Stringable
{
/**
* The k6 binary name format.
*/
private const K6 = 'k6-%s-%s';

/**
* Creates a new binary instance.
*/
private function __construct(private string $path)
{
//
}

/**
* Creates a new k6 binary instance from the environment.
*/
public static function k6(): self
{
$arch = str_contains(php_uname('m'), 'arm') ? 'arm64' : 'amd64';

$path = match (PHP_OS_FAMILY) {
'Darwin' => sprintf(self::K6, 'macos', $arch),
'Linux' => sprintf(self::K6, 'linux', $arch),
'Windows' => sprintf(self::K6, 'windows', $arch),
default => throw new RuntimeException('Unsupported OS.'),
};

return new self((string) realpath(__DIR__.'/../bin/'.$path));
}

/**
* The string representation of the binary.
*/
public function __toString(): string
{
return $this->path;
}
}
23 changes: 0 additions & 23 deletions src/Example.php

This file was deleted.

14 changes: 14 additions & 0 deletions src/Expectation.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<?php

declare(strict_types=1);

namespace Pest\Stressless;

/**
* @internal
*
* @mixin Result
*/
final class Expectation
{
}
97 changes: 97 additions & 0 deletions src/Factory.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
<?php

declare(strict_types=1);

namespace Pest\Stressless;

use Pest\Stressless\Fluent\WithOptions;

/**
* @internal
*
* @mixin Result
*/
final class Factory
{
/**
* The computed result, if any.
*/
private ?Result $result = null;

/**
* Creates a new instance of the run factory.
*
* @param array{stages: array<array{duration: string, target: int}>} $options
*/
private function __construct(private readonly string $url, private array $options)
{
//
}

/**
* Creates a new instance of the run factory.
*/
public static function make(string $url): self
{
return new self($url, ['stages' => []]);
}

/**
* Specifies that run should run with the given number of something to be determined.
*/
public function with(int $number): WithOptions
{
return new WithOptions($this, $number);
}

/**
* Specifies that run should run with the given number of something to be determined.
*/
public function then(int $with): WithOptions
{
return new WithOptions($this, $with);
}

/**
* Specifies that the stress test should make the given number of requests concurrently for the given duration in seconds.
*/
public function stage(int $requests, int $seconds): self
{
$this->options['stages'][] = [
'duration' => "{$seconds}s",
'target' => $requests,
];

return $this;
}

/**
* Creates a new run instance.
*/
public function run(): Result
{
return $this->result = (new Run($this->url, $this->options))->start();
}

/**
* Forwards calls to the run result.
*
* @param array<int, mixed> $arguments
*/
public function __call(string $name, array $arguments): mixed
{
if (! $this->result instanceof \Pest\Stressless\Result) {
$this->run();
}

return $this->result->{$name}(...$arguments); // @phpstan-ignore-line
}

/**
* Forwards property access to the run result.
*/
public function __get(string $name): mixed
{
return $this->{$name}(); // @phpstan-ignore-line
}
}
87 changes: 87 additions & 0 deletions src/Fluent/StageDurationOptions.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
<?php

declare(strict_types=1);

namespace Pest\Stressless\Fluent;

use Pest\Stressless\Factory;

/**
* @internal
*/
final readonly class StageDurationOptions
{
/**
* Creates a new stage duration options instance.
*/
public function __construct(
private Factory $factory,
private int $requests,
private int $duration,
) {
//
}

/**
* Specifies that the stage should run for 1 second.
*/
public function second(): Factory
{
assert($this->duration === 1, 'The duration must be 1 second.');

return $this->seconds();
}

/**
* Specifies that the stage should run for the given number of seconds.
*/
public function seconds(): Factory
{
$this->factory->stage($this->requests, 0);
$this->factory->stage($this->requests, $this->duration);

return $this->factory;
}

/**
* Specifies that the stage should run for 1 minute.
*/
public function minute(): Factory
{
assert($this->duration === 1, 'The duration must be 1 minute.');

return $this->minutes();
}

/**
* Specifies that the stage should run for the given number of minutes.
*/
public function minutes(): Factory
{
$this->factory->stage($this->requests, 0);
$this->factory->stage($this->requests, $this->duration * 60);

return $this->factory;
}

/**
* Specifies that the stage should run for 1 hour.
*/
public function hour(): Factory
{
assert($this->duration === 1, 'The duration must be 1 hour.');

return $this->hours();
}

/**
* Specifies that the stage should run for the given number of hours.
*/
public function hours(): Factory
{
$this->factory->stage($this->requests, 0);
$this->factory->stage($this->requests, $this->duration * 60 * 60);

return $this->factory;
}
}
31 changes: 31 additions & 0 deletions src/Fluent/StageOptions.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<?php

declare(strict_types=1);

namespace Pest\Stressless\Fluent;

use Pest\Stressless\Factory;

/**
* @internal
*/
final readonly class StageOptions
{
/**
* Creates a new stage options instance.
*/
public function __construct(
private Factory $factory,
private int $requests,
) {
//
}

/**
* Specifies that the stage should run for the given duration.
*/
public function for(int $duration): StageDurationOptions
{
return new StageDurationOptions($this->factory, $this->requests, $duration);
}
}
Loading

0 comments on commit 6b46023

Please sign in to comment.