# -*- shell-script -*-
# Copyright 2021-2022 Ian Jackson and contributors to Hippotat
# SPDX-License-Identifier: GPL-3.0-or-later WITH LicenseRef-Hippotat-OpenSSL-Exception
# There is NO WARRANTY.

set -o pipefail
set -x

. "${0%/*}"/../test/tcommon

exec >&2

on_failure=:

test-prep () {
    trap '
        rc=$?
 : =================== ^^ TEST FAILURE ^^ ====================
	set +e
	tail -500 /var/log/daemon.log
	$on_failure
        exit $rc
' 0

    determine-tname adt

    if [ "$AUTOPKGTEST_TMP" ]; then
	tmp=$AUTOPKGTEST_TMP
    else
	tmp=$PWD/tmp/$tname
	hosts-cleanup
	mkdir -p tmp
	rm -rf "$tmp"
	mkdir "$tmp"
    fi
}

filesystem-prep () {
    cs=$1; shift
    # expects $tmp to be set to test-specific temp dir (abs path)

    host-cleanup $cs

    mkdir "$tmp"/$cs-overlay
    
    for fs in root dev home; do
	case "$fs" in
	    root)	lower=/		;;
	    dev)	lower=/dev	;;
	    home)	lower=/home	;;
	    *) x-internal-error	;;
	esac

	rm -rf "$tmp"/$cs-$fs-{upper,work}
	mkdir "$tmp"/$cs-$fs-{upper,work}

	mount -t overlay -o \
 lowerdir=$lower,upperdir="$tmp"/$cs-$fs-upper,workdir="$tmp"/$cs-$fs-work \
	      none "$tmp"/$cs-overlay$lower
    done
}

hosts-cleanup () {
    host-cleanup client
    host-cleanup server
}

host-cleanup () {
    cs=$1; shift
    fuser -Mkm "$tmp"/$cs-overlay ||:
    umount "$tmp"/$cs-overlay/proc ||:
    umount "$tmp"/$cs-overlay/dev ||:
    umount "$tmp"/$cs-overlay/home ||:
    umount "$tmp"/$cs-overlay ||:
    umount "$tmp"/$cs-pidns ||:
    if test -d "$tmp"/$cs-overlay; then
	rmdir "$tmp"/$cs-overlay
    fi
}

pidnamespace-prep () {
    cs=$1; shift
    touch "$tmp"/$cs-pidns
    rm -f "$tmp"/$cs-overlay/adt-pidns-sentinel
    mkfifo -m 600 "$tmp"/$cs-overlay/adt-pidns-sentinel
    unshare --fork --pid="$tmp"/$cs-pidns \
	    chroot "$tmp"/$cs-overlay \
	    sh -ec '
		mount -t proc none /proc
		>/adt-pidns-sentinel
		sleep 10000000
	    ' &
    cat "$tmp"/$cs-overlay/adt-pidns-sentinel
}

configure () {
    cs=$1; shift
    in- $cs dd <<END of=/etc/hippotat/secrets.d/alice
[sam 192.0.2.3]
secret = sesame
END
    in- $cs dd <<END of=/etc/hippotat/main.cfg
[COMMON]
server = sam

[sam]
addrs = 198.51.100.1
port = 80
vnetwork = 192.0.2.0/24
END

    in- $cs bash -xe <<'END'
	ln -s ../services-available/ipif /etc/userv/services.d/ipif
END

    in- $cs hippotat-setup-permissions $cs

    configure-$cs
}

configure-client () {
    :
}
configure-server () {
    :
}

setup-host () {
    cs=$1; shift
    filesystem-prep $cs
    pidnamespace-prep $cs

    in- $cs bash -xec '
	if test -h /var/cache/apt/archives &&
         ! test -d /var/cache/apt/archives; then
	    rm /var/cache/apt/archives
	fi

	# On systemd systems, /dev/log is a symlink into /run/systemd,
	# but we cannot run systemd in the inner environment,
	# so we use rsyslog.  Clean out the symlink.
	#
	# The check for systemd is to let this test be less destructive
	# when run under inadequate isolation on a non-systemd setup.
        if ls -al /dev/log | grep systemd; then
	    rm -f /dev/log
	fi
    '

    : remove redundant packages
    perl -ne '
	next unless m{^Tests:.*\s'"$tname"'\s}..m{^$};
	next unless m{^Depends:}...m{^\S};
	s{^Depends:}{ };
	next if m{^\S};
	print $_, "\n" foreach split m{[\s,\|]+};
    ' debian/tests/control |sort >$tmp/$cs-unwanted-deps
    local unwanted_deps=$(perl -ne '
	next if m{^(?:userv-utils|libnetaddr-ip-perl|net-tools)$};
	next if m{^hippotat-'"$cs"'$};
	next if m{^(?:iptables|rsyslog|authbind)$} && "'"$cs"'" eq "server";
	# TODO for rsyslog, record bug number here
	next if m{^(?:orphan-sysvinit-scripts)$} && "'"$cs"'" eq "server";
	print;
    ' $tmp/$cs-unwanted-deps)
    in- $cs apt-mark auto $unwanted_deps
    in- $cs apt-get -y autoremove

    in- $cs service userv start

    configure $cs

    finish-setup-host-$cs
}

finish-setup-host-client () {
    yes '' | \
    in- client adduser --disabled-password user ||:
    in- client adduser user _hippotat
}
finish-setup-host-server () {
    in- server iptables -D INPUT -j empty -s 192.0.2.0/24 ||:
    in- server iptables -N empty ||:
    in- server iptables -I INPUT -j empty -s 192.0.2.0/24
    rsyslog-capture-daemon in- server

    in- server service rsyslog start || {
	# When the outer system is systemd, `service` doesn't find it
	# in the chroot, but the init script is in orphan-sysvinit-scripts
	# which is also missing.  Run it by hand.
	in- server rsyslogd -n &
	sleep 5
    }
}

in- () {
    cs=$1; shift
    in-ns $cs \
	  nsenter --pid="$tmp"/$cs-pidns \
	  chroot "$tmp"/$cs-overlay \
	  "$@"
}

setup-pair () {
    test-prep
    on_failure=pair-on-failure
    $test/netns-setup $tname
    setup-host client
    setup-host server
}

pair-on-failure () {
    tail -500 "$tmp"/server-overlay/var/log/daemon.log ||:
    hosts-cleanup
}

rsyslog-capture-daemon () {
    "$@" dd <<END of=/etc/rsyslog.d/hippotat.conf
daemon.*	/var/log/daemon.log
END
}

t-ok () {
    trap '' 0
    echo ok.
}
