Data files are always organized as follows:
Header1: Value1 \
... | head
HeaderN: ValueN /
mandatory blank line
Free-form text contents \
... | body
... /
A file must always contain a `Content-Type' header and must always separate that header from the body with a blank line, even if the body is empty.
The `Content-Type' is always of the form:
Content-Type: application/X-atf-; version=""
where `subtype' indicates the specific file format and `version' its format version. This header must be the first one of the file.
The main purpose of the `Content-Type' header, aside from determining the format used in the file, is to allow future changes to a given format. Whenever an incompatible change is made, the version is bumped by one. By keeping the header in the first line, future versions may even remove the need for such a header -- e.g. if some format was replaced by XML files, which have their own mandatory header.
The rest of this document details the different format types.
The grammar for Atffiles is the following:
DATA ::= ( ( CONF | PROP | TP )? COMMENT? NEWLINE )* EOF
CONF ::= 'conf:' WORD EQUAL STRING
PROP ::= 'prop:' WORD EQUAL STRING
TP ::= TPFILE | TPGLOB
TPFILE ::= 'tp: ' STRING
TPGLOB ::= 'tp-glob: ' STRING
STRING ::= WORD | '"' WORD* '"'
The meaning of the constructions above is:
An example:
prop: test-suite = utilities
conf: unprivileged-user = nobody
tp: t_cp
tp: t_mv
tp: t_df
tp-glob: t_dir_*
DATA ::= ( VAR? COMMENT? NEWLINE )* EOF
VAR ::= WORD EQUAL STRING
COMMENT ::= HASH WORD*
STRING ::= WORD | '"' WORD* '"'
An example:
# This is the system-wide configuration file for ATF.
# The above and this line are comments placed on their own line.
var1 = this is a variable value
var2 = this is another one # Optional comment at the end.
Because we have no control over the two standard streams, the `application/X-atf-tcs' format describes the structure of a third stream, known as the results output, that test programs must generate. (Note that test programs send, by default, the results output to the standard output; use their -r flag to change this whenever you need to parse the data.) This stream is decoupled from the other two and has the following grammar:
DATA ::= TCS-COUNT TC-STANZA* EOF
TCS-COUNT ::= 'tcs-count' COLON POSITIVE-NUMBER NEWLINE
TC-STANZA ::= TC-START TC-END
TC-START ::= 'tc-start' COLON STRING NEWLINE
TC-END ::= 'tc-end' COLON STRING COMMA TCR NEWLINE
TCR ::= 'passed' | ('failed' | 'skipped') COMMA STRING
The meaning of the constructions above is:
There are multiple reasons behind this design:
An example:
tcs-count: 2
tc-start: add
tc-end: add, passed
tc-start: subtract
tc-end: subtract, failed, Calculated an unexpected value
Going back to the standard output and standard error streams, the reader has to be able to match the messages in those two streams to the test cases they belong to. To do this, these two streams must print a magic string that separates the output of test cases from each other, which is enough to synchronize their contents with the results output. This string is `__atf_tc_separator__' and it must printed on a line of its own. The last test case should not be followed by this line because the end of file marker takes its role.
DATA ::= INFO* TPS-COUNT TP-STANZA* INFO* EOF
INFO ::= 'info' COLON STRING COMMA STRING NEWLINE
TPS-COUNT ::= 'tps-count' COLON POSITIVE-NUMBER NEWLINE
TP-STANZA ::= TP-START TC-STANZA* TC-END
TP-START ::= 'tp-start' COLON STRING COMMA POSITIVE-NUMBER NEWLINE
TP-END ::= 'tc-end' COLON STRING (COMMA STRING)?
TC-STANZA ::= TC-START (TC-SO | TC-SE)* TC-END
TC-START ::= 'tc-start' COLON STRING NEWLINE
TC-SO ::= 'tc-so' COLON STRING NEWLINE
TC-SE ::= 'tc-se' COLON STRING NEWLINE
TC-END ::= 'tc-end' COLON STRING COMMA TCR NEWLINE
TCR ::= 'passed' | ('failed' | 'skipped') COMMA STRING
The meaning of the constructions above is:
An example:
tps-count: 2
tp-start: calculator, 2
tc-start: add
tc-end: add, passed
tc-start: subtract
tc-so: 3-2 expected to return 1 but got 0
tc-end: subtract, failed, Calculated an unexpected value
tp-end: calculator
tp-start: files, 1
tc-start: copy
tc-se: could not find the cp(1) utility
tc-end: copy, skipped
tp-end: files