1#! /bin/sh 2# 3# SPDX-License-Identifier: BSD-2-Clause 4# 5# Copyright (c) 2018-2023 Gavin D. Howard and contributors. 6# 7# Redistribution and use in source and binary forms, with or without 8# modification, are permitted provided that the following conditions are met: 9# 10# * Redistributions of source code must retain the above copyright notice, this 11# list of conditions and the following disclaimer. 12# 13# * Redistributions in binary form must reproduce the above copyright notice, 14# this list of conditions and the following disclaimer in the documentation 15# and/or other materials provided with the distribution. 16# 17# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 18# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 21# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 25# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 26# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 27# POSSIBILITY OF SUCH DAMAGE. 28# 29 30set -e 31 32script="$0" 33testdir=$(dirname "$script") 34 35. "$testdir/../scripts/functions.sh" 36 37outputdir=${BC_TEST_OUTPUT_DIR:-$testdir} 38 39# Just print the usage and exit with an error. This can receive a message to 40# print. 41# @param 1 A message to print. 42usage() { 43 if [ $# -eq 1 ]; then 44 printf '%s\n\n' "$1" 45 fi 46 printf 'usage: %s dir extra_math [exec args...]\n' "$script" 47 exit 1 48} 49 50# Command-line processing. 51if [ "$#" -ge 2 ]; then 52 53 d="$1" 54 shift 55 check_d_arg "$d" 56 57 extra_math="$1" 58 shift 59 check_bool_arg "$extra_math" 60 61else 62 usage "Not enough arguments; need 2" 63fi 64 65if [ "$#" -lt 1 ]; then 66 exe="$testdir/../bin/$d" 67 check_exec_arg "$exe" 68else 69 exe="$1" 70 shift 71 check_exec_arg "$exe" 72fi 73 74if [ "$d" = "bc" ]; then 75 halt="quit" 76else 77 halt="q" 78fi 79 80mkdir -p "$outputdir" 81 82# For tests later. 83num=100000000000000000000000000000000000000000000000000000000000000000000000000000 84num2="$num" 85numres="$num" 86num70="10000000000000000000000000000000000000000000000000000000000000000000\\ 870000000000" 88 89# Set stuff for the correct calculator. 90if [ "$d" = "bc" ]; then 91 halt="halt" 92 opt="x" 93 lopt="extended-register" 94 line_var="BC_LINE_LENGTH" 95 lltest="line_length()" 96else 97 halt="q" 98 opt="l" 99 lopt="mathlib" 100 line_var="DC_LINE_LENGTH" 101 num="$num pR" 102 lltest="glpR" 103fi 104 105# I use these, so unset them to make the tests work. 106unset BC_ENV_ARGS 107unset BC_LINE_LENGTH 108unset DC_ENV_ARGS 109unset DC_LINE_LENGTH 110 111set +e 112 113printf '\nRunning %s quit test...' "$d" 114 115printf '%s\n' "$halt" 2> /dev/null | "$exe" "$@" > /dev/null 2>&1 116 117checktest_retcode "$d" "$?" "quit" 118 119# bc has two halt or quit commands, so test the second as well. 120if [ "$d" = bc ]; then 121 122 printf '%s\n' "quit" 2> /dev/null | "$exe" "$@" > /dev/null 2>&1 123 124 checktest_retcode "$d" "$?" quit 125 126 two=$("$exe" "$@" -e 1+1 -e quit) 127 128 checktest_retcode "$d" "$?" quit 129 130 if [ "$two" != "2" ]; then 131 err_exit "$d failed test quit" 1 132 fi 133fi 134 135printf 'pass\n' 136 137base=$(basename "$exe") 138 139printf 'Running %s environment var tests...' "$d" 140 141if [ "$d" = "bc" ]; then 142 143 export BC_ENV_ARGS=" '-l' '' -q" 144 145 printf 's(.02893)\n' 2> /dev/null | "$exe" "$@" > /dev/null 146 147 checktest_retcode "$d" "$?" "environment var" 148 149 printf 'halt\n' 2> /dev/null | "$exe" "$@" -e 4 > /dev/null 150 151 err="$?" 152 checktest_retcode "$d" "$?" "environment var" 153 154 printf 'pass\n' 155 156 printf 'Running keyword redefinition test...' 157 158 unset BC_ENV_ARGS 159 160 redefine_res="$outputdir/bc_outputs/redefine.txt" 161 redefine_out="$outputdir/bc_outputs/redefine_results.txt" 162 163 outdir=$(dirname "$redefine_out") 164 165 if [ ! -d "$outdir" ]; then 166 mkdir -p "$outdir" 167 fi 168 169 printf '5\n0\n' > "$redefine_res" 170 171 printf 'halt\n' 2> /dev/null | "$exe" "$@" --redefine=print -e 'define print(x) { x }' -e 'print(5)' > "$redefine_out" 172 err="$?" 173 174 checktest "$d" "$err" "keyword redefinition" "$redefine_res" "$redefine_out" 175 176 printf 'halt\n' 2> /dev/null | "$exe" "$@" -r "abs" -r "else" -e 'abs = 5;else = 0' -e 'abs;else' > "$redefine_out" 177 err="$?" 178 179 checktest "$d" "$err" "keyword redefinition" "$redefine_res" "$redefine_out" 180 181 if [ "$extra_math" -ne 0 ]; then 182 183 printf 'halt\n' 2> /dev/null | "$exe" "$@" -lr abs -e "perm(5, 1)" -e "0" > "$redefine_out" 184 err="$?" 185 186 checktest "$d" "$err" "keyword not redefined in builtin library" "$redefine_res" "$redefine_out" 187 188 fi 189 190 "$exe" "$@" -r "break" -e 'define break(x) { x }' 2> "$redefine_out" 191 err="$?" 192 193 checkerrtest "$d" "$err" "keyword redefinition error" "$redefine_out" "$d" 194 195 "$exe" "$@" -e 'define read(x) { x }' 2> "$redefine_out" 196 err="$?" 197 198 checkerrtest "$d" "$err" "Keyword redefinition error without BC_REDEFINE_KEYWORDS" "$redefine_out" "$d" 199 200 printf 'pass\n' 201 printf 'Running multiline comment expression file test...' 202 203 multiline_expr_res="" 204 multiline_expr_out="$outputdir/bc_outputs/multiline_expr_results.txt" 205 206 # tests/bc/misc1.txt happens to have a multiline comment in it. 207 printf 'halt\n' 2> /dev/null | "$exe" "$@" -f "$testdir/bc/misc1.txt" > "$multiline_expr_out" 208 err="$?" 209 210 checktest "$d" "$err" "multiline comment in expression file" "$testdir/bc/misc1_results.txt" \ 211 "$multiline_expr_out" 212 213 printf 'pass\n' 214 printf 'Running multiline comment expression file error test...' 215 216 printf 'halt\n' 2> /dev/null | "$exe" "$@" -f "$testdir/bc/errors/05.txt" 2> "$multiline_expr_out" 217 err="$?" 218 219 checkerrtest "$d" "$err" "multiline comment in expression file error" \ 220 "$multiline_expr_out" "$d" 221 222 printf 'pass\n' 223 printf 'Running multiline string expression file test...' 224 225 # tests/bc/strings.txt happens to have a multiline string in it. 226 printf 'halt\n' 2> /dev/null | "$exe" "$@" -f "$testdir/bc/strings.txt" > "$multiline_expr_out" 227 err="$?" 228 229 checktest "$d" "$err" "multiline string in expression file" "$testdir/bc/strings_results.txt" \ 230 "$multiline_expr_out" 231 232 printf 'pass\n' 233 printf 'Running multiline string expression file error test...' 234 235 printf 'halt\n' 2> /dev/null | "$exe" "$@" -f "$testdir/bc/errors/16.txt" 2> "$multiline_expr_out" 236 err="$?" 237 238 checkerrtest "$d" "$err" "multiline string in expression file with backslash error" \ 239 "$multiline_expr_out" "$d" 240 241 printf 'halt\n' 2> /dev/null | "$exe" "$@" -f "$testdir/bc/errors/04.txt" 2> "$multiline_expr_out" 242 err="$?" 243 244 checkerrtest "$d" "$err" "multiline string in expression file error" \ 245 "$multiline_expr_out" "$d" 246 247 printf 'pass\n' 248 249else 250 251 export DC_ENV_ARGS="'-x'" 252 export DC_EXPR_EXIT="1" 253 254 printf '4s stuff\n' 2> /dev/null | "$exe" "$@" > /dev/null 255 256 checktest_retcode "$d" "$?" "environment var" 257 258 "$exe" "$@" -e 4pR > /dev/null 259 260 checktest_retcode "$d" "$?" "environment var" 261 262 printf 'pass\n' 263 264 set +e 265 266 # dc has an extra test for a case that someone found running this easter.dc 267 # script. It went into an infinite loop, so we want to check that we did not 268 # regress. 269 printf 'three\n' 2> /dev/null | cut -c1-3 > /dev/null 270 err=$? 271 272 if [ "$err" -eq 0 ]; then 273 274 printf 'Running dc Easter script...' 275 276 easter_out="$outputdir/dc_outputs/easter.txt" 277 easter_res="$outputdir/dc_outputs/easter_results.txt" 278 279 outdir=$(dirname "$easter_out") 280 281 if [ ! -d "$outdir" ]; then 282 mkdir -p "$outdir" 283 fi 284 285 printf '4 April 2021\n' > "$easter_res" 286 287 "$testdir/dc/scripts/easter.sh" "$exe" 2021 "$@" 2> /dev/null | cut -c1-12 > "$easter_out" 288 err="$?" 289 290 checktest "$d" "$err" "Easter script" "$easter_out" "$easter_res" 291 292 printf 'pass\n' 293 fi 294 295 unset DC_ENV_ARGS 296 unset DC_EXPR_EXIT 297 298 printf 'Running dc extended register command tests...' 299 300 ext_reg_out="$outputdir/dc_outputs/ext_reg.txt" 301 ext_reg_res="$outputdir/dc_outputs/ext_reg_results.txt" 302 303 outdir=$(dirname "$ext_reg_out") 304 305 if [ ! -d "$outdir" ]; then 306 mkdir -p "$outdir" 307 fi 308 309 printf '0\n' > "$ext_reg_res" 310 311 "$exe" "$@" -e "gxpR" 2> /dev/null > "$ext_reg_out" 312 err="$?" 313 314 checktest "$d" "$err" "Extended register command" "$ext_reg_out" "$ext_reg_res" 315 316 printf '1\n' > "$ext_reg_res" 317 318 "$exe" "$@" -x -e "gxpR" 2> /dev/null > "$ext_reg_out" 319 err="$?" 320 321 checktest "$d" "$err" "Extended register command" "$ext_reg_out" "$ext_reg_res" 322 323 printf 'pass\n' 324 325fi 326 327out1="$outputdir/${d}_outputs/${d}_other.txt" 328out2="$outputdir/${d}_outputs/${d}_other_test.txt" 329 330printf 'Running %s line length tests...' "$d" 331 332printf '%s\n' "$numres" > "$out1" 333 334export "$line_var"=80 335printf '%s\n' "$num" 2> /dev/null | "$exe" "$@" > "$out2" 336 337checktest "$d" "$?" "line length" "$out1" "$out2" 338 339printf '%s\n' "$num70" > "$out1" 340 341export "$line_var"=2147483647 342printf '%s\n' "$num" 2> /dev/null | "$exe" "$@" > "$out2" 343 344checktest "$d" "$?" "line length 2" "$out1" "$out2" 345 346printf '%s\n' "$num2" > "$out1" 347 348export "$line_var"=62 349printf '%s\n' "$num" 2> /dev/null | "$exe" "$@" -L > "$out2" 350 351checktest "$d" "$?" "line length 3" "$out1" "$out2" 352 353printf '0\n' > "$out1" 354printf '%s\n' "$lltest" 2> /dev/null | "$exe" "$@" -L > "$out2" 355 356checktest "$d" "$?" "line length 3" "$out1" "$out2" 357 358printf 'pass\n' 359 360printf '%s\n' "$numres" > "$out1" 361export "$line_var"=2147483647 362 363printf 'Running %s arg tests...' "$d" 364 365f="$testdir/$d/add.txt" 366exprs=$(cat "$f") 367results=$(cat "$testdir/$d/add_results.txt") 368 369printf '%s\n%s\n%s\n%s\n' "$results" "$results" "$results" "$results" > "$out1" 370 371"$exe" "$@" -e "$exprs" -f "$f" --expression "$exprs" --file "$f" -e "$halt" > "$out2" 372 373checktest "$d" "$?" "arg" "$out1" "$out2" 374 375printf '%s\n' "$halt" 2> /dev/null | "$exe" "$@" -- "$f" "$f" "$f" "$f" > "$out2" 376 377checktest "$d" "$?" "arg" "$out1" "$out2" 378 379if [ "$d" = "bc" ]; then 380 printf '%s\n' "$halt" 2> /dev/null | "$exe" "$@" -i > /dev/null 2>&1 381fi 382 383printf '%s\n' "$halt" 2> /dev/null | "$exe" "$@" -h > /dev/null 384checktest_retcode "$d" "$?" "arg" 385printf '%s\n' "$halt" 2> /dev/null | "$exe" "$@" -P > /dev/null 386checktest_retcode "$d" "$?" "arg" 387printf '%s\n' "$halt" 2> /dev/null | "$exe" "$@" -R > /dev/null 388checktest_retcode "$d" "$?" "arg" 389printf '%s\n' "$halt" 2> /dev/null | "$exe" "$@" -v > /dev/null 390checktest_retcode "$d" "$?" "arg" 391printf '%s\n' "$halt" 2> /dev/null | "$exe" "$@" -V > /dev/null 392checktest_retcode "$d" "$?" "arg" 393 394out=$(printf '0.1\n-0.1\n1.1\n-1.1\n0.1\n-0.1\n') 395printf '%s\n' "$out" > "$out1" 396 397if [ "$d" = "bc" ]; then 398 data=$(printf '0.1\n-0.1\n1.1\n-1.1\n.1\n-.1\n') 399else 400 data=$(printf '0.1pR\n_0.1pR\n1.1pR\n_1.1pR\n.1pR\n_.1pR\n') 401fi 402 403printf '%s\n' "$data" 2> /dev/null | "$exe" "$@" -z > "$out2" 404checktest "$d" "$?" "leading zero" "$out1" "$out2" 405 406if [ "$d" = "bc" ] && [ "$extra_math" -ne 0 ]; then 407 408 printf '%s\n' "$halt" 2> /dev/null | "$exe" "$@" -lz "$testdir/bc/leadingzero.txt" > "$out2" 409 410 checktest "$d" "$?" "leading zero script" "$testdir/bc/leadingzero_results.txt" "$out2" 411 412fi 413 414"$exe" "$@" -f "saotehasotnehasthistohntnsahxstnhalcrgxgrlpyasxtsaosysxsatnhoy.txt" > /dev/null 2> "$out2" 415err="$?" 416 417checkerrtest "$d" "$err" "invalid file argument" "$out2" "$d" 418 419"$exe" "$@" "-$opt" -e "$exprs" > /dev/null 2> "$out2" 420err="$?" 421 422checkerrtest "$d" "$err" "invalid option argument" "$out2" "$d" 423 424"$exe" "$@" "--$lopt" -e "$exprs" > /dev/null 2> "$out2" 425err="$?" 426 427checkerrtest "$d" "$err" "invalid long option argument" "$out2" "$d" 428 429"$exe" "$@" "-u" -e "$exprs" > /dev/null 2> "$out2" 430err="$?" 431 432checkerrtest "$d" "$err" "unrecognized option argument" "$out2" "$d" 433 434"$exe" "$@" "--uniform" -e "$exprs" > /dev/null 2> "$out2" 435err="$?" 436 437checkerrtest "$d" "$err" "unrecognized long option argument" "$out2" "$d" 438 439"$exe" "$@" -f > /dev/null 2> "$out2" 440err="$?" 441 442checkerrtest "$d" "$err" "missing required argument to short option" "$out2" "$d" 443 444"$exe" "$@" --file > /dev/null 2> "$out2" 445err="$?" 446 447checkerrtest "$d" "$err" "missing required argument to long option" "$out2" "$d" 448 449"$exe" "$@" --version=5 > /dev/null 2> "$out2" 450err="$?" 451 452checkerrtest "$d" "$err" "given argument to long option with no argument" "$out2" "$d" 453 454"$exe" "$@" -: > /dev/null 2> "$out2" 455err="$?" 456 457checkerrtest "$d" "$err" "colon short option" "$out2" "$d" 458 459"$exe" "$@" --: > /dev/null 2> "$out2" 460err="$?" 461 462checkerrtest "$d" "$err" "colon long option" "$out2" "$d" 463 464printf 'pass\n' 465 466printf 'Running %s builtin variable arg tests...' "$d" 467 468if [ "$extra_math" -ne 0 ]; then 469 470 out=$(printf '14\n15\n16\n17.25\n') 471 printf '%s\n' "$out" > "$out1" 472 473 if [ "$d" = "bc" ]; then 474 data=$(printf 's=scale;i=ibase;o=obase;t=seed@2;ibase=A;obase=A;s;i;o;t;') 475 else 476 data=$(printf 'J2@OIKAiAopRpRpRpR') 477 fi 478 479 printf '%s\n' "$data" 2> /dev/null | "$exe" "$@" -S14 -I15 -O16 -E17.25 > "$out2" 480 checktest "$d" "$?" "builtin variable args" "$out1" "$out2" 481 482 printf '%s\n' "$data" 2> /dev/null | "$exe" "$@" --scale=14 --ibase=15 --obase=16 --seed=17.25 > "$out2" 483 checktest "$d" "$?" "builtin variable long args" "$out1" "$out2" 484 485else 486 487 out=$(printf '14\n15\n16\n') 488 printf '%s\n' "$out" > "$out1" 489 490 if [ "$d" = "bc" ]; then 491 data=$(printf 's=scale;i=ibase;o=obase;ibase=A;obase=A;s;i;o;') 492 else 493 data=$(printf 'OIKAiAopRpRpR') 494 fi 495 496 printf '%s\n' "$data" 2> /dev/null | "$exe" "$@" -S14 -I15 -O16 > "$out2" 497 checktest "$d" "$?" "builtin variable args" "$out1" "$out2" 498 499 printf '%s\n' "$data" 2> /dev/null | "$exe" "$@" --scale=14 --ibase=15 --obase=16 > "$out2" 500 checktest "$d" "$?" "builtin variable long args" "$out1" "$out2" 501 502fi 503 504if [ "$d" = "bc" ]; then 505 506 out=$(printf '100\n') 507 printf '%s\n' "$out" > "$out1" 508 509 printf 'scale\n' 2> /dev/null | "$exe" "$@" -S100 -l > "$out2" 510 checktest "$d" "$?" "builtin variable args with math lib" "$out1" "$out2" 511 512 printf 'scale\n' 2> /dev/null | "$exe" "$@" --scale=100 --mathlib > "$out2" 513 checktest "$d" "$?" "builtin variable long args with math lib" "$out1" "$out2" 514 515 export BC_ENV_ARGS="-l" 516 517 printf 'scale\n' 2> /dev/null | "$exe" "$@" -S100 > "$out2" 518 checktest "$d" "$?" "builtin variable args with math lib env arg" "$out1" "$out2" 519 520 printf 'scale\n' 2> /dev/null | "$exe" "$@" --scale=100 > "$out2" 521 checktest "$d" "$?" "builtin variable long args with math lib env arg" "$out1" "$out2" 522 523 export BC_ENV_ARGS="-S100" 524 525 printf 'scale\n' 2> /dev/null | "$exe" "$@" -l > "$out2" 526 checktest "$d" "$?" "builtin variable args with math lib arg" "$out1" "$out2" 527 528 export BC_ENV_ARGS="--scale=100" 529 530 printf 'scale\n' 2> /dev/null | "$exe" "$@" -l > "$out2" 531 checktest "$d" "$?" "builtin variable long args with math lib arg" "$out1" "$out2" 532 533fi 534 535printf 'scale\n' 2> /dev/null | "$exe" "$@" --scale=18923c.rlg > /dev/null 2> "$out2" 536err="$?" 537 538checkerrtest "$d" "$err" "invalid command-line arg for builtin variable" "$out2" "$d" 539 540if [ "$extra_math" -ne 0 ]; then 541 542 printf 'seed\n' 2> /dev/null | "$exe" "$@" --seed=18923c.rlg > /dev/null 2> "$out2" 543 err="$?" 544 545 checkerrtest "$d" "$err" "invalid command-line arg for seed" "$out2" "$d" 546 547fi 548 549printf 'pass\n' 550 551printf 'Running %s directory test...' "$d" 552 553"$exe" "$@" "$testdir" > /dev/null 2> "$out2" 554err="$?" 555 556checkerrtest "$d" "$err" "directory" "$out2" "$d" 557 558printf 'pass\n' 559 560printf 'Running %s binary file test...' "$d" 561 562bin="/bin/sh" 563 564"$exe" "$@" "$bin" > /dev/null 2> "$out2" 565err="$?" 566 567checkerrtest "$d" "$err" "binary file" "$out2" "$d" 568 569printf 'pass\n' 570 571printf 'Running %s binary stdin test...' "$d" 572 573cat "$bin" 2> /dev/null | "$exe" "$@" > /dev/null 2> "$out2" 574err="$?" 575 576checkerrtest "$d" "$err" "binary stdin" "$out2" "$d" 577 578printf 'pass\n' 579 580if [ "$d" = "bc" ]; then 581 582 printf 'Running %s limits tests...' "$d" 583 printf 'limits\n' 2> /dev/null | "$exe" "$@" /dev/null > "$out2" 2>&1 584 585 checktest_retcode "$d" "$?" "limits" 586 587 if [ ! -s "$out2" ]; then 588 err_exit "$d did not produce output on the limits test" 1 589 fi 590 591 exec printf 'pass\n' 592 593fi 594