Home | History | Annotate | Line # | Download | only in indent
t_errors.sh revision 1.14
      1 #! /bin/sh
      2 # $NetBSD: t_errors.sh,v 1.14 2021/10/30 13:30:26 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_argument'
     65 option_int_missing_argument_body()
     66 {
     67 	expect_error \
     68 	    'indent: Command line: argument "x" to option "-ts" must be an integer' \
     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: argument "-1" to option "-ts" must be between 1 and 80' \
     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: argument "0" to option "-ts" must be between 1 and 80' \
    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: argument "81" to option "-ts" must be between 1 and 80' \
    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: argument "3000000000" to option "-ts" must be between 1 and 80' \
    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: argument "0" to option "-i" must be between 1 and 80' \
    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: argument "3garbage" to option "-i" must be an integer' \
    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 	expect_error \
    156 	    'indent: buffer overflow in indent.pro, starting with '\''-123456781'\''' \
    157 	    -Pindent.pro
    158 }
    159 
    160 atf_test_case 'option_special_missing_param'
    161 option_special_missing_param_body()
    162 {
    163 	# TODO: Write '-cli' instead of only 'cli'.
    164 	expect_error \
    165 	    'indent: Command line: ``cli'\'\'' requires an argument' \
    166 	    -cli
    167 
    168 	expect_error \
    169 	    'indent: Command line: ``T'\'\'' requires an argument' \
    170 	    -T
    171 
    172 	expect_error \
    173 	    'indent: Command line: ``U'\'\'' requires an argument' \
    174 	    -U
    175 }
    176 
    177 atf_test_case 'unterminated_comment'
    178 unterminated_comment_body()
    179 {
    180 	echo '/*' > comment.c
    181 
    182 	atf_check -s 'exit:1' \
    183 	    -o 'inline:/*'"$nl"' *'"$nl" \
    184 	    -e 'inline:error: Standard Input:2: Unterminated comment'"$nl" \
    185 	    "$indent" -st < comment.c
    186 }
    187 
    188 atf_test_case 'in_place_wrong_backup'
    189 in_place_wrong_backup_body()
    190 {
    191 	cat <<-\EOF > code.c
    192 		int decl;
    193 	EOF
    194 	cp code.c code.c.orig
    195 
    196 	# Due to the strange backup suffix '/subdir', indent tries to create
    197 	# a file named 'code.c/subdir', but 'code.c' is already a regular
    198 	# file, not a directory.
    199 	atf_check -s 'exit:1' \
    200 	    -e 'inline:indent: code.c/subdir: Not a directory'"$nl" \
    201 	    env SIMPLE_BACKUP_SUFFIX="/subdir" "$indent" code.c
    202 
    203 	# Since there was an early error, the original file is kept as is.
    204 	atf_check -o 'file:code.c.orig' \
    205 	    cat code.c
    206 }
    207 
    208 atf_test_case 'argument_input_enoent'
    209 argument_input_enoent_body()
    210 {
    211 	atf_check -s 'exit:1' \
    212 	    -e 'inline:indent: ./nonexistent.c: No such file or directory'"$nl" \
    213 	    "$indent" ./nonexistent.c
    214 }
    215 
    216 atf_test_case 'argument_output_equals_input_name'
    217 argument_output_equals_input_name_body()
    218 {
    219 	echo '/* comment */' > code.c
    220 
    221 	atf_check -s 'exit:1' \
    222 	    -e 'inline:indent: input and output files must be different'"$nl" \
    223 	    "$indent" code.c code.c
    224 }
    225 
    226 atf_test_case 'argument_output_equals_input_file'
    227 argument_output_equals_input_file_body()
    228 {
    229 	echo '/* comment */' > code.c
    230 
    231 	atf_check \
    232 	    "$indent" code.c ./code.c
    233 
    234 	# Oops, the file has become empty since the output is first emptied,
    235 	# before reading any of the input.
    236 	atf_check \
    237 	    cat code.c
    238 }
    239 
    240 atf_test_case 'argument_output_enoent'
    241 argument_output_enoent_body()
    242 {
    243 	expect_error \
    244 	    'indent: subdir/nonexistent.c: No such file or directory' \
    245 	    /dev/null subdir/nonexistent.c
    246 }
    247 
    248 atf_test_case 'argument_too_many'
    249 argument_too_many_body()
    250 {
    251 	echo '/* comment */' > arg1.c
    252 
    253 	expect_error \
    254 	    'indent: too many arguments: arg3.c' \
    255 	    arg1.c arg2.c arg3.c arg4.c
    256 }
    257 
    258 atf_test_case 'unexpected_end_of_file'
    259 unexpected_end_of_file_body()
    260 {
    261 	echo 'struct{' > code.c
    262 
    263 	expect_error \
    264 	    'error: code.c:1: Stuff missing from end of file' \
    265 	    code.c
    266 
    267 	atf_check \
    268 	    -o 'inline:struct {'"$nl" \
    269 	    cat code.c
    270 }
    271 
    272 atf_test_case 'unexpected_closing_brace_top_level'
    273 unexpected_closing_brace_top_level_body()
    274 {
    275 	echo '}' > code.c
    276 
    277 	expect_error \
    278 	    'error: code.c:1: Statement nesting error' \
    279 	    code.c
    280 	atf_check \
    281 	    -o 'inline:}'"$nl" \
    282 	    cat code.c
    283 }
    284 
    285 atf_test_case 'unexpected_closing_brace_decl'
    286 unexpected_closing_brace_decl_body()
    287 {
    288 	echo 'int i = 3};' > code.c
    289 
    290 	expect_error \
    291 	    'error: code.c:1: Statement nesting error' \
    292 	    code.c
    293 	# Despite the error message, the original file got overwritten with a
    294 	# best-effort rewrite of the code.
    295 	atf_check \
    296 	    -o 'inline:int		i = 3};'"$nl" \
    297 	    cat code.c
    298 }
    299 
    300 atf_test_case 'preprocessing_overflow'
    301 preprocessing_overflow_body()
    302 {
    303 	cat <<-\EOF > code.c
    304 		#if 1
    305 		#if 2
    306 		#if 3
    307 		#if 4
    308 		#if 5
    309 		#if 6
    310 		#endif 6
    311 		#endif 5
    312 		#endif 4
    313 		#endif 3
    314 		#endif 2
    315 		#endif 1
    316 		#endif too much
    317 	EOF
    318 	cat <<-\EOF > stderr.exp
    319 		error: code.c:6: #if stack overflow
    320 		error: code.c:12: Unmatched #endif
    321 		error: code.c:13: Unmatched #endif
    322 	EOF
    323 
    324 	atf_check -s 'exit:1' \
    325 	    -e 'file:stderr.exp' \
    326 	    "$indent" code.c
    327 }
    328 
    329 atf_test_case 'preprocessing_unrecognized'
    330 preprocessing_unrecognized_body()
    331 {
    332 	cat <<-\EOF > code.c
    333 		#unknown
    334 		# 3 "file.c"
    335 		#elif 3
    336 		#else
    337 	EOF
    338 	cat <<-\EOF > stderr.exp
    339 		error: code.c:1: Unrecognized cpp directive
    340 		error: code.c:2: Unrecognized cpp directive
    341 		error: code.c:3: Unmatched #elif
    342 		error: code.c:4: Unmatched #else
    343 	EOF
    344 
    345 	atf_check -s 'exit:1' \
    346 	    -e 'file:stderr.exp' \
    347 	    "$indent" code.c
    348 }
    349 
    350 atf_test_case 'unbalanced_parentheses_1'
    351 unbalanced_parentheses_1_body()
    352 {
    353 	cat <<-\EOF > code.c
    354 		int var =
    355 		(
    356 		;
    357 		)
    358 		;
    359 	EOF
    360 	cat <<-\EOF > stderr.exp
    361 		error: code.c:3: Unbalanced parentheses
    362 		warning: code.c:4: Extra ')'
    363 	EOF
    364 
    365 	atf_check -s 'exit:1' -e 'file:stderr.exp' \
    366 	    "$indent" code.c
    367 }
    368 
    369 atf_test_case 'unbalanced_parentheses_2'
    370 unbalanced_parentheses_2_body()
    371 {
    372 	# '({...})' is the GCC extension "Statement expression".
    373 	cat <<-\EOF > code.c
    374 		int var =
    375 		(
    376 		{
    377 		1
    378 		}
    379 		)
    380 		;
    381 	EOF
    382 	cat <<-\EOF > stderr.exp
    383 		error: code.c:3: Unbalanced parentheses
    384 		warning: code.c:6: Extra ')'
    385 	EOF
    386 
    387 	atf_check -s 'exit:1' -e 'file:stderr.exp' \
    388 	    "$indent" code.c
    389 }
    390 
    391 atf_test_case 'unbalanced_parentheses_3'
    392 unbalanced_parentheses_3_body()
    393 {
    394 	# '({...})' is the GCC extension "Statement expression".
    395 	cat <<-\EOF > code.c
    396 		int var =
    397 		(
    398 		1
    399 		}
    400 		;
    401 	EOF
    402 	cat <<-\EOF > stderr.exp
    403 		error: code.c:4: Unbalanced parentheses
    404 		error: code.c:4: Statement nesting error
    405 	EOF
    406 
    407 	atf_check -s 'exit:1' -e 'file:stderr.exp' \
    408 	    "$indent" code.c
    409 }
    410 
    411 atf_test_case 'search_stmt_comment_segv'
    412 search_stmt_comment_segv_body()
    413 {
    414 	# Before NetBSD indent.c 1.187 from 2021-10-30, indent crashed while
    415 	# trying to format the following artificial code.
    416 
    417 	printf '{if(expr\n)/*c*/;}\n' > code.c
    418 
    419 	cat <<\EOF > code.exp
    420 {
    421 	if (expr
    422 		)		/* c */
    423 		;
    424 }
    425 EOF
    426 	atf_check -o 'file:code.exp' \
    427 	    "$indent" code.c -st
    428 }
    429 
    430 atf_init_test_cases()
    431 {
    432 	atf_add_test_case 'option_unknown'
    433 	atf_add_test_case 'option_bool_trailing_garbage'
    434 	atf_add_test_case 'option_int_missing_argument'
    435 	atf_add_test_case 'option_profile_not_found'
    436 	atf_add_test_case 'option_buffer_overflow'
    437 	atf_add_test_case 'option_typedefs_not_found'
    438 	atf_add_test_case 'option_special_missing_param'
    439 	atf_add_test_case 'option_tabsize_negative'
    440 	atf_add_test_case 'option_tabsize_zero'
    441 	atf_add_test_case 'option_tabsize_large'
    442 	atf_add_test_case 'option_tabsize_very_large'
    443 	atf_add_test_case 'option_int_trailing_garbage'
    444 	atf_add_test_case 'option_cli_trailing_garbage'
    445 	atf_add_test_case 'option_indent_size_zero'
    446 	atf_add_test_case 'unterminated_comment'
    447 	atf_add_test_case 'in_place_wrong_backup'
    448 	atf_add_test_case 'argument_input_enoent'
    449 	atf_add_test_case 'argument_output_equals_input_name'
    450 	atf_add_test_case 'argument_output_equals_input_file'
    451 	atf_add_test_case 'argument_output_enoent'
    452 	atf_add_test_case 'argument_too_many'
    453 	atf_add_test_case 'unexpected_end_of_file'
    454 	atf_add_test_case 'unexpected_closing_brace_top_level'
    455 	atf_add_test_case 'unexpected_closing_brace_decl'
    456 	atf_add_test_case 'preprocessing_overflow'
    457 	atf_add_test_case 'preprocessing_unrecognized'
    458 	atf_add_test_case 'unbalanced_parentheses_1'
    459 	atf_add_test_case 'unbalanced_parentheses_2'
    460 	atf_add_test_case 'unbalanced_parentheses_3'
    461 	atf_add_test_case 'search_stmt_comment_segv'
    462 }
    463