t_misc.sh revision 1.28 1 1.1 rillig #! /bin/sh
2 1.28 rillig # $NetBSD: t_misc.sh,v 1.28 2023/12/10 17:45:35 rillig Exp $
3 1.1 rillig #
4 1.1 rillig # Copyright (c) 2021 The NetBSD Foundation, Inc.
5 1.1 rillig # All rights reserved.
6 1.1 rillig #
7 1.1 rillig # Redistribution and use in source and binary forms, with or without
8 1.1 rillig # modification, are permitted provided that the following conditions
9 1.1 rillig # are met:
10 1.1 rillig # 1. Redistributions of source code must retain the above copyright
11 1.1 rillig # notice, this list of conditions and the following disclaimer.
12 1.1 rillig # 2. Redistributions in binary form must reproduce the above copyright
13 1.1 rillig # notice, this list of conditions and the following disclaimer in the
14 1.1 rillig # documentation and/or other materials provided with the distribution.
15 1.1 rillig #
16 1.1 rillig # THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
17 1.1 rillig # ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
18 1.1 rillig # TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 1.1 rillig # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
20 1.1 rillig # BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 1.1 rillig # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 1.1 rillig # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 1.1 rillig # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 1.1 rillig # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 1.1 rillig # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 1.1 rillig # POSSIBILITY OF SUCH DAMAGE.
27 1.1 rillig
28 1.1 rillig # Tests for indent that do not follow the input-profile-output scheme that is
29 1.23 rillig # used in t_options.
30 1.1 rillig
31 1.1 rillig indent=$(atf_config_get usr.bin.indent.test_indent /usr/bin/indent)
32 1.2 rillig
33 1.2 rillig atf_test_case 'in_place'
34 1.2 rillig in_place_body()
35 1.2 rillig {
36 1.2 rillig cat <<-\EOF > code.c
37 1.2 rillig int decl;
38 1.2 rillig EOF
39 1.2 rillig cat <<-\EOF > code.c.exp
40 1.2 rillig int decl;
41 1.2 rillig EOF
42 1.2 rillig cp code.c code.c.orig
43 1.2 rillig
44 1.2 rillig atf_check \
45 1.2 rillig env SIMPLE_BACKUP_SUFFIX=".bak" "$indent" code.c
46 1.2 rillig atf_check -o 'file:code.c.exp' \
47 1.2 rillig cat code.c
48 1.2 rillig atf_check -o 'file:code.c.orig' \
49 1.2 rillig cat code.c.bak
50 1.2 rillig }
51 1.1 rillig
52 1.18 rillig atf_test_case 'in_place_parse_error'
53 1.18 rillig in_place_parse_error_body()
54 1.18 rillig {
55 1.18 rillig # On normal parse errors, indent continues until the end of the file.
56 1.18 rillig # This means that even in the case of errors, not much is lost.
57 1.18 rillig
58 1.18 rillig cat <<-\EOF > code.c
59 1.18 rillig int line1;
60 1.18 rillig }
61 1.18 rillig int line3;
62 1.18 rillig EOF
63 1.18 rillig
64 1.18 rillig atf_check -s 'exit:1' -e 'ignore' \
65 1.18 rillig "$indent" code.c
66 1.18 rillig atf_check -o 'inline:int\t\tline1;\n}\nint\t\tline3;\n' \
67 1.18 rillig cat code.c
68 1.18 rillig }
69 1.18 rillig
70 1.1 rillig atf_test_case 'verbose_profile'
71 1.1 rillig verbose_profile_body()
72 1.1 rillig {
73 1.1 rillig cat <<-\EOF > .indent.pro
74 1.1 rillig -/* comment */bacc
75 1.1 rillig -v
76 1.1 rillig -fc1
77 1.1 rillig EOF
78 1.1 rillig cat <<-\EOF > before.c
79 1.1 rillig int decl;
80 1.1 rillig EOF
81 1.1 rillig cat <<-\EOF > after.c.exp
82 1.1 rillig int decl;
83 1.1 rillig EOF
84 1.27 rillig cat <<-\EOF > stderr.exp
85 1.1 rillig profile: -fc1
86 1.1 rillig profile: -bacc
87 1.1 rillig profile: -v
88 1.1 rillig profile: -fc1
89 1.1 rillig EOF
90 1.1 rillig
91 1.28 rillig # The code in args.c function load_profile suggests that options from
92 1.28 rillig # profile files are echoed to stderr during startup. But since the
93 1.1 rillig # command line options are handled after the profile files, a '-v' in
94 1.1 rillig # the command line has no effect. That's why '-bacc' is not listed
95 1.28 rillig # on stderr, but '-fc1' is. The second round of '-bacc', '-v', '-fc1'
96 1.28 rillig # is listed because when running the test via ATF, $HOME equals $PWD.
97 1.1 rillig
98 1.1 rillig atf_check \
99 1.27 rillig -e 'file:stderr.exp' \
100 1.1 rillig "$indent" -v before.c after.c
101 1.1 rillig atf_check \
102 1.1 rillig -o 'file:after.c.exp' \
103 1.1 rillig cat after.c
104 1.1 rillig }
105 1.1 rillig
106 1.3 rillig atf_test_case 'nested_struct_declarations'
107 1.3 rillig nested_struct_declarations_body()
108 1.3 rillig {
109 1.3 rillig # Trigger the warning about nested struct declarations.
110 1.3 rillig
111 1.3 rillig cat <<-\EOF > code.c
112 1.3 rillig struct s01 { struct s02 { struct s03 { struct s04 {
113 1.3 rillig struct s05 { struct s06 { struct s07 { struct s08 {
114 1.3 rillig struct s09 { struct s10 { struct s11 { struct s12 {
115 1.3 rillig struct s13 { struct s14 { struct s15 { struct s16 {
116 1.3 rillig struct s17 { struct s18 { struct s19 { struct s20 {
117 1.3 rillig struct s21 { struct s22 { struct s23 { struct s24 {
118 1.3 rillig };};};};
119 1.3 rillig };};};};
120 1.3 rillig };};};};
121 1.3 rillig };};};};
122 1.3 rillig };};};};
123 1.3 rillig };};};};
124 1.3 rillig EOF
125 1.3 rillig cat <<-\EOF > expected.out
126 1.3 rillig struct s01 {
127 1.3 rillig struct s02 {
128 1.3 rillig struct s03 {
129 1.3 rillig struct s04 {
130 1.3 rillig struct s05 {
131 1.3 rillig struct s06 {
132 1.3 rillig struct s07 {
133 1.3 rillig struct s08 {
134 1.3 rillig struct s09 {
135 1.3 rillig struct s10 {
136 1.3 rillig struct s11 {
137 1.3 rillig struct s12 {
138 1.3 rillig struct s13 {
139 1.3 rillig struct s14 {
140 1.3 rillig struct s15 {
141 1.3 rillig struct s16 {
142 1.3 rillig struct s17 {
143 1.3 rillig struct s18 {
144 1.3 rillig struct s19 {
145 1.3 rillig struct s20 {
146 1.3 rillig struct s21 {
147 1.3 rillig struct s22 {
148 1.3 rillig struct s23 {
149 1.3 rillig struct s24 {
150 1.3 rillig };
151 1.3 rillig };
152 1.3 rillig };
153 1.3 rillig };
154 1.3 rillig };
155 1.3 rillig };
156 1.3 rillig };
157 1.3 rillig };
158 1.3 rillig };
159 1.3 rillig };
160 1.3 rillig };
161 1.3 rillig };
162 1.3 rillig };
163 1.3 rillig };
164 1.3 rillig };
165 1.3 rillig };
166 1.3 rillig };
167 1.3 rillig };
168 1.3 rillig };
169 1.3 rillig };
170 1.3 rillig };
171 1.3 rillig };
172 1.3 rillig };
173 1.3 rillig };
174 1.3 rillig EOF
175 1.3 rillig cat <<-\EOF > expected.err
176 1.8 rillig warning: Standard Input:5: Reached internal limit of 20 struct levels
177 1.8 rillig warning: Standard Input:6: Reached internal limit of 20 struct levels
178 1.8 rillig warning: Standard Input:6: Reached internal limit of 20 struct levels
179 1.8 rillig warning: Standard Input:6: Reached internal limit of 20 struct levels
180 1.8 rillig warning: Standard Input:6: Reached internal limit of 20 struct levels
181 1.3 rillig EOF
182 1.3 rillig
183 1.3 rillig atf_check -o 'file:expected.out' -e 'file:expected.err' \
184 1.3 rillig "$indent" -i1 -nut < 'code.c'
185 1.3 rillig }
186 1.3 rillig
187 1.4 rillig atf_test_case 'option_P_in_profile_file'
188 1.4 rillig option_P_in_profile_file_body()
189 1.4 rillig {
190 1.4 rillig # Mentioning another profile via -P has no effect since only a single
191 1.4 rillig # profile can be specified on the command line, and there is no
192 1.4 rillig # 'include' option.
193 1.4 rillig
194 1.4 rillig # It's syntactically possible to specify a profile file inside another
195 1.4 rillig # profile file. Such a profile file is ignored since only a single
196 1.4 rillig # profile file is ever loaded.
197 1.4 rillig printf '%s\n' '-P/nonexistent' > .indent.pro
198 1.4 rillig
199 1.4 rillig echo 'syntax # error' > code.c
200 1.4 rillig
201 1.24 rillig atf_check -o 'inline:syntax\n# error\n' \
202 1.4 rillig "$indent" < code.c
203 1.4 rillig }
204 1.4 rillig
205 1.13 rillig atf_test_case 'option_without_hyphen'
206 1.13 rillig option_without_hyphen_body()
207 1.13 rillig {
208 1.28 rillig # Ensure that options in profile files start with '-', just like
209 1.28 rillig # command line options.
210 1.13 rillig
211 1.13 rillig printf ' -i3 xi5 +di0\n' > .indent.pro
212 1.13 rillig
213 1.13 rillig printf '%s\n' 'int var[] = {' '1,' '}' > code.c
214 1.13 rillig printf '%s\n' 'int var[] = {' ' 1,' '}' > code.exp
215 1.13 rillig
216 1.28 rillig atf_check \
217 1.28 rillig -s 'exit:1' \
218 1.28 rillig -e "match:/.indent.pro: option \"xi5\" must start with '-'" \
219 1.13 rillig "$indent" < code.c
220 1.13 rillig }
221 1.13 rillig
222 1.5 rillig atf_test_case 'opt'
223 1.5 rillig opt_body()
224 1.5 rillig {
225 1.5 rillig # Test parsing of command line options from a profile file.
226 1.5 rillig
227 1.5 rillig cat <<-\EOF > code.c
228 1.5 rillig int global_var;
229 1.5 rillig
230 1.5 rillig int function(int expr) {
231 1.5 rillig switch (expr) { case 1: return 1; default: return 0; }
232 1.5 rillig }
233 1.5 rillig EOF
234 1.5 rillig
235 1.5 rillig cat << \EOF > .indent.pro
236 1.5 rillig /* The latter of the two options wins. */
237 1.5 rillig -di5
238 1.5 rillig -di12
239 1.5 rillig
240 1.5 rillig /*
241 1.5 rillig * It is possible to embed comments in the middle of an option, but nobody
242 1.5 rillig * does that.
243 1.5 rillig */
244 1.5 rillig -/* comment */bacc
245 1.5 rillig -T/* define
246 1.5 rillig a type */custom_type
247 1.5 rillig
248 1.9 rillig /* For int options, trailing garbage would be an error. */
249 1.5 rillig -i3
250 1.5 rillig
251 1.17 rillig /* For float options, trailing garbage would be an error. */
252 1.9 rillig -cli3.5
253 1.5 rillig
254 1.5 rillig -b/*/acc /* The comment is '/' '*' '/', making the option '-bacc'. */
255 1.5 rillig EOF
256 1.5 rillig
257 1.5 rillig sed '/[$]/d' << \EOF > code.exp
258 1.5 rillig /* $ The variable name is indented by 12 characters due to -di12. */
259 1.5 rillig int global_var;
260 1.5 rillig
261 1.5 rillig int
262 1.5 rillig function(int expr)
263 1.5 rillig {
264 1.5 rillig switch (expr) {
265 1.5 rillig /* $ The indentation is 3 + (int)(3.5 * 3), so 3 + 10.5, so 13. */
266 1.5 rillig /* $ See parse.c, function parse, 'case switch_expr'. */
267 1.5 rillig case 1:
268 1.5 rillig /* $ The indentation is 3 + (int)3.5 * 3 + 3, so 3 + 9 + 3, so 15. */
269 1.5 rillig /* $ See parse.c, function parse, 'case switch_expr'. */
270 1.5 rillig return 1;
271 1.5 rillig default:
272 1.5 rillig return 0;
273 1.5 rillig }
274 1.5 rillig }
275 1.5 rillig EOF
276 1.5 rillig
277 1.5 rillig atf_check -o 'file:code.exp' \
278 1.5 rillig "$indent" code.c -st
279 1.5 rillig }
280 1.5 rillig
281 1.5 rillig atf_test_case 'opt_npro'
282 1.5 rillig opt_npro_body()
283 1.5 rillig {
284 1.5 rillig # Mentioning the option -npro in a .pro file has no effect since at
285 1.5 rillig # that point, indent has already decided to load the .pro file, and
286 1.5 rillig # it only decides once.
287 1.5 rillig
288 1.5 rillig echo ' -npro -di8' > .indent.pro
289 1.5 rillig echo 'int var;' > code.c
290 1.5 rillig printf 'int\tvar;\n' > code.exp
291 1.5 rillig
292 1.5 rillig atf_check -o 'file:code.exp' \
293 1.5 rillig "$indent" code.c -st
294 1.5 rillig }
295 1.5 rillig
296 1.5 rillig atf_test_case 'opt_U'
297 1.5 rillig opt_U_body()
298 1.5 rillig {
299 1.5 rillig # From each line of this file, the first word is taken to be a type
300 1.5 rillig # name.
301 1.5 rillig #
302 1.5 rillig # Since neither '/*' nor '' are syntactically valid type names, this
303 1.5 rillig # means that all kinds of comments are effectively ignored. When a
304 1.5 rillig # type name is indented by whitespace, it is ignored as well.
305 1.5 rillig #
306 1.5 rillig # Since only the first word of each line is relevant, any remaining
307 1.5 rillig # words can be used for comments.
308 1.5 rillig cat <<-\EOF > code.types
309 1.5 rillig /* Comments are effectively ignored since they never match. */
310 1.5 rillig # This comment is ignored as well.
311 1.5 rillig ; So is this comment.
312 1.5 rillig # The following line is empty and adds a type whose name is empty.
313 1.5 rillig
314 1.5 rillig size_t from stddef.h
315 1.5 rillig off_t for file offsets
316 1.25 rillig ignored_t is ignored since it is indented
317 1.5 rillig EOF
318 1.5 rillig
319 1.5 rillig cat <<-\EOF > code.c
320 1.5 rillig int known_1 = (size_t) * arg;
321 1.5 rillig int known_2 = (off_t) * arg;
322 1.5 rillig int ignored = (ignored_t) * arg;
323 1.5 rillig EOF
324 1.5 rillig cat <<-\EOF > code.exp
325 1.5 rillig int known_1 = (size_t)*arg;
326 1.5 rillig int known_2 = (off_t)*arg;
327 1.5 rillig int ignored = (ignored_t) * arg;
328 1.5 rillig EOF
329 1.5 rillig
330 1.5 rillig atf_check -o 'file:code.exp' \
331 1.5 rillig "$indent" -Ucode.types code.c -di0 -st
332 1.5 rillig }
333 1.5 rillig
334 1.6 rillig atf_test_case 'line_no_counting'
335 1.6 rillig line_no_counting_body()
336 1.6 rillig {
337 1.7 rillig # Before NetBSD indent.c 1.147 from 2021-10-24, indent reported the
338 1.7 rillig # warning in line 2 instead of the correct line 3.
339 1.7 rillig
340 1.6 rillig cat <<-\EOF > code.c
341 1.6 rillig void line_no_counting(void)
342 1.6 rillig {
343 1.6 rillig ())
344 1.6 rillig }
345 1.6 rillig EOF
346 1.6 rillig
347 1.6 rillig cat <<-\EOF > code.err
348 1.10 rillig warning: code.c:3: Extra ')'
349 1.6 rillig EOF
350 1.6 rillig
351 1.6 rillig atf_check -o 'ignore' -e 'file:code.err' \
352 1.6 rillig "$indent" code.c -st
353 1.6 rillig }
354 1.6 rillig
355 1.11 rillig atf_test_case 'default_backup_extension'
356 1.11 rillig default_backup_extension_body()
357 1.11 rillig {
358 1.11 rillig echo 'int var;' > code.c
359 1.11 rillig echo 'int var;' > code.c.orig
360 1.11 rillig
361 1.11 rillig atf_check \
362 1.11 rillig "$indent" code.c
363 1.11 rillig atf_check -o 'file:code.c.orig' \
364 1.11 rillig cat code.c.BAK
365 1.11 rillig }
366 1.11 rillig
367 1.12 rillig atf_test_case 'several_profiles'
368 1.12 rillig several_profiles_body()
369 1.12 rillig {
370 1.12 rillig # If the option '-P' occurs several times, only the last of the
371 1.12 rillig # profiles is loaded, the others are ignored.
372 1.12 rillig
373 1.12 rillig echo ' --invalid-option' > error.pro
374 1.12 rillig echo '' > last.pro
375 1.12 rillig echo '' > code.c
376 1.12 rillig
377 1.12 rillig atf_check \
378 1.12 rillig "$indent" -Pnonexistent.pro -Perror.pro -Plast.pro code.c -st
379 1.12 rillig }
380 1.12 rillig
381 1.16 rillig
382 1.16 rillig atf_test_case 'command_line_vs_profile'
383 1.16 rillig command_line_vs_profile_body()
384 1.16 rillig {
385 1.16 rillig # Options from the command line override those from a profile file,
386 1.16 rillig # no matter if they appear earlier or later than the '-P' in the
387 1.16 rillig # command line.
388 1.16 rillig
389 1.16 rillig echo ' -di24' > custom.pro
390 1.16 rillig printf 'int\t\tdecl;\n' > code.c
391 1.16 rillig
392 1.16 rillig atf_check -o 'inline:int decl;\n' \
393 1.16 rillig "$indent" -di0 -Pcustom.pro code.c -st
394 1.16 rillig atf_check -o 'inline:int decl;\n' \
395 1.16 rillig "$indent" -Pcustom.pro -di0 code.c -st
396 1.16 rillig atf_check -o 'inline:int decl;\n' \
397 1.16 rillig "$indent" -Pcustom.pro code.c -st -di0
398 1.16 rillig }
399 1.16 rillig
400 1.21 rillig
401 1.21 rillig atf_test_case 'opt_v_break_line'
402 1.21 rillig opt_v_break_line_body()
403 1.21 rillig {
404 1.21 rillig printf '%s\n' 'int *function(void)' '{}' > code.c
405 1.21 rillig
406 1.27 rillig atf_check -o 'ignore' \
407 1.21 rillig "$indent" -v code.c -st
408 1.21 rillig }
409 1.21 rillig
410 1.26 rillig
411 1.26 rillig atf_test_case 'trailing_whitespace_in_preprocessing_line'
412 1.26 rillig trailing_whitespace_in_preprocessing_line_body()
413 1.26 rillig {
414 1.26 rillig printf '#if trailing && space \n#endif\n' > code.c
415 1.26 rillig
416 1.26 rillig atf_check -o 'inline:#if trailing && space\n#endif\n' \
417 1.26 rillig "$indent" code.c -st
418 1.26 rillig }
419 1.26 rillig
420 1.1 rillig atf_init_test_cases()
421 1.1 rillig {
422 1.2 rillig atf_add_test_case 'in_place'
423 1.1 rillig atf_add_test_case 'verbose_profile'
424 1.3 rillig atf_add_test_case 'nested_struct_declarations'
425 1.4 rillig atf_add_test_case 'option_P_in_profile_file'
426 1.13 rillig atf_add_test_case 'option_without_hyphen'
427 1.5 rillig atf_add_test_case 'opt'
428 1.5 rillig atf_add_test_case 'opt_npro'
429 1.5 rillig atf_add_test_case 'opt_U'
430 1.21 rillig atf_add_test_case 'opt_v_break_line'
431 1.6 rillig atf_add_test_case 'line_no_counting'
432 1.11 rillig atf_add_test_case 'default_backup_extension'
433 1.12 rillig atf_add_test_case 'several_profiles'
434 1.16 rillig atf_add_test_case 'command_line_vs_profile'
435 1.18 rillig atf_add_test_case 'in_place_parse_error'
436 1.26 rillig atf_add_test_case 'trailing_whitespace_in_preprocessing_line'
437 1.1 rillig }
438