aboutsummaryrefslogtreecommitdiffhomepage
path: root/tests/testsuite.at
blob: 4d66392274411215377128f242b26c3df68a8494 (plain)
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
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
AT_INIT
AT_COLOR_TESTS

AT_ARG_OPTION([valgrind],
	AS_HELP_STRING([--valgrind], [Run tests under Valgrind (memcheck)]))

# NOTE: There is currently no way to influence the return
# code of SciTECO, except to provoke an error.
# Since errors cannot be yielded explicitly, we use the
# idiom "(0/0)" to enforce a "Division by zero" error
# whenever we want to fail.
#
# NOTE: Square brackets are significant for M4 but
# often required in TECO code as well.
# We therefore use double brackets [[ ... ]]
# (translated to [ ... ]) in simple cases where balanced
# brackets are required in TECO code as well and
# quadrigraphs (@<:@ and @:>@) in all other cases.
# Single round brackets also have to be replaced with the
# quadrigraphs @{:@ and @:}@.

AT_BANNER([Features])

AT_SETUP([Number stack])
AT_CHECK([$SCITECO -e "2%a,%a - 3\"N(0/0)'"], 0, ignore, ignore)
# It's not quite clear what would be the best semantics for comma:
# a) Superfluous commas as in ",," or "(1,)" should be an error.
# b) Superfluous commas should be ignored which is effectively what we do now.
#    Even then it might be advisable to treat (1,) like (1).
# c) The empty "list" element is equivalent to 0, so
#    "1,,2" is equivalent to "1,0,2" and (1,) to (1,0).
AT_CHECK([$SCITECO -e "(1,) \"~|(0/0)'"], 0, ignore, ignore)
AT_CHECK([$SCITECO -e "1,(2)=="], 0, ignore, ignore)
AT_CLEANUP

AT_SETUP([Radix])
AT_CHECK([$SCITECO -e "0^R"], 1, ignore, ignore)
AT_CHECK([$SCITECO -e "0U.^R"], 1, ignore, ignore)
AT_CHECK([$SCITECO -e "23 (2^R)\^D .-5\"N(0/0)"], 0, ignore, ignore)
AT_CLEANUP

AT_SETUP([Exponentiation])
AT_CHECK([$SCITECO -e "-1^*0  - (-1)\"N(0/0)'"], 0, ignore, ignore)
AT_CHECK([$SCITECO -e "-1^*-5 - (-1)\"N(0/0)'"], 0, ignore, ignore)
AT_CHECK([$SCITECO -e "0^*-5="], 1, ignore, ignore)
AT_CHECK([$SCITECO -e "0^*0   - 1\"N(0/0)'"], 0, ignore, ignore)
AT_CHECK([$SCITECO -e "1^*-5  - 1\"N(0/0)'"], 0, ignore, ignore)
AT_CHECK([$SCITECO -e "2^*-5  - 0\"N(0/0)'"], 0, ignore, ignore)
AT_CLEANUP

AT_SETUP([Missing left operand])
AT_CHECK([$SCITECO -e '+23='], 1, ignore, ignore)
AT_CLEANUP

AT_SETUP([Operator precedence])
AT_CHECK([$SCITECO -e "(10-2-3)-5\"N(0/0)'"], 0, ignore, ignore)
AT_CHECK([$SCITECO -e "(1-6*5)+29\"N(0/0)'"], 0, ignore, ignore)
AT_CHECK([$SCITECO -e "(1-6*5-1)+30\"N(0/0)'"], 0, ignore, ignore)
AT_CHECK([$SCITECO -e "(1-6*5-1*2*2)+33\"N(0/0)'"], 0, ignore, ignore)
AT_CLEANUP

AT_SETUP([Closing loops at the correct macro level])
AT_CHECK([$SCITECO -e '@^Ua{>} <Ma'], 1, ignore, ignore)
AT_CLEANUP

AT_SETUP([Braces in loops])
AT_CHECK([$SCITECO -e "1<23@{:@42>"], 1, ignore, ignore)
AT_CHECK([$SCITECO -e "1<23(1;)> \"~|(0/0)'"], 0, ignore, ignore)
AT_CLEANUP

AT_SETUP([Pass-through loops])
# NOTE: This requires the <=>, so that values get consumed from the stack.
# More elegant would be a command for popping exactly one argument like <:$>.
AT_CHECK([$SCITECO -e "1,2,3,-1:<\"~1;'%a=> Qa-6\"N(0/0)'"], 0, ignore, ignore)
AT_CHECK([$SCITECO -e "1,2,3,-1:<\"~1;'%a= F>(0/0)> Qa-6\"N(0/0)'"], 0, ignore, ignore)
AT_CHECK([$SCITECO -e "3<%a:>-3\"N(0/0)'"], 0, ignore, ignore)
AT_CHECK([$SCITECO -e "3<%a :F>(0/0):>-3\"N(0/0)'"], 0, ignore, ignore)
AT_CLEANUP

