xref: /openbmc/linux/tools/perf/tests/api-io.c (revision 9ccbc211)
1 // SPDX-License-Identifier: GPL-2.0-only
2 #include <sys/types.h>
3 #include <sys/stat.h>
4 #include <fcntl.h>
5 #include <limits.h>
6 #include <stdio.h>
7 #include <stdlib.h>
8 #include <string.h>
9 #include <unistd.h>
10 
11 #include "debug.h"
12 #include "tests.h"
13 #include <api/io.h>
14 #include <linux/kernel.h>
15 #include <linux/zalloc.h>
16 
17 #define TEMPL "/tmp/perf-test-XXXXXX"
18 
19 #define EXPECT_EQUAL(val, expected)                             \
20 do {								\
21 	if (val != expected) {					\
22 		pr_debug("%s:%d: %d != %d\n",			\
23 			__FILE__, __LINE__, val, expected);	\
24 		ret = -1;					\
25 	}							\
26 } while (0)
27 
28 #define EXPECT_EQUAL64(val, expected)                           \
29 do {								\
30 	if (val != expected) {					\
31 		pr_debug("%s:%d: %lld != %lld\n",		\
32 			__FILE__, __LINE__, val, expected);	\
33 		ret = -1;					\
34 	}							\
35 } while (0)
36 
make_test_file(char path[PATH_MAX],const char * contents)37 static int make_test_file(char path[PATH_MAX], const char *contents)
38 {
39 	ssize_t contents_len = strlen(contents);
40 	int fd;
41 
42 	strcpy(path, TEMPL);
43 	fd = mkstemp(path);
44 	if (fd < 0) {
45 		pr_debug("mkstemp failed");
46 		return -1;
47 	}
48 	if (write(fd, contents, contents_len) < contents_len) {
49 		pr_debug("short write");
50 		close(fd);
51 		unlink(path);
52 		return -1;
53 	}
54 	close(fd);
55 	return 0;
56 }
57 
setup_test(char path[PATH_MAX],const char * contents,size_t buf_size,struct io * io)58 static int setup_test(char path[PATH_MAX], const char *contents,
59 		      size_t buf_size, struct io *io)
60 {
61 	if (make_test_file(path, contents))
62 		return -1;
63 
64 	io->fd = open(path, O_RDONLY);
65 	if (io->fd < 0) {
66 		pr_debug("Failed to open '%s'\n", path);
67 		unlink(path);
68 		return -1;
69 	}
70 	io->buf = malloc(buf_size);
71 	if (io->buf == NULL) {
72 		pr_debug("Failed to allocate memory");
73 		close(io->fd);
74 		unlink(path);
75 		return -1;
76 	}
77 	io__init(io, io->fd, io->buf, buf_size);
78 	return 0;
79 }
80 
cleanup_test(char path[PATH_MAX],struct io * io)81 static void cleanup_test(char path[PATH_MAX], struct io *io)
82 {
83 	zfree(&io->buf);
84 	close(io->fd);
85 	unlink(path);
86 }
87 
do_test_get_char(const char * test_string,size_t buf_size)88 static int do_test_get_char(const char *test_string, size_t buf_size)
89 {
90 	char path[PATH_MAX];
91 	struct io io;
92 	int ch, ret = 0;
93 	size_t i;
94 
95 	if (setup_test(path, test_string, buf_size, &io))
96 		return -1;
97 
98 	for (i = 0; i < strlen(test_string); i++) {
99 		ch = io__get_char(&io);
100 
101 		EXPECT_EQUAL(ch, test_string[i]);
102 		EXPECT_EQUAL(io.eof, false);
103 	}
104 	ch = io__get_char(&io);
105 	EXPECT_EQUAL(ch, -1);
106 	EXPECT_EQUAL(io.eof, true);
107 
108 	cleanup_test(path, &io);
109 	return ret;
110 }
111 
test_get_char(void)112 static int test_get_char(void)
113 {
114 	int i, ret = 0;
115 	size_t j;
116 
117 	static const char *const test_strings[] = {
118 		"12345678abcdef90",
119 		"a\nb\nc\nd\n",
120 		"\a\b\t\v\f\r",
121 	};
122 	for (i = 0; i <= 10; i++) {
123 		for (j = 0; j < ARRAY_SIZE(test_strings); j++) {
124 			if (do_test_get_char(test_strings[j], 1 << i))
125 				ret = -1;
126 		}
127 	}
128 	return ret;
129 }
130 
do_test_get_hex(const char * test_string,__u64 val1,int ch1,__u64 val2,int ch2,__u64 val3,int ch3,bool end_eof)131 static int do_test_get_hex(const char *test_string,
132 			__u64 val1, int ch1,
133 			__u64 val2, int ch2,
134 			__u64 val3, int ch3,
135 			bool end_eof)
136 {
137 	char path[PATH_MAX];
138 	struct io io;
139 	int ch, ret = 0;
140 	__u64 hex;
141 
142 	if (setup_test(path, test_string, 4, &io))
143 		return -1;
144 
145 	ch = io__get_hex(&io, &hex);
146 	EXPECT_EQUAL64(hex, val1);
147 	EXPECT_EQUAL(ch, ch1);
148 
149 	ch = io__get_hex(&io, &hex);
150 	EXPECT_EQUAL64(hex, val2);
151 	EXPECT_EQUAL(ch, ch2);
152 
153 	ch = io__get_hex(&io, &hex);
154 	EXPECT_EQUAL64(hex, val3);
155 	EXPECT_EQUAL(ch, ch3);
156 
157 	EXPECT_EQUAL(io.eof, end_eof);
158 
159 	cleanup_test(path, &io);
160 	return ret;
161 }
162 
test_get_hex(void)163 static int test_get_hex(void)
164 {
165 	int ret = 0;
166 
167 	if (do_test_get_hex("12345678abcdef90",
168 				0x12345678abcdef90, -1,
169 				0, -1,
170 				0, -1,
171 				true))
172 		ret = -1;
173 
174 	if (do_test_get_hex("1\n2\n3\n",
175 				1, '\n',
176 				2, '\n',
177 				3, '\n',
178 				false))
179 		ret = -1;
180 
181 	if (do_test_get_hex("12345678ABCDEF90;a;b",
182 				0x12345678abcdef90, ';',
183 				0xa, ';',
184 				0xb, -1,
185 				true))
186 		ret = -1;
187 
188 	if (do_test_get_hex("0x1x2x",
189 				0, 'x',
190 				1, 'x',
191 				2, 'x',
192 				false))
193 		ret = -1;
194 
195 	if (do_test_get_hex("x1x",
196 				0, -2,
197 				1, 'x',
198 				0, -1,
199 				true))
200 		ret = -1;
201 
202 	if (do_test_get_hex("10000000000000000000000000000abcdefgh99i",
203 				0xabcdef, 'g',
204 				0, -2,
205 				0x99, 'i',
206 				false))
207 		ret = -1;
208 
209 	return ret;
210 }
211 
do_test_get_dec(const char * test_string,__u64 val1,int ch1,__u64 val2,int ch2,__u64 val3,int ch3,bool end_eof)212 static int do_test_get_dec(const char *test_string,
213 			__u64 val1, int ch1,
214 			__u64 val2, int ch2,
215 			__u64 val3, int ch3,
216 			bool end_eof)
217 {
218 	char path[PATH_MAX];
219 	struct io io;
220 	int ch, ret = 0;
221 	__u64 dec;
222 
223 	if (setup_test(path, test_string, 4, &io))
224 		return -1;
225 
226 	ch = io__get_dec(&io, &dec);
227 	EXPECT_EQUAL64(dec, val1);
228 	EXPECT_EQUAL(ch, ch1);
229 
230 	ch = io__get_dec(&io, &dec);
231 	EXPECT_EQUAL64(dec, val2);
232 	EXPECT_EQUAL(ch, ch2);
233 
234 	ch = io__get_dec(&io, &dec);
235 	EXPECT_EQUAL64(dec, val3);
236 	EXPECT_EQUAL(ch, ch3);
237 
238 	EXPECT_EQUAL(io.eof, end_eof);
239 
240 	cleanup_test(path, &io);
241 	return ret;
242 }
243 
test_get_dec(void)244 static int test_get_dec(void)
245 {
246 	int ret = 0;
247 
248 	if (do_test_get_dec("12345678abcdef90",
249 				12345678, 'a',
250 				0, -2,
251 				0, -2,
252 				false))
253 		ret = -1;
254 
255 	if (do_test_get_dec("1\n2\n3\n",
256 				1, '\n',
257 				2, '\n',
258 				3, '\n',
259 				false))
260 		ret = -1;
261 
262 	if (do_test_get_dec("12345678;1;2",
263 				12345678, ';',
264 				1, ';',
265 				2, -1,
266 				true))
267 		ret = -1;
268 
269 	if (do_test_get_dec("0x1x2x",
270 				0, 'x',
271 				1, 'x',
272 				2, 'x',
273 				false))
274 		ret = -1;
275 
276 	if (do_test_get_dec("x1x",
277 				0, -2,
278 				1, 'x',
279 				0, -1,
280 				true))
281 		ret = -1;
282 
283 	if (do_test_get_dec("10000000000000000000000000000000000000000000000000000000000123456789ab99c",
284 				123456789, 'a',
285 				0, -2,
286 				99, 'c',
287 				false))
288 		ret = -1;
289 
290 	return ret;
291 }
292 
test_get_line(void)293 static int test_get_line(void)
294 {
295 	char path[PATH_MAX];
296 	struct io io;
297 	char test_string[1024];
298 	char *line = NULL;
299 	size_t i, line_len = 0;
300 	size_t buf_size = 128;
301 	int ret = 0;
302 
303 	for (i = 0; i < 512; i++)
304 		test_string[i] = 'a';
305 	test_string[512] = '\n';
306 	for (i = 513; i < 1023; i++)
307 		test_string[i] = 'b';
308 	test_string[1023] = '\0';
309 
310 	if (setup_test(path, test_string, buf_size, &io))
311 		return -1;
312 
313 	EXPECT_EQUAL((int)io__getline(&io, &line, &line_len), 513);
314 	EXPECT_EQUAL((int)strlen(line), 513);
315 	for (i = 0; i < 512; i++)
316 		EXPECT_EQUAL(line[i], 'a');
317 	EXPECT_EQUAL(line[512], '\n');
318 	EXPECT_EQUAL((int)io__getline(&io, &line, &line_len), 510);
319 	for (i = 0; i < 510; i++)
320 		EXPECT_EQUAL(line[i], 'b');
321 
322 	free(line);
323 	cleanup_test(path, &io);
324 	return ret;
325 }
326 
test__api_io(struct test_suite * test __maybe_unused,int subtest __maybe_unused)327 static int test__api_io(struct test_suite *test __maybe_unused,
328 			int subtest __maybe_unused)
329 {
330 	int ret = 0;
331 
332 	if (test_get_char())
333 		ret = TEST_FAIL;
334 	if (test_get_hex())
335 		ret = TEST_FAIL;
336 	if (test_get_dec())
337 		ret = TEST_FAIL;
338 	if (test_get_line())
339 		ret = TEST_FAIL;
340 	return ret;
341 }
342 
343 DEFINE_SUITE("Test api io", api_io);
344