#include "config.h" #include #include #include #include "util-io.h" static MunitResult test_iobuf_new(const MunitParameter params[], void *user_data) { /* test allocation and freeing a buffer */ struct iobuf *buf = iobuf_new(10); munit_assert_size(buf->sz, ==, 10); munit_assert_size(buf->len, ==, 0); munit_assert_size(iobuf_len(buf), ==, 0); buf = iobuf_free(buf); munit_assert_null(buf); return MUNIT_OK; } static MunitResult test_iobuf_cleanup(const MunitParameter params[], void *user_data) { /* Test the attribute(cleanup) define. This test needs to run in * valgrind --leak-check=full to be really useful */ _cleanup_iobuf_ struct iobuf *buf = iobuf_new(10); _cleanup_iobuf_ struct iobuf *nullbuf = NULL; return MUNIT_OK; } static MunitResult test_iobuf_append(const MunitParameter params[], void *user_data) { /* Test appending data */ _cleanup_iobuf_ struct iobuf *buf = iobuf_new(10); /* append data without a resize */ const char data[] = "foo"; iobuf_append(buf, data, 3); munit_assert_size(buf->len, ==, 3); munit_assert_size(iobuf_len(buf), ==, 3); munit_assert_size(buf->sz, ==, 10); /* we don't have a trailing \0 */ const char *bufdata = iobuf_data(buf); munit_assert_char(bufdata[0], ==, 'f'); munit_assert_char(bufdata[1], ==, 'o'); munit_assert_char(bufdata[2], ==, 'o'); /* Now append enough data to force a buffer resize */ const char data2[] = "data forcing resize"; iobuf_append(buf, data2, sizeof(data2)); /* includes \0 */ size_t expected = strlen(data) + strlen(data2) + 1; munit_assert_size(iobuf_len(buf), ==, expected); munit_assert_size(buf->sz, ==, expected); /* now we have a trailing \0 */ munit_assert_string_equal(iobuf_data(buf), "foodata forcing resize"); return MUNIT_OK; } static MunitResult test_iobuf_append_short(const MunitParameter params[], void *user_data) { _cleanup_iobuf_ struct iobuf *buf = iobuf_new(10); /* Append only the first few bytes out of a larger data field, i.e. * make sure we honor the lenght parameter */ const char data[] = "foobar"; const char nullbyte = '\0'; iobuf_append(buf, data, 3); iobuf_append(buf, &nullbyte, 1); munit_assert_size(buf->len, ==, 4); munit_assert_size(iobuf_len(buf), ==, 4); munit_assert_size(buf->sz, ==, 10); munit_assert_string_equal(iobuf_data(buf), "foo"); return MUNIT_OK; } static MunitResult test_iobuf_append_fd(const MunitParameter params[], void *user_data) { _cleanup_iobuf_ struct iobuf *buf = iobuf_new(10); int fds[2]; int rc = socketpair(AF_UNIX, SOCK_STREAM|SOCK_NONBLOCK|SOCK_CLOEXEC, 0, fds); munit_assert_int(rc, ==, 0); int wr = fds[0], rd = fds[1]; /* write some data */ const char data[] = "foobar"; int wlen = xwrite(wr, data, 4); munit_assert_int(wlen, ==, 4); /* read that data */ int rlen = iobuf_append_from_fd(buf, rd); munit_assert_int(rlen, ==, 4); munit_assert_size(iobuf_len(buf), ==, 4); /* so we can do strcmp */ const char nullbyte = '\0'; iobuf_append(buf, &nullbyte, 1); munit_assert_string_equal(iobuf_data(buf), "foob"); /* read when there's nothing waiting */ int blocking_read = iobuf_append_from_fd(buf, rd); munit_assert_int(blocking_read, ==, -EAGAIN); const char largebuffer[2048] = {0xaa}; /* read data exactly our internal buffer size */ wlen = xwrite(wr, largebuffer, 1024); munit_assert_int(wlen, ==, 1024); int read_1024 = iobuf_append_from_fd(buf, rd); munit_assert_int(read_1024, ==, 1024); /* read data exactly our internal buffer size + 1*/ wlen = xwrite(wr, largebuffer, 1025); munit_assert_int(wlen, ==, 1025); int read_1025 = iobuf_append_from_fd(buf, rd); munit_assert_int(read_1025, ==, 1025); /* close write side, read nothing */ xclose(wr); int read_none = iobuf_append_from_fd(buf, rd); munit_assert_int(read_none, ==, 0); /* close read side, expect error */ xclose(rd); int read_fail = iobuf_append_from_fd(buf, rd); munit_assert_int(read_fail, ==, -EBADF); return MUNIT_OK; } static MunitTest iotest_tests[] = { { "iobuf/new", test_iobuf_new, NULL, NULL, MUNIT_TEST_OPTION_NONE, NULL}, { "iobuf/cleanup", test_iobuf_cleanup, NULL, NULL, MUNIT_TEST_OPTION_NONE, NULL}, { "iobuf/append", test_iobuf_append, NULL, NULL, MUNIT_TEST_OPTION_NONE, NULL}, { "iobuf/append_short", test_iobuf_append_short, NULL, NULL, MUNIT_TEST_OPTION_NONE, NULL}, { "iobuf/append_fd", test_iobuf_append_fd, NULL, NULL, MUNIT_TEST_OPTION_NONE, NULL}, }; static const MunitSuite iotest_suite = { "iotest", iotest_tests, NULL, 1, MUNIT_SUITE_OPTION_NONE, }; int main(int argc, char* argv[MUNIT_ARRAY_PARAM(argc + 1)]) { return munit_suite_main(&iotest_suite, NULL, argc, argv); }