RISC OS Build EnvironmentROBE

Appendix57Appendix W: riscos-tooltester file format

Overview

This appendix describes the plain text file formats used by riscos-tooltester. The runner is intentionally simple: test suites are line-oriented text files, expectations are ordinary text files, and optional replacement scripts normalise unstable output before comparison.

Suite format and command reference

Suite layout and defaults

The normal suite entry point is a file named tests.txt in the chosen test directory, though the runner can be pointed at a different file with -script. A suite directory commonly contains:

  • one main script file, usually tests.txt;
  • expected output files, often under expect/;
  • replacement scripts used to normalise unstable output before comparison; and
  • optional input data files, often under testdata/.

The script is read line by line. Blank lines and lines beginning with # are ignored.

Statement syntax

Each statement has one of these forms:

Keyword: value
Checker:parameter: value
-Keyword:
-Checker:parameter:

The two structural statements are:

StatementMeaning
Group: <name>Begin a group. The group establishes default statements inherited by later tests in that group.
Test: <name>Begin one individual test. It starts as a copy of the current group settings, then any following statements override or clear those inherited values.

To clear an inherited value from the current group, write the same keyword with a leading minus and no value, such as -Expect: or -Creates:.

Core suite commands

The runner accepts the following built-in suite statements:

StatementMeaning
Include: <file>Read another suite file inline at that point. This is commonly used to split a large suite into smaller files.
Suite: <name>Set the suite name used in JUnit XML output. If omitted, the runner infers a name from the script filename where possible.
Command: <command>Command line to execute for the test. The command may contain substitution variables such as $TOOL, $FILE, or $ARGS.
Capture: stdout|stderr|bothSelect which output stream is captured for comparison. The default is both.
File: <path>Source file value, available to substitutions as $FILE and $BASE.
Args: <arguments>Arbitrary argument string, available as $ARGS and tokenised into $ARG1, $ARG2, and so on.
Expect: <file>Expectation file containing the expected captured output.
Replace: <file>Replacement script applied to captured output before comparison.
Creates: <file...>One or more files that must be created by the command. The runner removes any pre-existing paths before the test and removes successful outputs afterwards.
CreatesDir: <dir...>One or more directories that must be created by the command. These are also removed before and after the test.
Length: <n>Expected file length in bytes for files named by Creates:. When more than one created file is named, they must all match this size.
Removes: <file>File that the command is expected to delete. The runner creates an empty placeholder before the test so that removal can be checked.
Absent: <file>File that must not exist after the command completes.
RC: <n>Expected return code. The default is 0.
Input: <file>File whose contents are supplied on standard input.
InputLine: <text>One line of text supplied on standard input, with a trailing newline appended by the runner.
Env: <VAR>=<value>Environment variable set only for this test execution. This statement may be repeated.
Disable: <reason>Disable the current group or test, recording the given reason in the reported skip result.

Substitution variables

Most statement values may contain substitution variables. The runner expands the following names:

VariableMeaning
$TOOLTool path supplied on the riscos-tooltester command line.
$FILEValue supplied by the current File: statement.
$OFILEObject-file path derived from $FILE using RISC OS build-directory conventions.
$SFILEAssembler-file path derived from $FILE.
$CFILEC-file path derived from $FILE.
$BASELeaf filename derived from $FILE.
$ARGSFull argument string from Args:.
$ARG1 ... $ARG9Whitespace-tokenised arguments derived from Args:. Missing values expand to an empty string.

Quoted argument text in Args: is preserved when the numbered $ARGn variables are extracted, so embedded spaces can still be treated as one argument.

Only $ARG1 through $ARG9 are ever defined; a tenth or later argument is simply not made available through a numbered variable. Writing $ARG10 in a command does not fall back to $ARG1 followed by a literal 0: the substitution logic greedily matches as many digits as possible when looking for a variable name, so it treats the whole of ARG10 as the candidate name, finds no such variable, and leaves $ARG10 in the command unsubstituted. A test needing a tenth or later argument should pass it through $ARGS instead and split it within the tested command.

Checker commands

Checker statements use the form <checker>:<parameter>: <value>. They attach extra validation rules to the current group or test and are typically used with one file named by Creates:. The runner currently supports the following checker families:

