226 lines
7.3 KiB
PHP
226 lines
7.3 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace MageSail\Magesail\Test\Unit\Model;
|
|
|
|
use MageSail\Magesail\Model\NginxGlobalMapManager;
|
|
use Magento\Framework\App\Config\ScopeConfigInterface;
|
|
use Magento\Framework\Exception\LocalizedException;
|
|
use Magento\Framework\Shell;
|
|
use PHPUnit\Framework\TestCase;
|
|
use Psr\Log\LoggerInterface;
|
|
|
|
class NginxGlobalMapManagerTest extends TestCase
|
|
{
|
|
private string $tmpRoot = '';
|
|
|
|
protected function setUp(): void
|
|
{
|
|
parent::setUp();
|
|
$this->tmpRoot = sys_get_temp_dir() . '/magesail_ngx_' . uniqid('', true);
|
|
mkdir($this->tmpRoot, 0777, true);
|
|
}
|
|
|
|
protected function tearDown(): void
|
|
{
|
|
$this->removeTree($this->tmpRoot);
|
|
parent::tearDown();
|
|
}
|
|
|
|
private function removeTree(string $path): void
|
|
{
|
|
if (!is_dir($path)) {
|
|
return;
|
|
}
|
|
foreach (glob($path . '/*') ?: [] as $f) {
|
|
is_dir($f) ? $this->removeTree($f) : @unlink($f);
|
|
}
|
|
@rmdir($path);
|
|
}
|
|
|
|
private function minimalMapContent(): string
|
|
{
|
|
return <<<'MAP'
|
|
map $http_host $MAGE_RUN_CODE {
|
|
default '';
|
|
}
|
|
|
|
map $http_host $MAGE_RUN_TYPE {
|
|
default '';
|
|
}
|
|
MAP;
|
|
}
|
|
|
|
/** @param array<string, string|bool|null> $pathValues path => value for getValue */
|
|
private function makeManager(array $pathValues): NginxGlobalMapManager
|
|
{
|
|
$scope = $this->createMock(ScopeConfigInterface::class);
|
|
$scope->method('getValue')->willReturnCallback(
|
|
static function (string $path) use ($pathValues): string|bool|null {
|
|
return $pathValues[$path] ?? null;
|
|
}
|
|
);
|
|
|
|
return new NginxGlobalMapManager(
|
|
$scope,
|
|
$this->createMock(Shell::class),
|
|
$this->createMock(LoggerInterface::class)
|
|
);
|
|
}
|
|
|
|
public function testGetMapFilePathNullWhenEmptyConfig(): void
|
|
{
|
|
$m = $this->makeManager(['magesail/nginx/global_map_path' => ' ']);
|
|
self::assertNull($m->getMapFilePath());
|
|
}
|
|
|
|
public function testGetMapFilePathTrims(): void
|
|
{
|
|
$path = $this->tmpRoot . '/map.conf';
|
|
touch($path);
|
|
$m = $this->makeManager(['magesail/nginx/global_map_path' => ' ' . $path . ' ']);
|
|
self::assertSame($path, $m->getMapFilePath());
|
|
}
|
|
|
|
public function testExtractHostname(): void
|
|
{
|
|
$m = $this->makeManager([]);
|
|
self::assertSame('t.example.com', $m->extractHostname('https://t.example.com/path'));
|
|
}
|
|
|
|
public function testExtractHostnameThrowsOnInvalid(): void
|
|
{
|
|
$m = $this->makeManager([]);
|
|
$this->expectException(LocalizedException::class);
|
|
$m->extractHostname('not-a-url');
|
|
}
|
|
|
|
public function testReadMapFileThrowsWhenUnconfigured(): void
|
|
{
|
|
$m = $this->makeManager([]);
|
|
$this->expectException(LocalizedException::class);
|
|
$m->readMapFile();
|
|
}
|
|
|
|
public function testReadMapFileThrowsWhenNotReadable(): void
|
|
{
|
|
// Use a path that does not exist: is_readable() is false without chmod tricks.
|
|
// chmod(0000) is unreliable under root / some CI images (file stays readable).
|
|
$path = $this->tmpRoot . '/does_not_exist.map';
|
|
$m = $this->makeManager(['magesail/nginx/global_map_path' => $path]);
|
|
$this->expectException(LocalizedException::class);
|
|
$m->readMapFile();
|
|
}
|
|
|
|
public function testReadMapFileReturnsContent(): void
|
|
{
|
|
$path = $this->tmpRoot . '/ok.map';
|
|
$body = $this->minimalMapContent();
|
|
file_put_contents($path, $body);
|
|
$m = $this->makeManager(['magesail/nginx/global_map_path' => $path]);
|
|
self::assertSame($body, $m->readMapFile());
|
|
}
|
|
|
|
public function testGetDiagnosticsWhenPathNotConfigured(): void
|
|
{
|
|
$m = $this->makeManager([]);
|
|
$d = $m->getDiagnostics();
|
|
self::assertNull($d['path']);
|
|
self::assertFalse($d['exists']);
|
|
self::assertNotNull($d['error']);
|
|
}
|
|
|
|
public function testGetDiagnosticsForExistingWritableFile(): void
|
|
{
|
|
$path = $this->tmpRoot . '/diag.map';
|
|
file_put_contents($path, 'x');
|
|
$m = $this->makeManager(['magesail/nginx/global_map_path' => $path]);
|
|
$d = $m->getDiagnostics();
|
|
self::assertSame($path, $d['path']);
|
|
self::assertTrue($d['exists']);
|
|
self::assertTrue($d['readable']);
|
|
self::assertTrue($d['writable']);
|
|
}
|
|
|
|
public function testValidateNginxConfigWhenPathMissing(): void
|
|
{
|
|
$m = $this->makeManager([]);
|
|
$r = $m->validateNginxConfig();
|
|
self::assertFalse($r['valid']);
|
|
self::assertStringContainsString('not configured', (string) ($r['error'] ?? ''));
|
|
}
|
|
|
|
public function testValidateNginxConfigWhenMapUnreadable(): void
|
|
{
|
|
$path = $this->tmpRoot . '/missing_for_validate.map';
|
|
$m = $this->makeManager(['magesail/nginx/global_map_path' => $path]);
|
|
$r = $m->validateNginxConfig();
|
|
self::assertFalse($r['valid']);
|
|
self::assertStringContainsString('not readable', (string) ($r['error'] ?? ''));
|
|
}
|
|
|
|
public function testAddAndRemoveTunnelMapping(): void
|
|
{
|
|
$path = $this->tmpRoot . '/live.map';
|
|
file_put_contents($path, $this->minimalMapContent());
|
|
|
|
$m = $this->makeManager([
|
|
'magesail/nginx/global_map_path' => $path,
|
|
'magesail/nginx/map_run_type_value' => 'store',
|
|
]);
|
|
|
|
$m->addTunnelMapping('tunnel.dev', 'mgtun_abc');
|
|
|
|
$afterAdd = file_get_contents($path);
|
|
self::assertStringContainsString('tunnel.dev', $afterAdd);
|
|
self::assertStringContainsString('mgtun_abc', $afterAdd);
|
|
self::assertStringContainsString(NginxGlobalMapManager::LINE_COMMENT, $afterAdd);
|
|
self::assertStringContainsString('store', $afterAdd);
|
|
|
|
$m->removeTunnelMapping('tunnel.dev');
|
|
$afterRemove = file_get_contents($path);
|
|
self::assertStringNotContainsString('tunnel.dev', $afterRemove);
|
|
}
|
|
|
|
public function testAddTunnelMappingReplacesExistingHost(): void
|
|
{
|
|
$path = $this->tmpRoot . '/replace.map';
|
|
file_put_contents($path, $this->minimalMapContent());
|
|
|
|
$m = $this->makeManager([
|
|
'magesail/nginx/global_map_path' => $path,
|
|
'magesail/nginx/map_run_type_value' => 'store',
|
|
]);
|
|
|
|
$m->addTunnelMapping('h1', 'code_a');
|
|
$m->addTunnelMapping('h1', 'code_b');
|
|
|
|
$content = file_get_contents($path);
|
|
self::assertStringContainsString('code_b', $content);
|
|
self::assertStringNotContainsString('code_a', $content);
|
|
}
|
|
|
|
public function testWriteMapFileThrowsWhenDirectoryMissing(): void
|
|
{
|
|
$path = $this->tmpRoot . '/nodir/sub/map.conf';
|
|
$m = $this->makeManager(['magesail/nginx/global_map_path' => $path]);
|
|
$this->expectException(LocalizedException::class);
|
|
$m->writeMapFile('x');
|
|
}
|
|
|
|
public function testInsertIntoNamedMapThrowsWhenBlockMissing(): void
|
|
{
|
|
$path = $this->tmpRoot . '/bad.map';
|
|
file_put_contents($path, "map \$http_host \$OTHER { default ''; }\n");
|
|
|
|
$m = $this->makeManager([
|
|
'magesail/nginx/global_map_path' => $path,
|
|
'magesail/nginx/map_run_type_value' => 'store',
|
|
]);
|
|
|
|
$this->expectException(LocalizedException::class);
|
|
$m->addTunnelMapping('x.com', 'c');
|
|
}
|
|
}
|