#include #include #include #ifdef PLAN9 #include "p9limits.h" #else #include #endif /* * $Id: tdp.c,v 1.7 1998/11/10 22:35:28 mhw Exp $ * * Test harness for the print family. This is a bit messy, * basically because I use the preprocessor to paste the * test cases together. This does allow us to run the * same test cases through sprint() and snprint() though. * * It's probably a bad idea to use fprint() to format and * report the error messages, as that is part of the code * being tested. It does let me run this test suite on * Plan 9 to check that my results match theirs. */ static int tests = 0; static int failed = 0; static char buf[8*1024]; static int length; static void start_test_sprint(void) { } static void check_test_sprint(char *expect) { ++tests; if (length != strlen(buf)) { ++failed; fprint(2, "length %d != strlen %d when expecting %s\n", length, strlen(buf), expect); } ++tests; if (strcmp(buf, expect) != 0) { ++failed; fprint(2, "expected %s; got %s\n", expect, buf); } } #ifndef LIMIT #define LIMIT 10 #endif static void start_test_snprint(void) { memset(buf, '#', 10+LIMIT+10); } static void check_test_snprint(char *expect) { int i; ++tests; if (length > LIMIT) { ++failed; fprint(2, "length %d > %d when expecting %s\n", length, LIMIT, expect); } ++tests; for (i = 0; i < 10; ++i) if (buf[i] != '#') { ++failed; fprint(2, "hit lower fencepost when expecting %s\n", expect); break; } ++tests; for (i = 10; i < 10+LIMIT; ) { Rune r; int b; if (buf[i] == 0) break; if (!fullrune(buf+i, 10+LIMIT-i)) break; b = chartorune(&r, buf+i); if (i+b >= 10+LIMIT || (r == Runeerror && b == 1)) break; i += b; } if (strncmp(buf+10, expect, i-10) != 0) { ++failed; fprint(2, "expected %.*s; got %.*s\n", i-10, expect, length, buf+10); } ++tests; for (i = 10+length; i < 10+LIMIT+10; ++i) if (buf[i] != '#') { ++failed; fprint(2, "hit upper fencepost when expecting %s\n", expect); break; } } /* * Pull in some Runes. */ #include "../libXg/latin1.c" typedef struct Point { int x; int y; } Point; typedef struct Rectangle { Point min; Point max; } Rectangle; int Pconv(void *v, Fconv *fp) { char str[50]; va_list ap = v; Point *p = va_arg(ap, Point *); sprint(str, "(%d,%d)", p->x, p->y); strconv(str, fp); return ap-(va_list)v; } int Rconv(void *v, Fconv *fp) { char str[50]; va_list ap = v; Rectangle *r = va_arg(ap, Rectangle *); sprint(str, "(%P,%P)", &r->min, &r->max); strconv(str, fp); return ap-(va_list)v; } int main(void) { Point p; Rectangle r; char expect[8*1024]; ++tests; if (fmtinstall('P', Pconv) != 0) { ++failed; fprint(2, "couldn't install Pconv\n"); } ++tests; if (fmtinstall('R', Rconv) != 0) { ++failed; fprint(2, "couldn't install Rconv\n"); } ++tests; if (fmtinstall(-1, Rconv) != -1) { ++failed; fprint(2, "managed to install conversion routine for bad character\n"); } ++tests; if (fmtinstall(256, Rconv) != -1) { ++failed; fprint(2, "managed to install conversion routine for bad character\n"); } #define A1 buf, #define T(ARGS, EXPECT) \ start_test_sprint(); \ length = sprint ARGS; \ check_test_sprint(EXPECT); #include "tdp-tests.h" #undef A1 #undef T #define A1 buf+10, LIMIT, #define T(ARGS, EXPECT) \ start_test_snprint(); \ length = snprint ARGS; \ check_test_snprint(EXPECT); #include "tdp-tests.h" #undef A1 #undef T if (failed) { fprint(2, "tdp: failed %d of %d tests.\n", failed, tests); return 1; } else { fprint(2, "tdp: passed all %d tests.\n", tests); return 0; } }