changeset 665:590bbd1d3fe5

int: add basic tests for __str2uXX and str2uXX functions Signed-off-by: Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
author Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
date Fri, 08 Feb 2019 17:21:55 -0500
parents da3cc572a748
children 7590cd6dee22
files tests/.hgignore tests/CMakeLists.txt tests/test_str2uint.c
diffstat 3 files changed, 231 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/tests/.hgignore	Wed Feb 13 10:23:49 2019 -0500
+++ b/tests/.hgignore	Fri Feb 08 17:21:55 2019 -0500
@@ -37,6 +37,7 @@
 test_sexpr_parser
 test_sexpr_eval
 test_sexpr_iter
+test_str2uint
 test_tree_bst
 test_tree_rb
 test_urldecode
--- a/tests/CMakeLists.txt	Wed Feb 13 10:23:49 2019 -0500
+++ b/tests/CMakeLists.txt	Fri Feb 08 17:21:55 2019 -0500
@@ -63,6 +63,7 @@
 build_test_bin_and_run(padding)
 build_test_bin_and_run(sexpr_eval)
 build_test_bin_and_run(sexpr_iter)
+build_test_bin_and_run(str2uint)
 build_test_bin_and_run(tree_bst)
 build_test_bin_and_run(tree_rb)
 build_test_bin_and_run(urldecode)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/test_str2uint.c	Fri Feb 08 17:21:55 2019 -0500