AT_SETUP([String arguments])
AT_CHECK([$SCITECO -e $'Ifoo^Q\e(0/0)\e'], 0, ignore, ignore)
AT_CHECK([$SCITECO -e '@I"foo^Q"(0/0)"'], 0, ignore, ignore)
AT_CHECK([$SCITECO -e '@I{foo{bar}foo^Q{(0/0)}'], 0, ignore, ignore)
AT_CHECK([$SCITECO -e '@Ia^EQa(0/0)a'], 0, ignore, ignore)
# TODO: String building characters
AT_CLEANUP

AT_SETUP([Q-Register definitions])
AT_CHECK([$SCITECO -e '0Ua'], 0, ignore, ignore)
AT_CHECK([$SCITECO -e '0U.a'], 0, ignore, ignore)
AT_CHECK([$SCITECO -e '0U.^X'], 0, ignore, ignore)
AT_CHECK([$SCITECO -e '0U#ab'], 0, ignore, ignore)
AT_CHECK([$SCITECO -e '0U.#ab'], 0, ignore, ignore)
AT_CHECK([$SCITECO -e '0U[[AB]]'], 0, ignore, ignore)
AT_CHECK([$SCITECO -e '0U.[[AB]]'], 0, ignore, ignore)
AT_CHECK([$SCITECO -e '0U[[AB^Q@:>@(0/0)]]'], 0, ignore, ignore)
# TODO: String building in Q-Register definitions
AT_CLEANUP

AT_SETUP([Copy, append and cut to Q-Registers])
AT_CHECK([$SCITECO -e "@I/12^J123/J Xa :Xa L-:@Xa :Qa-9\"N(0/0)' Z-3\"N(0/0)'"], 0, ignore, ignore)
AT_CHECK([$SCITECO -e "@I/ABCDE/ 1,4Xa 0,3:Xa 3,5:@Xa :Qa-8\"N(0/0)' Z-3\"N(0/0)'"], 0, ignore, ignore)
AT_CLEANUP

AT_SETUP([Q-Register stack])
AT_CHECK([$SCITECO -e "[[a 23Ub ]]b Qb\"N(0/0)'"], 0, ignore, ignore)
# FG will temporarily change the working directory to tests/testsuite.dir.
AT_CHECK([$SCITECO -e "[[\$ @FG'..' ]]\$ :Q\$-1Q\$-^^r\"=(0/0)'"], 0, ignore, ignore)
AT_CHECK([$SCITECO -e "[[: @I/XXX/ ]]: .\"N(0/0)'"], 0, ignore, ignore)
AT_CLEANUP

AT_SETUP([Convert between line and glyph positions])
AT_CHECK([$SCITECO -e "@I/1^J2^J3/J 2^QC :^Q-3\"N(0/0)'"], 0, ignore, ignore)
AT_CLEANUP

AT_SETUP([Deleting words])
AT_CHECK([$SCITECO -e "@I/deleting words is useful/3J 2V .-3\"N(0/0)' Z-13\"N(0/0)'"], 0, ignore, ignore)
AT_CHECK([$SCITECO -e "@I/deleting words is useful/3R 2Y .-14\"N(0/0)' Z-17\"N(0/0)'"], 0, ignore, ignore)
AT_CLEANUP

AT_SETUP([Searches])
# FIXME: We cannot currently easily insert a single ASCII 5 (^E), as it must be followed
# by a 2nd character. It can be quoted, but cannot be written as Caret+E.
# You also cannot search for a single ASCII 5 using Caret+E.
# 2 additional ^Q are translated to a single ^Q and interpreted at the search-pattern layer.
AT_CHECK([$SCITECO -e "@I/^Q\05/ J @:S/^Q^Q^Q\05/\"F(0/0)'"], 0, ignore, ignore)
# Canse-sensitive search
AT_CHECK([$SCITECO -e "@I/XXX/J -^X @:S/xxx/\"S(0/0)'"], 0, ignore, ignore)
# Search mode should be local to the macro frame.
AT_CHECK([$SCITECO -e "-^X @^Um{^X} Mm-0\"N(0/0)'"], 0, ignore, ignore)
AT_CHECK([$SCITECO -e "@I/XYZ/ J ::@S/X/\"F(0/0)' H::@S/Z/\"S(0/0)'"], 0, ignore, ignore)
AT_CLEANUP

