#!/bin/sh
set -e

#run with
#autopkgtest ../runit-init_2.2.0-7_amd64.deb ../runit_2.2.0-7_amd64.deb ../getty-run_2.2.0-7_all.deb  . --test-name=trigger-sv -- qemu ../autopkgtest.img

rc=0
nrestart=0

rcadd() { printf '%s\n' "$*"; rc=$((rc+1)); }
fail() { rcadd "FAIL: $*"; }
warn() { printf '%s\n' "WARN: $*"; }

clean_sv() {
    rm -rf "/etc/service/.$1" || true
    rm -rf "/etc/service/$1"  || true
}

fake_wtime() {
    wtnow=$(cat /etc/service/installedfull-sv/.meta/wtime)
    wtfake=$((wtnow-1))
    echo "$wtfake" > /etc/service/installedfull-sv/.meta/wtime
    wtact=$(cat /etc/service/installedfull-sv/.meta/wtime)
    if [ $wtact -lt $wtnow ]; then
        return 0
    else
        return 1
    fi
}

goodsvs="installed-sv installedfull-sv linklog-sv multi-sv@default uninstalled-sv"
badsvs="norun-sv binempty-sv binnopath-sv nobin-sv"
#TODO user istances
#usersvlist="user-sv@user linklog-usersv@user full-usersv@user"



                                                                ###test setup###
echo "preparing test setup..."
#enable verbose/debug mode
touch /etc/runit/verbose
touch /etc/runit/debug
#echo "listing links inside /etc/service:"
#ls -l /etc/service/
cp -r debian/tests/sv/installed-sv /usr/share/runit/sv/
cp -r debian/tests/sv/uninstalled-sv /usr/share/runit/sv/
cp -r debian/tests/sv/installedfull-sv /usr/share/runit/sv/
rm -rf /usr/share/runit/sv/installedfull-sv/log #log is not needed here
echo 'no' > /usr/share/runit/sv/installedfull-sv/.meta/enable #set to: disabled by default

#runsvchdir to default (trigger sv enables there)
if [ ! -h /etc/service ]; then
   fail "setup: /etc/service is not a symlink" && exit "$rc"
else
    runsvchdir default
    servicelink=$(readlink -f /etc/service)
    if [ "$servicelink" != /etc/runit/runsvdir/default ]; then
        fail "setup: /etc/service is not a symlink"  && exit "$rc"
    fi
fi

#copy to runtime dir with cpsv a
CPSV_DEST=/usr/share/runit/sv.now CPSV_SOURCE=/usr/share/runit/sv.src  cpsv a installed-sv uninstalled-sv installedfull-sv
echo "...done"

                                                ### test policy###
echo "testing policy: dot-links..."
sleep 1
# disable the service (create .link)
clean_sv "installed-sv"
ln -s  /usr/share/runit/sv.current/installed-sv  /etc/service/.installed-sv

#run trigger_sv manually, check that service is disabled
/lib/runit/trigger_sv setup
#/lib/runit/trigger_sv upgrade
[ -h /etc/service/installed-sv ] && fail "policy: installed-sv: expected disabled, but is enabled"
[ -h /etc/service/.installed-sv ] || fail "policy: installed-sv: missing .installed-sv symlink"

clean_sv "installed-sv"
echo "done"

                              ### core test: enabled/disabled bin logic###
echo "testing enable/disable core logic..."
sleep 1
# now that the .link is removed,  run the trigger again,
#  check that service is now enabled

/lib/runit/trigger_sv setup

#expected result:  installed-sv=enabled; uninstalled-sv=no links
[ ! -h /etc/service/installed-sv ] && fail "core: installed-sv: expected enabled, but it isn't"
[ -h /etc/service/.installed-sv ] && fail "core: installed-sv: expected enabled, but .installed-sv found"
[ -h /etc/service/uninstalled-sv ] && fail "core: uninstalled-sv: expected disabled, but it's enabled"
[ -h /etc/service/.uninstalled-sv ] && fail "core: uninstalled-sv: expected disabled (no links), but .uninstalled-sv found"
#test meta: enable=no on installedfull-sv
[ -h /etc/service/installedfull-sv ] && fail "core: installedfull-sv: expected disabled, but it's enabled"
[ -h /etc/service/.installedfull-sv ] && fail "core: installedfull-sv: expected disabled (no links), but .installedfull-sv found"

#emulate package removal, expected to be disabled
if [ -e /etc/service/installed-sv/.meta/bin ]; then
    echo "/bin/nonexistent" > /usr/share/runit/sv/installed-sv/.meta/bin
    echo "/bin/nonexistent" > /usr/share/runit/sv.current/installed-sv/.meta/bin
    #TODO fix cp_sv (cp -a) in cpsv --> make sure it overwrites/updates existing files in sv.current
else
    fail "core: installed-sv: bine metafile not found, can't test disable on binary removal"
