#Requires -Version 7.0 <# .SYNOPSIS Runs every scripts/e2e/test-*.ps1 and tallies PASS / FAIL / SKIP. .DESCRIPTION The per-protocol scripts require protocol-specific NodeIds that depend on your server's config DB seed. This runner expects a JSON sidecar at scripts/e2e/e2e-config.json (not checked in — see README) with one entry per driver giving the NodeIds + endpoints to pass through. Any driver missing from the sidecar is skipped with a clear message rather than failing hard. .PARAMETER ConfigFile Path to the sidecar JSON. Default: scripts/e2e/e2e-config.json. .PARAMETER OpcUaUrl Default OPC UA endpoint passed to each per-driver script. Default opc.tcp://localhost:4840. Individual entries in the config file can override. #> param( [string]$ConfigFile = "$PSScriptRoot/e2e-config.json", [string]$OpcUaUrl = "opc.tcp://localhost:4840" ) $ErrorActionPreference = "Stop" . "$PSScriptRoot/_common.ps1" if (-not (Test-Path $ConfigFile)) { Write-Fail "no config at $ConfigFile — copy e2e-config.sample.json + fill in your NodeIds first (see README)" exit 2 } $config = Get-Content $ConfigFile -Raw | ConvertFrom-Json $summary = [ordered]@{} function Run-Suite { param( [string]$Name, [scriptblock]$Action ) try { & $Action $summary[$Name] = if ($LASTEXITCODE -eq 0) { "PASS" } else { "FAIL" } } catch { Write-Fail "$Name runner crashed: $_" $summary[$Name] = "FAIL" } } # --------------------------------------------------------------------------- # Modbus # --------------------------------------------------------------------------- if ($config.modbus) { Write-Header "== MODBUS ==" Run-Suite "modbus" { & "$PSScriptRoot/test-modbus.ps1" ` -ModbusHost $config.modbus.endpoint ` -OpcUaUrl ($config.modbus.opcUaUrl ?? $OpcUaUrl) ` -BridgeNodeId $config.modbus.bridgeNodeId } } else { $summary["modbus"] = "SKIP (no config entry)" } # --------------------------------------------------------------------------- # AB CIP # --------------------------------------------------------------------------- if ($config.abcip) { Write-Header "== AB CIP ==" Run-Suite "abcip" { & "$PSScriptRoot/test-abcip.ps1" ` -Gateway $config.abcip.gateway ` -Family ($config.abcip.family ?? "ControlLogix") ` -TagPath ($config.abcip.tagPath ?? "TestDINT") ` -OpcUaUrl ($config.abcip.opcUaUrl ?? $OpcUaUrl) ` -BridgeNodeId $config.abcip.bridgeNodeId } } else { $summary["abcip"] = "SKIP (no config entry)" } # --------------------------------------------------------------------------- # AB Legacy # --------------------------------------------------------------------------- if ($config.ablegacy) { Write-Header "== AB LEGACY ==" Run-Suite "ablegacy" { & "$PSScriptRoot/test-ablegacy.ps1" ` -Gateway $config.ablegacy.gateway ` -PlcType ($config.ablegacy.plcType ?? "Slc500") ` -Address ($config.ablegacy.address ?? "N7:5") ` -OpcUaUrl ($config.ablegacy.opcUaUrl ?? $OpcUaUrl) ` -BridgeNodeId $config.ablegacy.bridgeNodeId } } else { $summary["ablegacy"] = "SKIP (no config entry)" } # --------------------------------------------------------------------------- # S7 # --------------------------------------------------------------------------- if ($config.s7) { Write-Header "== S7 ==" Run-Suite "s7" { & "$PSScriptRoot/test-s7.ps1" ` -S7Host $config.s7.endpoint ` -Cpu ($config.s7.cpu ?? "S71500") ` -Slot ($config.s7.slot ?? 0) ` -Address ($config.s7.address ?? "DB1.DBW0") ` -OpcUaUrl ($config.s7.opcUaUrl ?? $OpcUaUrl) ` -BridgeNodeId $config.s7.bridgeNodeId } } else { $summary["s7"] = "SKIP (no config entry)" } # --------------------------------------------------------------------------- # FOCAS # --------------------------------------------------------------------------- if ($config.focas) { Write-Header "== FOCAS ==" Run-Suite "focas" { & "$PSScriptRoot/test-focas.ps1" ` -CncHost $config.focas.host ` -CncPort ($config.focas.port ?? 8193) ` -Address ($config.focas.address ?? "R100") ` -OpcUaUrl ($config.focas.opcUaUrl ?? $OpcUaUrl) ` -BridgeNodeId $config.focas.bridgeNodeId } } else { $summary["focas"] = "SKIP (no config entry)" } # --------------------------------------------------------------------------- # TwinCAT # --------------------------------------------------------------------------- if ($config.twincat) { Write-Header "== TWINCAT ==" Run-Suite "twincat" { & "$PSScriptRoot/test-twincat.ps1" ` -AmsNetId $config.twincat.amsNetId ` -AmsPort ($config.twincat.amsPort ?? 851) ` -SymbolPath ($config.twincat.symbolPath ?? "MAIN.iCounter") ` -OpcUaUrl ($config.twincat.opcUaUrl ?? $OpcUaUrl) ` -BridgeNodeId $config.twincat.bridgeNodeId } } else { $summary["twincat"] = "SKIP (no config entry)" } # --------------------------------------------------------------------------- # Phase 7 virtual tags + scripted alarms # --------------------------------------------------------------------------- if ($config.phase7) { Write-Header "== PHASE 7 virtual tags + scripted alarms ==" Run-Suite "phase7" { & "$PSScriptRoot/test-phase7-virtualtags.ps1" ` -ModbusHost ($config.phase7.modbusEndpoint ?? $config.modbus.endpoint) ` -OpcUaUrl ($config.phase7.opcUaUrl ?? $OpcUaUrl) ` -InputNodeId $config.phase7.inputNodeId ` -VirtualNodeId $config.phase7.virtualNodeId ` -AlarmNodeId ($config.phase7.alarmNodeId ?? $null) } } else { $summary["phase7"] = "SKIP (no config entry)" } # --------------------------------------------------------------------------- # Final matrix # --------------------------------------------------------------------------- Write-Host "" Write-Host "==================== FINAL MATRIX ====================" -ForegroundColor Cyan $summary.GetEnumerator() | ForEach-Object { $color = switch -Wildcard ($_.Value) { "PASS" { "Green" } "FAIL" { "Red" } "SKIP*" { "Yellow" } default { "Gray" } } Write-Host (" {0,-10} {1}" -f $_.Key, $_.Value) -ForegroundColor $color } $failed = ($summary.Values | Where-Object { $_ -eq "FAIL" }).Count if ($failed -gt 0) { Write-Host "$failed suite(s) failed." -ForegroundColor Red exit 1 } Write-Host "All present suites passed." -ForegroundColor Green