t_errors.sh revision 1.14 1 #! /bin/sh
2 # $NetBSD: t_errors.sh,v 1.14 2021/10/30 13:30:26 rillig Exp $
3 #
4 # Copyright (c) 2021 The NetBSD Foundation, Inc.
5 # All rights reserved.
6 #
7 # Redistribution and use in source and binary forms, with or without
8 # modification, are permitted provided that the following conditions
9 # are met:
10 # 1. Redistributions of source code must retain the above copyright
11 # notice, this list of conditions and the following disclaimer.
12 # 2. Redistributions in binary form must reproduce the above copyright
13 # notice, this list of conditions and the following disclaimer in the
14 # documentation and/or other materials provided with the distribution.
15 #
16 # THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
17 # ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
18 # TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
20 # BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 # POSSIBILITY OF SUCH DAMAGE.
27 #
28 # $FreeBSD$
29
30 # Tests for error handling in indent.
31
32 indent=$(atf_config_get usr.bin.indent.test_indent /usr/bin/indent)
33 nl='
34 '
35
36 expect_error()
37 {
38 local msg
39
40 msg="$1"
41 shift
42
43 atf_check -s 'exit:1' \
44 -e "inline:$msg$nl" \
45 "$indent" "$@"
46 }
47
48 atf_test_case 'option_unknown'
49 option_unknown_body()
50 {
51 expect_error \
52 'indent: Command line: unknown option "-Z-unknown"' \
53 -Z-unknown
54 }
55
56 atf_test_case 'option_bool_trailing_garbage'
57 option_bool_trailing_garbage_body()
58 {
59 expect_error \
60 'indent: Command line: unknown option "-bacchus"' \
61 -bacchus
62 }
63
64 atf_test_case 'option_int_missing_argument'
65 option_int_missing_argument_body()
66 {
67 expect_error \
68 'indent: Command line: argument "x" to option "-ts" must be an integer' \
69 -tsx
70 }
71
72 atf_test_case 'option_profile_not_found'
73 option_profile_not_found_body()
74 {
75 expect_error \
76 'indent: profile ./nonexistent: No such file or directory' \
77 -P./nonexistent
78 }
79
80 atf_test_case 'option_typedefs_not_found'
81 option_typedefs_not_found_body()
82 {
83 expect_error \
84 'indent: cannot open file ./nonexistent' \
85 -U./nonexistent
86 }
87
88 atf_test_case 'option_tabsize_negative'
89 option_tabsize_negative_body()
90 {
91 expect_error \
92 'indent: Command line: argument "-1" to option "-ts" must be between 1 and 80' \
93 -ts-1
94 }
95
96 atf_test_case 'option_tabsize_zero'
97 option_tabsize_zero_body()
98 {
99 expect_error \
100 'indent: Command line: argument "0" to option "-ts" must be between 1 and 80' \
101 -ts0
102 }
103
104 atf_test_case 'option_tabsize_large'
105 option_tabsize_large_body()
106 {
107 # Integer overflow, on both ILP32 and LP64 platforms.
108 expect_error \
109 'indent: Command line: argument "81" to option "-ts" must be between 1 and 80' \
110 -ts81
111 }
112
113 atf_test_case 'option_tabsize_very_large'
114 option_tabsize_very_large_body()
115 {
116 # Integer overflow, on both ILP32 and LP64 platforms.
117 expect_error \
118 'indent: Command line: argument "3000000000" to option "-ts" must be between 1 and 80' \
119 -ts3000000000
120 }
121
122 atf_test_case 'option_indent_size_zero'
123 option_indent_size_zero_body()
124 {
125 expect_error \
126 'indent: Command line: argument "0" to option "-i" must be between 1 and 80' \
127 -i0
128 }
129
130 atf_test_case 'option_int_trailing_garbage'
131 option_int_trailing_garbage_body()
132 {
133 expect_error \
134 'indent: Command line: argument "3garbage" to option "-i" must be an integer' \
135 -i3garbage
136 }
137
138 atf_test_case 'option_cli_trailing_garbage'
139 option_cli_trailing_garbage_body()
140 {
141 expect_error \
142 'indent: Command line: argument "3garbage" to option "-cli" must be numeric' \
143 -cli3garbage
144 }
145
146 atf_test_case 'option_buffer_overflow'
147 option_buffer_overflow_body()
148 {
149 opt='12345678123456781234567812345678' # 32
150 opt="$opt$opt$opt$opt$opt$opt$opt$opt" # 256
151 opt="$opt$opt$opt$opt$opt$opt$opt$opt" # 2048
152 opt="$opt$opt$opt$opt$opt$opt$opt$opt" # 16384
153 printf '%s\n' "-$opt" > indent.pro
154
155 expect_error \
156 'indent: buffer overflow in indent.pro, starting with '\''-123456781'\''' \
157 -Pindent.pro
158 }
159
160 atf_test_case 'option_special_missing_param'
161 option_special_missing_param_body()
162 {
163 # TODO: Write '-cli' instead of only 'cli'.
164 expect_error \
165 'indent: Command line: ``cli'\'\'' requires an argument' \
166 -cli
167
168 expect_error \
169 'indent: Command line: ``T'\'\'' requires an argument' \
170 -T
171
172 expect_error \
173 'indent: Command line: ``U'\'\'' requires an argument' \
174 -U
175 }
176
177 atf_test_case 'unterminated_comment'
178 unterminated_comment_body()
179 {
180 echo '/*' > comment.c
181
182 atf_check -s 'exit:1' \
183 -o 'inline:/*'"$nl"' *'"$nl" \
184 -e 'inline:error: Standard Input:2: Unterminated comment'"$nl" \
185 "$indent" -st < comment.c
186 }
187
188 atf_test_case 'in_place_wrong_backup'
189 in_place_wrong_backup_body()
190 {
191 cat <<-\EOF > code.c
192 int decl;
193 EOF
194 cp code.c code.c.orig
195
196 # Due to the strange backup suffix '/subdir', indent tries to create
197 # a file named 'code.c/subdir', but 'code.c' is already a regular
198 # file, not a directory.
199 atf_check -s 'exit:1' \
200 -e 'inline:indent: code.c/subdir: Not a directory'"$nl" \
201 env SIMPLE_BACKUP_SUFFIX="/subdir" "$indent" code.c
202
203 # Since there was an early error, the original file is kept as is.
204 atf_check -o 'file:code.c.orig' \
205 cat code.c
206 }
207
208 atf_test_case 'argument_input_enoent'
209 argument_input_enoent_body()
210 {
211 atf_check -s 'exit:1' \
212 -e 'inline:indent: ./nonexistent.c: No such file or directory'"$nl" \
213 "$indent" ./nonexistent.c
214 }
215
216 atf_test_case 'argument_output_equals_input_name'
217 argument_output_equals_input_name_body()
218 {
219 echo '/* comment */' > code.c
220
221 atf_check -s 'exit:1' \
222 -e 'inline:indent: input and output files must be different'"$nl" \
223 "$indent" code.c code.c
224 }
225
226 atf_test_case 'argument_output_equals_input_file'
227 argument_output_equals_input_file_body()
228 {
229 echo '/* comment */' > code.c
230
231 atf_check \
232 "$indent" code.c ./code.c
233
234 # Oops, the file has become empty since the output is first emptied,
235 # before reading any of the input.
236 atf_check \
237 cat code.c
238 }
239
240 atf_test_case 'argument_output_enoent'
241 argument_output_enoent_body()
242 {
243 expect_error \
244 'indent: subdir/nonexistent.c: No such file or directory' \
245 /dev/null subdir/nonexistent.c
246 }
247
248 atf_test_case 'argument_too_many'
249 argument_too_many_body()
250 {
251 echo '/* comment */' > arg1.c
252
253 expect_error \
254 'indent: too many arguments: arg3.c' \
255 arg1.c arg2.c arg3.c arg4.c
256 }
257
258 atf_test_case 'unexpected_end_of_file'
259 unexpected_end_of_file_body()
260 {
261 echo 'struct{' > code.c
262
263 expect_error \
264 'error: code.c:1: Stuff missing from end of file' \
265 code.c
266
267 atf_check \
268 -o 'inline:struct {'"$nl" \
269 cat code.c
270 }
271
272 atf_test_case 'unexpected_closing_brace_top_level'
273 unexpected_closing_brace_top_level_body()
274 {
275 echo '}' > code.c
276
277 expect_error \
278 'error: code.c:1: Statement nesting error' \
279 code.c
280 atf_check \
281 -o 'inline:}'"$nl" \
282 cat code.c
283 }
284
285 atf_test_case 'unexpected_closing_brace_decl'
286 unexpected_closing_brace_decl_body()
287 {
288 echo 'int i = 3};' > code.c
289
290 expect_error \
291 'error: code.c:1: Statement nesting error' \
292 code.c
293 # Despite the error message, the original file got overwritten with a
294 # best-effort rewrite of the code.
295 atf_check \
296 -o 'inline:int i = 3};'"$nl" \
297 cat code.c
298 }
299
300 atf_test_case 'preprocessing_overflow'
301 preprocessing_overflow_body()
302 {
303 cat <<-\EOF > code.c
304 #if 1
305 #if 2
306 #if 3
307 #if 4
308 #if 5
309 #if 6
310 #endif 6
311 #endif 5
312 #endif 4
313 #endif 3
314 #endif 2
315 #endif 1
316 #endif too much
317 EOF
318 cat <<-\EOF > stderr.exp
319 error: code.c:6: #if stack overflow
320 error: code.c:12: Unmatched #endif
321 error: code.c:13: Unmatched #endif
322 EOF
323
324 atf_check -s 'exit:1' \
325 -e 'file:stderr.exp' \
326 "$indent" code.c
327 }
328
329 atf_test_case 'preprocessing_unrecognized'
330 preprocessing_unrecognized_body()
331 {
332 cat <<-\EOF > code.c
333 #unknown
334 # 3 "file.c"
335 #elif 3
336 #else
337 EOF
338 cat <<-\EOF > stderr.exp
339 error: code.c:1: Unrecognized cpp directive
340 error: code.c:2: Unrecognized cpp directive
341 error: code.c:3: Unmatched #elif
342 error: code.c:4: Unmatched #else
343 EOF
344
345 atf_check -s 'exit:1' \
346 -e 'file:stderr.exp' \
347 "$indent" code.c
348 }
349
350 atf_test_case 'unbalanced_parentheses_1'
351 unbalanced_parentheses_1_body()
352 {
353 cat <<-\EOF > code.c
354 int var =
355 (
356 ;
357 )
358 ;
359 EOF
360 cat <<-\EOF > stderr.exp
361 error: code.c:3: Unbalanced parentheses
362 warning: code.c:4: Extra ')'
363 EOF
364
365 atf_check -s 'exit:1' -e 'file:stderr.exp' \
366 "$indent" code.c
367 }
368
369 atf_test_case 'unbalanced_parentheses_2'
370 unbalanced_parentheses_2_body()
371 {
372 # '({...})' is the GCC extension "Statement expression".
373 cat <<-\EOF > code.c
374 int var =
375 (
376 {
377 1
378 }
379 )
380 ;
381 EOF
382 cat <<-\EOF > stderr.exp
383 error: code.c:3: Unbalanced parentheses
384 warning: code.c:6: Extra ')'
385 EOF
386
387 atf_check -s 'exit:1' -e 'file:stderr.exp' \
388 "$indent" code.c
389 }
390
391 atf_test_case 'unbalanced_parentheses_3'
392 unbalanced_parentheses_3_body()
393 {
394 # '({...})' is the GCC extension "Statement expression".
395 cat <<-\EOF > code.c
396 int var =
397 (
398 1
399 }
400 ;
401 EOF
402 cat <<-\EOF > stderr.exp
403 error: code.c:4: Unbalanced parentheses
404 error: code.c:4: Statement nesting error
405 EOF
406
407 atf_check -s 'exit:1' -e 'file:stderr.exp' \
408 "$indent" code.c
409 }
410
411 atf_test_case 'search_stmt_comment_segv'
412 search_stmt_comment_segv_body()
413 {
414 # Before NetBSD indent.c 1.187 from 2021-10-30, indent crashed while
415 # trying to format the following artificial code.
416
417 printf '{if(expr\n)/*c*/;}\n' > code.c
418
419 cat <<\EOF > code.exp
420 {
421 if (expr
422 ) /* c */
423 ;
424 }
425 EOF
426 atf_check -o 'file:code.exp' \
427 "$indent" code.c -st
428 }
429
430 atf_init_test_cases()
431 {
432 atf_add_test_case 'option_unknown'
433 atf_add_test_case 'option_bool_trailing_garbage'
434 atf_add_test_case 'option_int_missing_argument'
435 atf_add_test_case 'option_profile_not_found'
436 atf_add_test_case 'option_buffer_overflow'
437 atf_add_test_case 'option_typedefs_not_found'
438 atf_add_test_case 'option_special_missing_param'
439 atf_add_test_case 'option_tabsize_negative'
440 atf_add_test_case 'option_tabsize_zero'
441 atf_add_test_case 'option_tabsize_large'
442 atf_add_test_case 'option_tabsize_very_large'
443 atf_add_test_case 'option_int_trailing_garbage'
444 atf_add_test_case 'option_cli_trailing_garbage'
445 atf_add_test_case 'option_indent_size_zero'
446 atf_add_test_case 'unterminated_comment'
447 atf_add_test_case 'in_place_wrong_backup'
448 atf_add_test_case 'argument_input_enoent'
449 atf_add_test_case 'argument_output_equals_input_name'
450 atf_add_test_case 'argument_output_equals_input_file'
451 atf_add_test_case 'argument_output_enoent'
452 atf_add_test_case 'argument_too_many'
453 atf_add_test_case 'unexpected_end_of_file'
454 atf_add_test_case 'unexpected_closing_brace_top_level'
455 atf_add_test_case 'unexpected_closing_brace_decl'
456 atf_add_test_case 'preprocessing_overflow'
457 atf_add_test_case 'preprocessing_unrecognized'
458 atf_add_test_case 'unbalanced_parentheses_1'
459 atf_add_test_case 'unbalanced_parentheses_2'
460 atf_add_test_case 'unbalanced_parentheses_3'
461 atf_add_test_case 'search_stmt_comment_segv'
462 }
463