api-io.c 6.2 KB

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