mix bash_fixtures.gen (JustBash v0.4.0)
View SourceGenerates enumerated fixture matrices — the cases nobody thinks to write.
The corpus grew by example: someone fixed a bug, then wrote a case for the shape
they had just fixed. That leaves whole alphabets unexamined. date.json has 30
hand-written cases and covers none of %F, %D, %T, %R, -I or -v — the
exact directives that shipped emitting themselves literally at exit 0, which an
agent then used as if it were a date.
A command's flag and directive sets are finite. They are not a space to sample with a fuzzer; they are a list to enumerate. This task writes that enumeration out as ordinary case files, so recording and comparison work exactly as they do for hand-written cases:
mix bash_fixtures.gen date # write the matrix
mix bash_fixtures date_matrix # record what real bash does
mix test --only suite:date_matrix
mix bash_fixtures.gen printf # write the matrix
mix bash_fixtures printf_matrix # record what real bash does
mix test --only suite:printf_matrix
mix bash_fixtures.gen test # write the matrix
mix bash_fixtures test_matrix # record what real bash does
mix test --only suite:test_matrix
mix bash_fixtures.gen varop # write the matrix
mix bash_fixtures varop_matrix # record what real bash does
mix test --only suite:varop_matrix
mix bash_fixtures.gen flags # write the matrix
mix bash_fixtures flags_matrix # record what real bash does
mix test --only suite:flags_matrix
mix bash_fixtures.gen seto # write the matrix
mix bash_fixtures seto_matrix # record what real bash does
mix test --only suite:seto_matrixGenerated suites are named <matrix>_matrix and are safe to regenerate: the
digest in JustBash.Fixtures is content-derived, so a case that did not change
keeps its recording.
Matrices
date— every strftime conversion alone, adjacently paired, and crossed with every field flag, locale modifier, width and compound form, plus-Igranularities,-dinput forms, and flags GNU date does not haveprintf— every bash/coreutils conversion (%s %c %d %i %u %o %x %X %f %e %E %g %G %a %A %%, plus bash extras%b%q) alone at two or more bases, then crossed with every format flag, width, precision and*, plus%b/%qinputs that make escapes and quoting visible, and format recycling with excess arguments. Oilsbuiltin-printf.test.shis a cross-check, not this matrix. See #70 item 2.test— every POSIX/[operator (-b -c -d -e -f -g -h -k -L -n -p -r -S -s -t -u -w -x -z,===!=<>,-eq -ne -lt -le -gt -ge,-nt -ot -ef,-a -o,!, plus bash extras-G -O -N) crossed with revealing operand shapes for that operator — file/dir/missing/empty/ symlink/dangling for file tests, empty/nonempty/"0" for-z/-n, equal/ unequal/10-vs-9 for string and integer compares. Bothtestand[for a representative subset so they cannot drift; the full operator list is ontest. This is not the item-3 filesystem-shape × command cube. See #70 item 2.varop— every POSIX/bash${var op word}form (-:-=:=+:+?:?,###%%%,${#var},${var:offset},${var:offset:len},${var/pat/rep},${var//pat/rep}) crossed with unset / set-empty / set-nonempty, and with a nonempty vs empty word where that changes the answer. Two nonempty bases (foovsfoobar, plusfoofoowhere shortest vs longest or first vs all would otherwise hide) so one value cannot hide the bug. Suitevarop_matrix. See #70 item 2.flags—cmd --jb-not-a-flagandcmd -Zfor every name inCommands.Registry. The default assertion is non-zero exit and usage-bearing stderr (never exit 0). Commands that legitimately treat the token as an operand (echo), accept GNU-Z(SELinux,diff -Z,grep -Z,curl -Z), or have no GNU twin (markdown/md) are still generated and named with a reason — never silently omitted. Suiteflags_matrix. This is the registry-wide unknown-flag probe from #70 item 2;unknown_flags_test.exskeeps the FlagParser unit tests from #68 rather than a second classification table.seto— every POSIXset -oname and every extra bash nameset -olists, plus unknown names, each asked as-oand+o. NamesJustBash.Commands.Setimplements are generated unmarked; real names this shell rejects, and names bash itself refuses, are still generated and named with a reason — never silently omitted. Suiteseto_matrix. This is theset -oname alphabet from #70 item 2, not the short-option cluster (-euo) orset -owith no name (that lists every option).
A list of conversions and a list of flags are each easy to write down. The
cross of the two is where the bugs live and is what nobody enumerates by hand:
the first version of this matrix listed both alphabets and still missed that
%-T rendered "9:05:03", because it never asked a flag and a conversion in the
same breath. Cross what you enumerate.
Usage
mix bash_fixtures.gen # every matrix
mix bash_fixtures.gen date # one matrix
mix bash_fixtures.gen printf # one matrix
mix bash_fixtures.gen test # one matrix
mix bash_fixtures.gen varop # one matrix
mix bash_fixtures.gen flags # one matrix
mix bash_fixtures.gen seto # one matrix
mix bash_fixtures.gen --dry-run # report counts, write nothing