chiark / gitweb /
Typo fix.
[disorder] / libtests / test.c
1 /*
2  * This file is part of DisOrder.
3  * Copyright (C) 2005, 2007, 2008 Richard Kettlewell
4  *
5  * This program is free software: you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation, either version 3 of the License, or
8  * (at your option) any later version.
9  * 
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  * 
15  * You should have received a copy of the GNU General Public License
16  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
17  */
18 /** @file libtests/test.c @brief Library tests */
19
20 #include "test.h"
21 #include "version.h"
22 #include <getopt.h>
23
24 /** @brief Count of tests */
25 long long tests;
26
27 /** @brief Count of errors */
28 long long errors;
29
30 /** @brief If set, first error will fail whole test */
31 int fail_first;
32
33 /** @brief Verbose mode */
34 int verbose;
35
36 /** @brief If set, test will return 'skipped' indicator */
37 int skipped;
38
39 /** @brief Count up an error
40  *
41  * If @ref fail_first is set then the test run is aborted.
42  */
43 void count_error(void) {
44   ++errors;
45   if(fail_first)
46     abort();
47 }
48
49 /** @brief Render a string into printable ASCII
50  * @param s String to format
51  * @return Allocated copy of formatted string
52  *
53  * Replaces any non-ASCII characters with a hex escape.
54  */
55 const char *format(const char *s) {
56   struct dynstr d;
57   int c;
58   char buf[10];
59
60   dynstr_init(&d);
61   while((c = (unsigned char)*s++)) {
62     if(c >= ' ' && c <= '~')
63       dynstr_append(&d, c);
64     else {
65       sprintf(buf, "\\x%02X", (unsigned)c);
66       dynstr_append_string(&d, buf);
67     }
68   }
69   dynstr_terminate(&d);
70   return d.vec;
71 }
72
73 /** @brief Format a UTF-32 string into hex
74  * @param s String to format
75  * @return Allocated copy of formatted string
76  *
77  * Returns the hex codes of @p s separated by spaces.
78  */
79 const char *format_utf32(const uint32_t *s) {
80   struct dynstr d;
81   uint32_t c;
82   char buf[64];
83
84   dynstr_init(&d);
85   while((c = *s++)) {
86     sprintf(buf, " %04lX", (long)c);
87     dynstr_append_string(&d, buf);
88   }
89   dynstr_terminate(&d);
90   return d.vec;
91 }
92
93 /** @brief Convert a string of hex codes to a UTF-32 string
94  * @param s String of hex codes, separated by spaces
95  * @return Allocated string, 0-terminated
96  */
97 uint32_t *ucs4parse(const char *s) {
98   struct dynstr_ucs4 d;
99   char *e;
100
101   dynstr_ucs4_init(&d);
102   while(*s) {
103     errno = 0;
104     dynstr_ucs4_append(&d, strtoul(s, &e, 0));
105     if(errno) fatal(errno, "strtoul (%s)", s);
106     s = e;
107   }
108   dynstr_ucs4_terminate(&d);
109   return d.vec;
110 }
111
112 /** @brief Format a string like asprintf()
113  * @param fmt Format string, per printf(3)
114  * @param ... Arguments
115  * @return Formatted string or null pointer on error
116  */
117 const char *do_printf(const char *fmt, ...) {
118   va_list ap;
119   char *s;
120   int rc;
121
122   va_start(ap, fmt);
123   rc = byte_vasprintf(&s, fmt, ap);
124   va_end(ap);
125   if(rc < 0)
126     return 0;
127   return s;
128 }
129
130 /** @brief Jump buffer for exitfn() testing */
131 jmp_buf fatal_env;
132
133 /** @brief exitfn() callback for testing
134  * @param rc Value to return from setjmp()
135  * Jumps to @ref fatal_env
136  */
137 void test_exitfn(int rc) {
138   assert(rc != 0);
139   longjmp(fatal_env, rc);
140 }
141
142 static const struct option options[] = {
143   { "verbose", no_argument, 0, 'v' },
144   { "fail-first", no_argument, 0, 'F' },
145   { "help", no_argument, 0, 'h' },
146   { "version", no_argument, 0, 'V' },
147 };
148
149 /* display usage message and terminate */
150 static void help(void) {
151   xprintf("Usage:\n"
152           "  %s [OPTIONS]\n"
153           "Options:\n"
154           "  --help, -h               Display usage message\n"
155           "  --version, -V            Display version number\n"
156           "  --verbose, -v            Verbose output\n"
157           "  --fail-first, -F         Stop on first failure\n",
158           progname);
159   xfclose(stdout);
160   exit(0);
161 }
162
163 /** @brief Standard test program initialization
164  * @param argc Argument count
165  * @param argv Arguments
166  */
167 void test_init(int argc, char **argv) {
168   int n;
169
170   set_progname(argv);
171   mem_init();
172   while((n = getopt_long(argc, argv, "vFhV", options, 0)) >= 0) {
173     switch(n) {
174     case 'v': verbose = 1; break;
175     case 'F': fail_first = 1; break;
176     case 'h': help();
177     case 'V': version(progname);
178     default: exit(1);
179     }
180   }
181   if(getenv("FAIL_FIRST"))
182     fail_first = 1;
183 }
184
185
186 /*
187 Local Variables:
188 c-basic-offset:2
189 comment-column:40
190 fill-column:79
191 indent-tabs-mode:nil
192 End:
193 */