#!/bin/sh
#
# zyginit integration test harness
#
# Black-box tests for zyginit daemon + zygctl CLI.
# Creates temporary service definitions, starts zyginit in non-PID-1 mode,
# exercises zygctl commands, and verifies expected behavior.
#
# Usage: ./tests/integration/run_tests.sh
#
# Requirements:
#   - zyginit built at build/zyginit
#   - zygctl built at tools/zygctl/build/zygctl
#

set -e

# ============================================================================
# Configuration
# ============================================================================

SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
PROJECT_DIR="$(cd "$SCRIPT_DIR/../.." && pwd)"
ZYGINIT="$PROJECT_DIR/build/zyginit"
ZYGCTL="$PROJECT_DIR/tools/zygctl/build/zygctl"

TEST_DIR=$(mktemp -d /tmp/zyginit-test.XXXXXX)
CONFIG_DIR="$TEST_DIR/config"
ENABLED_DIR="$CONFIG_DIR/enabled.d"
BIN_DIR="$TEST_DIR/bin"
SOCKET="$TEST_DIR/zyginit.sock"
DAEMON_LOG="$TEST_DIR/zyginit.log"
DAEMON_PID=""

LOG_DIR="$TEST_DIR/log"
RUN_DIR="$TEST_DIR/run"
export ZYGINIT_CONFIG_DIR="$CONFIG_DIR"
export ZYGINIT_SOCKET="$SOCKET"
export ZYGINIT_LOG_DIR="$LOG_DIR"
export ZYGINIT_RUN_DIR="$RUN_DIR"
# Force the daemon into plain mode regardless of TTY state — keeps
# integration test diffs stable and prevents ANSI escapes from
# polluting captured assertions.
export ZYGINIT_NO_UI=1

PASS=0
FAIL=0
TOTAL=0

# ============================================================================
# Test framework
# ============================================================================

pass() {
    PASS=$((PASS + 1))
    TOTAL=$((TOTAL + 1))
    printf "  PASS: %s\n" "$1"
}

fail() {
    FAIL=$((FAIL + 1))
    TOTAL=$((TOTAL + 1))
    printf "  FAIL: %s\n" "$1"
    if [ -n "$2" ]; then
        printf "        expected: %s\n" "$2"
    fi
    if [ -n "$3" ]; then
        printf "        got:      %s\n" "$3"
    fi
}

section() {
    printf "\n=== %s ===\n" "$1"
}

# Assert output contains a substring
assert_contains() {
    local output="$1"
    local expected="$2"
    local label="$3"
    if echo "$output" | grep -q "$expected"; then
        pass "$label"
    else
        fail "$label" "contains '$expected'" "$output"
    fi
}

# Assert output does NOT contain a substring
assert_not_contains() {
    local output="$1"
    local expected="$2"
    local label="$3"
    if echo "$output" | grep -q "$expected"; then
        fail "$label" "not contains '$expected'" "$output"
    else
        pass "$label"
    fi
}

# Assert exact match (trimmed)
assert_equals() {
    local output="$(echo "$1" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')"
    local expected="$(echo "$2" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')"
    local label="$3"
    if [ "$output" = "$expected" ]; then
        pass "$label"
    else
        fail "$label" "'$expected'" "'$output'"
    fi
}

# Run zygctl and capture output
zygctl() {
    "$ZYGCTL" "$@" 2>&1
}

# ============================================================================
# Service definition helpers
# ============================================================================

create_service() {
    local name="$1"
    local type="$2"
    local cmd="$3"
    local restart="${4:-never}"
    local delay="${5:-1}"
    local max_retries="${6:-3}"

    cat > "$CONFIG_DIR/$name.toml" << TOML
[service]
name = "$name"
description = "Test service: $name"
type = "$type"

[exec]
start = "$cmd"

[restart]
on = "$restart"
delay = $delay
max_retries = $max_retries
TOML
}

create_service_with_workdir() {
    local name="$1"
    local type="$2"
    local cmd="$3"
    local workdir="$4"

    cat > "$CONFIG_DIR/$name.toml" << TOML
[service]
name = "$name"
description = "Test service: $name"
type = "$type"

[exec]
start = "$cmd"
working_directory = "$workdir"

[restart]
on = "never"
TOML
}

