From 3a38a92326c983ba33807d956a4bbfb4b05da971 Mon Sep 17 00:00:00 2001 From: David Robillard Date: Sun, 9 Oct 2011 22:56:37 +0000 Subject: Fix RingBuffer error when reading split/wrapped messages. More rigorous, multithreaded RingBuffer test. git-svn-id: http://svn.drobilla.net/lad/trunk/raul@3540 a436a847-0d15-0410-975c-d299462d15a1 --- test/ringbuffer_test.cpp | 172 ++++++++++++++++++++++++++++++++--------------- 1 file changed, 119 insertions(+), 53 deletions(-) (limited to 'test/ringbuffer_test.cpp') diff --git a/test/ringbuffer_test.cpp b/test/ringbuffer_test.cpp index ea1088c..c843ed2 100644 --- a/test/ringbuffer_test.cpp +++ b/test/ringbuffer_test.cpp @@ -1,6 +1,7 @@ -#include -#include +#include #include +#include +#include #include "raul/log.hpp" #include "raul/RingBuffer.hpp" @@ -8,67 +9,132 @@ using namespace std; using namespace Raul; -int -main() +#define MSG_SIZE 20 + +Raul::RingBuffer* ring = 0; +size_t n_writes = 0; +bool ring_error = false; + +static int +gen_msg(int* msg, int start) { - static const int n_tests = 32; - for (int i = 0; i < n_tests; ++i) { - const int size = (rand() % 2000) + 8; - RingBuffer rb(size); - - for (int j = 0; j < size * 32; ++j) { - char ev1[] = { 'a', 'b', 'c' }; - rb.write(3, ev1); - - char buf[3]; - uint32_t read = rb.read(3, buf); - if (read != 3 || strncmp(buf, "abc", 3)) { - error << "Corrupt event " << i << ".1: " - << buf[0] << buf[1] << buf[2] << endl; - return 1; - } - - char ev2[] = { 'd', 'e', 'f' }; - if (!rb.write(3, ev2)) { - error << "Failed write " << i << ".2" << endl; - return 1; - } + for (int i = 0; i < MSG_SIZE; ++i) { + msg[i] = start; + start = (start + 1) % INT_MAX; + } + return start; +} - char ev3[] = { 'g', 'h' }; - if (!rb.write(2, ev3)) { - error << "Failed write " << i << ".3" << endl; - return 1; - } +static int +cmp_msg(int* msg1, int* msg2) +{ + for (int i = 0; i < MSG_SIZE; ++i) { + if (msg1[i] != msg2[i]) { + fprintf(stderr, "ERROR: %d != %d @ %d\n", msg1[i], msg2[i], i); + return 0; + } + } - if (rb.skip(1) != 1) { - error << "Failed skip " << i << endl; - return 1; - } + return 1; +} - uint32_t n_read = rb.read(2, buf); - if (n_read != 2 || strncmp(buf, "ef", 2)) { - error << "Corrupt event " << i << ".4: " - << buf[0] << buf[1] << buf[2] << endl; - return 1; - } +static void* +reader(void* arg) +{ + printf("Reader starting\n"); - n_read = rb.peek(2, buf); - if (n_read != 2 || strncmp(buf, "gh", 2)) { - error << "Corrupt peek event " << i << ".5: " - << buf[0] << buf[1] << endl; - return 1; + int ref_msg[MSG_SIZE]; // Reference generated for comparison + int read_msg[MSG_SIZE]; // Read from ring + size_t count = 0; + int start = gen_msg(ref_msg, 0); + for (size_t i = 0; i < n_writes; ++i) { + if (ring->read_space() >= MSG_SIZE * sizeof(int)) { + const uint32_t n_read = ring->read(MSG_SIZE * sizeof(int), read_msg); + if (n_read != MSG_SIZE * sizeof(int)) { + fprintf(stderr, "FAIL: Read size incorrect\n"); + ring_error = true; + return NULL; + } + if (!cmp_msg(ref_msg, read_msg)) { + fprintf(stderr, "FAIL: Message %zu is corrupt\n", count); + ring_error = true; + return NULL; } + start = gen_msg(ref_msg, start); + ++count; + } + } + + printf("Reader finished\n"); + return NULL; +} + +static void* +writer(void* arg) +{ + printf("Writer starting\n"); - n_read = rb.read(2, buf); - if (n_read != 2 || strncmp(buf, "gh", 2)) { - error << "Corrupt event " << i << ".6: " - << buf[0] << buf[1] << endl; - return 1; + int write_msg[MSG_SIZE]; // Written to ring + int start = gen_msg(write_msg, 0); + for (size_t i = 0; i < n_writes; ++i) { + if (ring->write_space() >= MSG_SIZE * sizeof(int)) { + const uint32_t n_write = ring->write(MSG_SIZE * sizeof(int), write_msg); + if (n_write != MSG_SIZE * sizeof(int)) { + fprintf(stderr, "FAIL: Write size incorrect\n"); + ring_error = true; + return NULL; } + start = gen_msg(write_msg, start); } } - info << "Successfully ran " << n_tests << " tests." << endl; - return 0; + printf("Writer finished\n"); + return NULL; } +int +main(int argc, char** argv) +{ + if (argc > 1 && argv[1][0] == '-') { + printf("Usage: %s SIZE N_WRITES\n", argv[0]); + return 1; + } + + int size = 1024; + if (argc > 1) { + size = atoi(argv[1]); + } + + n_writes = size * 1024; + if (argc > 2) { + n_writes = atoi(argv[2]); + } + + printf("Testing %zu writes of %d ints to a %d int ring...\n", + n_writes, MSG_SIZE, size); + + ring = new Raul::RingBuffer(size); + + pthread_t reader_thread; + if (pthread_create(&reader_thread, NULL, reader, NULL)) { + fprintf(stderr, "Failed to create reader thread\n"); + return 1; + } + + pthread_t writer_thread; + if (pthread_create(&writer_thread, NULL, writer, NULL)) { + fprintf(stderr, "Failed to create writer thread\n"); + return 1; + } + + pthread_join(reader_thread, NULL); + pthread_join(writer_thread, NULL); + + if (ring_error) { + fprintf(stderr, "FAIL: Error occurred\n"); + return 1; + } + + delete ring; + return 0; +} -- cgit v1.2.1