Home | History | Annotate | Line # | Download | only in indent
t_misc.sh revision 1.12
      1 #! /bin/sh
      2 # $NetBSD: t_misc.sh,v 1.12 2021/10/30 09:32:46 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 'opt'
    194 opt_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
    217 a type */custom_type
    218 
    219 /* For int options, trailing garbage would be an error. */
    220 -i3
    221 
    222 /*For float options, trailing garbage would be an error. */
    223 -cli3.5
    224 
    225 -b/*/acc	/* The comment is '/' '*' '/', making the option '-bacc'. */
    226 EOF
    227 
    228 	sed '/[$]/d' << \EOF > code.exp
    229 /* $ The variable name is indented by 12 characters due to -di12. */
    230 int	    global_var;
    231 
    232 int
    233 function(int expr)
    234 {
    235    switch (expr) {
    236 /* $ The indentation is 3 + (int)(3.5 * 3), so 3 + 10.5, so 13. */
    237 /* $ See parse.c, function parse, 'case switch_expr'. */
    238 	     case 1:
    239 /* $ The indentation is 3 + (int)3.5 * 3 + 3, so 3 + 9 + 3, so 15. */
    240 /* $ See parse.c, function parse, 'case switch_expr'. */
    241 	       return 1;
    242 	     default:
    243 	       return 0;
    244    }
    245 }
    246 EOF
    247 
    248 	atf_check -o 'file:code.exp' \
    249 	    "$indent" code.c -st
    250 }
    251 
    252 atf_test_case 'opt_npro'
    253 opt_npro_body()
    254 {
    255 	# Mentioning the option -npro in a .pro file has no effect since at
    256 	# that point, indent has already decided to load the .pro file, and
    257 	# it only decides once.
    258 
    259 	echo ' -npro -di8' > .indent.pro
    260 	echo 'int var;' > code.c
    261 	printf 'int\tvar;\n' > code.exp
    262 
    263 	atf_check -o 'file:code.exp' \
    264 	    "$indent" code.c -st
    265 }
    266 
    267 atf_test_case 'opt_U'
    268 opt_U_body()
    269 {
    270 	# From each line of this file, the first word is taken to be a type
    271 	# name.
    272 	#
    273 	# Since neither '/*' nor '' are syntactically valid type names, this
    274 	# means that all kinds of comments are effectively ignored.  When a
    275 	# type name is indented by whitespace, it is ignored as well.
    276 	#
    277 	# Since only the first word of each line is relevant, any remaining
    278 	# words can be used for comments.
    279 	cat <<-\EOF > code.types
    280 		/* Comments are effectively ignored since they never match. */
    281 		# This comment is ignored as well.
    282 		; So is this comment.
    283 		# The following line is empty and adds a type whose name is empty.
    284 
    285 		size_t			from stddef.h
    286 		off_t			for file offsets
    287  		 ignored_t		is ignored since it is indented
    288 	EOF
    289 
    290 	cat <<-\EOF > code.c
    291 		int known_1 = (size_t)   *   arg;
    292 		int known_2 = (off_t)   *   arg;
    293 		int ignored = (ignored_t)   *   arg;
    294 	EOF
    295 	cat <<-\EOF > code.exp
    296 		int known_1 = (size_t)*arg;
    297 		int known_2 = (off_t)*arg;
    298 		int ignored = (ignored_t) * arg;
    299 	EOF
    300 
    301 	atf_check -o 'file:code.exp' \
    302 	    "$indent" -Ucode.types code.c -di0 -st
    303 }
    304 
    305 atf_test_case 'line_no_counting'
    306 line_no_counting_body()
    307 {
    308 	# Before NetBSD indent.c 1.147 from 2021-10-24, indent reported the
    309 	# warning in line 2 instead of the correct line 3.
    310 
    311 	cat <<-\EOF > code.c
    312 		void line_no_counting(void)
    313 		{
    314 			())
    315 		}
    316 	EOF
    317 
    318 	cat <<-\EOF > code.err
    319 		warning: code.c:3: Extra ')'
    320 	EOF
    321 
    322 	atf_check -o 'ignore' -e 'file:code.err' \
    323 	    "$indent" code.c -st
    324 }
    325 
    326 atf_test_case 'default_backup_extension'
    327 default_backup_extension_body()
    328 {
    329 	echo 'int var;' > code.c
    330 	echo 'int var;' > code.c.orig
    331 
    332 	atf_check \
    333 	    "$indent" code.c
    334 	atf_check -o 'file:code.c.orig' \
    335 	    cat code.c.BAK
    336 }
    337 
    338 atf_test_case 'several_profiles'
    339 several_profiles_body()
    340 {
    341 	# If the option '-P' occurs several times, only the last of the
    342 	# profiles is loaded, the others are ignored.
    343 
    344 	echo ' --invalid-option' > error.pro
    345 	echo '' > last.pro
    346 	echo '' > code.c
    347 
    348 	atf_check \
    349 	    "$indent" -Pnonexistent.pro -Perror.pro -Plast.pro code.c -st
    350 }
    351 
    352 atf_init_test_cases()
    353 {
    354 	atf_add_test_case 'in_place'
    355 	atf_add_test_case 'verbose_profile'
    356 	atf_add_test_case 'nested_struct_declarations'
    357 	atf_add_test_case 'option_P_in_profile_file'
    358 	atf_add_test_case 'opt'
    359 	atf_add_test_case 'opt_npro'
    360 	atf_add_test_case 'opt_U'
    361 	atf_add_test_case 'line_no_counting'
    362 	atf_add_test_case 'default_backup_extension'
    363 	atf_add_test_case 'several_profiles'
    364 }
    365