create_service_with_env() {
    local name="$1"
    local type="$2"
    local cmd="$3"
    local workdir="$4"
    local env_array="$5"

    cat > "$CONFIG_DIR/$name.toml" << TOML
[service]
name = "$name"
description = "Test service: $name"
type = "$type"

[exec]
start = "$cmd"
working_directory = "$workdir"
environment = $env_array

[restart]
on = "never"
TOML
}

enable_service() {
    ln -sf "../$1.toml" "$ENABLED_DIR/$1"
}

disable_service() {
    rm -f "$ENABLED_DIR/$1"
}

# ============================================================================
# Daemon lifecycle
# ============================================================================

start_daemon() {
    "$ZYGINIT" > "$DAEMON_LOG" 2>&1 &
    DAEMON_PID=$!
    # Wait for socket to appear
    local retries=0
    while [ ! -S "$SOCKET" ] && [ $retries -lt 30 ]; do
        sleep 0.1
        retries=$((retries + 1))
    done
    if [ ! -S "$SOCKET" ]; then
        echo "ERROR: zyginit failed to start (no socket after 3s)"
        cat "$DAEMON_LOG"
        exit 1
    fi
    # Give services a moment to start
    sleep 1
}

stop_daemon() {
    if [ -n "$DAEMON_PID" ]; then
        kill "$DAEMON_PID" 2>/dev/null || true
        # Wait up to 5 seconds for graceful shutdown
        local retries=0
        while kill -0 "$DAEMON_PID" 2>/dev/null && [ $retries -lt 50 ]; do
            sleep 0.1
            retries=$((retries + 1))
        done
        # Force kill if still alive
        kill -9 "$DAEMON_PID" 2>/dev/null || true
        wait "$DAEMON_PID" 2>/dev/null || true
        DAEMON_PID=""
    fi
    # Kill any orphaned test service processes
    pkill -f "sleeper.sh" 2>/dev/null || true
    rm -f "$SOCKET"
}

# ============================================================================
# Cleanup
# ============================================================================

cleanup() {
    stop_daemon
    rm -rf "$TEST_DIR"
}
trap cleanup EXIT

# ============================================================================
# Create test helper scripts
# ============================================================================

mkdir -p "$BIN_DIR" "$RUN_DIR"

# Long-running daemon (sleeps via shell trap loop)
cat > "$BIN_DIR/sleeper.sh" << 'SCRIPT'
#!/bin/sh
trap 'exit 0' TERM INT
while true; do sleep 1; done
SCRIPT
chmod +x "$BIN_DIR/sleeper.sh"

# Successful oneshot
cat > "$BIN_DIR/succeed.sh" << 'SCRIPT'
#!/bin/sh
exit 0
SCRIPT
chmod +x "$BIN_DIR/succeed.sh"

# Failing oneshot/daemon
cat > "$BIN_DIR/fail.sh" << 'SCRIPT'
#!/bin/sh
exit 1
SCRIPT
chmod +x "$BIN_DIR/fail.sh"

# Write current directory to a marker file, then exit
cat > "$BIN_DIR/write_cwd.sh" << 'SCRIPT'
#!/bin/sh
pwd > cwd_marker.txt
exit 0
SCRIPT
chmod +x "$BIN_DIR/write_cwd.sh"

# Write an env var to a marker file, then exit
cat > "$BIN_DIR/write_env.sh" << 'SCRIPT'
#!/bin/sh
echo "$TEST_VAR" > env_marker.txt
exit 0
SCRIPT
chmod +x "$BIN_DIR/write_env.sh"

# Write to stderr and exit with failure (for log capture testing)
cat > "$BIN_DIR/log_fail.sh" << 'SCRIPT'
#!/bin/sh
echo "service starting up" >&1
echo "fatal: something went wrong" >&2
exit 1
SCRIPT
chmod +x "$BIN_DIR/log_fail.sh"

# ============================================================================
# Pre-flight checks
# ============================================================================

if [ ! -x "$ZYGINIT" ]; then
    echo "ERROR: zyginit binary not found at $ZYGINIT"
    echo "Run: reefc build --obj build/contract_stubs.o"
    exit 1
fi

if [ ! -x "$ZYGCTL" ]; then
    echo "ERROR: zygctl binary not found at $ZYGCTL"
    echo "Run: cd tools/zygctl && reefc build --obj build/symlink_wrapper.o"
    exit 1
fi

