Skip to content

Commit

Permalink
Merge pull request #392 from gwleuverink/feature/child-processes
Browse files Browse the repository at this point in the history
child process - sanity tests and tweaks
  • Loading branch information
simonhamp authored Oct 31, 2024
2 parents 62ce895 + a8bf775 commit c1b46f4
Show file tree
Hide file tree
Showing 3 changed files with 156 additions and 9 deletions.
23 changes: 19 additions & 4 deletions src/ChildProcess.php
Original file line number Diff line number Diff line change
Expand Up @@ -52,23 +52,38 @@ public function all(): array
}

public function start(
string|array $cmd,
string $alias,
array $cmd,
?string $cwd = null,
?array $env = null,
bool $persistent = false
): static {

$process = $this->client->post('child-process/start', [
'alias' => $alias,
'cmd' => $cmd,
'cwd' => base_path(),
'cmd' => (array) $cmd,
'cwd' => $cwd ?? base_path(),
'env' => $env,
'persistent' => $persistent,
])->json();

return $this->fromRuntimeProcess($process);
}

public function php(string|array $cmd, string $alias, ?array $env = null, ?bool $persistent = false): self
{
$cmd = [PHP_BINARY, ...(array) $cmd];

return $this->start($cmd, $alias, env: $env, persistent: $persistent);
}

public function artisan(string|array $cmd, string $alias, ?array $env = null, ?bool $persistent = false): self
{
$cmd = ['artisan', ...(array) $cmd];

return $this->php($cmd, $alias, env: $env, persistent: $persistent);
}

