Home | History | Annotate | Line # | Download | only in indent
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