echo "zyginit integration tests"
echo "  zyginit: $ZYGINIT"
echo "  zygctl:  $ZYGCTL"
echo "  tmpdir:  $TEST_DIR"

# ============================================================================
# Test Suite 1: zygctl local commands (no daemon)
# ============================================================================

section "zygctl local commands"

# Setup config dir
mkdir -p "$CONFIG_DIR" "$ENABLED_DIR"

# Test help
output=$(zygctl help)
assert_contains "$output" "zygctl" "help shows program name"
assert_contains "$output" "enable" "help lists enable command"
assert_contains "$output" "disable" "help lists disable command"
assert_contains "$output" "reload" "help lists reload command"

# Test enable — service does not exist
output=$(zygctl enable nonexistent)
assert_contains "$output" "error" "enable nonexistent shows error"

# Create a service definition and test enable
create_service "sleeper" "daemon" "$BIN_DIR/sleeper.sh"
output=$(zygctl enable sleeper)
assert_contains "$output" "enabled" "enable sleeper succeeds"

# Verify symlink was created
if [ -L "$ENABLED_DIR/sleeper" ]; then
    pass "enable creates symlink"
else
    fail "enable creates symlink" "symlink at $ENABLED_DIR/sleeper" "not found"
fi

# Test enable again (already enabled)
output=$(zygctl enable sleeper)
assert_contains "$output" "already enabled" "enable again shows already enabled"

# Test disable
output=$(zygctl disable sleeper)
assert_contains "$output" "disabled" "disable sleeper succeeds"

# Verify symlink was removed
if [ ! -e "$ENABLED_DIR/sleeper" ]; then
    pass "disable removes symlink"
else
    fail "disable removes symlink" "no file at $ENABLED_DIR/sleeper" "file exists"
fi

# Test disable again (not enabled)
output=$(zygctl disable sleeper)
assert_contains "$output" "not enabled" "disable again shows not enabled"

# Test connect failure (no daemon running)
output=$(zygctl status)
assert_contains "$output" "cannot connect" "status without daemon shows connection error"

# ============================================================================
# Test Suite 2: Basic daemon operation
# ============================================================================

section "Basic daemon operation"

# Clean up and set up fresh
rm -rf "$CONFIG_DIR"
mkdir -p "$CONFIG_DIR" "$ENABLED_DIR"

# Create test services
create_service "sleeper" "daemon" "$BIN_DIR/sleeper.sh"
create_service "greeter" "oneshot" "$BIN_DIR/succeed.sh"
enable_service "sleeper"
enable_service "greeter"

start_daemon

# Test list
output=$(zygctl list)
assert_contains "$output" "sleeper" "list shows sleeper"
assert_contains "$output" "greeter" "list shows greeter"
assert_contains "$output" "daemon" "list shows daemon type"
assert_contains "$output" "oneshot" "list shows oneshot type"

# Test status (all)
output=$(zygctl status)
assert_contains "$output" "sleeper" "status shows sleeper"
assert_contains "$output" "greeter" "status shows greeter"

# Test status of running daemon
output=$(zygctl status sleeper)
assert_contains "$output" "running" "sleeper is running"
assert_contains "$output" "sleeper" "sleeper status row present"

# Test status of completed oneshot
output=$(zygctl status greeter)
assert_contains "$output" "stopped" "greeter (oneshot) is stopped after completion"

# Test help via socket (this goes through socket since daemon is running... actually
# version and help are local in zygctl. Let me test an actual socket help)
# Actually, version/help in zygctl are intercepted locally. Let me test unknown command.
output=$(zygctl unknown_cmd 2>&1)
assert_contains "$output" "error" "unknown command returns error"

# Test stop
output=$(zygctl stop sleeper)
assert_contains "$output" "stopping" "stop sleeper succeeds"
sleep 1

output=$(zygctl status sleeper)
assert_contains "$output" "stopped" "sleeper is stopped after stop"

# Test start
output=$(zygctl start sleeper)
assert_contains "$output" "started" "start sleeper succeeds"
sleep 1

output=$(zygctl status sleeper)
assert_contains "$output" "running" "sleeper is running after start"

# Test restart
output=$(zygctl restart sleeper)
# restart of a running service sends stop first
sleep 2

output=$(zygctl status sleeper)
# It should be running or restarting
assert_contains "$output" "sleeper" "restart: service exists after restart"