AT_SETUP([Search and insertion ranges])
AT_CHECK([$SCITECO -e "@I/XXYYZZ/^SC .\"N(0/0)' C @S/YY/^YU1U0 Q0-2\"N(0/0)' Q1-4\"N(0/0)'"], 0, ignore, ignore)
AT_CHECK([$SCITECO -e "@I/XXYYZZ/J @S/XX^E[[^EMY]]/ 1^YXa :Qa-2\"N(0/0)'"], 0, ignore, ignore)
AT_CLEANUP

AT_SETUP([Editing local registers in macro calls])
AT_CHECK([$SCITECO -e '@^Ua{@EQ.x//} :Ma @^U.x/FOO/'], 0, ignore, ignore)
AT_CHECK([$SCITECO -e '@^Ua{@EQ.x//}  Ma @^U.x/FOO/'], 1, ignore, ignore)
AT_CHECK([$SCITECO -e '@^Ua{@EQ.x// Mb Q*U*} Ma'], 0, ignore, ignore)
AT_CLEANUP

AT_SETUP([Loading files into Q-Registers])
AT_CHECK([$SCITECO -e "@I/../ @EW/loadqreg.txt/ @EQa/loadqreg.txt/ :Qa-2\"N(0/0)'"], 0, ignore, ignore)
# Does the same as FG..$. Afterwards, the parent directory should be shorter.
AT_CHECK([$SCITECO -e ":Q\$Ul @EQ\$/loadqreg.txt/ :Q\$-Ql+1\">(0/0)'"], 0, ignore, ignore)
AT_CLEANUP

AT_SETUP([Saving Q-Registers contents to files])
AT_CHECK([$SCITECO -e "@^Ua/test/ @E%a/saveqreg.txt/ @EB/saveqreg.txt/ Z-4\"N(0/0)'"], 0, ignore, ignore)
AT_CHECK([$SCITECO -e "@E%\$/saveqreg.txt/ @EB/saveqreg.txt/ Z-:Q\$\"N(0/0)'"], 0, ignore, ignore)
AT_CLEANUP

AT_SETUP([8-bit cleanliness])
AT_CHECK([$SCITECO -e "0@I//J 0A\"N(0/0)' :@S/^@/\"F(0/0)'"], 0, ignore, ignore)
AT_CHECK([$SCITECO -e "@EQa//0EE 1U*0EE 0:@EUa/f^@^@/ :Qa-4\"N(0/0)' Ga Z-4\"N(0/0)'"], 0, ignore, ignore)
AT_CHECK([$SCITECO -e "0EE 129@I// -A-129\"N(0/0)' HXa @EQa// EE\"N(0/0)'"], 0, ignore, ignore)
AT_CHECK([$SCITECO -8e "129@:^Ua// 0Qa-129\"N(0/0)'"], 0, ignore, ignore)
AT_CHECK([$SCITECO -e "1EE 167Ua @I/^EUa/ .-1\"N(0/0)'"], 0, ignore, ignore)
AT_CHECK([$SCITECO -8e "194Ua Qa@I//J :@S/^EUa/\"F(0/0)'"], 0, ignore, ignore)
AT_CLEANUP

AT_SETUP([Unicode])
AT_CHECK([$SCITECO -e "8594@I/Здравствуй, мир!/ Z-17\"N(0/0)' J0A-8594\"N(0/0)'"], 0, ignore, ignore)
AT_CHECK([$SCITECO -e "8594@^Ua/Здравствуй, мир!/ :Qa-17\"N(0/0)' 0Qa-8594\"N(0/0)'"], 0, ignore, ignore)
AT_CHECK([$SCITECO -e "@I/Здравствуй, мир!/ JW .-10\"N(0/0)' ^E-20\"N(0/0)' 204:EE .-10\"N(0/0)'"], 0, ignore, ignore)
AT_CHECK([$SCITECO -e "@I/TEST/ @EW/юникод.txt/"], 0, ignore, ignore)
AT_CHECK([test -f юникод.txt], 0, ignore, ignore)
AT_CHECK([$SCITECO -e "^^ß-223\"N(0/0) 23Uъ Q[Ъ]-23\"N(0/0)'"], 0, ignore, ignore)
AT_CHECK([$SCITECO -e "@O/метка/ !метка!"], 0, ignore, ignore)
AT_CLEANUP

AT_SETUP([Automatic EOL normalization])
AT_CHECK([$SCITECO -e "@EB'${srcdir}/autoeol-input.txt' EL-2\"N(0/0)' 2LR 13@I'' 0EL @EW'autoeol-sciteco.txt'"],
         0, ignore, ignore)
