Skip to content

Commit 4721633

Browse files
committed
Add more test coverage
1 parent 5ce30a1 commit 4721633

3 files changed

Lines changed: 101 additions & 10 deletions

File tree

demo-file.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
Hello users! At: 2026-01-15T09:46:38+00:00
1+
Hello users! At: 2026-01-15T12:35:35+00:00

src/Terremoth/Async/PhpFile.php

Lines changed: 27 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,12 @@
66
use InvalidArgumentException;
77
use Symfony\Component\Process\Process as SymfonyProcess;
88

9-
readonly class PhpFile
9+
class PhpFile
1010
{
1111
/**
1212
* @param string $file
13-
* @throws Exception
1413
* @param list<string> $args
14+
* @throws Exception
1515
*/
1616
public function __construct(private string $file, private array $args = [])
1717
{
@@ -20,9 +20,9 @@ public function __construct(private string $file, private array $args = [])
2020
. ' does not exists or is not readable!');
2121
}
2222

23-
$finfo = finfo_open(FILEINFO_MIME_TYPE);
24-
$mimeType = finfo_file($finfo, $this->file);
25-
finfo_close($finfo);
23+
$fileInfo = finfo_open(FILEINFO_MIME_TYPE);
24+
$mimeType = finfo_file($fileInfo, $this->file);
25+
finfo_close($fileInfo);
2626

2727
if (!in_array($mimeType, ['text/x-php', 'application/x-php', 'application/php', 'application/x-httpd-php'])) {
2828
throw new Exception('Error: file ' . $this->file . ' is not a PHP file!');
@@ -31,14 +31,32 @@ public function __construct(private string $file, private array $args = [])
3131

3232
public function run(): void
3333
{
34-
if (PHP_OS_FAMILY === 'Windows') {
34+
if ($this->getOsFamily() === 'Windows') {
3535
$template = ['start', "", '/B', PHP_BINARY, $this->file, ...$this->args];
3636
$process = new SymfonyProcess($template);
37-
$process->start();
37+
38+
$this->startProcess($process);
3839
return;
3940
}
4041

41-
$args = implode(' ', $this->args);
42-
exec(PHP_BINARY . ' ' . $this->file . ' ' . $args . ' > /dev/null 2>&1 &');
42+
$arguments = implode(' ', $this->args);
43+
$command = PHP_BINARY . ' ' . $this->file . ' ' . $arguments . ' > /dev/null 2>&1 &';
44+
45+
$this->executeCommand($command);
46+
}
47+
48+
protected function getOsFamily(): string
49+
{
50+
return PHP_OS_FAMILY;
51+
}
52+
53+
protected function startProcess(SymfonyProcess $symfonyProcess): void
54+
{
55+
$symfonyProcess->start();
56+
}
57+
58+
protected function executeCommand(string $command): void
59+
{
60+
exec($command);
4361
}
4462
}

tests/Terremoth/AsyncTest/PhpFileTest.php

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
namespace Terremoth\AsyncTest;
44

55
use PHPUnit\Framework\TestCase;
6+
use Symfony\Component\Process\Process as SymfonyProcess;
67
use Terremoth\Async\PhpFile;
78
use InvalidArgumentException;
89
use Exception;
@@ -97,4 +98,76 @@ public function testRunDoesNotThrow(): void
9798

9899
$this->expectNotToPerformAssertions();
99100
}
101+
102+
103+
public function testRunExecutesWindowsFlowWhenOsIsWindows(): void
104+
{
105+
$tempFile = tempnam(sys_get_temp_dir(), 'test_win') . '.php';
106+
file_put_contents($tempFile, '<?php echo "hello";');
107+
108+
try {
109+
$phpFile = $this->getMockBuilder(PhpFile::class)
110+
->setConstructorArgs([$tempFile, ['arg1', 'arg2']])
111+
->onlyMethods(['getOsFamily', 'startProcess', 'executeCommand'])
112+
->getMock();
113+
114+
$phpFile->expects($this->once())
115+
->method('getOsFamily')
116+
->willReturn('Windows');
117+
118+
$phpFile->expects($this->once())
119+
->method('startProcess')
120+
->willReturnCallback(function (SymfonyProcess $process) use ($tempFile) {
121+
$commandLine = $process->getCommandLine();
122+
123+
$this->assertStringContainsString('start', $commandLine);
124+
$this->assertStringContainsString('/B', $commandLine);
125+
$this->assertStringContainsString($tempFile, $commandLine);
126+
$this->assertStringContainsString('arg1', $commandLine);
127+
});
128+
129+
$phpFile->expects($this->never())
130+
->method('executeCommand');
131+
132+
$phpFile->run();
133+
} finally {
134+
if (file_exists($tempFile)) {
135+
unlink($tempFile);
136+
}
137+
}
138+
}
139+
140+
public function testRunExecutesUnixFlowWhenOsIsLinux(): void
141+
{
142+
$tempFile = tempnam(sys_get_temp_dir(), 'test_unix') . '.php';
143+
file_put_contents($tempFile, '<?php echo "hello";');
144+
145+
try {
146+
$phpFile = $this->getMockBuilder(PhpFile::class)
147+
->setConstructorArgs([$tempFile, ['argA']])
148+
->onlyMethods(['getOsFamily', 'startProcess', 'executeCommand'])
149+
->getMock();
150+
151+
$phpFile->expects($this->once())
152+
->method('getOsFamily')
153+
->willReturn('Linux');
154+
155+
$phpFile->expects($this->never())
156+
->method('startProcess');
157+
158+
$phpFile->expects($this->once())
159+
->method('executeCommand')
160+
->willReturnCallback(function (string $command) use ($tempFile) {
161+
$this->assertStringContainsString('> /dev/null 2>&1 &', $command);
162+
$this->assertStringContainsString($tempFile, $command);
163+
$this->assertStringContainsString('argA', $command);
164+
});
165+
166+
$phpFile->run();
167+
} finally {
168+
if (file_exists($tempFile)) {
169+
unlink($tempFile);
170+
}
171+
}
172+
}
100173
}

0 commit comments

Comments
 (0)