# Test status of unknown service
output=$(zygctl status nonexistent)
assert_contains "$output" "error" "status of unknown service shows error"

# Ensure sleeper is running before testing double-start
sleep 1
output=$(zygctl status sleeper)
if echo "$output" | grep -q "running"; then
    output=$(zygctl start sleeper)
    assert_contains "$output" "already running" "start already running shows message"
else
    # Restart may have left it stopped; start it, wait, then try again
    zygctl start sleeper > /dev/null 2>&1
    sleep 1
    output=$(zygctl start sleeper)
    assert_contains "$output" "already running" "start already running shows message"
fi

stop_daemon

# ============================================================================
# Test Suite 3: Restart policies
# ============================================================================

section "Restart policies"

rm -rf "$CONFIG_DIR"
mkdir -p "$CONFIG_DIR" "$ENABLED_DIR"

# Service that exits immediately with failure — restart on failure, max 2 retries
create_service "failer" "daemon" "$BIN_DIR/fail.sh" "failure" 1 2

enable_service "failer"

start_daemon

# Wait for restart attempts to play out (1s delay * 2 retries + startup time)
sleep 5

output=$(zygctl status failer)
assert_contains "$output" "maint." "failer enters maintenance after max retries"
assert_contains "$output" "restarts=" "failer shows restart count"
assert_contains "$output" "exit=" "failer shows exit code"

stop_daemon

# ============================================================================
# Test Suite 4: Enable/disable via socket + reload
# ============================================================================

section "Enable/disable via socket + reload"

rm -rf "$CONFIG_DIR"
mkdir -p "$CONFIG_DIR" "$ENABLED_DIR"

# Start with one service
create_service "alpha" "daemon" "$BIN_DIR/sleeper.sh"
enable_service "alpha"

start_daemon

output=$(zygctl status)
assert_contains "$output" "alpha" "alpha is loaded"

# Create a new service and enable it
create_service "beta" "daemon" "$BIN_DIR/sleeper.sh"

# Enable via socket (server-side)
output=$(zygctl enable beta)
assert_contains "$output" "enabled" "enable beta via socket"

# Reload to pick up the new service
output=$(zygctl reload)
assert_contains "$output" "reload" "reload command accepted"
sleep 2

output=$(zygctl status beta)
assert_contains "$output" "beta" "beta appears after reload"
assert_contains "$output" "running" "beta is running after reload"

# Disable alpha and reload
output=$(zygctl disable alpha)
assert_contains "$output" "disabled" "disable alpha via socket"

output=$(zygctl reload)
sleep 2

output=$(zygctl status alpha)
assert_contains "$output" "disabled" "alpha is disabled after reload"

stop_daemon

# ============================================================================
# Test Suite 5: Oneshot service behavior
# ============================================================================

section "Oneshot services"

rm -rf "$CONFIG_DIR"
mkdir -p "$CONFIG_DIR" "$ENABLED_DIR"

# Successful oneshot
create_service "setup-ok" "oneshot" "$BIN_DIR/succeed.sh"
# Failing oneshot
create_service "setup-fail" "oneshot" "$BIN_DIR/fail.sh"

enable_service "setup-ok"
enable_service "setup-fail"

start_daemon

sleep 2

output=$(zygctl status setup-ok)
assert_contains "$output" "stopped" "successful oneshot shows stopped"

output=$(zygctl status setup-fail)
assert_contains "$output" "failed" "failing oneshot shows failed"
assert_contains "$output" "exit=" "failing oneshot shows exit code"

stop_daemon

# ============================================================================
# Test Suite 6: Working directory
# ============================================================================

section "Working directory"

rm -rf "$CONFIG_DIR"
mkdir -p "$CONFIG_DIR" "$ENABLED_DIR"

# Create a target directory for the service to run in
WORK_DIR="$TEST_DIR/workdir"
mkdir -p "$WORK_DIR"

create_service_with_workdir "cwd-test" "oneshot" "$BIN_DIR/write_cwd.sh" "$WORK_DIR"
enable_service "cwd-test"

start_daemon

sleep 2

# Check that the marker file was written in the working directory
if [ -f "$WORK_DIR/cwd_marker.txt" ]; then
    pass "working_directory: marker file created in workdir"
    marker_content=$(cat "$WORK_DIR/cwd_marker.txt" | tr -d '\n')
    assert_equals "$marker_content" "$WORK_DIR" "working_directory: cwd matches configured path"