public function stop(?string $alias = null): void
{
$this->client->post('child-process/stop', [
Expand Down Expand Up @@ -99,7 +114,7 @@ public function message(string $message, ?string $alias = null): static
return $this;
}

private function fromRuntimeProcess($process): static
protected function fromRuntimeProcess($process): static
{
if (isset($process['pid'])) {
$this->pid = $process['pid'];
Expand Down
15 changes: 10 additions & 5 deletions src/Facades/ChildProcess.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,24 @@
namespace Native\Laravel\Facades;

use Illuminate\Support\Facades\Facade;
use Native\Laravel\ChildProcess as Implement;

/**
* @method static \Native\Laravel\ChildProcess[] all()
* @method static \Native\Laravel\ChildProcess get(string $alias)
* @method static \Native\Laravel\ChildProcess get(string $alias = null)
* @method static \Native\Laravel\ChildProcess message(string $message, string $alias = null)
* @method static \Native\Laravel\ChildProcess restart(string $alias)
* @method static \Native\Laravel\ChildProcess start(string $alias, array $cmd, string $cwd = null, array $env = null, bool $persistent = false)
* @method static void stop(string $alias)
* @method static \Native\Laravel\ChildProcess restart(string $alias = null)
* @method static \Native\Laravel\ChildProcess start(string|array $cmd, string $alias, string $cwd = null, array $env = null, bool $persistent = false)
* @method static \Native\Laravel\ChildProcess php(string|array $cmd, string $alias, array $env = null, bool $persistent = false)
* @method static \Native\Laravel\ChildProcess artisan(string|array $cmd, string $alias, array $env = null, bool $persistent = false)
* @method static void stop(string $alias = null)
*/
class ChildProcess extends Facade
{
protected static function getFacadeAccessor()
{
return \Native\Laravel\ChildProcess::class;
self::clearResolvedInstance(Implement::class);

return Implement::class;
}
}
127 changes: 127 additions & 0 deletions tests/ChildProcess/ChildProcessTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
<?php

use Illuminate\Http\Client\Request;
use Illuminate\Support\Facades\Http;
use Mockery;

Check warning on line 5 in tests/ChildProcess/ChildProcessTest.php

View workflow job for this annotation

GitHub Actions / P8.3 - L11.* - prefer-lowest - ubuntu-latest

The use statement with non-compound name 'Mockery' has no effect

Check warning on line 5 in tests/ChildProcess/ChildProcessTest.php

View workflow job for this annotation

GitHub Actions / P8.3 - L10.* - prefer-lowest - ubuntu-latest

The use statement with non-compound name 'Mockery' has no effect

Check warning on line 5 in tests/ChildProcess/ChildProcessTest.php

View workflow job for this annotation

GitHub Actions / P8.3 - L10.* - prefer-stable - ubuntu-latest

The use statement with non-compound name 'Mockery' has no effect

Check warning on line 5 in tests/ChildProcess/ChildProcessTest.php

View workflow job for this annotation

GitHub Actions / P8.2 - L11.* - prefer-lowest - ubuntu-latest

The use statement with non-compound name 'Mockery' has no effect

Check warning on line 5 in tests/ChildProcess/ChildProcessTest.php

View workflow job for this annotation

GitHub Actions / P8.1 - L10.* - prefer-lowest - ubuntu-latest

The use statement with non-compound name 'Mockery' has no effect

Check warning on line 5 in tests/ChildProcess/ChildProcessTest.php

View workflow job for this annotation

GitHub Actions / P8.1 - L10.* - prefer-stable - ubuntu-latest

The use statement with non-compound name 'Mockery' has no effect
use Native\Laravel\ChildProcess as ChildProcessImplement;
use Native\Laravel\Client\Client;
use Native\Laravel\Facades\ChildProcess;

beforeEach(function () {
Http::fake();

$mock = Mockery::mock(ChildProcessImplement::class, [resolve(Client::class)])
->makePartial()
->shouldAllowMockingProtectedMethods();

$this->instance(ChildProcessImplement::class, $mock->allows([
'fromRuntimeProcess' => $mock,
]));
});

it('can start a child process', function () {
ChildProcess::start('foo bar', 'some-alias', 'path/to/dir', ['baz' => 'zah']);

Http::assertSent(function (Request $request) {
return $request->url() === 'http://localhost:4000/api/child-process/start' &&
$request['alias'] === 'some-alias' &&
$request['cmd'] === ['foo bar'] &&
$request['cwd'] === 'path/to/dir' &&
$request['env'] === ['baz' => 'zah'];
});
});

it('can start a php command', function () {
ChildProcess::php("-r 'sleep(5);'", 'some-alias', ['baz' => 'zah']);

Http::assertSent(function (Request $request) {
return $request->url() === 'http://localhost:4000/api/child-process/start' &&
$request['alias'] === 'some-alias' &&
$request['cmd'] === [PHP_BINARY, "-r 'sleep(5);'"] &&
$request['cwd'] === base_path() &&
$request['env'] === ['baz' => 'zah'];
});
});

it('can start a artisan command', function () {
ChildProcess::artisan('foo:bar --verbose', 'some-alias', ['baz' => 'zah']);

Http::assertSent(function (Request $request) {
return $request->url() === 'http://localhost:4000/api/child-process/start' &&
$request['alias'] === 'some-alias' &&
$request['cmd'] === [PHP_BINARY, 'artisan', 'foo:bar --verbose'] &&
$request['cwd'] === base_path() &&
$request['env'] === ['baz' => 'zah'];
});
});

it('accepts either a string or a array as start command argument', function () {
ChildProcess::start('foo bar', 'some-alias');
Http::assertSent(fn (Request $request) => $request['cmd'] === ['foo bar']);

ChildProcess::start(['foo', 'baz'], 'some-alias');
Http::assertSent(fn (Request $request) => $request['cmd'] === ['foo', 'baz']);
});

it('accepts either a string or a array as php command argument', function () {
ChildProcess::php("-r 'sleep(5);'", 'some-alias');
Http::assertSent(fn (Request $request) => $request['cmd'] === [PHP_BINARY, "-r 'sleep(5);'"]);

ChildProcess::php(['-r', "'sleep(5);'"], 'some-alias');
Http::assertSent(fn (Request $request) => $request['cmd'] === [PHP_BINARY, '-r', "'sleep(5);'"]);
});

it('accepts either a string or a array as artisan command argument', function () {
ChildProcess::artisan('foo:bar', 'some-alias');
Http::assertSent(fn (Request $request) => $request['cmd'] === [PHP_BINARY, 'artisan', 'foo:bar']);

ChildProcess::artisan(['foo:baz'], 'some-alias');
Http::assertSent(fn (Request $request) => $request['cmd'] === [PHP_BINARY, 'artisan', 'foo:baz']);
});

it('sets the cwd to the base path if none was given', function () {
ChildProcess::start(['foo', 'bar'], 'some-alias', cwd: 'path/to/dir');
Http::assertSent(fn (Request $request) => $request['cwd'] === 'path/to/dir');

ChildProcess::start(['foo', 'bar'], 'some-alias');
Http::assertSent(fn (Request $request) => $request['cwd'] === base_path());
});

it('can stop a child process', function () {
ChildProcess::stop('some-alias');

Http::assertSent(function (Request $request) {
return $request->url() === 'http://localhost:4000/api/child-process/stop' &&
$request['alias'] === 'some-alias';
});
});

it('can send messages to a child process', function () {
ChildProcess::message('some-message', 'some-alias');

Http::assertSent(function (Request $request) {
return $request->url() === 'http://localhost:4000/api/child-process/message' &&
$request['alias'] === 'some-alias' &&
$request['message'] === 'some-message';
});
});

it('can mark a process as persistent', function () {
ChildProcess::start('foo bar', 'some-alias', persistent: true);
Http::assertSent(fn (Request $request) => $request['persistent'] === true);
});

it('can mark a php command as persistent', function () {
ChildProcess::php("-r 'sleep(5);'", 'some-alias', persistent: true);
Http::assertSent(fn (Request $request) => $request['persistent'] === true);
});

it('can mark a artisan command as persistent', function () {
ChildProcess::artisan('foo:bar', 'some-alias', persistent: true);
Http::assertSent(fn (Request $request) => $request['persistent'] === true);
});

it('marks the process as non-persistent by default', function () {
ChildProcess::start('foo bar', 'some-alias');
Http::assertSent(fn (Request $request) => $request['persistent'] === false);
});

0 comments on commit c1b46f4

Please sign in to comment.