aboutsummaryrefslogtreecommitdiff
path: root/scripts/test_windows/service-test.ps1
diff options
context:
space:
mode:
Diffstat (limited to 'scripts/test_windows/service-test.ps1')
-rw-r--r--scripts/test_windows/service-test.ps1355
1 files changed, 355 insertions, 0 deletions
diff --git a/scripts/test_windows/service-test.ps1 b/scripts/test_windows/service-test.ps1
new file mode 100644
index 000000000..a2723681e
--- /dev/null
+++ b/scripts/test_windows/service-test.ps1
@@ -0,0 +1,355 @@
+# Test zen service command lifecycle on Windows (SCM).
+#
+# Requires: Administrator privileges
+#
+# Usage:
+# # From an elevated PowerShell prompt:
+# .\scripts\test_windows\service-test.ps1 [-ZenBinary <path>]
+#
+# If -ZenBinary is not given, defaults to build\windows\x64\debug\zen.exe
+# relative to the repository root.
+
+param(
+ [string]$ZenBinary
+)
+
+$ErrorActionPreference = "Stop"
+
+$ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
+$RepoRoot = (Resolve-Path "$ScriptDir\..\..").Path
+
+if (-not $ZenBinary) {
+ $ZenBinary = Join-Path $RepoRoot "build\windows\x64\debug\zen.exe"
+}
+$ZenServerBinary = Join-Path (Split-Path -Parent $ZenBinary) "zenserver.exe"
+
+function Zen { & $ZenBinary --enable-execution-history=false @args }
+$ServiceName = "ZenServerTest-$PID"
+
+$Script:Passed = 0
+$Script:Failed = 0
+$Script:TestsRun = 0
+
+function Pass($Message) {
+ $Script:TestsRun++
+ $Script:Passed++
+ Write-Host " PASS: $Message" -ForegroundColor Green
+}
+
+function Fail($Message, $Detail) {
+ $Script:TestsRun++
+ $Script:Failed++
+ Write-Host " FAIL: $Message" -ForegroundColor Red
+ if ($Detail) {
+ Write-Host " $Detail"
+ }
+}
+
+function Cleanup {
+ Write-Host ""
+ Write-Host "--- Cleanup ---"
+
+ # Stop the service if running
+ $svc = Get-Service -Name $ServiceName -ErrorAction SilentlyContinue
+ if ($svc -and $svc.Status -eq "Running") {
+ Write-Host "Stopping test service..."
+ Stop-Service -Name $ServiceName -Force -ErrorAction SilentlyContinue
+ Start-Sleep -Seconds 2
+ }
+
+ # Delete the service if it exists
+ if (Get-Service -Name $ServiceName -ErrorAction SilentlyContinue) {
+ Write-Host "Removing test service..."
+ sc.exe delete $ServiceName 2>$null | Out-Null
+ }
+
+ Write-Host ""
+ Write-Host "=============================="
+ Write-Host " Tests run: $Script:TestsRun"
+ Write-Host " Passed: $Script:Passed" -ForegroundColor Green
+ if ($Script:Failed -gt 0) {
+ Write-Host " Failed: $Script:Failed" -ForegroundColor Red
+ } else {
+ Write-Host " Failed: $Script:Failed"
+ }
+ Write-Host "=============================="
+}
+
+# ── Preflight checks ──────────────────────────────────────────────
+
+$IsAdmin = ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole(
+ [Security.Principal.WindowsBuiltInRole]::Administrator)
+
+if (-not $IsAdmin) {
+ Write-Host "Error: this test must be run from an elevated (Administrator) prompt." -ForegroundColor Red
+ exit 1
+}
+
+if (-not (Test-Path $ZenBinary)) {
+ Write-Host "Error: zen binary not found at '$ZenBinary'" -ForegroundColor Red
+ Write-Host "Build with: xmake config -m debug && xmake build zen"
+ exit 1
+}
+
+if (-not (Test-Path $ZenServerBinary)) {
+ Write-Host "Error: zenserver binary not found at '$ZenServerBinary'" -ForegroundColor Red
+ Write-Host "Build with: xmake config -m debug && xmake build zenserver"
+ exit 1
+}
+
+Write-Host "zen binary: $ZenBinary"
+Write-Host "zenserver binary: $ZenServerBinary"
+Write-Host "service name: $ServiceName"
+Write-Host ""
+
+try {
+
+# ── Test: status before install (should fail) ─────────────────────
+
+Write-Host "--- Test: status before install ---"
+
+$Output = Zen service status $ServiceName 2>&1 | Out-String
+if ($Output -match "not installed") {
+ Pass "status reports 'not installed' for non-existent service"
+} else {
+ Fail "status should report 'not installed'" "got: $Output"
+}
+
+# ── Test: install ─────────────────────────────────────────────────
+
+Write-Host "--- Test: install ---"
+
+$Output = Zen service install $ZenServerBinary $ServiceName --allow-elevation 2>&1 | Out-String
+$ExitCode = $LASTEXITCODE
+
+if ($ExitCode -eq 0) {
+ Pass "install exits with code 0"
+} else {
+ Fail "install exits with code 0" "got exit code: $ExitCode, output: $Output"
+}
+
+$svc = Get-Service -Name $ServiceName -ErrorAction SilentlyContinue
+if ($svc) {
+ Pass "service registered in SCM"
+} else {
+ Fail "service registered in SCM"
+}
+
+# Verify service configuration
+if ($svc) {
+ $svcWmi = Get-CimInstance -ClassName Win32_Service -Filter "Name='$ServiceName'" -ErrorAction SilentlyContinue
+ if ($svcWmi -and $svcWmi.PathName -match "zenserver") {
+ Pass "service binary path contains zenserver"
+ } else {
+ Fail "service binary path contains zenserver" "got: $($svcWmi.PathName)"
+ }
+
+ if ($svcWmi -and $svcWmi.StartMode -eq "Auto") {
+ Pass "service is set to auto-start"
+ } else {
+ Fail "service is set to auto-start" "got: $($svcWmi.StartMode)"
+ }
+}
+
+# ── Test: install again (already installed, no --full) ────────────
+
+Write-Host "--- Test: install again (idempotent) ---"
+
+$Output = Zen service install $ZenServerBinary $ServiceName --allow-elevation 2>&1 | Out-String
+$ExitCode = $LASTEXITCODE
+
+if ($ExitCode -eq 0) {
+ Pass "re-install exits with code 0"
+} else {
+ Fail "re-install exits with code 0" "got exit code: $ExitCode"
+}
+
+if ($Output -match "already installed") {
+ Pass "re-install reports service already installed"
+} else {
+ Fail "re-install reports service already installed" "got: $Output"
+}
+
+# ── Test: status after install (not yet started) ──────────────────
+
+Write-Host "--- Test: status after install (stopped) ---"
+
+$Output = Zen service status $ServiceName 2>&1 | Out-String
+if ($Output -match "not running") {
+ Pass "status reports 'not running' for stopped service"
+} else {
+ Fail "status reports 'not running' for stopped service" "got: $Output"
+}
+
+# ── Test: start ───────────────────────────────────────────────────
+
+Write-Host "--- Test: start ---"
+
+$Output = Zen service start $ServiceName --allow-elevation 2>&1 | Out-String
+$ExitCode = $LASTEXITCODE
+
+if ($ExitCode -eq 0) {
+ Pass "start exits with code 0"
+} else {
+ Fail "start exits with code 0" "got exit code: $ExitCode, output: $Output"
+}
+
+Start-Sleep -Seconds 2
+
+$svc = Get-Service -Name $ServiceName -ErrorAction SilentlyContinue
+if ($svc -and $svc.Status -eq "Running") {
+ Pass "service is running after start"
+
+ # ── Test: status while running ────────────────────────────────
+
+ Write-Host "--- Test: status (running) ---"
+
+ $Output = Zen service status $ServiceName 2>&1 | Out-String
+ if ($Output -match "Running") {
+ Pass "status reports 'Running'"
+ } else {
+ Fail "status reports 'Running'" "got: $Output"
+ }
+
+ if ($Output -match "zenserver") {
+ Pass "status shows executable path"
+ } else {
+ Fail "status shows executable path" "got: $Output"
+ }
+
+ # ── Test: start again (already running) ───────────────────────
+
+ Write-Host "--- Test: start again (already running) ---"
+
+ $Output = Zen service start $ServiceName --allow-elevation 2>&1 | Out-String
+ if ($Output -match "already running") {
+ Pass "start reports service already running"
+ } else {
+ Fail "start reports service already running" "got: $Output"
+ }
+
+ # ── Test: stop ────────────────────────────────────────────────
+
+ Write-Host "--- Test: stop ---"
+
+ $Output = Zen service stop $ServiceName --allow-elevation 2>&1 | Out-String
+ $ExitCode = $LASTEXITCODE
+
+ if ($ExitCode -eq 0) {
+ Pass "stop exits with code 0"
+ } else {
+ Fail "stop exits with code 0" "got exit code: $ExitCode, output: $Output"
+ }
+
+ Start-Sleep -Seconds 2
+
+ $svc = Get-Service -Name $ServiceName -ErrorAction SilentlyContinue
+ if ($svc -and $svc.Status -ne "Running") {
+ Pass "service is not running after stop"
+ } else {
+ Fail "service is not running after stop"
+ }
+} else {
+ Fail "service is running after start" "(skipping start-dependent tests)"
+}
+
+# ── Test: stop when already stopped ───────────────────────────────
+
+Write-Host "--- Test: stop when already stopped ---"
+
+Stop-Service -Name $ServiceName -Force -ErrorAction SilentlyContinue
+Start-Sleep -Seconds 1
+
+$Output = Zen service stop $ServiceName --allow-elevation 2>&1 | Out-String
+if ($Output -match "not running") {
+ Pass "stop reports 'not running' when already stopped"
+} else {
+ Fail "stop reports 'not running' when already stopped" "got: $Output"
+}
+
+# ── Test: uninstall while running (should fail) ───────────────────
+
+Write-Host "--- Test: uninstall while running (should fail) ---"
+
+Zen service start $ServiceName --allow-elevation 2>&1 | Out-Null
+Start-Sleep -Seconds 2
+
+$svc = Get-Service -Name $ServiceName -ErrorAction SilentlyContinue
+if ($svc -and $svc.Status -eq "Running") {
+ $Output = Zen service uninstall $ServiceName --allow-elevation 2>&1 | Out-String
+ $ExitCode = $LASTEXITCODE
+
+ if ($ExitCode -ne 0 -or $Output -match "running.*stop") {
+ Pass "uninstall refuses while service is running"
+ } else {
+ Fail "uninstall refuses while service is running" "got: exit=$ExitCode, output: $Output"
+ }
+
+ # Stop it for the real uninstall test
+ Zen service stop $ServiceName --allow-elevation 2>&1 | Out-Null
+ Stop-Service -Name $ServiceName -Force -ErrorAction SilentlyContinue
+ Start-Sleep -Seconds 2
+} else {
+ Write-Host " (skipped: could not start service for this test)"
+}
+
+# ── Test: uninstall ───────────────────────────────────────────────
+
+Write-Host "--- Test: uninstall ---"
+
+Stop-Service -Name $ServiceName -Force -ErrorAction SilentlyContinue
+Start-Sleep -Seconds 1
+
+$Output = Zen service uninstall $ServiceName --allow-elevation 2>&1 | Out-String
+$ExitCode = $LASTEXITCODE
+
+if ($ExitCode -eq 0) {
+ Pass "uninstall exits with code 0"
+} else {
+ Fail "uninstall exits with code 0" "got exit code: $ExitCode, output: $Output"
+}
+
+$svc = Get-Service -Name $ServiceName -ErrorAction SilentlyContinue
+if (-not $svc) {
+ Pass "service removed from SCM after uninstall"
+} else {
+ Fail "service removed from SCM after uninstall"
+}
+
+# ── Test: status after uninstall ──────────────────────────────────
+
+Write-Host "--- Test: status after uninstall ---"
+
+$Output = Zen service status $ServiceName 2>&1 | Out-String
+if ($Output -match "not installed") {
+ Pass "status reports 'not installed' after uninstall"
+} else {
+ Fail "status reports 'not installed' after uninstall" "got: $Output"
+}
+
+# ── Test: uninstall when not installed (idempotent) ───────────────
+
+Write-Host "--- Test: uninstall when not installed ---"
+
+$Output = Zen service uninstall $ServiceName --allow-elevation 2>&1 | Out-String
+$ExitCode = $LASTEXITCODE
+
+if ($ExitCode -eq 0) {
+ Pass "uninstall of non-existent service exits with code 0"
+} else {
+ Fail "uninstall of non-existent service exits with code 0" "got exit code: $ExitCode"
+}
+
+if ($Output -match "not installed") {
+ Pass "uninstall reports service not installed"
+} else {
+ Fail "uninstall reports service not installed" "got: $Output"
+}
+
+} finally {
+ Cleanup
+}
+
+if ($Script:Failed -gt 0) {
+ exit 1
+}