diff options
| author | Brent Cook <busterb@gmail.com> | 2024-02-12 03:10:44 -0600 |
|---|---|---|
| committer | Brent Cook <busterb@gmail.com> | 2024-02-12 03:15:18 -0600 |
| commit | ff0300c550905b7b7a28e452c2d48a3f2e98dad5 (patch) | |
| tree | e3abdc5655b40332c7d7c5f221ab7604248f1e26 | |
| parent | 37cff9e9a408570a96e3080249f8c70f6296a26f (diff) | |
| download | portable-ff0300c550905b7b7a28e452c2d48a3f2e98dad5.tar.gz portable-ff0300c550905b7b7a28e452c2d48a3f2e98dad5.tar.bz2 portable-ff0300c550905b7b7a28e452c2d48a3f2e98dad5.zip | |
delete checked-in tap-driver.sh
it is autogenerated, so don't keep it in tree
| -rw-r--r-- | .gitignore | 1 | ||||
| -rwxr-xr-x | tap-driver.sh | 650 |
2 files changed, 1 insertions, 650 deletions
| @@ -59,6 +59,7 @@ openssl.cnf | |||
| 59 | x509v3.cnf | 59 | x509v3.cnf |
| 60 | 60 | ||
| 61 | # tests | 61 | # tests |
| 62 | tap-driver.sh | ||
| 62 | test-driver | 63 | test-driver |
| 63 | *.log | 64 | *.log |
| 64 | *.trs | 65 | *.trs |
diff --git a/tap-driver.sh b/tap-driver.sh deleted file mode 100755 index 1e444b2..0000000 --- a/tap-driver.sh +++ /dev/null | |||
| @@ -1,650 +0,0 @@ | |||
| 1 | #! /bin/sh | ||
| 2 | # Copyright (C) 2011-2021 Free Software Foundation, Inc. | ||
| 3 | # | ||
| 4 | # This program is free software; you can redistribute it and/or modify | ||
| 5 | # it under the terms of the GNU General Public License as published by | ||
| 6 | # the Free Software Foundation; either version 2, or (at your option) | ||
| 7 | # any later version. | ||
| 8 | # | ||
| 9 | # This program is distributed in the hope that it will be useful, | ||
| 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 12 | # GNU General Public License for more details. | ||
| 13 | # | ||
| 14 | # You should have received a copy of the GNU General Public License | ||
| 15 | # along with this program. If not, see <https://www.gnu.org/licenses/>. | ||
| 16 | |||
| 17 | # As a special exception to the GNU General Public License, if you | ||
| 18 | # distribute this file as part of a program that contains a | ||
| 19 | # configuration script generated by Autoconf, you may include it under | ||
| 20 | # the same distribution terms that you use for the rest of that program. | ||
| 21 | |||
| 22 | # This file is maintained in Automake, please report | ||
| 23 | # bugs to <bug-automake@gnu.org> or send patches to | ||
| 24 | # <automake-patches@gnu.org>. | ||
| 25 | |||
| 26 | scriptversion=2013-12-23.17; # UTC | ||
| 27 | |||
| 28 | # Make unconditional expansion of undefined variables an error. This | ||
| 29 | # helps a lot in preventing typo-related bugs. | ||
| 30 | set -u | ||
| 31 | |||
| 32 | me=tap-driver.sh | ||
| 33 | |||
| 34 | fatal () | ||
| 35 | { | ||
| 36 | echo "$me: fatal: $*" >&2 | ||
| 37 | exit 1 | ||
| 38 | } | ||
| 39 | |||
| 40 | usage_error () | ||
| 41 | { | ||
| 42 | echo "$me: $*" >&2 | ||
| 43 | print_usage >&2 | ||
| 44 | exit 2 | ||
| 45 | } | ||
| 46 | |||
| 47 | print_usage () | ||
| 48 | { | ||
| 49 | cat <<END | ||
| 50 | Usage: | ||
| 51 | tap-driver.sh --test-name=NAME --log-file=PATH --trs-file=PATH | ||
| 52 | [--expect-failure={yes|no}] [--color-tests={yes|no}] | ||
| 53 | [--enable-hard-errors={yes|no}] [--ignore-exit] | ||
| 54 | [--diagnostic-string=STRING] [--merge|--no-merge] | ||
| 55 | [--comments|--no-comments] [--] TEST-COMMAND | ||
| 56 | The '--test-name', '-log-file' and '--trs-file' options are mandatory. | ||
| 57 | END | ||
| 58 | } | ||
| 59 | |||
| 60 | # TODO: better error handling in option parsing (in particular, ensure | ||
| 61 | # TODO: $log_file, $trs_file and $test_name are defined). | ||
| 62 | test_name= # Used for reporting. | ||
| 63 | log_file= # Where to save the result and output of the test script. | ||
| 64 | trs_file= # Where to save the metadata of the test run. | ||
| 65 | expect_failure=0 | ||
| 66 | color_tests=0 | ||
| 67 | merge=0 | ||
| 68 | ignore_exit=0 | ||
| 69 | comments=0 | ||
| 70 | diag_string='#' | ||
| 71 | while test $# -gt 0; do | ||
| 72 | case $1 in | ||
| 73 | --help) print_usage; exit $?;; | ||
| 74 | --version) echo "$me $scriptversion"; exit $?;; | ||
| 75 | --test-name) test_name=$2; shift;; | ||
| 76 | --log-file) log_file=$2; shift;; | ||
| 77 | --trs-file) trs_file=$2; shift;; | ||
| 78 | --color-tests) color_tests=$2; shift;; | ||
| 79 | --expect-failure) expect_failure=$2; shift;; | ||
| 80 | --enable-hard-errors) shift;; # No-op. | ||
| 81 | --merge) merge=1;; | ||
| 82 | --no-merge) merge=0;; | ||
| 83 | --ignore-exit) ignore_exit=1;; | ||
| 84 | --comments) comments=1;; | ||
| 85 | --no-comments) comments=0;; | ||
| 86 | --diagnostic-string) diag_string=$2; shift;; | ||
| 87 | --) shift; break;; | ||
| 88 | -*) usage_error "invalid option: '$1'";; | ||
| 89 | esac | ||
| 90 | shift | ||
| 91 | done | ||
| 92 | |||
| 93 | test $# -gt 0 || usage_error "missing test command" | ||
| 94 | |||
| 95 | case $expect_failure in | ||
| 96 | yes) expect_failure=1;; | ||
| 97 | *) expect_failure=0;; | ||
| 98 | esac | ||
| 99 | |||
| 100 | if test $color_tests = yes; then | ||
| 101 | init_colors=' | ||
| 102 | color_map["red"]="[0;31m" # Red. | ||
| 103 | color_map["grn"]="[0;32m" # Green. | ||
| 104 | color_map["lgn"]="[1;32m" # Light green. | ||
| 105 | color_map["blu"]="[1;34m" # Blue. | ||
| 106 | color_map["mgn"]="[0;35m" # Magenta. | ||
| 107 | color_map["std"]="[m" # No color. | ||
| 108 | color_for_result["ERROR"] = "mgn" | ||
| 109 | color_for_result["PASS"] = "grn" | ||
| 110 | color_for_result["XPASS"] = "red" | ||
| 111 | color_for_result["FAIL"] = "red" | ||
| 112 | color_for_result["XFAIL"] = "lgn" | ||
| 113 | color_for_result["SKIP"] = "blu"' | ||
| 114 | else | ||
| 115 | init_colors='' | ||
| 116 | fi | ||
| 117 | |||
| 118 | # :; is there to work around a bug in bash 3.2 (and earlier) which | ||
| 119 | # does not always set '$?' properly on redirection failure. | ||
| 120 | # See the Autoconf manual for more details. | ||
| 121 | :;{ | ||
| 122 | ( | ||
| 123 | # Ignore common signals (in this subshell only!), to avoid potential | ||
| 124 | # problems with Korn shells. Some Korn shells are known to propagate | ||
| 125 | # to themselves signals that have killed a child process they were | ||
| 126 | # waiting for; this is done at least for SIGINT (and usually only for | ||
| 127 | # it, in truth). Without the `trap' below, such a behaviour could | ||
| 128 | # cause a premature exit in the current subshell, e.g., in case the | ||
| 129 | # test command it runs gets terminated by a SIGINT. Thus, the awk | ||
| 130 | # script we are piping into would never seen the exit status it | ||
| 131 | # expects on its last input line (which is displayed below by the | ||
| 132 | # last `echo $?' statement), and would thus die reporting an internal | ||
| 133 | # error. | ||
| 134 | # For more information, see the Autoconf manual and the thread: | ||
| 135 | # <https://lists.gnu.org/archive/html/bug-autoconf/2011-09/msg00004.html> | ||
| 136 | trap : 1 3 2 13 15 | ||
| 137 | if test $merge -gt 0; then | ||
| 138 | exec 2>&1 | ||
| 139 | else | ||
| 140 | exec 2>&3 | ||
| 141 | fi | ||
| 142 | "$@" | ||
| 143 | echo $? | ||
| 144 | ) | LC_ALL=C ${AM_TAP_AWK-awk} \ | ||
| 145 | -v me="$me" \ | ||
| 146 | -v test_script_name="$test_name" \ | ||
| 147 | -v log_file="$log_file" \ | ||
| 148 | -v trs_file="$trs_file" \ | ||
| 149 | -v expect_failure="$expect_failure" \ | ||
| 150 | -v merge="$merge" \ | ||
| 151 | -v ignore_exit="$ignore_exit" \ | ||
| 152 | -v comments="$comments" \ | ||
| 153 | -v diag_string="$diag_string" \ | ||
| 154 | ' | ||
| 155 | # TODO: the usages of "cat >&3" below could be optimized when using | ||
| 156 | # GNU awk, and/on on systems that supports /dev/fd/. | ||
| 157 | |||
| 158 | # Implementation note: in what follows, `result_obj` will be an | ||
| 159 | # associative array that (partly) simulates a TAP result object | ||
| 160 | # from the `TAP::Parser` perl module. | ||
| 161 | |||
| 162 | ## ----------- ## | ||
| 163 | ## FUNCTIONS ## | ||
| 164 | ## ----------- ## | ||
| 165 | |||
| 166 | function fatal(msg) | ||
| 167 | { | ||
| 168 | print me ": " msg | "cat >&2" | ||
| 169 | exit 1 | ||
| 170 | } | ||
| 171 | |||
| 172 | function abort(where) | ||
| 173 | { | ||
| 174 | fatal("internal error " where) | ||
| 175 | } | ||
| 176 | |||
| 177 | # Convert a boolean to a "yes"/"no" string. | ||
| 178 | function yn(bool) | ||
| 179 | { | ||
| 180 | return bool ? "yes" : "no"; | ||
| 181 | } | ||
| 182 | |||
| 183 | function add_test_result(result) | ||
| 184 | { | ||
| 185 | if (!test_results_index) | ||
| 186 | test_results_index = 0 | ||
| 187 | test_results_list[test_results_index] = result | ||
| 188 | test_results_index += 1 | ||
| 189 | test_results_seen[result] = 1; | ||
| 190 | } | ||
| 191 | |||
| 192 | # Whether the test script should be re-run by "make recheck". | ||
| 193 | function must_recheck() | ||
| 194 | { | ||
| 195 | for (k in test_results_seen) | ||
| 196 | if (k != "XFAIL" && k != "PASS" && k != "SKIP") | ||
| 197 | return 1 | ||
| 198 | return 0 | ||
| 199 | } | ||
| 200 | |||
| 201 | # Whether the content of the log file associated to this test should | ||
| 202 | # be copied into the "global" test-suite.log. | ||
| 203 | function copy_in_global_log() | ||
| 204 | { | ||
| 205 | for (k in test_results_seen) | ||
| 206 | if (k != "PASS") | ||
| 207 | return 1 | ||
| 208 | return 0 | ||
| 209 | } | ||
| 210 | |||
| 211 | function get_global_test_result() | ||
| 212 | { | ||
| 213 | if ("ERROR" in test_results_seen) | ||
| 214 | return "ERROR" | ||
| 215 | if ("FAIL" in test_results_seen || "XPASS" in test_results_seen) | ||
| 216 | return "FAIL" | ||
| 217 | all_skipped = 1 | ||
| 218 | for (k in test_results_seen) | ||
| 219 | if (k != "SKIP") | ||
| 220 | all_skipped = 0 | ||
| 221 | if (all_skipped) | ||
| 222 | return "SKIP" | ||
| 223 | return "PASS"; | ||
| 224 | } | ||
| 225 | |||
| 226 | function stringify_result_obj(result_obj) | ||
| 227 | { | ||
| 228 | if (result_obj["is_unplanned"] || result_obj["number"] != testno) | ||
| 229 | return "ERROR" | ||
| 230 | |||
| 231 | if (plan_seen == LATE_PLAN) | ||
| 232 | return "ERROR" | ||
| 233 | |||
| 234 | if (result_obj["directive"] == "TODO") | ||
| 235 | return result_obj["is_ok"] ? "XPASS" : "XFAIL" | ||
| 236 | |||
| 237 | if (result_obj["directive"] == "SKIP") | ||
| 238 | return result_obj["is_ok"] ? "SKIP" : COOKED_FAIL; | ||
| 239 | |||
| 240 | if (length(result_obj["directive"])) | ||
| 241 | abort("in function stringify_result_obj()") | ||
| 242 | |||
| 243 | return result_obj["is_ok"] ? COOKED_PASS : COOKED_FAIL | ||
| 244 | } | ||
| 245 | |||
| 246 | function decorate_result(result) | ||
| 247 | { | ||
| 248 | color_name = color_for_result[result] | ||
| 249 | if (color_name) | ||
| 250 | return color_map[color_name] "" result "" color_map["std"] | ||
| 251 | # If we are not using colorized output, or if we do not know how | ||
| 252 | # to colorize the given result, we should return it unchanged. | ||
| 253 | return result | ||
| 254 | } | ||
| 255 | |||
| 256 | function report(result, details) | ||
| 257 | { | ||
| 258 | if (result ~ /^(X?(PASS|FAIL)|SKIP|ERROR)/) | ||
| 259 | { | ||
| 260 | msg = ": " test_script_name | ||
| 261 | add_test_result(result) | ||
| 262 | } | ||
| 263 | else if (result == "#") | ||
| 264 | { | ||
| 265 | msg = " " test_script_name ":" | ||
| 266 | } | ||
| 267 | else | ||
| 268 | { | ||
| 269 | abort("in function report()") | ||
| 270 | } | ||
| 271 | if (length(details)) | ||
| 272 | msg = msg " " details | ||
| 273 | # Output on console might be colorized. | ||
| 274 | print decorate_result(result) msg | ||
| 275 | # Log the result in the log file too, to help debugging (this is | ||
| 276 | # especially true when said result is a TAP error or "Bail out!"). | ||
| 277 | print result msg | "cat >&3"; | ||
| 278 | } | ||
| 279 | |||
| 280 | function testsuite_error(error_message) | ||
| 281 | { | ||
| 282 | report("ERROR", "- " error_message) | ||
| 283 | } | ||
| 284 | |||
| 285 | function handle_tap_result() | ||
| 286 | { | ||
| 287 | details = result_obj["number"]; | ||
| 288 | if (length(result_obj["description"])) | ||
| 289 | details = details " " result_obj["description"] | ||
| 290 | |||
| 291 | if (plan_seen == LATE_PLAN) | ||
| 292 | { | ||
| 293 | details = details " # AFTER LATE PLAN"; | ||
| 294 | } | ||
| 295 | else if (result_obj["is_unplanned"]) | ||
| 296 | { | ||
| 297 | details = details " # UNPLANNED"; | ||
| 298 | } | ||
| 299 | else if (result_obj["number"] != testno) | ||
| 300 | { | ||
| 301 | details = sprintf("%s # OUT-OF-ORDER (expecting %d)", | ||
| 302 | details, testno); | ||
| 303 | } | ||
| 304 | else if (result_obj["directive"]) | ||
| 305 | { | ||
| 306 | details = details " # " result_obj["directive"]; | ||
| 307 | if (length(result_obj["explanation"])) | ||
| 308 | details = details " " result_obj["explanation"] | ||
| 309 | } | ||
| 310 | |||
| 311 | report(stringify_result_obj(result_obj), details) | ||
| 312 | } | ||
| 313 | |||
| 314 | # `skip_reason` should be empty whenever planned > 0. | ||
| 315 | function handle_tap_plan(planned, skip_reason) | ||
| 316 | { | ||
| 317 | planned += 0 # Avoid getting confused if, say, `planned` is "00" | ||
| 318 | if (length(skip_reason) && planned > 0) | ||
| 319 | abort("in function handle_tap_plan()") | ||
| 320 | if (plan_seen) | ||
| 321 | { | ||
| 322 | # Error, only one plan per stream is acceptable. | ||
| 323 | testsuite_error("multiple test plans") | ||
| 324 | return; | ||
| 325 | } | ||
| 326 | planned_tests = planned | ||
| 327 | # The TAP plan can come before or after *all* the TAP results; we speak | ||
| 328 | # respectively of an "early" or a "late" plan. If we see the plan line | ||
| 329 | # after at least one TAP result has been seen, assume we have a late | ||
| 330 | # plan; in this case, any further test result seen after the plan will | ||
| 331 | # be flagged as an error. | ||
| 332 | plan_seen = (testno >= 1 ? LATE_PLAN : EARLY_PLAN) | ||
| 333 | # If testno > 0, we have an error ("too many tests run") that will be | ||
| 334 | # automatically dealt with later, so do not worry about it here. If | ||
| 335 | # $plan_seen is true, we have an error due to a repeated plan, and that | ||
| 336 | # has already been dealt with above. Otherwise, we have a valid "plan | ||
| 337 | # with SKIP" specification, and should report it as a particular kind | ||
| 338 | # of SKIP result. | ||
| 339 | if (planned == 0 && testno == 0) | ||
| 340 | { | ||
| 341 | if (length(skip_reason)) | ||
| 342 | skip_reason = "- " skip_reason; | ||
| 343 | report("SKIP", skip_reason); | ||
| 344 | } | ||
| 345 | } | ||
| 346 | |||
| 347 | function extract_tap_comment(line) | ||
| 348 | { | ||
| 349 | if (index(line, diag_string) == 1) | ||
| 350 | { | ||
| 351 | # Strip leading `diag_string` from `line`. | ||
| 352 | line = substr(line, length(diag_string) + 1) | ||
| 353 | # And strip any leading and trailing whitespace left. | ||
| 354 | sub("^[ \t]*", "", line) | ||
| 355 | sub("[ \t]*$", "", line) | ||
| 356 | # Return what is left (if any). | ||
| 357 | return line; | ||
| 358 | } | ||
| 359 | return ""; | ||
| 360 | } | ||
| 361 | |||
| 362 | # When this function is called, we know that line is a TAP result line, | ||
| 363 | # so that it matches the (perl) RE "^(not )?ok\b". | ||
| 364 | function setup_result_obj(line) | ||
| 365 | { | ||
| 366 | # Get the result, and remove it from the line. | ||
| 367 | result_obj["is_ok"] = (substr(line, 1, 2) == "ok" ? 1 : 0) | ||
| 368 | sub("^(not )?ok[ \t]*", "", line) | ||
| 369 | |||
| 370 | # If the result has an explicit number, get it and strip it; otherwise, | ||
| 371 | # automatically assign the next test number to it. | ||
| 372 | if (line ~ /^[0-9]+$/ || line ~ /^[0-9]+[^a-zA-Z0-9_]/) | ||
| 373 | { | ||
| 374 | match(line, "^[0-9]+") | ||
| 375 | # The final `+ 0` is to normalize numbers with leading zeros. | ||
| 376 | result_obj["number"] = substr(line, 1, RLENGTH) + 0 | ||
| 377 | line = substr(line, RLENGTH + 1) | ||
| 378 | } | ||
| 379 | else | ||
| 380 | { | ||
| 381 | result_obj["number"] = testno | ||
| 382 | } | ||
| 383 | |||
| 384 | if (plan_seen == LATE_PLAN) | ||
| 385 | # No further test results are acceptable after a "late" TAP plan | ||
| 386 | # has been seen. | ||
| 387 | result_obj["is_unplanned"] = 1 | ||
| 388 | else if (plan_seen && testno > planned_tests) | ||
| 389 | result_obj["is_unplanned"] = 1 | ||
| 390 | else | ||
| 391 | result_obj["is_unplanned"] = 0 | ||
| 392 | |||
| 393 | # Strip trailing and leading whitespace. | ||
| 394 | sub("^[ \t]*", "", line) | ||
| 395 | sub("[ \t]*$", "", line) | ||
| 396 | |||
| 397 | # This will have to be corrected if we have a "TODO"/"SKIP" directive. | ||
| 398 | result_obj["description"] = line | ||
| 399 | result_obj["directive"] = "" | ||
| 400 | result_obj["explanation"] = "" | ||
| 401 | |||
| 402 | if (index(line, "#") == 0) | ||
| 403 | return # No possible directive, nothing more to do. | ||
| 404 | |||
| 405 | # Directives are case-insensitive. | ||
| 406 | rx = "[ \t]*#[ \t]*([tT][oO][dD][oO]|[sS][kK][iI][pP])[ \t]*" | ||
| 407 | |||
| 408 | # See whether we have the directive, and if yes, where. | ||
| 409 | pos = match(line, rx "$") | ||
| 410 | if (!pos) | ||
| 411 | pos = match(line, rx "[^a-zA-Z0-9_]") | ||
| 412 | |||
| 413 | # If there was no TAP directive, we have nothing more to do. | ||
| 414 | if (!pos) | ||
| 415 | return | ||
| 416 | |||
| 417 | # Let`s now see if the TAP directive has been escaped. For example: | ||
| 418 | # escaped: ok \# SKIP | ||
| 419 | # not escaped: ok \\# SKIP | ||
| 420 | # escaped: ok \\\\\# SKIP | ||
| 421 | # not escaped: ok \ # SKIP | ||
| 422 | if (substr(line, pos, 1) == "#") | ||
| 423 | { | ||
| 424 | bslash_count = 0 | ||
| 425 | for (i = pos; i > 1 && substr(line, i - 1, 1) == "\\"; i--) | ||
| 426 | bslash_count += 1 | ||
| 427 | if (bslash_count % 2) | ||
| 428 | return # Directive was escaped. | ||
| 429 | } | ||
| 430 | |||
| 431 | # Strip the directive and its explanation (if any) from the test | ||
| 432 | # description. | ||
| 433 | result_obj["description"] = substr(line, 1, pos - 1) | ||
| 434 | # Now remove the test description from the line, that has been dealt | ||
| 435 | # with already. | ||
| 436 | line = substr(line, pos) | ||
| 437 | # Strip the directive, and save its value (normalized to upper case). | ||
| 438 | sub("^[ \t]*#[ \t]*", "", line) | ||
| 439 | result_obj["directive"] = toupper(substr(line, 1, 4)) | ||
| 440 | line = substr(line, 5) | ||
| 441 | # Now get the explanation for the directive (if any), with leading | ||
| 442 | # and trailing whitespace removed. | ||
| 443 | sub("^[ \t]*", "", line) | ||
| 444 | sub("[ \t]*$", "", line) | ||
| 445 | result_obj["explanation"] = line | ||
| 446 | } | ||
| 447 | |||
| 448 | function get_test_exit_message(status) | ||
| 449 | { | ||
| 450 | if (status == 0) | ||
| 451 | return "" | ||
| 452 | if (status !~ /^[1-9][0-9]*$/) | ||
| 453 | abort("getting exit status") | ||
| 454 | if (status < 127) | ||
| 455 | exit_details = "" | ||
| 456 | else if (status == 127) | ||
| 457 | exit_details = " (command not found?)" | ||
| 458 | else if (status >= 128 && status <= 255) | ||
| 459 | exit_details = sprintf(" (terminated by signal %d?)", status - 128) | ||
| 460 | else if (status > 256 && status <= 384) | ||
| 461 | # We used to report an "abnormal termination" here, but some Korn | ||
| 462 | # shells, when a child process die due to signal number n, can leave | ||
| 463 | # in $? an exit status of 256+n instead of the more standard 128+n. | ||
| 464 | # Apparently, both behaviours are allowed by POSIX (2008), so be | ||
| 465 | # prepared to handle them both. See also Austing Group report ID | ||
| 466 | # 0000051 <https://www.austingroupbugs.net/view.php?id=51> | ||
| 467 | exit_details = sprintf(" (terminated by signal %d?)", status - 256) | ||
| 468 | else | ||
| 469 | # Never seen in practice. | ||
| 470 | exit_details = " (abnormal termination)" | ||
| 471 | return sprintf("exited with status %d%s", status, exit_details) | ||
| 472 | } | ||
| 473 | |||
| 474 | function write_test_results() | ||
| 475 | { | ||
| 476 | print ":global-test-result: " get_global_test_result() > trs_file | ||
| 477 | print ":recheck: " yn(must_recheck()) > trs_file | ||
| 478 | print ":copy-in-global-log: " yn(copy_in_global_log()) > trs_file | ||
| 479 | for (i = 0; i < test_results_index; i += 1) | ||
| 480 | print ":test-result: " test_results_list[i] > trs_file | ||
| 481 | close(trs_file); | ||
| 482 | } | ||
| 483 | |||
| 484 | BEGIN { | ||
| 485 | |||
| 486 | ## ------- ## | ||
| 487 | ## SETUP ## | ||
| 488 | ## ------- ## | ||
| 489 | |||
| 490 | '"$init_colors"' | ||
| 491 | |||
| 492 | # Properly initialized once the TAP plan is seen. | ||
| 493 | planned_tests = 0 | ||
| 494 | |||
| 495 | COOKED_PASS = expect_failure ? "XPASS": "PASS"; | ||
| 496 | COOKED_FAIL = expect_failure ? "XFAIL": "FAIL"; | ||
| 497 | |||
| 498 | # Enumeration-like constants to remember which kind of plan (if any) | ||
| 499 | # has been seen. It is important that NO_PLAN evaluates "false" as | ||
| 500 | # a boolean. | ||
| 501 | NO_PLAN = 0 | ||
| 502 | EARLY_PLAN = 1 | ||
| 503 | LATE_PLAN = 2 | ||
| 504 | |||
| 505 | testno = 0 # Number of test results seen so far. | ||
| 506 | bailed_out = 0 # Whether a "Bail out!" directive has been seen. | ||
| 507 | |||
| 508 | # Whether the TAP plan has been seen or not, and if yes, which kind | ||
| 509 | # it is ("early" is seen before any test result, "late" otherwise). | ||
| 510 | plan_seen = NO_PLAN | ||
| 511 | |||
| 512 | ## --------- ## | ||
| 513 | ## PARSING ## | ||
| 514 | ## --------- ## | ||
| 515 | |||
| 516 | is_first_read = 1 | ||
| 517 | |||
| 518 | while (1) | ||
| 519 | { | ||
| 520 | # Involutions required so that we are able to read the exit status | ||
| 521 | # from the last input line. | ||
| 522 | st = getline | ||
| 523 | if (st < 0) # I/O error. | ||
| 524 | fatal("I/O error while reading from input stream") | ||
| 525 | else if (st == 0) # End-of-input | ||
| 526 | { | ||
| 527 | if (is_first_read) | ||
| 528 | abort("in input loop: only one input line") | ||
| 529 | break | ||
| 530 | } | ||
| 531 | if (is_first_read) | ||
| 532 | { | ||
| 533 | is_first_read = 0 | ||
| 534 | nextline = $0 | ||
| 535 | continue | ||
| 536 | } | ||
| 537 | else | ||
| 538 | { | ||
| 539 | curline = nextline | ||
| 540 | nextline = $0 | ||
| 541 | $0 = curline | ||
| 542 | } | ||
| 543 | # Copy any input line verbatim into the log file. | ||
| 544 | print | "cat >&3" | ||
| 545 | # Parsing of TAP input should stop after a "Bail out!" directive. | ||
| 546 | if (bailed_out) | ||
| 547 | continue | ||
| 548 | |||
| 549 | # TAP test result. | ||
| 550 | if ($0 ~ /^(not )?ok$/ || $0 ~ /^(not )?ok[^a-zA-Z0-9_]/) | ||
| 551 | { | ||
| 552 | testno += 1 | ||
| 553 | setup_result_obj($0) | ||
| 554 | handle_tap_result() | ||
| 555 | } | ||
| 556 | # TAP plan (normal or "SKIP" without explanation). | ||
| 557 | else if ($0 ~ /^1\.\.[0-9]+[ \t]*$/) | ||
| 558 | { | ||
| 559 | # The next two lines will put the number of planned tests in $0. | ||
| 560 | sub("^1\\.\\.", "") | ||
| 561 | sub("[^0-9]*$", "") | ||
| 562 | handle_tap_plan($0, "") | ||
| 563 | continue | ||
| 564 | } | ||
| 565 | # TAP "SKIP" plan, with an explanation. | ||
| 566 | else if ($0 ~ /^1\.\.0+[ \t]*#/) | ||
| 567 | { | ||
| 568 | # The next lines will put the skip explanation in $0, stripping | ||
| 569 | # any leading and trailing whitespace. This is a little more | ||
| 570 | # tricky in truth, since we want to also strip a potential leading | ||
| 571 | # "SKIP" string from the message. | ||
| 572 | sub("^[^#]*#[ \t]*(SKIP[: \t][ \t]*)?", "") | ||
| 573 | sub("[ \t]*$", ""); | ||
| 574 | handle_tap_plan(0, $0) | ||
| 575 | } | ||
| 576 | # "Bail out!" magic. | ||
| 577 | # Older versions of prove and TAP::Harness (e.g., 3.17) did not | ||
| 578 | # recognize a "Bail out!" directive when preceded by leading | ||
| 579 | # whitespace, but more modern versions (e.g., 3.23) do. So we | ||
| 580 | # emulate the latter, "more modern" behaviour. | ||
| 581 | else if ($0 ~ /^[ \t]*Bail out!/) | ||
| 582 | { | ||
| 583 | bailed_out = 1 | ||
| 584 | # Get the bailout message (if any), with leading and trailing | ||
| 585 | # whitespace stripped. The message remains stored in `$0`. | ||
| 586 | sub("^[ \t]*Bail out![ \t]*", ""); | ||
| 587 | sub("[ \t]*$", ""); | ||
| 588 | # Format the error message for the | ||
| 589 | bailout_message = "Bail out!" | ||
| 590 | if (length($0)) | ||
| 591 | bailout_message = bailout_message " " $0 | ||
| 592 | testsuite_error(bailout_message) | ||
| 593 | } | ||
| 594 | # Maybe we have too look for dianogtic comments too. | ||
| 595 | else if (comments != 0) | ||
| 596 | { | ||
| 597 | comment = extract_tap_comment($0); | ||
| 598 | if (length(comment)) | ||
| 599 | report("#", comment); | ||
| 600 | } | ||
| 601 | } | ||
| 602 | |||
| 603 | ## -------- ## | ||
| 604 | ## FINISH ## | ||
| 605 | ## -------- ## | ||
| 606 | |||
| 607 | # A "Bail out!" directive should cause us to ignore any following TAP | ||
| 608 | # error, as well as a non-zero exit status from the TAP producer. | ||
| 609 | if (!bailed_out) | ||
| 610 | { | ||
| 611 | if (!plan_seen) | ||
| 612 | { | ||
| 613 | testsuite_error("missing test plan") | ||
| 614 | } | ||
| 615 | else if (planned_tests != testno) | ||
| 616 | { | ||
| 617 | bad_amount = testno > planned_tests ? "many" : "few" | ||
| 618 | testsuite_error(sprintf("too %s tests run (expected %d, got %d)", | ||
| 619 | bad_amount, planned_tests, testno)) | ||
| 620 | } | ||
| 621 | if (!ignore_exit) | ||
| 622 | { | ||
| 623 | # Fetch exit status from the last line. | ||
| 624 | exit_message = get_test_exit_message(nextline) | ||
| 625 | if (exit_message) | ||
| 626 | testsuite_error(exit_message) | ||
| 627 | } | ||
| 628 | } | ||
| 629 | |||
| 630 | write_test_results() | ||
| 631 | |||
| 632 | exit 0 | ||
| 633 | |||
| 634 | } # End of "BEGIN" block. | ||
| 635 | ' | ||
| 636 | |||
| 637 | # TODO: document that we consume the file descriptor 3 :-( | ||
| 638 | } 3>"$log_file" | ||
| 639 | |||
| 640 | test $? -eq 0 || fatal "I/O or internal error" | ||
| 641 | |||
| 642 | # Local Variables: | ||
| 643 | # mode: shell-script | ||
| 644 | # sh-indentation: 2 | ||
| 645 | # eval: (add-hook 'before-save-hook 'time-stamp) | ||
| 646 | # time-stamp-start: "scriptversion=" | ||
| 647 | # time-stamp-format: "%:y-%02m-%02d.%02H" | ||
| 648 | # time-stamp-time-zone: "UTC0" | ||
| 649 | # time-stamp-end: "; # UTC" | ||
| 650 | # End: | ||
