#!/bin/sh set -eu tool=${1:-zig-out/bin/pick} tmp=${TMPDIR:-.zig-cache}/pick-smoke.$$ mkdir -p "$tmp" trap 'rm -rf "$tmp"' EXIT HUP INT TERM # req: pick/008 # req: pick/009 # req: pick/010 assert_eq() { want=$1 got=$2 cmp "$want" "$got" } assert_empty() { file=$1 if [ -s "$file" ]; then echo "pick: expected empty file: $file" >&2 exit 1 fi } assert_fails() { if "$@"; then echo "pick: command unexpectedly succeeded: $*" >&2 exit 1 fi } # Numeric field selection preserves records and stdout contains only selected TSV. printf 'a\tb\tc\n1\t2\t3\n' | "$tool" 2 > "$tmp/pick-one.out" printf 'b\n2\n' > "$tmp/pick-one.want" assert_eq "$tmp/pick-one.want" "$tmp/pick-one.out" # Header selection emits the selected header and selected data columns. printf 'path\tsize\tkind\na\t10\tfile\n' | "$tool" --header path size > "$tmp/pick-header.out" printf 'path\tsize\na\t10\n' > "$tmp/pick-header.want" assert_eq "$tmp/pick-header.want" "$tmp/pick-header.out" # Missing fields are empty fields, not pipeline failures. printf 'a\tb\n1\n' | "$tool" 1 2 > "$tmp/pick-missing.out" printf 'a\tb\n1\t\n' > "$tmp/pick-missing.want" assert_eq "$tmp/pick-missing.want" "$tmp/pick-missing.out" # CRLF input is accepted and normalized to LF records. printf 'a\tb\r\n1\t2\r\n' | "$tool" 2 > "$tmp/pick-crlf.out" printf 'b\n2\n' > "$tmp/pick-crlf.want" assert_eq "$tmp/pick-crlf.want" "$tmp/pick-crlf.out" # A record longer than the internal read buffer still streams correctly across # chunk boundaries without whole-input buffering. : > "$tmp/pick-long.in" i=0 while [ "$i" -lt 9000 ]; do printf x >> "$tmp/pick-long.in" i=$((i + 1)) done printf '\tb\n' >> "$tmp/pick-long.in" "$tool" 2 < "$tmp/pick-long.in" > "$tmp/pick-long.out" printf 'b\n' > "$tmp/pick-long.want" assert_eq "$tmp/pick-long.want" "$tmp/pick-long.out" # Help is stdout-only and successful. "$tool" --help > "$tmp/pick-help.out" 2> "$tmp/pick-help.err" grep -q '^usage: pick' "$tmp/pick-help.out" assert_empty "$tmp/pick-help.err" # Usage errors are stderr-only and nonzero. assert_fails "$tool" > "$tmp/pick-noargs.out" 2> "$tmp/pick-noargs.err" assert_empty "$tmp/pick-noargs.out" grep -q '^usage: pick' "$tmp/pick-noargs.err" assert_fails "$tool" 0 > "$tmp/pick-zero.out" 2> "$tmp/pick-zero.err" assert_empty "$tmp/pick-zero.out" grep -q 'fields are 1-based' "$tmp/pick-zero.err" assert_fails "$tool" nope > "$tmp/pick-invalid.out" 2> "$tmp/pick-invalid.err" assert_empty "$tmp/pick-invalid.out" grep -q 'invalid field' "$tmp/pick-invalid.err" # Forbidden near miss: option-looking regex/expression input is rejected as data, # not interpreted as another command language. assert_fails "$tool" --regex '.*' > "$tmp/pick-regex.out" 2> "$tmp/pick-regex.err" assert_empty "$tmp/pick-regex.out" grep -q 'invalid field' "$tmp/pick-regex.err" # Head-style consumers may close stdout early; that must not pollute stderr. i=0 { while [ "$i" -lt 20000 ]; do printf 'a\tb\n' i=$((i + 1)) done } | "$tool" 1 2> "$tmp/pick-head.err" | sed 1q > "$tmp/pick-head.out" printf 'a\n' > "$tmp/pick-head.want" assert_eq "$tmp/pick-head.want" "$tmp/pick-head.out" assert_empty "$tmp/pick-head.err"