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" | "$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" | "$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' | "$exe" "$@" > /dev/null 146 147 checktest_retcode "$d" "$?" "environment var" 148 149 printf 'halt\n' | "$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' | "$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' | "$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' | "$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' | "$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' | "$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' | "$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' | "$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' | "$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' | "$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' | cut -c1-3 > /dev/null 270 err=$? 271 272 if [ "$err" -eq 0 ]; then 273 274 printf 'Running dc Easter script...' 275 276 easter_res="$outputdir/dc_outputs/easter.txt" 277 easter_out="$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 "$@" | cut -c1-12 > "$easter_out" 288 err="$?" 289 290 checktest "$d" "$err" "Easter script" "$easter_res" "$easter_out" 291 292 printf 'pass\n' 293 fi 294 295fi 296 297out1="$outputdir/${d}_outputs/${d}_other.txt" 298out2="$outputdir/${d}_outputs/${d}_other_test.txt" 299 300printf 'Running %s line length tests...' "$d" 301 302printf '%s\n' "$numres" > "$out1" 303 304export "$line_var"=80 305printf '%s\n' "$num" | "$exe" "$@" > "$out2" 306 307checktest "$d" "$?" "line length" "$out1" "$out2" 308 309printf '%s\n' "$num70" > "$out1" 310 311export "$line_var"=2147483647 312printf '%s\n' "$num" | "$exe" "$@" > "$out2" 313 314checktest "$d" "$?" "line length 2" "$out1" "$out2" 315 316printf '%s\n' "$num2" > "$out1" 317 318export "$line_var"=62 319printf '%s\n' "$num" | "$exe" "$@" -L > "$out2" 320 321checktest "$d" "$?" "line length 3" "$out1" "$out2" 322 323printf '0\n' > "$out1" 324printf '%s\n' "$lltest" | "$exe" "$@" -L > "$out2" 325 326checktest "$d" "$?" "line length 3" "$out1" "$out2" 327 328printf 'pass\n' 329 330printf '%s\n' "$numres" > "$out1" 331export "$line_var"=2147483647 332 333printf 'Running %s arg tests...' "$d" 334 335f="$testdir/$d/add.txt" 336exprs=$(cat "$f") 337results=$(cat "$testdir/$d/add_results.txt") 338 339printf '%s\n%s\n%s\n%s\n' "$results" "$results" "$results" "$results" > "$out1" 340 341"$exe" "$@" -e "$exprs" -f "$f" --expression "$exprs" --file "$f" -e "$halt" > "$out2" 342 343checktest "$d" "$?" "arg" "$out1" "$out2" 344 345printf '%s\n' "$halt" | "$exe" "$@" -- "$f" "$f" "$f" "$f" > "$out2" 346 347checktest "$d" "$?" "arg" "$out1" "$out2" 348 349if [ "$d" = "bc" ]; then 350 printf '%s\n' "$halt" | "$exe" "$@" -i > /dev/null 2>&1 351fi 352 353printf '%s\n' "$halt" | "$exe" "$@" -h > /dev/null 354checktest_retcode "$d" "$?" "arg" 355printf '%s\n' "$halt" | "$exe" "$@" -P > /dev/null 356checktest_retcode "$d" "$?" "arg" 357printf '%s\n' "$halt" | "$exe" "$@" -R > /dev/null 358checktest_retcode "$d" "$?" "arg" 359printf '%s\n' "$halt" | "$exe" "$@" -v > /dev/null 360checktest_retcode "$d" "$?" "arg" 361printf '%s\n' "$halt" | "$exe" "$@" -V > /dev/null 362checktest_retcode "$d" "$?" "arg" 363 364out=$(printf '0.1\n-0.1\n1.1\n-1.1\n0.1\n-0.1\n') 365printf '%s\n' "$out" > "$out1" 366 367if [ "$d" = "bc" ]; then 368 data=$(printf '0.1\n-0.1\n1.1\n-1.1\n.1\n-.1\n') 369else 370 data=$(printf '0.1pR\n_0.1pR\n1.1pR\n_1.1pR\n.1pR\n_.1pR\n') 371fi 372 373printf '%s\n' "$data" | "$exe" "$@" -z > "$out2" 374checktest "$d" "$?" "leading zero" "$out1" "$out2" 375 376if [ "$d" = "bc" ] && [ "$extra_math" -ne 0 ]; then 377 378 printf '%s\n' "$halt" | "$exe" "$@" -lz "$testdir/bc/leadingzero.txt" > "$out2" 379 380 checktest "$d" "$?" "leading zero script" "$testdir/bc/leadingzero_results.txt" "$out2" 381 382fi 383 384"$exe" "$@" -f "saotehasotnehasthistohntnsahxstnhalcrgxgrlpyasxtsaosysxsatnhoy.txt" > /dev/null 2> "$out2" 385err="$?" 386 387checkerrtest "$d" "$err" "invalid file argument" "$out2" "$d" 388 389"$exe" "$@" "-$opt" -e "$exprs" > /dev/null 2> "$out2" 390err="$?" 391 392checkerrtest "$d" "$err" "invalid option argument" "$out2" "$d" 393 394"$exe" "$@" "--$lopt" -e "$exprs" > /dev/null 2> "$out2" 395err="$?" 396 397checkerrtest "$d" "$err" "invalid long option argument" "$out2" "$d" 398 399"$exe" "$@" "-u" -e "$exprs" > /dev/null 2> "$out2" 400err="$?" 401 402checkerrtest "$d" "$err" "unrecognized option argument" "$out2" "$d" 403 404"$exe" "$@" "--uniform" -e "$exprs" > /dev/null 2> "$out2" 405err="$?" 406 407checkerrtest "$d" "$err" "unrecognized long option argument" "$out2" "$d" 408 409"$exe" "$@" -f > /dev/null 2> "$out2" 410err="$?" 411 412checkerrtest "$d" "$err" "missing required argument to short option" "$out2" "$d" 413 414"$exe" "$@" --file > /dev/null 2> "$out2" 415err="$?" 416 417checkerrtest "$d" "$err" "missing required argument to long option" "$out2" "$d" 418 419"$exe" "$@" --version=5 > /dev/null 2> "$out2" 420err="$?" 421 422checkerrtest "$d" "$err" "given argument to long option with no argument" "$out2" "$d" 423 424"$exe" "$@" -: > /dev/null 2> "$out2" 425err="$?" 426 427checkerrtest "$d" "$err" "colon short option" "$out2" "$d" 428 429"$exe" "$@" --: > /dev/null 2> "$out2" 430err="$?" 431 432checkerrtest "$d" "$err" "colon long option" "$out2" "$d" 433 434printf 'pass\n' 435 436printf 'Running %s builtin variable arg tests...' "$d" 437 438if [ "$extra_math" -ne 0 ]; then 439 440 out=$(printf '14\n15\n16\n17.25\n') 441 printf '%s\n' "$out" > "$out1" 442 443 if [ "$d" = "bc" ]; then 444 data=$(printf 's=scale;i=ibase;o=obase;t=seed@2;ibase=A;obase=A;s;i;o;t;') 445 else 446 data=$(printf 'J2@OIKAiAopRpRpRpR') 447 fi 448 449 printf '%s\n' "$data" | "$exe" "$@" -S14 -I15 -O16 -E17.25 > "$out2" 450 checktest "$d" "$?" "builtin variable args" "$out1" "$out2" 451 452 printf '%s\n' "$data" | "$exe" "$@" --scale=14 --ibase=15 --obase=16 --seed=17.25 > "$out2" 453 checktest "$d" "$?" "builtin variable long args" "$out1" "$out2" 454 455else 456 457 out=$(printf '14\n15\n16\n') 458 printf '%s\n' "$out" > "$out1" 459 460 if [ "$d" = "bc" ]; then 461 data=$(printf 's=scale;i=ibase;o=obase;ibase=A;obase=A;s;i;o;') 462 else 463 data=$(printf 'OIKAiAopRpRpR') 464 fi 465 466 printf '%s\n' "$data" | "$exe" "$@" -S14 -I15 -O16 > "$out2" 467 checktest "$d" "$?" "builtin variable args" "$out1" "$out2" 468 469 printf '%s\n' "$data" | "$exe" "$@" --scale=14 --ibase=15 --obase=16 > "$out2" 470 checktest "$d" "$?" "builtin variable long args" "$out1" "$out2" 471 472fi 473 474if [ "$d" = "bc" ]; then 475 476 out=$(printf '100\n') 477 printf '%s\n' "$out" > "$out1" 478 479 printf 'scale\n' | "$exe" "$@" -S100 -l > "$out2" 480 checktest "$d" "$?" "builtin variable args with math lib" "$out1" "$out2" 481 482 printf 'scale\n' | "$exe" "$@" --scale=100 --mathlib > "$out2" 483 checktest "$d" "$?" "builtin variable long args with math lib" "$out1" "$out2" 484 485 export BC_ENV_ARGS="-l" 486 487 printf 'scale\n' | "$exe" "$@" -S100 > "$out2" 488 checktest "$d" "$?" "builtin variable args with math lib env arg" "$out1" "$out2" 489 490 printf 'scale\n' | "$exe" "$@" --scale=100 > "$out2" 491 checktest "$d" "$?" "builtin variable long args with math lib env arg" "$out1" "$out2" 492 493 export BC_ENV_ARGS="-S100" 494 495 printf 'scale\n' | "$exe" "$@" -l > "$out2" 496 checktest "$d" "$?" "builtin variable args with math lib arg" "$out1" "$out2" 497 498 export BC_ENV_ARGS="--scale=100" 499 500 printf 'scale\n' | "$exe" "$@" -l > "$out2" 501 checktest "$d" "$?" "builtin variable long args with math lib arg" "$out1" "$out2" 502 503fi 504 505printf 'scale\n' | "$exe" "$@" --scale=18923c.rlg > /dev/null 2> "$out2" 506err="$?" 507 508checkerrtest "$d" "$err" "invalid command-line arg for builtin variable" "$out2" "$d" 509 510if [ "$extra_math" -ne 0 ]; then 511 512 printf 'seed\n' | "$exe" "$@" --seed=18923c.rlg > /dev/null 2> "$out2" 513 err="$?" 514 515 checkerrtest "$d" "$err" "invalid command-line arg for seed" "$out2" "$d" 516 517fi 518 519printf 'pass\n' 520 521printf 'Running %s directory test...' "$d" 522 523"$exe" "$@" "$testdir" > /dev/null 2> "$out2" 524err="$?" 525 526checkerrtest "$d" "$err" "directory" "$out2" "$d" 527 528printf 'pass\n' 529 530printf 'Running %s binary file test...' "$d" 531 532bin="/bin/sh" 533 534"$exe" "$@" "$bin" > /dev/null 2> "$out2" 535err="$?" 536 537checkerrtest "$d" "$err" "binary file" "$out2" "$d" 538 539printf 'pass\n' 540 541printf 'Running %s binary stdin test...' "$d" 542 543cat "$bin" | "$exe" "$@" > /dev/null 2> "$out2" 544err="$?" 545 546checkerrtest "$d" "$err" "binary stdin" "$out2" "$d" 547 548printf 'pass\n' 549 550if [ "$d" = "bc" ]; then 551 552 printf 'Running %s limits tests...' "$d" 553 printf 'limits\n' | "$exe" "$@" /dev/null > "$out2" 2>&1 554 555 checktest_retcode "$d" "$?" "limits" 556 557 if [ ! -s "$out2" ]; then 558 err_exit "$d did not produce output on the limits test" 1 559 fi 560 561 exec printf 'pass\n' 562 563fi 564