test: add a test for the util-io helpers

Using munit via a wrap file, let's see if that test suite is scalable to what
we want.

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
This commit is contained in:
Peter Hutterer 2020-07-31 09:56:07 +10:00
parent 0426c99278
commit f94a7bae85
3 changed files with 198 additions and 0 deletions

View file

@ -84,4 +84,27 @@ executable('ei-socket-client',
'tools/ei-socket-client.c',
dependencies: [dep_libei])
# tests
subproject('munit')
munit = dependency('munit', fallback: ['munit', 'munit_dep'])
test('iotest',
executable('iotest',
'test/iotest.c',
include_directories: 'src',
dependencies: munit))
valgrind = find_program('valgrind', required : false)
if valgrind.found()
add_test_setup('valgrind',
exe_wrapper : [ valgrind,
'--leak-check=full',
'--gen-suppressions=all',
'--error-exitcode=3' ],
timeout_multiplier : 100)
else
message('valgrind not found, disabling valgrind test suite')
endif
configure_file(output: 'config.h', configuration: config_h)

4
subprojects/munit.wrap Normal file
View file

@ -0,0 +1,4 @@
[wrap-git]
directory=munit
url=https://github.com/nemequ/munit/
revision=head

171
test/iotest.c Normal file
View file

@ -0,0 +1,171 @@
#include "config.h"
#include <sys/types.h>
#include <sys/socket.h>
#include <munit.h>
#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, (void*) "io/", argc, argv);
}