Group all 69 projects into category subfolders under src/ and tests/ so the Rider Solution Explorer mirrors the module structure. Folders: Core, Server, Drivers (with a nested Driver CLIs subfolder), Client, Tooling. - Move every project folder on disk with git mv (history preserved as renames). - Recompute relative paths in 57 .csproj files: cross-category ProjectReferences, the lib/ HintPath+None refs in Driver.Historian.Wonderware, and the external mxaccessgw refs in Driver.Galaxy and its test project. - Rebuild ZB.MOM.WW.OtOpcUa.slnx with nested solution folders. - Re-prefix project paths in functional scripts (e2e, compliance, smoke SQL, integration, install). Build green (0 errors); unit tests pass. Docs left for a separate pass. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
124 lines
4.3 KiB
PowerShell
124 lines
4.3 KiB
PowerShell
#Requires -Version 7.0
|
|
<#
|
|
.SYNOPSIS
|
|
Orchestrates the FOCAS driver integration-test loop: bring up the
|
|
focas-mock Docker container, run the managed wire-client integration
|
|
tests, tear down Docker.
|
|
|
|
.DESCRIPTION
|
|
The FOCAS integration fixture now needs just two things running
|
|
together:
|
|
1. A single focas-mock container listening on :8193 (one service,
|
|
no per-series compose profile ceremony — the mock's native
|
|
FOCAS Ethernet responder handles every call the managed driver
|
|
issues).
|
|
2. The integration-test assembly built. The managed
|
|
`WireFocasClient` dials the mock directly; there is no shim
|
|
DLL, no P/Invoke, no test-bin DLL copy step.
|
|
This script handles both and cleans up on exit.
|
|
|
|
Designed to run unattended on a build agent or on a developer box.
|
|
Exit code matches the test suite (0 = all pass or skip-clean,
|
|
non-zero when any integration test failed).
|
|
|
|
.PARAMETER Profile
|
|
focas-mock profile name to seed at startup (e.g. `ThirtyOne_i`,
|
|
`Sixteen_i`, `fwlib30i64`). Defaults to `ThirtyOne_i`. The fixture
|
|
resolves aliases via `FocasCncSeries`, and tests that need per-series
|
|
state can call `fixture.LoadProfileAsync` directly at test start to
|
|
override the default.
|
|
|
|
.PARAMETER SkipDocker
|
|
Skip docker up/down. Use when the mock is already running from
|
|
another shell.
|
|
|
|
.PARAMETER Configuration
|
|
Build configuration — Debug or Release. Default: Debug.
|
|
|
|
.PARAMETER KeepDocker
|
|
Don't tear down the docker stack on exit. Useful for iterating on
|
|
tests.
|
|
#>
|
|
|
|
param(
|
|
[string]$Profile = "ThirtyOne_i",
|
|
[switch]$SkipDocker,
|
|
[ValidateSet("Debug", "Release")]
|
|
[string]$Configuration = "Debug",
|
|
[switch]$KeepDocker
|
|
)
|
|
|
|
Set-StrictMode -Version 3.0
|
|
$ErrorActionPreference = "Stop"
|
|
|
|
$repoRoot = (Resolve-Path (Join-Path $PSScriptRoot "..\..")).Path
|
|
$integTests = Join-Path $repoRoot "tests\Drivers\ZB.MOM.WW.OtOpcUa.Driver.FOCAS.IntegrationTests"
|
|
$dockerYml = Join-Path $integTests "Docker\docker-compose.yml"
|
|
|
|
function Write-Step { param([string]$Msg) Write-Host ""; Write-Host "=== $Msg ===" -ForegroundColor Cyan }
|
|
function Write-Info { param([string]$Msg) Write-Host "[INFO] $Msg" -ForegroundColor Gray }
|
|
function Write-Fail { param([string]$Msg) Write-Host "[FAIL] $Msg" -ForegroundColor Red }
|
|
|
|
$cleanupScripts = @()
|
|
trap {
|
|
Write-Host ""
|
|
Write-Fail "run-focas.ps1 crashed: $_"
|
|
foreach ($c in $cleanupScripts) { try { & $c } catch { Write-Host "cleanup failed: $_" -ForegroundColor DarkYellow } }
|
|
exit 2
|
|
}
|
|
|
|
Write-Step "Build FOCAS IntegrationTests ($Configuration)"
|
|
dotnet build (Join-Path $integTests "ZB.MOM.WW.OtOpcUa.Driver.FOCAS.IntegrationTests.csproj") `
|
|
--configuration $Configuration --nologo --verbosity minimal
|
|
if ($LASTEXITCODE -ne 0) { throw "dotnet build failed (exit $LASTEXITCODE)" }
|
|
|
|
if (-not $SkipDocker) {
|
|
Write-Step "docker compose up"
|
|
if (-not (Get-Command docker -ErrorAction SilentlyContinue)) {
|
|
Write-Fail "docker CLI not on PATH. Install Docker Desktop or pass -SkipDocker + run the mock externally."
|
|
exit 4
|
|
}
|
|
|
|
docker compose -f $dockerYml up -d --build --wait 2>&1 | Write-Host
|
|
if ($LASTEXITCODE -ne 0) { throw "docker compose up failed (exit $LASTEXITCODE)" }
|
|
|
|
if (-not $KeepDocker) {
|
|
$cleanupScripts += {
|
|
Write-Step "docker compose down"
|
|
docker compose -f $dockerYml down --remove-orphans 2>&1 | Write-Host
|
|
}
|
|
}
|
|
|
|
Write-Info "probing localhost:8193..."
|
|
$tcp = [System.Net.Sockets.TcpClient]::new()
|
|
try {
|
|
$ok = $tcp.ConnectAsync("127.0.0.1", 8193).Wait([TimeSpan]::FromSeconds(5))
|
|
if (-not $ok -or -not $tcp.Connected) {
|
|
throw "TCP probe to localhost:8193 failed after docker compose --wait succeeded"
|
|
}
|
|
}
|
|
finally { $tcp.Dispose() }
|
|
Write-Info "mock is accepting connections"
|
|
}
|
|
else {
|
|
Write-Step "Docker (skipped)"
|
|
}
|
|
|
|
Write-Step "dotnet test (wire-backend integration)"
|
|
$env:OTOPCUA_FOCAS_SIM_PROFILE = $Profile
|
|
|
|
dotnet test (Join-Path $integTests "ZB.MOM.WW.OtOpcUa.Driver.FOCAS.IntegrationTests.csproj") `
|
|
--configuration $Configuration --no-build --nologo --verbosity minimal
|
|
$testExit = $LASTEXITCODE
|
|
|
|
foreach ($c in $cleanupScripts) { & $c }
|
|
|
|
if ($testExit -ne 0) {
|
|
Write-Fail "integration tests failed with exit $testExit"
|
|
exit $testExit
|
|
}
|
|
|
|
Write-Host ""
|
|
Write-Host "run-focas.ps1 completed successfully." -ForegroundColor Green
|
|
exit 0
|