-
Notifications
You must be signed in to change notification settings - Fork 0
/
test
executable file
·259 lines (230 loc) · 7.43 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
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
#!/usr/bin/bash
command -v script &>/dev/null || { printf "These tests require the \`script\` utility!\n" >&2; exit 1; }
[ ${BASH_VERSION::1} -ge 5 ] || { printf "These tests require \`bash\` 5 or later to use multiple coprocesses!\n" >&2; exit 1; }
#{{{ coproc setup
printf "Setting up vim processes. . . " >&2
export SHELL="/usr/bin/bash"
coproc tvt {
export HOME="$(realpath "${BASH_SOURCE[0]%/*}")"
script -q -c 'TVT_TEST="-" vim -n -s /dev/fd/3 --not-a-term 4>&1 &>/dev/null' /dev/null 3<&0 < /dev/null 2>/dev/null &
trap "sleep 1; kill -9 $! 2>/dev/null" SIGINT
wait $!
}
actual="${tvt[0]}"
actual_PID=$tvt_PID
actual_in="${tvt[1]}"
# this is illegal but works at the moment so. . .
exec 3>&2 2>&-
coproc v {
export HOME="$(realpath "${BASH_SOURCE[0]%/*}")/tests"
script -q -c 'vim -n -s /dev/fd/3 --not-a-term 4>&1 &>/dev/null' /dev/null 3<&0 < /dev/null 2>/dev/null
trap "sleep 1; kill -9 $! 2>/dev/null" SIGINT
wait $!
}
exec 2>&3 3>&-
expected="${v[0]}"
expected_PID=$v_PID
expected_in="${v[1]}"
printf "done\n" >&2
#}}}
#{{{ close()
close() {
trap "" SIGINT
[ "${1::1}" = "-" ] && printf "\n"
printf "Finishing up. . .\n"
exec 3>&2 2>&-
timeout 1 cat <&"$actual" > /dev/null
timeout 1 cat <&"$expected" > /dev/null
exec 2>&3 3>&-
{ kill -0 $actual_PID 2>/dev/null || kill -0 $expected_PID 2>/dev/null; } && {
kill $actual_PID 2>/dev/null; kill $expected_PID 2>/dev/null
wait $actual_PID 2>/dev/null; wait $expected_PID 2>/dev/null
}
[ -n "$1" ] && exit ${1#-}
}
trap "close -1" SIGINT
#}}}
#{{{ send()
send() {
printf "%s" "$1" >&"$actual_in"
printf "%s" "$1" >&"$expected_in"
}
#}}}
#{{{ init
printf "Waiting for vim processes to be ready. . . " >&2
send ':call writefile(["-"],"/dev/fd/4","a")'$'\n'
head -n 1 <&"$actual" > /dev/null
head -n 1 <&"$expected" > /dev/null
printf "done\n" >&2
send ":set columns=128"$'\n'
#}}}
cd "${BASH_SOURCE[0]%/*}/tests"
for shell in "bash" "zsh"; do
command -v "$shell" &>/dev/null || continue
#{{{ run tests
printf "With shell=\`$shell\`:\n" >&2
#{{{ true vim terminal setup and storing prompt
#{{{ setup and setting escape variables
printf "\tGetting a safe TVT_ESCAPE. . . " >&2
escape_ascii="$(../util/get_usable | head -n 1)"
escape_key="$(printf "%s" "$escape_ascii" | ../util/convert_key)"
printf "done\n" >&2
printf "\tStarting true vim terminal. . . " >&2
escape_wait="${escape_key}t"
escape="${escape_key}n"
escape_force="${escape_key}f"
# ordinarily vim would pass TVT_ESCAPE on to the terminal then check for more to do, which would make it block until there are further instructions
# the Tapi_TVT_Escape call wouldn't happen at all until certain instructions are sent (<c-w>N, sleep, term_wait)
# simplified and fixed by cancelling the Tapi_TVT_Escape call with TVT_TEST and doing it with this first mapping
# but to ensure Tapi_TVT_Escape is triggered after all keys are handled by terminal, use escape_wait and wait for terminal response due to TVT_TEST then use escape (instead of mapping this to TVT_ESCAPE<c-w>N)
printf ":tnoremap \026${escape_key}n <c-w>N|" >&"$actual_in"
printf "nnoremap \026${escape_key}f <Nop>|" >&"$actual_in"
printf "tnoremap \026${escape_key}f <Space>(still in terminal job mode)<c-w>N:term_wait(term_list()[-1],1000)\n" >&"$actual_in"
printf ":let \$TVT_ESCAPE=\"${escape_ascii}t\"\n" >&"$actual_in"
printf ':call term_start(["'"$shell"'","-i"],{"term_rows":1,"curwin":1,"norestore":1})|' >&"$actual_in"
# x is fine here
printf 'call feedkeys("\<c-w>N","nx")\n' >&"$actual_in"
printf "done\n" >&2
#}}}
#{{{ waiting for true vim terminal to be ready
printf "\tWaiting for true vim terminal to be ready. . . " >&2
REPLY=
while [ -z "$REPLY" ]; do
sleep 0.1
printf ':call writefile([expand("%%")],"/dev/fd/4","a")\n' >&"$actual_in"
IFS= read -r <&"$actual"
done
printf "done\n" >&2
#}}}
#{{{ storing prompt
printf "\tStoring prompt. . . " >&2
prompt=
while true; do
printf ':call term_wait(term_list()[-1],100)|call writefile([term_getline(term_list()[-1],1)],"/dev/fd/4","a")\n' >&"$actual_in"
IFS= read -r prompt <&"$actual"
[ "${prompt#*]}" != "$prompt" ] && break
done
printf "done\n" >&2
#}}}
# cancelling insert above and sending shell vim escape down here because all shells draw funky things upon getting it
# the sleep is necessary for reasons and isn't a race condition
printf ":call term_sendkeys(term_list()[-1],\"\026$escape_wait\")|sleep 1m\n" >&"$actual_in"
head -n 1 <&"$actual" > /dev/null
#}}}
while IFS= read -r test; do
printf "\t" >&2
printf "Running test '%s'. . . " "$test"
while IFS= read -r line; do
#{{{ test special characters
# ^[ is escape, ^^[ is literal ^[
# * is 'just went to terminal job mode', ** is literal *
# @ is 'in terminal job mode and should not be', @@ is literal @
# used with things like d that go in to update preview and need to get out
# # is comment char, ## is literal #
# note that whitespace before comments is not trimmed
# whitespace at the beginning of lines is trimmed
#}}}
#{{{ test special character substitution
line="${line#${line%%[![:space:]]*}}"
line="${line//^\[/$'\033'}"
line="${line//^$'\033'/^[}"
line="${line//@/$'\035'}"
line="${line//$'\035'$'\035'/@}"
line="${line//\*/$'\037'}"
line="${line//$'\037'$'\037'/*}"
line="${line//#/$'\003'}"
line="${line//$'\003\003'/\#}"
line="${line%%$'\003'*}"
#}}}
[ -n "$line" ] || continue
#{{{ test special character handling
buf=""
while IFS= read -r -n 1; do
#{{{ 'in terminal job mode and should not be'
[ "$REPLY" = $'\035' ] && {
[ -n "$buf" ] && { send "$buf"; buf=""; }
head -n 1 <&"$actual" > /dev/null
printf "%s" "$escape" >&"$actual_in"
continue
}
#}}}
#{{{ 'just went to terminal job mode'
[ "$REPLY" = $'\037' ] && {
[ -n "$buf" ] && { send "$buf"; buf=""; }
head -n 1 <&"$actual" > /dev/null
continue
}
#}}}
#{{{ escape
[ "$REPLY" = $'\033' ] && {
[ -n "$buf" ] && { send "$buf"; buf=""; }
printf "%s" "$escape_wait" >&"$actual_in"
printf "\033" >&"$expected_in"
head -n 1 <&"$actual" > /dev/null
printf "%s" "$escape" >&"$actual_in"
continue
}
#}}}
buf="$buf$REPLY"
done <<< "$line"
[ -n "$buf" ] && send "$buf"
#}}}
done < "./$test"
# ensure in normal mode
printf "\033" >&"$expected_in"
printf "%s" "$escape_force" >&"$actual_in"
#{{{ check and clear results
send ':call writefile([getline("$")],"/dev/fd/4","a")'$'\n'
IFS= read -r -t 5 result_v <&"$expected" || {
printf "failed! (bad test, didn't end in normal mode)\n"
close 1
}
IFS= read -r -t 5 result_tvt <&"$actual" || {
printf "failed! (timeout)\n"
close 1
}
result_tvt="${result_tvt#"$prompt"}"
[ "$result_tvt" = "$result_v" ] && printf "passed ('%s')\n" "$result_v" || {
printf "failed!\n"
diff <(printf "%s\n" "$result_v") <(printf "%s\n" "$result_tvt")
close 1
}
send "0d$"
head -n 1 <&"$actual" > /dev/null
printf "%s" "$escape" >&"$actual_in"
#}}}
#{{{ test list
# test d after i because it is used in the lines just above this to reset, so if that fails it will fail the d test
done <<- "__EOF__"
i
d
i_2
I
a
a_2
A
c
cc
C
dd
D
p
P
r
r_2
s
s_2
S
x
x_2
__EOF__
#}}}
printf ":bd!\n" >&"$actual_in"
#}}}
done
# dash is to make `script` exit, not sure why it's necessary
# it's even tacked onto the printf that makes vim close
printf ":q!\n-" >&"$actual_in"
printf ":q!\n-" >&"$expected_in"
close
printf "All tests passed!\n"