[PATCH 3/3] tests: add tests for wl_buffer_*
Marek Ch
mchqwerty at gmail.com
Thu Dec 5 07:38:22 PST 2013
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
More information about the wayland-devel
mailing list