aboutsummaryrefslogtreecommitdiff
path: root/scripts/test_windows/block-clone-test.ps1
diff options
context:
space:
mode:
authorStefan Boberg <[email protected]>2026-03-21 21:43:22 +0100
committerGitHub Enterprise <[email protected]>2026-03-21 21:43:22 +0100
commit14ca5b35d0fc477ba30f10b80f937b523fd7e930 (patch)
tree8aab2acfec8be1af4bf0dffdb4badc3b64bf8385 /scripts/test_windows/block-clone-test.ps1
parentfix null stats provider crash when build store is not configured (#875) (diff)
downloadzen-14ca5b35d0fc477ba30f10b80f937b523fd7e930.tar.xz
zen-14ca5b35d0fc477ba30f10b80f937b523fd7e930.zip
Interprocess pipe support (for stdout/stderr capture) (#866)
- **RAII pipe handles for child process stdout/stderr capture**: `StdoutPipeHandles` is now a proper RAII type with automatic cleanup, move semantics, and partial close support. This makes it safe to use pipes for capturing child process output without risking handle/fd leaks. - **Optional separate stderr pipe**: `CreateProcOptions` now accepts a `StderrPipe` field so callers can capture stdout and stderr independently. When null (default), stderr shares the stdout pipe as before. - **LogStreamListener with pluggable handler**: The TCP log stream listener accepts connections from remote processes and delivers parsed log lines through a `LogStreamHandler` interface, set dynamically via `SetHandler()`. This allows any client to receive log messages without depending on a specific console implementation. - **TcpLogStreamSink for zen::logging**: A logging sink that forwards log messages to a `LogStreamListener` over TCP, using the native `zen::logging::Sink` infrastructure with proper thread-safe synchronization. - **Reliable child process exit codes on Linux**: `waitpid` result handling is fixed so `ProcessHandle::GetExitCode()` returns the real exit code. `ProcessHandle::Reset()` reaps zombies directly, replacing the global `IgnoreChildSignals()` which prevented exit code collection entirely. Also fixes a TOCTOU race in `ProcessHandle::Wait()` on Linux/Mac. - **Pipe capture test suite**: Tests covering stdout/stderr capture via pipes (both shared and separate modes), RAII cleanup, move semantics, and exit code propagation using `zentest-appstub` as the child process. - **Service command integration tests**: Shell-based integration tests for `zen service` covering the full lifecycle (install, status, start, stop, uninstall) on all three platforms — Linux (systemd), macOS (launchd), and Windows (SCM via PowerShell). - **Test script reorganization**: Platform-specific test scripts moved from `scripts/test_scripts/` into `scripts/test_linux/`, `test_mac/`, and `test_windows/`.
Diffstat (limited to 'scripts/test_windows/block-clone-test.ps1')
-rw-r--r--scripts/test_windows/block-clone-test.ps1145
1 files changed, 145 insertions, 0 deletions
diff --git a/scripts/test_windows/block-clone-test.ps1 b/scripts/test_windows/block-clone-test.ps1
new file mode 100644
index 000000000..aa6ec3a39
--- /dev/null
+++ b/scripts/test_windows/block-clone-test.ps1
@@ -0,0 +1,145 @@
+# Test block-clone functionality on a temporary ReFS VHD.
+#
+# Requires:
+# - Administrator privileges
+# - Windows Server, or Windows 10/11 Pro for Workstations (ReFS support)
+# - Hyper-V PowerShell module (for New-VHD), or diskpart fallback
+#
+# Usage:
+# # From an elevated PowerShell prompt:
+# .\scripts\test_windows\block-clone-test.ps1 [-TestBinary <path>]
+#
+# If -TestBinary is not given, defaults to build\windows\x64\debug\zencore-test.exe
+# relative to the repository root.
+
+param(
+ [string]$TestBinary = ""
+)
+
+$ErrorActionPreference = "Stop"
+
+$ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Definition
+$RepoRoot = (Resolve-Path "$ScriptDir\..\..").Path
+
+if (-not $TestBinary) {
+ $TestBinary = Join-Path $RepoRoot "build\windows\x64\debug\zencore-test.exe"
+}
+
+$ImageSizeMB = 2048
+$TestCases = "TryCloneFile,CopyFile.Clone,SupportsBlockRefCounting,CloneQueryInterface"
+
+$VhdPath = ""
+$MountLetter = ""
+
+function Cleanup {
+ $ErrorActionPreference = "SilentlyContinue"
+
+ if ($MountLetter) {
+ Write-Host "Dismounting VHD ..."
+ Dismount-VHD -Path $VhdPath -ErrorAction SilentlyContinue
+ }
+ if ($VhdPath -and (Test-Path $VhdPath)) {
+ Remove-Item -Force $VhdPath -ErrorAction SilentlyContinue
+ }
+}
+
+trap {
+ Cleanup
+ throw $_
+}
+
+# --- Preflight checks ---
+
+$IsAdmin = ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole(
+ [Security.Principal.WindowsBuiltInRole]::Administrator)
+if (-not $IsAdmin) {
+ Write-Error "This script must be run as Administrator (for VHD mount/format)."
+ exit 1
+}
+
+if (-not (Test-Path $TestBinary)) {
+ Write-Error "Test binary not found: $TestBinary`nHint: build with 'xmake config -m debug && xmake build zencore-test'"
+ exit 1
+}
+
+# Check that ReFS formatting is available
+$RefsAvailable = $true
+try {
+ # A quick check: on non-Server/Workstation SKUs, Format-Volume -FileSystem ReFS will fail
+ $OsCaption = (Get-CimInstance Win32_OperatingSystem).Caption
+ if ($OsCaption -notmatch "Server|Workstation|Enterprise") {
+ Write-Warning "ReFS may not be available on this Windows edition: $OsCaption"
+ Write-Warning "Continuing anyway — format step will fail if unsupported."
+ }
+} catch {
+ # Non-fatal, just proceed
+}
+
+# --- Create and mount ReFS VHD ---
+
+$VhdPath = Join-Path $env:TEMP "refs-clone-test-$([guid]::NewGuid().ToString('N').Substring(0,8)).vhdx"
+
+Write-Host "Creating ${ImageSizeMB}MB VHDX at $VhdPath ..."
+
+try {
+ # Prefer Hyper-V cmdlet if available
+ New-VHD -Path $VhdPath -SizeBytes ($ImageSizeMB * 1MB) -Fixed | Out-Null
+} catch {
+ # Fallback to diskpart
+ Write-Host "New-VHD not available, falling back to diskpart ..."
+ $DiskpartScript = @"
+create vdisk file="$VhdPath" maximum=$ImageSizeMB type=fixed
+"@
+ $DiskpartScript | diskpart | Out-Null
+}
+
+Write-Host "Mounting and initializing VHD ..."
+
+Mount-VHD -Path $VhdPath
+$Disk = Get-VHD -Path $VhdPath | Get-Disk
+
+# Suppress Explorer's auto-open / "format disk?" prompts for the raw partition
+Stop-Service ShellHWDetection -ErrorAction SilentlyContinue
+
+try {
+ Initialize-Disk -Number $Disk.Number -PartitionStyle GPT -ErrorAction SilentlyContinue
+ $Partition = New-Partition -DiskNumber $Disk.Number -UseMaximumSize -AssignDriveLetter
+ $MountLetter = $Partition.DriveLetter
+
+ Write-Host "Formatting ${MountLetter}: as ReFS with integrity disabled ..."
+ Format-Volume -DriveLetter $MountLetter -FileSystem ReFS -NewFileSystemLabel "CloneTest" -Confirm:$false | Out-Null
+
+ # Disable integrity streams (required for block cloning to work on ReFS)
+ Set-FileIntegrity "${MountLetter}:\" -Enable $false -ErrorAction SilentlyContinue
+} finally {
+ Start-Service ShellHWDetection -ErrorAction SilentlyContinue
+}
+
+$MountRoot = "${MountLetter}:\"
+
+# --- Copy test binary and run ---
+
+Write-Host "Copying test binary to ReFS volume ..."
+Copy-Item $TestBinary "$MountRoot\zencore-test.exe"
+
+Write-Host "Running block-clone tests ..."
+Write-Host "---"
+
+$proc = Start-Process -FilePath "$MountRoot\zencore-test.exe" `
+ -ArgumentList "--test-suite=core.filesystem", "--test-case=$TestCases" `
+ -NoNewWindow -Wait -PassThru
+
+Write-Host "---"
+
+if ($proc.ExitCode -ne 0) {
+ Write-Error "Tests failed with exit code $($proc.ExitCode)"
+ Cleanup
+ exit $proc.ExitCode
+}
+
+Write-Host "ReFS: all block-clone tests passed."
+
+# --- Cleanup ---
+
+Cleanup
+Write-Host "Done."