343 lines · 6.2 KB · C
RawDownload
// SPDX-License-Identifier: GPL-2.0-only#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include <limits.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <unistd.h> #include "debug.h"#include "tests.h"#include <api/io.h>#include <linux/kernel.h>#include <linux/zalloc.h> #define TEMPL "/tmp/perf-test-XXXXXX" #define EXPECT_EQUAL(val, expected)                             \do {								\	if (val != expected) {					\		pr_debug("%s:%d: %d != %d\n",			\			__FILE__, __LINE__, val, expected);	\		ret = -1;					\	}							\} while (0) #define EXPECT_EQUAL64(val, expected)                           \do {								\	if (val != expected) {					\		pr_debug("%s:%d: %lld != %lld\n",		\			__FILE__, __LINE__, val, expected);	\		ret = -1;					\	}							\} while (0) static int make_test_file(char path[PATH_MAX], const char *contents){	ssize_t contents_len = strlen(contents);	int fd; 	strcpy(path, TEMPL);	fd = mkstemp(path);	if (fd < 0) {		pr_debug("mkstemp failed");		return -1;	}	if (write(fd, contents, contents_len) < contents_len) {		pr_debug("short write");		close(fd);		unlink(path);		return -1;	}	close(fd);	return 0;} static int setup_test(char path[PATH_MAX], const char *contents,		      size_t buf_size, struct io *io){	if (make_test_file(path, contents))		return -1; 	io->fd = open(path, O_RDONLY);	if (io->fd < 0) {		pr_debug("Failed to open '%s'\n", path);		unlink(path);		return -1;	}	io->buf = malloc(buf_size);	if (io->buf == NULL) {		pr_debug("Failed to allocate memory");		close(io->fd);		unlink(path);		return -1;	}	io__init(io, io->fd, io->buf, buf_size);	return 0;} static void cleanup_test(char path[PATH_MAX], struct io *io){	zfree(&io->buf);	close(io->fd);	unlink(path);} static int do_test_get_char(const char *test_string, size_t buf_size){	char path[PATH_MAX];	struct io io;	int ch, ret = 0;	size_t i; 	if (setup_test(path, test_string, buf_size, &io))		return -1; 	for (i = 0; i < strlen(test_string); i++) {		ch = io__get_char(&io); 		EXPECT_EQUAL(ch, test_string[i]);		EXPECT_EQUAL(io.eof, false);	}	ch = io__get_char(&io);	EXPECT_EQUAL(ch, -1);	EXPECT_EQUAL(io.eof, true); 	cleanup_test(path, &io);	return ret;} static int test_get_char(void){	int i, ret = 0;	size_t j; 	static const char *const test_strings[] = {		"12345678abcdef90",		"a\nb\nc\nd\n",		"\a\b\t\v\f\r",	};	for (i = 0; i <= 10; i++) {		for (j = 0; j < ARRAY_SIZE(test_strings); j++) {			if (do_test_get_char(test_strings[j], 1 << i))				ret = -1;		}	}	return ret;} static int do_test_get_hex(const char *test_string,			__u64 val1, int ch1,			__u64 val2, int ch2,			__u64 val3, int ch3,			bool end_eof){	char path[PATH_MAX];	struct io io;	int ch, ret = 0;	__u64 hex; 	if (setup_test(path, test_string, 4, &io))		return -1; 	ch = io__get_hex(&io, &hex);	EXPECT_EQUAL64(hex, val1);	EXPECT_EQUAL(ch, ch1); 	ch = io__get_hex(&io, &hex);	EXPECT_EQUAL64(hex, val2);	EXPECT_EQUAL(ch, ch2); 	ch = io__get_hex(&io, &hex);	EXPECT_EQUAL64(hex, val3);	EXPECT_EQUAL(ch, ch3); 	EXPECT_EQUAL(io.eof, end_eof); 	cleanup_test(path, &io);	return ret;} static int test_get_hex(void){	int ret = 0; 	if (do_test_get_hex("12345678abcdef90",				0x12345678abcdef90, -1,				0, -1,				0, -1,				true))		ret = -1; 	if (do_test_get_hex("1\n2\n3\n",				1, '\n',				2, '\n',				3, '\n',				false))		ret = -1; 	if (do_test_get_hex("12345678ABCDEF90;a;b",				0x12345678abcdef90, ';',				0xa, ';',				0xb, -1,				true))		ret = -1; 	if (do_test_get_hex("0x1x2x",				0, 'x',				1, 'x',				2, 'x',				false))		ret = -1; 	if (do_test_get_hex("x1x",				0, -2,				1, 'x',				0, -1,				true))		ret = -1; 	if (do_test_get_hex("10000000000000000000000000000abcdefgh99i",				0xabcdef, 'g',				0, -2,				0x99, 'i',				false))		ret = -1; 	return ret;} static int do_test_get_dec(const char *test_string,			__u64 val1, int ch1,			__u64 val2, int ch2,			__u64 val3, int ch3,			bool end_eof){	char path[PATH_MAX];	struct io io;	int ch, ret = 0;	__u64 dec; 	if (setup_test(path, test_string, 4, &io))		return -1; 	ch = io__get_dec(&io, &dec);	EXPECT_EQUAL64(dec, val1);	EXPECT_EQUAL(ch, ch1); 	ch = io__get_dec(&io, &dec);	EXPECT_EQUAL64(dec, val2);	EXPECT_EQUAL(ch, ch2); 	ch = io__get_dec(&io, &dec);	EXPECT_EQUAL64(dec, val3);	EXPECT_EQUAL(ch, ch3); 	EXPECT_EQUAL(io.eof, end_eof); 	cleanup_test(path, &io);	return ret;} static int test_get_dec(void){	int ret = 0; 	if (do_test_get_dec("12345678abcdef90",				12345678, 'a',				0, -2,				0, -2,				false))		ret = -1; 	if (do_test_get_dec("1\n2\n3\n",				1, '\n',				2, '\n',				3, '\n',				false))		ret = -1; 	if (do_test_get_dec("12345678;1;2",				12345678, ';',				1, ';',				2, -1,				true))		ret = -1; 	if (do_test_get_dec("0x1x2x",				0, 'x',				1, 'x',				2, 'x',				false))		ret = -1; 	if (do_test_get_dec("x1x",				0, -2,				1, 'x',				0, -1,				true))		ret = -1; 	if (do_test_get_dec("10000000000000000000000000000000000000000000000000000000000123456789ab99c",				123456789, 'a',				0, -2,				99, 'c',				false))		ret = -1; 	return ret;} static int test_get_line(void){	char path[PATH_MAX];	struct io io;	char test_string[1024];	char *line = NULL;	size_t i, line_len = 0;	size_t buf_size = 128;	int ret = 0; 	for (i = 0; i < 512; i++)		test_string[i] = 'a';	test_string[512] = '\n';	for (i = 513; i < 1023; i++)		test_string[i] = 'b';	test_string[1023] = '\0'; 	if (setup_test(path, test_string, buf_size, &io))		return -1; 	EXPECT_EQUAL((int)io__getline(&io, &line, &line_len), 513);	EXPECT_EQUAL((int)strlen(line), 513);	for (i = 0; i < 512; i++)		EXPECT_EQUAL(line[i], 'a');	EXPECT_EQUAL(line[512], '\n');	EXPECT_EQUAL((int)io__getline(&io, &line, &line_len), 510);	for (i = 0; i < 510; i++)		EXPECT_EQUAL(line[i], 'b'); 	free(line);	cleanup_test(path, &io);	return ret;} static int test__api_io(struct test_suite *test __maybe_unused,			int subtest __maybe_unused){	int ret = 0; 	if (test_get_char())		ret = TEST_FAIL;	if (test_get_hex())		ret = TEST_FAIL;	if (test_get_dec())		ret = TEST_FAIL;	if (test_get_line())		ret = TEST_FAIL;	return ret;} DEFINE_SUITE("Test api io", api_io);