[Toybox] toybox shell: alias support

Rob Landley rob at landley.net
Wed Feb 11 13:21:44 PST 2026


On 2/11/26 01:16, Kevin Karhan wrote:
> As [hinted by Rob](https://mstdn.jp/@landley/116043106074437957) I'd 
> like to add some test cases for aiias support in toybox's shell.
> 
> - I mostly truncated [my public .bash_aliases file](https://github.com/ 
> kkarhan/misc-scripts/blob/master/bash/.bash_aliases), ditching external 
> tools like enc and rewriting it to use wget instead of curl (because a 
> wget implementation is part of toybox).

Which is good, but not quite the same as "tests". Your first one sets a 
"clr" alias, and then you don't have anything that uses it. That said, 
they seem obvious enough I can probably convert them myself.

I checked for documentation to point you at about the toybox test 
suite... and I need to write more documentation. I ALWAYS need to write 
more documentation. https://landley.net/toybox/faq.html#code isn't 
nearly enough of an intro to the test suite. and 
https://landley.net/toybox/code.html#infrastructure has a #tests link 
that doesn't even go anywhere! Great...

Right: the toybox test suite ("make test_sh" in this case) is a bunch of 
files in tests/*.test (one per command) with one-per-line tests, and 
then the driver scripts are scripts/test.sh calling scripts/runtest.sh.

The one you DON'T run directly is scripts/runtest.sh which contains all 
the guts of the test plumbing, the main part being the "testing" and 
"testcmd" shell functions which run an actual test. Their arguments are 
explained starting at scripts/runtest.sh line 15. (The second is a 
convenience wrapper for the first.)

The other one (scripts/test.sh) is called directly, providing a command 
line UI that either tests a single command (ala: scripts/test.sh sed) or 
tests all the commands if run with no arguments. It does this by 
creating "generated/testdir" (all toybox intermediate build files go in 
generated/ so half of clean is just "rm -rf generated" and the rest is 
deleting the final output files produced at the top level), plonking the 
appropriate binary to be tested in there, sticking it at the start of 
the $PATH, and then making an empty generated/testdir/testdir under that 
to cd into and run all the tests in sequence in an empty scratch dir. If 
you run it twice it'll rm -rf generated/testdir at the start so it sets 
up a clean environment each time.

Android doesn't use test.sh, it only uses runtest.sh and creates its own 
environment for it as part of the AOSP plumbing. (That's the main reason 
they're two scripts, for integration into other projects' test suites.)

There are three main environment variables that modify how the tests get 
run, two of which are described at the start of runtest.sh and the other 
is mainly about how test.sh sets up the test environment:

TEST_HOST=1 - don't build a toybox binary, just test the existing 
command out of the host $PATH.
DEBUG=1 - show every command run by every test script (you generally 
don't want this unless you're doing development on the test suite itself).
VERBOSE=... - You can add multiple things here (ala VERBOSE=allnopass):
   all - don't stop at the first FAIL, keep going until the end.
   nopass - don't show PASS: lines, just failures
   quiet - don't show diff -u between expected/actual output for failures
   spam - show ALL THE OUTPUT (like DEBUG=1 above but for results)

The test suite also has a built in shell-based "expect" (the function 
txpect() in scripts/runtest.sh starting line 182) which sh.tests then 
wraps as shxpect() around line 19 so it can invoke the shell with:

env -i PATH=${PATH at Q} PS1='\\$ ' $SH --noediting --noprofile --norc -is

I.E. run in a clean environment (env -i), $SH runs sh or bash as 
appropriate (toysh makes "sh" but /bin/sh is the Defective Annoying 
SHell on ubuntu, not bash), and then some --longopts to beat testable 
behavior out of bash. (without --noediting gnu/gnu/ftaghn/readline reads 
from /dev/tty instead of stdin, yes really).

And then shxpect calls txpect but the first thing it does is wait for an 
appropriate incoming interactive prompt on stderr and _then_ starts the 
supplied challenge/response series.

You need to regression test alias this way because alias ONLY applies to 
interactive input, it doesn't apply in shell scripts! (Which is just 
nuts, but I didn't design it...)

In theory I added basic alias support in f43c79154259 and that had some 
shxpect tests, and then updated it a bit in 8433c5d9a435 with more tests 
(some about alias/unalias but mostly about prefix assignment).

Possibly the main thing missing here is that the startup logic doesn't 
read .bash_aliases. If you source it yourself, which ones don't do what 
you expect?

Rob


More information about the Toybox mailing list