Commit 69f2cd9f authored by Thomas Weißschuh's avatar Thomas Weißschuh Committed by Paul E. McKenney
Browse files

tools/nolibc: add testcases for vfprintf



vfprintf() is complex and so far did not have proper tests.

Signed-off-by: default avatarThomas Weißschuh <linux@weissschuh.net>
Signed-off-by: default avatarWilly Tarreau <w@1wt.eu>
Signed-off-by: default avatarPaul E. McKenney <paulmck@kernel.org>
parent 5df28c15
Loading
Loading
Loading
Loading
+86 −0
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@
#include <linux/reboot.h>
#include <sys/io.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <sys/mount.h>
#include <sys/reboot.h>
#include <sys/stat.h>
@@ -669,6 +670,90 @@ int run_stdlib(int min, int max)
	return ret;
}

#define EXPECT_VFPRINTF(c, expected, fmt, ...)				\
	ret += expect_vfprintf(llen, c, expected, fmt, ##__VA_ARGS__)

static int expect_vfprintf(int llen, size_t c, const char *expected, const char *fmt, ...)
{
	int ret, fd, w, r;
	char buf[100];
	FILE *memfile;
	va_list args;

	fd = memfd_create("vfprintf", 0);
	if (fd == -1) {
		pad_spc(llen, 64, "[FAIL]\n");
		return 1;
	}

	memfile = fdopen(fd, "w+");
	if (!memfile) {
		pad_spc(llen, 64, "[FAIL]\n");
		return 1;
	}

	va_start(args, fmt);
	w = vfprintf(memfile, fmt, args);
	va_end(args);

	if (w != c) {
		llen += printf(" written(%d) != %d", w, (int) c);
		pad_spc(llen, 64, "[FAIL]\n");
		return 1;
	}

	fflush(memfile);
	lseek(fd, 0, SEEK_SET);

	r = read(fd, buf, sizeof(buf) - 1);
	buf[r] = '\0';

	fclose(memfile);

	if (r != w) {
		llen += printf(" written(%d) != read(%d)", w, r);
		pad_spc(llen, 64, "[FAIL]\n");
		return 1;
	}

	llen += printf(" \"%s\" = \"%s\"", expected, buf);
	ret = strncmp(expected, buf, c);

	pad_spc(llen, 64, ret ? "[FAIL]\n" : " [OK]\n");
	return ret;
}

static int run_vfprintf(int min, int max)
{
	int test;
	int tmp;
	int ret = 0;
	void *p1, *p2;

	for (test = min; test >= 0 && test <= max; test++) {
		int llen = 0; // line length

		/* avoid leaving empty lines below, this will insert holes into
		 * test numbers.
		 */
		switch (test + __LINE__ + 1) {
		CASE_TEST(empty);        EXPECT_VFPRINTF(0, "", ""); break;
		CASE_TEST(simple);       EXPECT_VFPRINTF(3, "foo", "foo"); break;
		CASE_TEST(string);       EXPECT_VFPRINTF(3, "foo", "%s", "foo"); break;
		CASE_TEST(number);       EXPECT_VFPRINTF(4, "1234", "%d", 1234); break;
		CASE_TEST(negnumber);    EXPECT_VFPRINTF(5, "-1234", "%d", -1234); break;
		CASE_TEST(unsigned);     EXPECT_VFPRINTF(5, "12345", "%u", 12345); break;
		CASE_TEST(char);         EXPECT_VFPRINTF(1, "c", "%c", 'c'); break;
		CASE_TEST(hex);          EXPECT_VFPRINTF(1, "f", "%x", 0xf); break;
		CASE_TEST(pointer);      EXPECT_VFPRINTF(3, "0x1", "%p", (void *) 0x1); break;
		case __LINE__:
			return ret; /* must be last */
		/* note: do not set any defaults so as to permit holes above */
		}
	}
	return ret;
}

static int smash_stack(void)
{
	char buf[100];
@@ -777,6 +862,7 @@ static const struct test test_names[] = {
	/* add new tests here */
	{ .name = "syscall",    .func = run_syscall    },
	{ .name = "stdlib",     .func = run_stdlib     },
	{ .name = "vfprintf",   .func = run_vfprintf   },
	{ .name = "protection", .func = run_protection },
	{ 0 }
};