Subject: Re: [PATCH 2/2] t6402: check exit status of ls-files

From: Đoàn Trần Công Danh <[email-masked]>
Date: Thu, 22 Apr 2021 22:07:36 +0700

On 2021-04-22 20:49:04+0700, Đoàn Trần Công Danh <[email-masked]> wrote:
> On 2021-04-21 16:32:40-0700, Junio C Hamano <[email-masked]> wrote:
> > Eric Sunshine <[email-masked]> writes:
> > 
> > > On Wed, Apr 21, 2021 at 12:55 PM Eric Sunshine <[email-masked]> wrote:
> > >>     count_ls_files 5 -s &&
> > >>     count_ls_files 3 -u &&
> > >>     count_ls_files 1 -u one~HEAD &&
> > >>     ...
> > >>
> > >> The nice thing about having a helper function is that it can clean up
> > >> after itself by not leaving a new file lying around, thus you wouldn't
> > >> have to make adjustments to the expected number of untracked files (as
> > >> mentioned in the commit message). If this is the sort of thing which
> > >> comes up often enough (if there are more such cases beyond the two
> > >> scripts you changed in this series), then it might make sense to
> > >> promote the helper function to test-lib-functions.sh.
> > >
> > > The frequency with which this idiom crops up with commands beyond
> > > git-ls-files suggests the more general solution of supporting it
> > > directly in test-lib-functions.sh for any command. For instance:
> > >
> > >     test_cmd_line_count = 3 git ls-files -u &&
> > >
> > > Or, perhaps, a new mode of test_line_count():
> > >
> > >     test_line_count = 3 -c git ls-files -u &&
> 
> Hm, I'm not sure how would we implement such mode:
> 
> * Will we run such command in a subprocess and and pipe to "wc -l"
>   directly to avoid a temporary file, but we will lose the exit code
>   of running command in process?
> * Will we run in a separated chain? Thus, a temporary file would be
>   created, skimming over test-lib-functions.sh, I couldn't find any
>   convention for creating such files, except for specific use cases,
>   let's say "*.config".
> * Another clever hacks that I don't know *shrug*

Hm, I figured out, just a bit insane for reviewing.
-----8<--------
Subject: [PATCH] test-lib-functions: add test_line_count_in helper

Signed-off-by: Đoàn Trần Công Danh <[email-masked]>
---
 t/t0000-basic.sh        |  7 +++++
 t/test-lib-functions.sh | 62 +++++++++++++++++++++++++++++++++++++++++
 2 files changed, 69 insertions(+)

diff --git a/t/t0000-basic.sh b/t/t0000-basic.sh
index 705d62cc27..2ddb50e919 100755
--- a/t/t0000-basic.sh
+++ b/t/t0000-basic.sh
@@ -60,6 +60,13 @@ test_expect_success '.git/objects should have 3 subdirectories' '
 	test_line_count = 3 full-of-directories
 '
 
+test_expect_success 'check test_line_count_in' '
+	test_line_count_in --stdout = 4 --stderr = 3 -- sh -c "
+		printf \"%s\\n\" 1 2 3 4
+		printf >&2 \"%s\\n\" a b c
+		"
+'
+
 ################################################################
 # Test harness
 test_expect_success 'success is reported like this' '
diff --git a/t/test-lib-functions.sh b/t/test-lib-functions.sh
index 6348e8d733..3b3dc3020a 100644
--- a/t/test-lib-functions.sh
+++ b/t/test-lib-functions.sh
@@ -817,6 +817,68 @@ test_line_count () {
 	fi
 }
 
+# test_line_count_in checks if stdout and/or stderr has the number of lines it
+# ought to. E.g.
+#
+# 	test_expect_success 'product 1 line in stdout and 2 lines in stderr' '
+# 		test_line_count_in --stdout = 1 --stderr = 3 do_something
+# 	'
+test_line_count_in () {
+	local out_ops=-ge
+	local out_val=0
+	local err_ops=-ge
+	local err_val=0
+	local opt_set=
+
+	while test $# != 0
+	do
+		case "$1" in
+		--stdout)
+			if test $# -lt 3
+			then
+				BUG "need ops and value for --stdout"
+			fi
+			out_ops=$2
+			out_val=$3
+			opt_set=yes
+			shift 3
+			;;
+		--stderr)
+			if test $# -lt 3
+			then
+				BUG "need ops and value for --stderr"
+			fi
+			err_ops=$2
+			err_val=$3
+			opt_set=yes
+			shift 3
+			;;
+		--)
+			shift
+			break
+			;;
+		esac
+	done
+
+	if test -z "$opt_set"
+	then
+		BUG "need check ops for test_line_count_in"
+	else
+		! (
+		test $(
+			(
+			test $(
+				( "$@" || echo "'$*' run into failure" >&3) |
+				wc -l
+				) "$out_ops" "$out_val" ||
+			echo "test_line_count_in --stdout: !$out_ops $out_val '$*'" >&3
+			) 2>&1 | wc -l
+		) "$err_ops" "$err_val" ||
+		echo "test_line_count_in --stderr: !$out_ops $out_val '$*'" >&3
+		) 3>&1 | grep .
+	fi
+}
+
 test_file_size () {
 	test "$#" -ne 1 && BUG "1 param"
 	test-tool path-utils file-size "$1"
-- 
2.31.1.500.gbc6bbdd36b