/*
SSSD
test_iobuf - IO buffer tests
Copyright (C) 2016 Red Hat
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see .
*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include "util/sss_iobuf.h"
#include "util/util.h"
static void test_sss_iobuf_read(void **state)
{
errno_t ret;
uint8_t buffer[] = { 'H', 'e', 'l', 'l', 'o', ' ', 'w', 'o', 'r', 'l', 'd', 0 };
uint8_t readbuf[64] = { 0 };
size_t nread;
struct sss_iobuf *rb;
rb = sss_iobuf_init_readonly(NULL, buffer, sizeof(buffer));
assert_non_null(rb);
ret = sss_iobuf_read(rb, 5, readbuf, &nread);
assert_int_equal(ret, EOK);
/* There is enough data in the buffer */
assert_int_equal(nread, 5);
/* The data matches beginning of the buffer */
assert_int_equal(strncmp((const char *) readbuf, "Hello", 5), 0);
memset(readbuf, 0, sizeof(readbuf));
ret = sss_iobuf_read(rb, 3, readbuf, &nread);
assert_int_equal(ret, EOK);
/* There is enough data in the buffer */
assert_int_equal(nread, 3);
/* The data matches beginning of the buffer */
assert_int_equal(strncmp((const char *) readbuf, " wo", 3), 0);
/* Try to read more than the buffer has */
memset(readbuf, 0, sizeof(readbuf));
ret = sss_iobuf_read(rb, 10, readbuf, &nread);
/* This is not a fatal error */
assert_int_equal(ret, EOK);
/* We just see how much there was */
assert_int_equal(nread, 4);
/* And get the rest of the buffer back. readbuf includes trailing zero now */
assert_int_equal(strcmp((const char *) readbuf, "rld"), 0);
/* Reading a depleted buffer will just yield zero bytes read now */
ret = sss_iobuf_read(rb, 10, readbuf, &nread);
assert_int_equal(ret, EOK);
assert_int_equal(nread, 0);
/* Failure cases */
ret = sss_iobuf_read(NULL, 10, readbuf, &nread);
assert_int_equal(ret, EINVAL);
ret = sss_iobuf_read(rb, 10, NULL, &nread);
assert_int_equal(ret, EINVAL);
talloc_free(rb);
}
static void test_sss_iobuf_write(void **state)
{
struct sss_iobuf *wb;
struct sss_iobuf *rb;
size_t hwlen = sizeof("Hello world"); /* Includes trailing zero */
uint8_t readbuf[64];
size_t nread;
errno_t ret;
/* Exactly fill the capacity */
wb = sss_iobuf_init_empty(NULL, hwlen, hwlen);
assert_non_null(wb);
ret = sss_iobuf_write_len(wb,
(uint8_t *) discard_const("Hello world"),
sizeof("Hello world"));
assert_int_equal(ret, EOK);
rb = sss_iobuf_init_readonly(NULL,
sss_iobuf_get_data(wb),
sss_iobuf_get_len(wb));
talloc_free(wb);
assert_non_null(rb);
ret = sss_iobuf_read(rb, sizeof(readbuf), readbuf, &nread);
assert_int_equal(ret, EOK);
assert_int_equal(nread, hwlen);
assert_int_equal(strcmp((const char *) readbuf, "Hello world"), 0);
talloc_zfree(rb);
/* Overflow the capacity by one */
wb = sss_iobuf_init_empty(NULL, hwlen, hwlen);
assert_non_null(wb);
ret = sss_iobuf_write_len(wb,
(uint8_t *) discard_const("Hello world!"),
sizeof("Hello world!"));
assert_int_not_equal(ret, EOK);
talloc_zfree(wb);
/* Test resizing exactly up to capacity in several writes */
wb = sss_iobuf_init_empty(NULL, 2, hwlen);
assert_non_null(wb);
ret = sss_iobuf_write_len(wb,
(uint8_t *) discard_const("Hello "),
sizeof("Hello ")-1); /* Not the null byte now.. */
assert_int_equal(ret, EOK);
ret = sss_iobuf_write_len(wb,
(uint8_t *) discard_const("world"),
sizeof("world"));
assert_int_equal(ret, EOK);
rb = sss_iobuf_init_readonly(NULL,
sss_iobuf_get_data(wb),
sss_iobuf_get_len(wb));
talloc_free(wb);
assert_non_null(rb);
ret = sss_iobuf_read(rb, sizeof(readbuf), readbuf, &nread);
assert_int_equal(ret, EOK);
assert_int_equal(nread, hwlen);
assert_int_equal(strcmp((const char *) readbuf, "Hello world"), 0);
talloc_zfree(rb);
/* Overflow the capacity during a resize by one */
wb = sss_iobuf_init_empty(NULL, 2, hwlen);
assert_non_null(wb);
ret = sss_iobuf_write_len(wb,
(uint8_t *) discard_const("Hello "),
sizeof("Hello ")-1); /* Not the null byte now.. */
assert_int_equal(ret, EOK);
ret = sss_iobuf_write_len(wb,
(uint8_t *) discard_const("world!"),
sizeof("world!"));
assert_int_not_equal(ret, EOK);
talloc_zfree(wb);
/* Test allocating an unlimited buffer */
wb = sss_iobuf_init_empty(NULL, 2, 0);
assert_non_null(wb);
ret = sss_iobuf_write_len(wb,
(uint8_t *) discard_const("Hello "),
sizeof("Hello ")-1); /* Not the null byte now.. */
assert_int_equal(ret, EOK);
ret = sss_iobuf_write_len(wb,
(uint8_t *) discard_const("world"),
sizeof("world"));
assert_int_equal(ret, EOK);
rb = sss_iobuf_init_readonly(NULL,
sss_iobuf_get_data(wb),
sss_iobuf_get_len(wb));
talloc_free(wb);
assert_non_null(rb);
ret = sss_iobuf_read(rb, sizeof(readbuf), readbuf, &nread);
assert_int_equal(ret, EOK);
assert_int_equal(nread, hwlen);
assert_int_equal(strcmp((const char *) readbuf, "Hello world"), 0);
talloc_zfree(rb);
}
int main(void)
{
const struct CMUnitTest tests[] = {
cmocka_unit_test(test_sss_iobuf_read),
cmocka_unit_test(test_sss_iobuf_write),
};
return cmocka_run_group_tests(tests, NULL, NULL);
}