.\" -*-nroff-*- .de VS .sp 1 .in +5 .nf .ft B .. .de VE .ft R .fi .in -5 .sp 1 .. .TH testrig 3 "5 June 1999" "Straylight/Edgeware" "mLib utilities library" .SH NAME testrig \- generic test rig .\" @test_run .SH SYNOPSIS .nf .B "#include " .BI "void test_do(const test_suite " suite [], .BI " FILE *" fp , .BI " test_results *" results ); .BI "void test_run(int " argc ", char *" argv [], .BI " const test_chunk " chunk [], .BI " const char *" def ); .fi .SH DESCRIPTION .SS Structure Test vectors are gathered together into .I chunks which should be processed in the same way. Chunks, in turn, are grouped into .IR suites . .SS Functions The .B test_do function runs a collection of tests, as defined by .IR suite , given the test vectors in the file .IR fp . It returns results in the .B test_results structure .IR results , which has two members: .TP .B "unsigned tests" counts the number of tests carried out, and .TP .B "unsigned failed" counts the number of tests which failed. .PP The function returns negative if there was a system error or the test vector file was corrupt in some way, zero if all the tests were successful, or positive if some tests failed. .PP The .B test_run provides a simple command-line interface to the test system. It is intended to be called from the .B main function of a test rig program to check that a particular function or suite of functions are running properly. It does not return. The arguments .I argc and .I argv should just be the arguments given to .BR main . The .I def argument gives the name of the default file of test vectors to read. This can be overridden at run-time by passing the program a .B \-f command-line option. The .I chunk argument is (the address of) an array of .I "chunk definitions" describing the layout of the test vector file. .SS "Test vector file syntax" Test vector files are mostly free-form. Comments begin with a hash .RB (` # ') and extend to the end of the line. Apart from that, newline characters are just considered to be whitespace. .PP Test vector files have the following syntax: .PP .I file ::= .RI [ suite-header | chunk " ...]" .br .I suite-header ::= .B suite .I name .br .I chunk ::= .I name .B { .RI [ test-vector " ...]" .B } .br .I test-vector ::= .RI [ value ...] .B ; .PP Briefly in English: a test vector file is divided into chunks, each of which consists of a textual name and a brace-enclosed list of test vectors. Each test vector consists of a number of values terminated by a semicolon. .PP A value is either a sequence of .I "word characters" (alphanumerics and some other characters) or a string enclosed in quote marks (double or single). Quoted strings may contain newlines. In either type of value, a backslash escapes the following character. .SS "Suite definitions" A .I suite definition is described by the structure .VS typedef struct test_suite { const char *name; /* Name of this suite */ const test_chunk *chunks; /* Pointer to chunks */ } test_suite; .VE The .I suite argument to .B test_do is a pointer to an array of these structures, terminated by one with a null .BR name . .SS "Chunk definitions" A .I "chunk definition" describes the format of a named chunk: the number and type of the values required and the function to call in order to test the system against that test vector. The array is terminated by a chunk definition whose name field is a null pointer. .PP A chunk definition is described by the following structure: .VS typedef struct test_chunk { const char *name; /* Name of this chunk */ int (*test)(dstr dv[]); /* Test verification function */ test_type *f[TEST_FIELDMAX]; /* Field definitions */ } test_chunk; .VE The members of this structure are as follows: .TP .B "const char *name" The name of the chunk described by this chunk definition, or null if this is the termination marker. .TP .B "int (*test)(dstr dv[])" The test function. It is passed an array of dynamic strings, one for each field, and must return nonzero if the test succeeded or zero if the test failed. On success, the function should not write anything to stdout or stderr; on failure, a report of the test arguments should be emitted to stderr. .TP .B "test_type *f[TEST_FIELDMAX]" Definitions of the fields. This is an array of pointers to .I "field types" (see below), terminated by a null pointer. .PP When the test driver encounters a chunk it has a definition for, it reads test vectors one by one, translating each value according to the designated field type, and then passing the completed array of fields to the test function. .SS "Field types" A field type describes how a field is to be read and written. A field type is described by a structure: .VS typedef struct test_type { void (*cvt)(const char *buf, dstr *d); void (*dump)(dstr *d, FILE *fp); } test_type; .VE The .B cvt member is a function called to read an input string stored in .B buf and output internal-format data in the dynamic string .IR d . The testrig driver has already stripped of quotes and dealt with backslash escapes. The .B dump member is called to write the internal-format data in dynamic string .I d to the .B stdio stream .IR fp . .PP There are three predefined field types: .TP .B "type_string" The simplest type. The string contents is not interpreted at all. .TP .B "type_hex" The string is interpreted as binary data encoded as hexadecimal. .TP .B "type_int" The string is interpreted as a textual representation of an integer. The integer is written to the dynamic string, and can be read out again with the expression .VS *(int *)d.buf .VE which isn't pretty but does the job. .TP .B "type_long" As for .B type_int but reads and stores a .B long instead. .TP .B "type_ulong" As for .B type_long but reads and stores an .B "unsigned long" instead. .TP .B "type_uint32" As for .B type_int but reads and stores a .B uint32 (see .BR bits (3)) instead. .SH "SEE ALSO" .BR mLib (3). .SH "AUTHOR" Mark Wooding,