Coverage Report

Created: 2025-07-12 06:21

/src/libcups/cups/test-internal.h
Line
Count
Source (jump to first uncovered line)
1
//
2
// Unit test header for C/C++ programs.
3
//
4
// Copyright © 2021-2022 by Michael R Sweet.
5
//
6
// Redistribution and use in source and binary forms, with or without
7
// modification, are permitted provided that the following conditions are met:
8
//
9
// 1. Redistributions of source code must retain the above copyright notice,
10
//    this list of conditions and the following disclaimer.
11
// 2. Redistributions in binary form must reproduce the above copyright notice,
12
//    this list of conditions and the following disclaimer in the documentation
13
//    and/or other materials provided with the distribution.
14
//
15
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
19
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25
// POSSIBILITY OF SUCH DAMAGE.
26
//
27
28
#ifndef TEST_H
29
#  define TEST_H
30
#  include <stdio.h>
31
#  include <stdlib.h>
32
#  include <stdarg.h>
33
#  include <stdbool.h>
34
#  include <string.h>
35
#  if _WIN32
36
#    define isatty(f) _isatty(f)
37
#  else
38
#    include <unistd.h>
39
#  endif // !_WIN32
40
#  ifdef __cplusplus
41
extern "C" {
42
#  endif // __cplusplus
43
44
45
//
46
// This header implements a simple unit test framework for C/C++ programs.
47
// Inline functions are provided to write a test summary to stdout and the
48
// details to stderr.  This allows unit test programs to output a summary to
49
// stdout with details sent to stderr, e.g.:
50
//
51
//     mytestprogram 2>test.log
52
//
53
// Documentation:
54
//
55
// void testBegin(const char *title, ...)
56
//
57
//     Start a test with a printf-style title message.  "Title:" (the formatted
58
//     title followed by a colon) is output.
59
//
60
// void testEnd(bool pass)
61
//
62
//     End a test without an additional message.  "pass" should be `true` if the
63
//     test passed and `false` otherwise.  "PASS" or "FAIL" is output.
64
//
65
// void testEndMessage(bool pass, const char *message, ...)
66
//
67
//     End a test with an additional printf-style message.  "pass" should be
68
//     `true` if the test passed and `false` otherwise.  "PASS (message)" or
69
//     "FAIL (message)" is output.
70
//
71
// testError(const char *error, ...)
72
//
73
//     Sends a formatted error string to stderr.
74
//
75
// testHexDump(const unsigned char *buffer, size_t bytes)
76
//
77
//     Sends a hex dump of the specified buffer to stderr.
78
//
79
// testMessage(const char *error, ...)
80
//
81
//     Outputs a formatted message string.
82
//
83
// testProgress(void)
84
//
85
//     Shows a progress spinner for long-running tests.
86
//
87
// bool testsPassed
88
//
89
//     This global variable specifies whether all tests have passed (`true`)
90
//     or one or more have failed (`false`).
91
//
92
93
static bool testsPassed = true;   // All tests passed?
94
static int test_progress;   // Current progress
95
static char test_title[1024] = "";  // Current test title
96
97
98
// Start a test
99
static inline void
100
testBegin(const char *title, ...) // I - printf-style title string
101
0
{
102
0
  va_list ap;     // Pointer to additional arguments
103
0
104
0
105
0
  // Format the title string
106
0
  va_start(ap, title);
107
0
  vsnprintf(test_title, sizeof(test_title), title, ap);
108
0
  va_end(ap);
109
0
110
0
  // Send the title to stdout and stderr...
111
0
  test_progress = 0;
112
0
113
0
  printf("%s: ", test_title);
114
0
  fflush(stdout);
115
0
116
0
  if (!isatty(2))
117
0
    fprintf(stderr, "%s: ", test_title);
118
0
}
119
120
121
// End a test with no additional information
122
static inline void
123
testEnd(bool pass)      // I - `true` if the test passed, `false` otherwise
124
0
{
125
0
  // Send the test result to stdout and stderr
126
0
  if (test_progress)
127
0
    putchar('\b');
128
0
129
0
  if (!pass)
130
0
    testsPassed = false;
131
0
132
0
  puts(pass ? "PASS" : "FAIL");
133
0
  if (!isatty(2))
134
0
    fputs(pass ? "PASS\n" : "FAIL\n", stderr);
135
0
136
0
  test_title[0] = '\0';
137
0
}
138
139
140
// End a test with no additional information
141
static inline void
142
testEndMessage(bool       pass,   // I - `true` if the test passed, `false` otherwise
143
               const char *message, ...)// I - printf-style message
144
0
{
145
0
  char    buffer[1024];   // Formatted title string
146
0
  va_list ap;     // Pointer to additional arguments
147
0
148
0
149
0
  // Format the title string
150
0
  va_start(ap, message);
151
0
  vsnprintf(buffer, sizeof(buffer), message, ap);
152
0
  va_end(ap);
153
0
154
0
  // Send the test result to stdout and stderr
155
0
  if (test_progress)
156
0
    putchar('\b');
157
0
158
0
  printf(pass ? "PASS (%s)\n" : "FAIL (%s)\n", buffer);
159
0
  if (!isatty(2))
160
0
    fprintf(stderr, pass ? "PASS (%s)\n" : "FAIL (%s)\n", buffer);
161
0
162
0
  test_title[0] = '\0';
163
0
}
164
165
166
// Show/update a progress spinner
167
static inline void
168
testProgress(void)
169
0
{
170
0
  if (test_progress)
171
0
    putchar('\b');
172
0
  putchar("-\\|/"[test_progress & 3]);
173
0
  fflush(stdout);
174
0
175
0
  test_progress ++;
176
0
}
177
178
179
// Show an error to stderr...
180
static inline void
181
testError(const char *error, ...) // I - printf-style error string
182
0
{
183
0
  char    buffer[1024];   // Formatted title string
184
0
  va_list ap;     // Pointer to additional arguments
185
0
186
0
187
0
  // Format the error string
188
0
  va_start(ap, error);
189
0
  vsnprintf(buffer, sizeof(buffer), error, ap);
190
0
  va_end(ap);
191
0
192
0
  // Send the error to stderr...
193
0
  fprintf(stderr, "%s\n", buffer);
194
0
195
0
  if (test_title[0])
196
0
    fprintf(stderr, "%s: ", test_title);
197
0
}
198
199
200
// Show a message to stdout and stderr...
201
static inline void
202
testMessage(const char *error, ...) // I - printf-style error string
203
0
{
204
0
  char    buffer[1024];   // Formatted title string
205
0
  va_list ap;     // Pointer to additional arguments
206
0
207
0
208
0
  // Format the error string
209
0
  va_start(ap, error);
210
0
  vsnprintf(buffer, sizeof(buffer), error, ap);
211
0
  va_end(ap);
212
0
213
0
  // Send the message to stdout and stderr too if needed...
214
0
  printf("%s\n", buffer);
215
0
  if (test_title[0])
216
0
  {
217
0
    printf("%s: ", test_title);
218
0
    fflush(stdout);
219
0
  }
220
0
221
0
  if (!isatty(2))
222
0
  {
223
0
    fprintf(stderr, "%s\n", buffer);
224
0
225
0
    if (test_title[0])
226
0
      fprintf(stderr, "%s: ", test_title);
227
0
  }
228
0
}
229
230
231
// Show a hex dump of a buffer to stderr...
232
static inline void
233
testHexDump(const unsigned char *buffer,// I - Buffer
234
            size_t              bytes)  // I - Number of bytes
235
0
{
236
0
  size_t  i, j;     // Looping vars
237
0
  int   ch;     // Current ASCII char
238
0
239
0
240
0
  if (test_title[0])
241
0
    fputs("\n", stderr);
242
0
243
0
  // Show lines of 16 bytes at a time...
244
0
  for (i = 0; i < bytes; i += 16)
245
0
  {
246
0
    // Show the offset...
247
0
    fprintf(stderr, "%04x ", (unsigned)i);
248
0
249
0
    // Then up to 16 bytes in hex...
250
0
    for (j = 0; j < 16; j ++)
251
0
    {
252
0
      if ((i + j) < bytes)
253
0
        fprintf(stderr, " %02x", buffer[i + j]);
254
0
      else
255
0
        fputs("   ", stderr);
256
0
    }
257
0
258
0
    // Then the ASCII representation of the bytes...
259
0
    fputs("  ", stderr);
260
0
261
0
    for (j = 0; j < 16 && (i + j) < bytes; j ++)
262
0
    {
263
0
      ch = buffer[i + j] & 127;
264
0
265
0
      if (ch < ' ' || ch == 127)
266
0
        fputc('.', stderr);
267
0
      else
268
0
        fputc(ch, stderr);
269
0
    }
270
0
271
0
    fputc('\n', stderr);
272
0
  }
273
0
274
0
  if (test_title[0])
275
0
    fprintf(stderr, "%s: ", test_title);
276
0
}
277
278
#  ifdef __cplusplus
279
}
280
#  endif // __cplusplus
281
#endif // !TEST_H