AOF checker

StatementMeaning
aof:totalareasize: <size>Require the sum of all AOF area sizes to match the given value.

ALF checker

StatementMeaning
alf:files: <count>Require the library to contain the given number of files.

ELF checker

StatementMeaning
elf:endianness: little|bigExpected ELF endianness.
elf:entry: <address>Expected entry address.
elf:type: <type>Expected ELF object type, checked as a plain numeric comparison against the file's e_type field with no restriction to particular values. The installed script's own comments only mention 1 (relocatable) and 2 (executable), but the standard ELF enumeration's other small values also work: 3 for a shared object and 4 for a core file.
elf:osabi: <value>Expected OS/ABI value.
elf:phoff: <offset>Expected program-header table offset.
elf:shoff: <offset>Expected section-header table offset.
elf:ehsize: <size>Expected ELF header size.
elf:flags: <flags>Expected ELF flags field.
elf:phentsize: <size>Expected size of each program-header entry.
elf:phnum: <count>Expected number of program-header entries.
elf:shentsize: <size>Expected size of each section-header entry.
elf:shnum: <count>Expected number of section-header entries.
elf:shstrndx: <index>Expected section-name string-table index.

Text checker

StatementMeaning
text:matches: <file>Compare the created file's textual content against the named file.
text:replace: <file>Apply a replacement script before the textual comparison.

Binary checker

StatementMeaning
binary:matches: <file>Compare the created file byte-for-byte against the named file.
binary:checkfile: <file>Validate specific offsets described by a separate checkfile.
binary:replace: <file>Apply a replacement script before comparing the binary file rendered as text.

The installed script comments describe the checkfile syntax as:

<offset> [word|byte|string]: <value>

The installed runner does not permit checker use with more than one created file in the same test. If you need checker validation for multiple outputs, split them into separate tests.

Replacement script language

Replacement scripts are miniature line-processing programs. They transform the captured output into a stable form before it is compared against the expectation file, which is useful when the tool prints variable data such as absolute paths, timestamps, branch names, or memory addresses.

The replacement file is read line by line:

  • blank lines and comment lines beginning with # are ignored;
  • directive lines begin with %;
  • all other lines are rules made of zero or more conditions followed by one action.

Directives

The installed runner supports one directive:

DirectiveMeaning
%include <file>Read another replacement file inline. Paths are resolved relative to the current replacement file.

Conditions

Rules may be restricted by line number, by regular-expression match, or by both together.

Condition formMeaning
5Apply only to line 5.
-5Apply only to lines 1 through 5.
3-10Apply only to lines 3 through 10.
10-Apply only to line 10 onwards.
/pattern/Apply only when the line matches the regular expression.
/pattern/ !Negated regular-expression condition: apply only when the line does not match.

The installed script also accepts negation on the numeric range condition by adding ! immediately after it. When both a range and a regular-expression condition are present, both must match for the action to run.

Actions

The supported actions are:

ActionMeaning
s/from/to/Replace the first regular-expression match on the line.
s/from/to/gReplace all matches on the line.
s/from/to/iCase-insensitive single substitution.
s/from/to/giCase-insensitive global substitution.
pWrite the line to the output immediately and continue with the next input line.
dDelete the line from the output.
qStop processing and end the output before the current line.

If no rule takes an early action and the end of the rule list is reached, the current line is written to the output unchanged.

Replacement example

This example removes transient progress messages, normalises a test-data path, and rewrites hexadecimal addresses:

/^Processing:/ d
s!/[^ ]+/testdata!TESTDATA!g
s/0x[0-9a-f]{8}/0xXXXXXXXX/gi

Worked suite example

A compact suite for command help and version output can be written like this:

Group: Core behaviour
Command: $TOOL $ARGS
Replace: expect/shared_replacements

Test: Help text
Args: --help
Expect: expect/help

Test: Version text
Args: --version
Expect: expect/version

Test: Writes report
Args: --report out.txt
Creates: out.txt
text:matches: expect/report

That pattern keeps the command line and shared replacements at group level, leaving each test to describe only the inputs and checks that differ.