diff options
author | teor <teor@torproject.org> | 2019-11-13 16:37:32 +1000 |
---|---|---|
committer | teor <teor@torproject.org> | 2019-11-14 10:55:21 +1000 |
commit | 39046019ec1192bd8222821a6b8677fabc0a9968 (patch) | |
tree | 1e00b4238741293970ae33570495c74d504ba122 /src | |
parent | b4b3060f692ed934fe89d791be683a7506e5860e (diff) | |
download | tor-39046019ec1192bd8222821a6b8677fabc0a9968.tar.gz tor-39046019ec1192bd8222821a6b8677fabc0a9968.zip |
test/parseconf: Refactor and standardise, stage 1
Remove duplicate code, and standardise similar behaviour.
Add some additional error checking.
Cleanup after 32451.
Diffstat (limited to 'src')
-rwxr-xr-x | src/test/test_parseconf.sh | 400 |
1 files changed, 272 insertions, 128 deletions
diff --git a/src/test/test_parseconf.sh b/src/test/test_parseconf.sh index 237bf33ce3..edda6c3ef8 100755 --- a/src/test/test_parseconf.sh +++ b/src/test/test_parseconf.sh @@ -128,7 +128,7 @@ fi TOR_BINARY="$(abspath "$TOR_BINARY")" -echo "TOR BINARY IS $TOR_BINARY" +echo "Using Tor binary '$TOR_BINARY'." # make a safe space for temporary files DATA_DIR=$(mktemp -d -t tor_parseconf_tests.XXXXXX) @@ -157,23 +157,32 @@ else fi FINAL_EXIT=0 - NEXT_TEST= -fail_printf() { printf "FAIL: " >&2; - # The first argument is a printf string, so this warning is - # spurious - # shellcheck disable=SC2059 - printf "$@" >&2; - printf "\\n" >&2; - NEXT_TEST="yes" - FINAL_EXIT=$EXITCODE; } -die_printf() { printf "FAIL: CRITICAL error in '%s':" "$MYNAME" >&2; - # The first argument is a printf string, so this warning is - # spurious - # shellcheck disable=SC2059 - printf "$@" >&2; - printf "\\n" >&2; - exit $EXITCODE; } + +# Log a failure message to stderr, using $@ as a printf string and arguments +# Set NEXT_TEST to "yes" and FINAL_EXIT to $EXITCODE. +fail_printf() +{ + printf "FAIL: " >&2 + # The first argument is a printf string, so this warning is spurious + # shellcheck disable=SC2059 + printf "$@" >&2 + printf "\\n" >&2 + NEXT_TEST="yes" + FINAL_EXIT=$EXITCODE +} + +# Log a failure message to stderr, using $@ as a printf string and arguments +# Exit with status $EXITCODE. +die_printf() +{ + printf "FAIL: CRITICAL error in '%s':" "$MYNAME" >&2 + # The first argument is a printf string, so this warning is spurious + # shellcheck disable=SC2059 + printf "$@" >&2 + printf "\\n" >&2 + exit $EXITCODE +} if test "$WINDOWS" = 1; then FILTER="dos2unix" @@ -182,9 +191,12 @@ else fi EMPTY="${DATA_DIR}/EMPTY" - touch "$EMPTY" || die_printf "Couldn't create empty file '%s'." \ "$EMPTY" +NON_EMPTY="${DATA_DIR}/NON_EMPTY" +echo "This pattern should not match any log messages" \ + > "$NON_EMPTY" || die_printf "Couldn't create non-empty file '%s'." \ + "$NON_EMPTY" STANDARD_LIBS="libevent\\|openssl\\|zlib" # Lib names are restricted to [a-z0-9]* at the moment @@ -230,6 +242,178 @@ if test "$TOR_LIBS_ENABLED"; then fi echo "Disabled Modules: ${TOR_MODULES_DISABLED:-(None)}" +# Yes, unix uses "0" for a successful command +TRUE=0 +FALSE=1 + +# Run tor --verify-config on the torrc $1, and defaults torrc $2, which may +# be $EMPTY. Pass tor the extra command line arguments $3, which will be +# passed unquoted. +# Send tor's standard output to stderr. +log_verify_config() +{ + # We need cmdline unquoted + # shellcheck disable=SC2086 + "$TOR_BINARY" --verify-config \ + -f "$1" \ + --defaults-torrc "$2" \ + $3 \ + >&2 \ + || true +} + +# Run "tor --dump-config short" on the torrc $1, and defaults torrc $2, which +# may be $EMPTY. Pass tor the extra command line arguments $3, which will be +# passed unquoted. +# Send the standard output to $4. +# If tor fails, fail_printf() using the file name $5, and context $6, +# which may be an empty string. Then run "tor --verify-config", and log tor's +# error messages to stderr. +dump_config() +{ + if test "$6"; then + CONTEXT=" $6" + else + CONTEXT="" + fi + + # We need cmdline unquoted + # shellcheck disable=SC2086 + if ! "$TOR_BINARY" --dump-config short \ + -f "$1" \ + --defaults-torrc "$2" \ + $3 \ + > "$4"; then + fail_printf "'%s': Tor --dump-config reported an error%s. Tor said:" \ + "$5" \ + "$CONTEXT" + log_verify_config "$1" \ + "$2" \ + "$3" + fi +} + +# Run "$FILTER" on the input $1. +# Send the standard output to $2. +# If tor fails, log a failure message using the file name $3, and context $4, +# which may be an empty string. +filter() +{ + if test "$4"; then + CONTEXT=" $4" + else + CONTEXT="" + fi + + "$FILTER" "$1" \ + > "$2" \ + || fail_printf "'%s': Filter '%s' reported an error%s." \ + "$3" \ + "$FILTER" \ + "$CONTEXT" +} + +# Compare the input file $1, and output file $2. +# +# If they are different, fail. If this is the first step that failed in this +# test, run log_verify_config with torrc $3, defaults torrc $4, and command +# line $5, to log Tor's error messages. Finally, log the differences between +# the files. +# +# If the file contents are identical, returns true. Otherwise, return false. +# +# Log failure messages using fail_printf(), with the file name $6, and +# context $7, which may be an empty string. +check_diff() +{ + if test "$7"; then + CONTEXT=" $=7" + else + CONTEXT="" + fi + + if cmp "$1" "$2" > /dev/null; then + return "$TRUE" + else + # If this is the first step that failed in this test, + # show tor's logs + if test -z "$NEXT_TEST"; then + fail_printf "'%s': Tor said%s:" \ + "$6" \ + "$CONTEXT" + log_verify_config "$3" \ + "$4" \ + "$5" + fi + fail_printf "'%s' did not match%s:" \ + "$6" \ + "$CONTEXT" + diff -u "$1" "$2" >&2 \ + || true + return "$FALSE" + fi +} + +# Check if $1 is an empty file. +# If it is, fail_printf() using $2 as the type of file. +# Returns true if the file is empty, false otherwise. +check_empty_pattern() +{ + if ! test -s "$1"; then + fail_printf "%s file '%s' is empty, and will match any output." \ + "$2" \ + "$1" + return "$TRUE" + else + return "$FALSE" + fi +} + +# Run tor --verify-config on the torrc $1, and defaults torrc $2, which may +# be $EMPTY. Pass tor the extra command line arguments $3, which will be +# passed unquoted. +# Send tor's standard output to $4. +# If tor's exit status does not match the boolean $5, fail_printf() +# using the file name $6, and context $7, which is required. +verify_config() +{ + RESULT=$TRUE + # We need cmdline unquoted + # shellcheck disable=SC2086 + "$TOR_BINARY" --verify-config \ + -f "$1" \ + --defaults-torrc "$2" \ + $3 \ + > "$4" || RESULT=$FALSE + + # Convert the actual and expected results to boolean, and compare + if test $((! (! RESULT))) -ne $((! (! $5))); then + fail_printf "'%s': Tor --verify-config did not %s." \ + "$6" \ + "$7" + fi +} + +# Check for the pattern in file $1, in the lines in the output file $2. +# Uses grep with the entire contents of $1 as the pattern. (Not "grep -f".) +# +# If the pattern does not match any lines in the output file, fail. +# Log the pattern, and the entire contents of the output file. +# +# Log failure messages using fail_printf(), with the file name $1, and +# context $3, which is required. +check_pattern() +{ + expect_log="$(cat "$1")" + if ! grep "$expect_log" "$2" > /dev/null; then + fail_printf "Expected %s '%s':\\n%s\\nTor said:" \ + "$3" \ + "$1" \ + "$expect_log" + cat "$2" >&2 + fi +} + for dir in "${EXAMPLEDIR}"/*; do NEXT_TEST= @@ -306,140 +490,100 @@ for dir in "${EXAMPLEDIR}"/*; do # This case should succeed: run dump-config and see if it does. if test -f "$EXPECTED_LOG"; then - if ! test -s "$EXPECTED_LOG"; then - fail_printf "Expected log file '%s' is empty.%s" \ - "$EXPECTED_LOG" \ - "(Empty expected log files match any output.)" + if check_empty_pattern "$EXPECTED_LOG" "Expected log"; then continue fi fi - "$TOR_BINARY" -f "./torrc" \ - --defaults-torrc "$DEFAULTS" \ - --dump-config short \ - $CMDLINE > "${DATA_DIR}/output_raw.${testname}" \ - || fail_printf "'%s': Tor --dump-config reported an error." \ - "$EXPECTED" - - "$FILTER" "${DATA_DIR}/output_raw.${testname}" \ - > "${DATA_DIR}/output.${testname}" \ - || fail_printf "'%s': Filter '%s' reported an error." \ - "$EXPECTED" \ - "$FILTER" - - if cmp "$EXPECTED" "${DATA_DIR}/output.${testname}" > /dev/null; then + dump_config "./torrc" \ + "$DEFAULTS" \ + "$CMDLINE" \ + "${DATA_DIR}/output_raw.${testname}" \ + "$EXPECTED" \ + "" + + filter "${DATA_DIR}/output_raw.${testname}" \ + "${DATA_DIR}/output.${testname}" \ + "$EXPECTED" \ + "" + + if check_diff "$EXPECTED" \ + "${DATA_DIR}/output.${testname}" \ + "./torrc" \ + "$DEFAULTS" \ + "$CMDLINE" \ + "$EXPECTED" \ + ""; then # Check round-trip. - "$TOR_BINARY" -f "${DATA_DIR}/output.${testname}" \ - --defaults-torrc "$EMPTY" \ - --dump-config short \ - > "${DATA_DIR}/output_2_raw.${testname}" \ - || fail_printf "'%s': Tor --dump-config reported an %s." \ - "$EXPECTED" \ - "error on round-trip" - - "$FILTER" "${DATA_DIR}/output_2_raw.${testname}" \ - > "${DATA_DIR}/output_2.${testname}" \ - || fail_printf "'%s': Filter '%s' reported an error." \ - "$EXPECTED" \ - "$FILTER" - - if ! cmp "${DATA_DIR}/output.${testname}" \ - "${DATA_DIR}/output_2.${testname}"; then - fail_printf "'%s': did not match on round-trip:" \ - "$EXPECTED" - diff -u "${DATA_DIR}/output.${testname}" \ - "${DATA_DIR}/output_2.${testname}" >&2 \ - || true - fi - else - if test "$(wc -c < "${DATA_DIR}/output.${testname}")" = 0; then - # There was no output -- probably we failed. - fail_printf "'%s': Tor said:" \ - "$EXPECTED" - "$TOR_BINARY" -f "./torrc" \ - --defaults-torrc "$DEFAULTS" \ - --verify-config \ - $CMDLINE >&2 \ - || true - fi - fail_printf "'%s' did not match:" \ - "$EXPECTED" - diff -u "$EXPECTED" "${DATA_DIR}/output.${testname}" >&2 \ - || true + dump_config "${DATA_DIR}/output.${testname}" \ + "$EMPTY" \ + "" \ + "${DATA_DIR}/output_2_raw.${testname}" \ + "$EXPECTED" \ + "on round-trip" + + filter "${DATA_DIR}/output_2_raw.${testname}" \ + "${DATA_DIR}/output_2.${testname}" \ + "$EXPECTED" \ + "on round-trip" + + check_diff "${DATA_DIR}/output.${testname}" \ + "${DATA_DIR}/output_2.${testname}" \ + "${DATA_DIR}/output.${testname}" \ + "$EMPTY" \ + "" \ + "$EXPECTED" \ + "on round-trip" || true fi - if test -f "$EXPECTED_LOG" || test "$NEXT_TEST"; then + if test -f "$EXPECTED_LOG"; then # This case should succeed: run verify-config and see if it does. - # - # As a temporary hack, we also use this code when --dump-config - # has failed, to display the error logs. - if ! test -f "$EXPECTED_LOG"; then - NON_EMPTY="${DATA_DIR}/NON_EMPTY" - echo "This pattern should not match any log messages" \ - > "$NON_EMPTY" - EXPECTED_LOG=$NON_EMPTY - fi - "$TOR_BINARY" --verify-config \ - -f ./torrc \ - --defaults-torrc "$DEFAULTS" \ - $CMDLINE \ - > "${DATA_DIR}/output_log.${testname}" \ - || fail_printf "'%s': Tor --verify-config reported an error." \ - "$EXPECTED_LOG" - - expect_log="$(cat "${EXPECTED_LOG}")" - if grep "$expect_log" "${DATA_DIR}/output_log.${testname}" \ - > /dev/null; then - : - else - fail_printf "Expected '%s':\\n%s\\nTor said:" \ - "$EXPECTED_LOG" \ - "$expect_log" - cat "${DATA_DIR}/output_log.${testname}" >&2 - fi - fi - - if test -z "$NEXT_TEST"; then - echo "OK" + verify_config "./torrc" \ + "$DEFAULTS" \ + "$CMDLINE" \ + "${DATA_DIR}/output_log.${testname}" \ + "$TRUE" \ + "$EXPECTED_LOG" \ + "succeed" + + check_pattern "$EXPECTED_LOG" \ + "${DATA_DIR}/output_log.${testname}" \ + "log" fi elif test -f "$ERROR"; then # This case should fail: run verify-config and see if it does. if ! test -s "$ERROR"; then - fail_printf "Error file '%s' is empty.%s" \ - "$ERROR" \ - "(Empty error files match any output.)" - continue - fi - - "$TOR_BINARY" --verify-config \ - -f ./torrc \ - --defaults-torrc "$DEFAULTS" \ - $CMDLINE \ - > "${DATA_DIR}/output.${testname}" \ - && fail_printf "'%s': Tor did not report an error." \ - "$ERROR" - - expect_err="$(cat "${ERROR}")" - if grep "$expect_err" "${DATA_DIR}/output.${testname}" > /dev/null; then - echo "OK" - else - fail_printf "Expected '%s':\\n%s\\nTor said:" \ - "$ERROR" \ - "$expect_err" - cat "${DATA_DIR}/output.${testname}" >&2 + if check_empty_pattern "$ERROR" "Error"; then + continue + fi fi + verify_config "./torrc" \ + "$DEFAULTS" \ + "$CMDLINE" \ + "${DATA_DIR}/output.${testname}" \ + "$FALSE" \ + "$ERROR" \ + "report an error" + + check_pattern "$ERROR" \ + "${DATA_DIR}/output.${testname}" \ + "error" else # This case is not actually configured with a success or a failure. # call that an error. fail_printf "Did not find ${dir}/*expected or ${dir}/*error." fi + if test -z "$NEXT_TEST"; then + echo "OK" + fi + cd "$PREV_DIR" done -exit $FINAL_EXIT +exit "$FINAL_EXIT" |