AT_CHECK([cmp autoeol-sciteco.txt ${srcdir}/autoeol-output.txt], 0, ignore, ignore)
AT_CHECK([$SCITECO -e "@EB'autoeol-sciteco.txt' EL-0\"N(0/0)' 2EL @EW''"], 0, ignore, ignore)
AT_CHECK([cmp autoeol-sciteco.txt ${srcdir}/autoeol-input.txt], 0, ignore, ignore)
AT_CLEANUP

AT_SETUP([Memory limiting])
AT_CHECK([$SCITECO -e "50*1000*1000,2EJ <@<:@a>"], 1, ignore, ignore)
AT_CLEANUP

AT_SETUP([Execute external command])
# TODO: It would be a better test to generate a random number of bytes.
# Unfortunately, neither $RANDOM, shuf nor jot are portable.
# So we have to wait until SciTECO supports a random number generator.
AT_CHECK([$SCITECO -e "@EC'dd if=/dev/zero bs=512 count=1' Z= Z-512\"N(0/0)'"], 0, ignore, ignore)
AT_CHECK([$SCITECO -e "0,128ED @EC'dd if=/dev/zero bs=512 count=1' Z= Z-512\"N(0/0)'"], 0, ignore, ignore)
AT_CLEANUP

AT_BANNER([Regression Tests])

AT_SETUP([Glob patterns with character classes])
# Also checks closing brackets as part of the character set.
AT_CHECK([$SCITECO -e ":@EN/*.[[@:>@ch]]/foo.h/\"F(0/0)'"], 0, ignore, ignore)
AT_CLEANUP

AT_SETUP([Glob patterns with unclosed trailing brackets])
AT_CHECK([$SCITECO -e ":@EN/*.@<:@h/foo.@<:@h/\"F(0/0)'"], 0, ignore, ignore)
AT_CLEANUP

AT_SETUP([Searching with large counts])
# Even though the search will be unsuccessful, it will not be considered
# a proper error, so the process return code is still 0.
AT_CHECK([$SCITECO -e "2147483647@S/foo/"], 0, ignore, ignore)
# Will always break the memory limit which is considered an error.
AT_CHECK([$SCITECO -e "-2147483648@S/foo/"], 1, ignore, ignore)
AT_CLEANUP

AT_SETUP([Search on new empty document])
AT_CHECK([$SCITECO -e ":@S/foo/\"S(0/0)'"], 0, ignore, ignore)
AT_CHECK([$SCITECO -e ":@N/foo/\"S(0/0)'"], 0, ignore, ignore)
AT_CLEANUP

AT_SETUP([Search for one of characters in uninitialized Q-Register])
# Register "a" exists, but it's string part is yet uninitialized.
AT_CHECK([$SCITECO -e ":@S/^EGa/\"S(0/0)'"], 0, ignore, ignore)
AT_CLEANUP

AT_SETUP([Search accesses wrong Q-Register table])
AT_CHECK([$SCITECO -e '@^U.#xx/123/ @^Um{:@S/^EG.#xx/$} :Mm Mm'], 1, ignore, ignore)
AT_CLEANUP

AT_SETUP([Memory limiting during spawning])
# This might result in an OOM if memory limiting is not working
AT_CHECK([$SCITECO -e "50*1000*1000,2EJ 0,128ED @EC'dd if=/dev/zero'"], 1, ignore, ignore)
AT_CLEANUP

AT_SETUP([Memory limiting during file reading])
AT_CHECK([dd if=/dev/zero of=big-file.txt bs=1000 count=50000], 0, ignore, ignore)
AT_CHECK([$SCITECO -8e "50*1000*1000,2EJ @EB'big-file.txt'"], 1, ignore, ignore)
AT_CLEANUP

AT_SETUP([Q-Register stack cleanup])
AT_CHECK([$SCITECO -e '@<:@a'], 0, ignore, ignore)
AT_CLEANUP

AT_SETUP([Uninitialized "_"-register])
AT_CHECK([$SCITECO -e ":@S//\"S(0/0)'"], 0, ignore, ignore)
AT_CHECK([$SCITECO -e ":@EN///\"S(0/0)'"], 0, ignore, ignore)
AT_CLEANUP

AT_SETUP([Uninitialized Q-Register in string building])
AT_CHECK([$SCITECO -e '@I/^E@a/'], 0, ignore, ignore)
AT_CHECK([$SCITECO -e '@I/^ENa/'], 0, ignore, ignore)
AT_CLEANUP

