#!/bin/sh # tests/test_grep.sh - Tests for grep/egrep/fgrep applets _test_name="grep" . "$(dirname "$0")/harness.sh" setup_tmpdir GREP="$VX grep" EGREP="$VX egrep" FGREP="$VX fgrep" echo "Running grep tests..." # --- create test files --- cat > haystack.txt <<'EOF' Hello World hello world HELLO WORLD foo bar baz The quick brown fox jumps over the lazy dog line with numbers 12345 another line here foobar EOF cat > patterns.txt <<'EOF' foo bar EOF # --- basic match --- _got="$($GREP 'Hello' haystack.txt)" check_eq "$_got" "Hello World" "basic: literal match" # --- case insensitive --- _count="$($GREP -ic 'hello' haystack.txt)" check_eq "$_count" "3" "iflag: case insensitive count" # --- -v invert --- _count="$($GREP -vic 'hello' haystack.txt | tr -d ' ')" _total="$(wc -l < haystack.txt | tr -d ' ')" _expect=$((${_total} - 3)) check_eq "$_count" "$_expect" "vflag: invert count" # --- -n line numbers --- _got="$($GREP -n 'foo bar' haystack.txt)" check_eq "$_got" "4:foo bar baz" "nflag: line number" # --- -c count --- _got="$($GREP -c 'line' haystack.txt)" check_eq "$_got" "2" "cflag: count lines" # --- -l files-with-matches --- _got="$($GREP -l 'Hello' haystack.txt)" check_eq "$_got" "haystack.txt" "lflag: filename" # --- -L files-without-match --- echo "no match here" > other.txt _got="$($GREP -L 'Hello' haystack.txt other.txt)" check_eq "$_got" "other.txt" "Lflag: no-match filename" # --- -w word match --- _got="$($GREP -wc 'foo' haystack.txt)" check_eq "$_got" "1" "wflag: word boundary (foo not foobar)" # --- -x line match --- _got="$($GREP -x 'foobar' haystack.txt)" check_eq "$_got" "foobar" "xflag: exact line match" # --- -o only matching --- _got="$($GREP -o 'fox' haystack.txt)" check_eq "$_got" "fox" "oflag: only matching part" # --- -m max count --- _got="$($GREP -m1 'line' haystack.txt)" _count="$(printf '%s\n' "$_got" | wc -l | tr -d ' ')" check_eq "$_count" "1" "mflag: max count 1" # --- -e multiple patterns --- _count="$($GREP -c -e 'Hello' -e 'quick' haystack.txt)" check_eq "$_count" "2" "eflag: multiple patterns" # --- -f pattern file --- _count="$($GREP -c -f patterns.txt haystack.txt)" check_eq "$_count" "2" "fflag: pattern file (foo, bar match 2 lines)" # --- -q quiet mode --- $GREP -q 'Hello' haystack.txt check_eq "$?" "0" "qflag: quiet match exits 0" $GREP -q 'NOMATCH_XYZ' haystack.txt check_eq "$?" "1" "qflag: quiet no-match exits 1" # --- -s suppress errors --- $GREP -s 'test' nonexistent_file 2>err_out _err="$(cat err_out)" check_eq "$_err" "" "sflag: suppresses error messages" # --- -b byte offset --- _got="$($GREP -b 'foo bar' haystack.txt | cut -d: -f1)" # "foo bar" is on line 4, after 3 lines + newlines test -n "$_got" check_eq "$?" "0" "bflag: byte offset present" # --- -H / -h filename control --- _got="$($GREP -H 'Hello' haystack.txt)" echo "$_got" | grep -q '^haystack.txt:' check_eq "$?" "0" "Hflag: filename shown" _got="$($GREP -h 'Hello' haystack.txt)" echo "$_got" | grep -qv ':' check_eq "$?" "0" "hflag: no filename" # --- extended regex (egrep / -E) --- _got="$($GREP -Ec 'foo|quick' haystack.txt)" check_eq "$_got" "3" "Eflag: extended regex" _got="$($EGREP -c 'foo|quick' haystack.txt)" check_eq "$_got" "3" "egrep: dispatch works" # --- fixed strings (fgrep / -F) --- _got="$($FGREP -c 'foo' haystack.txt)" check_eq "$_got" "2" "fgrep: fixed strings" # --- context: -A after --- _count="$($GREP -A1 'quick' haystack.txt | wc -l | tr -d ' ')" check_eq "$_count" "2" "Aflag: after context" # --- context: -B before --- _count="$($GREP -B1 'quick' haystack.txt | wc -l | tr -d ' ')" check_eq "$_count" "2" "Bflag: before context" # --- context: -C both --- _count="$($GREP -C1 'quick' haystack.txt | wc -l | tr -d ' ')" check_eq "$_count" "3" "Cflag: context both sides" # --- stdin --- _got="$(echo 'test line' | $GREP 'test')" check_eq "$_got" "test line" "stdin: pipe works" # --- exit codes --- check_exit "exit: match returns 0" 0 $GREP -q 'Hello' haystack.txt check_exit "exit: no match returns 1" 1 $GREP -q 'ZZZNOTFOUND' haystack.txt check_exit "exit: error returns 2" 2 $GREP 'test' --bogus-flag 2>/dev/null # --- recursive --- mkdir -p subdir echo "findme here" > subdir/nested.txt _got="$($GREP -r 'findme' .)" echo "$_got" | grep -q 'nested.txt' check_eq "$?" "0" "rflag: recursive find" # --- --include --- echo "match" > inc_yes.c echo "match" > inc_no.txt _got="$($GREP -r --include='*.c' 'match' .)" echo "$_got" | grep -q 'inc_yes.c' check_eq "$?" "0" "include: *.c matches" echo "$_got" | grep -q 'inc_no.txt' check_eq "$?" "1" "include: *.txt excluded" # --- --exclude --- _got="$($GREP -r --exclude='*.txt' 'match' .)" echo "$_got" | grep -q 'inc_yes.c' check_eq "$?" "0" "exclude: *.c still matches" # --- -z null data --- printf 'aaa\0bbb\0ccc\0' > nulldata _count="$($GREP -zc 'bbb' nulldata)" check_eq "$_count" "1" "zflag: null-delimited" summary