#!/bin/bash
#
# Run gnulib tests under Syd.
#
# Copyright 2024 Ali Polatel <alip@chesswob.org>
#
# SPDX-License-Identifier: GPL-3.0

# TEST_LIMIT: Number of tests to run at a time.
# TEST_PATTERN: An Extended Regex for tests to run.
test_pattern_set=false
case "$1" in
    '')
        TEST_LIMIT=4096
        TEST_PATTERN='.*'
        test_pattern_set=true
        ;;
    [0-9]*)
        TEST_LIMIT="${1}"
        TEST_PATTERN='.*'
        ;;
    *)
        TEST_LIMIT=250
        TEST_PATTERN="${1}"
        test_pattern_set=true
        ;;
esac

# A Regex (PCRE) for tests to skip.
# i586-only (compile) fails: backupfile, copy-file, exclude, mbsstr, nan, wctype.
# vma-prot: https://builds.sr.ht/~alip/job/1351977 TODO: Figure out why!
# physmem: Smashes the stack: https://builds.sr.ht/~alip/job/1395200 TODO: ditto!
# getloadavg: ditto: https://builds.sr.ht/~alip/job/1395813 TODO: ditto!
# localename-environ: config fails: configure.ac:41: error: possibly undefined macro: gl_LOCALE_MODULE_INDICATOR
# poll: racy test, fails randomly, passes most of the time: https://builds.sr.ht/~alip/job/1454355#task-test64
# quotearg: https://builds.sr.ht/~alip/job/1533212#task-test32 TODO: Figure out why!
SKIP_PATTERN='(backupfile|bison|copy-file|datetime|exception|exclude|gettext|link-warning|localename-environ|mbsstr|nan|poll|printf|quotearg|trapping|vma-prot|wctype|windows|^(array|java|uni)|-ieee$|(^(execinfo|getloadavg|gnumakefile|havelib|physmem|timevar)$))'

# Tests that have failed in the past.
# canonicalize-lgpl: https://builds.sr.ht/~alip/job/1549072#task-test64
# linkat: https://builds.sr.ht/query/log/1402429/test32/log
# mkdir: https://builds.sr.ht/~alip/job/1286254
# openat-safer: https://builds.sr.ht/~alip/job/1522333
# openat2: https://builds.sr.ht/query/log/1604803/test32/log
# posix_openpt: https://builds.sr.ht/~alip/job/126488
# readdir: no known fail but best to check everytime.
# rename: https://builds.sr.ht/~alip/job/1286933
# select: https://builds.sr.ht/~alip/job/1574787
# truncate: https://gitlab.exherbo.org/sydbox/sydbox/-/jobs/83046
# utimensat: https://builds.sr.ht/~alip/job/1257729
FAIL_HISTORY=(
    canonicalize-lgpl
    linkat
    mkdir
    openat-safer
    openat2
    posix_openpt
    readdir
    rename
    select
    truncate
    utimensat
)
# Do not go over history, if user specified a test pattern.
$test_pattern_set && FAIL_HISTORY=()

# Make sure we don't trigger TPE.
umask 077

# Enable coredumps.
ulimit -c unlimited

# Force TTY output.
export SYD_FORCE_TTY=YesPlease

# Enable path hiding and ioctl sandboxing for wider coverage.
export SYD_PALUDIS_LPATH=1
export SYD_PALUDIS_IOCTL=1

# Timeout is 45 minutes for all tests unless otherwise specified.
SYD_TEST_TIMEOUT=${SYD_TEST_TIMEOUT:-45m}

export SYD_LOG=${SYD_LOG:-info}
SYD="${CARGO_BIN_EXE_syd:-syd}"

set -ex
DIR="$(mktemp -d syd-gnulib.XXXXXX)"
DIR="$(readlink -f "${DIR}")"
set +ex

edo() {
    echo >&2 "-- $*"
    "$@"
}

run_tests() {
    [[ -n "${SYD_TEST_DMESG}" ]] && sudo dmesg -C

    edo \
        timeout -sKILL ${SYD_TEST_TIMEOUT} \
        ${SYD} -ppaludis -m 'allow/all+/***' -mlock:on \
        -- make -j check
    r=$?

    if [[ $r == 0 ]]; then
        rm -fr "${DIR}"
        return 0
    fi

    echo '--8<-- TEST LOG BEGIN -->8--'
    cat ./gltests/test-suite.log
    echo '-->8-- TEST LOG END   --8<--'

    if [[ -n "${SYD_TEST_DMESG}" ]]; then
        echo '--8<-- KERNEL LOG BEGIN -->8--'
        sudo dmesg
        echo '-->8-- KERNEL LOG END   --8<--'
    fi

    echo >&2 "[*] Keeping test directory of failed tests: ${DIR}"
    return $r
}

arg_depth='--depth 1'
if [[ -n "${GNULIB_HEAD}" ]]; then
    arg_depth=
fi
set -ex
pushd "${DIR}"
git clone ${arg_depth} https://github.com/coreutils/gnulib.git || exit 0
pushd gnulib
if [[ -n "${GNULIB_HEAD}" ]]; then
    git checkout "${GNULIB_HEAD}" || exit 127
fi
git rev-parse HEAD
sed -i \
    -e 's|"0.0.0.0"|"127.0.0.1"|' \
    tests/test-getsockname.c
set +x

PASS=0
FAIL=0
SKIP=0
TESTS=( $(./gnulib-tool --list | grep -E "${TEST_PATTERN}" | grep -vE "${SKIP_PATTERN}" | shuf ) )
CTEST=${#TESTS[@]}
NTEST=${TEST_LIMIT}
if [[ ${NTEST} -gt ${CTEST} ]]; then
    NTEST=${CTEST}
fi
TESTS=( "${FAIL_HISTORY[@]}" "${TESTS[@]:0:${NTEST}}" )
NTEST=${#TESTS[@]}

set -ex
./gnulib-tool --avoid=pt_chown --create-testdir --dir "${DIR}"/tmp "${TESTS[@]}"
pushd "${DIR}"/tmp
./configure
make -j
run_tests