fi
/lib/runit/trigger_sv setup
[ -h /etc/service/installed-sv ] && fail "core: installed-sv: expected disabled (pkg removed), but installed-sv found"
[ -h /etc/service/.installed-sv ] && fail "core: installed-sv: expected no links (pkg removed), but .installed-sv found"

clean_sv "installed-sv"
echo "done"


                               ### policy: /etc/sv overrides /usr/share/runit/sv.current###
echo "testing policy: /etc/sv/ override..."
sleep 1
# copy the service with meta unistalled to /etc/sv, the change bin to installed
cpsv a uninstalled-sv
[ -d /etc/sv/uninstalled-sv ] || fail "cpsv a: /etc/sv/uninstalled-sv: not found"
echo "/bin/true" > /etc/sv/uninstalled-sv/.meta/bin
/lib/runit/trigger_sv setup
#expected: is enabled, and that link points to /etc/sv
[ ! -h /etc/service/uninstalled-sv ] && fail "policy: uninstalled-sv: expected enabled, but it isn't"
[ -h /etc/service/.uninstalled-sv ] && fail "policy: uninstalled-sv: expected enabled, but .uninstalled-sv found"
uninstlink=$(readlink -f /etc/service/uninstalled-sv)
if [ "$uninstlink" != /etc/sv/uninstalled-sv ]; then
        fail "setup: /etc/service/uninstalled-sv does not point to /etc/sv/"
fi

clean_sv "uninstalled-sv"
clean_sv "installed-sv"

if [ -e /etc/sv/uninstalled-sv/supervise/lock ]; then
    echo "waiting for uninstalled-sv's runsv to exit.."
    chpst -l  /etc/sv/uninstalled-sv/supervise/lock true
    echo "..ok"
fi
rm -rf "/etc/sv/uninstalled-sv" || true
rm -rf "/usr/share/runit/sv.current/uninstalled-sv" || true
if [ -e /usr/share/runit/sv.current/installed-sv/supervise/lock ]; then
    echo "waiting for installed-sv's runsv to exit.."
    chpst -l  /usr/share/runit/sv.current/installed-sv/supervise/lock true
    echo "..ok"
fi
rm -rf "/usr/share/runit/sv.current/uninstalled-sv" || true
rm -rf "/usr/share/runit/sv.current/uninstalled-sv" || true

echo "...done"


                                                ### test upgrade restart-wtime###
if systemctl is-active --quiet runit.service ; then
    echo "testing upgrade/restart..."
    #test: onupgrade=restart
    echo 'yes' > /usr/share/runit/sv.current/installedfull-sv/.meta/enable
    echo 'yes' > /usr/share/runit/sv/installedfull-sv/.meta/enable #TODO fix in cpsv, see above
    /lib/runit/trigger_sv setup
    [ ! -h /etc/service/installedfull-sv ] && fail "upgrade-restart: uninstalled-sv: expected enabled, but it isn't"
    for i in 1 2 3 4 5 6 7; do #wait for the service to be up
        sleep 1 && echo "waiting for service to be up: $i"
        [ -p "/etc/service/installedfull-sv/supervise/ok" ] && break
    done
    sleep 1
    sv check installedfull-sv || fail "sv: not in the requested status"
    fake_wtime
    sleep 1
    sv s installedfull-sv || true
    echo 0 > /etc/service/installedfull-sv/rcounter
    /lib/runit/trigger_sv upgrade
    sleep 2
    sv check installedfull-sv || fail "sv: after upgrade: not in the requested status"
    nrestart=$(cat /etc/service/installedfull-sv/rcounter)
    #expect 1(restart happened)
    [ $nrestart -eq '1' ] || fail "nrestart: expected 1 but value is $nrestart"
    echo "...done"
    #test: onupgrade=nostop
    echo "testing upgrade/nostop..."
    echo 0 > /etc/service/installedfull-sv/rcounter
    echo nostop > /etc/service/installedfull-sv/.meta/onupgrade
    fake_wtime
    /lib/runit/trigger_sv upgrade
    sleep 2
    #expect 0(=norestart), wrong if 1(=restart)
    nrestart=$(cat /etc/service/installedfull-sv/rcounter)
    [ $nrestart -eq '0' ] || fail "nrestart: expected 0 but value is $nrestart"
    echo "...done"
else
    warn "can't perform upgrade/restart test, skipping..."
fi

                                                            ###test cleanup###

#delete test services from /etc/sv, /usr/share/runit/sv.current | sv
#rm -rf ...
echo "test cleanup.."
runsvchdir svmanaged
rm -rf /etc/sv/installedfull-sv@instance1 || true
rm -rf /etc/sv/multi-sv@instance1 || true
rm -rf /etc/sv/uninstalled-sv
#rm -rf "$runtimedir/installedfull-sv@default" || true
for dir in installed-sv uninstalled-sv installedfull-sv; do
    rm -rf "/usr/share/runit/sv/$dir" || true
    rm -rf "/usr/share/runit/sv.current/$dir" || true
done
rm -f /etc/runit/verbose


[ "$rc" -eq 0 ] || echo "FATAL: failed test: cpsv: rc is $rc"

exit "$rc"
