t_misc.sh revision 1.6
1#! /bin/sh
2# $NetBSD: t_misc.sh,v 1.6 2021/10/24 16:46:12 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
33indent=$(atf_config_get usr.bin.indent.test_indent /usr/bin/indent)
34nl='
35'
36
37atf_test_case 'in_place'
38in_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
56atf_test_case 'verbose_profile'
57verbose_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
94atf_test_case 'nested_struct_declarations'
95nested_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		/**INDENT** Warning@5: Reached internal limit of 20 struct levels */
165		/**INDENT** Warning@6: Reached internal limit of 20 struct levels */
166		/**INDENT** Warning@6: Reached internal limit of 20 struct levels */
167		/**INDENT** Warning@6: Reached internal limit of 20 struct levels */
168		/**INDENT** Warning@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
175atf_test_case 'option_P_in_profile_file'
176option_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
193atf_test_case 'opt'
194opt_body()
195{
196	# Test parsing of command line options from a profile file.
197
198	cat <<-\EOF > code.c
199		int global_var;
200
201		int function(int expr) {
202		switch (expr) { case 1: return 1; default: return 0; }
203		}
204	EOF
205
206	cat << \EOF > .indent.pro
207/* The latter of the two options wins. */
208-di5
209-di12
210
211/*
212 * It is possible to embed comments in the middle of an option, but nobody
213 * does that.
214 */
215-/* comment */bacc
216-T/* define
217a type */custom_type
218
219/* For int options, trailing garbage would lead to an error message. */
220-i3
221
222/*
223 * For float options, trailing garbage is ignored.
224 *
225 * See atof.
226 */
227-cli3.5garbage
228
229-b/*/acc	/* The comment is '/' '*' '/', making the option '-bacc'. */
230EOF
231
232	sed '/[$]/d' << \EOF > code.exp
233/* $ The variable name is indented by 12 characters due to -di12. */
234int	    global_var;
235
236int
237function(int expr)
238{
239   switch (expr) {
240/* $ The indentation is 3 + (int)(3.5 * 3), so 3 + 10.5, so 13. */
241/* $ See parse.c, function parse, 'case switch_expr'. */
242	     case 1:
243/* $ The indentation is 3 + (int)3.5 * 3 + 3, so 3 + 9 + 3, so 15. */
244/* $ See parse.c, function parse, 'case switch_expr'. */
245	       return 1;
246	     default:
247	       return 0;
248   }
249}
250EOF
251
252	atf_check -o 'file:code.exp' \
253	    "$indent" code.c -st
254}
255
256atf_test_case 'opt_npro'
257opt_npro_body()
258{
259	# Mentioning the option -npro in a .pro file has no effect since at
260	# that point, indent has already decided to load the .pro file, and
261	# it only decides once.
262
263	echo ' -npro -di8' > .indent.pro
264	echo 'int var;' > code.c
265	printf 'int\tvar;\n' > code.exp
266
267	atf_check -o 'file:code.exp' \
268	    "$indent" code.c -st
269}
270
271atf_test_case 'opt_U'
272opt_U_body()
273{
274	# From each line of this file, the first word is taken to be a type
275	# name.
276	#
277	# Since neither '/*' nor '' are syntactically valid type names, this
278	# means that all kinds of comments are effectively ignored.  When a
279	# type name is indented by whitespace, it is ignored as well.
280	#
281	# Since only the first word of each line is relevant, any remaining
282	# words can be used for comments.
283	cat <<-\EOF > code.types
284		/* Comments are effectively ignored since they never match. */
285		# This comment is ignored as well.
286		; So is this comment.
287		# The following line is empty and adds a type whose name is empty.
288
289		size_t			from stddef.h
290		off_t			for file offsets
291 		 ignored_t		is ignored since it is indented
292	EOF
293
294	cat <<-\EOF > code.c
295		int known_1 = (size_t)   *   arg;
296		int known_2 = (off_t)   *   arg;
297		int ignored = (ignored_t)   *   arg;
298	EOF
299	cat <<-\EOF > code.exp
300		int known_1 = (size_t)*arg;
301		int known_2 = (off_t)*arg;
302		int ignored = (ignored_t) * arg;
303	EOF
304
305	atf_check -o 'file:code.exp' \
306	    "$indent" -Ucode.types code.c -di0 -st
307}
308
309atf_test_case 'line_no_counting'
310line_no_counting_body()
311{
312	cat <<-\EOF > code.c
313		void line_no_counting(void)
314		{
315			())
316		}
317	EOF
318
319	# FIXME: the wrong ')' is in line 3, not 2.
320	cat <<-\EOF > code.err
321		/**INDENT** Warning@2: Extra ) */
322	EOF
323
324	atf_check -o 'ignore' -e 'file:code.err' \
325	    "$indent" code.c -st
326}
327
328atf_init_test_cases()
329{
330	atf_add_test_case 'in_place'
331	atf_add_test_case 'verbose_profile'
332	atf_add_test_case 'nested_struct_declarations'
333	atf_add_test_case 'option_P_in_profile_file'
334	atf_add_test_case 'opt'
335	atf_add_test_case 'opt_npro'
336	atf_add_test_case 'opt_U'
337	atf_add_test_case 'line_no_counting'
338}
339