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