2026-08-07 01:01:58 +09:00
|
|
|
<?php
|
|
|
|
|
|
|
|
|
|
use OPNsense\NordVPN\SystemRunner;
|
|
|
|
|
use OPNsense\NordVPN\TunnelHealth;
|
|
|
|
|
use PHPUnit\Framework\TestCase;
|
|
|
|
|
|
|
|
|
|
final class SystemRunnerAndHealthTest extends TestCase
|
|
|
|
|
{
|
2026-08-07 02:30:26 +09:00
|
|
|
public function testRunDrainsStderr(): void
|
|
|
|
|
{
|
|
|
|
|
$runner = new SystemRunner(null, 2);
|
|
|
|
|
$output = $runner->run([
|
|
|
|
|
PHP_BINARY,
|
|
|
|
|
'-r',
|
|
|
|
|
'fwrite(STDERR, str_repeat("x", 262144)); echo "done";',
|
|
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
self::assertSame('done', $output);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function testRunTimesOut(): void
|
|
|
|
|
{
|
|
|
|
|
$runner = new SystemRunner(null, 1);
|
|
|
|
|
$started = hrtime(true);
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
$runner->run([PHP_BINARY, '-r', 'while (true) { usleep(100000); }']);
|
|
|
|
|
self::fail('Expected the system command to time out.');
|
|
|
|
|
} catch (\RuntimeException $exception) {
|
|
|
|
|
self::assertSame('System command timed out.', $exception->getMessage());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
self::assertLessThan(3, (hrtime(true) - $started) / 1_000_000_000);
|
|
|
|
|
}
|
|
|
|
|
|
2026-08-07 01:01:58 +09:00
|
|
|
public function testTunnelHealthRequiresRecentHandshake(): void
|
|
|
|
|
{
|
|
|
|
|
$runner = new SystemRunner(static fn() => "public-key\t900\n");
|
|
|
|
|
$recent = new TunnelHealth($runner, 180, static fn() => 1000);
|
|
|
|
|
$stale = new TunnelHealth($runner, 50, static fn() => 1000);
|
|
|
|
|
|
|
|
|
|
$this->assertTrue($recent->check('wg0')['available']);
|
|
|
|
|
$this->assertFalse($stale->check('wg0')['available']);
|
|
|
|
|
$this->assertFalse($recent->check('invalid')['available']);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function testWireGuardApplyFollowsRegistrationSequence(): void
|
|
|
|
|
{
|
|
|
|
|
$commands = [];
|
|
|
|
|
$runner = new SystemRunner(static function ($command) use (&$commands): string {
|
|
|
|
|
$commands[] = $command;
|
|
|
|
|
return '';
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
$runner->applyWireGuard();
|
|
|
|
|
|
|
|
|
|
$this->assertSame([
|
|
|
|
|
['/usr/local/sbin/configctl', 'interface', 'invoke', 'registration'],
|
|
|
|
|
['/usr/local/sbin/configctl', 'template', 'reload', 'OPNsense/Wireguard'],
|
|
|
|
|
['/usr/local/opnsense/scripts/wireguard/wg-service-control.php', '-a', 'configure'],
|
|
|
|
|
], $commands);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function testFirewallApplyReloadsRulesBeforeEvictingPluginStates(): void
|
|
|
|
|
{
|
|
|
|
|
$commands = [];
|
|
|
|
|
$runner = new SystemRunner(static function ($command) use (&$commands): string {
|
|
|
|
|
$commands[] = $command;
|
|
|
|
|
return '';
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
$runner->applyFirewall();
|
|
|
|
|
|
|
|
|
|
$this->assertSame([
|
|
|
|
|
['/usr/local/etc/rc.filter_configure'],
|
|
|
|
|
['/sbin/pfctl', '-k', 'label', '-k', SystemRunner::FIREWALL_LABEL],
|
|
|
|
|
], $commands);
|
|
|
|
|
}
|
|
|
|
|
}
|