3 * Test-vector framework ad-hoc testing interface
5 * (c) 2024 Straylight/Edgeware
8 /*----- Licensing notice --------------------------------------------------*
10 * This file is part of the mLib utilities library.
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.
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.
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,
28 #ifndef MLIB_TVEC_ADHOC_H
29 #define MLIB_TVEC_ADHOC_H
35 /*----- Header files ------------------------------------------------------*/
43 /*----- Data structures ---------------------------------------------------*/
45 extern const struct tvec_config tvec_adhocconfig;
46 /* A special @struct tvec_config@ to use for programs which perform ad-hoc
50 /*----- Functions provided ------------------------------------------------*/
52 /* --- @tvec_adhoc@ --- *
54 * Arguments: @struct tvec_state *tv@ = test-vector state
58 * Use: Begin ad-hoc testing, i.e., without reading a file of
61 * The other functions in this section assume that @tvec_adhoc@
65 extern void tvec_adhoc(struct tvec_state */*tv*/);
67 /* --- @tvec_begingroup@, @TVEC_BEGINGROUP@ --- *
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
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.
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)
86 /* --- @tvec_endgroup@ --- *
88 * Arguments: @struct tvec_state *tv@ = test-vector state
92 * Use: End an ad-hoc test group. The statistics are updated and the
93 * outcome is reported to the output formatter.
96 extern void tvec_endgroup(struct tvec_state */*tv*/);
98 /* --- @TVEC_TESTGROUP@, @TVEC_TESTGROUP_TAG@ --- *
100 * Arguments: @tag@ = label-disambiguation tag
101 * @const struct tvec_state *tv = test-vector state
102 * @const char *name@ = test-group name
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.
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)
122 /* --- @tvec_begintest@, @TVEC_BEGINTEST@ --- *
124 * Arguments: @struct tvec_state *tv@ = test-vector state
125 * @const char *file@, @unsigned @lno@ = calling file and line
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.
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)
140 /* --- @tvec_endtest@ --- *
142 * Arguments: @struct tvec_state *tv@ = test-vector state
146 * Use: End an ad-hoc test case, The statistics are updated and the
147 * outcome is reported to the output formatter.
150 extern void tvec_endtest(struct tvec_state */*tv*/);
152 /* --- @TVEC_TEST@, @TVEC_TEST_TAG@ --- *
154 * Arguments: @tag@ = label-disambiguation tag
155 * @struct tvec_test *t@ = space for a test definition
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.
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); \
172 #define TVEC_TEST(tv) TVEC_TEST_TAG(test, tv)
174 /* --- @tvec_claim@, @tvec_claim_v@, @TVEC_CLAIM@ --- *
176 * Arguments: @struct tvec_state *tv@ = test-vector state
178 * @const char *file@, @unsigned @lno@ = calling file and line
179 * @const char *msg@, @va_list *ap@ = message to report on
182 * Returns: The value @ok@.
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@.
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.
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))
209 /* --- @tvec_claimeq@ --- *
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
217 * Returns: Nonzero if the input and output values of register 0 are
218 * equal, zero if they differ.
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.
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@.
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*/);
238 /*----- That's all, folks -------------------------------------------------*/