diff options
| author | Mehmet Samet Duman <yongdohyun@projecttick.org> | 2026-04-02 18:25:26 +0300 |
|---|---|---|
| committer | Mehmet Samet Duman <yongdohyun@projecttick.org> | 2026-04-02 18:25:26 +0300 |
| commit | 5c7294b9667f0a38005272add8c78483b8658092 (patch) | |
| tree | 5916ac24ae1c67c72b96a6e6fd745dc25ff1187d /corebinutils/expr/tests | |
| parent | f0f174696b38adfd6063bb74e5b48d2b864cb650 (diff) | |
| parent | 23bf7a79f51567e56bfb4fc657e3dc66c36b41de (diff) | |
| download | Project-Tick-5c7294b9667f0a38005272add8c78483b8658092.tar.gz Project-Tick-5c7294b9667f0a38005272add8c78483b8658092.zip | |
Add 'corebinutils/expr/' from commit '23bf7a79f51567e56bfb4fc657e3dc66c36b41de'
git-subtree-dir: corebinutils/expr
git-subtree-mainline: f0f174696b38adfd6063bb74e5b48d2b864cb650
git-subtree-split: 23bf7a79f51567e56bfb4fc657e3dc66c36b41de
Diffstat (limited to 'corebinutils/expr/tests')
| -rw-r--r-- | corebinutils/expr/tests/test.sh | 206 |
1 files changed, 206 insertions, 0 deletions
diff --git a/corebinutils/expr/tests/test.sh b/corebinutils/expr/tests/test.sh new file mode 100644 index 0000000000..23728d5e3b --- /dev/null +++ b/corebinutils/expr/tests/test.sh @@ -0,0 +1,206 @@ +#!/bin/sh +set -eu + +ROOT=$(CDPATH= cd -- "$(dirname -- "$0")/.." && pwd) +EXPR_BIN=${EXPR_BIN:-"$ROOT/out/expr"} +TMPDIR=${TMPDIR:-/tmp} +WORKDIR=$(mktemp -d "$TMPDIR/expr-test.XXXXXX") +trap 'rm -rf "$WORKDIR"' EXIT INT TERM + +LC_ALL=C +LANG=C +export LC_ALL LANG + +fail() { + printf '%s\n' "FAIL: $1" >&2 + exit 1 +} + +assert_status() { + name=$1 + expected=$2 + actual=$3 + + [ "$expected" -eq "$actual" ] || fail "$name: expected exit $expected got $actual" +} + +assert_file_match() { + name=$1 + pattern=$2 + actual_file=$3 + + if ! grep -Eq "$pattern" "$actual_file"; then + printf '%s\n' "FAIL: $name" >&2 + printf '%s\n' "--- actual ---" >&2 + cat "$actual_file" >&2 + exit 1 + fi +} + +assert_file_eq() { + name=$1 + expected_text=$2 + actual_file=$3 + expected_file=$WORKDIR/expected.$$ + + printf '%s' "$expected_text" > "$expected_file" + if ! cmp -s "$expected_file" "$actual_file"; then + printf '%s\n' "FAIL: $name" >&2 + printf '%s\n' "--- expected ---" >&2 + od -An -tx1 -v "$expected_file" >&2 + printf '%s\n' "--- actual ---" >&2 + od -An -tx1 -v "$actual_file" >&2 + exit 1 + fi +} + +run_case() { + name=$1 + expected_status=$2 + expected_stdout=$3 + expected_stderr=$4 + shift 4 + + stdout_file=$WORKDIR/stdout + stderr_file=$WORKDIR/stderr + + if "$EXPR_BIN" "$@" >"$stdout_file" 2>"$stderr_file"; then + status=0 + else + status=$? + fi + + assert_status "$name status" "$expected_status" "$status" + assert_file_eq "$name stdout" "$expected_stdout" "$stdout_file" + assert_file_eq "$name stderr" "$expected_stderr" "$stderr_file" +} + +run_case_match_stderr() { + name=$1 + expected_status=$2 + expected_stdout=$3 + stderr_pattern=$4 + shift 4 + + stdout_file=$WORKDIR/stdout + stderr_file=$WORKDIR/stderr + + if "$EXPR_BIN" "$@" >"$stdout_file" 2>"$stderr_file"; then + status=0 + else + status=$? + fi + + assert_status "$name status" "$expected_status" "$status" + assert_file_eq "$name stdout" "$expected_stdout" "$stdout_file" + assert_file_match "$name stderr" "$stderr_pattern" "$stderr_file" +} + +derive_intmax_bounds() { + power=1 + steps=0 + + while next=$("$EXPR_BIN" "$power" "*" "2" 2>/dev/null); do + power=$next + steps=$((steps + 1)) + [ "$steps" -le 256 ] || fail "could not derive intmax bounds" + done + + INTMAX_MAX_VALUE=$("$EXPR_BIN" "(" "$power" "-" "1" ")" "+" "$power") + INTMAX_MIN_VALUE=$("$EXPR_BIN" "0" "-" "1" "-" "$INTMAX_MAX_VALUE") + export INTMAX_MAX_VALUE INTMAX_MIN_VALUE +} + +[ -x "$EXPR_BIN" ] || fail "missing binary: $EXPR_BIN" +derive_intmax_bounds + +run_case "no arguments" 2 "" "usage: expr [-e] [--] expression +" +run_case "invalid option" 2 "" "usage: expr [-e] [--] expression +" "-x" +run_case "integer addition" 0 "7 +" "" "3" "+" "4" +run_case "zero exit status" 1 "0 +" "" "3" "-" "3" +run_case "parentheses precedence" 0 "21 +" "" "(" "3" "+" "4" ")" "*" "3" +run_case "left associative subtraction" 0 "3 +" "" "8" "-" "3" "-" "2" +run_case "left associative division" 0 "2 +" "" "12" "/" "3" "/" "2" +run_case "division by zero" 2 "" "expr: division by zero +" "7" "/" "0" +run_case "remainder by zero" 2 "" "expr: division by zero +" "7" "%" "0" +run_case "type mismatch" 2 "" "expr: not a decimal number: 'abc' +" "abc" "+" "1" +run_case "too large operand" 2 "" "expr: operand too large: '999999999999999999999999999999999999' +" "999999999999999999999999999999999999" "+" "1" +run_case "addition overflow" 2 "" "expr: overflow +" "$INTMAX_MAX_VALUE" "+" "1" +run_case "subtraction overflow" 2 "" "expr: overflow +" "--" "$INTMAX_MIN_VALUE" "-" "1" +run_case "multiplication overflow" 2 "" "expr: overflow +" "$INTMAX_MAX_VALUE" "*" "2" +run_case "division overflow" 2 "" "expr: overflow +" "--" "$INTMAX_MIN_VALUE" "/" "-1" +run_case "string comparison" 0 "1 +" "" "b" ">" "a" +run_case "numeric string comparison" 0 "1 +" "" "--" "09" "=" "9" +run_case "strict plus stays string" 1 "0 +" "" "--" "+7" "=" "7" +run_case "logical or keeps left value" 0 "left +" "" "left" "|" "right" +run_case "logical or returns right" 0 "fallback +" "" "0" "|" "fallback" +run_case "logical and keeps left value" 0 "left +" "" "left" "&" "right" +run_case "logical and returns zero" 1 "0 +" "" "" "&" "right" +run_case "regex length" 0 "6 +" "" "abcdef" ":" "abc.*" +run_case "regex capture" 0 "de +" "" "abcde" ":" "abc\\(..\\)" +run_case "regex anchor" 1 "0 +" "" "abcde" ":" "bc" +run_case "regex capture miss" 1 " +" "" "abcde" ":" "zzz\\(..\\)" +run_case_match_stderr "regex syntax error" 2 "" '^expr: regular expression error: ' "abc" ":" "[[" +run_case "strict negative needs --" 2 "" "usage: expr [-e] [--] expression +" "-1" "+" "2" +run_case "negative with --" 0 "1 +" "" "--" "-1" "+" "2" +run_case "compat still needs -- for leading negative operand" 2 "" "usage: expr [-e] [--] expression +" "-e" "-1" "+" "2" +run_case "compat leading plus" 0 "1 +" "" "-e" " +7" "=" "7" +run_case "compat empty string as zero" 0 "1 +" "" "-e" "" "+" "1" +run_case "compat empty string compares as zero" 0 "1 +" "" "-e" "" "=" "0" +run_case "syntax error" 2 "" "expr: syntax error +" "1" "+" +run_case "trailing token syntax error" 2 "" "expr: syntax error +" "1" "2" +run_case "missing closing parenthesis" 2 "" "expr: syntax error +" "(" "1" "+" "2" + +stdout_file=$WORKDIR/write-fail.stdout +stderr_file=$WORKDIR/write-fail.stderr +if ( + exec 1>&- + "$EXPR_BIN" "write-test" +) >"$stdout_file" 2>"$stderr_file"; then + status=0 +else + status=$? +fi +assert_status "write failure status" 2 "$status" +assert_file_eq "write failure stdout" "" "$stdout_file" +case $(cat "$stderr_file") in + "expr: write failed: "* ) ;; + * ) fail "write failure stderr" ;; +esac + +printf '%s\n' "PASS" |
