Home | History | Annotate | Line # | Download | only in indent
t_errors.sh revision 1.6
      1 #! /bin/sh
      2 # $NetBSD: t_errors.sh,v 1.6 2021/10/28 21:02:05 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 error handling in indent.
     31 
     32 indent=$(atf_config_get usr.bin.indent.test_indent /usr/bin/indent)
     33 nl='
     34 '
     35 
     36 expect_error()
     37 {
     38 	local msg
     39 
     40 	msg="$1"
     41 	shift
     42 
     43 	atf_check -s 'exit:1' \
     44 	    -e "inline:$msg$nl" \
     45 	    "$indent" "$@"
     46 }
     47 
     48 atf_test_case 'option_unknown'
     49 option_unknown_body()
     50 {
     51 	expect_error \
     52 	    'indent: Command line: unknown option "-Z-unknown"' \
     53 	    -Z-unknown
     54 }
     55 
     56 atf_test_case 'option_bool_trailing_garbage'
     57 option_bool_trailing_garbage_body()
     58 {
     59 	expect_error \
     60 	    'indent: Command line: unknown option "-bacchus"' \
     61 	    -bacchus
     62 }
     63 
     64 atf_test_case 'option_int_missing_parameter'
     65 option_int_missing_parameter_body()
     66 {
     67 	expect_error \
     68 	    'indent: Command line: option "-ts" requires an integer parameter' \
     69 	    -tsx
     70 }
     71 
     72 atf_test_case 'option_profile_not_found'
     73 option_profile_not_found_body()
     74 {
     75 	expect_error \
     76 	    'indent: profile ./nonexistent: No such file or directory' \
     77 	    -P./nonexistent
     78 }
     79 
     80 atf_test_case 'option_typedefs_not_found'
     81 option_typedefs_not_found_body()
     82 {
     83 	expect_error \
     84 	    'indent: cannot open file ./nonexistent' \
     85 	    -U./nonexistent
     86 }
     87 
     88 atf_test_case 'option_tabsize_negative'
     89 option_tabsize_negative_body()
     90 {
     91 	expect_error \
     92 	    'indent: Command line: option "-ts" requires an integer parameter' \
     93 	    -ts-1
     94 }
     95 
     96 atf_test_case 'option_tabsize_zero'
     97 option_tabsize_zero_body()
     98 {
     99 	expect_error \
    100 	    'indent: Command line: invalid argument "0" for option "-ts"' \
    101 	    -ts0
    102 }
    103 
    104 atf_test_case 'option_tabsize_large'
    105 option_tabsize_large_body()
    106 {
    107 	# Integer overflow, on both ILP32 and LP64 platforms.
    108 	expect_error \
    109 	    'indent: Command line: invalid argument "81" for option "-ts"' \
    110 	    -ts81
    111 }
    112 
    113 atf_test_case 'option_tabsize_very_large'
    114 option_tabsize_very_large_body()
    115 {
    116 	# Integer overflow, on both ILP32 and LP64 platforms.
    117 	expect_error \
    118 	    'indent: Command line: invalid argument "3000000000" for option "-ts"' \
    119 	    -ts3000000000
    120 }
    121 
    122 atf_test_case 'option_indent_size_zero'
    123 option_indent_size_zero_body()
    124 {
    125 	expect_error \
    126 	    'indent: Command line: invalid argument "0" for option "-i"' \
    127 	    -i0
    128 }
    129 
    130 atf_test_case 'option_int_trailing_garbage'
    131 option_int_trailing_garbage_body()
    132 {
    133 	expect_error \
    134 	    'indent: Command line: invalid argument "3garbage" for option "-i"' \
    135 	    -i3garbage
    136 }
    137 
    138 atf_test_case 'option_cli_trailing_garbage'
    139 option_cli_trailing_garbage_body()
    140 {
    141 	expect_error \
    142 	    'indent: Command line: argument "3garbage" to option "-cli" must be numeric' \
    143 	    -cli3garbage
    144 }
    145 
    146 atf_test_case 'option_buffer_overflow'
    147 option_buffer_overflow_body()
    148 {
    149 	opt='12345678123456781234567812345678'	# 32
    150 	opt="$opt$opt$opt$opt$opt$opt$opt$opt"	# 256
    151 	opt="$opt$opt$opt$opt$opt$opt$opt$opt"	# 2048
    152 	opt="$opt$opt$opt$opt$opt$opt$opt$opt"	# 16384
    153 	printf '%s\n' "-$opt" > indent.pro
    154 
    155 	# TODO: The call to 'diag' should be replaced with 'errx'.
    156 	expect_error \
    157 	    'error: Standard Input:1: buffer overflow in indent.pro, starting with '\''-123456781'\''' \
    158 	    -Pindent.pro
    159 }
    160 
    161 atf_test_case 'option_special_missing_param'
    162 option_special_missing_param_body()
    163 {
    164 	# TODO: Write '-cli' instead of only 'cli'.
    165 	expect_error \
    166 	    'indent: Command line: ``cli'\'\'' requires a parameter' \
    167 	    -cli
    168 
    169 	expect_error \
    170 	    'indent: Command line: ``T'\'\'' requires a parameter' \
    171 	    -T
    172 
    173 	expect_error \
    174 	    'indent: Command line: ``U'\'\'' requires a parameter' \
    175 	    -U
    176 }
    177 
    178 atf_test_case 'unterminated_comment'
    179 unterminated_comment_body()
    180 {
    181 	echo '/*' > comment.c
    182 
    183 	atf_check -s 'exit:1' \
    184 	    -o 'inline:/*'"$nl"' *'"$nl" \
    185 	    -e 'inline:error: Standard Input:2: Unterminated comment'"$nl" \
    186 	    "$indent" -st < comment.c
    187 }
    188 
    189 atf_test_case 'in_place_wrong_backup'
    190 in_place_wrong_backup_body()
    191 {
    192 	cat <<-\EOF > code.c
    193 		int decl;
    194 	EOF
    195 	cp code.c code.c.orig
    196 
    197 	# Due to the strange backup suffix '/subdir', indent tries to create
    198 	# a file named 'code.c/subdir', but 'code.c' is already a regular
    199 	# file, not a directory.
    200 	atf_check -s 'exit:1' \
    201 	    -e 'inline:indent: code.c/subdir: Not a directory'"$nl" \
    202 	    env SIMPLE_BACKUP_SUFFIX="/subdir" "$indent" code.c
    203 
    204 	# Since there was an early error, the original file is kept as is.
    205 	atf_check -o 'file:code.c.orig' \
    206 	    cat code.c
    207 }
    208 
    209 atf_test_case 'argument_input_enoent'
    210 argument_input_enoent_body()
    211 {
    212 	atf_check -s 'exit:1' \
    213 	    -e 'inline:indent: ./nonexistent.c: No such file or directory'"$nl" \
    214 	    "$indent" ./nonexistent.c
    215 }
    216 
    217 atf_test_case 'argument_output_equals_input_name'
    218 argument_output_equals_input_name_body()
    219 {
    220 	echo '/* comment */' > code.c
    221 
    222 	atf_check -s 'exit:1' \
    223 	    -e 'inline:indent: input and output files must be different'"$nl" \
    224 	    "$indent" code.c code.c
    225 }
    226 
    227 atf_test_case 'argument_output_equals_input_file'
    228 argument_output_equals_input_file_body()
    229 {
    230 	echo '/* comment */' > code.c
    231 
    232 	atf_check \
    233 	    "$indent" code.c ./code.c
    234 
    235 	# Oops, the file has become empty since the output is first emptied,
    236 	# before reading any of the input.
    237 	atf_check \
    238 	    cat code.c
    239 }
    240 
    241 atf_test_case 'argument_output_enoent'
    242 argument_output_enoent_body()
    243 {
    244 	expect_error \
    245 	    'indent: subdir/nonexistent.c: No such file or directory' \
    246 	    /dev/null subdir/nonexistent.c
    247 }
    248 
    249 atf_test_case 'argument_too_many'
    250 argument_too_many_body()
    251 {
    252 	echo '/* comment */' > arg1.c
    253 
    254 	expect_error \
    255 	    'indent: unknown parameter: arg3.c' \
    256 	    arg1.c arg2.c arg3.c arg4.c
    257 }
    258 
    259 atf_test_case 'unexpected_end_of_file'
    260 unexpected_end_of_file_body()
    261 {
    262 	echo 'struct{' > code.c
    263 
    264 	expect_error \
    265 	    'error: code.c:1: Stuff missing from end of file' \
    266 	    code.c
    267 
    268 	atf_check \
    269 	    -o 'inline:struct {'"$nl" \
    270 	    cat code.c
    271 }
    272 
    273 atf_test_case 'unexpected_closing_brace_top_level'
    274 unexpected_closing_brace_top_level_body()
    275 {
    276 	echo '}' > code.c
    277 
    278 	expect_error \
    279 	    'error: code.c:1: Statement nesting error' \
    280 	    code.c
    281 	atf_check \
    282 	    -o 'inline:}'"$nl" \
    283 	    cat code.c
    284 }
    285 
    286 atf_test_case 'unexpected_closing_brace_decl'
    287 unexpected_closing_brace_decl_body()
    288 {
    289 	echo 'int i = 3};' > code.c
    290 
    291 	expect_error \
    292 	    'error: code.c:1: Statement nesting error' \
    293 	    code.c
    294 	# Despite the error message, the original file got overwritten with a
    295 	# best-effort rewrite of the code.
    296 	atf_check \
    297 	    -o 'inline:int		i = 3};'"$nl" \
    298 	    cat code.c
    299 }
    300 
    301 atf_test_case 'preprocessing_overflow'
    302 preprocessing_overflow_body()
    303 {
    304 	cat <<-\EOF > code.c
    305 		#if 1
    306 		#if 2
    307 		#if 3
    308 		#if 4
    309 		#if 5
    310 		#if 6
    311 		#endif 6
    312 		#endif 5
    313 		#endif 4
    314 		#endif 3
    315 		#endif 2
    316 		#endif 1
    317 		#endif too much
    318 	EOF
    319 	cat <<-\EOF > stderr.exp
    320 		error: code.c:6: #if stack overflow
    321 		error: code.c:12: Unmatched #endif
    322 		error: code.c:13: Unmatched #endif
    323 	EOF
    324 
    325 	atf_check -s 'exit:1' \
    326 	    -e 'file:stderr.exp' \
    327 	    "$indent" code.c
    328 }
    329 
    330 atf_test_case 'preprocessing_unrecognized'
    331 preprocessing_unrecognized_body()
    332 {
    333 	cat <<-\EOF > code.c
    334 		#unknown
    335 		# 3 "file.c"
    336 		#elif 3
    337 		#else
    338 	EOF
    339 	cat <<-\EOF > stderr.exp
    340 		error: code.c:1: Unrecognized cpp directive
    341 		error: code.c:2: Unrecognized cpp directive
    342 		error: code.c:3: Unmatched #elif
    343 		error: code.c:4: Unmatched #else
    344 	EOF
    345 
    346 	atf_check -s 'exit:1' \
    347 	    -e 'file:stderr.exp' \
    348 	    "$indent" code.c
    349 }
    350 
    351 atf_init_test_cases()
    352 {
    353 	atf_add_test_case 'option_unknown'
    354 	atf_add_test_case 'option_bool_trailing_garbage'
    355 	atf_add_test_case 'option_int_missing_parameter'
    356 	atf_add_test_case 'option_profile_not_found'
    357 	atf_add_test_case 'option_buffer_overflow'
    358 	atf_add_test_case 'option_typedefs_not_found'
    359 	atf_add_test_case 'option_special_missing_param'
    360 	atf_add_test_case 'option_tabsize_negative'
    361 	atf_add_test_case 'option_tabsize_zero'
    362 	atf_add_test_case 'option_tabsize_large'
    363 	atf_add_test_case 'option_tabsize_very_large'
    364 	atf_add_test_case 'option_int_trailing_garbage'
    365 	atf_add_test_case 'option_cli_trailing_garbage'
    366 	atf_add_test_case 'option_indent_size_zero'
    367 	atf_add_test_case 'unterminated_comment'
    368 	atf_add_test_case 'in_place_wrong_backup'
    369 	atf_add_test_case 'argument_input_enoent'
    370 	atf_add_test_case 'argument_output_equals_input_name'
    371 	atf_add_test_case 'argument_output_equals_input_file'
    372 	atf_add_test_case 'argument_output_enoent'
    373 	atf_add_test_case 'argument_too_many'
    374 	atf_add_test_case 'unexpected_end_of_file'
    375 	atf_add_test_case 'unexpected_closing_brace_top_level'
    376 	atf_add_test_case 'unexpected_closing_brace_decl'
    377 	atf_add_test_case 'preprocessing_overflow'
    378 	atf_add_test_case 'preprocessing_unrecognized'
    379 }
    380