From 77285ceee8f82b65020567883e5317be5f88be61 Mon Sep 17 00:00:00 2001 From: Julian Squires Date: Mon, 16 Oct 2017 13:57:09 -0400 Subject: [PATCH] Make output matching more robust After struggling with what seem to be tty driver timing differences, not to mention different people's shell output, I gave in and removed the leading CRLF hack from matching. This means that now no test can have the same trailing input as the output it matches. We're also more careful about signal names. --- .gitignore | 5 +-- helpers/echo-rot13.c | 35 +++++++++++++++++++ helpers/echo-signal.c | 20 +++++++++-- helpers/harness.tcl | 13 +++---- stage_1/01-fork-exec.t | 2 ++ stage_1/03-cd-changes-directory.t | 3 +- stage_1/04-semicolon-separates-commands.t | 4 +-- stage_1/05-and-or-chaining.t | 26 +++++++------- stage_1/07-subshell.t | 8 ++--- stage_1/08-bang-negates-exit-code.t | 12 +++---- stage_1/10-multiline-list.t | 4 +-- stage_2/02-redirections.t | 4 +-- stage_2/04-ensure-pipes-are-closed.t | 4 +-- stage_2/07-bang-only-at-start-of-pipelines.t | 4 +-- stage_2/08-builtin-in-pipeline.t | 4 +-- .../01-executed-command-receives-signals.t | 13 ++++--- stage_3/02-job-control-with-fg-bg.t | 18 +++++----- stage_3/03-sequencing-with-suspend.t | 7 ++-- stage_3/05-sigquit.t | 6 ++-- stage_4/05-commands-can-be-quoted.t | 4 ++- stage_4/10-tilde-expansion.t | 2 +- stage_5/01-tab-completion.t | 4 +-- stage_5/02-basic-history.t | 9 ++--- stage_5/03-search-with-control-r.t | 10 +++--- 24 files changed, 142 insertions(+), 79 deletions(-) create mode 100755 helpers/echo-rot13.c diff --git a/.gitignore b/.gitignore index 96e9a1b..6acf8cd 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,8 @@ # binaries -helpers/echo-signal helpers/echo-exit +helpers/echo-rot13 +helpers/echo-signal helpers/exit-status-0 -helpers/list-fds helpers/fd-perms +helpers/list-fds helpers/timeout diff --git a/helpers/echo-rot13.c b/helpers/echo-rot13.c new file mode 100755 index 0000000..365923e --- /dev/null +++ b/helpers/echo-rot13.c @@ -0,0 +1,35 @@ +#if 0 +set -x "$(dirname $0)/$(basename $0 .c)" +exec ${CC:-cc} ${CFLAGS:--Wall -Wextra -g} $0 -o $1 +#endif + +/* Echo our arguments, rot13'd. */ + +#include +#include +#include +#include +#include +#include +#include + +static void rot13(char *s) +{ + while (*s) { + char c = *s|32; + if (c >= 'a' && c <= 'm') *s += 13; + else if (c >= 'n' && c <= 'z') *s -= 13; + ++s; + } +} + +int main(int argc, char **argv) +{ + for (int i = 1; i < argc; ++i) + rot13(argv[i]); + if (argc > 1) printf("%s", argv[1]); + for (int i = 2; i < argc; ++i) + printf(" %s", argv[i]); + puts(""); + return 0; +} diff --git a/helpers/echo-signal.c b/helpers/echo-signal.c index fdbe9ff..f377c96 100755 --- a/helpers/echo-signal.c +++ b/helpers/echo-signal.c @@ -9,19 +9,33 @@ exec ${CC:-cc} ${CFLAGS:--Wall -Wextra -g} $0 -o $1 #include #include #include +#include #include -static void echo(int n) +static char *awaited; + +static int int_of_signal_name(char *name) +{ + if (!strcmp(name, "INT")) return SIGINT; + if (!strcmp(name, "TSTP")) return SIGTSTP; + if (!strcmp(name, "CONT")) return SIGCONT; + abort(); +} + +static void echo(int _) { - printf("%d\n", n); /* safe-ish because we don't do anything else. hah. */ + (void)_; + puts(awaited); /* never do stuff like this in signal handlers. */ } int main(int argc, char **argv) { struct sigaction action = { .sa_handler = echo }; if (2 != argc) abort(); - int sig = atoi(argv[1]); + int sig = int_of_signal_name(argv[1]); + awaited = argv[1]; sigaction(sig, &action, NULL); + puts("ready"); pause(); return 0; } diff --git a/helpers/harness.tcl b/helpers/harness.tcl index 7e226c2..2624131 100755 --- a/helpers/harness.tcl +++ b/helpers/harness.tcl @@ -95,7 +95,7 @@ while {![eof $test_file]} { seek $test_file 0 start log_user 0 -set send_slow { 10 .001 } +set send_slow { 1 .01 } setup_execution_environment if [catch {spawn $shell} err] {error $err} # waiting for first prompt can help @@ -125,12 +125,13 @@ proc not_ok {} { proc is {x} { uplevel 1 [list if $x {ok} {not_ok}]} proc expect_line {line} { - # NB: the \r\n at the start of the line here breaks fish, and - # makes this somewhat unreliable, but it's tricky to find an - # alternative that is as simple and stops cat from passing the - # tests. + # NB: this is fairly unreliable, and we should have some lint + # where we reject tests whose expected output would match the tail + # of their input. There doesn't seem to be a better way to deal + # with the output and timing differences between shells, short of + # going full ptrace as mentioned previously. set rv [expect { - "\r\n$line\r\n" {return 1} + "$line\r\n" {return 1} default {return 0} }] expect * diff --git a/stage_1/01-fork-exec.t b/stage_1/01-fork-exec.t index 8d1736d..0acce79 100644 --- a/stage_1/01-fork-exec.t +++ b/stage_1/01-fork-exec.t @@ -2,5 +2,7 @@ ← foo bar → tr a-z n-za-m⏎foo bar baz⏎^D ← sbb one onm +→ ./helpers/echo-rot13 foo bar⏎ +← sbb one → ./helpers/echo-exit ./helpers/successful-exit-status⏎ ← 0 diff --git a/stage_1/03-cd-changes-directory.t b/stage_1/03-cd-changes-directory.t index f91c2a0..295695f 100644 --- a/stage_1/03-cd-changes-directory.t +++ b/stage_1/03-cd-changes-directory.t @@ -1,5 +1,6 @@ → /bin/pwd⏎ ≠ /tmp → cd /tmp⏎ +→ cd ..⏎ → /bin/pwd⏎ -← /tmp +← / diff --git a/stage_1/04-semicolon-separates-commands.t b/stage_1/04-semicolon-separates-commands.t index 2507453..f70dd74 100644 --- a/stage_1/04-semicolon-separates-commands.t +++ b/stage_1/04-semicolon-separates-commands.t @@ -3,5 +3,5 @@ ← foobarbaz → cd /tmp; pwd⏎ ← /tmp -→ false; echo foo⏎ -← foo +→ false; echo-rot13 foo⏎ +← sbb diff --git a/stage_1/05-and-or-chaining.t b/stage_1/05-and-or-chaining.t index d181b88..9342429 100644 --- a/stage_1/05-and-or-chaining.t +++ b/stage_1/05-and-or-chaining.t @@ -1,13 +1,15 @@ # POSIX calls these AND Lists and OR Lists -→ true && echo foo⏎ -← foo -→ false && echo foo⏎ -≠ foo -→ true && false && echo foo⏎ -≠ foo -→ false || echo foo⏎ -← foo -→ true || false || echo foo⏎ -≠ foo -→ false || true && echo foo⏎ -← foo +→ true && echo-rot13 foo⏎ +← sbb +→ false && echo-rot13 foo⏎ +≠ sbb +→ true && false && echo-rot13 foo⏎ +≠ sbb +→ false || echo-rot13 foo⏎ +← sbb +→ true || false || echo-rot13 foo⏎ +≠ sbb +→ false || true && echo-rot13 foo⏎ +← sbb +→ nonexistent-command || echo-rot13 zim⏎ +← mvz diff --git a/stage_1/07-subshell.t b/stage_1/07-subshell.t index e03020e..838650d 100644 --- a/stage_1/07-subshell.t +++ b/stage_1/07-subshell.t @@ -4,7 +4,7 @@ ← /tmp → pwd⏎ ≠ /tmp -→ (exit 1) && echo foo⏎ -≠ foo -→ (exit 0 && exit 1) && echo foo⏎ -← foo +→ (exit 1) && echo-rot13 foo⏎ +≠ sbb +→ (exit 0 && exit 1) && echo-rot13 foo⏎ +← sbb diff --git a/stage_1/08-bang-negates-exit-code.t b/stage_1/08-bang-negates-exit-code.t index 1ae6748..4018a52 100644 --- a/stage_1/08-bang-negates-exit-code.t +++ b/stage_1/08-bang-negates-exit-code.t @@ -1,6 +1,6 @@ -→ ! false && echo foo⏎ -← foo -→ ! true && echo foo⏎ -≠ foo -→ ! true || echo foo⏎ -← foo +→ ! false && echo-rot13 foo⏎ +← sbb +→ ! true && echo-rot13 foo⏎ +≠ sbb +→ ! true || echo-rot13 foo⏎ +← sbb diff --git a/stage_1/10-multiline-list.t b/stage_1/10-multiline-list.t index c78e190..3f67029 100644 --- a/stage_1/10-multiline-list.t +++ b/stage_1/10-multiline-list.t @@ -1,2 +1,2 @@ -→ true &&⏎false ||⏎echo foo ||⏎echo bar⏎ -← foo +→ true &&⏎false ||⏎echo-rot13 foo ||⏎echo-rot13 bar⏎ +← sbb diff --git a/stage_2/02-redirections.t b/stage_2/02-redirections.t index 38c05ae..04b76a0 100644 --- a/stage_2/02-redirections.t +++ b/stage_2/02-redirections.t @@ -8,8 +8,8 @@ # NB echo -n isn't portable... → echo -n a > foo ; echo b >> foo ; cat foo⏎ ← ab -→ cat < /non-existent-file || echo foo⏎ -← foo +→ cat < /non-existent-file || echo-rot13 foo⏎ +← sbb → cat /non-existent-file 2>foo || grep -c . foo && cat < foo⏎ diff --git a/stage_2/04-ensure-pipes-are-closed.t b/stage_2/04-ensure-pipes-are-closed.t index 00def44..4004254 100644 --- a/stage_2/04-ensure-pipes-are-closed.t +++ b/stage_2/04-ensure-pipes-are-closed.t @@ -1,4 +1,4 @@ # This will hang in the case of a very common bug: you forget to close # the other ends of the pipe. -→ cat /dev/null | echo foo⏎ -← foo +→ cat /dev/null | echo-rot13 foo⏎ +← sbb diff --git a/stage_2/07-bang-only-at-start-of-pipelines.t b/stage_2/07-bang-only-at-start-of-pipelines.t index 56f87e7..7906a50 100644 --- a/stage_2/07-bang-only-at-start-of-pipelines.t +++ b/stage_2/07-bang-only-at-start-of-pipelines.t @@ -1,5 +1,5 @@ # Would prefer to test this but mksh doesn't agree #→ echo zim | ! tr z b | grep -qc bim || echo foo⏎ #≠ foo -→ ! echo zim | tr z b | grep -qc bim || echo foo⏎ -← foo +→ ! echo zim | tr z b | grep -qc bim || echo-rot13 foo⏎ +← sbb diff --git a/stage_2/08-builtin-in-pipeline.t b/stage_2/08-builtin-in-pipeline.t index 84ce145..4deef2d 100644 --- a/stage_2/08-builtin-in-pipeline.t +++ b/stage_2/08-builtin-in-pipeline.t @@ -1,4 +1,4 @@ → echo foo | cd /tmp | pwd⏎ ≠ /tmp -→ echo foo | cd /tmp | echo bar⏎ -← bar +→ echo foo | cd /tmp | echo-rot13 bar⏎ +← one diff --git a/stage_3/01-executed-command-receives-signals.t b/stage_3/01-executed-command-receives-signals.t index a7e64c5..61db2a6 100644 --- a/stage_3/01-executed-command-receives-signals.t +++ b/stage_3/01-executed-command-receives-signals.t @@ -1,10 +1,9 @@ # this would be nicer if we already had $@... -→ echo-signal 2⏎ +→ echo-signal INT⏎ +← ready → ^C⏎ -← 2 -→ cat⏎ -→ ^\⏎echo foo⏎ -← foo -→ echo-signal 20⏎ +← INT +→ echo-signal TSTP⏎ +← ready → ^Z⏎ -← 20 +← TSTP diff --git a/stage_3/02-job-control-with-fg-bg.t b/stage_3/02-job-control-with-fg-bg.t index 5f73fe6..4923564 100644 --- a/stage_3/02-job-control-with-fg-bg.t +++ b/stage_3/02-job-control-with-fg-bg.t @@ -1,12 +1,14 @@ -→ echo-signal 18⏎ +→ echo-signal CONT⏎ +← ready → ^Z -→ echo foo⏎ -← foo +→ echo-rot13 foo⏎ +← sbb → fg⏎ -← 18 -→ echo-signal 2 &⏎ -→ echo foo⏎ -← foo +← CONT +→ echo-signal INT &⏎ +← ready +→ echo-rot13 foo⏎ +← sbb → fg⏎ → ^C⏎ -← 2 +← INT diff --git a/stage_3/03-sequencing-with-suspend.t b/stage_3/03-sequencing-with-suspend.t index 5674a7a..3f7a2de 100644 --- a/stage_3/03-sequencing-with-suspend.t +++ b/stage_3/03-sequencing-with-suspend.t @@ -1,5 +1,6 @@ -→ echo-signal 2 & echo foo⏎ -← foo +→ echo-signal INT & sleep 1; echo-rot13 foo⏎ +← ready +← sbb → fg⏎ → ^C⏎ -← 2 +← INT diff --git a/stage_3/05-sigquit.t b/stage_3/05-sigquit.t index 0416c13..d97880a 100644 --- a/stage_3/05-sigquit.t +++ b/stage_3/05-sigquit.t @@ -1,2 +1,4 @@ -→ cat⏎^\⏎echo foo⏎ -← foo +→ cat⏎^\⏎echo-rot13 foo⏎ +← sbb +→ ^\^\echo-rot13 blah⏎ +← oynu diff --git a/stage_4/05-commands-can-be-quoted.t b/stage_4/05-commands-can-be-quoted.t index cad30f4..c261300 100644 --- a/stage_4/05-commands-can-be-quoted.t +++ b/stage_4/05-commands-can-be-quoted.t @@ -1,4 +1,6 @@ → e'ch'o foo⏎ ← foo -→ ''''""/"b"i'n/e'"c"ho''"" yup⏎ +→ ''''""/"b"i'n/e'"c"ho''"" yup; true⏎ ← yup +→ ""'echo'"-"rot1'3' yup⏎ +← lhc diff --git a/stage_4/10-tilde-expansion.t b/stage_4/10-tilde-expansion.t index 543b41f..b721a94 100644 --- a/stage_4/10-tilde-expansion.t +++ b/stage_4/10-tilde-expansion.t @@ -1,4 +1,4 @@ -→ echo ~⏎ +→ echo ~; true⏎ ≠ ~ # XXX this will vary by system; use magic. → echo ~root⏎ diff --git a/stage_5/01-tab-completion.t b/stage_5/01-tab-completion.t index a4c1ae6..ebc7194 100644 --- a/stage_5/01-tab-completion.t +++ b/stage_5/01-tab-completion.t @@ -1,4 +1,4 @@ # not POSIX → touch foo bar⏎ -→ ech^I f^I b^I⏎ -← foo bar +→ ech^I-rot^I f^I b^I⏎ +← sbb one diff --git a/stage_5/02-basic-history.t b/stage_5/02-basic-history.t index bde7318..f3409c1 100644 --- a/stage_5/02-basic-history.t +++ b/stage_5/02-basic-history.t @@ -1,5 +1,6 @@ -→ echo foo⏎ -← foo -→ echo bar⏎ +→ echo-rot13 foo⏎ +← sbb +→ echo-rot13 bar⏎ +← one → ⇑⇑⏎ -← foo +← sbb diff --git a/stage_5/03-search-with-control-r.t b/stage_5/03-search-with-control-r.t index d271b59..f92d742 100644 --- a/stage_5/03-search-with-control-r.t +++ b/stage_5/03-search-with-control-r.t @@ -1,7 +1,7 @@ → true⏎ -→ echo foo⏎ -← foo -→ echo bar⏎ -← bar +→ echo-rot13 foo⏎ +← sbb +→ echo-rot13 bar⏎ +← one → ^Rf⏎ -← foo +← sbb