Scoring against bash's own test suite
- #history
- #testing
- #bash-compat
bash ships its own test suite: 82 files of shell fragments, each with the exact output the real shell produces. It is designed to test bash. Pointed at huck, it becomes something better than a test suite — an external scoreboard, written by someone with no interest in flattering this project.
A category counts as passing only when huck's output is byte-identical to bash's. Not "equivalent". Identical.
The first sweep, in late June, passed 5 of 82. By the end of July, 39.
What that kind of scoreboard is for
Left to your own judgment, you fix the bugs you can imagine. A suite written by the people who wrote the shell tests the things they know are load-bearing, including plenty you would never invent. Some of what it found was ordinary — brace ranges with a negative step, which huck simply didn't parse:
# huck, 20 July # huck, 30 July (and bash)
$ echo {5..1..-2} $ echo {5..1..-2}
{5..1..-2} 5 3 1And some of it was this:
# huck, 20 July
$ declare -A m=([a]=1 [b]=2 [c]=3); echo "${!m[@]}"
a b c
# bash
c b ahuck listed the keys in the order you inserted them, which is the obvious
choice, and defensible, and wrong. bash iterates an associative array in the
order its internal hash table happens to hold the keys. There is no
specification for that order. It is an implementation detail — and it is
observable from every script that loops over "${!m[@]}", so a shell that
wants identical output has to reproduce the detail exactly.
So it got reverse-engineered against the real shell: bash hashes keys with
32-bit FNV-1, distributes them over 1024 buckets, walks the buckets in
ascending order, and within a bucket returns the most recently inserted key
first. That last clause is why c b a comes out reversed here — three keys
that all land in different buckets, walked in an order that has nothing to do
with insertion, and every one of them a fresh chain head.
# huck, 30 July
$ declare -A m=([a]=1 [b]=2 [c]=3); echo "${!m[@]}"
c b aThe rule that made that safe to attempt: validate the reverse-engineered algorithm against the real shell across hundreds of generated key sets before writing any of it into huck. A hash function you inferred from three examples is a hypothesis, not a specification.
What the score is actually measuring
Not "how much of bash is implemented" — huck implements far more than 39/82 suggests. Byte-identical is a brutal bar: one category can fail on a single error message with the wrong wording, or a line number off by one, while hundreds of assertions around it pass. What the number measures is how much of bash huck can be substituted for without anyone noticing. That's the only definition of compatibility that means anything, and it's why the failures are worth chasing one category at a time.