chiark / gitweb /
@@@ fltfmt mess
[mLib] / test / tvec-adhoc.h
1 /* -*-c-*-
2  *
3  * Test-vector framework ad-hoc testing interface
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_ADHOC_H
29 #define MLIB_TVEC_ADHOC_H
30
31 #ifdef __cplusplus
32   extern "C" {
33 #endif
34
35 /*----- Header files ------------------------------------------------------*/
36
37 #include <stdarg.h>
38
39 #ifndef MLIB_TVEC_H
40 #  include "tvec.h"
41 #endif
42
43 /*----- Data structures ---------------------------------------------------*/
44
45 extern const struct tvec_config tvec_adhocconfig;
46   /* A special @struct tvec_config@ to use for programs which perform ad-hoc
47    * testing.
48    */
49
50 /*----- Functions provided ------------------------------------------------*/
51
52 /* --- @tvec_adhoc@ --- *
53  *
54  * Arguments:   @struct tvec_state *tv@ = test-vector state
55  *
56  * Returns:     ---
57  *
58  * Use:         Begin ad-hoc testing, i.e., without reading a file of
59  *              test-vector data.
60  *
61  *              The other functions in this section assume that @tvec_adhoc@
62  *              has been called.
63  */
64
65 extern void tvec_adhoc(struct tvec_state */*tv*/);
66
67 /* --- @tvec_begingroup@, @TVEC_BEGINGROUP@ --- *
68  *
69  * Arguments:   @struct tvec_state *tv@ = test-vector state
70  *              @const char *name@ = name for this test group
71  *              @const char *file@, @unsigned @lno@ = calling file and line
72  *
73  * Returns:     ---
74  *
75  * Use:         Begin an ad-hoc test group with the given name.  The @file@
76  *              and @lno@ can be anything, but it's usually best if they
77  *              refer to the source code performing the test: the macro
78  *              @TVEC_BEGINGROUP@ does this automatically.
79  */
80
81 extern void tvec_begingroup(struct tvec_state */*tv*/, const char */*name*/,
82                             const char */*file*/, unsigned /*lno*/);
83 #define TVEC_BEGINGROUP(tv, name)                                       \
84         do tvec_begingroup(tv, name, __FILE__, __LINE__); while (0)
85
86 /* --- @tvec_endgroup@ --- *
87  *
88  * Arguments:   @struct tvec_state *tv@ = test-vector state
89  *
90  * Returns:     ---
91  *
92  * Use:         End an ad-hoc test group.  The statistics are updated and the
93  *              outcome is reported to the output formatter.
94  */
95
96 extern void tvec_endgroup(struct tvec_state */*tv*/);
97
98 /* --- @TVEC_TESTGROUP@, @TVEC_TESTGROUP_TAG@ --- *
99  *
100  * Arguments:   @tag@ = label-disambiguation tag
101  *              @const struct tvec_state *tv = test-vector state
102  *              @const char *name@ = test-group name
103  *
104  * Returns:     ---
105  *
106  * Use:         Control-structure macro: @TVEC_TESTGROUP(tv, name) stmt@
107  *              establishes a test group with the given @name@ (attributing
108  *              it to the source file and lie number), executes @stmt@, and
109  *              ends the test group.  If @stmt@ invokes @break@ then the test
110  *              group is skipped.  @TVEC_TESTGROUP_TAG@ is the same, with an
111  *              additional @tag@ argument for use in higher-level macros.
112  */
113
114 #define TVEC_TESTGROUP_TAG(tag, tv, name)                               \
115         MC_WRAP(tag##__around,                                          \
116           { TVEC_BEGINGROUP(tv, name); },                               \
117           { tvec_endgroup(tv); },                                       \
118           { if (!((tv)->f&TVSF_SKIP)) tvec_skipgroup(tv, 0);            \
119             tvec_endgroup(tv); })
120 #define TVEC_TESTGROUP(tv, name) TVEC_TESTGROUP_TAG(grp, tv, name)
121
122 /* --- @tvec_begintest@, @TVEC_BEGINTEST@ --- *
123  *
124  * Arguments:   @struct tvec_state *tv@ = test-vector state
125  *              @const char *file@, @unsigned @lno@ = calling file and line
126  *
127  * Returns:     ---
128  *
129  * Use:         Begin an ad-hoc test case.  The @file@ and @lno@ can be
130  *              anything, but it's usually best if they refer to the source
131  *              code performing the test: the macro @TVEC_BEGINGROUP@ does
132  *              this automatically.
133  */
134
135 extern void tvec_begintest(struct tvec_state */*tv*/,
136                            const char */*file*/, unsigned /*lno*/);
137 #define TVEC_BEGINTEST(tv)                                              \
138         do tvec_begintest(tv, __FILE__, __LINE__); while (0)
139
140 /* --- @tvec_endtest@ --- *
141  *
142  * Arguments:   @struct tvec_state *tv@ = test-vector state
143  *
144  * Returns:     ---
145  *
146  * Use:         End an ad-hoc test case,  The statistics are updated and the
147  *              outcome is reported to the output formatter.
148  */
149
150 extern void tvec_endtest(struct tvec_state */*tv*/);
151
152 /* --- @TVEC_TEST@, @TVEC_TEST_TAG@ --- *
153  *
154  * Arguments:   @tag@ = label-disambiguation tag
155  *              @struct tvec_test *t@ = space for a test definition
156  *
157  * Returns:     ---
158  *
159  * Use:         Control-structure macro: @TVEC_TEST(tv) stmt@ begins a test
160  *              case, executes @stmt@, and ends the test case.  If @stmt@
161  *              invokes @break@ then the test case is skipped.
162  *              @TVEC_TEST_TAG@ is the same, with an additional @tag@ argumet
163  *              for use in higher-level macros.
164  */
165
166 #define TVEC_TEST_TAG(tag, tv)                                          \
167         MC_WRAP(tag##__around,                                          \
168           { TVEC_BEGINTEST(tv); },                                      \
169           { tvec_endtest(tv); },                                        \
170           { if ((tv)->f&TVSF_ACTIVE) tvec_skip((tv), 0);                \
171             tvec_endtest(tv); })
172 #define TVEC_TEST(tv) TVEC_TEST_TAG(test, tv)
173
174 /* --- @tvec_claim@, @tvec_claim_v@, @TVEC_CLAIM@ --- *
175  *
176  * Arguments:   @struct tvec_state *tv@ = test-vector state
177  *              @int ok@ = a flag
178  *              @const char *file@, @unsigned @lno@ = calling file and line
179  *              @const char *msg@, @va_list *ap@ = message to report on
180  *                      failure
181  *
182  * Returns:     The value @ok@.
183  *
184  * Use:         Check that a claimed condition holds, as (part of) a test.
185  *              If no test case is underway (i.e., if @TVSF_OPEN@ is reset in
186  *              @tv->f@), then a new test case is begun and ended.  The
187  *              @file@ and @lno@ are passed to the output formatter to be
188  *              reported in case of a failure.  If @ok@ is nonzero, then
189  *              nothing else happens; so, in particular, if @tvec_claim@
190  *              established a new test case, then the test case succeeds.  If
191  *              @ok@ is zero, then a failure is reported, quoting @msg@.
192  *
193  *              The @TVEC_CLAIM@ macro is similar, only it (a) identifies the
194  *              file and line number of the call site automatically, and (b)
195  *              implicitly quotes the source text of the @ok@ condition in
196  *              the failure message.
197  */
198
199 extern PRINTF_LIKE(5, 6)
200   int tvec_claim(struct tvec_state */*tv*/, int /*ok*/,
201                  const char */*file*/, unsigned /*lno*/,
202                  const char */*msg*/, ...);
203 extern int tvec_claim_v(struct tvec_state */*tv*/, int /*ok*/,
204                         const char */*file*/, unsigned /*lno*/,
205                         const char */*msg*/, va_list */*ap*/);
206 #define TVEC_CLAIM(tv, cond)                                            \
207         (tvec_claim(tv, !!(cond), __FILE__, __LINE__, "%s untrue", #cond))
208
209 /* --- @tvec_claimeq@ --- *
210  *
211  * Arguments:   @struct tvec_state *tv@ = test-vector state
212  *              @const struct tvec_regty *ty@ = register type
213  *              @const union tvec_misc *arg@ = register type argument
214  *              @const char *file@, @unsigned @lno@ = calling file and line
215  *              @const char *expr@ = the expression to quote on failure
216  *
217  * Returns:     Nonzero if the input and output values of register 0 are
218  *              equal, zero if they differ.
219  *
220  * Use:         Check that the input and output values of register 0 are
221  *              equal (according to the register type @ty@).  As for
222  *              @tvec_claim@ above, a test case is automatically begun and
223  *              ended if none is already underway.  If the values are
224  *              unequal, then @tvec_fail@ is called, quoting @expr@, and the
225  *              mismatched values are dumped.
226  *
227  *              This function is not expected to be called directly, but
228  *              through type-specific wrapper functions or macros such as
229  *              @TVEC_CLAIMEQ_INT@.
230  */
231
232 extern int tvec_claimeq(struct tvec_state */*tv*/,
233                         const struct tvec_regty */*ty*/,
234                         const union tvec_misc */*arg*/,
235                         const char */*file*/, unsigned /*lno*/,
236                         const char */*expr*/);
237
238 /*----- That's all, folks -------------------------------------------------*/
239
240 #ifdef __cplusplus
241   }
242 #endif
243
244 #endif