summaryrefslogtreecommitdiffstats
path: root/test
diff options
context:
space:
mode:
Diffstat (limited to 'test')
-rw-r--r--test/array_test.cpp74
-rw-r--r--test/build_test.cpp36
-rw-r--r--test/double_buffer_test.cpp42
-rw-r--r--test/maid_test.cpp125
-rw-r--r--test/path_test.cpp101
-rw-r--r--test/ringbuffer_test.cpp216
-rw-r--r--test/sem_test.cpp74
-rw-r--r--test/socket_test.cpp111
-rw-r--r--test/symbol_test.cpp77
-rw-r--r--test/thread_test.cpp69
-rw-r--r--test/time_test.cpp44
11 files changed, 969 insertions, 0 deletions
diff --git a/test/array_test.cpp b/test/array_test.cpp
new file mode 100644
index 0000000..ea9eb13
--- /dev/null
+++ b/test/array_test.cpp
@@ -0,0 +1,74 @@
+/*
+ This file is part of Raul.
+ Copyright 2007-2016 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 <stdio.h>
+
+#include "raul/Array.hpp"
+
+int
+main(int argc, char** argv)
+{
+ Raul::Array<int> array1(32, 2);
+
+ array1[0] = 42;
+ if (array1[0] != 42) {
+ fprintf(stderr, "array1[0] != 42\n");
+ return 1;
+ } else if (array1[1] != 2) {
+ fprintf(stderr, "array1[1] != 2\n");
+ return 1;
+ } else if (array1.size() != 32) {
+ fprintf(stderr, "array1.size() != 1\n");
+ return 1;
+ }
+
+ array1.alloc(16, 0);
+ if (array1[0] != 0) {
+ fprintf(stderr, "array1[0] != 0\n");
+ return 1;
+ } else if (array1.at(0) != 0) {
+ fprintf(stderr, "array1.at(0) != 0\n");
+ return 1;
+ } else if (array1.size() != 16) {
+ fprintf(stderr, "array1.size() != 16\n");
+ return 1;
+ }
+
+ array1.alloc(8, 0);
+ if (array1.size() != 8) {
+ fprintf(stderr, "array1.size() != 8\n");
+ return 1;
+ }
+
+ Raul::Array<int> array2(array1);
+ for (size_t i = 0; i < array1.size(); ++i) {
+ if (array2[i] != array1[i]) {
+ fprintf(stderr, "Mismatch at %zu\n", i);
+ return 1;
+ }
+ }
+
+ Raul::Array<int> array3(8, 47);
+ if (array3[0] != 47) {
+ fprintf(stderr, "array3[0] != 47\n");
+ return 1;
+ } else if (array3.size() != 8) {
+ fprintf(stderr, "array3.size() != 8\n");
+ return 1;
+ }
+
+ return 0;
+}
diff --git a/test/build_test.cpp b/test/build_test.cpp
new file mode 100644
index 0000000..314862c
--- /dev/null
+++ b/test/build_test.cpp
@@ -0,0 +1,36 @@
+/*
+ This file is part of Raul.
+ Copyright 2007-2017 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 "raul/Array.hpp"
+#include "raul/Deletable.hpp"
+#include "raul/DoubleBuffer.hpp"
+#include "raul/Exception.hpp"
+#include "raul/Maid.hpp"
+#include "raul/Noncopyable.hpp"
+#include "raul/Path.hpp"
+#include "raul/Process.hpp"
+#include "raul/RingBuffer.hpp"
+#include "raul/Semaphore.hpp"
+#include "raul/Socket.hpp"
+#include "raul/Symbol.hpp"
+#include "raul/TimeSlice.hpp"
+#include "raul/TimeStamp.hpp"
+
+int
+main(int argc, char** argv)
+{
+ return 0;
+}
diff --git a/test/double_buffer_test.cpp b/test/double_buffer_test.cpp
new file mode 100644
index 0000000..d4d0554
--- /dev/null
+++ b/test/double_buffer_test.cpp
@@ -0,0 +1,42 @@
+/*
+ This file is part of Raul.
+ Copyright 2013 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 "raul/DoubleBuffer.hpp"
+
+using namespace std;
+using namespace Raul;
+
+int
+main(int argc, char** argv)
+{
+ DoubleBuffer<int> db(0);
+
+ if (db.get() != 0) {
+ return 1;
+ }
+
+ db.set(42);
+ if (db.get() != 42) {
+ return 1;
+ }
+
+ db.set(43);
+ if (db.get() != 43) {
+ return 1;
+ }
+
+ return 0;
+}
diff --git a/test/maid_test.cpp b/test/maid_test.cpp
new file mode 100644
index 0000000..e21ba04
--- /dev/null
+++ b/test/maid_test.cpp
@@ -0,0 +1,125 @@
+/*
+ This file is part of Raul.
+ Copyright 2007-2017 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/>.
+*/
+
+#undef NDEBUG
+
+#include <cassert>
+#include <cstdio>
+#include <thread>
+#include <vector>
+
+#include "raul/Maid.hpp"
+
+using Raul::Maid;
+
+static const size_t n_threads = 8;
+static const size_t n_junk_per_thread = 1 << 18;
+
+static std::atomic<size_t> n_junk(0);
+static std::atomic<size_t> n_finished_threads(0);
+
+class Junk : public Maid::Disposable {
+public:
+ explicit Junk(size_t v) : val(v) { ++n_junk; }
+ ~Junk() { --n_junk; }
+
+ size_t val;
+};
+
+static void
+litter(Maid* maid)
+{
+ for (size_t i = 0; i < n_junk_per_thread; ++i) {
+ Maid::managed_ptr<Junk> a = maid->make_managed<Junk>(i);
+ }
+
+ ++n_finished_threads;
+}
+
+static void
+test()
+{
+ Maid maid;
+
+ // Check basic single-threaded correctness
+ {
+ assert(n_junk == 0);
+ Maid::managed_ptr<Junk> a = maid.make_managed<Junk>(1U);
+ assert(n_junk == 1);
+ Maid::managed_ptr<Junk> b = maid.make_managed<Junk>(2U);
+ assert(n_junk == 2);
+ }
+
+ maid.dispose(nullptr); // Mustn't crash
+
+ // All referenes dropped, but deletion deferred
+ assert(n_junk == 2);
+
+ // Trigger actual deletion
+ maid.cleanup();
+ assert(n_junk == 0);
+ assert(maid.empty());
+
+ // Create some threads to produce garbage
+ std::vector<std::thread> litterers;
+ for (size_t i = 0; i < n_threads; ++i) {
+ litterers.push_back(std::thread(litter, &maid));
+ }
+
+ // Wait for some garbage to show up if necessary (unlikely)
+ size_t initial_n_junk = n_junk;
+ while (maid.empty()) {
+ std::this_thread::sleep_for(std::chrono::milliseconds(1));
+ initial_n_junk = n_junk;
+ }
+
+ printf("Starting with %zu initial bits of junk\n", initial_n_junk);
+
+ // Ensure we're actually cleaning things up concurrently
+ maid.cleanup();
+ assert(n_junk != initial_n_junk);
+
+ // Continue cleaning up as long as threads are running
+ size_t n_cleanup_calls = 1;
+ while (n_finished_threads < n_threads) {
+ maid.cleanup();
+ ++n_cleanup_calls;
+ }
+
+ printf("Called cleanup %zu times\n", n_cleanup_calls);
+
+ // Join litterer threads
+ for (auto& t : litterers) {
+ t.join();
+ }
+
+ // Clean up any leftover garbage (unlikely/impossible?)
+ maid.cleanup();
+ assert(n_junk == 0);
+
+ // Allocate a new object, then let it and the Maid go out of scope
+ Maid::managed_ptr<Junk> c = maid.make_managed<Junk>(5U);
+ assert(n_junk == 1);
+}
+
+int
+main(int argc, char** argv)
+{
+ assert(n_junk == 0);
+ test();
+ assert(n_junk == 0);
+ return 0;
+}
diff --git a/test/path_test.cpp b/test/path_test.cpp
new file mode 100644
index 0000000..01f55c0
--- /dev/null
+++ b/test/path_test.cpp
@@ -0,0 +1,101 @@
+/*
+ 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 <cstring>
+#include <iostream>
+
+#include "raul/Path.hpp"
+
+using namespace std;
+using namespace Raul;
+
+int
+main()
+{
+#define CHECK(cond) \
+ do { if (!(cond)) { \
+ cerr << "Test failed: " << (cond) << endl; \
+ return 1; \
+ } } while (0)
+
+ CHECK(Path("/foo/bar").parent() == Path("/foo"));
+ CHECK(Path("/foo").parent() == Path("/"));
+ CHECK(Path("/").parent() == Path("/"));
+
+ CHECK(Path("/").is_parent_of(Path("/foo")));
+ CHECK(Path("/foo").is_parent_of(Path("/foo/bar")));
+ CHECK(!(Path("/foo").is_parent_of(Path("/foo2"))));
+ CHECK(!(Path("/foo").is_parent_of(Path("/foo"))));
+
+ CHECK(Path::lca(Path("/foo"), Path("/foo/bar/baz")) == Path("/"));
+ CHECK(Path::lca(Path("/foo/bar"), Path("/foo/bar/baz")) == Path("/foo"));
+ CHECK(Path::lca(Path("/foo/bar/quux"), Path("/foo/bar/baz")) == Path("/foo/bar"));
+
+ CHECK(!Path::is_valid(""));
+ CHECK(!Path::is_valid("hello"));
+ CHECK(!Path::is_valid("/foo/bar/"));
+ CHECK(!Path::is_valid("/foo//bar"));
+ CHECK(!Path::is_valid("/foo/bar/d*s"));
+ CHECK(Path::is_valid("/"));
+ CHECK(!Path::is_valid("/foo/3foo/bar"));
+
+ CHECK(Path::descendant_comparator(Path("/"), Path("/")));
+ CHECK(Path::descendant_comparator(Path("/"), Path("/foo")));
+ CHECK(Path::descendant_comparator(Path("/foo"), Path("/foo/bar")));
+ CHECK(Path::descendant_comparator(Path("/foo"), Path("/foo")));
+ CHECK(Path::descendant_comparator(Path("/"), Path("/")));
+ CHECK(!Path::descendant_comparator(Path("/baz"), Path("/")));
+ CHECK(!Path::descendant_comparator(Path("/foo"), Path("/bar")));
+ CHECK(!Path::descendant_comparator(Path("/foo/bar"), Path("/foo")));
+
+ CHECK(!Symbol::is_valid(""));
+ CHECK(!Symbol::is_valid("/I/have/slashes"));
+ CHECK(!Symbol::is_valid("!illegalchar"));
+ CHECK(!Symbol::is_valid("0illegalleadingdigit"));
+ CHECK(strcmp(Symbol::symbolify("").c_str(), ""));
+
+ CHECK(Path("/foo").child(Symbol("bar")) == "/foo/bar");
+ CHECK(Path("/foo").child(Path("/bar/baz")) == "/foo/bar/baz");
+ CHECK(Path("/foo").child(Path("/")) == "/foo");
+
+ CHECK(!strcmp(Path("/foo").symbol(), "foo"));
+ CHECK(!strcmp(Path("/foo/bar").symbol(), "bar"));
+ CHECK(!strcmp(Path("/").symbol(), ""));
+
+ Path original(std::string("/foo/bar"));
+ Path copy(original);
+ CHECK(original == copy);
+
+ bool valid = true;
+ try {
+ Path path("/ends/in/slash/");
+ } catch (const Path::BadPath& e) {
+ std::cerr << "Caught exception: " << e.what() << std::endl;
+ valid = false;
+ }
+ CHECK(!valid);
+
+ valid = true;
+ try {
+ Path path(std::string("/has//double/slash"));
+ } catch (const Path::BadPath& e) {
+ std::cerr << "Caught exception: " << e.what() << std::endl;
+ valid = false;
+ }
+ CHECK(!valid);
+
+ return 0;
+}
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;
+}
diff --git a/test/sem_test.cpp b/test/sem_test.cpp
new file mode 100644
index 0000000..f44fc5e
--- /dev/null
+++ b/test/sem_test.cpp
@@ -0,0 +1,74 @@
+/*
+ This file is part of Raul.
+ Copyright 2007-2017 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/>.
+*/
+
+#undef NDEBUG
+
+#include <cassert>
+#include <chrono>
+#include <iostream>
+#include <limits>
+#include <thread>
+
+#include "raul/Semaphore.hpp"
+
+static void
+wait_for_sem(Raul::Semaphore* sem)
+{
+ sem->wait();
+}
+
+static void
+timed_wait_for_sem(Raul::Semaphore* sem)
+{
+ while (!sem->timed_wait(std::chrono::milliseconds(100))) {}
+}
+
+int
+main()
+{
+ Raul::Semaphore sem(0);
+ assert(!sem.try_wait());
+
+ // Check that semaphore wakes up strict waiter
+ std::thread waiter(wait_for_sem, &sem);
+ std::this_thread::sleep_for(std::chrono::milliseconds(100));
+ sem.post();
+ waiter.join();
+
+ // Check that semaphore wakes up timed waiter
+ std::thread timed_waiter(timed_wait_for_sem, &sem);
+ std::this_thread::sleep_for(std::chrono::milliseconds(100));
+ sem.post();
+ timed_waiter.join();
+
+ // Check that timed_wait actually waits
+ const auto start = std::chrono::steady_clock::now();
+ sem.timed_wait(std::chrono::milliseconds(100));
+ const auto end = std::chrono::steady_clock::now();
+ assert(end - start > std::chrono::milliseconds(100));
+ assert(end - start < std::chrono::milliseconds(200));
+
+ // Check that we can't successfully wait on a zero semaphore
+ assert(!sem.timed_wait(std::chrono::milliseconds(100)));
+
+ // Check that initial value works correctly
+ Raul::Semaphore sem2(2);
+ assert(sem2.wait());
+ assert(sem2.wait());
+ assert(!sem2.try_wait());
+
+ return 0;
+}
diff --git a/test/socket_test.cpp b/test/socket_test.cpp
new file mode 100644
index 0000000..8dd4aff
--- /dev/null
+++ b/test/socket_test.cpp
@@ -0,0 +1,111 @@
+/*
+ This file is part of Raul.
+ Copyright 2007-2014 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 <stdio.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <unistd.h>
+
+#include "raul/Socket.hpp"
+
+using namespace std;
+using namespace Raul;
+
+int
+main(int argc, char** argv)
+{
+ std::string unix_uri("unix:///tmp/raul_test_sock");
+ std::string tcp_uri("tcp://127.0.0.1:12345");
+
+ Raul::Socket unix_server_sock(Socket::Type::UNIX);
+ Raul::Socket tcp_server_sock(Socket::Type::TCP);
+ if (!unix_server_sock.bind(unix_uri)) {
+ fprintf(stderr, "Failed to bind UNIX server socket (%s)\n",
+ strerror(errno));
+ return 1;
+ } else if (!unix_server_sock.listen()) {
+ fprintf(stderr, "Failed to listen on UNIX server socket (%s)\n",
+ strerror(errno));
+ return 1;
+ } else if (!tcp_server_sock.bind(tcp_uri)) {
+ fprintf(stderr, "Failed to bind TCP server socket (%s)\n",
+ strerror(errno));
+ return 1;
+ } else if (!tcp_server_sock.listen()) {
+ fprintf(stderr, "Failed to listen on TCP server socket (%s)\n",
+ strerror(errno));
+ return 1;
+ }
+
+ const pid_t child_pid = fork();
+ if (child_pid) {
+ // This is the parent (server) process
+ int status = 0;
+ waitpid(child_pid, &status, 0);
+
+ struct pollfd pfds[2];
+ pfds[0].fd = unix_server_sock.fd();
+ pfds[0].events = POLLIN;
+ pfds[0].revents = 0;
+ pfds[1].fd = tcp_server_sock.fd();
+ pfds[1].events = POLLIN;
+ pfds[1].revents = 0;
+
+ unsigned n_received = 0;
+ while (n_received < 2) {
+ const int ret = poll(pfds, 2, -1);
+ if (ret == -1) {
+ fprintf(stderr, "poll error (%s)\n", strerror(errno));
+ break;
+ } else if ((pfds[0].revents & POLLHUP) || pfds[1].revents & POLLHUP) {
+ break;
+ } else if (ret == 0) {
+ fprintf(stderr, "poll returned with no data\n");
+ continue;
+ }
+
+ if (pfds[0].revents & POLLIN) {
+ std::shared_ptr<Socket> conn = unix_server_sock.accept();
+ ++n_received;
+ }
+
+ if (pfds[1].revents & POLLIN) {
+ std::shared_ptr<Socket> conn = tcp_server_sock.accept();
+ ++n_received;
+ }
+ }
+
+ unix_server_sock.shutdown();
+ tcp_server_sock.shutdown();
+ unlink("/tmp/raul_test_sock");
+ fprintf(stderr, "n received: %d\n", n_received);
+ return n_received != 2;
+ }
+
+ // This is the child (client) process
+ Raul::Socket unix_sock(Socket::Type::UNIX);
+ Raul::Socket tcp_sock(Socket::Type::TCP);
+
+ if (!unix_sock.connect(unix_uri)) {
+ fprintf(stderr, "Failed to connect to UNIX socket\n");
+ return 1;
+ } else if (!tcp_sock.connect(tcp_uri)) {
+ fprintf(stderr, "Failed to connect to TCP socket\n");
+ return 1;
+ }
+
+ return 0;
+}
diff --git a/test/symbol_test.cpp b/test/symbol_test.cpp
new file mode 100644
index 0000000..5164998
--- /dev/null
+++ b/test/symbol_test.cpp
@@ -0,0 +1,77 @@
+/*
+ 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 <cstring>
+#include <iostream>
+#include <list>
+
+#include "raul/Path.hpp"
+
+using namespace std;
+using namespace Raul;
+
+int
+main()
+{
+#define CHECK(cond) \
+ do { if (!(cond)) { \
+ cerr << "Test failed: " << (cond) << endl; \
+ return 1; \
+ } } while (0)
+
+ list<string> names;
+ names.push_back("Dry/Wet Balance");
+ names.push_back("foo+1bar(baz)");
+ names.push_back("ThisCRAR");
+ names.push_back("NAME");
+ names.push_back("thing with a bunch of spaces");
+ names.push_back("thing-with-a-bunch-of-dashes");
+ names.push_back("CamelCaseABC");
+ names.push_back("Signal Level [dB]");
+ names.push_back("Gain dB");
+ names.push_back("Dry/Wet Balance");
+ names.push_back("Phaser1 - Similar to CSound's phaser1 by Sean Costello");
+ names.push_back("1");
+ names.push_back("");
+
+ for (list<string>::iterator i = names.begin(); i != names.end(); ++i) {
+ CHECK(!Symbol::symbolify(*i).empty());
+ }
+
+ Symbol original("sym");
+ Symbol copy(original);
+ CHECK(original == copy);
+
+ bool valid = true;
+ try {
+ Symbol symbol("0startswithdigit");
+ } catch (const Symbol::BadSymbol& e) {
+ std::cerr << "Caught exception: " << e.what() << std::endl;
+ valid = false;
+ }
+ CHECK(!valid);
+
+ valid = true;
+ try {
+ Symbol symbol(std::string("invalid/symbol"));
+ } catch (const Symbol::BadSymbol& e) {
+ std::cerr << "Caught exception: " << e.what() << std::endl;
+ valid = false;
+ }
+ CHECK(!valid);
+
+ return 0;
+}
diff --git a/test/thread_test.cpp b/test/thread_test.cpp
new file mode 100644
index 0000000..9012b4c
--- /dev/null
+++ b/test/thread_test.cpp
@@ -0,0 +1,69 @@
+/*
+ This file is part of Raul.
+ Copyright 2007-2017 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 <atomic>
+#include <iostream>
+#include <thread>
+
+#include "raul/Semaphore.hpp"
+
+using namespace std;
+using namespace Raul;
+
+namespace {
+
+thread_local int var(0);
+std::atomic<int> n_errors(0);
+
+void
+wait_for_sem(Semaphore* sem)
+{
+ var = 41;
+ cout << "[Waiter] Waiting for signal..." << endl;
+ sem->wait();
+ cout << "[Waiter] Received signal, exiting" << endl;
+ var = 42;
+ if (var != 42) {
+ cerr << "[Waiter] var != 42" << endl;
+ ++n_errors;
+ }
+}
+
+} // namespace
+
+int
+main()
+{
+ Semaphore sem(0);
+ std::thread waiter(wait_for_sem, &sem);
+
+ var = 24;
+
+ cout << "[Main] Signalling..." << endl;
+ sem.post();
+
+ cout << "[Main] Waiting for waiter..." << endl;
+ waiter.join();
+
+ cout << "[Main] Exiting" << endl;
+
+ if (var != 24) {
+ cerr << "[Main] var != 24" << endl;
+ ++n_errors;
+ }
+
+ return n_errors.load();
+}
diff --git a/test/time_test.cpp b/test/time_test.cpp
new file mode 100644
index 0000000..69416cd
--- /dev/null
+++ b/test/time_test.cpp
@@ -0,0 +1,44 @@
+/*
+ This file is part of Raul.
+ Copyright 2007-2015 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 "raul/TimeStamp.hpp"
+#include "raul/TimeSlice.hpp"
+#include <iostream>
+
+using namespace std;
+using namespace Raul;
+
+int
+main()
+{
+ TimeUnit unit(TimeUnit::BEATS, 19200);
+ TimeSlice ts(48000, 19200, 120.0);
+
+ double in_double = 2.5;
+
+ TimeStamp t(unit, static_cast<uint32_t>(in_double),
+ static_cast<uint32_t>((in_double - static_cast<uint32_t>(in_double)) * unit.ppt()));
+
+ cout << "\tSeconds: ";
+ cout << ts.beats_to_seconds(t);
+ cout << endl;
+
+ cout << "\tTicks: ";
+ cout << ts.beats_to_ticks(t);
+ cout << endl;
+
+ return 0;
+}