clusev/tests/Feature/WgBridgeTest.php

101 lines
3.6 KiB
PHP

<?php
namespace Tests\Feature;
use App\Services\WgBridge;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;
class WgBridgeTest extends TestCase
{
use RefreshDatabase;
private string $dir;
protected function setUp(): void
{
parent::setUp();
$this->dir = storage_path('app/restart-signal');
@mkdir($this->dir, 0775, true);
foreach (glob($this->dir.'/wg-*') ?: [] as $f) {
@unlink($f);
}
}
protected function tearDown(): void
{
foreach (glob($this->dir.'/wg-*') ?: [] as $f) {
@unlink($f);
}
parent::tearDown();
}
public function test_request_writes_a_well_formed_request_and_returns_an_id(): void
{
$id = app(WgBridge::class)->request('add-peer', ['name' => 'laptop']);
$this->assertMatchesRegularExpression('/^[A-Za-z0-9]{16,64}$/', $id);
$req = json_decode((string) file_get_contents($this->dir.'/wg-request.json'), true);
$this->assertSame($id, $req['id']);
$this->assertSame('add-peer', $req['action']);
$this->assertSame('laptop', $req['name']);
}
public function test_request_rejects_an_unknown_action(): void
{
$this->expectException(\InvalidArgumentException::class);
app(WgBridge::class)->request('rm -rf', ['name' => 'x']);
}
public function test_request_rejects_an_invalid_name(): void
{
$this->expectException(\InvalidArgumentException::class);
app(WgBridge::class)->request('add-peer', ['name' => 'bad name; rm']);
}
public function test_request_rejects_bad_port_and_subnet_and_endpoint(): void
{
$b = app(WgBridge::class);
foreach ([['set-port', ['port' => '70000']], ['set-port', ['port' => 'abc']], ['set-subnet', ['subnet' => 'not-a-cidr']], ['set-endpoint', ['endpoint' => 'a b']]] as [$a, $args]) {
try {
$b->request($a, $args);
$this->fail("expected rejection for $a");
} catch (\InvalidArgumentException $e) {
$this->assertTrue(true);
}
}
}
public function test_result_only_returns_for_the_matching_id(): void
{
$id = app(WgBridge::class)->request('add-peer', ['name' => 'laptop']);
file_put_contents($this->dir."/wg-result-{$id}.json", json_encode(['id' => $id, 'ok' => true, 'message' => 'ok', 'config' => 'cfg', 'at' => time()]));
$this->assertNull(app(WgBridge::class)->result('AAAAAAAAAAAAAAAAdifferent'));
$r = app(WgBridge::class)->result($id);
$this->assertTrue($r['ok']);
$this->assertSame('cfg', $r['config']);
}
public function test_result_rejects_a_malformed_id_without_filesystem_access(): void
{
$this->assertNull(app(WgBridge::class)->result('../etc/passwd'));
$this->assertNull(app(WgBridge::class)->result('x'));
}
public function test_setup_request_validates_and_writes(): void
{
$id = app(WgBridge::class)->request('setup', ['subnet' => '10.99.0.0/24', 'port' => '51820', 'endpoint' => '1.2.3.4:51820', 'name' => 'client-1']);
$this->assertMatchesRegularExpression('/^[A-Za-z0-9]{16,64}$/', $id);
$req = json_decode((string) file_get_contents(storage_path('app/restart-signal/wg-request.json')), true);
$this->assertSame('setup', $req['action']);
$this->assertSame('10.99.0.0/24', $req['subnet']);
}
public function test_setup_request_rejects_a_bad_subnet(): void
{
$this->expectException(\InvalidArgumentException::class);
app(WgBridge::class)->request('setup', ['subnet' => 'nope', 'port' => '51820', 'name' => 'c']);
}
}