tools/nolibc: add testcases for vfprintf
vfprintf() is complex and so far did not have proper tests. Signed-off-by: Thomas Weißschuh <linux@weissschuh.net> Signed-off-by: Willy Tarreau <w@1wt.eu> Signed-off-by: Paul E. McKenney <paulmck@kernel.org>
This commit is contained in:
parent
5df28c153d
commit
69f2cd9fea
@ -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 }
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user