WIP
parent
bbe775d870
commit
b378cbdf6a
|
@ -74,7 +74,7 @@ check-docgen:
|
|||
build-aux/asg-ontviz >/dev/null
|
||||
|
||||
.PHONY: check-system
|
||||
check-system: bin
|
||||
check-system: bin conf.sh
|
||||
tests/run-tests
|
||||
|
||||
.PHONY: check-lint
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
#!/bin/bash
|
||||
|
||||
# This configuration file is populated by `configure` and is intended to be
|
||||
# sourced by shell scripts.
|
||||
|
||||
|
@ -62,4 +64,69 @@ fi
|
|||
declare -r TAMER_PATH_TAMEC="$TAMER_PATH_BIN/tamec"
|
||||
declare -r TAMER_PATH_TAMELD="$TAMER_PATH_BIN/tameld"
|
||||
|
||||
declare -r P_XMLLINT="@XMLLINT@"
|
||||
# Miscellaneous programs used by shell scripts.
|
||||
#
|
||||
# Note that, just because these programs were populated by a configure
|
||||
# script, that does not mean that they actually exist. In particular, users
|
||||
# may arbitrarily override these programs during configuration.
|
||||
#
|
||||
# To mitigate this issue, we define functions that serve _in place of_ these
|
||||
# programs. This provides two major benefits: it allows us to display a
|
||||
# helpful error when the program cannot be found, and it allows shell
|
||||
# scripts to simply pretend that those programs exist in the environment
|
||||
# without having to worry about an extra layer of abstraction.
|
||||
#
|
||||
# The most notable downside to this approach is that it is not obvious by
|
||||
# looking at a shell script whether we have considered that a program may be
|
||||
# missing, but this ought to be caught by a comprehensive test suite.
|
||||
awk() { __try-run-cfg-prog "@AWK@" "$@"; }
|
||||
sed() { __try-run-cfg-prog "@SED@" "$@"; }
|
||||
grep() { __try-run-cfg-prog "@GREP@" "$@"; }
|
||||
xmllint() { __try-run-cfg-prog "@XMLLINT@" "$@"; }
|
||||
dot() { __try-run-cfg-prog "@DOT@" "$@"; }
|
||||
diff() { __try-run-cfg-prog "@DIFF@" "$@"; }
|
||||
find() { __try-run-cfg-prog "@FIND@" "$@"; }
|
||||
xargs() { __try-run-cfg-prog "@XARGS@" "$@"; }
|
||||
# 'time' is a builtin, so we need a different name
|
||||
time-cmd() { __try-run-cfg-prog "@TIME@" "$@"; }
|
||||
|
||||
# Exit code when bash is unable to locate the requested command.
|
||||
declare -ri EX_CMD_NOT_FOUND=127
|
||||
|
||||
# Attempt to run a program that is configurable via the `configure` script.
|
||||
# If the program cannot be found, then display a helpful error message that
|
||||
# directs the user to the configure script.
|
||||
__try-run-cfg-prog() {
|
||||
local -r prog="${1?Missing program name}"
|
||||
shift
|
||||
|
||||
# The name of the wrapper command is assumed to be the name of the
|
||||
# function that called us (the above functions).
|
||||
local -r name="${FUNCNAME[1]}"
|
||||
|
||||
local -i ex=0
|
||||
|
||||
command "$prog" "$@" || {
|
||||
ex=$?
|
||||
|
||||
if [ "$ex" == "$EX_CMD_NOT_FOUND" ]; then
|
||||
# The goal is to notify the user of a few things:
|
||||
# 1. That they should consult 'configure';
|
||||
# 2. The name of the command that we _tried_ to invoke; and
|
||||
# 3. The name that is usually used to invoke this command.
|
||||
#
|
||||
# That is: '$prog' and '$name' may differ if someone ran
|
||||
# ./configure DIFF=foo
|
||||
# which would try to invoke 'foo' for 'diff'.
|
||||
cat >&2 <<EOF
|
||||
help: the missing program '$prog' originates from 'configure' as the command
|
||||
help: for the program '$name'; did you configure from a different
|
||||
help: environment than the one you are running in now (e.g. a container),
|
||||
hwlp: or did you explicitly specify this command/path via 'configure'?
|
||||
EOF
|
||||
fi
|
||||
}
|
||||
|
||||
return "$ex"
|
||||
}
|
||||
|
||||
|
|
|
@ -146,11 +146,50 @@ test -z "$FEATURES" || {
|
|||
}
|
||||
|
||||
# Other programs used by scripts
|
||||
AC_ARG_VAR([XMLLINT], [xmllint from libxml2])
|
||||
AC_CHECK_PROGS(XMLLINT, [xmllint])
|
||||
test -n "$XMLLINT" || AC_MSG_ERROR([xmllint not found])
|
||||
|
||||
AC_ARG_VAR([DOT], [Graphviz filter for directed graphs])
|
||||
AC_CHECK_PROGS(DOT, [dot])
|
||||
test -n "$DOT" || AC_MSG_ERROR([Graphviz dot not found])
|
||||
|
||||
|
||||
# These programs are typically available, but may not be in a minimal
|
||||
# container, so let's check for them early to help container authors get
|
||||
# their dependencies right and avoid awkward runtime errors.
|
||||
|
||||
AC_ARG_VAR([AWK], [Awk (e.g. Gawk, mawk)])
|
||||
AC_CHECK_PROGS(AWK, [awk])
|
||||
|
||||
AC_ARG_VAR([SED], [sed command])
|
||||
AC_CHECK_PROGS(SED, [sed])
|
||||
|
||||
AC_ARG_VAR([GREP], [grep command])
|
||||
AC_CHECK_PROGS(GREP, [grep])
|
||||
|
||||
AC_ARG_VAR([DIFF], [diff utility (e.g. from GNU diffutils)])
|
||||
AC_CHECK_PROGS(DIFF, [diff])
|
||||
|
||||
AC_ARG_VAR([FIND], [find utility (e.g. from GNU findutils)])
|
||||
AC_CHECK_PROGS(FIND, [find])
|
||||
|
||||
AC_ARG_VAR([XARGS], [xargs utility (e.g. from GNU findutils)])
|
||||
AC_CHECK_PROGS(XARGS, [xargs])
|
||||
|
||||
AC_ARG_VAR([TIME], [time utility (non-shell-builtin)])
|
||||
AC_CHECK_PROGS(TIME, [time])
|
||||
|
||||
# Check for missing programs all at once so that a user can foresee what
|
||||
# other errors may be coming up, rather than having to modify the
|
||||
# environment and re-run configure and repeat.
|
||||
test -n "$XMLLINT" || AC_MSG_ERROR([xmllint not found])
|
||||
test -n "$DOT" || AC_MSG_ERROR([Graphviz dot not found])
|
||||
test -n "$AWK" || AC_MSG_ERROR([awk not found])
|
||||
test -n "$SED" || AC_MSG_ERROR([sed not found])
|
||||
test -n "$GREP" || AC_MSG_ERROR([grep not found])
|
||||
test -n "$DIFF" || AC_MSG_ERROR([diff not found])
|
||||
test -n "$FIND" || AC_MSG_ERROR([find not found])
|
||||
test -n "$XARGS" || AC_MSG_ERROR([xargs not found])
|
||||
test -n "$TIME" || AC_MSG_ERROR([time (non-builtin) not found])
|
||||
|
||||
AC_CONFIG_FILES([Makefile conf.sh])
|
||||
|
||||
|
|
|
@ -0,0 +1,72 @@
|
|||
#!/bin/bash
|
||||
# Copyright (C) 2014-2024 Ryan Specialty, LLC.
|
||||
#
|
||||
# This file is part of TAME.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
# Assert that, for each AC_CHECK_PROGS in 'configure.ac', there is a
|
||||
# corresponding shell function defined for use in shell scripts.
|
||||
# #
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
declare -r mypath=$(dirname "$0")
|
||||
|
||||
# The functions will be defined in here.
|
||||
. "$mypath/../conf.sh"
|
||||
|
||||
declare -r root="$mypath/.."
|
||||
|
||||
# These commands appear in configure.ac as AC_CHECK_PROGS, but they are not
|
||||
# invoked via shell scripts and so should be ignored here.
|
||||
declare -ra excluded_cmds=(cargo rustc)
|
||||
|
||||
expected-fns() {
|
||||
# note that some programs are exempt (since they are not invoked via shell
|
||||
# scripts) and 'time' requires renaming because it is a builtin
|
||||
awk -F'[][ (,]' '/AC_CHECK_PROGS/{print $5}' "$root/configure.ac" \
|
||||
| sans-excluded \
|
||||
| sed 's/^time$/time-cmd/'
|
||||
}
|
||||
|
||||
sans-excluded() {
|
||||
grep -vF "$( IFS=$'\n'; echo "${excluded_cmds[*]}" )"
|
||||
}
|
||||
|
||||
main() {
|
||||
local -i ex=0
|
||||
|
||||
while read prog; do
|
||||
printf "checking for shell function %-15s" "'$prog'..."
|
||||
|
||||
test "$(type -t "$prog")" == function || {
|
||||
echo '[FAIL]'
|
||||
ex=1
|
||||
continue
|
||||
}
|
||||
|
||||
echo '[ OK ]'
|
||||
done < <( expected-fns )
|
||||
|
||||
if [ "$ex" -ne 0 ]; then
|
||||
echo 'fail: every AC_CHECK_PROGS in configure.ac must appear as a function'
|
||||
echo ' in conf.sh.in'.
|
||||
fi
|
||||
|
||||
return "$ex"
|
||||
}
|
||||
|
||||
main "$@"
|
||||
|
|
@ -5,12 +5,9 @@
|
|||
|
||||
set -euo pipefail
|
||||
|
||||
mypath=$(dirname "$0")
|
||||
declare -r 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}"
|
||||
|
@ -48,7 +45,7 @@ timed-tamec() {
|
|||
objty=xmlo-experimental
|
||||
fi
|
||||
|
||||
command time -f "%F/%Rfault %I/%Oio %Mrss %c/%wctx \n%C" -o "$dir/time.log" \
|
||||
time-cmd -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=$?
|
||||
|
@ -86,8 +83,8 @@ test-derive-from-src() {
|
|||
|
||||
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') \
|
||||
diff <(xmllint --format "$dir/expected.xml" || echo 'ERR expected.xml') \
|
||||
<(xmllint --format "$dir/out.xmli" || echo 'ERR out.xmli') \
|
||||
&> "$dir/diff.log"
|
||||
}
|
||||
|
||||
|
@ -111,8 +108,8 @@ test-fixpoint() {
|
|||
|
||||
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') \
|
||||
diff <(xmllint --format "$dir/expected.xml" || echo 'ERR expected.xml') \
|
||||
<(xmllint --format "$dir/out-2.xmli" || echo 'ERR out.xmli') \
|
||||
&> "$dir/diff.log"
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue