#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 } # -AsHashtable + Get-Or below keeps access tolerant of missing keys even under # Set-StrictMode -Version 3.0 (inherited from _common.ps1). Without this a # missing "$config.ablegacy" throws "property cannot be found on this object". $config = Get-Content $ConfigFile -Raw | ConvertFrom-Json -AsHashtable $summary = [ordered]@{} # Return $Table[$Key] if present, else $Default. Nested tables are themselves # hashtables so this composes: (Get-Or $config modbus)['opcUaUrl']. function Get-Or { param($Table, [string]$Key, $Default = $null) if ($Table -and $Table.ContainsKey($Key)) { return $Table[$Key] } return $Default } 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 # --------------------------------------------------------------------------- $modbus = Get-Or $config "modbus" if ($modbus) { Write-Header "== MODBUS ==" Run-Suite "modbus" { & "$PSScriptRoot/test-modbus.ps1" ` -ModbusHost $modbus["endpoint"] ` -OpcUaUrl (Get-Or $modbus "opcUaUrl" $OpcUaUrl) ` -BridgeNodeId $modbus["bridgeNodeId"] } } else { $summary["modbus"] = "SKIP (no config entry)" } # --------------------------------------------------------------------------- # AB CIP # --------------------------------------------------------------------------- $abcip = Get-Or $config "abcip" if ($abcip) { Write-Header "== AB CIP ==" Run-Suite "abcip" { & "$PSScriptRoot/test-abcip.ps1" ` -Gateway $abcip["gateway"] ` -Family (Get-Or $abcip "family" "ControlLogix") ` -TagPath (Get-Or $abcip "tagPath" "TestDINT") ` -OpcUaUrl (Get-Or $abcip "opcUaUrl" $OpcUaUrl) ` -BridgeNodeId $abcip["bridgeNodeId"] } } else { $summary["abcip"] = "SKIP (no config entry)" } # --------------------------------------------------------------------------- # AB Legacy # --------------------------------------------------------------------------- $ablegacy = Get-Or $config "ablegacy" if ($ablegacy) { Write-Header "== AB LEGACY ==" Run-Suite "ablegacy" { & "$PSScriptRoot/test-ablegacy.ps1" ` -Gateway $ablegacy["gateway"] ` -PlcType (Get-Or $ablegacy "plcType" "Slc500") ` -Address (Get-Or $ablegacy "address" "N7:5") ` -OpcUaUrl (Get-Or $ablegacy "opcUaUrl" $OpcUaUrl) ` -BridgeNodeId $ablegacy["bridgeNodeId"] } } else { $summary["ablegacy"] = "SKIP (no config entry)" } # --------------------------------------------------------------------------- # S7 # --------------------------------------------------------------------------- $s7 = Get-Or $config "s7" if ($s7) { Write-Header "== S7 ==" Run-Suite "s7" { & "$PSScriptRoot/test-s7.ps1" ` -S7Host $s7["endpoint"] ` -Cpu (Get-Or $s7 "cpu" "S71500") ` -Slot (Get-Or $s7 "slot" 0) ` -Address (Get-Or $s7 "address" "DB1.DBW0") ` -OpcUaUrl (Get-Or $s7 "opcUaUrl" $OpcUaUrl) ` -BridgeNodeId $s7["bridgeNodeId"] } } else { $summary["s7"] = "SKIP (no config entry)" } # --------------------------------------------------------------------------- # FOCAS # --------------------------------------------------------------------------- $focas = Get-Or $config "focas" if ($focas) { Write-Header "== FOCAS ==" Run-Suite "focas" { & "$PSScriptRoot/test-focas.ps1" ` -CncHost $focas["host"] ` -CncPort (Get-Or $focas "port" 8193) ` -Address (Get-Or $focas "address" "R100") ` -OpcUaUrl (Get-Or $focas "opcUaUrl" $OpcUaUrl) ` -BridgeNodeId $focas["bridgeNodeId"] } } else { $summary["focas"] = "SKIP (no config entry)" } # --------------------------------------------------------------------------- # TwinCAT # --------------------------------------------------------------------------- $twincat = Get-Or $config "twincat" if ($twincat) { Write-Header "== TWINCAT ==" Run-Suite "twincat" { & "$PSScriptRoot/test-twincat.ps1" ` -AmsNetId $twincat["amsNetId"] ` -AmsPort (Get-Or $twincat "amsPort" 851) ` -SymbolPath (Get-Or $twincat "symbolPath" "MAIN.iCounter") ` -OpcUaUrl (Get-Or $twincat "opcUaUrl" $OpcUaUrl) ` -BridgeNodeId $twincat["bridgeNodeId"] } } else { $summary["twincat"] = "SKIP (no config entry)" } # --------------------------------------------------------------------------- # Phase 7 virtual tags + scripted alarms # --------------------------------------------------------------------------- $phase7 = Get-Or $config "phase7" if ($phase7) { Write-Header "== PHASE 7 virtual tags + scripted alarms ==" Run-Suite "phase7" { $defaultModbus = if ($modbus) { $modbus["endpoint"] } else { $null } & "$PSScriptRoot/test-phase7-virtualtags.ps1" ` -ModbusHost (Get-Or $phase7 "modbusEndpoint" $defaultModbus) ` -OpcUaUrl (Get-Or $phase7 "opcUaUrl" $OpcUaUrl) ` -InputNodeId $phase7["inputNodeId"] ` -VirtualNodeId $phase7["virtualNodeId"] ` -AlarmNodeId (Get-Or $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