@@ -0,0 +1,229 @@
+/*
+ * Copyright (c) 2019 Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <jeffpc/int.h>
+#include <jeffpc/types.h>
+#include <jeffpc/error.h>
+
+#include "test.c"
+
+struct res {
+	int ret;
+	uint64_t out;
+};
+
+struct run {
+	const char *in;
+	struct res out[3][3]; /* out[base][size] */
+};
+
+#define B8	0
+#define B10	1
+#define B16	2
+
+static const int bases[] = {
+	[B8] = 8,
+	[B10] = 10,
+	[B16] = 16,
+};
+
+#define SZ16	0
+#define SZ32	1
+#define SZ64	2
+
+static const int sizes[] = {
+	[SZ16] = 16,
+	[SZ32] = 32,
+	[SZ64] = 64,
+};
+
+#define ENT(v_s16, v_s32, v_s64, r_s16, r_s32, r_s64) \
+	{ \
+		[SZ16] = { .ret = (r_s16), .out = (v_s16), }, \
+		[SZ32] = { .ret = (r_s32), .out = (v_s32), }, \
+		[SZ64] = { .ret = (r_s64), .out = (v_s64), }, \
+	}
+
+static const struct run runs[] = {
+	{
+		.in	  = "",
+		.out[B8]  = ENT(0, 0, 0, -EINVAL, -EINVAL, -EINVAL),
+		.out[B10] = ENT(0, 0, 0, -EINVAL, -EINVAL, -EINVAL),
+		.out[B16] = ENT(0, 0, 0, -EINVAL, -EINVAL, -EINVAL),
+	},
+	{
+		.in	  = "0",
+		.out[B8]  = ENT(0, 0, 0, 0, 0, 0),
+		.out[B10] = ENT(0, 0, 0, 0, 0, 0),
+		.out[B16] = ENT(0, 0, 0, 0, 0, 0),
+	},
+	{
+		.in	  = "00",
+		.out[B8]  = ENT(0, 0, 0, 0, 0, 0),
+		.out[B10] = ENT(0, 0, 0, 0, 0, 0),
+		.out[B16] = ENT(0, 0, 0, 0, 0, 0),
+	},
+	{
+		.in	  = "0x0",
+		/* FIXME: base 8 & 10 should return -EINVAL */
+		.out[B8]  = ENT(0, 0, 0, 0, 0, 0),
+		.out[B10] = ENT(0, 0, 0, 0, 0, 0),
+		.out[B16] = ENT(0, 0, 0, 0, 0, 0),
+	},
+	{
+		.in	  = "5",
+		.out[B8]  = ENT(5, 5, 5, 0, 0, 0),
+		.out[B10] = ENT(5, 5, 5, 0, 0, 0),
+		.out[B16] = ENT(5, 5, 5, 0, 0, 0),
+	},
+	{
+		.in	  = "8",
+		.out[B8]  = ENT(0, 0, 0, -EINVAL, -EINVAL, -EINVAL),
+		.out[B10] = ENT(8, 8, 8, 0, 0, 0),
+		.out[B16] = ENT(8, 8, 8, 0, 0, 0),
+	},
+	{
+		.in	  = "0x8",
+		/* FIXME: base 8 & 10 should return -EINVAL */
+		.out[B8]  = ENT(0, 0, 0, 0, 0, 0),
+		.out[B10] = ENT(0, 0, 0, 0, 0, 0),
+		.out[B16] = ENT(8, 8, 8, 0, 0, 0),
+	},
+	{
+		.in	  = "A",
+		.out[B8]  = ENT(0, 0, 0, -EINVAL, -EINVAL, -EINVAL),
+		.out[B10] = ENT(0, 0, 0, -EINVAL, -EINVAL, -EINVAL),
+		.out[B16] = ENT(0xa, 0xa, 0xa, 0, 0, 0),
+	},
+	{
+		.in	  = "a",
+		.out[B8]  = ENT(0, 0, 0, -EINVAL, -EINVAL, -EINVAL),
+		.out[B10] = ENT(0, 0, 0, -EINVAL, -EINVAL, -EINVAL),
+		.out[B16] = ENT(0xa, 0xa, 0xa, 0, 0, 0),
+	},
+	{
+		.in	  = "0XA",
+		/* FIXME: base 8 & 10 should return -EINVAL */
+		.out[B8]  = ENT(0, 0, 0, 0, 0, 0),
+		.out[B10] = ENT(0, 0, 0, 0, 0, 0),
+		.out[B16] = ENT(0xa, 0xa, 0xa, 0, 0, 0),
+	},
+	{
+		.in	  = "0Xa",
+		/* FIXME: base 8 & 10 should return -EINVAL */
+		.out[B8]  = ENT(0, 0, 0, 0, 0, 0),
+		.out[B10] = ENT(0, 0, 0, 0, 0, 0),
+		.out[B16] = ENT(0xa, 0xa, 0xa, 0, 0, 0),
+	},
+	{
+		.in	  = "0xA",
+		/* FIXME: base 8 & 10 should return -EINVAL */
+		.out[B8]  = ENT(0, 0, 0, 0, 0, 0),
+		.out[B10] = ENT(0, 0, 0, 0, 0, 0),
+		.out[B16] = ENT(0xa, 0xa, 0xa, 0, 0, 0),
+	},
+	{
+		.in	  = "0xa",
+		/* FIXME: base 8 & 10 should return -EINVAL */
+		.out[B8]  = ENT(0, 0, 0, 0, 0, 0),
+		.out[B10] = ENT(0, 0, 0, 0, 0, 0),
+		.out[B16] = ENT(0xa, 0xa, 0xa, 0, 0, 0),
+	},
+	/*
+	 * FIXME: more test cases
+	 *   - check values > max for type
+	 *   - check inputs starting with '-' ?
+	 *   - check inputs with leading garbage
+	 *   - check inputs with trailing garbage
+	 */
+};
+
+#define TEST(i, bidx, szidx, expr, type)				\
+	do {								\
+		const char *in = runs[i].in;				\
+		const struct res *res = &runs[i].out[bidx][szidx];	\
+		const int base = bases[bidx];				\
+		const int size = sizes[szidx];				\
+		type tmp;						\
+		uint64_t out;						\
+		int ret;						\
+									\
+		fprintf(stderr, "%2d: ... %s -> ", (i), #expr);		\
+									\
+		ret = (expr);						\
+		out = tmp;						\
+									\
+		/* print the result we got */				\
+		if (ret) {						\
+			fprintf(stderr, "ret=%d", ret);			\
+		} else {						\
+			static const char *fmts[] = {			\
+				[B8] = "%#0*"PRIo64,			\
+				[B10] = "%#0*"PRIu64,			\
+				[B16] = "%#0*"PRIx64,			\
+			};						\
+			int width = 2 * size / 8;			\
+									\
+			if (base == 8)					\
+				width++; /* extra leading 0 */		\
+			else if (base == 16)				\
+				width += 2; /* leading 0x */		\
+									\
+			fprintf(stderr, "out=");			\
+			fprintf(stderr, fmts[bidx], width, out);	\
+		}							\
+		fprintf(stderr, "...");					\
+									\
+		check_rets(res->ret, ret, "__str2u%d", base);		\
+									\
+		if (!ret)						\
+			ASSERT3U(out, ==, res->out);			\
+									\
+		fprintf(stderr, "ok.\n");				\
+	} while (0)
+
+void test(void)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_LEN(runs); i++) {
+		fprintf(stderr, "%2d: in='%s'...\n", i, runs[i].in);
+
+		/* test simple base 10 parsing */
+		TEST(i, B10, SZ16, str2u16(in, &tmp), uint16_t);
+		TEST(i, B10, SZ32, str2u32(in, &tmp), uint32_t);
+		TEST(i, B10, SZ64, str2u64(in, &tmp), uint64_t);
+
+		/* test underlying function with all bases */
+		TEST(i, B8, SZ16, __str2u16(in, &tmp, 8), uint16_t);
+		TEST(i, B8, SZ32, __str2u32(in, &tmp, 8), uint32_t);
+		TEST(i, B8, SZ64, __str2u64(in, &tmp, 8), uint64_t);
+
+		TEST(i, B10, SZ16, __str2u16(in, &tmp, 10), uint16_t);
+		TEST(i, B10, SZ32, __str2u32(in, &tmp, 10), uint32_t);
+		TEST(i, B10, SZ64, __str2u64(in, &tmp, 10), uint64_t);
+
+		TEST(i, B16, SZ16, __str2u16(in, &tmp, 16), uint16_t);
+		TEST(i, B16, SZ32, __str2u32(in, &tmp, 16), uint32_t);
+		TEST(i, B16, SZ64, __str2u64(in, &tmp, 16), uint64_t);
+	}
+}