AT_SETUP([Setting special Q-Registers with EU])
# NOTE: The clipboard registers also suffered from this, but the test suite
# should not influence the clipboard (and it's not in Curses anyway).
#
# Should fail, but not crash
AT_CHECK([$SCITECO -e '@EU*""'], 1, ignore, ignore)
AT_CHECK([$SCITECO -e '@EU$"."'], 0, ignore, ignore)
AT_CLEANUP

AT_SETUP([Empty help topic])
AT_CHECK([$SCITECO -e '@?//'], 1, ignore, ignore)
AT_CLEANUP

AT_SETUP([Empty lexer name])
AT_CHECK([$SCITECO -e '@ES/SETILEXER//'], 1, ignore, ignore)
AT_CLEANUP

AT_SETUP([Empty command string])
AT_CHECK([$SCITECO -e '@EC//'], 1, ignore, ignore)
AT_CHECK([$SCITECO -e '@EGa//'], 1, ignore, ignore)
AT_CLEANUP

AT_SETUP([Jump to beginning of macro])
AT_CHECK([$SCITECO -e "%a-2\"< F< ' Qa-2\"N(0/0)'"], 0, ignore, ignore)
AT_CLEANUP

AT_SETUP([Gotos and labels])
# Not a label redefinition, there must not even be a warning.
AT_CHECK([$SCITECO -e '2<!foo!>'], 0, ignore, stderr)
AT_FAIL_IF([$GREP "^Warning:" stderr])
# Will print a warning about label redefinition, though...
AT_CHECK([$SCITECO -e "!foo! Qa\"S^C' !foo! Qa\"S(0/0)' -Ua @O/foo/"], 0, ignore, ignore)
AT_CLEANUP

#
# Command-line editing bugs.
#
# NOTE: It would generally be possible to use control codes like ^H (8)
# and ^W (23) for rubout as well, but this is tricky to write in a portable manner.
# Therefore we usally use the push/pop command-line commands { and }.
# NOTE: Most errors are not reported in exit codes - you must check stderr.
#
AT_SETUP([Rub out string append])
AT_CHECK([$SCITECO_CMDLINE "@I/XXX/ H:Xa{-4D} :Qa-0\"N(0/0)'"], 0, ignore, stderr)
AT_FAIL_IF([$GREP "^Error:" stderr])
AT_CLEANUP

AT_SETUP([Rub out of empty forward kill])
AT_CHECK([$SCITECO_CMDLINE "@I/F/ J @I/X/ @FK/F/{-6D} Z-2\"N(0/0)'"], 0, ignore, stderr)
AT_FAIL_IF([$GREP "^Error:" stderr])
AT_CLEANUP

AT_SETUP([Searches from macro calls])
AT_CHECK([$SCITECO_CMDLINE "@^Um{:@S/XXX/} :Mm\"S(0/0)' Mm\"S(0/0)'"], 0, ignore, stderr)
AT_FAIL_IF([$GREP "^Error:" stderr])
AT_CLEANUP

AT_BANNER([Known Bugs])

AT_SETUP([Number stack])
# Nobody needs the current semantic of digit "commands" and they
# will be replaced with proper number parser states, which will also allow for
# floating point constants.
# With the current parser, it is hard to even interpret the following code correctly...
AT_CHECK([$SCITECO -e "(12)3 - 3\"N(0/0)'"], 0, ignore, ignore)
AT_XFAIL_IF(true)
AT_CLEANUP

AT_SETUP([Dangling Else/End-If])
AT_CHECK([$SCITECO -e "'"], 1, ignore, ignore)
AT_CHECK([$SCITECO -e "| (0/0) '"], 1, ignore, ignore)
AT_XFAIL_IF(true)
AT_CLEANUP

# NOTE: This bug depends on specific build options of Glib's
# PCRE which is not predictable.
# It segfaults at least on Ubuntu 20.04 (libpcre3 v2:8.39).
#AT_SETUP([Pattern matching overflow])
## Should no longer dump core.
## It could fail because the memory limit is exceeed,
## but not in this case since the match string isn't too large.
#AT_CHECK([$SCITECO -e '100000<@I"X">J @S"^EM^X"'], 0, ignore, ignore)
#AT_XFAIL_IF(true)
#AT_CLEANUP

AT_SETUP([Recursion overflow])
# Should no longer dump core.
# It could fail because the memory limit is exceeed,
# but not in this case since we limit the recursion.
AT_CHECK([$SCITECO -e "@^Um{U.a Q.a-100000\"<%.aMm'} 0Mm"], 0, ignore, ignore)
AT_XFAIL_IF(true)
AT_CLEANUP