#!/bin/sh

set -ex

export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin

mount -t proc none /proc
mount -t sysfs none /sys
mount -t debugfs debugfs /sys/kernel/debug/ || true
mount -t tracefs tracefs /sys/kernel/tracing/ || true
mount -t tmpfs none /mnt
mount -t tmpfs none /run
mount -t tmpfs none /tmp

BUILD_DIR="build/"

# parse cmdline
for x in $(cat /proc/cmdline); do
  if [ "$x" = "shell" ]; then
    SHELL=1
  elif [ "$x" = "system" ]; then
    SHELL=1
    SERVICE=1
  elif [ "$x" = "asan" ]; then
    export G_SLICE=always-malloc G_DEBUG=gc-friendly
    export ASAN_OPTIONS=malloc_context_size=64:fast_unwind_on_malloc=0
  elif [ "$x" = "service-backtrace" ]; then
    SERVICE_BACKTRACE=1
  fi
done
if [ -n "$test" ]; then
  MESON_TEST="$test"
fi

hostname qemu-test

# loopback interface
ip addr add 127.0.0.1 dev lo
ip link set lo up

# main interface
ip link set eth0 up
ip addr add 10.0.2.15/24 dev eth0
ip link set eth0 up
ip route add default via 10.0.2.2
# /etc is not writable from here
echo "nameserver 10.0.2.3" > /tmp/resolv.conf
mount --bind /tmp/resolv.conf /etc/resolv.conf

# switch to rauc dir
cd "$(dirname "$0")"

# fake entropy
$BUILD_DIR/test/fakerand

# grub env
mkdir -p /tmp/boot/grub
mount --bind /tmp/boot /boot
grub-editenv test/grubenv.test create
touch /tmp/boot/grub/grubenv
mount --bind test/grubenv.test /tmp/boot/grub/grubenv

grub-editenv /tmp/boot/grub/grubenv set ORDER="A B" A_TRY="0" B_TRY="0" A_OK="1" B_OK="1"

# fake slot devices
truncate --size=64M /tmp/rootdev
mkfs.ext4 /tmp/rootdev
truncate --size=64M /tmp/appdev
mkfs.ext4 /tmp/appdev

# dbus daemon if service is enabled
if grep -q "ENABLE_SERVICE 1" $BUILD_DIR/config.h; then
  cp -a /etc/dbus-1/system.d /tmp
  cp -a $BUILD_DIR/data/de.pengutronix.rauc.conf /tmp/system.d
  chown root:root /tmp/system.d/de.pengutronix.rauc.conf
  chmod 644 /tmp/system.d/de.pengutronix.rauc.conf
  mount --bind /tmp/system.d /etc/dbus-1/system.d
  mount -t tmpfs none /var/run
  mkdir -p /var/run/dbus
  time dbus-daemon --system --fork --nopidfile --nosyslog --print-address
fi

# rauc binary in PATH
if [ -n "$SHELL" ]; then
  mkdir /tmp/bin
  cp -a $BUILD_DIR/rauc /tmp/bin/rauc
  export PATH=/tmp/bin:$PATH
fi
export RAUC_TEST_NBD_SERVER="$(realpath $BUILD_DIR/rauc)"

if type losetup; then
  truncate --size=64M /tmp/rauc-disk.img
  losetup -P /dev/loop0 /tmp/rauc-disk.img
  export RAUC_TEST_BLOCK_LOOP=/dev/loop0
fi

cat /proc/mtd

if [ -c /dev/mtd0 ] && type flashcp; then
  export RAUC_TEST_MTD_NOR=/dev/mtd0
fi

if [ -c /dev/mtd2 ] && type flash_erase; then
  export RAUC_TEST_MTD_NAND=/dev/mtd2
fi

if [ -c /dev/mtd3 ] && type ubiattach; then
  ubiattach -m 3 -d 0
  ubimkvol /dev/ubi0 -s 12096KiB -N rauc-test
  export RAUC_TEST_MTD_UBI=/dev/ubi0
  export RAUC_TEST_MTD_UBIVOL=/dev/ubi0_0
fi

if type casync; then
  export RAUC_TEST_CASYNC=1
fi

# rauc system config & service start
if [ -n "$SERVICE" ]; then
  mkdir /tmp/rauc
  cp qemu-test-rauc-config /tmp/rauc/system.conf
  cp test/openssl-ca/dev-ca.pem /tmp/rauc/ca.cert.pem
  if [ -n "$SERVICE_BACKTRACE" ] && type gdb; then
    gdb --batch --ex "run" --ex "thread apply all bt" --args rauc service --conf=/tmp/rauc/system.conf &
  else
    rauc service --conf=/tmp/rauc/system.conf &
  fi
fi

if type nginx; then
  mount -t tmpfs tmpfs /var/lib/nginx
  mount -t tmpfs tmpfs /var/log/nginx
  nginx -c test/nginx.conf -p "$PWD"
  export RAUC_TEST_HTTP_SERVER=1
fi

if python3 test/nginx_backend.py; then
  export RAUC_TEST_HTTP_BACKEND=1
fi

echo "use ctrl-a x to exit and ctrl-a c to access the qemu monitor"

echo "system ready"

if [ -n "$SHELL" ]; then
  echo "alias ll='ls -l'" >> /tmp/bashrc
  BASH_CMD="exec bash --rcfile /tmp/bashrc"
  if type resize; then
    BASH_CMD="eval \$(resize); $BASH_CMD"
  fi
  HISTFILE="$(pwd)/.qemu_bash_history" \
  setsid bash -c "$BASH_CMD" </dev/ttyS0 >/dev/ttyS0 2>&1 || echo exit-code=$?
  echo o > /proc/sysrq-trigger
fi

if [ -n "$SERVICE" ]; then
  rauc status mark-good
fi

if meson test -C $BUILD_DIR "$MESON_TEST"; then
  touch qemu-test-ok
  echo "RESULT: PASSED"
else
  cat $BUILD_DIR/meson-logs/testlog.txt || true
  # show system status on error
  mount || true
  df -h || true
  free || true
  echo "RESULT: FAILED"
fi
sleep 1
echo o > /proc/sysrq-trigger
sleep 1
