t_misc.sh revision 1.15 1 #! /bin/sh
2 # $NetBSD: t_misc.sh,v 1.15 2021/11/07 19:18:56 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 indent that do not follow the input-profile-output scheme that is
31 # used in t_indent.
32
33 indent=$(atf_config_get usr.bin.indent.test_indent /usr/bin/indent)
34 nl='
35 '
36
37 atf_test_case 'in_place'
38 in_place_body()
39 {
40 cat <<-\EOF > code.c
41 int decl;
42 EOF
43 cat <<-\EOF > code.c.exp
44 int decl;
45 EOF
46 cp code.c code.c.orig
47
48 atf_check \
49 env SIMPLE_BACKUP_SUFFIX=".bak" "$indent" code.c
50 atf_check -o 'file:code.c.exp' \
51 cat code.c
52 atf_check -o 'file:code.c.orig' \
53 cat code.c.bak
54 }
55
56 atf_test_case 'verbose_profile'
57 verbose_profile_body()
58 {
59 cat <<-\EOF > .indent.pro
60 -/* comment */bacc
61 -v
62 -fc1
63 EOF
64 cat <<-\EOF > before.c
65 int decl;
66 EOF
67 cat <<-\EOF > after.c.exp
68 int decl;
69 EOF
70 cat <<-\EOF > stdout.exp
71 profile: -fc1
72 profile: -bacc
73 profile: -v
74 profile: -fc1
75 There were 1 output lines and 0 comments
76 (Lines with comments)/(Lines with code): 0.000
77 EOF
78
79 # The code in args.c function set_profile suggests that options from
80 # profile files are echoed to stdout during startup. But since the
81 # command line options are handled after the profile files, a '-v' in
82 # the command line has no effect. That's why '-bacc' is not listed
83 # in stdout, but '-fc1' is. The second round of '-bacc', '-v', '-fc1'
84 # is listed because when running ATF, $HOME equals $PWD.
85
86 atf_check \
87 -o 'file:stdout.exp' \
88 "$indent" -v before.c after.c
89 atf_check \
90 -o 'file:after.c.exp' \
91 cat after.c
92 }
93
94 atf_test_case 'nested_struct_declarations'
95 nested_struct_declarations_body()
96 {
97 # Trigger the warning about nested struct declarations.
98
99 cat <<-\EOF > code.c
100 struct s01 { struct s02 { struct s03 { struct s04 {
101 struct s05 { struct s06 { struct s07 { struct s08 {
102 struct s09 { struct s10 { struct s11 { struct s12 {
103 struct s13 { struct s14 { struct s15 { struct s16 {
104 struct s17 { struct s18 { struct s19 { struct s20 {
105 struct s21 { struct s22 { struct s23 { struct s24 {
106 };};};};
107 };};};};
108 };};};};
109 };};};};
110 };};};};
111 };};};};
112 EOF
113 cat <<-\EOF > expected.out
114 struct s01 {
115 struct s02 {
116 struct s03 {
117 struct s04 {
118 struct s05 {
119 struct s06 {
120 struct s07 {
121 struct s08 {
122 struct s09 {
123 struct s10 {
124 struct s11 {
125 struct s12 {
126 struct s13 {
127 struct s14 {
128 struct s15 {
129 struct s16 {
130 struct s17 {
131 struct s18 {
132 struct s19 {
133 struct s20 {
134 struct s21 {
135 struct s22 {
136 struct s23 {
137 struct s24 {
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 EOF
163 cat <<-\EOF > expected.err
164 warning: Standard Input:5: Reached internal limit of 20 struct levels
165 warning: Standard Input:6: Reached internal limit of 20 struct levels
166 warning: Standard Input:6: Reached internal limit of 20 struct levels
167 warning: Standard Input:6: Reached internal limit of 20 struct levels
168 warning: Standard Input:6: Reached internal limit of 20 struct levels
169 EOF
170
171 atf_check -o 'file:expected.out' -e 'file:expected.err' \
172 "$indent" -i1 -nut < 'code.c'
173 }
174
175 atf_test_case 'option_P_in_profile_file'
176 option_P_in_profile_file_body()
177 {
178 # Mentioning another profile via -P has no effect since only a single
179 # profile can be specified on the command line, and there is no
180 # 'include' option.
181
182 # It's syntactically possible to specify a profile file inside another
183 # profile file. Such a profile file is ignored since only a single
184 # profile file is ever loaded.
185 printf '%s\n' '-P/nonexistent' > .indent.pro
186
187 echo 'syntax # error' > code.c
188
189 atf_check -o 'inline:syntax'"$nl"'#error'"$nl" \
190 "$indent" < code.c
191 }
192
193 atf_test_case 'option_without_hyphen'
194 option_without_hyphen_body()
195 {
196 # TODO: Options in profile files should be required to start with
197 # '-', just like in the command line arguments.
198
199 printf ' -i3 xi5 +di0\n' > .indent.pro
200
201 printf '%s\n' 'int var[] = {' '1,' '}' > code.c
202 printf '%s\n' 'int var[] = {' ' 1,' '}' > code.exp
203
204 atf_check -o 'file:code.exp' \
205 "$indent" < code.c
206 }
207
208 atf_test_case 'opt'
209 opt_body()
210 {
211 # Test parsing of command line options from a profile file.
212
213 cat <<-\EOF > code.c
214 int global_var;
215
216 int function(int expr) {
217 switch (expr) { case 1: return 1; default: return 0; }
218 }
219 EOF
220
221 cat << \EOF > .indent.pro
222 /* The latter of the two options wins. */
223 -di5
224 -di12
225
226 /*
227 * It is possible to embed comments in the middle of an option, but nobody
228 * does that.
229 */
230 -/* comment */bacc
231 -T/* define
232 a type */custom_type
233
234 /* For int options, trailing garbage would be an error. */
235 -i3
236
237 /*For float options, trailing garbage would be an error. */
238 -cli3.5
239
240 -b/*/acc /* The comment is '/' '*' '/', making the option '-bacc'. */
241 EOF
242
243 sed '/[$]/d' << \EOF > code.exp
244 /* $ The variable name is indented by 12 characters due to -di12. */
245 int global_var;
246
247 int
248 function(int expr)
249 {
250 switch (expr) {
251 /* $ The indentation is 3 + (int)(3.5 * 3), so 3 + 10.5, so 13. */
252 /* $ See parse.c, function parse, 'case switch_expr'. */
253 case 1:
254 /* $ The indentation is 3 + (int)3.5 * 3 + 3, so 3 + 9 + 3, so 15. */
255 /* $ See parse.c, function parse, 'case switch_expr'. */
256 return 1;
257 default:
258 return 0;
259 }
260 }
261 EOF
262
263 atf_check -o 'file:code.exp' \
264 "$indent" code.c -st
265 }
266
267 atf_test_case 'opt_npro'
268 opt_npro_body()
269 {
270 # Mentioning the option -npro in a .pro file has no effect since at
271 # that point, indent has already decided to load the .pro file, and
272 # it only decides once.
273
274 echo ' -npro -di8' > .indent.pro
275 echo 'int var;' > code.c
276 printf 'int\tvar;\n' > code.exp
277
278 atf_check -o 'file:code.exp' \
279 "$indent" code.c -st
280 }
281
282 atf_test_case 'opt_U'
283 opt_U_body()
284 {
285 # From each line of this file, the first word is taken to be a type
286 # name.
287 #
288 # Since neither '/*' nor '' are syntactically valid type names, this
289 # means that all kinds of comments are effectively ignored. When a
290 # type name is indented by whitespace, it is ignored as well.
291 #
292 # Since only the first word of each line is relevant, any remaining
293 # words can be used for comments.
294 cat <<-\EOF > code.types
295 /* Comments are effectively ignored since they never match. */
296 # This comment is ignored as well.
297 ; So is this comment.
298 # The following line is empty and adds a type whose name is empty.
299
300 size_t from stddef.h
301 off_t for file offsets
302 ignored_t is ignored since it is indented
303 EOF
304
305 cat <<-\EOF > code.c
306 int known_1 = (size_t) * arg;
307 int known_2 = (off_t) * arg;
308 int ignored = (ignored_t) * arg;
309 EOF
310 cat <<-\EOF > code.exp
311 int known_1 = (size_t)*arg;
312 int known_2 = (off_t)*arg;
313 int ignored = (ignored_t) * arg;
314 EOF
315
316 atf_check -o 'file:code.exp' \
317 "$indent" -Ucode.types code.c -di0 -st
318 }
319
320 atf_test_case 'line_no_counting'
321 line_no_counting_body()
322 {
323 # Before NetBSD indent.c 1.147 from 2021-10-24, indent reported the
324 # warning in line 2 instead of the correct line 3.
325
326 cat <<-\EOF > code.c
327 void line_no_counting(void)
328 {
329 ())
330 }
331 EOF
332
333 cat <<-\EOF > code.err
334 warning: code.c:3: Extra ')'
335 EOF
336
337 atf_check -o 'ignore' -e 'file:code.err' \
338 "$indent" code.c -st
339 }
340
341 atf_test_case 'default_backup_extension'
342 default_backup_extension_body()
343 {
344 echo 'int var;' > code.c
345 echo 'int var;' > code.c.orig
346
347 atf_check \
348 "$indent" code.c
349 atf_check -o 'file:code.c.orig' \
350 cat code.c.BAK
351 }
352
353 atf_test_case 'several_profiles'
354 several_profiles_body()
355 {
356 # If the option '-P' occurs several times, only the last of the
357 # profiles is loaded, the others are ignored.
358
359 echo ' --invalid-option' > error.pro
360 echo '' > last.pro
361 echo '' > code.c
362
363 atf_check \
364 "$indent" -Pnonexistent.pro -Perror.pro -Plast.pro code.c -st
365 }
366
367 atf_init_test_cases()
368 {
369 atf_add_test_case 'in_place'
370 atf_add_test_case 'verbose_profile'
371 atf_add_test_case 'nested_struct_declarations'
372 atf_add_test_case 'option_P_in_profile_file'
373 atf_add_test_case 'option_without_hyphen'
374 atf_add_test_case 'opt'
375 atf_add_test_case 'opt_npro'
376 atf_add_test_case 'opt_U'
377 atf_add_test_case 'line_no_counting'
378 atf_add_test_case 'default_backup_extension'
379 atf_add_test_case 'several_profiles'
380 }
381