else
    fail "working_directory: marker file created in workdir" "file at $WORK_DIR/cwd_marker.txt" "not found"
    fail "working_directory: cwd matches configured path" "$WORK_DIR" "marker file missing"
fi

stop_daemon

# ============================================================================
# Test Suite 7: Environment variables
# ============================================================================

section "Environment variables"

rm -rf "$CONFIG_DIR"
mkdir -p "$CONFIG_DIR" "$ENABLED_DIR"

ENV_DIR="$TEST_DIR/envdir"
mkdir -p "$ENV_DIR"

create_service_with_env "env-test" "oneshot" "$BIN_DIR/write_env.sh" "$ENV_DIR" '["TEST_VAR=hello_zyginit"]'
enable_service "env-test"

start_daemon

sleep 2

if [ -f "$ENV_DIR/env_marker.txt" ]; then
    pass "environment: marker file created"
    marker_content=$(cat "$ENV_DIR/env_marker.txt" | tr -d '\n')
    assert_equals "$marker_content" "hello_zyginit" "environment: env var passed to service"
else
    fail "environment: marker file created" "file at $ENV_DIR/env_marker.txt" "not found"
    fail "environment: env var passed to service" "hello_zyginit" "marker file missing"
fi

stop_daemon

# ============================================================================
# Test Suite 8: Privilege separation (error path)
# ============================================================================

section "Privilege separation"

rm -rf "$CONFIG_DIR"
mkdir -p "$CONFIG_DIR" "$ENABLED_DIR"

# Service with nonexistent user — should fail with exit 126
cat > "$CONFIG_DIR/baduser.toml" << TOML
[service]
name = "baduser"
description = "Test bad user"
type = "oneshot"

[exec]
start = "$BIN_DIR/succeed.sh"
user = "nonexistent_user_zyginit_test"

[restart]
on = "never"
TOML
enable_service "baduser"

start_daemon

sleep 2

output=$(zygctl status baduser)
assert_contains "$output" "failed" "privilege: bad user causes failure"
assert_contains "$output" "exit=" "privilege: exit code shown"

stop_daemon

# ============================================================================
# Test Suite 9: Service output capture + zygctl log
# ============================================================================

section "Service output capture"

rm -rf "$CONFIG_DIR" "$LOG_DIR"
mkdir -p "$CONFIG_DIR" "$ENABLED_DIR"

create_service "log-test" "oneshot" "$BIN_DIR/log_fail.sh"
enable_service "log-test"

start_daemon

sleep 2

# Check that log file was created
if [ -f "$LOG_DIR/log-test.log" ]; then
    pass "log: per-service log file created"
else
    fail "log: per-service log file created" "file at $LOG_DIR/log-test.log" "not found"
fi

# Check log file contains expected output
log_content=$(cat "$LOG_DIR/log-test.log" 2>/dev/null)
assert_contains "$log_content" "something went wrong" "log: stderr captured in log file"
assert_contains "$log_content" "starting up" "log: stdout captured in log file"

# Check zygctl log command
output=$(zygctl log log-test)
assert_contains "$output" "something went wrong" "log: zygctl log shows stderr"
assert_contains "$output" "starting up" "log: zygctl log shows stdout"

# Check zygctl log for unknown service
output=$(zygctl log nonexistent)
assert_contains "$output" "error" "log: unknown service shows error"

# Check zygctl log for service with no log
output=$(zygctl log setup-fail 2>&1)
# setup-fail doesn't exist in this test run, so it'll be unknown
assert_contains "$output" "error" "log: missing service shows error"

stop_daemon

# ============================================================================
# Test Suite 10: zygctl replace — command parsing and state-file write
# ============================================================================

section "zygctl replace — command parsing and state-file write"

rm -rf "$CONFIG_DIR"
mkdir -p "$CONFIG_DIR" "$ENABLED_DIR"

# Create a minimal service
create_service "sleeper" "daemon" "$BIN_DIR/sleeper.sh"
enable_service "sleeper"

start_daemon

# Test 1: zygctl replace with no args
out=$("$ZYGCTL" replace 2>&1 || true)
assert_contains "$out" "replace queued" "replace acks with no args"
assert_contains "$out" "wait=0" "replace acks with default wait=0"

