Files
michaelschiemer/tests/Unit/Framework/Process/SystemProcessTest.php
Michael Schiemer fc3d7e6357 feat(Production): Complete production deployment infrastructure
- Add comprehensive health check system with multiple endpoints
- Add Prometheus metrics endpoint
- Add production logging configurations (5 strategies)
- Add complete deployment documentation suite:
  * QUICKSTART.md - 30-minute deployment guide
  * DEPLOYMENT_CHECKLIST.md - Printable verification checklist
  * DEPLOYMENT_WORKFLOW.md - Complete deployment lifecycle
  * PRODUCTION_DEPLOYMENT.md - Comprehensive technical reference
  * production-logging.md - Logging configuration guide
  * ANSIBLE_DEPLOYMENT.md - Infrastructure as Code automation
  * README.md - Navigation hub
  * DEPLOYMENT_SUMMARY.md - Executive summary
- Add deployment scripts and automation
- Add DEPLOYMENT_PLAN.md - Concrete plan for immediate deployment
- Update README with production-ready features

All production infrastructure is now complete and ready for deployment.
2025-10-25 19:18:37 +02:00

244 lines
7.0 KiB
PHP

<?php
declare(strict_types=1);
use App\Framework\Console\ExitCode;
use App\Framework\Core\ValueObjects\Duration;
use App\Framework\Filesystem\ValueObjects\FilePath;
use App\Framework\Logging\Logger;
use App\Framework\Process\Exceptions\ProcessException;
use App\Framework\Process\SystemProcess;
use App\Framework\Process\ValueObjects\Command;
use App\Framework\Process\ValueObjects\EnvironmentVariables;
beforeEach(function () {
$this->logger = Mockery::mock(Logger::class);
$this->logger->shouldReceive('debug')->andReturn(null);
$this->process = new SystemProcess($this->logger);
});
afterEach(function () {
Mockery::close();
});
describe('SystemProcess - Basic Execution', function () {
it('can execute simple command successfully', function () {
$result = $this->process->run(
Command::fromArray(['echo', 'hello'])
);
expect($result->isSuccess())->toBeTrue()
->and($result->exitCode)->toBe(ExitCode::SUCCESS)
->and($result->getOutput())->toContain('hello')
->and($result->hasOutput())->toBeTrue();
});
it('captures stdout correctly', function () {
$result = $this->process->run(
Command::fromArray(['echo', 'test output'])
);
expect($result->stdout)->toContain('test output')
->and($result->getOutput())->toContain('test output');
});
it('captures stderr correctly', function () {
$result = $this->process->run(
Command::fromString('>&2 echo "error message"')
);
expect($result->stderr)->toContain('error message')
->and($result->getErrorOutput())->toContain('error message')
->and($result->hasErrors())->toBeTrue();
});
it('handles failed commands', function () {
$result = $this->process->run(
Command::fromString('exit 1')
);
expect($result->isFailed())->toBeTrue()
->and($result->exitCode)->toBe(ExitCode::GENERAL_ERROR);
});
it('tracks execution time', function () {
$result = $this->process->run(
Command::fromArray(['sleep', '0.1'])
);
expect($result->runtime->toMilliseconds())->toBeGreaterThan(50);
});
});
describe('SystemProcess - Working Directory', function () {
it('can execute command in specific directory', function () {
$tempDir = sys_get_temp_dir();
$workingDir = FilePath::create($tempDir);
$result = $this->process->run(
command: Command::fromString('pwd'),
workingDirectory: $workingDir
);
expect($result->isSuccess())->toBeTrue()
->and($result->stdout)->toContain($tempDir);
});
it('throws exception for invalid working directory', function () {
$invalidDir = FilePath::create('/nonexistent/directory/path');
$this->process->run(
command: Command::fromArray(['echo', 'test']),
workingDirectory: $invalidDir
);
})->throws(ProcessException::class);
});
describe('SystemProcess - Environment Variables', function () {
it('can pass environment variables', function () {
$env = EnvironmentVariables::fromArray([
'TEST_VAR' => 'test_value',
]);
$result = $this->process->run(
command: Command::fromString('echo $TEST_VAR'),
env: $env
);
expect($result->stdout)->toContain('test_value');
});
it('merges with existing environment', function () {
$env = EnvironmentVariables::fromArray([
'CUSTOM_VAR' => 'custom_value',
]);
$result = $this->process->run(
command: Command::fromString('echo $PATH'),
env: $env
);
// PATH should still be available
expect($result->stdout)->not->toBeEmpty();
});
});
describe('SystemProcess - Timeout', function () {
it('respects timeout for long-running commands', function () {
$timeout = Duration::fromSeconds(1);
$result = $this->process->run(
command: Command::fromArray(['sleep', '0.5']),
timeout: $timeout
);
expect($result->isSuccess())->toBeTrue()
->and($result->runtime->toSeconds())->toBeLessThan(1.0);
});
it('handles commands that complete within timeout', function () {
$timeout = Duration::fromSeconds(5);
$result = $this->process->run(
command: Command::fromArray(['echo', 'fast']),
timeout: $timeout
);
expect($result->isSuccess())->toBeTrue();
});
});
describe('SystemProcess - Command Existence', function () {
it('detects existing commands', function () {
$exists = $this->process->commandExists('echo');
expect($exists)->toBeTrue();
});
it('detects non-existing commands', function () {
$exists = $this->process->commandExists('nonexistent_command_xyz');
expect($exists)->toBeFalse();
});
});
describe('SystemProcess - Async Execution', function () {
it('can start process asynchronously', function () {
$running = $this->process->start(
Command::fromArray(['sleep', '0.1'])
);
expect($running->isRunning())->toBeTrue()
->and($running->getPid())->toBeGreaterThan(0);
$result = $running->wait();
expect($result->isSuccess())->toBeTrue()
->and($running->isRunning())->toBeFalse();
});
it('can terminate running process', function () {
$running = $this->process->start(
Command::fromArray(['sleep', '10'])
);
expect($running->isRunning())->toBeTrue();
$running->terminate();
// Give it a moment to terminate
usleep(100000);
expect($running->isRunning())->toBeFalse();
});
it('can kill running process', function () {
$running = $this->process->start(
Command::fromArray(['sleep', '10'])
);
expect($running->isRunning())->toBeTrue();
$running->kill();
// Give it a moment to be killed
usleep(100000);
expect($running->isRunning())->toBeFalse();
});
});
describe('SystemProcess - ProcessResult', function () {
it('provides combined output', function () {
$result = $this->process->run(
Command::fromString('echo "stdout" && >&2 echo "stderr"')
);
$combined = $result->getCombinedOutput();
expect($combined)->toContain('stdout')
->and($combined)->toContain('stderr');
});
it('converts result to array', function () {
$result = $this->process->run(
Command::fromArray(['echo', 'test'])
);
$array = $result->toArray();
expect($array)->toHaveKeys([
'command',
'stdout',
'stderr',
'exit_code',
'exit_description',
'runtime_ms',
'success',
])
->and($array['success'])->toBeTrue()
->and($array['exit_code'])->toBe(0);
});
});