#!/bin/bash
# Exercise the installed tool: the entry point finds its own tree, the
# built-in layer library parses, and the sbin PATH fix (d/patches/0001) holds.
set -uo pipefail

IGSHARE=/usr/share/rpi-image-gen
fail=0

# dependencies_check ends every call - whatever category was asked for - by
# requiring binfmt_misc on a non-arm host, so without it nothing below runs,
# not even "layer --list". That is an unusable environment rather than a
# broken package, so skip rather than report a failure we cannot attribute.
case $(uname -m) in
   aarch64|arm*) ;;
   *)
      grep -q binfmt_misc /proc/filesystems || {
         echo "SKIP: binfmt_misc not available and host is not arm" >&2
         exit 77
      }
      ;;
esac

# Leave nothing behind in the caller's directory.
cd "${AUTOPKGTEST_TMP:-$(mktemp -d)}" || exit 1

run() {
   local desc=$1 ; shift
   echo "== ${desc}"
   if "$@" > "${AUTOPKGTEST_TMP:-/tmp}/out" 2>&1 ; then
      echo "   ok"
   else
      echo "   FAIL (exit $?)"
      sed 's/^/   | /' "${AUTOPKGTEST_TMP:-/tmp}/out"
      fail=1
   fi
}

# The symlink in /usr/bin must resolve back to the installed tree, otherwise
# rootpath() picks the wrong IGTOP and everything after this is meaningless.
echo "== entry point resolves to ${IGSHARE}"
resolved=$(dirname "$(readlink -e /usr/bin/rpi-image-gen)")
if [[ $resolved == "$IGSHARE" ]] ; then
   echo "   ok"
else
   echo "   FAIL: resolved to '${resolved}'"
   fail=1
fi

run "help"              rpi-image-gen help
run "layer --list"      rpi-image-gen layer --list
run "layer --describe"  rpi-image-gen layer --describe rpi5
run "registry lints"    rpi-image-gen metadata --lint "${IGSHARE}/registry.defs"

# Every layer in the built-in library should pass its own linter. This is the
# cheapest check that debian/*.install did not drop something: a layer that
# references a hook, overlay or schema which was not installed fails here.
#
# A few layers - sys-devel/gnu-common.yaml today - interpolate variables that
# only exist once a build has worked out its toolchain (DEB_HOST_ARCH,
# TOOLCHAIN_MODE). Linting one of those standalone cannot resolve them, and
# that says nothing about the packaging, so accept it. The file still had to
# parse to get that far.
echo "== built-in layer library lints"
bad=0
seen=0
while IFS= read -r -d '' layer ; do
   grep -q 'X-Env-Layer-Name' "$layer" || continue
   seen=$((seen + 1))
   out=$(rpi-image-gen metadata --lint "$layer" 2>&1) && continue
   if grep -q 'Unresolved environment variables' <<<"$out" ; then
      echo "   skip (needs build context): ${layer#"${IGSHARE}"/}"
      continue
   fi
   echo "   FAIL: $layer"
   sed 's/^/   | /' <<<"$out"
   bad=$((bad + 1))
done < <(find "${IGSHARE}/layer" "${IGSHARE}/device" "${IGSHARE}/image" \
            -name '*.yaml' -print0 2>/dev/null)
if (( seen < 50 )) ; then
   echo "   FAIL: only ${seen} layers found, expected the whole library"
   fail=1
elif (( bad == 0 )) ; then
   echo "   ok (${seen} layers)"
else
   fail=1
fi

# d/patches/0001. Without it, a build started by an unprivileged user dies in
# dependencies_check because mkdosfs and friends live in /usr/sbin, which is
# not on a non-root PATH on Debian.
#
# "clean" is the cheap way to reach that check: it runs the same
# dependencies_check --category all as "build" and then does parameter
# assembly and layer collection, but touches the network not at all and
# finishes in about a second. Run it against a config whose work tree does
# not exist, so there is nothing for it to remove and nothing to prompt about.
#
# Require a zero exit, not just the absence of the error string. Grepping
# alone passes vacuously: anything that fails BEFORE the dependency check -
# a missing config, or the binfmt_misc test above - also leaves the string
# absent.
echo "== dependency check passes with sbin stripped from PATH"
log=$PWD/pathcheck.log
probe=$PWD/pathcheck.d
mkdir -p "$probe" || exit 1
( cd "$probe" && env PATH=/usr/local/bin:/usr/bin:/bin \
     rpi-image-gen clean -c "${IGSHARE}/config/trixie-minbase.yaml" \
     < /dev/null ) > "$log" 2>&1
rc=$?
if grep -q 'is installed, but not found' "$log" ; then
   echo "   FAIL: dependency check rejected an installed tool"
   grep 'is installed, but not found' "$log" | sed 's/^/   | /'
   fail=1
elif (( rc != 0 )) ; then
   echo "   FAIL: exited ${rc} before reaching the end of the run"
   tail -20 "$log" | sed 's/^/   | /'
   fail=1
else
   echo "   ok"
fi

exit $fail
