diff options
| author | Stefan Boberg <[email protected]> | 2026-03-21 21:43:22 +0100 |
|---|---|---|
| committer | GitHub Enterprise <[email protected]> | 2026-03-21 21:43:22 +0100 |
| commit | 14ca5b35d0fc477ba30f10b80f937b523fd7e930 (patch) | |
| tree | 8aab2acfec8be1af4bf0dffdb4badc3b64bf8385 /scripts/test_scripts | |
| parent | fix null stats provider crash when build store is not configured (#875) (diff) | |
| download | zen-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_scripts')
| -rwxr-xr-x | scripts/test_scripts/block-clone-test-mac.sh | 43 | ||||
| -rw-r--r-- | scripts/test_scripts/block-clone-test-windows.ps1 | 145 | ||||
| -rwxr-xr-x | scripts/test_scripts/block-clone-test.sh | 143 |
3 files changed, 0 insertions, 331 deletions
diff --git a/scripts/test_scripts/block-clone-test-mac.sh b/scripts/test_scripts/block-clone-test-mac.sh deleted file mode 100755 index a3d3ca4d3..000000000 --- a/scripts/test_scripts/block-clone-test-mac.sh +++ /dev/null @@ -1,43 +0,0 @@ -#!/usr/bin/env bash -# Test block-clone functionality on macOS (APFS). -# -# APFS is the default filesystem on modern Macs and natively supports -# clonefile(), so no special setup is needed — just run the tests. -# -# Usage: -# ./scripts/test_scripts/block-clone-test-mac.sh [path-to-zencore-test] -# -# If no path is given, defaults to build/macosx/<arch>/debug/zencore-test -# relative to the repository root. - -set -euo pipefail - -SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" -REPO_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)" - -ARCH="$(uname -m)" -TEST_BINARY="${1:-$REPO_ROOT/build/macosx/$ARCH/debug/zencore-test}" - -if [ ! -x "$TEST_BINARY" ]; then - echo "error: test binary not found or not executable: $TEST_BINARY" >&2 - echo "hint: build with 'xmake config -m debug && xmake build zencore-test'" >&2 - exit 1 -fi - -# Verify we're on APFS -BINARY_DIR="$(dirname "$TEST_BINARY")" -FS_TYPE="$(diskutil info "$(df "$BINARY_DIR" | tail -1 | awk '{print $1}')" 2>/dev/null | grep "Type (Bundle)" | awk '{print $NF}' || true)" - -if [ "$FS_TYPE" != "apfs" ]; then - echo "warning: filesystem does not appear to be APFS (got: ${FS_TYPE:-unknown}), clone tests may skip" >&2 -fi - -TEST_CASES="TryCloneFile,CopyFile.Clone,SupportsBlockRefCounting,CloneQueryInterface" - -echo "Running block-clone tests ..." -echo "---" -"$TEST_BINARY" \ - --test-suite="core.filesystem" \ - --test-case="$TEST_CASES" -echo "---" -echo "All block-clone tests passed." diff --git a/scripts/test_scripts/block-clone-test-windows.ps1 b/scripts/test_scripts/block-clone-test-windows.ps1 deleted file mode 100644 index df24831a4..000000000 --- a/scripts/test_scripts/block-clone-test-windows.ps1 +++ /dev/null @@ -1,145 +0,0 @@ -# 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_scripts\block-clone-test-windows.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." diff --git a/scripts/test_scripts/block-clone-test.sh b/scripts/test_scripts/block-clone-test.sh deleted file mode 100755 index 7c6bf5605..000000000 --- a/scripts/test_scripts/block-clone-test.sh +++ /dev/null @@ -1,143 +0,0 @@ -#!/usr/bin/env bash -# Test block-clone functionality on temporary Btrfs and XFS loopback filesystems. -# -# Requires: root/sudo, btrfs-progs (mkfs.btrfs), xfsprogs (mkfs.xfs) -# -# Usage: -# sudo ./scripts/test_scripts/block-clone-test.sh [path-to-zencore-test] -# -# If no path is given, defaults to build/linux/x86_64/debug/zencore-test -# relative to the repository root. -# -# Options: -# --btrfs-only Only test Btrfs -# --xfs-only Only test XFS - -set -euo pipefail - -SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" -REPO_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)" - -TEST_BINARY="" -RUN_BTRFS=true -RUN_XFS=true - -for arg in "$@"; do - case "$arg" in - --btrfs-only) RUN_XFS=false ;; - --xfs-only) RUN_BTRFS=false ;; - *) TEST_BINARY="$arg" ;; - esac -done - -TEST_BINARY="${TEST_BINARY:-$REPO_ROOT/build/linux/x86_64/debug/zencore-test}" -IMAGE_SIZE="512M" -TEST_CASES="TryCloneFile,CopyFile.Clone,SupportsBlockRefCounting,CloneQueryInterface" - -# Track all temp files for cleanup -CLEANUP_MOUNTS=() -CLEANUP_DIRS=() -CLEANUP_FILES=() - -cleanup() { - local exit_code=$? - set +e - - for mnt in "${CLEANUP_MOUNTS[@]}"; do - if mountpoint -q "$mnt" 2>/dev/null; then - umount "$mnt" - fi - done - for dir in "${CLEANUP_DIRS[@]}"; do - [ -d "$dir" ] && rmdir "$dir" - done - for f in "${CLEANUP_FILES[@]}"; do - [ -f "$f" ] && rm -f "$f" - done - - if [ $exit_code -ne 0 ]; then - echo "FAILED (exit code $exit_code)" - fi - exit $exit_code -} -trap cleanup EXIT - -# --- Preflight checks --- - -if [ "$(id -u)" -ne 0 ]; then - echo "error: this script must be run as root (for mount/umount)" >&2 - exit 1 -fi - -if [ ! -x "$TEST_BINARY" ]; then - echo "error: test binary not found or not executable: $TEST_BINARY" >&2 - echo "hint: build with 'xmake config -m debug && xmake build zencore-test'" >&2 - exit 1 -fi - -if $RUN_BTRFS && ! command -v mkfs.btrfs &>/dev/null; then - echo "warning: mkfs.btrfs not found — install btrfs-progs to test Btrfs, skipping" >&2 - RUN_BTRFS=false -fi - -if $RUN_XFS && ! command -v mkfs.xfs &>/dev/null; then - echo "warning: mkfs.xfs not found — install xfsprogs to test XFS, skipping" >&2 - RUN_XFS=false -fi - -if ! $RUN_BTRFS && ! $RUN_XFS; then - echo "error: no filesystems to test" >&2 - exit 1 -fi - -# --- Helper to create, mount, and run tests on a loopback filesystem --- - -run_tests_on_fs() { - local fs_type="$1" - local mkfs_cmd="$2" - - echo "" - echo "========================================" - echo " Testing block-clone on $fs_type" - echo "========================================" - - local image_path mount_path - image_path="$(mktemp "/tmp/${fs_type}-clone-test-XXXXXX.img")" - mount_path="$(mktemp -d "/tmp/${fs_type}-clone-mount-XXXXXX")" - CLEANUP_FILES+=("$image_path") - CLEANUP_DIRS+=("$mount_path") - CLEANUP_MOUNTS+=("$mount_path") - - echo "Creating ${IMAGE_SIZE} ${fs_type} image at ${image_path} ..." - truncate -s "$IMAGE_SIZE" "$image_path" - $mkfs_cmd "$image_path" - - echo "Mounting at ${mount_path} ..." - mount -o loop "$image_path" "$mount_path" - chmod 777 "$mount_path" - - echo "Copying test binary ..." - cp "$TEST_BINARY" "$mount_path/zencore-test" - chmod +x "$mount_path/zencore-test" - - echo "Running tests ..." - echo "---" - "$mount_path/zencore-test" \ - --test-suite="core.filesystem" \ - --test-case="$TEST_CASES" - echo "---" - echo "$fs_type: all block-clone tests passed." -} - -# --- Run --- - -if $RUN_BTRFS; then - run_tests_on_fs "btrfs" "mkfs.btrfs -q" -fi - -if $RUN_XFS; then - run_tests_on_fs "xfs" "mkfs.xfs -q -m reflink=1" -fi - -echo "" -echo "All block-clone tests passed." |