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
 

Reply via email to