Decoded: test (coreutils)

[Back to Project Main Page]

Note: This page explores the design of command-line utilities. It is not a user guide.
[GNU Manual] [POSIX requirement] [Linux man] [FreeBSD man]

Logical flow of test command (coreutils)

Summary

test - check file types and compare values

[Source] [Code Walkthrough]

Lines of code: 886
Principal syscall: None
Support syscalls: None
Options: 2 (hardcoded checks for --help and --version)

Descended from stty introduced in Version 7 UNIX (1979)
Added to Shellutils in October 1992 [First version]
Number of revisions: 178

The test utility departs from typical utilities by using a custom parser to evaluate expressions with special return values. Note that test is the general implementation of the '[' lbracket utility.

Helpers:
  • advance() - Updates argument position and compares count
  • and() - Evaluates AND operations (-a term)
  • beyond() - Throws a syntax error for missing arguments
  • binary_operator() - Evaluates the valid binary operators
  • binop() - Tests for a valid binary operator
  • expr() - Evaluates expression terms
  • find_int() - Finds a pointer to the start of a number
  • get_mtime() - Tests for and locates file modification time
  • one_argument() - Produce for a single argument test, simple non-null test
  • or() - Evaluates OR operations (-o)
  • posixtest() - The top-level procedure for test
  • term() - Parses an input term and returns the evaluation
  • test_main_return() - Function-like macro for the utility return value
  • test_syntax_error() - Throws a syntax error
  • test_unop() - Verifies a given unary operator
  • three_arguments() - Produce for a three argument test, binary operator
  • two_arguments() - Produce for a two argument test, unary operator
  • unary_advance() - Tests and updates argument position
  • unary_operator() - Evaluates the valid unary operators
External non-standard helpers:
  • die() - Exit with mandatory non-zero error and message to stderr
  • error() - Outputs error message to standard error with possible process termination

Setup

test keeps several variables as globals, the most important is pos, which is the index to the current argument under evaluation. The other globals are the expected argc, and **argv

main() introduces one important variable, value, which holds the eventual return value of the utility.


Parsing

Parsing for test is different from many other utilities in that it doesn't support any utility-level options or doesn't even use Getopt. It does hardcode a check for the help/version output.

Since the purpose of the utility is to parse and evaluate the command line, these tasks fall under the execution section. At a minimum, we confirm that there are no more than three arguments provided by the user as the only failure condition


Execution

test evaluates a single expression, which may contain of to 3 arguments. Each of these considers a different control flow:

  • The 1 argument expression checks that the argument is NULL or not and returns the truth of the check
  • The 2 argument expression assumes an op code and an argument. These include the file type checks and the access permission checks
  • The 3 argument expression assumes an op code and two arguments. These types include numeric and some string comparisons

Failure cases:

  • Unknown operation provided
  • Missing arguments
  • Unbalanced bracket usage
  • Unexpected argument types

All failures at this stage output an error message to STDERR and return without displaying usage help


[Back to Project Main Page]