# Wait briefly to let the daemon process the flag (it will attempt exec
# of /sbin/init, which fails on Linux because that's systemd, not us;
# zyginit logs FATAL: execve returned and continues running.)
sleep 1.5

# Verify state.toml was written before the exec attempt
if [ -f "$RUN_DIR/state.toml" ]; then
    pass "state.toml written by replace flow"
    out=$(cat "$RUN_DIR/state.toml")
    assert_contains "$out" "boot_time =" "state.toml has boot_time line"
else
    fail "state.toml written by replace flow" "file present at $RUN_DIR/state.toml" "missing"
fi

# Verify the daemon log shows the outgoing flow
log_out=$(cat "$DAEMON_LOG")
assert_contains "$log_out" "replace: requested" "daemon logged replace request"
assert_contains "$log_out" "replace: state written" "daemon logged state write"
assert_contains "$log_out" "replace: execve" "daemon logged execve attempt"

# Stop daemon (it survived the failed execve and is still running)
stop_daemon
# Clean up the leftover state.toml so the next test starts fresh
rm -f "$RUN_DIR/state.toml"

# Test 2: zygctl replace --wait=N
start_daemon
out=$("$ZYGCTL" replace --wait=10 2>&1 || true)
assert_contains "$out" "replace queued" "replace --wait=10 acks"
assert_contains "$out" "wait=10" "replace --wait=10 reflects wait value"
sleep 1.5
stop_daemon
rm -f "$RUN_DIR/state.toml"

# Test 3: zygctl replace --bogus
start_daemon
out=$("$ZYGCTL" replace --bogus 2>&1 || true)
assert_contains "$out" "error" "replace --bogus returns error"
assert_contains "$out" "unknown argument" "replace --bogus error mentions unknown argument"
stop_daemon

# ============================================================================
# Test Suite 11: TTY-aware dispatch — plain output when piped
# ============================================================================

section "TTY-aware dispatch"

rm -rf "$CONFIG_DIR"
mkdir -p "$CONFIG_DIR" "$ENABLED_DIR"

create_service "sleeper" "daemon" "$BIN_DIR/sleeper.sh"
enable_service "sleeper"

start_daemon

# zygctl status is piped here (stdout is not a TTY), so client_should_be_plain()
# returns true and the client sends "status plain". Output must contain no ANSI
# escape sequences.
out=$(zygctl status)
if printf '%s' "$out" | grep -qP '\x1b'; then
    fail "zygctl status returns no ANSI escapes when piped" "no ESC bytes" "ESC found"
else
    pass "zygctl status returns no ANSI escapes when piped"
fi

# Same check for list
out=$(zygctl list)
if printf '%s' "$out" | grep -qP '\x1b'; then
    fail "zygctl list returns no ANSI escapes when piped" "no ESC bytes" "ESC found"
else
    pass "zygctl list returns no ANSI escapes when piped"
fi

stop_daemon

# ============================================================================
# Shutdown orchestration tests (standalone script)
# ============================================================================

section "Shutdown orchestration"

if bash "$SCRIPT_DIR/test_shutdown.sh" >> "$TEST_DIR/shutdown.log" 2>&1; then
    pass "oneshot stop command runs at shutdown"
else
    fail "oneshot stop command runs at shutdown" "PASS" "FAIL — see $TEST_DIR/shutdown.log"
fi

# ============================================================================
# Version reporting
# ============================================================================

section "Version reporting"

# Both binaries should respond to --version (and `version` subcommand for zygctl)
# with a single line "<binary> <version>" matching reef.toml.

EXPECTED_VERSION=$(grep '^version' "$PROJECT_DIR/reef.toml" | head -1 | sed 's/.*"\([^"]*\)".*/\1/')

OUT="$("$ZYGINIT" --version 2>&1)"
assert_equals "$OUT" "zyginit $EXPECTED_VERSION" "zyginit --version output"

OUT="$(zygctl --version)"
assert_equals "$OUT" "zygctl $EXPECTED_VERSION" "zygctl --version output"

OUT="$(zygctl version)"
assert_equals "$OUT" "zygctl $EXPECTED_VERSION" "zygctl version subcommand output"

# ============================================================================
# Results
# ============================================================================

echo ""
echo "========================================"
echo "Results: $PASS passed, $FAIL failed (of $TOTAL)"
echo "========================================"

if [ $FAIL -gt 0 ]; then
    exit 1
fi

exit 0
