aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.gitignore2
-rw-r--r--Makefile6
-rw-r--r--test_gen.c114
-rw-r--r--unpack_test.c96
4 files changed, 141 insertions, 77 deletions
diff --git a/.gitignore b/.gitignore
index 64c75c2..981c059 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,2 +1,4 @@
*.o
*_test
+*.inc
+*_gen
diff --git a/Makefile b/Makefile
index 40e1cff..d8037f6 100644
--- a/Makefile
+++ b/Makefile
@@ -1,3 +1,9 @@
# Copyright (C) 2020 Tomasz Kramkowski <tk@the-tk.com>
# SPDX-License-Identifier: MIT
unpack_test: unpack_test.o unpack.o common.o trace.o
+unpack_test.o: unpack_test.c pack.h trace.h common.h unpack_test.inc
+trace.o: trace.c trace.h
+common.o: common.c common.h
+unpack_test.inc: test_gen
+ ./$< >$@
+test_gen: test_gen.o
diff --git a/test_gen.c b/test_gen.c
new file mode 100644
index 0000000..ca46672
--- /dev/null
+++ b/test_gen.c
@@ -0,0 +1,114 @@
+/*
+ * Copyright (C) 2020 Tomasz Kramkowski <tk@the-tk.com>
+ * SPDX-License-Identifier: MIT
+ */
+#include <assert.h>
+#include <ctype.h>
+#include <inttypes.h>
+#include <limits.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdio.h>
+
+struct {
+ enum endian { BIG, LITTLE } e;
+ char *prefix;
+} endian[] = {
+ { BIG, "" },
+ { BIG, ">" },
+ { LITTLE, "<" },
+};
+
+char cchar(char c)
+{
+ if (c == '\0') return c;
+ if (isalnum(c)) return c;
+ return '_';
+}
+
+const char *cname(const char *s)
+{
+ static char ret[100];
+ for (int i = 0; i < 99; i++) {
+ ret[i] = cchar(s[i]);
+ if (s[i] == '\0') break;
+ }
+ return ret;
+}
+
+const char *u2bytes(enum endian e, int n, uintmax_t v)
+{
+ static char b[100];
+ char *p = b;
+
+ assert(n > 0 && n <= 8);
+
+ for (int i = 0; i < n; i++) {
+ p += snprintf(p, b + sizeof(b) - p, "%s0x%x", i == 0 ? "" : ", ",
+ (v >> (e == LITTLE ? i : n - i - 1) * 8) & 0xff);
+ assert(p < b + sizeof(b));
+ }
+
+ return b;
+}
+
+uintmax_t i2u(int n, intmax_t v)
+{
+ if (v >= 0)
+ return v;
+
+ return (UINTMAX_MAX >> (sizeof (uintmax_t) * CHAR_BIT - n * 8)) + v + 1;
+}
+
+const char *i2bytes(enum endian e, int n, intmax_t v)
+{
+ return u2bytes(e, n, i2u(n, v));
+}
+
+void generate_simple(FILE *out, char fmt, const char *type, intmax_t min, uintmax_t max, int size)
+{
+ unsigned char data[8];
+ char *prefix;
+ bool sign;
+
+ sign = islower(fmt);
+ prefix = sign ? "signed" : "unsigned";
+
+ assert(size <= sizeof data);
+
+ fprintf(out, "TEST(%s_%s)\n", prefix, cname(type));
+ fprintf(out, "{\n");
+ fprintf(out, "\t%s %s %c = __LINE__;\n", prefix, type, fmt);
+ for (size_t e = 0; e < sizeof endian / sizeof endian[0]; e++) {
+ for (int i = sign ? -1 : 0; i <= 1; i++) {
+ fprintf(out, "\tCHECK_UNPACK(DATA(%s), \"%s%c\", &%c);\n",
+ i2bytes(endian[e].e, size, i), endian[e].prefix, fmt, fmt);
+ fprintf(out, "\tCHECK_EQUAL(PRIdMAX, (intmax_t)%c, INTMAX_C(%d));\n", fmt, i);
+ }
+ if (sign) {
+ fprintf(out, "\tCHECK_UNPACK(DATA(%s), \"%s%c\", &%c);\n",
+ i2bytes(endian[e].e, size, min), endian[e].prefix, fmt, fmt);
+ fprintf(out, "\tCHECK_EQUAL(PRIdMAX, (intmax_t)%c, INTMAX_C(%" PRIdMAX "));\n", fmt, min);
+ }
+ fprintf(out, "\tCHECK_UNPACK(DATA(%s), \"%s%c\", &%c);\n",
+ u2bytes(endian[e].e, size, max), endian[e].prefix, fmt, fmt);
+ fprintf(out, "\tCHECK_EQUAL(PRIuMAX, (uintmax_t)%c, UINTMAX_C(%" PRIuMAX "));\n", fmt, max);
+ }
+ fprintf(out, "\treturn true;\n");
+ fprintf(out, "}\n");
+}
+
+int main(void)
+{
+ FILE *out = stdout;
+ generate_simple(out, 'b', "char", INTMAX_C( -128), UINTMAX_C( 127), 1);
+ generate_simple(out, 'B', "char", INTMAX_C( 0), UINTMAX_C( 255), 1);
+ generate_simple(out, 'h', "short", INTMAX_C( -32768), UINTMAX_C( 32767), 2);
+ generate_simple(out, 'H', "short", INTMAX_C( 0), UINTMAX_C( 65535), 2);
+ generate_simple(out, 'i', "int", INTMAX_C( -32768), UINTMAX_C( 32767), 2);
+ generate_simple(out, 'I', "int", INTMAX_C( 0), UINTMAX_C( 65535), 2);
+ generate_simple(out, 'l', "long", INTMAX_C( -2147483648), UINTMAX_C( 2147483647), 4);
+ generate_simple(out, 'L', "long", INTMAX_C( 0), UINTMAX_C( 4294967295), 4);
+ generate_simple(out, 'q', "long long", -INTMAX_C(9223372036854775807)-1, UINTMAX_C( 9223372036854775807), 8);
+ generate_simple(out, 'Q', "long long", INTMAX_C( 0), UINTMAX_C(18446744073709551615), 8);
+}
diff --git a/unpack_test.c b/unpack_test.c
index 1dbc4ac..f89cd62 100644
--- a/unpack_test.c
+++ b/unpack_test.c
@@ -2,6 +2,8 @@
* Copyright (C) 2020 Tomasz Kramkowski <tk@the-tk.com>
* SPDX-License-Identifier: MIT
*/
+#include <stdint.h>
+#include <inttypes.h>
#include <stdio.h>
#include <stdbool.h>
@@ -21,91 +23,31 @@ struct test {
#define CHECK(test) if (!(test)) { puts("! " #test); return false; }
#define CHECK_UNPACK(data, fmt, ...) do { \
- enum pack_status s = unpack(data, fmt, __VA_ARGS__); \
- if (s != PACK_OK) { \
- printf(__FILE__ ":%d unpack(" #data ", " #fmt ", ...) -> %s (%d)\n", __LINE__, pack_strerror(s), s); \
+ enum pack_status CHECK_UNPACK_s = unpack(data, fmt, __VA_ARGS__); \
+ if (CHECK_UNPACK_s != PACK_OK) { \
+ printf(__FILE__ ":%d unpack(" #data ", " #fmt ", ...) -> %s (%d)\n", __LINE__, pack_strerror(CHECK_UNPACK_s), CHECK_UNPACK_s); \
return false; \
} \
} while (0)
-#define CHECK_EQUAL(a, b) if (a != b) { printf(__FILE__ ":%d %d != %d\n", __LINE__, a, b); return false; }
+#define CHECK_EQUAL(f, a, b) if (a != b) { printf(__FILE__ ":%d %"f" != %"f"\n", __LINE__, a, b); return false; }
-TEST(schar)
-{
- signed char c = __LINE__;
- fprintf(stderr, "Address of c: %p\n", (void *)&c);
- CHECK_UNPACK(DATA(0), "b", &c);
- CHECK_EQUAL(c, 0);
- CHECK_UNPACK(DATA(1), "b", &c);
- CHECK_EQUAL(c, 1);
- CHECK_UNPACK(DATA(127), "b", &c);
- CHECK_EQUAL(c, 127);
- CHECK_UNPACK(DATA(255), "b", &c);
- CHECK_EQUAL(c, -1);
- CHECK_UNPACK(DATA(128), "b", &c);
- CHECK_EQUAL(c, -128);
- return true;
-}
-
-TEST(uchar)
-{
- unsigned char c = __LINE__;
- fprintf(stderr, "Address of c: %p\n", (void *)&c);
- CHECK_UNPACK(DATA(0), "B", &c);
- CHECK_EQUAL(c, 0);
- CHECK_UNPACK(DATA(1), "B", &c);
- CHECK_EQUAL(c, 1);
- CHECK_UNPACK(DATA(255), "B", &c);
- CHECK_EQUAL(c, 255);
- return true;
-}
-
-TEST(sshort)
-{
- short s = __LINE__;
- fprintf(stderr, "Address of s: %p\n", (void *)&s);
- CHECK_UNPACK(DATA(0, 0), "h", &s);
- CHECK_EQUAL(s, 0);
- CHECK_UNPACK(DATA(0, 0), ">h", &s);
- CHECK_EQUAL(s, 0);
- CHECK_UNPACK(DATA(0, 0), "<h", &s);
- CHECK_EQUAL(s, 0);
- CHECK_UNPACK(DATA(0, 1), "h", &s);
- CHECK_EQUAL(s, 1);
- CHECK_UNPACK(DATA(0, 1), ">h", &s);
- CHECK_EQUAL(s, 1);
- CHECK_UNPACK(DATA(1, 0), "<h", &s);
- CHECK_EQUAL(s, 1);
- CHECK_UNPACK(DATA(0x7f, 0xff), "h", &s);
- CHECK_EQUAL(s, 32767);
- CHECK_UNPACK(DATA(0x7f, 0xff), ">h", &s);
- CHECK_EQUAL(s, 32767);
- CHECK_UNPACK(DATA(0xff, 0x7f), "<h", &s);
- CHECK_EQUAL(s, 32767);
- CHECK_UNPACK(DATA(0xff, 0xff), "h", &s);
- CHECK_EQUAL(s, -1);
- CHECK_UNPACK(DATA(0xff, 0xff), ">h", &s);
- CHECK_EQUAL(s, -1);
- CHECK_UNPACK(DATA(0xff, 0xff), "<h", &s);
- CHECK_EQUAL(s, -1);
- CHECK_UNPACK(DATA(0x80, 0x00), "h", &s);
- CHECK_EQUAL(s, -32768);
- CHECK_UNPACK(DATA(0x80, 0x00), ">h", &s);
- CHECK_EQUAL(s, -32768);
- CHECK_UNPACK(DATA(0x00, 0x80), "<h", &s);
- CHECK_EQUAL(s, -32768);
-}
-
-TEST(ushort)
-{
- unsigned short s;
-}
+#include "unpack_test.inc"
int main(void)
{
+ pack_trace = PACK_TRACE_OFF;
+
struct test tests[] = {
- TEST_ENTRY(schar, "schar unpacking"),
- TEST_ENTRY(uchar, "uchar unpacking"),
- TEST_ENTRY(sshort, "sshort unpacking"),
+ TEST_ENTRY(signed_char, "signed char unpacking"),
+ TEST_ENTRY(unsigned_char, "unsigned char unpacking"),
+ TEST_ENTRY(signed_short, "signed short unpacking"),
+ TEST_ENTRY(unsigned_short, "unsigned short unpacking"),
+ TEST_ENTRY(signed_int, "signed int unpacking"),
+ TEST_ENTRY(unsigned_int, "unsigned int unpacking"),
+ TEST_ENTRY(signed_long, "signed long unpacking"),
+ TEST_ENTRY(unsigned_long, "unsigned long unpacking"),
+ TEST_ENTRY(signed_long_long, "signed long long unpacking"),
+ TEST_ENTRY(unsigned_long_long, "unsigned long long unpacking"),
TEST_ENTRY_END
};