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