Module Name: src Committed By: kre Date: Thu Nov 16 19:41:42 UTC 2017
Modified Files: src/tests/bin/sh: t_option.sh Log Message: Add a test case for "set -X". Currently (or when testing any shell that does not support -X) the test will be skipped (also for [m]ksh (but not ksh93 etc) where there is an absurdly badly named -X option, skip the new test for them as well.) When -X appears in /bin/sh, this will verify that it is probably working (the test is MUCH more gruelling than any rational use of -X would be.) To generate a diff of this commit: cvs rdiff -u -r1.5 -r1.6 src/tests/bin/sh/t_option.sh Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/tests/bin/sh/t_option.sh diff -u src/tests/bin/sh/t_option.sh:1.5 src/tests/bin/sh/t_option.sh:1.6 --- src/tests/bin/sh/t_option.sh:1.5 Sat Jul 15 18:52:21 2017 +++ src/tests/bin/sh/t_option.sh Thu Nov 16 19:41:41 2017 @@ -1,4 +1,4 @@ -# $NetBSD: t_option.sh,v 1.5 2017/07/15 18:52:21 kre Exp $ +# $NetBSD: t_option.sh,v 1.6 2017/11/16 19:41:41 kre Exp $ # # Copyright (c) 2016 The NetBSD Foundation, Inc. # All rights reserved. @@ -77,7 +77,7 @@ test_option_on_off() # if we do not do this, -x tracing splatters stderr # for some shells, -v does as well (is that correct?) case "${opt}" in - (*[xv]*) exec 2>/dev/null;; + (*[xXv]*) exec 2>/dev/null;; esac o="$-" @@ -498,6 +498,329 @@ set_x_body() { 'set -x; for i in 111 222 333; do printf "%s" $i; done; echo; exit 0' } +atf_test_case set_X +set_X_head() { + atf_set "descr" "Tests that 'set -X' turns on command exec logging " \ + "and that it enables set -x and retains a single fd" +} +set_X_body() { + + # First we need to verify that $TEST_SH supports -X + test_optional_on_off X || + atf_skip "$TEST_SH does not support -X" + + # and that the -X it implements is the -X we expect + $TEST_SH -c 'exec 2>/dev/null; + set +x; set -X; + case "$-" in (*x*) exit 0;; esac; + exit 1' || + atf_skip "$TEST_SH supports -X but not 'the' -X" + + # Above has already tested that set -X => set -x + # Now test that set +X => set +x + # and that set -x and set +x do not affect -X + + atf_check -s exit:0 -o empty -e ignore ${TEST_SH} -c \ + 'set -x; set +X; case "$-" in (*x*) echo FAIL; exit 1;; esac' + + atf_check -s exit:0 -o empty -e ignore ${TEST_SH} -c \ + 'set -X; set +x; + case "$-" in (*x*) echo FAIL; exit 1;; esac + case "$-" in (*X*) exit 0;; esac; echo ERROR; exit 2' + + atf_check -s exit:0 -o empty -e ignore ${TEST_SH} -c \ + 'set -X; set +x; set -x; + case "$-" in (*x*X*|*X*x*) exit 0;; esac; echo ERROR; exit 2' + + atf_check -s exit:0 -o empty -e ignore ${TEST_SH} -c \ + 'set +X; set -x; + case "$-" in (*X*) echo FAIL; exit 1;; esac + case "$-" in (*x*) exit 0;; esac; echo ERROR; exit 2' + + atf_check -s exit:0 -o empty -e ignore ${TEST_SH} -c \ + 'set +X; set -x; set +x; + case "$-" in (*[xX]*) echo FAULT; exit 3;; esac' + + # The following just verify regular tracing using -X instead of -x + # These are the same tests as the -x test (set_x) performs. + + # check that cmd output appears after -X is enabled + atf_check -s exit:0 \ + -o match:OKOK -o not-match:echo -o not-match:printf \ + -e not-match:printf -e match:OK -e match:echo \ + ${TEST_SH} -ec 'printf "%s" OK; set -X; echo OK; exit 0' + + # and that it stops again afer -X is disabled + atf_check -s exit:0 \ + -o match:OKOK -o not-match:echo -o not-match:printf \ + -e match:printf -e match:OK -e not-match:echo \ + ${TEST_SH} -ec 'set -X; printf "%s" OK; set +X; echo OK; exit 0' + + # also check that PS4 is output correctly + atf_check -s exit:0 \ + -o match:OK -o not-match:echo \ + -e match:OK -e match:Run:echo \ + ${TEST_SH} -ec 'PS4=Run:; set -X; echo OK; exit 0' + + # end copies of -x tests ... + + # now check that we can move stderr around without affecting -X output + + atf_check -s exit:0 \ + -o match:OKOK -o not-match:echo -o not-match:printf \ + -e match:printf -e match:OK -e match:echo \ + ${TEST_SH} -ecX 'printf "%s" OK; exec 2>/dev/null; echo OK' + atf_check -s exit:0 \ + -o match:OKOK -o not-match:echo -o not-match:printf \ + -e match:printf -e match:OK -e match:echo \ + ${TEST_SH} -ecX 'printf "%s" OK; exec 2>&1; echo OK' + atf_check -s exit:0 \ + -o match:OKOK -o not-match:echo -o not-match:printf \ + -e match:printf -e match:OK -e match:echo \ + ${TEST_SH} -ecX 'printf "%s" OK; exec 2>&-; echo OK' + + # and that we can put tracing on an external file, leaving stderr alone + + atf_require_prog grep + + rm -f X-trace + atf_check -s exit:0 \ + -o match:OKOK -o not-match:echo -o not-match:printf \ + -e empty \ + ${TEST_SH} -ec 'PS4=; set -X 2>X-trace; printf "%s" OK; echo OK' + test -s X-trace || atf_fail "T1: Failed to create trace output file" + grep >/dev/null 2>&1 'printf.*%s.*OK' X-trace || + atf_fail "T1: -X tracing missing printf" + grep >/dev/null 2>&1 'echo.*OK' X-trace || + atf_fail "T1: -X tracing missing echo" + + rm -f X-trace + atf_check -s exit:0 \ + -o match:OKOK -o not-match:echo -o not-match:printf \ + -e empty \ + ${TEST_SH} -ec \ + 'PS4=; set -X 2>X-trace; + printf "%s" OK; + exec 2>/dev/null; + echo OK' + test -s X-trace || atf_fail "T2: Failed to create trace output file" + grep >/dev/null 2>&1 'printf.*%s.*OK' X-trace || + atf_fail "T2: -X tracing missing printf" + grep >/dev/null 2>&1 'exec' X-trace || + atf_fail "T2: -X tracing missing exec" + grep >/dev/null 2>&1 'echo.*OK' X-trace || + atf_fail "T2: -X tracing missing echo after stderr redirect" + + rm -f X-trace + atf_check -s exit:0 \ + -o match:OKOK -o not-match:echo -o not-match:printf \ + -e empty \ + ${TEST_SH} -ec \ + 'PS4=; set -X 2>X-trace; + printf "%s" OK; + set -X 2>/dev/null; + echo OK' + test -s X-trace || atf_fail "T3: Failed to create trace output file" + grep >/dev/null 2>&1 'printf.*%s.*OK' X-trace || + atf_fail "T3: -X tracing missing printf" + grep >/dev/null 2>&1 'set.*-X' X-trace || + atf_fail "T3: -X tracing missing set -X" + grep >/dev/null 2>&1 'echo.*OK' X-trace && + atf_fail "T3: -X tracing included echo after set -X redirect" + + rm -f X-trace + atf_check -s exit:0 \ + -o match:OKOK -o not-match:echo -o not-match:printf \ + -e match:echo -e match:OK -e not-match:printf \ + ${TEST_SH} -ec \ + 'PS4=; set -X 2>X-trace; + printf "%s" OK; + set -X; + echo OK' + test -s X-trace || atf_fail "T4: Failed to create trace output file" + grep >/dev/null 2>&1 'printf.*%s.*OK' X-trace || + atf_fail "T4: -X tracing missing printf" + grep >/dev/null 2>&1 'set.*-X' X-trace || + atf_fail "T4: -X tracing missing set -X" + grep >/dev/null 2>&1 'echo.*OK' X-trace && + atf_fail "T4: -X tracing included echo after set -X redirect" + + # Now check that -X and the tracing files work properly wrt functions + + # a shell that supports -X should support "local -" ... but verify + + ( ${TEST_SH} -c 'fn() { local - || exit 2; set -f; }; set +f; fn; + case "$-" in ("*f*") exit 1;; esac; exit 0' ) 2>/dev/null || + atf_skip "-X function test: 'local -' unsupported" + + rm -f X-trace X-trace-fn + atf_check -s exit:0 \ + -o match:OKhelloGOOD \ + -e empty \ + ${TEST_SH} -c ' + say() { + printf "%s" "$*" + } + funct() { + local - + + set -X 2>X-trace-fn + say hello + } + + set -X 2>X-trace + + printf OK + funct + echo GOOD + ' + test -s X-trace || atf_fail "T5: Failed to create trace output file" + test -s X-trace-fn || atf_fail "T5: Failed to create fn trace output" + grep >/dev/null 2>&1 'printf.*OK' X-trace || + atf_fail "T5: -X tracing missing printf" + grep >/dev/null 2>&1 funct X-trace || + atf_fail "T5: -X tracing missing funct" + grep >/dev/null 2>&1 'set.*-X' X-trace || + atf_fail "T5: -X tracing missing set -X from in funct" + grep >/dev/null 2>&1 'echo.*GOOD' X-trace || + atf_fail "T5: -X tracing missing echo after funct redirect" + grep >/dev/null 2>&1 'say.*hello' X-trace && + atf_fail "T5: -X tracing included 'say' after funct redirect" + grep >/dev/null 2>&1 'say.*hello' X-trace-fn || + atf_fail "T5: -X funct tracing missed 'say'" + + rm -f X-trace X-trace-fn + + atf_check -s exit:0 \ + -o match:OKhelloGOOD \ + -e empty \ + ${TEST_SH} -c ' + say() { + printf "%s" "$*" + } + funct() { + local - + + set +X + say hello + } + + set -X 2>X-trace + + printf OK + funct + echo GOOD + ' + test -s X-trace || atf_fail "T6: Failed to create trace output file" + grep >/dev/null 2>&1 'printf.*OK' X-trace || + atf_fail "T6: -X tracing missing printf" + grep >/dev/null 2>&1 funct X-trace || + atf_fail "T6: -X tracing missing funct" + grep >/dev/null 2>&1 'set.*+X' X-trace || + atf_fail "T6: -X tracing missing set +X from in funct" + grep >/dev/null 2>&1 'echo.*GOOD' X-trace || + atf_fail "T6: -X tracing missing echo after funct redirect" + grep >/dev/null 2>&1 'say.*hello' X-trace && + atf_fail "T6: -X tracing included 'say' after funct redirect" + + rm -f X-trace + + atf_check -s exit:0 \ + -o match:OKtracednotraceGOOD \ + -e match:say -e match:traced -e not-match:notrace \ + ${TEST_SH} -c ' + say() { + printf "%s" "$*" + } + funct() { + local - + + set +X -x + + say traced + exec 2>/dev/null + say notrace + + } + + set -X 2>X-trace + + printf OK + funct + echo GOOD + ' + test -s X-trace || atf_fail "T7: Failed to create trace output file" + grep >/dev/null 2>&1 'printf.*OK' X-trace || + atf_fail "T7: -X tracing missing printf" + grep >/dev/null 2>&1 funct X-trace || + atf_fail "T7: -X tracing missing funct" + grep >/dev/null 2>&1 'set.*+X.*-x' X-trace || + atf_fail "T7: -X tracing missing set +X -x from in funct" + grep >/dev/null 2>&1 'echo.*GOOD' X-trace || + atf_fail "T7: -X tracing missing echo after funct +X" + grep >/dev/null 2>&1 'say.*hello' X-trace && + atf_fail "T7: -X tracing included 'say' after funct +X" + + rm -f X-trace X-trace-fn + atf_check -s exit:0 \ + -o "match:OKg'daybye-bye.*hello.*GOOD" \ + -e empty \ + ${TEST_SH} -c ' + say() { + printf "%s" "$*" + } + fn1() { + local - + + set -X 2>>X-trace-fn + say "g'\''day" + "$@" + say bye-bye + } + fn2() { + set +X + say hello + "$@" + say goodbye + } + + set -X 2>X-trace + + printf OK + fn1 + fn1 fn2 + fn1 fn1 fn2 + fn1 fn2 fn1 fn2 fn1 + fn1 fn1 fn2 fn2 fn1 + echo GOOD + ' + + # That test generally succeeds if the earlier ones did + # and if it did not dump core! + + # But we can check a few things... + + test -s X-trace || atf_fail "T8: Failed to create trace output file" + test -s X-trace-fn || atf_fail "T8: Failed to create trace output file" + grep >/dev/null 2>&1 'printf.*OK' X-trace || + atf_fail "T8: -X tracing missing printf" + grep >/dev/null 2>&1 fn1 X-trace || + atf_fail "T8: -X tracing missing fn1" + grep >/dev/null 2>&1 'set.*-X' X-trace || + atf_fail "T8: -X tracing missing set -X from in fn1" + grep >/dev/null 2>&1 'echo.*GOOD' X-trace || + atf_fail "T8: -X tracing missing echo after fn1 redirect" + grep >/dev/null 2>&1 'say.*hello' X-trace && + atf_fail "T8: -X tracing included 'say' after fn2 +X" + grep >/dev/null 2>&1 'say.*hello' X-trace-fn && + atf_fail "T8: -X fn tracing included 'say' after fn2 +X" + + + rm -f X-trace + + return 0 +} + opt_test_setup() { test -n "$1" || { echo >&2 "Internal error"; exit 1; } @@ -686,7 +1009,7 @@ Option_switching_body() { # be accessable via the "set" command, just the command line. # We allow for -i to work with set, as that makes some sense, # -c and -s do not. - test_optional_on_off E i I p q V || true + test_optional_on_off E i I p q V X || true # Also test (some) option combinations ... # only testing posix options here, because it is easier... @@ -720,6 +1043,7 @@ atf_init_test_cases() { atf_add_test_case set_u atf_add_test_case set_v atf_add_test_case set_x + atf_add_test_case set_X atf_add_test_case vi_emacs_VE_toggle