summaryrefslogtreecommitdiffstats
path: root/test
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2010-01-07 21:27:39 +0000
committerDavid Robillard <d@drobilla.net>2010-01-07 21:27:39 +0000
commit0d009a4e980e40dc8a9c9b5e3d25c3fafb363e95 (patch)
tree4d41dea009f1647519af8df10f114cd7a6165792 /test
parent61ac4a41f0aea63f45d7b27be3ef2e0554e93ece (diff)
downloadraul-0d009a4e980e40dc8a9c9b5e3d25c3fafb363e95.tar.gz
raul-0d009a4e980e40dc8a9c9b5e3d25c3fafb363e95.tar.bz2
raul-0d009a4e980e40dc8a9c9b5e3d25c3fafb363e95.zip
Move unit testing and coverage framework into autowaf.
Make raul tests return 0 on success, 1 on failure. Test coverage for Raul. git-svn-id: http://svn.drobilla.net/lad/trunk/raul@2368 a436a847-0d15-0410-975c-d299462d15a1
Diffstat (limited to 'test')
-rw-r--r--test/atomic_test.cpp14
-rw-r--r--test/list_test.cpp141
-rw-r--r--test/midi_ringbuffer_test.cpp43
-rw-r--r--test/path_test.cpp68
-rw-r--r--test/quantize_test.cpp25
-rw-r--r--test/queue_test.cpp254
-rw-r--r--test/ringbuffer_test.cpp47
-rw-r--r--test/smf_test.cpp62
-rw-r--r--test/table_test.cpp379
-rw-r--r--test/thread_test.cpp19
-rw-r--r--test/time_test.cpp32
11 files changed, 1084 insertions, 0 deletions
diff --git a/test/atomic_test.cpp b/test/atomic_test.cpp
new file mode 100644
index 0000000..6611c91
--- /dev/null
+++ b/test/atomic_test.cpp
@@ -0,0 +1,14 @@
+#include <iostream>
+#include "raul/AtomicInt.hpp"
+#include "raul/AtomicPtr.hpp"
+
+using namespace std;
+using namespace Raul;
+
+int
+main()
+{
+ cout << "Well, at least I compiled; that's gotta count for something eh?" << endl;
+
+ return 0;
+}
diff --git a/test/list_test.cpp b/test/list_test.cpp
new file mode 100644
index 0000000..664ca5b
--- /dev/null
+++ b/test/list_test.cpp
@@ -0,0 +1,141 @@
+#include <iostream>
+#include <cstddef>
+#include "raul/log.hpp"
+#include "raul/List.hpp"
+
+using namespace std;
+using namespace Raul;
+
+int
+main()
+{
+#define CHECK(cond) \
+ do { if (!(cond)) { \
+ error << "Test at " << __FILE__ << ":" << __LINE__ << " failed: " << __STRING(cond) << endl; \
+ return 1; \
+ } } while (0)
+
+ List<int> l;
+
+ l.push_back(new List<int>::Node(1));
+ l.push_back(new List<int>::Node(2));
+ l.push_back(new List<int>::Node(3));
+ l.push_back(new List<int>::Node(4));
+ l.push_back(new List<int>::Node(5));
+ l.push_back(new List<int>::Node(6));
+ l.push_back(new List<int>::Node(7));
+ l.push_back(new List<int>::Node(8));
+
+ /*cout << "List:" << endl;
+ for (List<int>::iterator i = l.begin(); i != l.end(); ++i) {
+ cout << *i << endl;
+ }
+ cout << endl;*/
+
+ // Remove 4
+ for (List<int>::iterator i = l.begin(); i != l.end(); ++i) {
+ if ((*i) == 4) {
+ l.erase(i);
+ break;
+ }
+ }
+
+ // Check
+ int idx = 0;
+ for (List<int>::iterator i = l.begin(); i != l.end(); ++i, ++idx) {
+ if (idx < 3)
+ CHECK(*i == idx + 1);
+ else
+ CHECK(*i == idx + 2);
+ }
+
+ // Remove 1 (head)
+ for (List<int>::iterator i = l.begin(); i != l.end(); ++i) {
+ if ((*i) == 1) {
+ l.erase(i);
+ break;
+ }
+ }
+
+ // Check
+ idx = 0;
+ for (List<int>::iterator i = l.begin(); i != l.end(); ++i, ++idx) {
+ if (idx < 2)
+ CHECK(*i == idx + 2);
+ else
+ CHECK(*i == idx + 3);
+ }
+
+ // Remove 8 (tail)
+ for (List<int>::iterator i = l.begin(); i != l.end(); ++i) {
+ if ((*i) == 8) {
+ l.erase(i);
+ break;
+ }
+ }
+
+ // Check
+ idx = 0;
+ for (List<int>::iterator i = l.begin(); i != l.end(); ++i, ++idx) {
+ if (idx < 2)
+ CHECK(*i == idx + 2);
+ else if (idx < 4)
+ CHECK(*i == idx + 3);
+ else
+ CHECK(*i == 7);
+ }
+
+ // Create, push, erase (should get empty list)
+ List<int> r;
+ r.push_back(new List<int>::Node(9));
+ r.erase(r.begin());
+ CHECK(r.size() == 0);
+ CHECK(r.empty());
+
+ // Appending to an empty list
+ l.clear();
+ CHECK(l.size() == 0);
+ CHECK(l.empty());
+
+ List<int> l2;
+ l2.push_back(new List<int>::Node(0));
+ l2.push_back(new List<int>::Node(2));
+ l2.push_back(new List<int>::Node(4));
+ l2.push_back(new List<int>::Node(6));
+
+ l.append(l2);
+ idx = 0;
+ for (List<int>::iterator i = l.begin(); i != l.end(); ++i, ++idx) {
+ CHECK(*i == idx * 2);
+ }
+
+ // Appending non-empty lists
+ l2.push_back(new List<int>::Node(5));
+ l2.push_back(new List<int>::Node(6));
+ l2.push_back(new List<int>::Node(7));
+ l2.push_back(new List<int>::Node(8));
+
+ l.append(l2);
+ idx = 0;
+ for (List<int>::iterator i = l.begin(); i != l.end(); ++i, ++idx) {
+ if (idx < 4)
+ CHECK(*i == idx * 2);
+ else
+ CHECK(*i == idx + 1);
+ }
+
+
+ // Appending an empty list
+ l2.clear();
+ l.append(l2);
+
+ idx = 0;
+ for (List<int>::iterator i = l.begin(); i != l.end(); ++i, ++idx) {
+ if (idx < 4)
+ CHECK(*i == idx * 2);
+ else
+ CHECK(*i == idx + 1);
+ }
+
+ return 0;
+}
diff --git a/test/midi_ringbuffer_test.cpp b/test/midi_ringbuffer_test.cpp
new file mode 100644
index 0000000..f75cfd5
--- /dev/null
+++ b/test/midi_ringbuffer_test.cpp
@@ -0,0 +1,43 @@
+#include <iostream>
+#include <cstring>
+#include <cstdio>
+#include <stdio.h>
+#include "raul/TimeStamp.hpp"
+#include "raul/EventRingBuffer.hpp"
+#include "raul/midi_names.h"
+
+using namespace std;
+using namespace Raul;
+
+int
+read_write_test(EventRingBuffer& rb, unsigned offset)
+{
+ TimeStamp t(TimeUnit(TimeUnit::FRAMES, 48000), 0, 0);
+ size_t size;
+ unsigned char write_buf[5];
+ unsigned char read_buf[5];
+
+ snprintf((char*)write_buf, 5, "%d", offset);
+ size = strlen((char*)write_buf);
+
+ const size_t written = rb.write(t, size, write_buf);
+ assert(written == size);
+
+ rb.read(&t, &size, read_buf);
+
+ return (strncmp((const char*)write_buf, (const char*)read_buf, size));
+}
+
+
+int
+main()
+{
+ EventRingBuffer rb(32);
+
+ for (size_t i = 0; i < 1000000; ++i)
+ if (read_write_test(rb, i))
+ return 1;
+
+ return 0;
+}
+
diff --git a/test/path_test.cpp b/test/path_test.cpp
new file mode 100644
index 0000000..099b463
--- /dev/null
+++ b/test/path_test.cpp
@@ -0,0 +1,68 @@
+#include <iostream>
+#include <list>
+#include "raul/log.hpp"
+#include "raul/Path.hpp"
+
+using namespace std;
+using namespace Raul;
+
+int
+main()
+{
+#define CHECK(cond) \
+ do { if (!(cond)) { \
+ error << "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");
+
+ for (list<string>::iterator i = names.begin(); i != names.end(); ++i) {
+ CHECK(Symbol::is_valid(Path::nameify(*i)));
+ CHECK(Symbol::is_valid(Symbol::symbolify(*i)));
+ }
+
+ 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::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("/", "/foo"));
+ CHECK(Path::descendant_comparator("/foo", "/foo/bar"));
+ CHECK(Path::descendant_comparator("/foo", "/foo"));
+ CHECK(Path::descendant_comparator("/", "/"));
+ CHECK(!Path::descendant_comparator("/baz", "/"));
+ CHECK(!Path::descendant_comparator("/foo", "/bar"));
+ CHECK(!Path::descendant_comparator("/foo/bar", "/foo"));
+
+ CHECK(!Symbol::is_valid(""));
+ CHECK(!Symbol::is_valid("/I/have/slashes"));
+ CHECK(!Symbol::is_valid("!illegalchar"));
+ CHECK(!Symbol::is_valid("0illegalleadingdigit"));
+ CHECK(Symbol::is_valid(Symbol::symbolify("")));
+ CHECK(Symbol::is_valid(Symbol::symbolify("1hello")));
+
+ return 0;
+}
diff --git a/test/quantize_test.cpp b/test/quantize_test.cpp
new file mode 100644
index 0000000..39ba899
--- /dev/null
+++ b/test/quantize_test.cpp
@@ -0,0 +1,25 @@
+#include "raul/Quantizer.hpp"
+#include <iostream>
+
+using namespace std;
+using namespace Raul;
+
+
+int
+main()
+{
+ TimeStamp q(TimeUnit(TimeUnit::BEATS, 19200), 0.25);
+
+ for (double in = 0.0; in < 32; in += 0.23) {
+ TimeStamp beats(TimeUnit(TimeUnit::BEATS, 19200), in);
+
+ cout << "Q(" << in << ", 1/4) = "
+ << Quantizer::quantize(q, beats) << endl;
+
+ if (Quantizer::quantize(q, beats).subticks() % (19200/4) != 0)
+ return 1;
+ }
+
+ return 0;
+}
+
diff --git a/test/queue_test.cpp b/test/queue_test.cpp
new file mode 100644
index 0000000..49ba6f2
--- /dev/null
+++ b/test/queue_test.cpp
@@ -0,0 +1,254 @@
+#include <iostream>
+#include <string>
+#include <vector>
+#include <algorithm>
+#include <stdio.h>
+#include <stdlib.h>
+#include "raul/SRSWQueue.hpp"
+#include "raul/SRMWQueue.hpp"
+#include "raul/Thread.hpp"
+#include "raul/AtomicInt.hpp"
+
+using namespace std;
+using namespace Raul;
+
+static const unsigned NUM_DATA = 10;
+static const unsigned QUEUE_SIZE = 128;
+static const unsigned NUM_WRITERS = 2;
+static const unsigned PUSHES_PER_ITERATION = 3;
+
+// Data to read/write using actions pumped through the queue
+struct Record {
+ Record() : read_count(0), write_count(0) {}
+
+ AtomicInt read_count;
+ AtomicInt write_count;
+};
+
+Record data[NUM_DATA];
+
+
+// Actions pumped through the queue to manipulate data
+struct WriteAction {
+ WriteAction(unsigned idx) : index(idx) {}
+
+ inline void read() const {
+ ++(data[index].read_count);
+ };
+
+ unsigned index;
+};
+
+
+// The victim
+SRMWQueue<WriteAction> queue(QUEUE_SIZE);
+
+
+class WriteThread : public Thread {
+protected:
+ void _run() {
+ // Wait for everything to get ready
+ sleep(1);
+
+ while (true) {
+ for (unsigned j=0; j < PUSHES_PER_ITERATION; ++j) {
+ unsigned i = rand() % NUM_DATA;
+ if (queue.push(WriteAction(i))) {
+ ++(data[i].write_count);
+ //cout << "WRITE " << i << "\r\n";
+ } else {
+ //cerr << "FAILED WRITE\r\n";
+ }
+ }
+
+ // This thread will never cancel without this here since
+ // this loop is hard RT safe and thus cancellation point free
+ pthread_testcancel();
+ }
+
+ cout << "Writer exiting." << endl;
+ }
+};
+
+
+// Returns 0 if all read count/write count pairs are equal,
+// otherwise how far off total count was
+unsigned
+data_is_sane()
+{
+ unsigned ret = 0;
+ for (unsigned i = 0; i < NUM_DATA; ++i) {
+ unsigned diff = abs(data[i].read_count.get() - data[i].write_count.get());
+ ret += diff;
+ }
+
+ return ret;
+}
+
+
+void
+dump_data()
+{
+ for (unsigned i = 0; i < NUM_DATA; ++i) {
+ cout << i << ":\t" << data[i].read_count.get()
+ << "\t : \t" << data[i].write_count.get();
+ if (data[i].read_count.get() == data[i].write_count.get())
+ cout << "\t OK" << endl;
+ else
+ cout << "\t FAIL" << endl;
+ }
+}
+
+
+int
+main()
+{
+ unsigned long total_processed = 0;
+
+ cout << "Testing size" << endl;
+ for (unsigned i=0; i < queue.capacity(); ++i) {
+ queue.push(i);
+ if (i == queue.capacity()-1) {
+ if (!queue.full()) {
+ cerr << "ERROR: Should be full at " << i
+ << " (size " << queue.capacity() << ")" << endl;
+ return -1;
+ }
+ } else {
+ if (queue.full()) {
+ cerr << "ERROR: Prematurely full at " << i
+ << " (size " << queue.capacity() << ")" << endl;
+ return -1;
+ }
+ }
+ }
+
+ for (unsigned i = 0; i < queue.capacity(); ++i)
+ queue.pop();
+
+ if (!queue.empty()) {
+ cerr << "ERROR: Should be empty" << endl;
+ return -1;
+ }
+
+ cout << "Testing concurrent reading/writing" << endl;
+ vector<WriteThread*> writers(NUM_WRITERS, new WriteThread());
+
+ for (unsigned i=0; i < NUM_WRITERS; ++i) {
+ writers[i]->set_name(string("Writer ") + (char)('0' + i));
+ writers[i]->start();
+ }
+
+ sleep(1);
+
+ // Read
+ unsigned count = 0;
+ for (unsigned i = 0; i < 10000000; ++i) {
+ while (count < queue.capacity() && !queue.empty()) {
+ WriteAction action = queue.front();
+ queue.pop();
+ action.read();
+ ++count;
+ ++total_processed;
+ }
+
+ /*if (count > 0)
+ cout << "Processed " << count << " requests\t\t"
+ << "(total " << total_processed << ")\r\n";
+
+ if (total_processed > 0 && total_processed % 128l == 0)
+ cout << "Total processed: " << total_processed << "\r\n";*/
+ }
+
+ cout << "Processed " << total_processed << " requests" << endl;
+
+ // Stop the writers
+ for (unsigned i=0; i < NUM_WRITERS; ++i)
+ writers[i]->stop();
+
+ //cout << "\n\n****************** DONE *********************\n\n";
+
+ unsigned leftovers = 0;
+
+ // Drain anything left in the queue
+ while (!queue.empty()) {
+ WriteAction action = queue.front();
+ queue.pop();
+ action.read();
+ leftovers++;
+ ++total_processed;
+ }
+
+ if (leftovers > 0)
+ cout << "Processed " << leftovers << " leftovers." << endl;
+
+
+ //cout << "\n\n*********************************************\n\n";
+
+ cout << "Total processed: " << total_processed << endl;
+ if (total_processed > INT_MAX)
+ cout << "(Counter had to wrap)" << endl;
+ else
+ cout << "(Counter did NOT have to wrap)" << endl;
+
+
+ const unsigned diff = data_is_sane();
+
+ if (diff == 0) {
+ return EXIT_SUCCESS;
+ } else {
+ cout << "FAILED BY " << diff << endl;
+ return EXIT_FAILURE;
+ }
+
+ //dump_data();
+
+ return 0;
+}
+
+
+#if 0
+int main()
+{
+ //SRSWQueue<int> q(10);
+ SRMWQueue<int> q(10);
+
+ cout << "New queue. Should be empty: " << q.empty() << endl;
+ cout << "Capacity: " << q.capacity() << endl;
+ //cout << "Fill: " << q.fill() << endl;
+
+ for (uint i=0; i < 5; ++i) {
+ q.push(i);
+ assert(!q.full());
+ q.pop();
+ }
+ cout << "Pushed and popped 5 elements. Queue should be empty: " << q.empty() << endl;
+ //cout << "Fill: " << q.fill() << endl;
+
+ for (uint i=10; i < 20; ++i) {
+ assert(q.push(i));
+ }
+ cout << "Pushed 10 elements. Queue should be full: " << q.full() << endl;
+ //cout << "Fill: " << q.fill() << endl;
+
+ cout << "The digits 10->19 should print: " << endl;
+ while (!q.empty()) {
+ int foo = q.front();
+ q.pop();
+ cout << "Popped: " << foo << endl;
+ }
+ cout << "Queue should be empty: " << q.empty() << endl;
+ //cout << "Fill: " << q.fill() << endl;
+
+ cout << "Attempting to add eleven elements to queue of size 10. Only first 10 should succeed:" << endl;
+ for (uint i=20; i <= 39; ++i) {
+ cout << i;
+ //cout << " - Fill: " << q.fill();
+ cout << " - full: " << q.full();
+ cout << ", succeeded: " << q.push(i) << endl;
+ }
+
+ return 0;
+}
+#endif
+
diff --git a/test/ringbuffer_test.cpp b/test/ringbuffer_test.cpp
new file mode 100644
index 0000000..87b81c6
--- /dev/null
+++ b/test/ringbuffer_test.cpp
@@ -0,0 +1,47 @@
+#include <iostream>
+#include <cstring>
+#include "raul/RingBuffer.hpp"
+
+using namespace std;
+using namespace Raul;
+
+void
+print_buf(size_t size, char* buf)
+{
+ cout << "{ ";
+ for (size_t i=0; i < size; ++i) {
+ cout << buf[i];
+ if (i < size-1)
+ cout << ", ";
+ }
+
+ cout << " }" << endl;
+}
+
+
+int
+main()
+{
+ RingBuffer<char> rb(5);
+
+ char ev[] = { 'a', 'b', 'c' };
+
+ rb.write(3, ev);
+
+ char buf[3];
+ rb.read(3, buf);
+ print_buf(3, buf);
+
+ char ev2[] = { 'd', 'e', 'f' };
+ rb.write(3, ev2);
+
+
+ size_t read = rb.read(3, buf);
+ if (read < 3)
+ rb.read(3 - read, buf + read);
+
+ print_buf(3, buf);
+
+ return 0;
+}
+
diff --git a/test/smf_test.cpp b/test/smf_test.cpp
new file mode 100644
index 0000000..40465ed
--- /dev/null
+++ b/test/smf_test.cpp
@@ -0,0 +1,62 @@
+#include <iostream>
+#include <string>
+#include "raul/SMFReader.hpp"
+#include "raul/SMFWriter.hpp"
+
+using namespace std;
+using namespace Raul;
+
+
+int
+main(int argc, char** argv)
+{
+ const char* filename = NULL;
+
+ if (argc < 2) {
+ filename = "./test.mid";
+ SMFWriter writer(TimeUnit(TimeUnit::BEATS, 19200));
+ writer.start(string(filename), TimeStamp(writer.unit(), 0, 0));
+ writer.finish();
+ cout << "Wrote " << filename << " with PPQN = " << writer.unit().ppt() << endl;
+
+ } else {
+ filename = argv[1];
+ }
+
+
+ SMFReader reader;
+ bool opened = reader.open(filename);
+
+ if (!opened) {
+ cerr << "Unable to open SMF file " << filename << endl;
+ return -1;
+ }
+
+ cout << "Opened SMF file " << filename << endl;
+
+ cout << "Type: " << reader.type() << endl;
+ cout << "Num tracks: " << reader.num_tracks() << endl;
+ cout << "PPQN: " << reader.ppqn() << endl;
+
+ for (unsigned t=1; t <= reader.num_tracks(); ++t) {
+ cout << "******** Track " << t << " ********" << endl;
+ reader.seek_to_track(t);
+
+ unsigned char buf[4];
+ uint32_t ev_size;
+ uint32_t ev_delta_time;
+ while (reader.read_event(4, buf, &ev_size, &ev_delta_time) >= 0) {
+
+ cout << "Event, size = " << ev_size << ", time = " << ev_delta_time;
+ cout << ":\t";
+ cout.flags(ios::hex);
+ for (uint32_t i=0; i < ev_size; ++i) {
+ cout << "0x" << (int)buf[i] << " ";
+ }
+ cout.flags(ios::dec);
+ cout << endl;
+ }
+ }
+
+ return 0;
+}
diff --git a/test/table_test.cpp b/test/table_test.cpp
new file mode 100644
index 0000000..882873a
--- /dev/null
+++ b/test/table_test.cpp
@@ -0,0 +1,379 @@
+#include <string>
+#include <iostream>
+#include <utility>
+#include <map>
+#include <set>
+#include <sys/time.h>
+#include "raul/PathTable.hpp"
+#include "raul/Table.hpp"
+#include "raul/TableImpl.hpp"
+
+//#define WITH_TR1 1
+
+#ifdef WITH_TR1
+ #define BOOST_MULTI_INDEX_DISABLE_SERIALIZATION 1
+ #include <boost/functional/hash.hpp>
+ #include <tr1/unordered_map>
+#endif
+
+using namespace Raul;
+using namespace std;
+
+int range_end_val;
+
+bool range_comparator(const int& a, const int& b)
+{
+ bool ret = (b >= a && b <= range_end_val);
+ //cout << "COMP: " << a << " . " << b << " = " << ret << endl;
+ return ret;
+}
+
+void benchmark(size_t n);
+
+int
+main(int argc, char** argv)
+{
+ if (argc == 3 && !strcmp(argv[1], "-b")) {
+ benchmark(atoi(argv[2]));
+ return 0;
+ }
+
+ cout << "run with -b num_elems to benchmark" << endl;
+ srand(time(NULL));
+
+ range_end_val = rand()%10;
+
+ Table<int, int> t;
+ for (size_t i=0; i < 20; ++i) {
+ int val = rand()%10;
+ t.insert(make_pair(val, val));
+ }
+
+ t[20] = 20;
+ t[21] = 21;
+
+ cout << "Contents:" << endl;
+ for (Table<int,int>::const_iterator i = t.begin(); i != t.end(); ++i)
+ cout << i->first << " ";
+ cout << endl;
+
+ std::cout << "Range " << t.begin()->first << " .. " << range_end_val << std::endl;
+
+ Table<int,int>::const_iterator range_begin = t.begin();
+ ++range_begin; ++range_begin;
+
+ Table<int,int>::iterator range_end = t.find_range_end(t.begin(), range_comparator);
+
+ for (Table<int,int>::const_iterator i = t.begin(); i != range_end; ++i)
+ cout << i->first << " ";
+ cout << endl;
+
+ Table<int, int>::iterator first = t.begin();
+ ++first;
+ Table<int, int>::iterator last = first;
+ ++last; ++last; ++last;
+
+ cout << "Erasing elements 1..3:" << endl;
+ t.erase(first, last);
+
+ for (Table<int,int>::const_iterator i = t.begin(); i != t.end(); ++i)
+ cout << i->first << " ";
+ cout << endl;
+
+ cout << "Erasing elements 0..3" << endl;
+ first = t.begin();
+ last = first;
+ ++last; ++last; ++last;
+ t.erase(first, last);
+
+ for (Table<int,int>::const_iterator i = t.begin(); i != t.end(); ++i)
+ cout << i->first << " ";
+ cout << endl;
+
+ cout << "Erasing elements end()-2..end()" << endl;
+ last = t.end();
+ first = last;
+ --first; --first;
+ t.erase(first, last);
+
+ for (Table<int,int>::const_iterator i = t.begin(); i != t.end(); ++i)
+ cout << i->first << " ";
+ cout << endl;
+
+ cout << "Erasing everything" << endl;
+ first = t.begin();
+ last = t.end();
+ t.erase(first, last);
+
+ for (Table<int,int>::const_iterator i = t.begin(); i != t.end(); ++i)
+ cout << i->first << " ";
+ cout << endl;
+
+ /* **** */
+
+ PathTable<char> pt;
+ pt.insert(make_pair("/foo", 'a'));
+ pt.insert(make_pair("/bar", 'a'));
+ pt.insert(make_pair("/bar/baz", 'b'));
+ pt.insert(make_pair("/bar/bazz/NO", 'c'));
+ pt.insert(make_pair("/bar/baz/YEEEAH", 'c'));
+ pt.insert(make_pair("/bar/baz/YEEEAH/BOOOEEEEE", 'c'));
+ pt.insert(make_pair("/bar/buzz", 'b'));
+ pt.insert(make_pair("/bar/buzz/WHAT", 'c'));
+ pt.insert(make_pair("/bar/buzz/WHHHhhhhhAT", 'c'));
+ pt.insert(make_pair("/quux", 'a'));
+
+ cout << "Paths: " << endl;
+ for (PathTable<char>::const_iterator i = pt.begin(); i != pt.end(); ++i)
+ cout << i->first << " ";
+ cout << endl;
+
+ PathTable<char>::const_iterator descendants_begin = pt.begin();
+ size_t begin_index = rand() % pt.size();
+ for (size_t i=0; i < begin_index; ++i)
+ ++descendants_begin;
+
+ cout << "\nDescendants of " << descendants_begin->first << endl;
+ PathTable<char>::const_iterator descendants_end = pt.find_descendants_end(descendants_begin);
+
+ for (PathTable<char>::const_iterator i = pt.begin(); i != descendants_end; ++i)
+ cout << i->first << " ";
+ cout << endl;
+
+ const Path yank_path("/bar");
+ PathTable<char>::iterator quux = pt.find(yank_path);
+ assert(quux != pt.end());
+ PathTable<char>::iterator quux_end = pt.find_descendants_end(quux );
+ assert(quux_end != quux);
+
+ SharedPtr< Table<Path,char> > yanked = pt.yank(quux, quux_end);
+
+ cout << "Yanked " << yank_path << endl;
+ for (PathTable<char>::const_iterator i = pt.begin(); i != pt.end(); ++i)
+ cout << i->first << " ";
+ cout << endl;
+
+ pt.cram(*yanked.get());
+
+ cout << "Crammed " << yank_path << endl;
+ for (PathTable<char>::const_iterator i = pt.begin(); i != pt.end(); ++i)
+ cout << i->first << " ";
+ cout << endl;
+
+ /* **** */
+
+ Table<string, string> st;
+
+ st.insert(make_pair("apple", "core"));
+ st.insert(make_pair("candy", "cane"));
+ st.insert(make_pair("banana", "peel"));
+ //st["alpha"] = "zero";
+ //st["zeta"] = "one";
+
+ st.erase("banana");
+
+ for (Table<int,int>::const_iterator i = t.begin(); i != t.end(); ++i)
+ cout << i->first << " ";
+ cout << endl;
+
+ for (int i = 0; i < 1000; ++i) {
+ Table<int, int> t;
+
+ size_t table_size = (rand() % 1000) + 1;
+
+ for (size_t i=0; i < table_size; ++i) {
+ int val = rand()%100;
+ t.insert(make_pair(val, ((val + 3) * 17)));
+ }
+
+ for (int i=0; i < (int)table_size; ++i) {
+ int val = rand()%100;
+ Table<int, int>::iterator iter = t.find(val);
+ assert(iter == t.end() || iter->second == (val + 3) * 17);
+ }
+
+ /*cout << "CONTENTS:" << endl;
+
+ for (Table<int,int>::const_iterator i = t.begin(); i != t.end(); ++i) {
+ cout << i->first << ": " << i->second << endl;
+ }
+
+ Table<int,int>::iterator i = t.find(7);
+ if (i != t.end())
+ cout << "Find: 7: " << i->second << endl;*/
+ }
+
+ return 0;
+}
+
+string
+random_string()
+{
+ string ret(60, 'A' + (rand() % 26));
+ return ret;
+}
+
+
+void
+benchmark(size_t n)
+{
+ cout << "Benchmarking with n = " << n << endl;
+
+ int useless_accumulator = 0;
+
+ srand(time(NULL));
+
+ vector<string> values(n);
+ for (size_t i=0; i < n; ++i)
+ values.push_back(random_string());
+
+ timeval t1;
+ t1.tv_sec=0;
+ t1.tv_usec=0;
+
+ timeval t2;
+ t2.tv_sec=0;
+ t2.tv_usec=0;
+
+
+ /** std::map **/
+
+ std::map<string,int> m;
+
+ gettimeofday(&t1, NULL);
+
+ for (size_t i=0; i < n; ++i)
+ m.insert(make_pair(values[i], i));
+
+ gettimeofday(&t2, NULL);
+
+ float delta_t = (t2.tv_sec - t1.tv_sec) + (t2.tv_usec - t1.tv_usec) * 0.000001f;
+
+ cout << "std::map time to insert " << n << " values: \t" << delta_t << endl;
+
+ gettimeofday(&t1, NULL);
+
+ for (size_t i=0; i < n; ++i)
+ useless_accumulator += m.find(values[i])->second;
+
+ gettimeofday(&t2, NULL);
+
+ delta_t = (t2.tv_sec - t1.tv_sec) + (t2.tv_usec - t1.tv_usec) * 0.000001f;
+
+ cout << "std::map time to lookup " << n << " values: \t" << delta_t << endl;
+
+
+ /** std::set **/
+
+ std::set<std::string> s;
+
+ gettimeofday(&t1, NULL);
+
+ for (size_t i=0; i < n; ++i)
+ s.insert(values[i]);
+
+ gettimeofday(&t2, NULL);
+
+ delta_t = (t2.tv_sec - t1.tv_sec) + (t2.tv_usec - t1.tv_usec) * 0.000001f;
+
+ cout << "std::set time to insert " << n << " values: \t" << delta_t << endl;
+
+ gettimeofday(&t1, NULL);
+
+ for (size_t i=0; i < n; ++i)
+ useless_accumulator += (int)(*s.find(values[i]))[0];
+
+ gettimeofday(&t2, NULL);
+
+ delta_t = (t2.tv_sec - t1.tv_sec) + (t2.tv_usec - t1.tv_usec) * 0.000001f;
+
+ cout << "std::set time to lookup " << n << " values: \t" << delta_t << endl;
+
+
+ /** sorted std::vector **/
+
+ /*std::vector<int> v;
+
+ gettimeofday(&t1, NULL);
+
+ for (size_t i=0; i < n; ++i)
+ v.push_back(values[i]);
+
+ sort(v.begin(), v.end());
+
+ gettimeofday(&t2, NULL);
+
+ delta_t = (t2.tv_sec - t1.tv_sec) + (t2.tv_usec - t1.tv_usec) * 0.000001f;
+
+ cout << "std::vector (sorted) time to insert " << n << " values: \t" << delta_t << endl;
+
+ gettimeofday(&t1, NULL);
+
+ for (size_t i=0; i < n; ++i)
+ useless_accumulator += *lower_bound(v.begin(), v.end(), values[i]);
+
+ gettimeofday(&t2, NULL);
+
+ delta_t = (t2.tv_sec - t1.tv_sec) + (t2.tv_usec - t1.tv_usec) * 0.000001f;
+
+ cout << "std::vector (sorted) time to lookup " << n << " values: \t" << delta_t << endl;*/
+
+
+ /** Raul::Table **/
+
+ Raul::Table<string,int> t(n);
+
+ gettimeofday(&t1, NULL);
+
+ for (size_t i=0; i < n; ++i)
+ t.insert(make_pair(values[i], i));
+
+ gettimeofday(&t2, NULL);
+
+ delta_t = (t2.tv_sec - t1.tv_sec) + (t2.tv_usec - t1.tv_usec) * 0.000001f;
+
+ cout << "Raul::Table time to insert " << n << " values: " << delta_t << endl;
+
+ gettimeofday(&t1, NULL);
+
+ for (size_t i=0; i < n; ++i)
+ useless_accumulator += t.find(values[i])->second;
+
+ gettimeofday(&t2, NULL);
+
+ delta_t = (t2.tv_sec - t1.tv_sec) + (t2.tv_usec - t1.tv_usec) * 0.000001f;
+
+ cout << "Raul::Table time to lookup " << n << " values: \t" << delta_t << endl;
+
+
+#ifdef WITH_TR1
+ /** boost::hash && std::unordered_map **/
+
+ tr1::unordered_map<string, int, boost::hash<string> > um;
+
+ gettimeofday(&t1, NULL);
+
+ um.rehash(n);
+
+ for (size_t i=0; i < n; ++i)
+ um.insert(make_pair(values[i], i));
+
+ gettimeofday(&t2, NULL);
+
+ delta_t = (t2.tv_sec - t1.tv_sec) + (t2.tv_usec - t1.tv_usec) * 0.000001f;
+
+ cout << "tr1::unordered_map + boost::hash time to insert " << n << " values: \t" << delta_t << endl;
+
+ gettimeofday(&t1, NULL);
+
+ for (size_t i=0; i < n; ++i)
+ useless_accumulator += um.find(values[i])->second;
+
+ gettimeofday(&t2, NULL);
+
+ delta_t = (t2.tv_sec - t1.tv_sec) + (t2.tv_usec - t1.tv_usec) * 0.000001f;
+
+ cout << "tr1::unordered_map + boost::hash time to lookup " << n << " values: \t" << delta_t << endl;
+#endif
+}
+
diff --git a/test/thread_test.cpp b/test/thread_test.cpp
new file mode 100644
index 0000000..fd7a411
--- /dev/null
+++ b/test/thread_test.cpp
@@ -0,0 +1,19 @@
+#include <iostream>
+#include "raul/Thread.hpp"
+
+using namespace std;
+using namespace Raul;
+
+int
+main()
+{
+ Thread& this_thread = Thread::get();
+ this_thread.set_name("Main");
+
+ cout << "Thread name should be Main" << endl;
+
+ cout << "Thread name: " << Thread::get().name() << endl;
+
+ return 0;
+}
+
diff --git a/test/time_test.cpp b/test/time_test.cpp
new file mode 100644
index 0000000..2b53207
--- /dev/null
+++ b/test/time_test.cpp
@@ -0,0 +1,32 @@
+#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;
+ cout << "Beats: ";
+ cin >> in_double;
+
+ TimeStamp t(unit, (uint32_t)in_double,
+ (uint32_t)((in_double - (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;
+}
+