tame/tamer/tests/xmli/test-xmli

152 lines
4.0 KiB
Bash
Executable File

#!/bin/bash
# Assert that a program can be derived from the ASG as expected.
#
# See `./README.md` for more information.
set -euo pipefail
mypath=$(dirname "$0")
. "$mypath/../../conf.sh"
# Performing this check within `<()` below won't cause a failure.
: "${P_XMLLINT?}" # conf.sh
run-test() {
local name="${1?Missing test name}"
local dir="${2?Missing dir}"
shift 2
rm -f "$dir/"*.log
header "$dir" "$name"
"test-$name" "$dir" "$@" || {
local ret=$?
echo ' [FAIL]'
return "$ret"
}
echo ' [ OK ]'
}
timed-tamec() {
local dir="${1?Missing directory name}"
local in="${2?Missing input filename}"
local out="${3?Missing output filename}"
dir="${dir%/}" # strip trailing slash, if any (just to style output)
local -i ret=0
# /usr/bin/time does not have high enough precision
# This won't be wholly accurate because time is spent in shell,
# but it'll be close enough.
local -i start_ns=$(date +%s%N)
local objty=xmlo
if [ -f "$dir/is-experimental" ]; then
objty=xmlo-experimental
fi
command time -f "%F/%Rfault %I/%Oio %Mrss %c/%wctx \n%C" -o "$dir/time.log" \
"${TAMER_PATH_TAMEC?}" -o "$dir/$out" --emit "$objty" "$dir/$in" \
&> "$dir/tamec-$out.log" \
|| ret=$?
local -i end_ns=$(date +%s%N)
local -i elapsed_ms=$(( (end_ns - start_ns) / 1000000 ))
# First line will be "Command exited with non-zero status N" on failure.
# The last line will be '%C' above.
# So, we want the second-to-last line.
#
# Newline omission is intentional.
printf "<%3dms %s" "$elapsed_ms" "$(tail -n2 "$dir/time.log" | head -n1)"
return "$ret"
}
header() {
# allocate enough space based on the path we'll output
local -i mypath_len=${#mypath}
local -i dirlen=$((mypath_len + 14))
# newline intentionally omitted
printf "%-${dirlen}s %-20s " "$@"
}
# Derive a program from `src.xml` and verify that it meets our expectations.
#
# This test is inherently fragile, as it will break any time we perform
# certain types of optimizations or change internal representations. _But
# that is intended._ We want to be well aware of such changes in derivation
# so that we can judge whether it needs adjustment.
test-derive-from-src() {
local dir="${1?Missing directory name}"
timed-tamec "$dir" src.xml out.xmli || return
diff <("$P_XMLLINT" --format "$dir/expected.xml" || echo 'ERR expected.xml') \
<("$P_XMLLINT" --format "$dir/out.xmli" || echo 'ERR out.xmli') \
&> "$dir/diff.log"
}
# Having taken `A` and derived `B`, we should be able to take `B` and derive
# `C`, where `B` and `C` are equivalent programs.
#
# That is, this derivation should be transitively equivalent and reach a
# fixpoint on the second derivation. This serves as a sanity check to
# ensure that the program we generated makes sense to our own system.
#
# Note that, in the future, we'll have to strip handoff metadata
# (`preproc:*` data) from the output so that it will be accepted by TAMER.
test-fixpoint() {
local dir="${1?Missing directory name}"
if [ -f "$dir/no-fixpoint" ]; then
echo -n '!!!WARNING!!! test skipped: `no-fixpoint` file '
return
fi
timed-tamec "$dir" out.xmli out-2.xmli || return
diff <("$P_XMLLINT" --format "$dir/expected.xml" || echo 'ERR expected.xml') \
<("$P_XMLLINT" --format "$dir/out-2.xmli" || echo 'ERR out.xmli') \
&> "$dir/diff.log"
}
main() {
local -a fail=()
for dir in "$mypath"/*/; do
run-test derive-from-src "$dir" && run-test fixpoint "$dir" \
|| fail=("${fail[@]}" "$dir")
done
test -z "${fail[@]}" || {
cat << EOF
!!! TEST FAILED
tamec: $TAMER_PATH_TAMEC
note: The compiler output and diff between the expected and given data
are below. Both files are formatted with \`xmllint\` automatically.
EOF
for dir in "${fail[@]}"; do
echo
echo ",=====[ $dir logs ]======"
echo "|"
cat "$dir/"*.log | sed 's/^/| /'
echo "|"
echo "\`====[ end $dir logs ]===="
done
exit 1
}
}
main "$@"