chiark / gitweb /
@@@ fltfmt wip
[mLib] / test / tvec-output.h
1 /* -*-c-*-
2  *
3  * Test-vector framework output machinery
4  *
5  * (c) 2024 Straylight/Edgeware
6  */
7
8 /*----- Licensing notice --------------------------------------------------*
9  *
10  * This file is part of the mLib utilities library.
11  *
12  * mLib is free software: you can redistribute it and/or modify it under
13  * the terms of the GNU Library General Public License as published by
14  * the Free Software Foundation; either version 2 of the License, or (at
15  * your option) any later version.
16  *
17  * mLib is distributed in the hope that it will be useful, but WITHOUT
18  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
19  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
20  * License for more details.
21  *
22  * You should have received a copy of the GNU Library General Public
23  * License along with mLib.  If not, write to the Free Software
24  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
25  * USA.
26  */
27
28 #ifndef MLIB_TVEC_OUTPUT_H
29 #define MLIB_TVEC_OUTPUT_H
30
31 #ifdef __cplusplus
32   extern "C" {
33 #endif
34
35 /*----- Header files ------------------------------------------------------*/
36
37 #ifndef MLIB_TVEC_H
38 #  include "tvec.h"
39 #endif
40
41 /*----- Data structures ---------------------------------------------------*/
42
43 struct tvec_state;
44
45 struct tvec_output {
46   /* An output formatter. */
47
48   const struct tvec_outops *ops;        /* pointer to operations */
49 };
50
51 enum {
52   /* Register output dispositions. */
53
54   TVRD_INPUT,                           /* input-only register */
55   TVRD_OUTPUT,                          /* output-only (input is dead) */
56   TVRD_MATCH,                           /* matching (equal) registers */
57   TVRD_FOUND,                           /* mismatching output register */
58   TVRD_EXPECT,                          /* mismatching input register */
59   TVRD_LIMIT                            /* (number of dispositions) */
60 };
61
62 struct tvec_fallbackoutput {
63   /* Dummy fallback output driver.  This may be useful for fallback output
64    * driver implementations.
65    */
66
67   struct tvec_output _o;
68   struct tvec_state *tv;
69 };
70
71 struct tvec_outops {
72   /* Output operations. */
73
74   void (*bsession)(struct tvec_output */*o*/, struct tvec_state */*tv*/);
75     /* Begin a test session.  The output driver will probably want to
76      * save @tv@, because this isn't provided to any other methods.
77      */
78
79   int (*esession)(struct tvec_output */*o*/);
80     /* End a session, and return the suggested exit code. */
81
82   void (*bgroup)(struct tvec_output */*o*/);
83     /* Begin a test group.  The test group description is @tv->test@. */
84
85   void (*skipgroup)(struct tvec_output */*o*/,
86                     const char */*excuse*/, va_list */*ap*/);
87     /* The group is being skipped; @excuse@ may be null or a format
88      * string explaining why.  The @egroup@ method will not be called
89      * separately.
90      */
91
92   void (*egroup)(struct tvec_output */*o*/);
93     /* End a test group.  At least one test was attempted or @skipgroup@
94      * would have been called instead.  If @tv->curr[TVOUT_LOSE]@ is nonzero
95      * then the test group as a whole failed; otherwise it passed.
96      */
97
98   void (*btest)(struct tvec_output */*o*/);
99     /* Begin a test case. */
100
101   void (*skip)(struct tvec_output */*o*/,
102                const char */*excuse*/, va_list */*ap*/);
103     /* The test case is being skipped; @excuse@ may be null or a format
104      * string explaining why.  The @etest@ function will still be called (so
105      * this works differently from @skipgroup@ and @egroup@).  A test case
106      * can be skipped at most once, and, if skipped, it cannot fail.
107      */
108
109   void (*fail)(struct tvec_output */*o*/,
110                const char */*detail*/, va_list */*ap*/);
111     /* The test case failed.
112      *
113      * The output driver should preferably report the filename (@infile@) and
114      * line number (@test_lno@, not @lno@) for the failing test.
115      *
116      * The @detail@ may be null or a format string describing detail about
117      * how the failing test was run which can't be determined from the
118      * registers; a @detail@ is usually provided when (and only when) the
119      * test environment potentially invokes the test function more than once.
120      *
121      * A single test case can fail multiple times!
122      */
123
124   void (*dumpreg)(struct tvec_output */*o*/,
125                   unsigned /*disp*/, const union tvec_regval */*rv*/,
126                   const struct tvec_regdef */*rd*/);
127     /* Dump a register.  The `disposition' @disp@ explains what condition the
128      * register is in; see @tvec_dumpreg@ and the @TVRD_...@ codes.  The
129      * register value is at @rv@, and its definition, including its type, at
130      * @rd@.  Note that this function may be called on virtual registers
131      * which aren't in either of the register vectors or mentioned by the
132      * test description.  It may also be called with @rv@ null, indicating
133      * that the register is not live.
134      */
135
136   void (*etest)(struct tvec_output */*o*/, unsigned /*outcome*/);
137     /* The test case concluded with the given @outcome@ (one of the
138      * @TVOUT_...@ codes.
139      */
140
141   void (*report)(struct tvec_output */*o*/, unsigned /*level*/,
142                  const char */*msg*/, va_list */*ap*/);
143     /* Report a message.  The driver should ideally report the filename
144      * (@infile@) and line number (@lno@) prompting the error.
145      */
146
147   const void *(*extend)(struct tvec_output */*o*/, const char */*name*/);
148     /* Return a pointer to the output driver's implementation of the
149      * extension @name@, or null.  Typically, the implementation will be a
150      * structure of function pointers, though the details are necessarily
151      * extension-specific.
152      */
153
154   void (*destroy)(struct tvec_output */*o*/);
155     /* Release any resources acquired by the driver. */
156 };
157
158 /*----- Functions provided ------------------------------------------------*/
159
160 /* --- @tvec_outputext@ --- *
161  *
162  * Arguments:   @struct tvec_state *tv@ = test-vector state
163  *              @struct tvec_output **o_out@ = output object
164  *              @struct tvec_fallbackoutput *fo@ = fallback output
165  *                      (uninitialized)
166  *              @const char *ext@ = extension name
167  *              @const void *fops@ = fallback operations
168  *
169  * Returns:     An output extension operations table.
170  *
171  * Use:         Calls the output driver's @extend@ function, passing @ext@ as
172  *              the extension name.  If the output driver recognizes the
173  *              extension, then @*o_out@ is set to the output driver object
174  *              and the driver's extension-operations table is returned.
175  *              Otherwise, a fallback output object is constructed in @*fo@,
176  *              @*o_out@ is set to @&fo->_o@, and @fops@ is returned.  In
177  *              this way, a call to an extension function, passing @*o_out@
178  *              as the output object, will either call the output driver's
179  *              extension implementation or the fallback implementation as
180  *              required.
181  */
182
183 extern const void *tvec_outputext(struct tvec_state */*tv*/,
184                                   struct tvec_output **/*o_out*/,
185                                   struct tvec_fallbackoutput */*fo*/,
186                                   const char */*ext*/, const void */*fops*/);
187
188 /*----- That's all, folks -------------------------------------------------*/
189
190 #ifdef __cplusplus
191   }
192 #endif
193
194 #endif