summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPatrick McDermott <patrick.mcdermott@libiquity.com>2019-04-22 01:48:57 (EDT)
committer Patrick McDermott <patrick.mcdermott@libiquity.com>2019-04-22 01:48:57 (EDT)
commitd841dc0bfb1d18a2f85f76096d4aebc4d772b88e (patch)
treed3c59eed4e2af1a88b7a6cc7c06f1eee6c4e6110
parent44e452fb3c8cc7a093d72fbc280be3973e627a62 (diff)
parent76885ce7f12b98f0700a3a0535e06425bc1a9aa5 (diff)
Merge branch 'feature/tap-tests'
-rw-r--r--.gitignore8
-rw-r--r--Makefile.am17
-rw-r--r--NEWS1
-rw-r--r--build-aux/tap-driver.sh651
-rwxr-xr-xtests/arch_is_concerned.sh187
-rw-r--r--tests/aux/common.sh71
-rw-r--r--tests/aux/tap-functions.sh229
-rw-r--r--tests/common.sh110
-rw-r--r--tests/local.mk29
-rwxr-xr-xtests/match_arch.sh71
-rwxr-xr-xtests/match_plat.sh63
-rw-r--r--tests/parse_control.common.sh12
-rwxr-xr-xtests/plat_is_concerned.sh135
-rwxr-xr-xtests/reduce_deps.sh148
-rwxr-xr-xtests/resolve_deps.basic.sh9
15 files changed, 1336 insertions, 405 deletions
diff --git a/.gitignore b/.gitignore
index b4b96fa..d10c254 100644
--- a/.gitignore
+++ b/.gitignore
@@ -8,7 +8,8 @@
aclocal.m4
autom4te.cache/
configure
-build-aux/
+build-aux/*
+!build-aux/tap-driver.sh
ChangeLog
INSTALL
Makefile.in
@@ -25,10 +26,11 @@ prokit
locale/*.ms
man/*.[18]
man/*.[18].mdwn
-*-*/
-*-*.tar*
+prokit-*/
+prokit-*.tar*
.builddirstamp
tests/*[^.]??
+!tests/aux/
tests/*.log
tests/*.trs
test-suite.log
diff --git a/Makefile.am b/Makefile.am
index 2d25018..ece0410 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1,6 +1,6 @@
# Process this file with automake to produce an input makefile.
#
-# Copyright (C) 2013-2016 Patrick "P. J." McDermott
+# Copyright (C) 2013-2017 Patrick "P. J." McDermott
#
# This file is part of the ProteanOS Development Kit.
#
@@ -26,6 +26,16 @@ else
PACKAGE_VERSION_GIT = $(PACKAGE_VERSION)
endif
+# PACKAGE_STRING is used in the test suite output and log.
+# PACKAGE_VERSION can't be overridden. Automake ignores it in the IN_GIT
+# conditional (and throws a warning), and setting it to $(PACKAGE_VERSION_GIT)
+# outside the conditional causes PACKAGE_VERSION_GIT to reference itself.
+# VERSION is not set here because it is used by:
+# * Automake's distdir macro
+# * Automake's distdir target (which checks for $(VERSION) in NEWS)
+# * Our release target
+PACKAGE_STRING = $(PACKAGE_NAME) $(PACKAGE_VERSION_GIT)
+
MANUAL = ProteanOS Development Kit Manual
TEXTDOMAIN = $$(printf '%s\n' '$(PACKAGE)' | sed -e 's|-|_|g')
@@ -84,9 +94,12 @@ EXTRA_DIST = \
$(man8_sources) \
scripts/announce-release.sh \
tools/shpp.sh \
- tools/shld.sh
+ tools/shld.sh \
+ build-aux/tap-driver.sh \
+ tests/aux/tap-functions.sh
AM_TESTS_ENVIRONMENT = srcdir=$(top_srcdir) COLOR_TEST_LOGS=$(COLOR_TEST_LOGS)
+LOG_DRIVER = $(SHELL) $(top_srcdir)/build-aux/tap-driver.sh
.builddirstamp:
$(AM_V_GEN)touch .builddirstamp
diff --git a/NEWS b/NEWS
index 5733f1b..545f18b 100644
--- a/NEWS
+++ b/NEWS
@@ -69,6 +69,7 @@ Build system and code quality:
* Various error conditions are now handled more cleanly.
* Uses of the non-portable "%s" date format conversion specifier and
"expr" command have been replaced.
+ * The test suite is now based around the TAP protocol.
ProteanOS Development Kit version 1.1.0
---------------------------------------
diff --git a/build-aux/tap-driver.sh b/build-aux/tap-driver.sh
new file mode 100644
index 0000000..2516e9c
--- /dev/null
+++ b/build-aux/tap-driver.sh
@@ -0,0 +1,651 @@
+#! /bin/sh
+# Copyright (C) 2011-2018 Free Software Foundation, Inc.
+#
+# 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 2, 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 <https://www.gnu.org/licenses/>.
+
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# This file is maintained in Automake, please report
+# bugs to <bug-automake@gnu.org> or send patches to
+# <automake-patches@gnu.org>.
+
+scriptversion=2013-12-23.17; # UTC
+
+# Make unconditional expansion of undefined variables an error. This
+# helps a lot in preventing typo-related bugs.
+set -u
+
+me=tap-driver.sh
+
+fatal ()
+{
+ echo "$me: fatal: $*" >&2
+ exit 1
+}
+
+usage_error ()
+{
+ echo "$me: $*" >&2
+ print_usage >&2
+ exit 2
+}
+
+print_usage ()
+{
+ cat <<END
+Usage:
+ tap-driver.sh --test-name=NAME --log-file=PATH --trs-file=PATH
+ [--expect-failure={yes|no}] [--color-tests={yes|no}]
+ [--enable-hard-errors={yes|no}] [--ignore-exit]
+ [--diagnostic-string=STRING] [--merge|--no-merge]
+ [--comments|--no-comments] [--] TEST-COMMAND
+The '--test-name', '-log-file' and '--trs-file' options are mandatory.
+END
+}
+
+# TODO: better error handling in option parsing (in particular, ensure
+# TODO: $log_file, $trs_file and $test_name are defined).
+test_name= # Used for reporting.
+log_file= # Where to save the result and output of the test script.
+trs_file= # Where to save the metadata of the test run.
+expect_failure=0
+color_tests=0
+merge=0
+ignore_exit=0
+comments=0
+diag_string='#'
+while test $# -gt 0; do
+ case $1 in
+ --help) print_usage; exit $?;;
+ --version) echo "$me $scriptversion"; exit $?;;
+ --test-name) test_name=$2; shift;;
+ --log-file) log_file=$2; shift;;
+ --trs-file) trs_file=$2; shift;;
+ --color-tests) color_tests=$2; shift;;
+ --expect-failure) expect_failure=$2; shift;;
+ --enable-hard-errors) shift;; # No-op.
+ --merge) merge=1;;
+ --no-merge) merge=0;;
+ --ignore-exit) ignore_exit=1;;
+ --comments) comments=1;;
+ --no-comments) comments=0;;
+ --diagnostic-string) diag_string=$2; shift;;
+ --) shift; break;;
+ -*) usage_error "invalid option: '$1'";;
+ esac
+ shift
+done
+
+test $# -gt 0 || usage_error "missing test command"
+
+case $expect_failure in
+ yes) expect_failure=1;;
+ *) expect_failure=0;;
+esac
+
+if test $color_tests = yes; then
+ init_colors='
+ color_map["red"]="" # Red.
+ color_map["grn"]="" # Green.
+ color_map["lgn"]="" # Light green.
+ color_map["blu"]="" # Blue.
+ color_map["mgn"]="" # Magenta.
+ color_map["std"]="" # No color.
+ color_for_result["ERROR"] = "mgn"
+ color_for_result["PASS"] = "grn"
+ color_for_result["XPASS"] = "red"
+ color_for_result["FAIL"] = "red"
+ color_for_result["XFAIL"] = "lgn"
+ color_for_result["SKIP"] = "blu"'
+else
+ init_colors=''
+fi
+
+# :; is there to work around a bug in bash 3.2 (and earlier) which
+# does not always set '$?' properly on redirection failure.
+# See the Autoconf manual for more details.
+:;{
+ (
+ # Ignore common signals (in this subshell only!), to avoid potential
+ # problems with Korn shells. Some Korn shells are known to propagate
+ # to themselves signals that have killed a child process they were
+ # waiting for; this is done at least for SIGINT (and usually only for
+ # it, in truth). Without the `trap' below, such a behaviour could
+ # cause a premature exit in the current subshell, e.g., in case the
+ # test command it runs gets terminated by a SIGINT. Thus, the awk
+ # script we are piping into would never seen the exit status it
+ # expects on its last input line (which is displayed below by the
+ # last `echo $?' statement), and would thus die reporting an internal
+ # error.
+ # For more information, see the Autoconf manual and the threads:
+ # <https://lists.gnu.org/archive/html/bug-autoconf/2011-09/msg00004.html>
+ # <http://mail.opensolaris.org/pipermail/ksh93-integration-discuss/2009-February/004121.html>
+ trap : 1 3 2 13 15
+ if test $merge -gt 0; then
+ exec 2>&1
+ else
+ exec 2>&3
+ fi
+ "$@"
+ echo $?
+ ) | LC_ALL=C ${AM_TAP_AWK-awk} \
+ -v me="$me" \
+ -v test_script_name="$test_name" \
+ -v log_file="$log_file" \
+ -v trs_file="$trs_file" \
+ -v expect_failure="$expect_failure" \
+ -v merge="$merge" \
+ -v ignore_exit="$ignore_exit" \
+ -v comments="$comments" \
+ -v diag_string="$diag_string" \
+'
+# TODO: the usages of "cat >&3" below could be optimized when using
+# GNU awk, and/on on systems that supports /dev/fd/.
+
+# Implementation note: in what follows, `result_obj` will be an
+# associative array that (partly) simulates a TAP result object
+# from the `TAP::Parser` perl module.
+
+## ----------- ##
+## FUNCTIONS ##
+## ----------- ##
+
+function fatal(msg)
+{
+ print me ": " msg | "cat >&2"
+ exit 1
+}
+
+function abort(where)
+{
+ fatal("internal error " where)
+}
+
+# Convert a boolean to a "yes"/"no" string.
+function yn(bool)
+{
+ return bool ? "yes" : "no";
+}
+
+function add_test_result(result)
+{
+ if (!test_results_index)
+ test_results_index = 0
+ test_results_list[test_results_index] = result
+ test_results_index += 1
+ test_results_seen[result] = 1;
+}
+
+# Whether the test script should be re-run by "make recheck".
+function must_recheck()
+{
+ for (k in test_results_seen)
+ if (k != "XFAIL" && k != "PASS" && k != "SKIP")
+ return 1
+ return 0
+}
+
+# Whether the content of the log file associated to this test should
+# be copied into the "global" test-suite.log.
+function copy_in_global_log()
+{
+ for (k in test_results_seen)
+ if (k != "PASS")
+ return 1
+ return 0
+}
+
+function get_global_test_result()
+{
+ if ("ERROR" in test_results_seen)
+ return "ERROR"
+ if ("FAIL" in test_results_seen || "XPASS" in test_results_seen)
+ return "FAIL"
+ all_skipped = 1
+ for (k in test_results_seen)
+ if (k != "SKIP")
+ all_skipped = 0
+ if (all_skipped)
+ return "SKIP"
+ return "PASS";
+}
+
+function stringify_result_obj(result_obj)
+{
+ if (result_obj["is_unplanned"] || result_obj["number"] != testno)
+ return "ERROR"
+
+ if (plan_seen == LATE_PLAN)
+ return "ERROR"
+
+ if (result_obj["directive"] == "TODO")
+ return result_obj["is_ok"] ? "XPASS" : "XFAIL"
+
+ if (result_obj["directive"] == "SKIP")
+ return result_obj["is_ok"] ? "SKIP" : COOKED_FAIL;
+
+ if (length(result_obj["directive"]))
+ abort("in function stringify_result_obj()")
+
+ return result_obj["is_ok"] ? COOKED_PASS : COOKED_FAIL
+}
+
+function decorate_result(result)
+{
+ color_name = color_for_result[result]
+ if (color_name)
+ return color_map[color_name] "" result "" color_map["std"]
+ # If we are not using colorized output, or if we do not know how
+ # to colorize the given result, we should return it unchanged.
+ return result
+}
+
+function report(result, details)
+{
+ if (result ~ /^(X?(PASS|FAIL)|SKIP|ERROR)/)
+ {
+ msg = ": " test_script_name
+ add_test_result(result)
+ }
+ else if (result == "#")
+ {
+ msg = " " test_script_name ":"
+ }
+ else
+ {
+ abort("in function report()")
+ }
+ if (length(details))
+ msg = msg " " details
+ # Output on console might be colorized.
+ print decorate_result(result) msg
+ # Log the result in the log file too, to help debugging (this is
+ # especially true when said result is a TAP error or "Bail out!").
+ print result msg | "cat >&3";
+}
+
+function testsuite_error(error_message)
+{
+ report("ERROR", "- " error_message)
+}
+
+function handle_tap_result()
+{
+ details = result_obj["number"];
+ if (length(result_obj["description"]))
+ details = details " " result_obj["description"]
+
+ if (plan_seen == LATE_PLAN)
+ {
+ details = details " # AFTER LATE PLAN";
+ }
+ else if (result_obj["is_unplanned"])
+ {
+ details = details " # UNPLANNED";
+ }
+ else if (result_obj["number"] != testno)
+ {
+ details = sprintf("%s # OUT-OF-ORDER (expecting %d)",
+ details, testno);
+ }
+ else if (result_obj["directive"])
+ {
+ details = details " # " result_obj["directive"];
+ if (length(result_obj["explanation"]))
+ details = details " " result_obj["explanation"]
+ }
+
+ report(stringify_result_obj(result_obj), details)
+}
+
+# `skip_reason` should be empty whenever planned > 0.
+function handle_tap_plan(planned, skip_reason)
+{
+ planned += 0 # Avoid getting confused if, say, `planned` is "00"
+ if (length(skip_reason) && planned > 0)
+ abort("in function handle_tap_plan()")
+ if (plan_seen)
+ {
+ # Error, only one plan per stream is acceptable.
+ testsuite_error("multiple test plans")
+ return;
+ }
+ planned_tests = planned
+ # The TAP plan can come before or after *all* the TAP results; we speak
+ # respectively of an "early" or a "late" plan. If we see the plan line
+ # after at least one TAP result has been seen, assume we have a late
+ # plan; in this case, any further test result seen after the plan will
+ # be flagged as an error.
+ plan_seen = (testno >= 1 ? LATE_PLAN : EARLY_PLAN)
+ # If testno > 0, we have an error ("too many tests run") that will be
+ # automatically dealt with later, so do not worry about it here. If
+ # $plan_seen is true, we have an error due to a repeated plan, and that
+ # has already been dealt with above. Otherwise, we have a valid "plan
+ # with SKIP" specification, and should report it as a particular kind
+ # of SKIP result.
+ if (planned == 0 && testno == 0)
+ {
+ if (length(skip_reason))
+ skip_reason = "- " skip_reason;
+ report("SKIP", skip_reason);
+ }
+}
+
+function extract_tap_comment(line)
+{
+ if (index(line, diag_string) == 1)
+ {
+ # Strip leading `diag_string` from `line`.
+ line = substr(line, length(diag_string) + 1)
+ # And strip any leading and trailing whitespace left.
+ sub("^[ \t]*", "", line)
+ sub("[ \t]*$", "", line)
+ # Return what is left (if any).
+ return line;
+ }
+ return "";
+}
+
+# When this function is called, we know that line is a TAP result line,
+# so that it matches the (perl) RE "^(not )?ok\b".
+function setup_result_obj(line)
+{
+ # Get the result, and remove it from the line.
+ result_obj["is_ok"] = (substr(line, 1, 2) == "ok" ? 1 : 0)
+ sub("^(not )?ok[ \t]*", "", line)
+
+ # If the result has an explicit number, get it and strip it; otherwise,
+ # automatically assing the next progresive number to it.
+ if (line ~ /^[0-9]+$/ || line ~ /^[0-9]+[^a-zA-Z0-9_]/)
+ {
+ match(line, "^[0-9]+")
+ # The final `+ 0` is to normalize numbers with leading zeros.
+ result_obj["number"] = substr(line, 1, RLENGTH) + 0
+ line = substr(line, RLENGTH + 1)
+ }
+ else
+ {
+ result_obj["number"] = testno
+ }
+
+ if (plan_seen == LATE_PLAN)
+ # No further test results are acceptable after a "late" TAP plan
+ # has been seen.
+ result_obj["is_unplanned"] = 1
+ else if (plan_seen && testno > planned_tests)
+ result_obj["is_unplanned"] = 1
+ else
+ result_obj["is_unplanned"] = 0
+
+ # Strip trailing and leading whitespace.
+ sub("^[ \t]*", "", line)
+ sub("[ \t]*$", "", line)
+
+ # This will have to be corrected if we have a "TODO"/"SKIP" directive.
+ result_obj["description"] = line
+ result_obj["directive"] = ""
+ result_obj["explanation"] = ""
+
+ if (index(line, "#") == 0)
+ return # No possible directive, nothing more to do.
+
+ # Directives are case-insensitive.
+ rx = "[ \t]*#[ \t]*([tT][oO][dD][oO]|[sS][kK][iI][pP])[ \t]*"
+
+ # See whether we have the directive, and if yes, where.
+ pos = match(line, rx "$")
+ if (!pos)
+ pos = match(line, rx "[^a-zA-Z0-9_]")
+
+ # If there was no TAP directive, we have nothing more to do.
+ if (!pos)
+ return
+
+ # Let`s now see if the TAP directive has been escaped. For example:
+ # escaped: ok \# SKIP
+ # not escaped: ok \\# SKIP
+ # escaped: ok \\\\\# SKIP
+ # not escaped: ok \ # SKIP
+ if (substr(line, pos, 1) == "#")
+ {
+ bslash_count = 0
+ for (i = pos; i > 1 && substr(line, i - 1, 1) == "\\"; i--)
+ bslash_count += 1
+ if (bslash_count % 2)
+ return # Directive was escaped.
+ }
+
+ # Strip the directive and its explanation (if any) from the test
+ # description.
+ result_obj["description"] = substr(line, 1, pos - 1)
+ # Now remove the test description from the line, that has been dealt
+ # with already.
+ line = substr(line, pos)
+ # Strip the directive, and save its value (normalized to upper case).
+ sub("^[ \t]*#[ \t]*", "", line)
+ result_obj["directive"] = toupper(substr(line, 1, 4))
+ line = substr(line, 5)
+ # Now get the explanation for the directive (if any), with leading
+ # and trailing whitespace removed.
+ sub("^[ \t]*", "", line)
+ sub("[ \t]*$", "", line)
+ result_obj["explanation"] = line
+}
+
+function get_test_exit_message(status)
+{
+ if (status == 0)
+ return ""
+ if (status !~ /^[1-9][0-9]*$/)
+ abort("getting exit status")
+ if (status < 127)
+ exit_details = ""
+ else if (status == 127)
+ exit_details = " (command not found?)"
+ else if (status >= 128 && status <= 255)
+ exit_details = sprintf(" (terminated by signal %d?)", status - 128)
+ else if (status > 256 && status <= 384)
+ # We used to report an "abnormal termination" here, but some Korn
+ # shells, when a child process die due to signal number n, can leave
+ # in $? an exit status of 256+n instead of the more standard 128+n.
+ # Apparently, both behaviours are allowed by POSIX (2008), so be
+ # prepared to handle them both. See also Austing Group report ID
+ # 0000051 <http://www.austingroupbugs.net/view.php?id=51>
+ exit_details = sprintf(" (terminated by signal %d?)", status - 256)
+ else
+ # Never seen in practice.
+ exit_details = " (abnormal termination)"
+ return sprintf("exited with status %d%s", status, exit_details)
+}
+
+function write_test_results()
+{
+ print ":global-test-result: " get_global_test_result() > trs_file
+ print ":recheck: " yn(must_recheck()) > trs_file
+ print ":copy-in-global-log: " yn(copy_in_global_log()) > trs_file
+ for (i = 0; i < test_results_index; i += 1)
+ print ":test-result: " test_results_list[i] > trs_file
+ close(trs_file);
+}
+
+BEGIN {
+
+## ------- ##
+## SETUP ##
+## ------- ##
+
+'"$init_colors"'
+
+# Properly initialized once the TAP plan is seen.
+planned_tests = 0
+
+COOKED_PASS = expect_failure ? "XPASS": "PASS";
+COOKED_FAIL = expect_failure ? "XFAIL": "FAIL";
+
+# Enumeration-like constants to remember which kind of plan (if any)
+# has been seen. It is important that NO_PLAN evaluates "false" as
+# a boolean.
+NO_PLAN = 0
+EARLY_PLAN = 1
+LATE_PLAN = 2
+
+testno = 0 # Number of test results seen so far.
+bailed_out = 0 # Whether a "Bail out!" directive has been seen.
+
+# Whether the TAP plan has been seen or not, and if yes, which kind
+# it is ("early" is seen before any test result, "late" otherwise).
+plan_seen = NO_PLAN
+
+## --------- ##
+## PARSING ##
+## --------- ##
+
+is_first_read = 1
+
+while (1)
+ {
+ # Involutions required so that we are able to read the exit status
+ # from the last input line.
+ st = getline
+ if (st < 0) # I/O error.
+ fatal("I/O error while reading from input stream")
+ else if (st == 0) # End-of-input
+ {
+ if (is_first_read)
+ abort("in input loop: only one input line")
+ break
+ }
+ if (is_first_read)
+ {
+ is_first_read = 0
+ nextline = $0
+ continue
+ }
+ else
+ {
+ curline = nextline
+ nextline = $0
+ $0 = curline
+ }
+ # Copy any input line verbatim into the log file.
+ print | "cat >&3"
+ # Parsing of TAP input should stop after a "Bail out!" directive.
+ if (bailed_out)
+ continue
+
+ # TAP test result.
+ if ($0 ~ /^(not )?ok$/ || $0 ~ /^(not )?ok[^a-zA-Z0-9_]/)
+ {
+ testno += 1
+ setup_result_obj($0)
+ handle_tap_result()
+ }
+ # TAP plan (normal or "SKIP" without explanation).
+ else if ($0 ~ /^1\.\.[0-9]+[ \t]*$/)
+ {
+ # The next two lines will put the number of planned tests in $0.
+ sub("^1\\.\\.", "")
+ sub("[^0-9]*$", "")
+ handle_tap_plan($0, "")
+ continue
+ }
+ # TAP "SKIP" plan, with an explanation.
+ else if ($0 ~ /^1\.\.0+[ \t]*#/)
+ {
+ # The next lines will put the skip explanation in $0, stripping
+ # any leading and trailing whitespace. This is a little more
+ # tricky in truth, since we want to also strip a potential leading
+ # "SKIP" string from the message.
+ sub("^[^#]*#[ \t]*(SKIP[: \t][ \t]*)?", "")
+ sub("[ \t]*$", "");
+ handle_tap_plan(0, $0)
+ }
+ # "Bail out!" magic.
+ # Older versions of prove and TAP::Harness (e.g., 3.17) did not
+ # recognize a "Bail out!" directive when preceded by leading
+ # whitespace, but more modern versions (e.g., 3.23) do. So we
+ # emulate the latter, "more modern" behaviour.
+ else if ($0 ~ /^[ \t]*Bail out!/)
+ {
+ bailed_out = 1
+ # Get the bailout message (if any), with leading and trailing
+ # whitespace stripped. The message remains stored in `$0`.
+ sub("^[ \t]*Bail out![ \t]*", "");
+ sub("[ \t]*$", "");
+ # Format the error message for the
+ bailout_message = "Bail out!"
+ if (length($0))
+ bailout_message = bailout_message " " $0
+ testsuite_error(bailout_message)
+ }
+ # Maybe we have too look for dianogtic comments too.
+ else if (comments != 0)
+ {
+ comment = extract_tap_comment($0);
+ if (length(comment))
+ report("#", comment);
+ }
+ }
+
+## -------- ##
+## FINISH ##
+## -------- ##
+
+# A "Bail out!" directive should cause us to ignore any following TAP
+# error, as well as a non-zero exit status from the TAP producer.
+if (!bailed_out)
+ {
+ if (!plan_seen)
+ {
+ testsuite_error("missing test plan")
+ }
+ else if (planned_tests != testno)
+ {
+ bad_amount = testno > planned_tests ? "many" : "few"
+ testsuite_error(sprintf("too %s tests run (expected %d, got %d)",
+ bad_amount, planned_tests, testno))
+ }
+ if (!ignore_exit)
+ {
+ # Fetch exit status from the last line.
+ exit_message = get_test_exit_message(nextline)
+ if (exit_message)
+ testsuite_error(exit_message)
+ }
+ }
+
+write_test_results()
+
+exit 0
+
+} # End of "BEGIN" block.
+'
+
+# TODO: document that we consume the file descriptor 3 :-(
+} 3>"$log_file"
+
+test $? -eq 0 || fatal "I/O or internal error"
+
+# Local Variables:
+# mode: shell-script
+# sh-indentation: 2
+# eval: (add-hook 'before-save-hook 'time-stamp)
+# time-stamp-start: "scriptversion="
+# time-stamp-format: "%:y-%02m-%02d.%02H"
+# time-stamp-time-zone: "UTC0"
+# time-stamp-end: "; # UTC"
+# End:
diff --git a/tests/arch_is_concerned.sh b/tests/arch_is_concerned.sh
index 837d3be..7614dad 100755
--- a/tests/arch_is_concerned.sh
+++ b/tests/arch_is_concerned.sh
@@ -1,6 +1,6 @@
# arch_is_concerned() tests
#
-# Copyright (C) 2014 Patrick "P. J." McDermott
+# Copyright (C) 2014, 2018, 2019 Patrick McDermott
#
# This file is part of the ProteanOS Development Kit.
#
@@ -18,68 +18,157 @@
# along with the ProteanOS Development Kit. If not, see
# <http://www.gnu.org/licenses/>.
-do_test()
-{
- local host_arch="${1}"
- local arches="${2}"
- local result="${3}"
-
- if arch_is_concerned "${host_arch}" "${arches}"; then
- if ! ${result}; then
- printf 'False positive:\n'
- printf ' Host architecture: "%s"\n' "${host_arch}"
- printf ' Package architectures: "%s"\n' "${arches}"
- tests_es=1
- fi
- else
- if ${result}; then
- printf 'False negative:\n'
- printf ' Host architecture: "%s"\n' "${host_arch}"
- printf ' Package architectures: "%s"\n' "${arches}"
- tests_es=1
- fi
- fi
-}
-
main()
{
- local arches=
+ plan_ 24
# Architecture: all
- arches='all'
- do_test 'amd64-linux-glibc' "${arches}" false
- do_test 'i686-linux-glibc' "${arches}" false
- do_test 'all' "${arches}" true
+ command_ok_ \
+ 'HOST "amd64-linux-glibc" DOES NOT MATCH ARCH "all"' -- \
+ not arch_is_concerned \
+ 'amd64-linux-glibc' \
+ 'all'
+ command_ok_ \
+ 'HOST "i686-linux-glibc" DOES NOT MATCH ARCH "all"' -- \
+ not arch_is_concerned \
+ 'i686-linux-glibc' \
+ 'all'
+ command_ok_ \
+ 'HOST "all" DOES MATCH ARCH "all"' -- \
+ arch_is_concerned \
+ 'all' \
+ 'all'
# Architecture: any
- arches='any'
- do_test 'amd64-linux-glibc' "${arches}" true
- do_test 'i686-linux-glibc' "${arches}" true
- do_test 'all' "${arches}" false
+ command_ok_ \
+ 'HOST "amd64-linux-glibc" DOES MATCH ARCH "any"' -- \
+ arch_is_concerned \
+ 'amd64-linux-glibc' \
+ 'any'
+ command_ok_ \
+ 'HOST "i686-linux-glibc" DOES MATCH ARCH "any"' -- \
+ arch_is_concerned \
+ 'i686-linux-glibc' \
+ 'any'
+ command_ok_ \
+ 'HOST "all" DOES NOT MATCH ARCH "any"' -- \
+ not arch_is_concerned \
+ 'all' \
+ 'any'
# Architecture: amd64-linux-glibc
- arches='amd64-linux-glibc'
- do_test 'amd64-linux-glibc' "${arches}" true
- do_test 'i686-linux-glibc' "${arches}" false
- do_test 'all' "${arches}" false
+ command_ok_ \
+ 'HOST "amd64-linux-glibc" DOES MATCH ARCH '$(: \
+ )'"amd64-linux-glibc"' -- \
+ arch_is_concerned \
+ 'amd64-linux-glibc' \
+ 'amd64-linux-glibc'
+ command_ok_ \
+ 'HOST "i686-linux-glibc" DOES NOT MATCH ARCH '$(: \
+ )'"amd64-linux-glibc"' -- \
+ not arch_is_concerned \
+ 'i686-linux-glibc' \
+ 'amd64-linux-glibc'
+ command_ok_ \
+ 'HOST "all" DOES NOT MATCH ARCH "amd64-linux-glibc"' -- \
+ not arch_is_concerned \
+ 'all' \
+ 'amd64-linux-glibc'
# Architecture: !amd64-linux-glibc
- arches='!amd64-linux-glibc'
- do_test 'amd64-linux-glibc' "${arches}" false
- do_test 'i686-linux-glibc' "${arches}" true
- do_test 'all' "${arches}" false
+ command_ok_ \
+ 'HOST "amd64-linux-glibc" DOES NOT MATCH ARCH '$(: \
+ )'"!amd64-linux-glibc"' -- \
+ not arch_is_concerned \
+ 'amd64-linux-glibc' \
+ '!amd64-linux-glibc'
+ command_ok_ \
+ 'HOST "i686-linux-glibc" DOES MATCH ARCH '$(: \
+ )'"!amd64-linux-glibc"' -- \
+ arch_is_concerned \
+ 'i686-linux-glibc' \
+ '!amd64-linux-glibc'
+ command_ok_ \
+ 'HOST "all" DOES NOT MATCH ARCH "!amd64-linux-glibc"' -- \
+ not arch_is_concerned \
+ 'all' \
+ '!amd64-linux-glibc'
# Architecture: amd64-linux-glibc cortexa8-linux-glibc
- arches='amd64-linux-glibc cortexa8-linux-glibc'
- do_test 'amd64-linux-glibc' "${arches}" true
- do_test 'i686-linux-glibc' "${arches}" false
- do_test 'all' "${arches}" false
+ command_ok_ \
+ 'HOST "amd64-linux-glibc" DOES MATCH ARCH '$(: \
+ )'"amd64-linux-glibc cortexa8-linux-glibc"' -- \
+ arch_is_concerned \
+ 'amd64-linux-glibc' \
+ 'amd64-linux-glibc cortexa8-linux-glibc'
+ command_ok_ \
+ 'HOST "i686-linux-glibc" DOES MATCH ARCH '$(: \
+ )'"amd64-linux-glibc cortexa8-linux-glibc"' -- \
+ not arch_is_concerned \
+ 'i686-linux-glibc' \
+ 'amd64-linux-glibc cortexa8-linux-glibc'
+ command_ok_ \
+ 'HOST "all" DOES MATCH ARCH '$(: \
+ )'"amd64-linux-glibc cortexa8-linux-glibc"' -- \
+ not arch_is_concerned \
+ 'all' \
+ 'amd64-linux-glibc cortexa8-linux-glibc'
# Architecture: amd64-linux-glibc all
- arches='amd64-linux-glibc all'
- do_test 'amd64-linux-glibc' "${arches}" true
- do_test 'i686-linux-glibc' "${arches}" false
- do_test 'all' "${arches}" true
+ command_ok_ \
+ 'HOST "amd64-linux-glibc" DOES MATCH ARCH '$(: \
+ )'"amd64-linux-glibc all"' -- \
+ arch_is_concerned \
+ 'amd64-linux-glibc' \
+ 'amd64-linux-glibc all'
+ command_ok_ \
+ 'HOST "i686-linux-glibc" DOES NOT MATCH ARCH '$(: \
+ )'"amd64-linux-glibc all"' --\
+ not arch_is_concerned \
+ 'i686-linux-glibc' \
+ 'amd64-linux-glibc all'
+ command_ok_ \
+ 'HOST "all" DOES MATCH ARCH "amd64-linux-glibc all"' -- \
+ arch_is_concerned \
+ 'all' \
+ 'amd64-linux-glibc all'
+
+ # Architecture: amd64-any-any
+ command_ok_ \
+ 'HOST "amd64-linux-glibc" DOES NOT MATCH ARCH "amd64-any-any"' -- \
+ arch_is_concerned \
+ 'amd64-linux-glibc' \
+ 'amd64-any-any'
+ command_ok_ \
+ 'HOST "i686-linux-glibc" DOES MATCH ARCH "amd64-any-any"' -- \
+ not arch_is_concerned \
+ 'i686-linux-glibc' \
+ 'amd64-any-any'
+ command_ok_ \
+ 'HOST "all" DOES NOT MATCH ARCH "amd64-any-any"' -- \
+ not arch_is_concerned \
+ 'all' \
+ 'amd64-any-any'
+
+ # Architecture: cortexa8-any-any i686-any-any
+ command_ok_ \
+ 'HOST "amd64-linux-glibc" DOES NOT MATCH ARCH '$(: \
+ )'"cortexa8-any-any i686-any-any"' -- \
+ not arch_is_concerned \
+ 'amd64-linux-glibc' \
+ 'cortexa8-any-any i686-any-any'
+ command_ok_ \
+ 'HOST "i686-linux-glibc" DOES MATCH ARCH '$(: \
+ )'"cortexa8-any-any i686-any-any"' -- \
+ arch_is_concerned \
+ 'i686-linux-glibc' \
+ 'cortexa8-any-any i686-any-any'
+ command_ok_ \
+ 'HOST "all" DOES NOT MATCH ARCH '$(: \
+ )'"cortexa8-any-any i686-any-any"' -- \
+ not arch_is_concerned \
+ 'all' \
+ 'cortexa8-any-any i686-any-any'
return 0
}
diff --git a/tests/aux/common.sh b/tests/aux/common.sh
new file mode 100644
index 0000000..27db133
--- /dev/null
+++ b/tests/aux/common.sh
@@ -0,0 +1,71 @@
+# Common testsuite functions
+#
+# Copyright (C) 2019 Patrick McDermott
+#
+# This file is part of the ProteanOS Development Kit.
+#
+# The ProteanOS Development Kit 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.
+#
+# The ProteanOS Development Kit 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 the ProteanOS Development Kit. If not, see
+# <http://www.gnu.org/licenses/>.
+
+LF='
+'
+
+# is_diff() is based on cmd_is() from opkbuild 4.0.2, with test results passed
+# by argument and context added to the diagnostic output.
+is_diff()
+{
+ local description="${1}"
+ local got="${2}"
+ local exp="${3}"
+ shift 3
+ local ok=
+ local diag=
+ local eof=
+
+ ok=true
+ diag=''
+ exec 3<<-EOF
+ ${got}
+ EOF
+ exec 4<<-EOF
+ ${exp}
+ EOF
+ while :; do
+ eof=0
+ read -r got 0<&3 || eof=$((${eof} + 1))
+ read -r exp 0<&4 || eof=$((${eof} + 2))
+ [ ${eof} -eq 3 ] && break
+ if [ x"${got}" = x"${exp}" ]; then
+ diag="${diag} '${got}'${LF}"
+ else
+ ok=false
+ diag="${diag} got: '${got}'${LF}"
+ diag="${diag} expected: '${exp}'${LF}"
+ fi
+ done
+ exec 3<&-
+ exec 4<&-
+
+ if ${ok}; then
+ ok_ -- "${description}"
+ else
+ not_ok_ -- "${description}"
+ diag_ " Failed test '${description}'"
+ while IFS='' read -r diag; do
+ diag_ "${diag}"
+ done <<-EOF
+ ${diag}
+ EOF
+ fi
+}
diff --git a/tests/aux/tap-functions.sh b/tests/aux/tap-functions.sh
new file mode 100644
index 0000000..dd634b3
--- /dev/null
+++ b/tests/aux/tap-functions.sh
@@ -0,0 +1,229 @@
+# -*- shell-script -*-
+#
+# Copyright (C) 2011-2018 Free Software Foundation, Inc.
+#
+# 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 2, 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 <https://www.gnu.org/licenses/>.
+
+# Helper functions used by TAP-producing tests of the Automake testsuite.
+
+#
+# IMPORTANT: All the functions defined in this file can *not* be used
+# from within a subshell, unless explicitly noted otherwise.
+#
+
+# The counts of the TAP test results seen so far: total count and
+# per-result counts.
+tap_count_=0
+tap_pass_count_=0
+tap_skip_count_=0
+tap_fail_count_=0
+tap_xfail_count_=0
+tap_xpass_count_=0
+
+# not COMMAND [ARGS...]
+# ---------------------
+# Run the given command and invert its exit status.
+not () { ! "$@"; }
+
+# plan_ [unknown|later|lazy|now|NUMBER-OF-PLANNED-TESTS]
+# ------------------------------------------------------
+# Print a TAP plan for the given number of tests. This must be called
+# before reporting any test result. If called with the special argument
+# "unknown" or "later", it will do nothing, expecting the calling script
+# to declare the plan later. If called with the special argument "lazy"
+# or "now", it will print a TAP plan that accounts for the number of tests
+# seen so far.
+plan_ ()
+{
+ if test $# -eq 0; then
+ bailout_ "plan_: missing argument"
+ elif test $# -ge 2; then
+ bailout_ "plan_: too many arguments"
+ elif test x"$planned_" != x"none" && test x"$planned_" != x"later"; then
+ bailout_ "plan_: called to many times"
+ elif test x"$1" = x"unknown" || test x"$1" = x"later"; then
+ # This means we want to get back later to declaring the TAP plan.
+ planned_=later
+ return 0
+ elif test x"$1" = x"lazy" || test x"$1" = x"now"; then
+ planned_=$tap_count_ # Number of test results seen so far.
+ elif test $1 -ge 0; then
+ planned_=$1
+ else
+ bailout_ "plan_: invalid argument '$1'"
+ fi
+ echo "1..$planned_"
+}
+planned_=none
+
+# diag_ [EXPLANATION]
+# ------------------
+# Report the given text as TAP diagnostic. Assumes the string denoting
+# TAP diagnostic lines is stored in the '$diag_string_' variable; this is
+# done to allow better interplay with TAP drivers that allow such a string
+# to be configured.
+diag_ ()
+{
+ test $# -eq 0 || echo "$diag_string_ $*"
+}
+
+# Used by the 'diag_' function above. User-overridable.
+diag_string_="#"
+
+# warn_ [EXPLANATION]
+# ------------------
+# Give a warning (using TAP diagnostic).
+warn_ ()
+{
+ case $# in
+ 0) diag_ "WARNING: (unknown warning)";;
+ *) diag_ "WARNING: $*";;
+ esac
+}
+
+# result_ RESULT [-D DIRECTIVE] [-r REASON] [--] [DESCRIPTION...]
+# ---------------------------------------------------------------
+# Report a test case with the given RESULT (valid values are "ok" and
+# "not ok") and the given DESCRIPTION (if any). If DIRECTIVE is given
+# and non-empty (valid values being "TODO" and "SKIP"), it will be
+# reported too, with the REASON (if given) appended.
+result_ ()
+{
+ test $# -gt 0 || bailout_ "result_: missing argument"
+ tap_result_=$1; shift
+ case $tap_result_ in
+ "ok"|"not ok") ;;
+ *) bailout_ "result_: invalid result '$tap_result'" ;;
+ esac
+ tap_directive_= tap_reason_=
+ while test $# -gt 0; do
+ case $1 in
+ -D|--directive) tap_directive_=$2; shift;;
+ -r|--reason) tap_reason_=$2; shift;;
+ --) shift; break;;
+ -*) bailout_ "result_: invalid option '$1'";;
+ *) break;;
+ esac
+ shift
+ done
+ case $tap_directive_ in
+ ""|TODO|SKIP) ;;
+ *) bailout_ "result_: invalid directive '$directive_'" ;;
+ esac
+ tap_count_=$(($tap_count_ + 1))
+ case $tap_result_,$tap_directive_ in
+ ok,) # Passed.
+ tap_pass_count_=$(($tap_pass_count_ + 1)) ;;
+ not\ ok,TODO) # Expected failure.
+ tap_xfail_count_=$(($tap_xfail_count_ + 1)) ;;
+ not\ ok,*) # Failed.
+ tap_fail_count_=$(($tap_fail_count_ + 1)) ;;
+ ok,TODO) # Unexpected pass.
+ tap_xpass_count_=$(($tap_xpass_count_ + 1)) ;;
+ ok,SKIP) # Skipped.
+ tap_skip_count_=$(($tap_skip_count_ + 1)) ;;
+ *) # Can't happen.
+ bailout_ "internal error in 'result_'" ;;
+ esac
+ tap_text_="$tap_result_ $tap_count_"
+ if test x"$*" != x; then
+ tap_text_="$tap_text_ - $*"
+ fi
+ if test x"$tap_directive_" != x; then
+ tap_text_="$tap_text_ # $tap_directive_"${tap_reason_:+" $tap_reason_"}
+ fi
+ printf '%s\n' "$tap_text_"
+}
+
+# Shorthands for common usages of 'result_'.
+ok_ () { result_ 'ok' ${1+"$@"}; }
+not_ok_ () { result_ 'not ok' ${1+"$@"}; }
+skip_ () { result_ 'ok' -D SKIP ${1+"$@"}; }
+
+# skip_row_ COUNT [-r REASON] [--] [DESCRIPTION...]
+# -------------------------------------------------
+# Report a COUNT of skipped test, with the given reason and descriptions
+# (if any). Useful to avoid cascade failures in case a fair number of
+# tests depend on an earlier one that failed.
+skip_row_ ()
+{
+ skip_count_=$1; shift
+ for i_ in $(seq_ $skip_count_); do skip_ ${1+"$@"}; done
+}
+
+# skip_all_ [REASON ...]
+# ----------------------
+# Skip all the tests in a test script. Must be used before calling 'plan_'
+# or reporting any test result. Can't be used from within a subshell.
+skip_all_ ()
+{
+ echo "1..0 # SKIP" ${1+"$@"}
+ planned_=0
+ exit 0
+}
+
+# bailout_ [REASON ...]
+# ---------------------
+# Stop the execution of the current test suite right now, due to an
+# unrecoverable error. Can be called at any point, but cannot be used
+# from within a subshell.
+bailout_ ()
+{
+ echo 'Bail out!' ${1+"$@"}
+ exit 99
+}
+
+# fatal_ [REASON ...]
+# -------------------
+# Same as 'bailout_'; for compatibility with 'plain-functions.sh'.
+fatal_ ()
+{
+ bailout_ ${1+"$@"}
+}
+
+# framework_failure_ [REASON ...]
+# -------------------------------
+# Stop the execution of the current test suite right now, due to an
+# unrecoverable error in the set-up of the test case. Can be called
+# at any point, but cannot be used from within a subshell.
+framework_failure_ ()
+{
+ bailout_ "set-up failure"${1+": $*"}
+}
+
+# command_ok_ TEST-DESCRIPTION [OPTIONS..] [--] CMD [ARGS...]
+# -----------------------------------------------------------
+# Helper subroutine for when a TAP result must be determined by the
+# outcome of a command.
+command_ok_ ()
+{
+ tap_directive_= tap_reason_=
+ test $# -gt 0 || bailout_ "command_ok_: missing argument"
+ tap_description_=$1; shift
+ while test $# -gt 0; do
+ case $1 in
+ -D|--directive) tap_directive_=$2; shift;;
+ -r|--reason) tap_reason_=$2; shift;;
+ --) shift; break;;
+ -*) bailout_ "command_ok_: invalid option '$1'";;
+ *) break;;
+ esac
+ shift
+ done
+ tap_result_="ok"; "$@" || tap_result_="not ok"
+ result_ "$tap_result_" -D "$tap_directive_" -r "$tap_reason_" \
+ -- "$tap_description_"
+}
+
+:
diff --git a/tests/common.sh b/tests/common.sh
deleted file mode 100644
index 293dc7d..0000000
--- a/tests/common.sh
+++ /dev/null
@@ -1,110 +0,0 @@
-# Common testsuite functions
-#
-# Copyright (C) 2013, 2014 Patrick "P. J." McDermott
-#
-# This file is part of the ProteanOS Development Kit.
-#
-# The ProteanOS Development Kit 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.
-#
-# The ProteanOS Development Kit 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 the ProteanOS Development Kit. If not, see
-# <http://www.gnu.org/licenses/>.
-
-tests_es=0
-atexit()
-{
- local es=${?}
-
- if [ ${es} -ne 0 ]; then
- exit ${es}
- else
- exit ${tests_es}
- fi
-}
-trap atexit EXIT
-
-in_place=true
-builddir='.'
-
-assert()
-{
- if ! eval "${@}"; then
- warn 'Assertion failed: %s\n' "${*}"
- tests_es=1
- fi
-}
-
-if [ "x${COLOR_TEST_LOGS:-no}" = 'xno' ]; then
- red= grn= lgn= blu= mgn= std=
-else
- red='' # Red.
- grn='' # Green.
- lgn='' # Light green.
- blu='' # Blue.
- mgn='' # Magenta.
- std='' # No color.
-fi
-
-test_diff()
-{
- local good_results="${1}"
- local test_results="${2}"
- local line_no=
- local errors=
- local good_line=
- local test_line=
- local line=
-
- printf 'Diff:\n'
- exec 3<<-EOF
- ${good_results}
- EOF
- exec 4<<-EOF
- ${test_results}
- EOF
- line_no=0
- while :; do
- line_no=$(($line_no + 1))
- errors=0
- read -r good_line <&3 || errors=$(($errors + 1))
- read -r test_line <&4 || errors=$(($errors + 1))
- [ ${errors} -eq 2 ] && break
- if [ "x${good_line}" = "x${test_line}" ]; then
- printf '%3d %s\n' ${line_no} "${good_line}"
- else
- printf '%3d %s-%s%s\n' ${line_no} "${red}" \
- "${good_line}" "${std}"
- printf '%3d %s+%s%s\n' ${line_no} "${grn}" \
- "${test_line}" "${std}"
- tests_es=1
- fi
- done
- exec 3<&-
- exec 4<&-
-
- printf '\nExpected results:\n'
- line_no=0
- while read -r line; do
- line_no=$(($line_no + 1))
- printf '%3d %s\n' ${line_no} "${line}"
- done <<-EOF
- ${good_results}
- EOF
- printf '\nTest results:\n'
- line_no=0
- while read -r line; do
- line_no=$(($line_no + 1))
- printf '%3d %s\n' ${line_no} "${line}"
- done <<-EOF
- ${test_results}
- EOF
- printf '\n'
-}
diff --git a/tests/local.mk b/tests/local.mk
index 6eb9878..42ac039 100644
--- a/tests/local.mk
+++ b/tests/local.mk
@@ -1,8 +1,6 @@
check_PROGRAMS = \
tests/parse_control.basic \
tests/resolve_deps.basic \
- tests/match_arch \
- tests/match_plat \
tests/arch_is_concerned \
tests/plat_is_concerned \
tests/reduce_deps
@@ -12,7 +10,9 @@ TESTS = $(check_PROGRAMS)
tests_parse_control_basic_SOURCES = \
tests/parse_control.basic.sh \
tests/parse_control.common.sh \
- tests/common.sh \
+ tests/aux/common.sh \
+ tests/aux/tap-functions.sh \
+ src/locale.sh \
src/output.sh \
src/control.sh
tests_parse_control_basic_LDADD = $(tests_parse_control_basic_SOURCES:.sh=.sho)
@@ -20,42 +20,29 @@ CLEANFILES += $(tests_parse_control_basic_LDADD)
tests_resolve_deps_basic_SOURCES = \
tests/resolve_deps.basic.sh \
- tests/common.sh \
+ tests/aux/common.sh \
+ tests/aux/tap-functions.sh \
src/deps.sh
tests_resolve_deps_basic_LDADD = $(tests_resolve_deps_basic_SOURCES:.sh=.sho)
CLEANFILES += $(tests_resolve_deps_basic_LDADD)
-tests_match_arch_SOURCES = \
- tests/match_arch.sh \
- tests/common.sh \
- src/archplat.sh
-tests_match_arch_LDADD = $(tests_match_arch_SOURCES:.sh=.sho)
-CLEANFILES += $(tests_match_arch_LDADD)
-
-tests_match_plat_SOURCES = \
- tests/match_plat.sh \
- tests/common.sh \
- src/archplat.sh
-tests_match_plat_LDADD = $(tests_match_plat_SOURCES:.sh=.sho)
-CLEANFILES += $(tests_match_plat_LDADD)
-
tests_arch_is_concerned_SOURCES = \
tests/arch_is_concerned.sh \
- tests/common.sh \
+ tests/aux/tap-functions.sh \
src/archplat.sh
tests_arch_is_concerned_LDADD = $(tests_arch_is_concerned_SOURCES:.sh=.sho)
CLEANFILES += $(tests_arch_is_concerned_LDADD)
tests_plat_is_concerned_SOURCES = \
tests/plat_is_concerned.sh \
- tests/common.sh \
+ tests/aux/tap-functions.sh \
src/archplat.sh
tests_plat_is_concerned_LDADD = $(tests_plat_is_concerned_SOURCES:.sh=.sho)
CLEANFILES += $(tests_plat_is_concerned_LDADD)
tests_reduce_deps_SOURCES = \
tests/reduce_deps.sh \
- tests/common.sh \
+ tests/aux/tap-functions.sh \
src/deps.sh \
src/archplat.sh
tests_reduce_deps_LDADD = $(tests_reduce_deps_SOURCES:.sh=.sho)
diff --git a/tests/match_arch.sh b/tests/match_arch.sh
deleted file mode 100755
index 2d3693b..0000000
--- a/tests/match_arch.sh
+++ /dev/null
@@ -1,71 +0,0 @@
-# match_arch() tests
-#
-# Copyright (C) 2014 Patrick "P. J." McDermott
-#
-# This file is part of the ProteanOS Development Kit.
-#
-# The ProteanOS Development Kit 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.
-#
-# The ProteanOS Development Kit 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 the ProteanOS Development Kit. If not, see
-# <http://www.gnu.org/licenses/>.
-
-do_test()
-{
- local arch="${1}"
- local arch_field="${2}"
- local result="${3}"
-
- if match_arch "${arch}" "${arch_field}"; then
- if [ "x${result}" = 'xfalse' ]; then
- printf 'False positive:\n'
- printf ' arch: %s\n arch_field: %s\n' \
- "${arch}" "${arch_field}"
- tests_es=1
- fi
- else
- if [ "x${result}" = 'xtrue' ]; then
- printf 'False negative:\n'
- printf ' arch: %s\n arch_field: %s\n' \
- "${arch}" "${arch_field}"
- tests_es=1
- fi
- fi
-}
-
-main()
-{
- do_test all 'all' true
-
- do_test foo-bar-baz 'any' true
-
- do_test foo-bar-baz 'any all' true
-
- do_test all 'any all' true
-
- do_test foo-bar-baz 'foo-bar-baz' true
-
- do_test foo-bar-baz 'foo-any-any' true
-
- do_test foo-bar-baz 'foo-bar-qux' false
-
- do_test foo-bar-baz 'any-qux-any any-bar-any' true
-
- do_test foo-bar-baz 'any-qux-any any-quux-any' false
-
- do_test all 'any' false
-
- do_test any 'all' false
-
- do_test all 'foo-any-any' false
-
- return 0
-}
diff --git a/tests/match_plat.sh b/tests/match_plat.sh
deleted file mode 100755
index 039f76a..0000000
--- a/tests/match_plat.sh
+++ /dev/null
@@ -1,63 +0,0 @@
-# match_plat() tests
-#
-# Copyright (C) 2014 Patrick "P. J." McDermott
-#
-# This file is part of the ProteanOS Development Kit.
-#
-# The ProteanOS Development Kit 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.
-#
-# The ProteanOS Development Kit 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 the ProteanOS Development Kit. If not, see
-# <http://www.gnu.org/licenses/>.
-
-do_test()
-{
- local plat="${1}"
- local plat_field="${2}"
- local result="${3}"
-
- if match_plat "${plat}" "${plat_field}"; then
- if [ "x${result}" = 'xfalse' ]; then
- printf 'False positive:\n'
- printf ' plat: %s\n plat_field: %s\n' \
- "${plat}" "${plat_field}"
- tests_es=1
- fi
- else
- if [ "x${result}" = 'xtrue' ]; then
- printf 'False negative:\n'
- printf ' plat: %s\n plat_field: %s\n' \
- "${plat}" "${plat_field}"
- tests_es=1
- fi
- fi
-}
-
-main()
-{
- do_test all 'all' true
-
- do_test dev 'any' true
-
- do_test dev 'any all' true
-
- do_test all 'any all' true
-
- do_test dev 'dev' true
-
- do_test dev 'ao751h' false
-
- do_test all 'any' false
-
- do_test any 'all' false
-
- return 0
-}
diff --git a/tests/parse_control.common.sh b/tests/parse_control.common.sh
index 9eee27b..c084cee 100644
--- a/tests/parse_control.common.sh
+++ b/tests/parse_control.common.sh
@@ -1,6 +1,6 @@
# Common parse_control() tests functions
#
-# Copyright (C) 2014 Patrick "P. J." McDermott
+# Copyright (C) 2014 Patrick McDermott
#
# This file is part of the ProteanOS Development Kit.
#
@@ -18,8 +18,6 @@
# along with the ProteanOS Development Kit. If not, see
# <http://www.gnu.org/licenses/>.
-load_locale
-
HT=' '
LF='
'
@@ -38,13 +36,19 @@ para()
main()
{
+ plan_ 1
+
+ in_place=true
+ builddir='.'
+ load_locale
+
parse_control - field para "${req_fields}" <<-EOF
${packages}
EOF
printf 'Required fields: %s\n\n' "${req_fields}"
- test_diff "${results}" "${test_results}"
+ is_diff 'parse_control() paragraphs' "${results}" "${test_results}"
return 0
}
diff --git a/tests/plat_is_concerned.sh b/tests/plat_is_concerned.sh
index 120aa5a..0905a22 100755
--- a/tests/plat_is_concerned.sh
+++ b/tests/plat_is_concerned.sh
@@ -1,6 +1,6 @@
# plat_is_concerned() tests
#
-# Copyright (C) 2014 Patrick "P. J." McDermott
+# Copyright (C) 2014, 2018, 2019 Patrick McDermott
#
# This file is part of the ProteanOS Development Kit.
#
@@ -18,60 +18,111 @@
# along with the ProteanOS Development Kit. If not, see
# <http://www.gnu.org/licenses/>.
-do_test()
-{
- local host_plat="${1}"
- local plats="${2}"
- local result="${3}"
-
- if plat_is_concerned "${host_plat}" "${plats}"; then
- if ! ${result}; then
- printf 'False positive:\n'
- printf ' Host platform: "%s"\n' "${host_plat}"
- printf ' Package platforms: "%s"\n' "${plats}"
- tests_es=1
- fi
- else
- if ${result}; then
- printf 'False negative:\n'
- printf ' Host platform: "%s"\n' "${host_plat}"
- printf ' Package platforms: "%s"\n' "${plats}"
- tests_es=1
- fi
- fi
-}
-
main()
{
+ plan_ 18
+
# Platform: all
- do_test dev 'all' false
- do_test ao751h 'all' false
- do_test all 'all' true
+ command_ok_ \
+ 'HOST "dev" DOES NOT MATCH PLAT "all"' -- \
+ not plat_is_concerned \
+ 'dev' \
+ 'all'
+ command_ok_ \
+ 'HOST "ao751h" DOES NOT MATCH PLAT "all"' -- \
+ not plat_is_concerned \
+ 'ao751h' \
+ 'all'
+ command_ok_ \
+ 'HOST "all" DOES MATCH PLAT "all"' -- \
+ plat_is_concerned \
+ 'all' \
+ 'all'
# Platform: any
- do_test dev 'any' true
- do_test ao751h 'any' true
- do_test all 'any' false
+ command_ok_ \
+ 'HOST "dev" DOES MATCH PLAT "any"' -- \
+ plat_is_concerned \
+ 'dev' \
+ 'any'
+ command_ok_ \
+ 'HOST "ao751h" DOES MATCH PLAT "any"' -- \
+ plat_is_concerned \
+ 'ao751h' \
+ 'any'
+ command_ok_ \
+ 'HOST "all" DOES NOT MATCH PLAT "any"' -- \
+ not plat_is_concerned \
+ 'all' \
+ 'any'
# Platform: dev
- do_test dev 'dev' true
- do_test ao751h 'dev' false
- do_test all 'dev' false
+ command_ok_ \
+ 'HOST "dev" DOES MATCH PLAT "dev"' -- \
+ plat_is_concerned \
+ 'dev' \
+ 'dev'
+ command_ok_ \
+ 'HOST "ao751h" DOES NOT MATCH PLAT "dev"' -- \
+ not plat_is_concerned \
+ 'ao751h' \
+ 'dev'
+ command_ok_ \
+ 'HOST "all" DOES NOT MATCH PLAT "dev"' -- \
+ not plat_is_concerned \
+ 'all' \
+ 'dev'
# Platform: !dev
- do_test dev '!dev' false
- do_test ao751h '!dev' true
- do_test all '!dev' false
+ command_ok_ \
+ 'HOST "dev" DOES NOT MATCH PLAT "!dev"' -- \
+ not plat_is_concerned \
+ 'dev' \
+ '!dev'
+ command_ok_ \
+ 'HOST "ao751h" DOES MATCH PLAT "!dev"' -- \
+ plat_is_concerned \
+ 'ao751h' \
+ '!dev'
+ command_ok_ \
+ 'HOST "all" DOES NOT MATCH PLAT "!dev"' -- \
+ not plat_is_concerned \
+ 'all' \
+ '!dev'
# Platform: dev dimension2400
- do_test 'dev' 'dev dimension2400' true
- do_test 'ao751h' 'dev dimension2400' false
- do_test 'all' 'dev dimension2400' false
+ command_ok_ \
+ 'HOST "dev" DOES MATCH PLAT "dev dimension2400"' -- \
+ plat_is_concerned \
+ 'dev' \
+ 'dev dimension2400'
+ command_ok_ \
+ 'HOST "ao751h" DOES NOT MATCH PLAT "dev dimension2400"' -- \
+ not plat_is_concerned \
+ 'ao751h' \
+ 'dev dimension2400'
+ command_ok_ \
+ 'HOST "all" DOES NOT MATCH PLAT "dev dimension2400"' -- \
+ not plat_is_concerned \
+ 'all' \
+ 'dev dimension2400'
# Platform: dev all
- do_test 'dev' 'dev all' true
- do_test 'ao751h' 'dev all' false
- do_test 'all' 'dev all' true
+ command_ok_ \
+ 'HOST "dev" DOES MATCH PLAT "dev all"' -- \
+ plat_is_concerned \
+ 'dev' \
+ 'dev all'
+ command_ok_ \
+ 'HOST "ao751h" DOES NOT MATCH PLAT "dev all"' -- \
+ not plat_is_concerned \
+ 'ao751h' \
+ 'dev all'
+ command_ok_ \
+ 'HOST "all" DOES MATCH PLAT "dev all"' -- \
+ plat_is_concerned \
+ 'all' \
+ 'dev all'
return 0
}
diff --git a/tests/reduce_deps.sh b/tests/reduce_deps.sh
index 386b609..41a4b58 100755
--- a/tests/reduce_deps.sh
+++ b/tests/reduce_deps.sh
@@ -1,6 +1,6 @@
# reduce_deps() tests
#
-# Copyright (C) 2014 Patrick "P. J." McDermott
+# Copyright (C) 2014, 2018, 2019 Patrick McDermott
#
# This file is part of the ProteanOS Development Kit.
#
@@ -18,51 +18,125 @@
# along with the ProteanOS Development Kit. If not, see
# <http://www.gnu.org/licenses/>.
-do_test()
-{
- local deps="${1}"
- local union="${2}"
- local host_arch="${3}"
- local host_plat="${4}"
- local result="${5}"
-
- deps="$(reduce_deps "${deps}" "${union}" "${host_arch}" "${host_plat}")"
-
- if [ "x${deps}" != "x${result}" ]; then
- ${union} && printf 'Union' || printf 'Normal'
- printf ' dependency list for '
- printf 'host arch "%s" and host plat "%s":\n' \
- "${host_arch}" "${host_plat}"
- printf ' "%s" != "%s"\n' \
- "${deps}" "${result}"
- tests_es=1
- fi
-}
-
main()
{
+ plan_ 13
+
# Normal and union AND-lists.
- do_test 'foo, bar' false 'amd64-linux-glibc' 'dev' 'foo, bar'
- do_test 'foo,bar' false 'amd64-linux-glibc' 'dev' 'foo, bar'
- do_test 'foo, bar' false 'amd64-linux-glibc' 'dev' 'foo, bar'
- do_test 'foo, bar' true 'amd64-linux-glibc' 'dev' 'foo, bar'
- do_test 'foo,bar' true 'amd64-linux-glibc' 'dev' 'foo, bar'
- do_test 'foo, bar' true 'amd64-linux-glibc' 'dev' 'foo, bar'
+ command_ok_ \
+ 'NORMAL LIST "foo, bar"' -- \
+ [ x"$(reduce_deps \
+ 'foo, bar' false \
+ 'amd64-linux-glibc' 'dev' \
+ )" = \
+ x'foo, bar' \
+ ]
+ command_ok_ \
+ 'NORMAL LIST "foo,bar"' -- \
+ [ x"$(reduce_deps \
+ 'foo,bar' false \
+ 'amd64-linux-glibc' 'dev' \
+ )" = \
+ x'foo, bar' \
+ ]
+ command_ok_ \
+ 'NORMAL LIST "foo, bar"' -- \
+ [ x"$(reduce_deps \
+ 'foo, bar' false \
+ 'amd64-linux-glibc' 'dev' \
+ )" = \
+ x'foo, bar' \
+ ]
+ command_ok_ \
+ 'UNION LIST "foo, bar"' -- \
+ [ x"$(reduce_deps \
+ 'foo, bar' true \
+ 'amd64-linux-glibc' 'dev' \
+ )" = \
+ x'foo, bar' \
+ ]
+ command_ok_ \
+ 'UNION LIST "foo,bar"' -- \
+ [ x"$(reduce_deps \
+ 'foo,bar' true \
+ 'amd64-linux-glibc' 'dev' \
+ )" = \
+ x'foo, bar' \
+ ]
+ command_ok_ \
+ 'UNION LIST "foo, bar"' -- \
+ [ x"$(reduce_deps \
+ 'foo, bar' true \
+ 'amd64-linux-glibc' 'dev' \
+ )" = \
+ x'foo, bar' \
+ ]
# Normal and union OR-lists.
- do_test 'foo | bar' false 'amd64-linux-glibc' 'dev' 'foo | bar'
- do_test 'foo|bar' false 'amd64-linux-glibc' 'dev' 'foo | bar'
- do_test 'foo | bar' false 'amd64-linux-glibc' 'dev' 'foo | bar'
+ command_ok_ \
+ 'NORMAL LIST "foo | bar"' -- \
+ [ x"$(reduce_deps \
+ 'foo | bar' false \
+ 'amd64-linux-glibc' 'dev' \
+ )" = \
+ x'foo | bar' \
+ ]
+ command_ok_ \
+ 'NORMAL LIST "foo|bar"' -- \
+ [ x"$(reduce_deps \
+ 'foo|bar' false \
+ 'amd64-linux-glibc' 'dev' \
+ )" = \
+ x'foo | bar' \
+ ]
+ command_ok_ \
+ 'NORMAL LIST "foo | bar"' -- \
+ [ x"$(reduce_deps \
+ 'foo | bar' false \
+ 'amd64-linux-glibc' 'dev' \
+ )" = \
+ x'foo | bar' \
+ ]
# Normal and union AND-lists with arch specs.
- do_test 'foo [amd64-linux-glibc], bar [!amd64-linux-glibc]' false \
- 'amd64-linux-glibc' 'dev' 'foo'
- do_test 'foo [amd64-linux-glibc], bar [!amd64-linux-glibc]' true \
- 'amd64-linux-glibc' 'dev' 'foo'
+ command_ok_ \
+ 'NORMAL LIST "foo [amd64-linux-glibc], '$(: \
+ )'bar [!amd64-linux-glibc]"' -- \
+ [ x"$(reduce_deps \
+ 'foo [amd64-linux-glibc], bar [!amd64-linux-glibc]' \
+ false \
+ 'amd64-linux-glibc' 'dev' \
+ )" = \
+ x'foo' \
+ ]
+ command_ok_ \
+ 'UNION LIST "foo [amd64-linux-glibc], '$(: \
+ )'bar [!amd64-linux-glibc]"' -- \
+ [ x"$(reduce_deps \
+ 'foo [amd64-linux-glibc], bar [!amd64-linux-glibc]' \
+ true \
+ 'amd64-linux-glibc' 'dev' \
+ )" = \
+ x'foo' \
+ ]
# Normal and union AND-lists with plat specs.
- do_test 'foo <dev>, bar <!dev>' false 'amd64-linux-glibc' 'dev' 'foo'
- do_test 'foo <dev>, bar <!dev>' true 'amd64-linux-glibc' 'dev' 'foo'
+ command_ok_ \
+ 'NORMAL LIST "foo <dev>, bar <!dev>"' -- \
+ [ x"$(reduce_deps \
+ 'foo <dev>, bar <!dev>' false \
+ 'amd64-linux-glibc' 'dev' \
+ )" = \
+ x'foo' \
+ ]
+ command_ok_ \
+ 'UNION LIST "foo <dev>, bar <!dev>"' -- \
+ [ x"$(reduce_deps \
+ 'foo <dev>, bar <!dev>' true \
+ 'amd64-linux-glibc' 'dev' \
+ )" = \
+ x'foo' \
+ ]
return 0
}
diff --git a/tests/resolve_deps.basic.sh b/tests/resolve_deps.basic.sh
index 3edad56..9281bb4 100755
--- a/tests/resolve_deps.basic.sh
+++ b/tests/resolve_deps.basic.sh
@@ -1,6 +1,6 @@
# Basic resolve_deps() test
#
-# Copyright (C) 2014 Patrick "P. J." McDermott
+# Copyright (C) 2014 Patrick McDermott
#
# This file is part of the ProteanOS Development Kit.
#
@@ -30,14 +30,17 @@ main()
local results=
local test_results=
+ plan_ 2
+
results='foo bar baz qux quux'
test_results="$(resolve_deps "${pkgs}" "${deps}")"
- test_diff "${results}" "${test_results}"
+ is_diff 'resolve_deps' "${results}" "${test_results}"
results="$(printf '%s\n' ${results} | sort)"
test_results="$(printf '%s\n' $(resolve_deps "${pkgs}" "${deps}") | \
sort)"
- test_diff "${results}" "${test_results}"
+ is_diff 'resolve_deps (split into multiple lines)' \
+ "${results}" "${test_results}"
return 0
}