X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~mdw/git/mLib/blobdiff_plain/8f45ff6cb9a269fc6f8f631908f93b4c8123419c..4aee39a18184ae8595936a03ad254c27d149a0eb:/testrig.3 diff --git a/testrig.3 b/testrig.3 new file mode 100644 index 0000000..b996617 --- /dev/null +++ b/testrig.3 @@ -0,0 +1,244 @@ +.\" -*-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,