logger = Mockery::mock(Logger::class); $this->logger->shouldReceive('debug')->andReturn(null); $this->process = new SystemProcess($this->logger); }); afterEach(function () { Mockery::close(); }); describe('Process Integration - Real World Scenarios', function () { it('can execute multi-line script', function () { $command = Command::fromString(' echo "line1" echo "line2" echo "line3" '); $result = $this->process->run($command); expect($result->isSuccess())->toBeTrue() ->and($result->stdout)->toContain('line1') ->and($result->stdout)->toContain('line2') ->and($result->stdout)->toContain('line3'); }); it('can create and read temporary file', function () { $tempFile = FilePath::temp('process_test.txt'); $command = Command::fromString( "echo 'test content' > {$tempFile->toString()} && cat {$tempFile->toString()}" ); $result = $this->process->run($command); expect($result->isSuccess())->toBeTrue() ->and($result->stdout)->toContain('test content'); // Cleanup if ($tempFile->exists()) { unlink($tempFile->toString()); } }); it('can pipe commands', function () { $command = Command::fromString('echo "hello world" | grep "world"'); $result = $this->process->run($command); expect($result->isSuccess())->toBeTrue() ->and($result->stdout)->toContain('world'); }); it('handles complex environment variable substitution', function () { $env = EnvironmentVariables::fromArray([ 'PREFIX' => 'test', 'SUFFIX' => 'value', ]); $command = Command::fromString('echo "$PREFIX-$SUFFIX"'); $result = $this->process->run( command: $command, env: $env ); expect($result->stdout)->toContain('test-value'); }); it('can execute PHP script', function () { $phpCode = 'echo json_encode(["status" => "ok", "pid" => getmypid()]);'; $command = Command::fromArray(['php', '-r', $phpCode]); $result = $this->process->run($command); expect($result->isSuccess())->toBeTrue(); $output = json_decode($result->stdout, true); expect($output)->toBeArray() ->and($output['status'])->toBe('ok') ->and($output['pid'])->toBeGreaterThan(0); }); it('handles large output', function () { // Generate 1000 lines of output $command = Command::fromString('for i in {1..1000}; do echo "Line $i"; done'); $result = $this->process->run($command); expect($result->isSuccess())->toBeTrue(); $lines = explode("\n", trim($result->stdout)); expect(count($lines))->toBeGreaterThanOrEqual(1000); }); it('preserves exit codes correctly', function () { $testCases = [ ['exit 0', ExitCode::SUCCESS], ['exit 1', ExitCode::GENERAL_ERROR], ['exit 2', ExitCode::USAGE_ERROR], ['exit 126', ExitCode::PERMISSION_DENIED], ]; foreach ($testCases as [$cmd, $expectedCode]) { $result = $this->process->run(Command::fromString($cmd)); expect($result->exitCode)->toBe($expectedCode); } }); }); describe('Process Integration - Error Handling', function () { it('handles command not found', function () { $result = $this->process->run( Command::fromString('nonexistent_command_xyz_123') ); expect($result->isFailed())->toBeTrue() ->and($result->hasErrors())->toBeTrue(); }); it('handles permission denied', function () { // Try to write to root directory (should fail) $command = Command::fromString('touch /root/test_file.txt'); $result = $this->process->run($command); expect($result->isFailed())->toBeTrue(); }); it('handles syntax errors in shell commands', function () { $command = Command::fromString('echo "unclosed string'); $result = $this->process->run($command); expect($result->isFailed())->toBeTrue(); }); }); describe('Process Integration - Performance', function () { it('can execute multiple processes sequentially', function () { $startTime = microtime(true); for ($i = 0; $i < 5; $i++) { $result = $this->process->run( Command::fromArray(['echo', "iteration {$i}"]) ); expect($result->isSuccess())->toBeTrue(); } $totalTime = microtime(true) - $startTime; // Should complete 5 simple commands in under 2 seconds expect($totalTime)->toBeLessThan(2.0); }); it('tracks runtime accurately', function () { $sleepTime = 0.2; // 200ms $result = $this->process->run( Command::fromArray(['sleep', (string) $sleepTime]) ); $runtime = $result->runtime->toSeconds(); // Runtime should be approximately the sleep time (with some tolerance) expect($runtime)->toBeGreaterThanOrEqual($sleepTime) ->and($runtime)->toBeLessThan($sleepTime + 0.1); }); }); describe('Process Integration - Async Process Management', function () { it('can manage multiple async processes', function () { $processes = []; // Start 3 processes for ($i = 0; $i < 3; $i++) { $processes[] = $this->process->start( Command::fromArray(['sleep', '0.1']) ); } // All should be running foreach ($processes as $proc) { expect($proc->isRunning())->toBeTrue(); } // Wait for all foreach ($processes as $proc) { $result = $proc->wait(); expect($result->isSuccess())->toBeTrue(); } }); it('can capture output from async process', function () { $running = $this->process->start( Command::fromArray(['echo', 'async output']) ); $result = $running->wait(); expect($result->stdout)->toContain('async output') ->and($result->isSuccess())->toBeTrue(); }); });