etc/services - sync with NetBSD-8
[minix.git] / external / bsd / bind / dist / contrib / idn / idnkit-1.0-src / lib / tests / testsuite.c
blobe626acc0487d0e1819b98fd5aa316f2aad888947
1 /* $NetBSD: testsuite.c,v 1.3 2014/12/10 04:37:56 christos Exp $ */
3 #ifndef lint
4 static char *rcsid = "$Id";
5 #endif
7 /*
8 * Copyright (c) 2002 Japan Network Information Center.
9 * All rights reserved.
11 * By using this file, you agree to the terms and conditions set forth bellow.
13 * LICENSE TERMS AND CONDITIONS
15 * The following License Terms and Conditions apply, unless a different
16 * license is obtained from Japan Network Information Center ("JPNIC"),
17 * a Japanese association, Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda,
18 * Chiyoda-ku, Tokyo 101-0047, Japan.
20 * 1. Use, Modification and Redistribution (including distribution of any
21 * modified or derived work) in source and/or binary forms is permitted
22 * under this License Terms and Conditions.
24 * 2. Redistribution of source code must retain the copyright notices as they
25 * appear in each source code file, this License Terms and Conditions.
27 * 3. Redistribution in binary form must reproduce the Copyright Notice,
28 * this License Terms and Conditions, in the documentation and/or other
29 * materials provided with the distribution. For the purposes of binary
30 * distribution the "Copyright Notice" refers to the following language:
31 * "Copyright (c) 2000-2002 Japan Network Information Center. All rights reserved."
33 * 4. The name of JPNIC may not be used to endorse or promote products
34 * derived from this Software without specific prior written approval of
35 * JPNIC.
37 * 5. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY JPNIC
38 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
39 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
40 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JPNIC BE LIABLE
41 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
42 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
43 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
44 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
45 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
46 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
47 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
50 #include <stddef.h>
51 #include <stdio.h>
52 #include <stdlib.h>
53 #include <string.h>
54 #include <assert.h>
56 #include <idn/result.h>
57 #include <idn/ucs4.h>
58 #include <testsuite.h>
60 typedef struct idn_testcase *idn_testcase_t;
62 struct idn_testcase {
63 char *title;
64 idn_testsuite_testproc_t proc;
67 struct idn_testsuite {
68 idn_testcase_t testcases;
69 int ntestcases;
70 int testcase_size;
72 int npassed;
73 int nfailed;
74 int nskipped;
75 idn_testcase_t current_testcase;
76 idn_teststatus_t current_status;
78 idn_testsuite_msgproc_t msgproc;
79 int verbose;
82 #define INITIAL_TESTCASE_SIZE 16
83 #define INITIAL_SETUP_SIZE 4
84 #define INITIAL_TEARDOWN_SIZE 4
86 static void run_internal(idn_testsuite_t ctx, char *titles[]);
87 static char *make_hex_string(const char *string);
88 static char *make_hex_ucs4string(const unsigned long *string);
89 static void put_failure_message(idn_testsuite_t ctx, const char *msg,
90 const char *file, int lineno);
91 static void idn_testsuite_msgtostderr(const char *msg);
93 int
94 idn_testsuite_create(idn_testsuite_t *ctxp) {
95 idn_testsuite_t ctx = NULL;
97 assert(ctxp != NULL);
99 ctx = (idn_testsuite_t) malloc(sizeof(struct idn_testsuite));
100 if (ctx == NULL)
101 goto error;
103 ctx->testcases = NULL;
104 ctx->ntestcases = 0;
105 ctx->testcase_size = 0;
106 ctx->npassed = 0;
107 ctx->nfailed = 0;
108 ctx->nskipped = 0;
109 ctx->current_testcase = NULL;
110 ctx->current_status = idn_teststatus_pass;
111 ctx->msgproc = NULL;
112 ctx->verbose = 0;
114 ctx->testcases = (idn_testcase_t) malloc(sizeof(struct idn_testcase)
115 * INITIAL_TESTCASE_SIZE);
116 if (ctx->testcases == NULL)
117 goto error;
118 ctx->testcase_size = INITIAL_TESTCASE_SIZE;
120 *ctxp = ctx;
121 return (1);
123 error:
124 if (ctx != NULL)
125 free(ctx->testcases);
126 free(ctx);
127 return (0);
130 void
131 idn_testsuite_destroy(idn_testsuite_t ctx) {
132 int i;
134 assert(ctx != NULL);
136 for (i = 0; i < ctx->ntestcases; i++)
137 free(ctx->testcases[i].title);
139 free(ctx->testcases);
140 free(ctx);
144 idn_testsuite_addtestcase(idn_testsuite_t ctx, const char *title,
145 idn_testsuite_testproc_t proc) {
146 char *dup_title = NULL;
147 idn_testcase_t new_buffer = NULL;
148 idn_testcase_t new_testcase;
149 int new_size;
151 assert(ctx != NULL && title != NULL && proc != NULL);
153 dup_title = (char *)malloc(strlen(title) + 1);
154 if (dup_title == NULL)
155 goto error;
156 strcpy(dup_title, title);
158 if (ctx->ntestcases == ctx->testcase_size) {
159 new_size = ctx->testcase_size + INITIAL_TESTCASE_SIZE;
160 new_buffer = (idn_testcase_t)
161 realloc(ctx->testcases,
162 sizeof(struct idn_testcase) * new_size);
163 if (new_buffer == NULL)
164 goto error;
165 ctx->testcases = new_buffer;
166 ctx->testcase_size = new_size;
169 new_testcase = ctx->testcases + ctx->ntestcases;
170 new_testcase->title = dup_title;
171 new_testcase->proc = proc;
172 ctx->ntestcases++;
173 return (1);
175 error:
176 free(dup_title);
177 free(new_buffer);
178 return (0);
182 idn_testsuite_ntestcases(idn_testsuite_t ctx) {
183 assert(ctx != NULL);
184 return (ctx->ntestcases);
187 void
188 idn_testsuite_setverbose(idn_testsuite_t ctx) {
189 assert(ctx != NULL);
190 ctx->verbose = 1;
193 void
194 idn_testsuite_unsetverbose(idn_testsuite_t ctx) {
195 assert(ctx != NULL);
196 ctx->verbose = 0;
199 static void
200 run_internal(idn_testsuite_t ctx, char *titles[]) {
201 int i, j;
202 int run_testcase;
203 const char *status;
205 assert(ctx != NULL);
207 ctx->npassed = 0;
208 ctx->nfailed = 0;
209 ctx->nskipped = 0;
211 for (i = 0; i < ctx->ntestcases; i++) {
212 ctx->current_testcase = ctx->testcases + i;
213 ctx->current_status = idn_teststatus_pass;
215 if (titles == NULL)
216 run_testcase = 1;
217 else {
218 run_testcase = 0;
219 for (j = 0; titles[j] != NULL; j++) {
220 if (strcmp(ctx->current_testcase->title,
221 titles[j]) == 0) {
222 run_testcase = 1;
223 break;
228 if (!run_testcase) {
229 ctx->nskipped++;
230 continue;
232 if (ctx->verbose) {
233 fprintf(stderr, "start testcase %d: %s\n", i + 1,
234 ctx->testcases[i].title);
236 (ctx->testcases[i].proc)(ctx);
237 status = idn_teststatus_tostring(ctx->current_status);
238 if (ctx->verbose) {
239 fprintf(stderr, "end testcase %d: %s\n", i + 1,
240 status);
243 switch (ctx->current_status) {
244 case idn_teststatus_pass:
245 ctx->npassed++;
246 break;
247 case idn_teststatus_fail:
248 ctx->nfailed++;
249 break;
250 case idn_teststatus_skip:
251 ctx->nskipped++;
252 break;
257 void
258 idn_testsuite_runall(idn_testsuite_t ctx) {
259 assert(ctx != NULL);
260 run_internal(ctx, NULL);
263 void
264 idn_testsuite_run(idn_testsuite_t ctx, char *titles[]) {
265 assert(ctx != NULL && titles != NULL);
266 run_internal(ctx, titles);
270 idn_testsuite_npassed(idn_testsuite_t ctx) {
271 assert(ctx != NULL);
272 return (ctx->npassed);
276 idn_testsuite_nfailed(idn_testsuite_t ctx) {
277 assert(ctx != NULL);
278 return (ctx->nfailed);
282 idn_testsuite_nskipped(idn_testsuite_t ctx) {
283 assert(ctx != NULL);
284 return (ctx->nskipped);
287 idn_teststatus_t
288 idn_testsuite_getstatus(idn_testsuite_t ctx) {
289 assert(ctx != NULL);
290 return (ctx->current_status);
293 void
294 idn_testsuite_setstatus(idn_testsuite_t ctx, idn_teststatus_t status) {
295 assert(ctx != NULL);
296 assert(status == idn_teststatus_pass ||
297 status == idn_teststatus_fail ||
298 status == idn_teststatus_skip);
300 ctx->current_status = status;
303 const char *
304 idn_teststatus_tostring(idn_teststatus_t status) {
305 assert(status == idn_teststatus_pass ||
306 status == idn_teststatus_fail ||
307 status == idn_teststatus_skip);
309 switch (status) {
310 case idn_teststatus_pass:
311 return "pass";
312 break;
313 case idn_teststatus_fail:
314 return "failed";
315 break;
316 case idn_teststatus_skip:
317 return "skipped";
318 break;
321 return "unknown";
324 void
325 idn_testsuite_assert(idn_testsuite_t ctx, const char *msg,
326 const char *file, int lineno) {
327 assert(ctx != NULL && msg != NULL && file != NULL);
329 if (idn_testsuite_getstatus(ctx) != idn_teststatus_pass)
330 return;
331 idn_testsuite_setstatus(ctx, idn_teststatus_fail);
332 put_failure_message(ctx, msg, file, lineno);
335 void
336 idn_testsuite_assertint(idn_testsuite_t ctx, int gotten, int expected,
337 const char *file, int lineno) {
338 char msg[256]; /* large enough */
340 assert(ctx != NULL && file != NULL);
342 if (idn_testsuite_getstatus(ctx) != idn_teststatus_pass)
343 return;
344 if (expected == gotten)
345 return;
346 idn_testsuite_setstatus(ctx, idn_teststatus_fail);
348 sprintf(msg, "`%d' expected, but got `%d'", expected, gotten);
349 put_failure_message(ctx, msg, file, lineno);
352 void
353 idn_testsuite_assertstring(idn_testsuite_t ctx,
354 const char *gotten, const char *expected,
355 const char *file, int lineno) {
356 char *expected_hex = NULL;
357 char *gotten_hex = NULL;
358 char *msg;
360 assert(ctx != NULL && gotten != NULL && expected != NULL &&
361 file != NULL);
363 if (idn_testsuite_getstatus(ctx) != idn_teststatus_pass)
364 return;
365 if (strcmp(expected, gotten) == 0)
366 return;
367 idn_testsuite_setstatus(ctx, idn_teststatus_fail);
369 msg = (char *)malloc(strlen(expected) * 4 + strlen(gotten) * 4 + 32);
370 expected_hex = make_hex_string(expected);
371 gotten_hex = make_hex_string(gotten);
372 if (msg == NULL || expected_hex == NULL || gotten_hex == NULL) {
373 msg = "";
374 } else {
375 sprintf(msg, "`%s' expected, but got `%s'",
376 expected_hex, gotten_hex);
379 put_failure_message(ctx, msg, file, lineno);
381 free(msg);
382 free(expected_hex);
383 free(gotten_hex);
386 void
387 idn_testsuite_assertptr(idn_testsuite_t ctx, const void *gotten,
388 const void *expected, const char *file, int lineno) {
389 char *msg;
391 assert(ctx != NULL && file != NULL);
393 if (idn_testsuite_getstatus(ctx) != idn_teststatus_pass)
394 return;
395 if (expected == gotten)
396 return;
397 idn_testsuite_setstatus(ctx, idn_teststatus_fail);
399 if (expected == NULL)
400 msg = "NULL expected, but got non-NULL";
401 else if (gotten == NULL)
402 msg = "non-NULL expected, but got NULL";
403 else
404 msg = "expected pointer != gotten pointer";
405 put_failure_message(ctx, msg, file, lineno);
408 void
409 idn_testsuite_assertptrne(idn_testsuite_t ctx,
410 const void *gotten, const void *unexpected,
411 const char *file, int lineno) {
412 char *msg;
414 assert(ctx != NULL && file != NULL);
416 if (idn_testsuite_getstatus(ctx) != idn_teststatus_pass)
417 return;
418 if (unexpected != gotten)
419 return;
420 idn_testsuite_setstatus(ctx, idn_teststatus_fail);
422 if (unexpected == NULL)
423 msg = "non-NULL unexpected, but got NULL";
424 else if (gotten == NULL)
425 msg = "non-NULL expected, but got NULL";
426 else
427 msg = "expected pointer == gotten pointer";
428 put_failure_message(ctx, msg, file, lineno);
431 void
432 idn_testsuite_assertresult(idn_testsuite_t ctx,
433 idn_result_t gotten, idn_result_t expected,
434 const char *file, int lineno) {
435 char msg[256]; /* large enough */
437 assert(ctx != NULL && file != NULL);
439 if (idn_testsuite_getstatus(ctx) != idn_teststatus_pass)
440 return;
441 if (expected == gotten)
442 return;
443 idn_testsuite_setstatus(ctx, idn_teststatus_fail);
445 sprintf(msg, "`%s' expected, but got `%s'",
446 idn_result_tostring(expected), idn_result_tostring(gotten));
447 put_failure_message(ctx, msg, file, lineno);
450 void
451 idn_testsuite_assertucs4string(idn_testsuite_t ctx,
452 const unsigned long *gotten,
453 const unsigned long *expected,
454 const char *file, int lineno) {
455 char *expected_hex = NULL;
456 char *gotten_hex = NULL;
457 char *msg;
459 assert(ctx != NULL && gotten != NULL && expected != NULL &&
460 file != NULL);
462 if (idn_testsuite_getstatus(ctx) != idn_teststatus_pass)
463 return;
464 if (idn_ucs4_strcmp(expected, gotten) == 0)
465 return;
466 idn_testsuite_setstatus(ctx, idn_teststatus_fail);
468 msg = (char *)malloc(idn_ucs4_strlen(expected) * 8 +
469 idn_ucs4_strlen(gotten) * 8 + 32);
470 expected_hex = make_hex_ucs4string(expected);
471 gotten_hex = make_hex_ucs4string(gotten);
472 if (msg == NULL || expected_hex == NULL || gotten_hex == NULL) {
473 msg = "";
474 } else {
475 sprintf(msg, "`%s' expected, but got `%s'",
476 expected_hex, gotten_hex);
479 put_failure_message(ctx, msg, file, lineno);
481 free(msg);
482 free(expected_hex);
483 free(gotten_hex);
486 static char *
487 make_hex_string(const char *string) {
488 static const char hex[] = {"0123456789abcdef"};
489 char *hex_string;
490 const char *src;
491 char *dst;
493 hex_string = (char *)malloc((strlen(string)) * 4 + 1);
494 if (hex_string == NULL)
495 return NULL;
497 for (src = string, dst = hex_string; *src != '\0'; src++) {
498 if (0x20 <= *src && *src <= 0x7e && *src != '\\') {
499 *dst++ = *src;
500 } else {
501 *dst++ = '\\';
502 *dst++ = 'x';
503 *dst++ = hex[*(const unsigned char *)src >> 4];
504 *dst++ = hex[*src & 0x0f];
507 *dst = '\0';
509 return hex_string;
512 #define UCS4_MAX 0x10fffffUL
514 static char *
515 make_hex_ucs4string(const unsigned long *string) {
516 static const char hex[] = {"0123456789abcdef"};
517 char *hex_string;
518 const unsigned long *src;
519 char *dst;
521 hex_string = (char *)malloc((idn_ucs4_strlen(string)) * 8 + 1);
522 if (hex_string == NULL)
523 return NULL;
525 for (src = string, dst = hex_string; *src != '\0'; src++) {
526 if (0x20 <= *src && *src <= 0x7e && *src != '\\') {
527 *dst++ = *src;
528 } else if (*src <= UCS4_MAX) {
529 *dst++ = '\\';
530 *dst++ = 'u';
531 if (*src >= 0x100000) {
532 *dst++ = hex[(*src >> 20) & 0x0f];
534 if (*src >= 0x10000) {
535 *dst++ = hex[(*src >> 16) & 0x0f];
537 *dst++ = hex[(*src >> 12) & 0x0f];
538 *dst++ = hex[(*src >> 8) & 0x0f];
539 *dst++ = hex[(*src >> 4) & 0x0f];
540 *dst++ = hex[*src & 0x0f];
541 } else {
542 *dst++ = '\\';
543 *dst++ = 'u';
544 *dst++ = '?';
545 *dst++ = '?';
546 *dst++ = '?';
547 *dst++ = '?';
550 *dst = '\0';
552 return hex_string;
555 static void
556 put_failure_message(idn_testsuite_t ctx, const char *msg, const char *file,
557 int lineno) {
558 idn_testsuite_msgproc_t proc;
559 char buffer[256];
560 const char *title;
562 proc = (ctx->msgproc == NULL) ?
563 idn_testsuite_msgtostderr : ctx->msgproc;
564 title = (ctx->current_testcase != NULL &&
565 ctx->current_testcase->title != NULL) ?
566 ctx->current_testcase->title : "anonymous";
568 sprintf(buffer, "%.100s: In test `%.100s':", file, title);
569 (*proc)(buffer);
571 sprintf(buffer, "%.100s:%d: failed (%.100s)", file, lineno, msg);
572 (*proc)(buffer);
576 static void
577 idn_testsuite_msgtostderr(const char *msg) {
578 fputs(msg, stderr);
579 fputc('\n', stderr);