param([switch]$KeepFixtures) $ErrorActionPreference = 'Stop' $repo = Split-Path $PSScriptRoot -Parent $compose = Join-Path $repo 'deploy/compose.test.yml' $project = 'linkport-matrix-' + [Guid]::NewGuid().ToString('N').Substring(0, 10) $tempDir = Join-Path ([IO.Path]::GetTempPath()) $project $caFile = Join-Path $tempDir 'ca.pem' . (Join-Path $PSScriptRoot 'go-toolchain.ps1') $goExecutable = Get-LinkPortGoExecutable -ProjectRoot $repo Get-Command docker -ErrorAction Stop | Out-Null $names = @('GOTOOLCHAIN', 'LINKPORT_MYSQL_TEST_ADDR', 'LINKPORT_MYSQL_TEST_USER', 'LINKPORT_MYSQL_TEST_PASSWORD', 'LINKPORT_MYSQL_TEST_CA', 'LINKPORT_MONGO_TEST_ADDR', 'LINKPORT_MONGO_TEST_USER', 'LINKPORT_MONGO_TEST_PASSWORD', 'LINKPORT_MONGO_TEST_CA', 'LINKPORT_SSH_TEST_ADDR', 'LINKPORT_SSH_TEST_USER', 'LINKPORT_SSH_TEST_PASSWORD', 'LINKPORT_TEST_SOCKS_ADDR', 'LINKPORT_TEST_SOCKS_USER', 'LINKPORT_TEST_SOCKS_PASSWORD') $previous = @{} foreach ($name in $names) { $previous[$name] = [Environment]::GetEnvironmentVariable($name, 'Process') } New-Item -ItemType Directory -Path $tempDir | Out-Null Push-Location -LiteralPath $repo try { $env:GOTOOLCHAIN = 'go1.27.1' docker compose -f $compose -p $project up -d --build --wait --wait-timeout 300 if ($LASTEXITCODE -ne 0) { throw 'Fixture startup failed' } docker compose -f $compose -p $project run --rm --no-deps mongo80-init if ($LASTEXITCODE -ne 0) { throw 'MongoDB replica initialization failed' } docker compose -f $compose -p $project cp 'cert-init:/certs/ca.pem' $caFile if ($LASTEXITCODE -ne 0) { throw 'Could not export test CA' } $env:LINKPORT_MYSQL_TEST_USER = 'root' $env:LINKPORT_MYSQL_TEST_PASSWORD = 'linkport-test-password' $env:LINKPORT_MYSQL_TEST_CA = $caFile $env:LINKPORT_MONGO_TEST_USER = 'root' $env:LINKPORT_MONGO_TEST_PASSWORD = 'linkport-test-password' $env:LINKPORT_MONGO_TEST_CA = Get-Content -LiteralPath $caFile -Raw $env:LINKPORT_SSH_TEST_USER = 'linkport' $env:LINKPORT_SSH_TEST_PASSWORD = 'linkport-test-password' $mysqlTargets = @(@('mysql57', 13357), @('mysql80', 13380), @('mysql84', 13384)) $mongoTargets = @(@('mongo60', 27060), @('mongo70', 27070), @('mongo80', 27080)) foreach ($route in @('direct', 'socks-open', 'socks-auth')) { $env:LINKPORT_TEST_SOCKS_ADDR = '' $env:LINKPORT_TEST_SOCKS_USER = '' $env:LINKPORT_TEST_SOCKS_PASSWORD = '' if ($route -eq 'socks-open') { $env:LINKPORT_TEST_SOCKS_ADDR = '127.0.0.1:11080' } if ($route -eq 'socks-auth') { $env:LINKPORT_TEST_SOCKS_ADDR = '127.0.0.1:11081' $env:LINKPORT_TEST_SOCKS_USER = 'socks' $env:LINKPORT_TEST_SOCKS_PASSWORD = 'socks-test-password' } foreach ($target in $mysqlTargets) { $env:LINKPORT_MYSQL_TEST_ADDR = if ($route -eq 'direct') { '127.0.0.1:' + $target[1] } else { $target[0] + ':3306' } Write-Host "Testing MySQL $($target[0]) via $route" & $goExecutable test -count=1 -timeout=120s ./internal/protocol/mysqlproxy -run '^TestRealMySQL$' -v if ($LASTEXITCODE -ne 0) { throw "MySQL matrix failed: $($target[0]) / $route" } } foreach ($target in $mongoTargets) { $env:LINKPORT_MONGO_TEST_ADDR = if ($route -eq 'direct') { '127.0.0.1:' + $target[1] } else { $target[0] + ':27017' } Write-Host "Testing MongoDB $($target[0]) via $route" & $goExecutable test -count=1 -timeout=120s ./internal/protocol/mongoproxy -run '^TestRealMongo$' -v if ($LASTEXITCODE -ne 0) { throw "MongoDB matrix failed: $($target[0]) / $route" } } $env:LINKPORT_SSH_TEST_ADDR = if ($route -eq 'direct') { '127.0.0.1:12222' } else { 'ssh:22' } Write-Host "Testing OpenSSH and SFTP via $route" & $goExecutable test -count=1 -timeout=120s ./internal/protocol/sshproxy -run '^TestRealSSH$' -v if ($LASTEXITCODE -ne 0) { throw "SSH matrix failed: $route" } } } finally { if ($KeepFixtures) { Write-Host ('Fixtures retained. Cleanup: docker compose -f "{0}" -p {1} down -v' -f $compose, $project) } else { docker compose -f $compose -p $project down -v } foreach ($name in $names) { [Environment]::SetEnvironmentVariable($name, $previous[$name], 'Process') } Pop-Location if (Test-Path -LiteralPath $caFile) { Remove-Item -LiteralPath $caFile -Force } Remove-Item -LiteralPath $tempDir }