t_misc.sh revision 1.26
1#! /bin/sh 2# $NetBSD: t_misc.sh,v 1.26 2023/06/05 07:23:03 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# Tests for indent that do not follow the input-profile-output scheme that is 29# used in t_options. 30 31indent=$(atf_config_get usr.bin.indent.test_indent /usr/bin/indent) 32 33atf_test_case 'in_place' 34in_place_body() 35{ 36 cat <<-\EOF > code.c 37 int decl; 38 EOF 39 cat <<-\EOF > code.c.exp 40 int decl; 41 EOF 42 cp code.c code.c.orig 43 44 atf_check \ 45 env SIMPLE_BACKUP_SUFFIX=".bak" "$indent" code.c 46 atf_check -o 'file:code.c.exp' \ 47 cat code.c 48 atf_check -o 'file:code.c.orig' \ 49 cat code.c.bak 50} 51 52atf_test_case 'in_place_parse_error' 53in_place_parse_error_body() 54{ 55 # On normal parse errors, indent continues until the end of the file. 56 # This means that even in the case of errors, not much is lost. 57 58 cat <<-\EOF > code.c 59 int line1; 60 } 61 int line3; 62 EOF 63 64 atf_check -s 'exit:1' -e 'ignore' \ 65 "$indent" code.c 66 atf_check -o 'inline:int\t\tline1;\n}\nint\t\tline3;\n' \ 67 cat code.c 68} 69 70atf_test_case 'verbose_profile' 71verbose_profile_body() 72{ 73 cat <<-\EOF > .indent.pro 74 -/* comment */bacc 75 -v 76 -fc1 77 EOF 78 cat <<-\EOF > before.c 79 int decl; 80 EOF 81 cat <<-\EOF > after.c.exp 82 int decl; 83 EOF 84 cat <<-\EOF > stdout.exp 85 profile: -fc1 86 profile: -bacc 87 profile: -v 88 profile: -fc1 89 EOF 90 91 # The code in args.c function set_profile suggests that options from 92 # profile files are echoed to stdout during startup. But since the 93 # command line options are handled after the profile files, a '-v' in 94 # the command line has no effect. That's why '-bacc' is not listed 95 # in stdout, but '-fc1' is. The second round of '-bacc', '-v', '-fc1' 96 # is listed because when running ATF, $HOME equals $PWD. 97 98 atf_check \ 99 -o 'file:stdout.exp' \ 100 "$indent" -v before.c after.c 101 atf_check \ 102 -o 'file:after.c.exp' \ 103 cat after.c 104} 105 106atf_test_case 'nested_struct_declarations' 107nested_struct_declarations_body() 108{ 109 # Trigger the warning about nested struct declarations. 110 111 cat <<-\EOF > code.c 112 struct s01 { struct s02 { struct s03 { struct s04 { 113 struct s05 { struct s06 { struct s07 { struct s08 { 114 struct s09 { struct s10 { struct s11 { struct s12 { 115 struct s13 { struct s14 { struct s15 { struct s16 { 116 struct s17 { struct s18 { struct s19 { struct s20 { 117 struct s21 { struct s22 { struct s23 { struct s24 { 118 };};};}; 119 };};};}; 120 };};};}; 121 };};};}; 122 };};};}; 123 };};};}; 124 EOF 125 cat <<-\EOF > expected.out 126 struct s01 { 127 struct s02 { 128 struct s03 { 129 struct s04 { 130 struct s05 { 131 struct s06 { 132 struct s07 { 133 struct s08 { 134 struct s09 { 135 struct s10 { 136 struct s11 { 137 struct s12 { 138 struct s13 { 139 struct s14 { 140 struct s15 { 141 struct s16 { 142 struct s17 { 143 struct s18 { 144 struct s19 { 145 struct s20 { 146 struct s21 { 147 struct s22 { 148 struct s23 { 149 struct s24 { 150 }; 151 }; 152 }; 153 }; 154 }; 155 }; 156 }; 157 }; 158 }; 159 }; 160 }; 161 }; 162 }; 163 }; 164 }; 165 }; 166 }; 167 }; 168 }; 169 }; 170 }; 171 }; 172 }; 173 }; 174 EOF 175 cat <<-\EOF > expected.err 176 warning: Standard Input:5: Reached internal limit of 20 struct levels 177 warning: Standard Input:6: Reached internal limit of 20 struct levels 178 warning: Standard Input:6: Reached internal limit of 20 struct levels 179 warning: Standard Input:6: Reached internal limit of 20 struct levels 180 warning: Standard Input:6: Reached internal limit of 20 struct levels 181 EOF 182 183 atf_check -o 'file:expected.out' -e 'file:expected.err' \ 184 "$indent" -i1 -nut < 'code.c' 185} 186 187atf_test_case 'option_P_in_profile_file' 188option_P_in_profile_file_body() 189{ 190 # Mentioning another profile via -P has no effect since only a single 191 # profile can be specified on the command line, and there is no 192 # 'include' option. 193 194 # It's syntactically possible to specify a profile file inside another 195 # profile file. Such a profile file is ignored since only a single 196 # profile file is ever loaded. 197 printf '%s\n' '-P/nonexistent' > .indent.pro 198 199 echo 'syntax # error' > code.c 200 201 atf_check -o 'inline:syntax\n# error\n' \ 202 "$indent" < code.c 203} 204 205atf_test_case 'option_without_hyphen' 206option_without_hyphen_body() 207{ 208 # TODO: Options in profile files should be required to start with 209 # '-', just like in the command line arguments. 210 211 printf ' -i3 xi5 +di0\n' > .indent.pro 212 213 printf '%s\n' 'int var[] = {' '1,' '}' > code.c 214 printf '%s\n' 'int var[] = {' ' 1,' '}' > code.exp 215 216 atf_check -o 'file:code.exp' \ 217 "$indent" < code.c 218} 219 220atf_test_case 'opt' 221opt_body() 222{ 223 # Test parsing of command line options from a profile file. 224 225 cat <<-\EOF > code.c 226 int global_var; 227 228 int function(int expr) { 229 switch (expr) { case 1: return 1; default: return 0; } 230 } 231 EOF 232 233 cat << \EOF > .indent.pro 234/* The latter of the two options wins. */ 235-di5 236-di12 237 238/* 239 * It is possible to embed comments in the middle of an option, but nobody 240 * does that. 241 */ 242-/* comment */bacc 243-T/* define 244a type */custom_type 245 246/* For int options, trailing garbage would be an error. */ 247-i3 248 249/* For float options, trailing garbage would be an error. */ 250-cli3.5 251 252-b/*/acc /* The comment is '/' '*' '/', making the option '-bacc'. */ 253EOF 254 255 sed '/[$]/d' << \EOF > code.exp 256/* $ The variable name is indented by 12 characters due to -di12. */ 257int global_var; 258 259int 260function(int expr) 261{ 262 switch (expr) { 263/* $ The indentation is 3 + (int)(3.5 * 3), so 3 + 10.5, so 13. */ 264/* $ See parse.c, function parse, 'case switch_expr'. */ 265 case 1: 266/* $ The indentation is 3 + (int)3.5 * 3 + 3, so 3 + 9 + 3, so 15. */ 267/* $ See parse.c, function parse, 'case switch_expr'. */ 268 return 1; 269 default: 270 return 0; 271 } 272} 273EOF 274 275 atf_check -o 'file:code.exp' \ 276 "$indent" code.c -st 277} 278 279atf_test_case 'opt_npro' 280opt_npro_body() 281{ 282 # Mentioning the option -npro in a .pro file has no effect since at 283 # that point, indent has already decided to load the .pro file, and 284 # it only decides once. 285 286 echo ' -npro -di8' > .indent.pro 287 echo 'int var;' > code.c 288 printf 'int\tvar;\n' > code.exp 289 290 atf_check -o 'file:code.exp' \ 291 "$indent" code.c -st 292} 293 294atf_test_case 'opt_U' 295opt_U_body() 296{ 297 # From each line of this file, the first word is taken to be a type 298 # name. 299 # 300 # Since neither '/*' nor '' are syntactically valid type names, this 301 # means that all kinds of comments are effectively ignored. When a 302 # type name is indented by whitespace, it is ignored as well. 303 # 304 # Since only the first word of each line is relevant, any remaining 305 # words can be used for comments. 306 cat <<-\EOF > code.types 307 /* Comments are effectively ignored since they never match. */ 308 # This comment is ignored as well. 309 ; So is this comment. 310 # The following line is empty and adds a type whose name is empty. 311 312 size_t from stddef.h 313 off_t for file offsets 314 ignored_t is ignored since it is indented 315 EOF 316 317 cat <<-\EOF > code.c 318 int known_1 = (size_t) * arg; 319 int known_2 = (off_t) * arg; 320 int ignored = (ignored_t) * arg; 321 EOF 322 cat <<-\EOF > code.exp 323 int known_1 = (size_t)*arg; 324 int known_2 = (off_t)*arg; 325 int ignored = (ignored_t) * arg; 326 EOF 327 328 atf_check -o 'file:code.exp' \ 329 "$indent" -Ucode.types code.c -di0 -st 330} 331 332atf_test_case 'line_no_counting' 333line_no_counting_body() 334{ 335 # Before NetBSD indent.c 1.147 from 2021-10-24, indent reported the 336 # warning in line 2 instead of the correct line 3. 337 338 cat <<-\EOF > code.c 339 void line_no_counting(void) 340 { 341 ()) 342 } 343 EOF 344 345 cat <<-\EOF > code.err 346 warning: code.c:3: Extra ')' 347 EOF 348 349 atf_check -o 'ignore' -e 'file:code.err' \ 350 "$indent" code.c -st 351} 352 353atf_test_case 'default_backup_extension' 354default_backup_extension_body() 355{ 356 echo 'int var;' > code.c 357 echo 'int var;' > code.c.orig 358 359 atf_check \ 360 "$indent" code.c 361 atf_check -o 'file:code.c.orig' \ 362 cat code.c.BAK 363} 364 365atf_test_case 'several_profiles' 366several_profiles_body() 367{ 368 # If the option '-P' occurs several times, only the last of the 369 # profiles is loaded, the others are ignored. 370 371 echo ' --invalid-option' > error.pro 372 echo '' > last.pro 373 echo '' > code.c 374 375 atf_check \ 376 "$indent" -Pnonexistent.pro -Perror.pro -Plast.pro code.c -st 377} 378 379 380atf_test_case 'command_line_vs_profile' 381command_line_vs_profile_body() 382{ 383 # Options from the command line override those from a profile file, 384 # no matter if they appear earlier or later than the '-P' in the 385 # command line. 386 387 echo ' -di24' > custom.pro 388 printf 'int\t\tdecl;\n' > code.c 389 390 atf_check -o 'inline:int decl;\n' \ 391 "$indent" -di0 -Pcustom.pro code.c -st 392 atf_check -o 'inline:int decl;\n' \ 393 "$indent" -Pcustom.pro -di0 code.c -st 394 atf_check -o 'inline:int decl;\n' \ 395 "$indent" -Pcustom.pro code.c -st -di0 396} 397 398 399atf_test_case 'opt_v_break_line' 400opt_v_break_line_body() 401{ 402 printf '%s\n' 'int *function(void)' '{}' > code.c 403 404 atf_check -o 'ignore' -e 'inline:warning: code.c:2: Line broken\n' \ 405 "$indent" -v code.c -st 406} 407 408 409atf_test_case 'trailing_whitespace_in_preprocessing_line' 410trailing_whitespace_in_preprocessing_line_body() 411{ 412 printf '#if trailing && space \n#endif\n' > code.c 413 414 atf_check -o 'inline:#if trailing && space\n#endif\n' \ 415 "$indent" code.c -st 416} 417 418atf_init_test_cases() 419{ 420 atf_add_test_case 'in_place' 421 atf_add_test_case 'verbose_profile' 422 atf_add_test_case 'nested_struct_declarations' 423 atf_add_test_case 'option_P_in_profile_file' 424 atf_add_test_case 'option_without_hyphen' 425 atf_add_test_case 'opt' 426 atf_add_test_case 'opt_npro' 427 atf_add_test_case 'opt_U' 428 atf_add_test_case 'opt_v_break_line' 429 atf_add_test_case 'line_no_counting' 430 atf_add_test_case 'default_backup_extension' 431 atf_add_test_case 'several_profiles' 432 atf_add_test_case 'command_line_vs_profile' 433 atf_add_test_case 'in_place_parse_error' 434 atf_add_test_case 'trailing_whitespace_in_preprocessing_line' 435} 436