-
Notifications
You must be signed in to change notification settings - Fork 5
/
test
executable file
·132 lines (116 loc) · 3.18 KB
/
test
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
#!/usr/bin/ruby --disable-gems
# We're being very lazy here and assuming macOS with some preconditions:
# /bin/bash is bash 3.2
# /usr/local/bin/bash is bash 4+
# /usr/local/bin/zsh is installed
require_relative 'shell'
require 'timeout'
REQUIRE_ESCAPES = %w(
alias alloc bg bind bindkey break breaksw builtins case cd chdir command complete continue default dirs do done echo
echotc elif else end endif endsw esac eval exec exit export fxlse fc fg filetest fi for foreach getopts glob goto
hash hashstat history hup if jobid jobs kill limit local log login logout ls-F nice nohup notify onintr popd
printenv pushd pwd read readonly rehash repeat return sched set setenv settc setty setvar shift source stop suspend
switch telltc test then time times trap true type ulimit umask unalias uncomplete unhash unlimit unset unsetenv
until wait where which while
)
ALIASES = REQUIRE_ESCAPES.map do |builtin|
%(\\alias #{builtin}='\\echo "unescaped #{builtin}: $0:$LINENO"')
end
INPUTS = [
[],
[
'\\set -eo pipefail',
],
[
'\\source hookbook.sh',
'\\echo $?',
],
[
'f() { \\echo $1; }',
'hookbook_add_hook f',
'hookbook_add_hook f',
],
[
'\\true',
'\\echo ok',
'\\echo ok | tr -d k',
'\\source hookbook.sh',
'\\echo ok | tr -d k',
],
]
PROMPT = '> '
# We call DEBUG/preexec a lot of times when we source hookbook.sh the second
# time. I wonder if we can cut that down to one.
BASH_EXPECT = <<EOF + PROMPT
\\true
preexec
precmd
> \\echo ok
preexec
ok
precmd
> \\echo ok | tr -d k
preexec
preexec
o
precmd
> \\source hookbook.sh
preexec
preexec
preexec
preexec
precmd
> \\echo ok | tr -d k
preexec
preexec
o
precmd
EOF
ZSH_EXPECT = BASH_EXPECT.gsub(/(preexec\n)+/, "preexec\n")
STRICT_EXPECT = <<EOF + PROMPT
\\source hookbook.sh
> \\echo $?
0
EOF
def run_test(version, expect, *argv, aliases: false)
inputs = INPUTS
inputs[0] = ALIASES if aliases
sh = Shell.new(*argv, prompt: PROMPT)
outputs = inputs.map do |commands|
sh.send_commands(commands)
sh.output!
end
sh.close
alias_lines, pipefail_lines, source_lines, setup_lines, output_lines = outputs
unescaped = (source_lines+setup_lines).select { |l| l.start_with?('unescaped ') }.uniq
title = "#{argv.first} #{version}#{' (escaping)' if aliases}"
if unescaped.any?
puts("NOT OK #{title}")
puts(unescaped)
abort('test failure')
elsif output_lines.join != expect
puts("NOT OK #{title}")
puts("HAVE: #{output_lines.join.inspect}")
puts("WANT: #{expect.inspect}")
abort('test failure')
elsif source_lines.join != STRICT_EXPECT
puts("NOT OK #{title}")
puts("failed strict check")
puts("HAVE: #{source_lines.join.inspect}")
puts("WANT: #{STRICT_EXPECT.inspect}")
abort('test failure')
else
puts("OK #{title}")
end
run_test(version, expect, *argv, aliases: true) unless aliases
rescue Timeout::Error
puts outputs
puts sh.output
raise
end
Shell.available_versions('zsh').each do |version, path|
run_test(version, ZSH_EXPECT, path, '--no-rcs', '--no-globalrcs', '-o', 'no_prompt_cr', '-o', 'no_zle')
end
Shell.available_versions('bash').each do |version, path|
run_test(version, BASH_EXPECT, path, '--noprofile', '--norc')
end