Tests for wl_buffer_* functions from connection.c --- src/connection.c | 10 +- src/wayland-private.h | 10 ++ tests/Makefile.am | 7 +- tests/buffer-test.c | 247 ++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 268 insertions(+), 6 deletions(-) create mode 100644 tests/buffer-test.c
diff --git a/src/connection.c b/src/connection.c index c85c669..55f6fae 100644 --- a/src/connection.c +++ b/src/connection.c @@ -53,7 +53,7 @@ struct wl_connection { int want_flush; }; -static void +WL_PRIVATE void wl_buffer_put(struct wl_buffer *b, const void *data, size_t count) { uint32_t head, size; @@ -70,7 +70,7 @@ wl_buffer_put(struct wl_buffer *b, const void *data, size_t count) b->head += count; } -static void +WL_PRIVATE void wl_buffer_put_iov(struct wl_buffer *b, struct iovec *iov, int *count) { uint32_t head, tail; @@ -94,7 +94,7 @@ wl_buffer_put_iov(struct wl_buffer *b, struct iovec *iov, int *count) } } -static void +WL_PRIVATE void wl_buffer_get_iov(struct wl_buffer *b, struct iovec *iov, int *count) { uint32_t head, tail; @@ -118,7 +118,7 @@ wl_buffer_get_iov(struct wl_buffer *b, struct iovec *iov, int *count) } } -static void +WL_PRIVATE void wl_buffer_copy(struct wl_buffer *b, void *data, size_t count) { uint32_t tail, size; @@ -133,7 +133,7 @@ wl_buffer_copy(struct wl_buffer *b, void *data, size_t count) } } -static uint32_t +WL_PRIVATE uint32_t wl_buffer_size(struct wl_buffer *b) { return b->head - b->tail; diff --git a/src/wayland-private.h b/src/wayland-private.h index 251e841..70d338b 100644 --- a/src/wayland-private.h +++ b/src/wayland-private.h @@ -99,6 +99,16 @@ struct wl_buffer { #define MASK(i) ((i) & 4095) +#ifdef UNIT_TEST +struct iovec; + +void wl_buffer_put(struct wl_buffer *b, const void *data, size_t count); +void wl_buffer_put_iov(struct wl_buffer *b, struct iovec *iov, int *count); +void wl_buffer_get_iov(struct wl_buffer *b, struct iovec *iov, int *count); +void wl_buffer_copy(struct wl_buffer *b, void *data, size_t count); +uint32_t wl_buffer_size(struct wl_buffer *b); +#endif /* UNIT_TEST */ + struct wl_connection *wl_connection_create(int fd); void wl_connection_destroy(struct wl_connection *connection); void wl_connection_copy(struct wl_connection *connection, void *data, size_t size); diff --git a/tests/Makefile.am b/tests/Makefile.am index 4552159..56c3644 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -12,7 +12,8 @@ TESTS = \ socket-test \ queue-test \ signal-test \ - resources-test + resources-test \ + buffer-test check_PROGRAMS = \ $(TESTS) \ @@ -36,6 +37,10 @@ socket_test_SOURCES = socket-test.c $(test_runner_src) queue_test_SOURCES = queue-test.c $(test_runner_src) signal_test_SOURCES = signal-test.c $(test_runner_src) resources_test_SOURCES = resources-test.c $(test_runner_src) +buffer_test_SOURCES = \ + buffer-test.c \ + $(top_srcdir)/src/connection.c \ + $(test_runner_src) fixed_benchmark_SOURCES = fixed-benchmark.c diff --git a/tests/buffer-test.c b/tests/buffer-test.c new file mode 100644 index 0000000..c454870 --- /dev/null +++ b/tests/buffer-test.c @@ -0,0 +1,247 @@ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <assert.h> +#include "test-runner.h" +#include "wayland-private.h" +#include <sys/uio.h> +#include <unistd.h> + +/* Assert with formated output */ +#define assertf(cond, ...) \ + do { \ + if (!(cond)) { \ + fprintf(stderr, "%s (%s: %d): Assertion %s failed!", \ + __FUNCTION__, __FILE__, __LINE__, #cond);\ + fprintf(stderr, " " __VA_ARGS__); \ + putc('\n', stderr); \ + abort(); \ + } \ + } while (0) + + +static const char data[] = "abcdefghijklmnopqrstuvwxyz"; + +static int +fill_buffer(struct wl_buffer *b) +{ + int i; + for (i = 1; i * (sizeof data) <= sizeof b->data; i++) { + wl_buffer_put(b, data, sizeof data); + + assert(b->tail == 0); + assertf(b->head == i * (sizeof data), + "head is %u instead of %lu", b->head, i * (sizeof data)); + assertf(wl_buffer_size(b) == i * sizeof data, + "wl_buffer_size() = %u instead of %lu", + wl_buffer_size(b), i * sizeof data); + } + + return i; +} + +TEST(wl_buffer_put_tst) +{ + struct wl_buffer b = {.head = 0, .tail = 0}; + size_t index; + int i; + + assert(wl_buffer_size(&b) == 0); + + i = fill_buffer(&b); + + /* do overflow */ + wl_buffer_put(&b, data, sizeof data); + + /* check for me */ + assert(i * sizeof data > sizeof b.data); + + /* size should not be cropped */ + assertf(wl_buffer_size(&b) == i * sizeof data, + "head: %u, tail: %u, wl_buffer_size: %u", + b.head, b.tail, wl_buffer_size(&b)); + + /* head must be somewhere on the begining of the buffer after owerflow */ + assertf(MASK(b.head) < sizeof b.data); + assert(b.tail == 0); + + /* get begining of the last string written to buffer */ + index = sizeof b.data % sizeof data; + + /* compare if the string is split (after overflow) right */ + assertf(strncmp((char *) b.data + sizeof b.data - index, data, index - 1) == 0, + "Should have '%*s', but have '%*s'\n", (int) (index - 1), data, + (int) (index - 1), (char *) b.data + sizeof b.data - index); + assertf(strncmp(b.data, (char *) data + index, sizeof data - index) == 0, + "Should have '%*s', but have '%*s'\n", + (int) (sizeof data - index), data + index, + (int) (sizeof data - index), (char *) b.data); + + struct wl_buffer bb = {.head = 0, .tail = 0}; + wl_buffer_put(&bb, data, sizeof data); + assert(strcmp(data, bb.data) == 0); +} + +TEST(wl_buffer_fill_alot) +{ + struct wl_buffer b = {.head = 0, .tail = 0}; + int i; + + /* put a lot of data into buffer (data < sizeof buffer.data) */ + for (i = 0; i * sizeof data < 100 * sizeof b.data; i++) + wl_buffer_put(&b, data, sizeof data); +} + +TEST(wl_buffer_copy_tst) +{ + char buf[40]; + struct wl_buffer b = {.head = 0, .tail = 0}; + + wl_buffer_put(&b, data, sizeof data); + wl_buffer_copy(&b, &buf, sizeof data); + + assert(strcmp(buf, b.data) == 0); + + /* wl_buffer_copy is not destructive */ + assertf(strcmp(buf, b.data) == 0, + "Previous wl_buffer_copy modified data"); + assert(b.tail == 0); + + /* do overflow */ + b.head = sizeof b.data - 10; + b.tail = b.head; + wl_buffer_put(&b, data, sizeof data); + + memset(&buf, 0, sizeof buf); + wl_buffer_copy(&b, buf, sizeof data); + assert(strcmp(buf, data) == 0); +} + +TEST(wl_buffer_put_iov_tst) +{ + struct wl_buffer b = {.head = 0, .tail = 0}; + struct iovec iov[2]; + int cnt = 0; + size_t len; + + int p[2]; + char buf1[] = "buffer1"; + char buf2[] = "buffer2"; + + assert(pipe(p) != -1); + + /* try empty buffer */ + wl_buffer_put_iov(&b, iov, &cnt); + assertf(cnt == 1, "Count: %d", cnt); + + write(p[1], buf1, sizeof buf1); + len = readv(p[0], iov, cnt); + assertf(len == sizeof buf1, "len: %lu, sizeof buf1: %lu", + len, sizeof buf1); + assert(strcmp(buf1, b.data) == 0); + + b.head += len; + wl_buffer_put_iov(&b, iov, &cnt); + assertf(cnt == 1, "Count: %d", cnt); + + write(p[1], buf2, sizeof buf2); + len = readv(p[0], iov, cnt); + assertf(len == sizeof buf2, "len: %lu, sizeof buf2: %lu", + len, sizeof buf2); + /* the contents should be "buffer1buffer2" */ + assert(strcmp(b.data, buf1) == 0); + assert(strcmp(b.data + sizeof buf1, buf2) == 0); + + /* set head 3 bytes from the end --> it should write only 3 bytes */ + b.head = sizeof b.data - 3; + wl_buffer_put_iov(&b, iov, &cnt); + assertf(cnt == 1, "Count: %d", cnt); + write(p[1], buf1, sizeof buf1); + len = readv(p[0], iov, cnt); + assertf(len == 3, "len: %lu", len); + + /* set tail != 0, it should fill both iovec structures */ + b.tail = 5; + wl_buffer_put_iov(&b, iov, &cnt); + assertf(cnt == 2, "Count: %d", cnt); + /* in the pipe left 5 bytes {'f', 'e', 'r', '1', '\0'}*/ + len = readv(p[0], iov, cnt); + assertf(len == 5, "len: %lu", len); + assert(strncmp(b.data + sizeof b.data - 3, "fer", 3) == 0); + assert(strcmp(b.data, "1") == 0); + + close(p[0]); + close(p[1]); +} + +TEST(wl_buffer_get_iov_tst) +{ + struct wl_buffer b = {.head = 0, .tail = 0}; + struct wl_buffer tmp; + struct iovec iov[2]; + int cnt = 0; + size_t index; + ssize_t len; + + int p[2]; + + assert(pipe(p) != -1); + + fill_buffer(&b); + index = sizeof b.data % sizeof data; + + wl_buffer_get_iov(&b, iov, &cnt); + assert((len = writev(p[1], iov, cnt)) > 0); + assert(read(p[0], &tmp.data, sizeof b.data - index) == len); + assert(strcmp(tmp.data, b.data) == 0); + + /* circulation */ + b.tail = sizeof b.data - 10; + b.head = b.tail; + wl_buffer_put(&b, data, sizeof data); + + wl_buffer_get_iov(&b, iov, &cnt); + assertf(cnt == 2, "cnt: %d", cnt); + assert((len = writev(p[1], iov, cnt)) > 0); + assert(read(p[0], &tmp.data, sizeof data) == len); + assert(strncmp(tmp.data, b.data + sizeof b.data - 10, 10) == 0); + assert(strcmp(tmp.data + 10, b.data) == 0); + + close(p[0]); + close(p[1]); +} + +TEST(wl_buffer_get_put_iov_tst) +{ + struct wl_buffer b1, b2; + struct iovec iov1[2], iov2[2]; + int cnt1 = 0; + int cnt2 = 0; + + int p[2]; + + assert(pipe(p) != -1); + memset(&b1, 0, sizeof b1); + memset(&b2, 0, sizeof b2); + + fill_buffer(&b1); + wl_buffer_get_iov(&b1, iov1, &cnt1); + wl_buffer_put_iov(&b2, iov2, &cnt2); + assert((writev(p[1], iov1, cnt1) == readv(p[0], iov2, cnt2)) > 0); + assert(memcmp(b1.data, b2.data, sizeof b1.data) == 0); + + /* try cycled buffer (head < tail) */ + b1.head = 10; + b1.tail = sizeof b1.data - 10; + b2.head = b1.tail; + b2.tail = b1.head; + wl_buffer_get_iov(&b1, iov1, &cnt1); + wl_buffer_put_iov(&b2, iov2, &cnt2); + assertf(cnt1 == 2 && cnt2 == 2, "cnt1: %d, cnt2: %d", cnt1, cnt2); + assert((writev(p[1], iov1, cnt1) == readv(p[0], iov2, cnt2)) > 0); + assert(memcmp(b1.data, b2.data, sizeof b1.data) == 0); + + close(p[0]); + close(p[1]); + +} -- 1.8.4.2 _______________________________________________ wayland-devel mailing list wayland-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/wayland-devel