#!/usr/bin/env bash
# ============================================================================
# Platform-category invariant test — TEMPLATE.
#
# These tests verify post-install invariants on the REAL host they run
# on, NOT a fixture tree. They typically run inside
# `os platform.test <platform> terminal` after `ossh install …` has
# completed, or directly on a deployed machine to verify it's healthy.
#
# Naming convention: `test.platform.<scope>.<aspect>.invariant`
#   e.g. test.platform.shared.config.invariant
#        test.platform.shared.oosh.invariant
#
# Invoke: ./test.suite run platform.<scope>.<aspect>.invariant 1
# (Note: not auto-included in `./test.suite core 1` — TEST_CATEGORY=platform
#  segregates these from fixture tests so a missing real-world precondition
#  doesn't fail a clean dev-host unit-test run.)
#
# Pattern conformance:
#   - Use `expect.pass <msg>` / `expect.fail <reason + recovery>` (NOT
#     `expect 0 "*"`) so the failure message surfaces a copy-paste-ready
#     recovery command — see `docs/test-suite.md` § Diagnostic-rich
#     assertions and memory [[feedback-real-env-tests-when-fixtures-miss]].
#   - Use `private.this.path.canonical` (from `this`) for cross-platform
#     symlink resolution — GNU `readlink -f` is missing on BSD/macOS.
#   - Use `case "$path" in */shared/…/Once.sh/*)` instead of hardcoded
#     paths so the test runs on both Linux (`/home/shared`) and macOS
#     (`/Users/Shared`).
#   - Bail out cleanly when a precondition is unmet (e.g. `~/oosh` not a
#     symlink → the next assertion can't run meaningfully). Use
#     `test.suite.save.results` + `return 0 2>/dev/null || exit 0`.
#
# REPLACE the four `INVARIANT-<n>` blocks below with the assertions
# specific to the invariant you're verifying. Delete the comment header
# above (this block) once you've adapted it.
# ============================================================================

TEST_CATEGORY=platform

level=$1
if [ -z "$level" ]; then
  level=1
else
  shift
fi
echo "starting: ${BASH_SOURCE[@]##*/} <LOG_LEVEL=$level>"

source this
source test.suite

log.level $level

# ----------------------------------------------------------------------------
# INVARIANT-0 (precondition): the artefact we're about to inspect must exist.
# Bail out cleanly if not — the rest of the assertions assume it does.
# ----------------------------------------------------------------------------
artefact="$HOME/oosh"   # ← adjust: this is the thing you're checking

test.case $level "platform.<scope>.<aspect>: precondition — $artefact exists" \
  test -e "$artefact"
if [ ! -e "$artefact" ]; then
  expect.fail "$artefact does not exist — run \`ossh install <host>\` first"
  test.suite.save.results
  return 0 2>/dev/null || exit 0
else
  expect.pass "$artefact present"
fi

# ----------------------------------------------------------------------------
# INVARIANT-1: structural shape (symlink / dir / file / mode / owner).
# Recovery hint should be a single concrete command the user can paste.
# ----------------------------------------------------------------------------
test.case $level "platform.<scope>.<aspect>: $artefact is a symlink" \
  test -L "$artefact"
if [ -L "$artefact" ]; then
  expect.pass "$artefact is a symlink"
else
  expect.fail "$artefact is not a symlink — run \`oo user.fix\` to repair"
fi

# ----------------------------------------------------------------------------
# INVARIANT-2: resolved target lives under the canonical shared tree.
# Use private.this.path.canonical (this:144) — portable across GNU + BSD.
# Use a glob pattern in `case` so both /home/shared (Linux) and
# /Users/Shared (macOS) match.
# ----------------------------------------------------------------------------
resolved=$(private.this.path.canonical "$artefact")
test.case $level "platform.<scope>.<aspect>: target lives under shared tree" true
case "$resolved" in
  */shared/EAMD.ucp/Components/com/ceruleanCircle/EAM/1_infrastructure/Once.sh/*)
    expect.pass "target under shared tree: $resolved"
    ;;
  *)
    expect.fail "target outside shared tree: $resolved — run \`oo user.fix\` to repoint"
    ;;
esac

# ----------------------------------------------------------------------------
# INVARIANT-3: behavioural — the user-visible feature that depends on the
# above invariants actually works end-to-end. This is the assertion the user
# would have noticed empirically; the earlier ones pinpoint the cause.
# ----------------------------------------------------------------------------
# Example placeholder — adapt to what `$artefact` enables:
test.case $level "platform.<scope>.<aspect>: <behaviour> works" true
if : ; then   # ← replace `:` with the actual smoke check
  expect.pass "<behaviour> verified"
else
  expect.fail "<behaviour> failed — see invariants 1-2 for the underlying cause"
fi

test.suite.save.results
