344 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2#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) \20do { \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) \29do { \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 37static 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 58static 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 81static void cleanup_test(char path[PATH_MAX], struct io *io)82{83 zfree(&io->buf);84 close(io->fd);85 unlink(path);86}87 88static 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 112static 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 131static 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 163static 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 212static 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 244static 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 293static 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 327static 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 343DEFINE_SUITE("Test api io", api_io);344