summaryrefslogtreecommitdiffstats
path: root/test/ringbuffer_test.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'test/ringbuffer_test.cpp')
-rw-r--r--test/ringbuffer_test.cpp216
1 files changed, 216 insertions, 0 deletions
diff --git a/test/ringbuffer_test.cpp b/test/ringbuffer_test.cpp
new file mode 100644
index 0000000..ee80e6a
--- /dev/null
+++ b/test/ringbuffer_test.cpp
@@ -0,0 +1,216 @@
+/*
+ This file is part of Raul.
+ Copyright 2007-2012 David Robillard <http://drobilla.net>
+
+ Raul 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 any later version.
+
+ Raul 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 Raul. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <climits>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+#include <iostream>
+#include <string>
+
+#include "raul/RingBuffer.hpp"
+
+using namespace std;
+using namespace Raul;
+
+#define MSG_SIZE 20
+
+namespace {
+
+Raul::RingBuffer* ring = 0;
+size_t n_writes = 0;
+bool ring_error = false;
+
+int
+gen_msg(int* msg, int start)
+{
+ for (int i = 0; i < MSG_SIZE; ++i) {
+ msg[i] = start;
+ start = (start + 1) % INT_MAX;
+ }
+ return start;
+}
+
+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;
+ }
+ }
+
+ return 1;
+}
+
+void*
+reader(void* arg)
+{
+ printf("Reader starting\n");
+
+ 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;
+}
+
+void*
+writer(void* arg)
+{
+ printf("Writer starting\n");
+
+ 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);
+ }
+ }
+
+ printf("Writer finished\n");
+ return NULL;
+}
+
+} // namespace
+
+int
+main(int argc, char** argv)
+{
+ if (argc > 1 && argv[1][0] == '-') {
+ printf("Usage: %s SIZE N_WRITES\n", argv[0]);
+ return 1;
+ }
+
+ size_t size = 1024;
+ if (argc > 1) {
+ size = std::stoul(argv[1]);
+ }
+
+ n_writes = size * 1024;
+ if (argc > 2) {
+ n_writes = std::stoul(argv[2]);
+ }
+
+ printf("Testing %zu writes of %u ints to a %zu int ring...\n",
+ n_writes, MSG_SIZE, size);
+
+ ring = new Raul::RingBuffer(uint32_t(size));
+ if (ring->capacity() < size - 1) {
+ fprintf(stderr, "Ring capacity is smaller than expected\n");
+ return 1;
+ }
+
+ if (ring->skip(1)) {
+ fprintf(stderr, "Successfully skipped in empty RingBuffer\n");
+ return 1;
+ }
+
+ char buf[6] = { 'h', 'e', 'l', 'l', '0', '\0' };
+ if (ring->read(1, buf)) {
+ fprintf(stderr, "Successfully read from empty RingBuffer\n");
+ return 1;
+ }
+
+ ring->write(sizeof(buf), buf);
+ ring->skip(1);
+ char buf2[sizeof(buf) - 1];
+ ring->read(sizeof(buf2), buf2);
+ if (strcmp(buf2, buf + 1)) {
+ fprintf(stderr, "Skip failed\n");
+ return 1;
+ }
+
+ ring->reset();
+ if (ring->read_space() != 0) {
+ fprintf(stderr, "Reset RingBuffer is not empty\n");
+ return 1;
+ }
+
+ for (uint32_t i = 0; i < ring->capacity(); ++i) {
+ const char c = 'X';
+ if (ring->write(1, &c) != 1) {
+ fprintf(stderr, "Write failed\n");
+ return 1;
+ }
+ }
+
+ if (ring->write_space() != 0) {
+ fprintf(stderr, "Ring is not full as expected\n");
+ return 1;
+ }
+
+ if (ring->write(1, buf) != 0) {
+ fprintf(stderr, "Successfully wrote to full RingBuffer\n");
+ return 1;
+ }
+
+ if (ring->peek(1, buf2) != 1 || buf2[0] != 'X') {
+ fprintf(stderr, "Failed to read from full RingBuffer\n");
+ return 1;
+ }
+
+ ring->reset();
+
+ 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;
+}