diff --git a/convert/BUILD.bazel b/convert/BUILD.bazel index bd2a938..d4445f6 100644 --- a/convert/BUILD.bazel +++ b/convert/BUILD.bazel @@ -48,5 +48,6 @@ cc_test( deps = [ ":convert", "//lib", + "//lib:test", ], ) diff --git a/convert/convert_test.c b/convert/convert_test.c index 325defc..18434a3 100644 --- a/convert/convert_test.c +++ b/convert/convert_test.c @@ -1,12 +1,8 @@ -/* Converter test. */ -#define _XOPEN_SOURCE 500 - #include "convert/convert.h" #include "convert/data.h" #include "lib/test.h" +#include "lib/util.h" -#include -#include #include #include #include @@ -17,55 +13,6 @@ enum kConvertBufferSize = 1024 }; -static int gFailCount; -static char gTestName[128]; - -static void Failf(const char *msg, ...) __attribute__((format(printf, 1, 2))); - -static void Failf(const char *msg, ...) -{ - va_list ap; - - gFailCount++; - fputs("Error: ", stderr); - fputs(gTestName, stderr); - fputs(": ", stderr); - va_start(ap, msg); - vfprintf(stderr, msg, ap); - va_end(ap); - fputc('\n', stderr); - if (gFailCount >= 10) { - exit(1); - } -} - -static const char *const kErrorNames[] = {"ok", "no memory", "bad data"}; - -static const char *ErrorName(ErrorCode err) -{ - if (err < 0 || (int)(sizeof(kErrorNames) / sizeof(*kErrorNames)) <= err) { - Dief("bad error code: %d", err); - } - return kErrorNames[err]; -} - -static void StringPrintf(char *dest, size_t destsz, const char *fmt, ...) - __attribute__((format(printf, 3, 4))); - -static void StringPrintf(char *dest, size_t destsz, const char *fmt, ...) -{ - va_list ap; - int n; - - va_start(ap, fmt); - n = vsnprintf(dest, destsz, fmt, ap); - va_end(ap); - - if (n < 0 || n >= (int)destsz) { - Dief("snprintf: overflow"); - } -} - static UInt8 *gBuffer[3]; static void PrintQuotedString(const UInt8 *buf, int len) @@ -161,19 +108,19 @@ static void TestConverter(const char *name, struct CharmapData data) cf.data = NULL; cr.data = NULL; - StringPrintf(gTestName, sizeof(gTestName), "%s", name); + SetTestNamef(name); /* Load the converter into memory and build the conversion table. */ datap = (void *)data.ptr; datah = &datap; err = ConverterBuild(&cf, datah, data.size, kToUTF8); if (err != 0) { - Failf("ConverterBuild: to UTF-8: %s", ErrorName(err)); + Failf("ConverterBuild: to UTF-8: %s", ErrorDescriptionOrDie(err)); goto done; } err = ConverterBuild(&cr, datah, data.size, kFromUTF8); if (err != 0) { - Failf("ConverterBuild: from UTF-8: %s", ErrorName(err)); + Failf("ConverterBuild: from UTF-8: %s", ErrorDescriptionOrDie(err)); goto done; } @@ -206,8 +153,7 @@ static void TestConverter(const char *name, struct CharmapData data) jmax = 4; } for (j = 1; j <= jmax; j++) { - StringPrintf(gTestName, sizeof(gTestName), "%s reverse i=%d j=%d", - name, i, j); + SetTestNamef("%s reverse i=%d j=%d", name, i, j); st.data = 0; iptr = gBuffer[1]; optr = gBuffer[2]; @@ -237,8 +183,7 @@ static void TestConverter(const char *name, struct CharmapData data) len1 = lblen[0]; /* Input data */ len0 = lblen[i]; /* Expected output */ for (j = 1; j < len1; j++) { - StringPrintf(gTestName, sizeof(gTestName), - "%s %s linebreak %s split=%d", name, + SetTestNamef("%s %s linebreak %s split=%d", name, k == 0 ? "forward" : "backward", kLineBreakName[i], j); st.data = 0; @@ -282,7 +227,7 @@ int main(int argc, char **argv) for (i = 0; i < 3; i++) { buf = malloc(kConvertBufferSize); if (buf == NULL) { - Dief("malloc failed"); + Fatalf("malloc failed"); } gBuffer[i] = buf; } @@ -302,10 +247,5 @@ int main(int argc, char **argv) free(gBuffer[i]); } - if (gFailCount > 0) { - fputs("failed\n", stderr); - return 1; - } - fputs("ok\n", stderr); - return 0; + return TestsDone(); } diff --git a/lib/BUILD.bazel b/lib/BUILD.bazel index 25027e1..fba139a 100644 --- a/lib/BUILD.bazel +++ b/lib/BUILD.bazel @@ -5,14 +5,31 @@ cc_library( name = "lib", srcs = [ "toolbox.c", + "util.c", ], hdrs = [ "defs.h", "endian.h", + "util.h", + ], + copts = COPTS, + visibility = ["//visibility:public"], +) + +cc_library( + name = "test", + testonly = True, + srcs = [ + "test.c", + ], + hdrs = [ "test.h", ], copts = COPTS, visibility = ["//visibility:public"], + deps = [ + ":lib", + ], ) cc_test( @@ -23,5 +40,6 @@ cc_test( copts = COPTS, deps = [ ":lib", + ":test", ], ) diff --git a/lib/endian_test.c b/lib/endian_test.c index 98e824f..27470ec 100644 --- a/lib/endian_test.c +++ b/lib/endian_test.c @@ -1,22 +1,22 @@ #include "lib/endian.h" +#include "lib/test.h" + #include #include #include -static int gDidFail; - -static void Fail(const char *name, UInt32 got, UInt32 expect) +static void EndianFail(const char *name, UInt32 got, UInt32 expect) { fprintf(stderr, "%s = 0x%" PRIx32 ", expect 0x%" PRIx32 "\n", name, got, expect); - gDidFail = 1; + gFailCount++; } -#define CHECK(fn, expect) \ - be = fn(u.i); \ - if (be != expect) { \ - Fail(#fn, be, expect); \ +#define CHECK(fn, expect) \ + be = fn(u.i); \ + if (be != expect) { \ + EndianFail(#fn, be, expect); \ } static void Test16(void) @@ -58,5 +58,5 @@ int main(int argc, char **argv) Test16(); Test32(); - return gDidFail; + return TestsDone(); } diff --git a/lib/test.c b/lib/test.c new file mode 100644 index 0000000..b51a882 --- /dev/null +++ b/lib/test.c @@ -0,0 +1,77 @@ +/* Defined to get vsnprintf. */ +#define _XOPEN_SOURCE 500 + +#include "lib/test.h" +#include "lib/util.h" + +#include +#include +#include +#include + +int gFailCount; + +static char gTestName[256]; + +void SetTestName(const char *name) +{ + size_t n; + + n = strlen(name); + if (n >= sizeof(gTestName) - 1) { + Fatalf("SetTestName: overflow"); + } + memcpy(gTestName, name, n + 1); +} + +void SetTestNamef(const char *fmt, ...) +{ + va_list ap; + int r; + + va_start(ap, fmt); + r = vsnprintf(gTestName, sizeof(gTestName), fmt, ap); + va_end(ap); + + if (r >= (int)sizeof(gTestName)) { + Fatalf("SetTestNamef: overflow"); + } +} + +void Failf(const char *msg, ...) +{ + va_list ap; + + gFailCount++; + fputs("Error: ", stderr); + fputs(gTestName, stderr); + fputs(": ", stderr); + va_start(ap, msg); + vfprintf(stderr, msg, ap); + va_end(ap); + fputc('\n', stderr); + if (gFailCount >= 10) { + exit(1); + } +} + +const char *ErrorDescriptionOrDie(ErrorCode err) +{ + const char *desc; + + desc = ErrorDescription(err); + if (desc == NULL) { + Fatalf("invalid error code: %d", err); + } + return desc; +} + +int TestsDone(void) +{ + if (gFailCount > 0) { + fputs("failed\n", stderr); + return 1; + } + fputs("ok\n", stderr); + return 0; +} diff --git a/lib/test.h b/lib/test.h index a803a16..1949309 100644 --- a/lib/test.h +++ b/lib/test.h @@ -4,11 +4,23 @@ #include "lib/defs.h" -/* Print an error message and exit. */ -void Dief(const char *msg, ...) __attribute__((noreturn, format(printf, 1, 2))); +/* The number of test failures. */ +extern int gFailCount; -/* Print an error message with an error code and exit. */ -void DieErrorf(int errcode, const char *msg, ...) - __attribute__((noreturn, format(printf, 2, 3))); +/* Set the name of the current test. */ +void SetTestName(const char *name); + +/* Set the name of the current test. */ +void SetTestNamef(const char *fmt, ...) __attribute__((format(printf, 1, 2))); + +/* Fail the current test. */ +void Failf(const char *msg, ...) __attribute__((format(printf, 1, 2))); + +/* Return the description of an error code. Fatal error if the error code is + invalid. */ +const char *ErrorDescriptionOrDie(ErrorCode err); + +/* Print information about completed tests and return the status code. */ +int TestsDone(void ); #endif diff --git a/lib/toolbox.c b/lib/toolbox.c index eb00834..aaffb96 100644 --- a/lib/toolbox.c +++ b/lib/toolbox.c @@ -4,31 +4,18 @@ development easier. These are not intended to make it possible to port the converter to non-Mac OS systems. */ #include "lib/defs.h" -#include "lib/test.h" +#include "lib/util.h" -#include -#include #include #include -void Dief(const char *msg, ...) -{ - va_list ap; - fputs("Error: ", stderr); - va_start(ap, msg); - vfprintf(stderr, msg, ap); - va_end(ap); - fputc('\n', stderr); - exit(1); -} - Handle NewHandle(Size byteCount) { Ptr p; Handle h; if (byteCount < 0) { - Dief("NewHandle: byteCount = %ld", byteCount); + Fatalf("NewHandle: byteCount = %ld", byteCount); } p = malloc(byteCount); if (byteCount > 0 && p == NULL) { @@ -55,10 +42,10 @@ Boolean ResizeHandle(Handle h, Size newSize) { Ptr p; if (h == NULL) { - Dief("ResizeHandle: h = NULL"); + Fatalf("ResizeHandle: h = NULL"); } if (newSize < 0) { - Dief("ResizeHandle: newSize = %ld", newSize); + Fatalf("ResizeHandle: newSize = %ld", newSize); } p = realloc(*h, newSize); if (newSize > 0 && p == NULL) { diff --git a/lib/util.c b/lib/util.c new file mode 100644 index 0000000..4c86e13 --- /dev/null +++ b/lib/util.c @@ -0,0 +1,26 @@ +#include "lib/util.h" + +#include +#include +#include + +void Fatalf(const char *msg, ...) +{ + va_list ap; + fputs("Error: ", stderr); + va_start(ap, msg); + vfprintf(stderr, msg, ap); + va_end(ap); + fputc('\n', stderr); + exit(1); +} + +static const char *const kErrorNames[] = {"ok", "no memory", "bad data"}; + +const char *ErrorDescription(ErrorCode err) +{ + if (err < 0 || (int)(sizeof(kErrorNames) / sizeof(*kErrorNames)) <= err) { + return NULL; + } + return kErrorNames[err]; +} diff --git a/lib/util.h b/lib/util.h new file mode 100644 index 0000000..a4c1375 --- /dev/null +++ b/lib/util.h @@ -0,0 +1,13 @@ +#ifndef lib_util_h +#define lib_util_h +#include "lib/defs.h" + +/* Print an error message and exit. */ +void Fatalf(const char *msg, ...) + __attribute__((noreturn, format(printf, 1, 2))); + +/* Return a basic description of the given error code, or NULL if the error code + is unknown. */ +const char *ErrorDescription(ErrorCode err); + +#endif