| 1 | .\" -*-nroff-*- |
| 2 | .de VS |
| 3 | .sp 1 |
| 4 | .in +5 |
| 5 | .nf |
| 6 | .ft B |
| 7 | .. |
| 8 | .de VE |
| 9 | .ft R |
| 10 | .fi |
| 11 | .in -5 |
| 12 | .sp 1 |
| 13 | .. |
| 14 | .TH testrig 3 "5 June 1999" "Straylight/Edgeware" "mLib utilities library" |
| 15 | .SH NAME |
| 16 | testrig \- generic test rig |
| 17 | .\" @test_run |
| 18 | .SH SYNOPSIS |
| 19 | .nf |
| 20 | .B "#include <mLib/testrig.h>" |
| 21 | |
| 22 | .B "#define TEST_FIELDMAX ..." |
| 23 | |
| 24 | .B "typedef struct {" |
| 25 | .B "\h'4n'unsigned tests, failed;" |
| 26 | .B "} test_results"; |
| 27 | |
| 28 | .B "typedef struct {" |
| 29 | .BI "\h'4n'void (*cvt)(const char *" buf ", dstr *" d ); |
| 30 | .BI "\h'4n'void (*dump)(dstr *" d ", FILE *" fp ); |
| 31 | .B "} test_type"; |
| 32 | |
| 33 | .B "typedef struct {" |
| 34 | .B "\h'4n'const char *name;" |
| 35 | .BI "\h'4n'void (*test)(dstr " dv "[]);" |
| 36 | .B "\h'4n'const test_type *f[TEST_FIELDMAX];" |
| 37 | .B "} test_chunk"; |
| 38 | |
| 39 | .B "typedef struct {" |
| 40 | .B "\h'4n'const char *name;" |
| 41 | .B "\h'4n'const test_chunk *chunks;" |
| 42 | .B "} test_suite"; |
| 43 | |
| 44 | .B "const test_type type_hex;" |
| 45 | .B "const test_type type_string;" |
| 46 | .B "const test_type type_int;" |
| 47 | .B "const test_type type_long;" |
| 48 | .B "const test_type type_ulong;" |
| 49 | .B "const test_type type_uint32;" |
| 50 | |
| 51 | .ds mT \fBint test_do( |
| 52 | .BI "\*(mTconst test_suite " suite [], |
| 53 | .BI "\h'\w'\*(mT'u'FILE *" fp , |
| 54 | .BI "\h'\w'\*(mT'u'test_results *" results ); |
| 55 | .ds mT \fBvoid test_run( |
| 56 | .BI "\*(mTint " argc ", char *" argv [], |
| 57 | .BI "\h'\w'\*(mT'u'const test_chunk " chunk [], |
| 58 | .BI "\h'\w'\*(mT'u'const char *" def ); |
| 59 | .fi |
| 60 | .SH DESCRIPTION |
| 61 | .SS Structure |
| 62 | Test vectors are gathered together into |
| 63 | .I chunks |
| 64 | which should be processed in the same way. Chunks, in turn, are grouped |
| 65 | into |
| 66 | .IR suites . |
| 67 | .SS Functions |
| 68 | The |
| 69 | .B test_do |
| 70 | function runs a collection of tests, as defined by |
| 71 | .IR suite , |
| 72 | given the test vectors in the file |
| 73 | .IR fp . |
| 74 | It returns results in the |
| 75 | .B test_results |
| 76 | structure |
| 77 | .IR results , |
| 78 | which has two members: |
| 79 | .TP |
| 80 | .B "unsigned tests" |
| 81 | counts the number of tests carried out, and |
| 82 | .TP |
| 83 | .B "unsigned failed" |
| 84 | counts the number of tests which failed. |
| 85 | .PP |
| 86 | The function returns negative if there was a system error or the test |
| 87 | vector file was corrupt in some way, zero if all the tests were |
| 88 | successful, or positive if some tests failed. |
| 89 | .PP |
| 90 | The |
| 91 | .B test_run |
| 92 | provides a simple command-line interface to the test system. It is |
| 93 | intended to be called from the |
| 94 | .B main |
| 95 | function of a test rig program to check that a particular function or |
| 96 | suite of functions are running properly. It does not return. The arguments |
| 97 | .I argc |
| 98 | and |
| 99 | .I argv |
| 100 | should just be the arguments given to |
| 101 | .BR main . |
| 102 | The |
| 103 | .I def |
| 104 | argument gives the name of the default file of test vectors to read. |
| 105 | This can be overridden at run-time by passing the program a |
| 106 | .B \-f |
| 107 | command-line option. The |
| 108 | .I chunk |
| 109 | argument is (the address of) an array of |
| 110 | .I "chunk definitions" |
| 111 | describing the layout of the test vector file. |
| 112 | .SS "Test vector file syntax" |
| 113 | Test vector files are mostly free-form. Comments begin with a hash |
| 114 | .RB (` # ') |
| 115 | and extend to the end of the line. Apart from that, newline characters |
| 116 | are just considered to be whitespace. |
| 117 | .PP |
| 118 | Test vector files have the following syntax: |
| 119 | .PP |
| 120 | .I file |
| 121 | ::= |
| 122 | .RI [ suite-header | chunk " ...]" |
| 123 | .br |
| 124 | .I suite-header |
| 125 | ::= |
| 126 | .B suite |
| 127 | .I name |
| 128 | .br |
| 129 | .I chunk |
| 130 | ::= |
| 131 | .I name |
| 132 | .B { |
| 133 | .RI [ test-vector " ...]" |
| 134 | .B } |
| 135 | .br |
| 136 | .I test-vector |
| 137 | ::= |
| 138 | .RI [ value ...] |
| 139 | .B ; |
| 140 | .PP |
| 141 | Briefly in English: a test vector file is divided into chunks, each of |
| 142 | which consists of a textual name and a brace-enclosed list of test |
| 143 | vectors. Each test vector consists of a number of values terminated by |
| 144 | a semicolon. |
| 145 | .PP |
| 146 | A value is either a sequence of |
| 147 | .I "word characters" |
| 148 | (alphanumerics and some other characters) |
| 149 | or a string enclosed in quote marks (double or single). Quoted strings |
| 150 | may contain newlines. In either type of value, a backslash escapes the |
| 151 | following character. |
| 152 | .SS "Suite definitions" |
| 153 | A |
| 154 | .I suite definition |
| 155 | is described by the |
| 156 | .B test_suite |
| 157 | structure. The |
| 158 | .I suite |
| 159 | argument to |
| 160 | .B test_do |
| 161 | is a pointer to an array of these structures, terminated by one with a |
| 162 | null |
| 163 | .BR name . |
| 164 | .SS "Chunk definitions" |
| 165 | A |
| 166 | .I "chunk definition" |
| 167 | describes the format of a named chunk: the number and type of the values |
| 168 | required and the function to call in order to test the system against |
| 169 | that test vector. The array is terminated by a chunk definition whose |
| 170 | name field is a null pointer. |
| 171 | .PP |
| 172 | A chunk definition is described by the |
| 173 | .B test_chunk |
| 174 | structure. The members of this structure are as follows: |
| 175 | .TP |
| 176 | .B "const char *name" |
| 177 | The name of the chunk described by this chunk definition, or null if |
| 178 | this is the termination marker. |
| 179 | .TP |
| 180 | .BI "int (*test)(dstr " dv "[])" |
| 181 | The test function. It is passed an array of dynamic strings, one for |
| 182 | each field, and must return nonzero if the test succeeded or zero if the |
| 183 | test failed. On success, the function should not write anything to |
| 184 | stdout or stderr; on failure, a report of the test arguments should be |
| 185 | emitted to stderr. |
| 186 | .TP |
| 187 | .B "test_type *f[TEST_FIELDMAX]" |
| 188 | Definitions of the fields. This is an array of pointers to |
| 189 | .I "field types" |
| 190 | (see below), terminated by a null pointer. |
| 191 | .PP |
| 192 | When the test driver encounters a chunk it has a definition for, it |
| 193 | reads test vectors one by one, translating each value according to the |
| 194 | designated field type, and then passing the completed array of fields to |
| 195 | the test function. |
| 196 | .SS "Field types" |
| 197 | A field type describes how a field is to be read and written. A field |
| 198 | type is described by a |
| 199 | .B test_type |
| 200 | structure. The |
| 201 | .B cvt |
| 202 | member is a function called to read an input string stored in |
| 203 | .B buf |
| 204 | and output internal-format data in the dynamic string |
| 205 | .IR d . |
| 206 | The testrig driver has already stripped of quotes and dealt with |
| 207 | backslash escapes. |
| 208 | The |
| 209 | .B dump |
| 210 | member is called to write the internal-format data in dynamic string |
| 211 | .I d |
| 212 | to the |
| 213 | .B stdio |
| 214 | stream |
| 215 | .IR fp . |
| 216 | .PP |
| 217 | There are three predefined field types: |
| 218 | .TP |
| 219 | .B "type_string" |
| 220 | The simplest type. The string contents is not interpreted at all. |
| 221 | .TP |
| 222 | .B "type_hex" |
| 223 | The string is interpreted as binary data encoded as hexadecimal. |
| 224 | .TP |
| 225 | .B "type_int" |
| 226 | The string is interpreted as a textual representation of an integer. |
| 227 | The integer is written to the dynamic string, and can be read out again |
| 228 | with the expression |
| 229 | .VS |
| 230 | *(int *)d.buf |
| 231 | .VE |
| 232 | which isn't pretty but does the job. |
| 233 | .TP |
| 234 | .B "type_long" |
| 235 | As for |
| 236 | .B type_int |
| 237 | but reads and stores a |
| 238 | .B long |
| 239 | instead. |
| 240 | .TP |
| 241 | .B "type_ulong" |
| 242 | As for |
| 243 | .B type_long |
| 244 | but reads and stores an |
| 245 | .B "unsigned long" |
| 246 | instead. |
| 247 | .TP |
| 248 | .B "type_uint32" |
| 249 | As for |
| 250 | .B type_int |
| 251 | but reads and stores a |
| 252 | .B uint32 |
| 253 | (see |
| 254 | .BR bits (3)) |
| 255 | instead. |
| 256 | .SH "SEE ALSO" |
| 257 | .BR mLib (3). |
| 258 | .SH "AUTHOR" |
| 259 | Mark Wooding, <mdw@distorted.org.uk> |