t_errors.sh revision 1.6 1 #! /bin/sh
2 # $NetBSD: t_errors.sh,v 1.6 2021/10/28 21:02:05 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_parameter'
65 option_int_missing_parameter_body()
66 {
67 expect_error \
68 'indent: Command line: option "-ts" requires an integer parameter' \
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: option "-ts" requires an integer parameter' \
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: invalid argument "0" for option "-ts"' \
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: invalid argument "81" for option "-ts"' \
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: invalid argument "3000000000" for option "-ts"' \
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: invalid argument "0" for option "-i"' \
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: invalid argument "3garbage" for option "-i"' \
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 # TODO: The call to 'diag' should be replaced with 'errx'.
156 expect_error \
157 'error: Standard Input:1: buffer overflow in indent.pro, starting with '\''-123456781'\''' \
158 -Pindent.pro
159 }
160
161 atf_test_case 'option_special_missing_param'
162 option_special_missing_param_body()
163 {
164 # TODO: Write '-cli' instead of only 'cli'.
165 expect_error \
166 'indent: Command line: ``cli'\'\'' requires a parameter' \
167 -cli
168
169 expect_error \
170 'indent: Command line: ``T'\'\'' requires a parameter' \
171 -T
172
173 expect_error \
174 'indent: Command line: ``U'\'\'' requires a parameter' \
175 -U
176 }
177
178 atf_test_case 'unterminated_comment'
179 unterminated_comment_body()
180 {
181 echo '/*' > comment.c
182
183 atf_check -s 'exit:1' \
184 -o 'inline:/*'"$nl"' *'"$nl" \
185 -e 'inline:error: Standard Input:2: Unterminated comment'"$nl" \
186 "$indent" -st < comment.c
187 }
188
189 atf_test_case 'in_place_wrong_backup'
190 in_place_wrong_backup_body()
191 {
192 cat <<-\EOF > code.c
193 int decl;
194 EOF
195 cp code.c code.c.orig
196
197 # Due to the strange backup suffix '/subdir', indent tries to create
198 # a file named 'code.c/subdir', but 'code.c' is already a regular
199 # file, not a directory.
200 atf_check -s 'exit:1' \
201 -e 'inline:indent: code.c/subdir: Not a directory'"$nl" \
202 env SIMPLE_BACKUP_SUFFIX="/subdir" "$indent" code.c
203
204 # Since there was an early error, the original file is kept as is.
205 atf_check -o 'file:code.c.orig' \
206 cat code.c
207 }
208
209 atf_test_case 'argument_input_enoent'
210 argument_input_enoent_body()
211 {
212 atf_check -s 'exit:1' \
213 -e 'inline:indent: ./nonexistent.c: No such file or directory'"$nl" \
214 "$indent" ./nonexistent.c
215 }
216
217 atf_test_case 'argument_output_equals_input_name'
218 argument_output_equals_input_name_body()
219 {
220 echo '/* comment */' > code.c
221
222 atf_check -s 'exit:1' \
223 -e 'inline:indent: input and output files must be different'"$nl" \
224 "$indent" code.c code.c
225 }
226
227 atf_test_case 'argument_output_equals_input_file'
228 argument_output_equals_input_file_body()
229 {
230 echo '/* comment */' > code.c
231
232 atf_check \
233 "$indent" code.c ./code.c
234
235 # Oops, the file has become empty since the output is first emptied,
236 # before reading any of the input.
237 atf_check \
238 cat code.c
239 }
240
241 atf_test_case 'argument_output_enoent'
242 argument_output_enoent_body()
243 {
244 expect_error \
245 'indent: subdir/nonexistent.c: No such file or directory' \
246 /dev/null subdir/nonexistent.c
247 }
248
249 atf_test_case 'argument_too_many'
250 argument_too_many_body()
251 {
252 echo '/* comment */' > arg1.c
253
254 expect_error \
255 'indent: unknown parameter: arg3.c' \
256 arg1.c arg2.c arg3.c arg4.c
257 }
258
259 atf_test_case 'unexpected_end_of_file'
260 unexpected_end_of_file_body()
261 {
262 echo 'struct{' > code.c
263
264 expect_error \
265 'error: code.c:1: Stuff missing from end of file' \
266 code.c
267
268 atf_check \
269 -o 'inline:struct {'"$nl" \
270 cat code.c
271 }
272
273 atf_test_case 'unexpected_closing_brace_top_level'
274 unexpected_closing_brace_top_level_body()
275 {
276 echo '}' > code.c
277
278 expect_error \
279 'error: code.c:1: Statement nesting error' \
280 code.c
281 atf_check \
282 -o 'inline:}'"$nl" \
283 cat code.c
284 }
285
286 atf_test_case 'unexpected_closing_brace_decl'
287 unexpected_closing_brace_decl_body()
288 {
289 echo 'int i = 3};' > code.c
290
291 expect_error \
292 'error: code.c:1: Statement nesting error' \
293 code.c
294 # Despite the error message, the original file got overwritten with a
295 # best-effort rewrite of the code.
296 atf_check \
297 -o 'inline:int i = 3};'"$nl" \
298 cat code.c
299 }
300
301 atf_test_case 'preprocessing_overflow'
302 preprocessing_overflow_body()
303 {
304 cat <<-\EOF > code.c
305 #if 1
306 #if 2
307 #if 3
308 #if 4
309 #if 5
310 #if 6
311 #endif 6
312 #endif 5
313 #endif 4
314 #endif 3
315 #endif 2
316 #endif 1
317 #endif too much
318 EOF
319 cat <<-\EOF > stderr.exp
320 error: code.c:6: #if stack overflow
321 error: code.c:12: Unmatched #endif
322 error: code.c:13: Unmatched #endif
323 EOF
324
325 atf_check -s 'exit:1' \
326 -e 'file:stderr.exp' \
327 "$indent" code.c
328 }
329
330 atf_test_case 'preprocessing_unrecognized'
331 preprocessing_unrecognized_body()
332 {
333 cat <<-\EOF > code.c
334 #unknown
335 # 3 "file.c"
336 #elif 3
337 #else
338 EOF
339 cat <<-\EOF > stderr.exp
340 error: code.c:1: Unrecognized cpp directive
341 error: code.c:2: Unrecognized cpp directive
342 error: code.c:3: Unmatched #elif
343 error: code.c:4: Unmatched #else
344 EOF
345
346 atf_check -s 'exit:1' \
347 -e 'file:stderr.exp' \
348 "$indent" code.c
349 }
350
351 atf_init_test_cases()
352 {
353 atf_add_test_case 'option_unknown'
354 atf_add_test_case 'option_bool_trailing_garbage'
355 atf_add_test_case 'option_int_missing_parameter'
356 atf_add_test_case 'option_profile_not_found'
357 atf_add_test_case 'option_buffer_overflow'
358 atf_add_test_case 'option_typedefs_not_found'
359 atf_add_test_case 'option_special_missing_param'
360 atf_add_test_case 'option_tabsize_negative'
361 atf_add_test_case 'option_tabsize_zero'
362 atf_add_test_case 'option_tabsize_large'
363 atf_add_test_case 'option_tabsize_very_large'
364 atf_add_test_case 'option_int_trailing_garbage'
365 atf_add_test_case 'option_cli_trailing_garbage'
366 atf_add_test_case 'option_indent_size_zero'
367 atf_add_test_case 'unterminated_comment'
368 atf_add_test_case 'in_place_wrong_backup'
369 atf_add_test_case 'argument_input_enoent'
370 atf_add_test_case 'argument_output_equals_input_name'
371 atf_add_test_case 'argument_output_equals_input_file'
372 atf_add_test_case 'argument_output_enoent'
373 atf_add_test_case 'argument_too_many'
374 atf_add_test_case 'unexpected_end_of_file'
375 atf_add_test_case 'unexpected_closing_brace_top_level'
376 atf_add_test_case 'unexpected_closing_brace_decl'
377 atf_add_test_case 'preprocessing_overflow'
378 atf_add_test_case 'preprocessing_unrecognized'
379 }
380