1122ad694Srillig#! /bin/sh 2*b4747d0dSrillig# $NetBSD: t_misc.sh,v 1.29 2023/12/17 10:02:09 rillig Exp $ 3122ad694Srillig# 4122ad694Srillig# Copyright (c) 2021 The NetBSD Foundation, Inc. 5122ad694Srillig# All rights reserved. 6122ad694Srillig# 7122ad694Srillig# Redistribution and use in source and binary forms, with or without 8122ad694Srillig# modification, are permitted provided that the following conditions 9122ad694Srillig# are met: 10122ad694Srillig# 1. Redistributions of source code must retain the above copyright 11122ad694Srillig# notice, this list of conditions and the following disclaimer. 12122ad694Srillig# 2. Redistributions in binary form must reproduce the above copyright 13122ad694Srillig# notice, this list of conditions and the following disclaimer in the 14122ad694Srillig# documentation and/or other materials provided with the distribution. 15122ad694Srillig# 16122ad694Srillig# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 17122ad694Srillig# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 18122ad694Srillig# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 19122ad694Srillig# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 20122ad694Srillig# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21122ad694Srillig# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22122ad694Srillig# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23122ad694Srillig# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24122ad694Srillig# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25122ad694Srillig# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26122ad694Srillig# POSSIBILITY OF SUCH DAMAGE. 27122ad694Srillig 28122ad694Srillig# Tests for indent that do not follow the input-profile-output scheme that is 29ff059387Srillig# used in t_options. 30122ad694Srillig 31122ad694Srilligindent=$(atf_config_get usr.bin.indent.test_indent /usr/bin/indent) 32656cedf7Srillig 33656cedf7Srilligatf_test_case 'in_place' 34656cedf7Srilligin_place_body() 35656cedf7Srillig{ 36656cedf7Srillig cat <<-\EOF > code.c 37656cedf7Srillig int decl; 38656cedf7Srillig EOF 39656cedf7Srillig cat <<-\EOF > code.c.exp 40656cedf7Srillig int decl; 41656cedf7Srillig EOF 42656cedf7Srillig cp code.c code.c.orig 43656cedf7Srillig 44656cedf7Srillig atf_check \ 45656cedf7Srillig env SIMPLE_BACKUP_SUFFIX=".bak" "$indent" code.c 46656cedf7Srillig atf_check -o 'file:code.c.exp' \ 47656cedf7Srillig cat code.c 48656cedf7Srillig atf_check -o 'file:code.c.orig' \ 49656cedf7Srillig cat code.c.bak 50656cedf7Srillig} 51122ad694Srillig 525852ffadSrilligatf_test_case 'in_place_parse_error' 535852ffadSrilligin_place_parse_error_body() 545852ffadSrillig{ 555852ffadSrillig # On normal parse errors, indent continues until the end of the file. 565852ffadSrillig # This means that even in the case of errors, not much is lost. 575852ffadSrillig 585852ffadSrillig cat <<-\EOF > code.c 595852ffadSrillig int line1; 605852ffadSrillig } 615852ffadSrillig int line3; 625852ffadSrillig EOF 635852ffadSrillig 645852ffadSrillig atf_check -s 'exit:1' -e 'ignore' \ 655852ffadSrillig "$indent" code.c 665852ffadSrillig atf_check -o 'inline:int\t\tline1;\n}\nint\t\tline3;\n' \ 675852ffadSrillig cat code.c 685852ffadSrillig} 695852ffadSrillig 70122ad694Srilligatf_test_case 'verbose_profile' 71122ad694Srilligverbose_profile_body() 72122ad694Srillig{ 73122ad694Srillig cat <<-\EOF > .indent.pro 74122ad694Srillig -/* comment */bacc 75122ad694Srillig -v 76122ad694Srillig -fc1 77122ad694Srillig EOF 78122ad694Srillig cat <<-\EOF > before.c 79122ad694Srillig int decl; 80122ad694Srillig EOF 81122ad694Srillig cat <<-\EOF > after.c.exp 82122ad694Srillig int decl; 83122ad694Srillig EOF 8424133b79Srillig cat <<-\EOF > stderr.exp 85122ad694Srillig profile: -fc1 86122ad694Srillig profile: -bacc 87122ad694Srillig profile: -v 88122ad694Srillig profile: -fc1 89122ad694Srillig EOF 90122ad694Srillig 9197817c96Srillig # The code in args.c function load_profile suggests that options from 9297817c96Srillig # profile files are echoed to stderr during startup. But since the 93122ad694Srillig # command line options are handled after the profile files, a '-v' in 94122ad694Srillig # the command line has no effect. That's why '-bacc' is not listed 9597817c96Srillig # on stderr, but '-fc1' is. The second round of '-bacc', '-v', '-fc1' 9697817c96Srillig # is listed because when running the test via ATF, $HOME equals $PWD. 97122ad694Srillig 98122ad694Srillig atf_check \ 9924133b79Srillig -e 'file:stderr.exp' \ 100122ad694Srillig "$indent" -v before.c after.c 101122ad694Srillig atf_check \ 102122ad694Srillig -o 'file:after.c.exp' \ 103122ad694Srillig cat after.c 104122ad694Srillig} 105122ad694Srillig 1068c1e5e02Srilligatf_test_case 'nested_struct_declarations' 1078c1e5e02Srillignested_struct_declarations_body() 1088c1e5e02Srillig{ 1098c1e5e02Srillig # Trigger the warning about nested struct declarations. 1108c1e5e02Srillig 1118c1e5e02Srillig cat <<-\EOF > code.c 1128c1e5e02Srillig struct s01 { struct s02 { struct s03 { struct s04 { 1138c1e5e02Srillig struct s05 { struct s06 { struct s07 { struct s08 { 1148c1e5e02Srillig struct s09 { struct s10 { struct s11 { struct s12 { 1158c1e5e02Srillig struct s13 { struct s14 { struct s15 { struct s16 { 1168c1e5e02Srillig struct s17 { struct s18 { struct s19 { struct s20 { 1178c1e5e02Srillig struct s21 { struct s22 { struct s23 { struct s24 { 1188c1e5e02Srillig };};};}; 1198c1e5e02Srillig };};};}; 1208c1e5e02Srillig };};};}; 1218c1e5e02Srillig };};};}; 1228c1e5e02Srillig };};};}; 1238c1e5e02Srillig };};};}; 1248c1e5e02Srillig EOF 1258c1e5e02Srillig cat <<-\EOF > expected.out 1268c1e5e02Srillig struct s01 { 1278c1e5e02Srillig struct s02 { 1288c1e5e02Srillig struct s03 { 1298c1e5e02Srillig struct s04 { 1308c1e5e02Srillig struct s05 { 1318c1e5e02Srillig struct s06 { 1328c1e5e02Srillig struct s07 { 1338c1e5e02Srillig struct s08 { 1348c1e5e02Srillig struct s09 { 1358c1e5e02Srillig struct s10 { 1368c1e5e02Srillig struct s11 { 1378c1e5e02Srillig struct s12 { 1388c1e5e02Srillig struct s13 { 1398c1e5e02Srillig struct s14 { 1408c1e5e02Srillig struct s15 { 1418c1e5e02Srillig struct s16 { 1428c1e5e02Srillig struct s17 { 1438c1e5e02Srillig struct s18 { 1448c1e5e02Srillig struct s19 { 1458c1e5e02Srillig struct s20 { 1468c1e5e02Srillig struct s21 { 1478c1e5e02Srillig struct s22 { 1488c1e5e02Srillig struct s23 { 1498c1e5e02Srillig struct s24 { 1508c1e5e02Srillig }; 1518c1e5e02Srillig }; 1528c1e5e02Srillig }; 1538c1e5e02Srillig }; 1548c1e5e02Srillig }; 1558c1e5e02Srillig }; 1568c1e5e02Srillig }; 1578c1e5e02Srillig }; 1588c1e5e02Srillig }; 1598c1e5e02Srillig }; 1608c1e5e02Srillig }; 1618c1e5e02Srillig }; 1628c1e5e02Srillig }; 1638c1e5e02Srillig }; 1648c1e5e02Srillig }; 1658c1e5e02Srillig }; 1668c1e5e02Srillig }; 1678c1e5e02Srillig }; 1688c1e5e02Srillig }; 1698c1e5e02Srillig }; 1708c1e5e02Srillig }; 1718c1e5e02Srillig }; 1728c1e5e02Srillig }; 1738c1e5e02Srillig }; 1748c1e5e02Srillig EOF 1758c1e5e02Srillig cat <<-\EOF > expected.err 176ccfddf6aSrillig warning: Standard Input:5: Reached internal limit of 20 struct levels 177ccfddf6aSrillig warning: Standard Input:6: Reached internal limit of 20 struct levels 178ccfddf6aSrillig warning: Standard Input:6: Reached internal limit of 20 struct levels 179ccfddf6aSrillig warning: Standard Input:6: Reached internal limit of 20 struct levels 180ccfddf6aSrillig warning: Standard Input:6: Reached internal limit of 20 struct levels 1818c1e5e02Srillig EOF 1828c1e5e02Srillig 1838c1e5e02Srillig atf_check -o 'file:expected.out' -e 'file:expected.err' \ 1848c1e5e02Srillig "$indent" -i1 -nut < 'code.c' 1858c1e5e02Srillig} 1868c1e5e02Srillig 18732fe626bSrilligatf_test_case 'option_P_in_profile_file' 18832fe626bSrilligoption_P_in_profile_file_body() 18932fe626bSrillig{ 19032fe626bSrillig # Mentioning another profile via -P has no effect since only a single 19132fe626bSrillig # profile can be specified on the command line, and there is no 19232fe626bSrillig # 'include' option. 19332fe626bSrillig 19432fe626bSrillig # It's syntactically possible to specify a profile file inside another 19532fe626bSrillig # profile file. Such a profile file is ignored since only a single 19632fe626bSrillig # profile file is ever loaded. 19732fe626bSrillig printf '%s\n' '-P/nonexistent' > .indent.pro 19832fe626bSrillig 19932fe626bSrillig echo 'syntax # error' > code.c 20032fe626bSrillig 20151ce682bSrillig atf_check -o 'inline:syntax\n# error\n' \ 20232fe626bSrillig "$indent" < code.c 20332fe626bSrillig} 20432fe626bSrillig 2056134a922Srilligatf_test_case 'option_without_hyphen' 2066134a922Srilligoption_without_hyphen_body() 2076134a922Srillig{ 20897817c96Srillig # Ensure that options in profile files start with '-', just like 20997817c96Srillig # command line options. 2106134a922Srillig 2116134a922Srillig printf ' -i3 xi5 +di0\n' > .indent.pro 2126134a922Srillig 2136134a922Srillig printf '%s\n' 'int var[] = {' '1,' '}' > code.c 2146134a922Srillig 21597817c96Srillig atf_check \ 21697817c96Srillig -s 'exit:1' \ 21797817c96Srillig -e "match:/.indent.pro: option \"xi5\" must start with '-'" \ 2186134a922Srillig "$indent" < code.c 2196134a922Srillig} 2206134a922Srillig 22119aed58aSrilligatf_test_case 'opt' 22219aed58aSrilligopt_body() 22319aed58aSrillig{ 22419aed58aSrillig # Test parsing of command line options from a profile file. 22519aed58aSrillig 22619aed58aSrillig cat <<-\EOF > code.c 22719aed58aSrillig int global_var; 22819aed58aSrillig 22919aed58aSrillig int function(int expr) { 23019aed58aSrillig switch (expr) { case 1: return 1; default: return 0; } 23119aed58aSrillig } 23219aed58aSrillig EOF 23319aed58aSrillig 23419aed58aSrillig cat << \EOF > .indent.pro 23519aed58aSrillig/* The latter of the two options wins. */ 23619aed58aSrillig-di5 23719aed58aSrillig-di12 23819aed58aSrillig 23919aed58aSrillig/* 24019aed58aSrillig * It is possible to embed comments in the middle of an option, but nobody 24119aed58aSrillig * does that. 24219aed58aSrillig */ 24319aed58aSrillig-/* comment */bacc 24419aed58aSrillig-T/* define 24519aed58aSrilliga type */custom_type 24619aed58aSrillig 247499bc8b3Srillig/* For int options, trailing garbage would be an error. */ 24819aed58aSrillig-i3 24919aed58aSrillig 250499bc8b3Srillig/* For float options, trailing garbage would be an error. */ 251499bc8b3Srillig-cli3.5 25219aed58aSrillig 25319aed58aSrillig-b/*/acc /* The comment is '/' '*' '/', making the option '-bacc'. */ 25419aed58aSrilligEOF 25519aed58aSrillig 25619aed58aSrillig sed '/[$]/d' << \EOF > code.exp 25719aed58aSrillig/* $ The variable name is indented by 12 characters due to -di12. */ 25819aed58aSrilligint global_var; 25919aed58aSrillig 26019aed58aSrilligint 26119aed58aSrilligfunction(int expr) 26219aed58aSrillig{ 26319aed58aSrillig switch (expr) { 26419aed58aSrillig/* $ The indentation is 3 + (int)(3.5 * 3), so 3 + 10.5, so 13. */ 26519aed58aSrillig/* $ See parse.c, function parse, 'case switch_expr'. */ 26619aed58aSrillig case 1: 26719aed58aSrillig/* $ The indentation is 3 + (int)3.5 * 3 + 3, so 3 + 9 + 3, so 15. */ 26819aed58aSrillig/* $ See parse.c, function parse, 'case switch_expr'. */ 26919aed58aSrillig return 1; 27019aed58aSrillig default: 27119aed58aSrillig return 0; 27219aed58aSrillig } 27319aed58aSrillig} 27419aed58aSrilligEOF 27519aed58aSrillig 27619aed58aSrillig atf_check -o 'file:code.exp' \ 27719aed58aSrillig "$indent" code.c -st 27819aed58aSrillig} 27919aed58aSrillig 28019aed58aSrilligatf_test_case 'opt_npro' 28119aed58aSrilligopt_npro_body() 28219aed58aSrillig{ 28319aed58aSrillig # Mentioning the option -npro in a .pro file has no effect since at 28419aed58aSrillig # that point, indent has already decided to load the .pro file, and 28519aed58aSrillig # it only decides once. 28619aed58aSrillig 28719aed58aSrillig echo ' -npro -di8' > .indent.pro 28819aed58aSrillig echo 'int var;' > code.c 28919aed58aSrillig printf 'int\tvar;\n' > code.exp 29019aed58aSrillig 29119aed58aSrillig atf_check -o 'file:code.exp' \ 29219aed58aSrillig "$indent" code.c -st 29319aed58aSrillig} 29419aed58aSrillig 29519aed58aSrilligatf_test_case 'opt_U' 29619aed58aSrilligopt_U_body() 29719aed58aSrillig{ 29819aed58aSrillig # From each line of this file, the first word is taken to be a type 29919aed58aSrillig # name. 30019aed58aSrillig # 30119aed58aSrillig # Since neither '/*' nor '' are syntactically valid type names, this 30219aed58aSrillig # means that all kinds of comments are effectively ignored. When a 30319aed58aSrillig # type name is indented by whitespace, it is ignored as well. 30419aed58aSrillig # 30519aed58aSrillig # Since only the first word of each line is relevant, any remaining 30619aed58aSrillig # words can be used for comments. 30719aed58aSrillig cat <<-\EOF > code.types 30819aed58aSrillig /* Comments are effectively ignored since they never match. */ 30919aed58aSrillig # This comment is ignored as well. 31019aed58aSrillig ; So is this comment. 31119aed58aSrillig # The following line is empty and adds a type whose name is empty. 31219aed58aSrillig 31319aed58aSrillig size_t from stddef.h 31419aed58aSrillig off_t for file offsets 31519aed58aSrillig ignored_t is ignored since it is indented 31619aed58aSrillig EOF 31719aed58aSrillig 31819aed58aSrillig cat <<-\EOF > code.c 31919aed58aSrillig int known_1 = (size_t) * arg; 32019aed58aSrillig int known_2 = (off_t) * arg; 32119aed58aSrillig int ignored = (ignored_t) * arg; 32219aed58aSrillig EOF 32319aed58aSrillig cat <<-\EOF > code.exp 32419aed58aSrillig int known_1 = (size_t)*arg; 32519aed58aSrillig int known_2 = (off_t)*arg; 32619aed58aSrillig int ignored = (ignored_t) * arg; 32719aed58aSrillig EOF 32819aed58aSrillig 32919aed58aSrillig atf_check -o 'file:code.exp' \ 33019aed58aSrillig "$indent" -Ucode.types code.c -di0 -st 33119aed58aSrillig} 33219aed58aSrillig 33367f162ccSrilligatf_test_case 'line_no_counting' 33467f162ccSrilligline_no_counting_body() 33567f162ccSrillig{ 33608637ac7Srillig # Before NetBSD indent.c 1.147 from 2021-10-24, indent reported the 33708637ac7Srillig # warning in line 2 instead of the correct line 3. 33808637ac7Srillig 33967f162ccSrillig cat <<-\EOF > code.c 34067f162ccSrillig void line_no_counting(void) 34167f162ccSrillig { 34267f162ccSrillig ()) 34367f162ccSrillig } 34467f162ccSrillig EOF 34567f162ccSrillig 34667f162ccSrillig cat <<-\EOF > code.err 3478c5268b6Srillig warning: code.c:3: Extra ')' 34867f162ccSrillig EOF 34967f162ccSrillig 35067f162ccSrillig atf_check -o 'ignore' -e 'file:code.err' \ 35167f162ccSrillig "$indent" code.c -st 35267f162ccSrillig} 35367f162ccSrillig 354b9453ae0Srilligatf_test_case 'default_backup_extension' 355b9453ae0Srilligdefault_backup_extension_body() 356b9453ae0Srillig{ 357b9453ae0Srillig echo 'int var;' > code.c 358b9453ae0Srillig echo 'int var;' > code.c.orig 359b9453ae0Srillig 360b9453ae0Srillig atf_check \ 361b9453ae0Srillig "$indent" code.c 362b9453ae0Srillig atf_check -o 'file:code.c.orig' \ 363b9453ae0Srillig cat code.c.BAK 364b9453ae0Srillig} 365b9453ae0Srillig 366cfdb0587Srilligatf_test_case 'several_profiles' 367cfdb0587Srilligseveral_profiles_body() 368cfdb0587Srillig{ 369cfdb0587Srillig # If the option '-P' occurs several times, only the last of the 370cfdb0587Srillig # profiles is loaded, the others are ignored. 371cfdb0587Srillig 372cfdb0587Srillig echo ' --invalid-option' > error.pro 373cfdb0587Srillig echo '' > last.pro 374cfdb0587Srillig echo '' > code.c 375cfdb0587Srillig 376cfdb0587Srillig atf_check \ 377cfdb0587Srillig "$indent" -Pnonexistent.pro -Perror.pro -Plast.pro code.c -st 378cfdb0587Srillig} 379cfdb0587Srillig 3806c6e6473Srillig 3816c6e6473Srilligatf_test_case 'command_line_vs_profile' 3826c6e6473Srilligcommand_line_vs_profile_body() 3836c6e6473Srillig{ 3846c6e6473Srillig # Options from the command line override those from a profile file, 3856c6e6473Srillig # no matter if they appear earlier or later than the '-P' in the 3866c6e6473Srillig # command line. 3876c6e6473Srillig 3886c6e6473Srillig echo ' -di24' > custom.pro 3896c6e6473Srillig printf 'int\t\tdecl;\n' > code.c 3906c6e6473Srillig 3916c6e6473Srillig atf_check -o 'inline:int decl;\n' \ 3926c6e6473Srillig "$indent" -di0 -Pcustom.pro code.c -st 3936c6e6473Srillig atf_check -o 'inline:int decl;\n' \ 3946c6e6473Srillig "$indent" -Pcustom.pro -di0 code.c -st 3956c6e6473Srillig atf_check -o 'inline:int decl;\n' \ 3966c6e6473Srillig "$indent" -Pcustom.pro code.c -st -di0 3976c6e6473Srillig} 3986c6e6473Srillig 39937331766Srillig 40037331766Srilligatf_test_case 'opt_v_break_line' 40137331766Srilligopt_v_break_line_body() 40237331766Srillig{ 40337331766Srillig printf '%s\n' 'int *function(void)' '{}' > code.c 40437331766Srillig 40524133b79Srillig atf_check -o 'ignore' \ 40637331766Srillig "$indent" -v code.c -st 40737331766Srillig} 40837331766Srillig 409a28f6dc6Srillig 410a28f6dc6Srilligatf_test_case 'trailing_whitespace_in_preprocessing_line' 411a28f6dc6Srilligtrailing_whitespace_in_preprocessing_line_body() 412a28f6dc6Srillig{ 413a28f6dc6Srillig printf '#if trailing && space \n#endif\n' > code.c 414a28f6dc6Srillig 415a28f6dc6Srillig atf_check -o 'inline:#if trailing && space\n#endif\n' \ 416a28f6dc6Srillig "$indent" code.c -st 417a28f6dc6Srillig} 418a28f6dc6Srillig 419122ad694Srilligatf_init_test_cases() 420122ad694Srillig{ 421656cedf7Srillig atf_add_test_case 'in_place' 422122ad694Srillig atf_add_test_case 'verbose_profile' 4238c1e5e02Srillig atf_add_test_case 'nested_struct_declarations' 42432fe626bSrillig atf_add_test_case 'option_P_in_profile_file' 4256134a922Srillig atf_add_test_case 'option_without_hyphen' 42619aed58aSrillig atf_add_test_case 'opt' 42719aed58aSrillig atf_add_test_case 'opt_npro' 42819aed58aSrillig atf_add_test_case 'opt_U' 42937331766Srillig atf_add_test_case 'opt_v_break_line' 43067f162ccSrillig atf_add_test_case 'line_no_counting' 431b9453ae0Srillig atf_add_test_case 'default_backup_extension' 432cfdb0587Srillig atf_add_test_case 'several_profiles' 4336c6e6473Srillig atf_add_test_case 'command_line_vs_profile' 4345852ffadSrillig atf_add_test_case 'in_place_parse_error' 435a28f6dc6Srillig atf_add_test_case 'trailing_whitespace_in_preprocessing_line' 436122ad694Srillig} 437