summaryrefslogtreecommitdiff
path: root/src/base/testbase.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/base/testbase.cpp')
-rw-r--r--src/base/testbase.cpp1024
1 files changed, 1024 insertions, 0 deletions
diff --git a/src/base/testbase.cpp b/src/base/testbase.cpp
new file mode 100644
index 0000000..57faf36
--- /dev/null
+++ b/src/base/testbase.cpp
@@ -0,0 +1,1024 @@
+//
+// libavg - Media Playback Engine.
+// Copyright (C) 2003-2014 Ulrich von Zadow
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2 of the License, or (at your option) any later version.
+//
+// This library 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
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// Current versions can be found at www.libavg.de
+//
+
+#include "DAG.h"
+#include "Queue.h"
+#include "Command.h"
+#include "WorkerThread.h"
+#include "ObjectCounter.h"
+#include "triangulate/Triangulate.h"
+#include "GLMHelper.h"
+#include "GeomHelper.h"
+#include "OSHelper.h"
+#include "FileHelper.h"
+#include "StringHelper.h"
+#include "MathHelper.h"
+#include "CubicSpline.h"
+#include "BezierCurve.h"
+#include "Signal.h"
+#include "Backtrace.h"
+#include "WideLine.h"
+#include "Rect.h"
+#include "Triangle.h"
+#include "TestSuite.h"
+#include "TimeSource.h"
+#include "XMLHelper.h"
+#include "Logger.h"
+
+#include <boost/thread/thread.hpp>
+
+#include <boost/bind.hpp>
+
+#include <iostream>
+#include <sstream>
+#include <stdio.h>
+#include <stdlib.h>
+
+using namespace avg;
+using namespace std;
+using namespace boost;
+
+class DAGTest: public Test
+{
+public:
+ DAGTest()
+ : Test("DAGTest", 2)
+ {
+ }
+
+ void runTests()
+ {
+ {
+ DAG dag;
+
+ dag.addNode(1, set<long>());
+ long outgoing2[] = {1};
+ dag.addNode(0, makeOutgoing(1, outgoing2));
+
+ long expected[] = {0, 1};
+ checkResults(&dag, expected);
+ }
+ {
+ DAG dag;
+
+ dag.addNode(2, set<long>());
+ long outgoing2[] = {1};
+ dag.addNode(0, makeOutgoing(1, outgoing2));
+ long outgoing3[] = {2};
+ dag.addNode(1, makeOutgoing(1, outgoing3));
+
+ long expected[] = {0, 1, 2};
+ checkResults(&dag, expected);
+ }
+ {
+ DAG dag;
+
+ long outgoing2[] = {1};
+ dag.addNode(0, makeOutgoing(1, outgoing2));
+ dag.addNode(2, set<long>());
+ long outgoing3[] = {2};
+ dag.addNode(1, makeOutgoing(1, outgoing3));
+
+ long expected[] = {0, 1, 2};
+ checkResults(&dag, expected);
+ }
+ {
+ DAG dag;
+
+ dag.addNode(2, set<long>());
+ long outgoing2[] = {1, 2};
+ dag.addNode(0, makeOutgoing(1, outgoing2));
+ long outgoing3[] = {2};
+ dag.addNode(1, makeOutgoing(1, outgoing3));
+
+ long expected[] = {0, 1, 2};
+ checkResults(&dag, expected);
+ }
+ {
+ DAG dag;
+
+ long outgoing2[] = {1};
+ dag.addNode(0, makeOutgoing(1, outgoing2));
+ long outgoing3[] = {0};
+ dag.addNode(1, makeOutgoing(1, outgoing3));
+
+ bool bExceptionThrown = false;
+ long expected[] = {0, 1, 2};
+ try {
+ checkResults(&dag, expected);
+ } catch (const Exception&) {
+ bExceptionThrown = true;
+ }
+ TEST(bExceptionThrown);
+ }
+ }
+
+private:
+ set<long> makeOutgoing(int n, long ids[])
+ {
+ set<long> v;
+ for (int i=0; i<n; ++i) {
+ v.insert(ids[i]);
+ }
+ return v;
+ }
+
+ void checkResults(DAG* pDAG, long expected[])
+ {
+ vector<long> results;
+ pDAG->sort(results);
+
+ for (unsigned i=0; i<results.size(); ++i) {
+ QUIET_TEST(results[i] == expected[i]);
+ }
+ }
+};
+
+class QueueTest: public Test
+{
+public:
+ QueueTest()
+ : Test("QueueTest", 2)
+ {
+ }
+
+ void runTests()
+ {
+ runSingleThreadTests();
+ runMultiThreadTests();
+ }
+
+private:
+ typedef Queue<int>::QElementPtr ElemPtr;
+
+ void runSingleThreadTests()
+ {
+ Queue<string> q;
+ typedef Queue<string>::QElementPtr ElemPtr;
+ TEST(q.empty());
+ q.push(ElemPtr(new string("1")));
+ TEST(q.size() == 1);
+ TEST(!q.empty());
+ q.push(ElemPtr(new string("2")));
+ q.push(ElemPtr(new string("3")));
+ TEST(q.size() == 3);
+ TEST(*q.pop() == "1");
+ TEST(*q.pop() == "2");
+ q.push(ElemPtr(new string("4")));
+ TEST(*q.pop() == "3");
+ TEST(*q.peek() == "4");
+ TEST(*q.pop() == "4");
+ TEST(q.empty());
+ ElemPtr pElem = q.pop(false);
+ TEST(!pElem);
+ }
+
+ void runMultiThreadTests()
+ {
+ {
+ Queue<int> q(10);
+ thread pusher(boost::bind(&pushThread, &q, 100));
+ thread popper(boost::bind(&popThread, &q, 100));
+ pusher.join();
+ popper.join();
+ TEST(q.empty());
+ }
+ {
+ Queue<int> q(10);
+ thread pusher1(boost::bind(&pushThread, &q, 100));
+ thread pusher2(boost::bind(&pushThread, &q, 100));
+ thread popper(boost::bind(&popThread, &q, 200));
+ pusher1.join();
+ pusher2.join();
+ popper.join();
+ TEST(q.empty());
+ }
+ {
+ Queue<int> q(10);
+ thread pusher(boost::bind(&pushClearThread, &q, 100));
+ thread popper(boost::bind(&popClearThread, &q));
+ pusher.join();
+ popper.join();
+ TEST(q.empty());
+ }
+ }
+
+ static void pushThread(Queue<int>* pq, int numPushes)
+ {
+ for (int i=0; i<numPushes; ++i) {
+ pq->push(ElemPtr(new int(i)));
+ msleep(1);
+ }
+ }
+
+ static void popThread(Queue<int>* pq, int numPops)
+ {
+ for (int i=0; i<numPops; ++i) {
+ pq->peek();
+ pq->pop();
+ msleep(3);
+ }
+ }
+
+ static void pushClearThread(Queue<int>* pq, int numPushes)
+ {
+ typedef Queue<int>::QElementPtr ElemPtr;
+ for (int i=0; i<numPushes; ++i) {
+ pq->push(ElemPtr(new int(i)));
+ if (i%7 == 0) {
+ pq->clear();
+ }
+ msleep(1);
+ }
+ pq->push(ElemPtr(new int(-1)));
+ }
+
+ static void popClearThread(Queue<int>* pq)
+ {
+ ElemPtr pElem;
+ do {
+ pElem = pq->pop();
+ } while (*pElem != -1);
+ }
+};
+
+class TestWorkerThread: public WorkerThread<TestWorkerThread>
+{
+public:
+ TestWorkerThread(CQueue& cmdQ, int* pNumFuncCalls, int* pIntParam,
+ string* pStringParam)
+ : WorkerThread<TestWorkerThread>("Thread1", cmdQ),
+ m_pNumFuncCalls(pNumFuncCalls),
+ m_pIntParam(pIntParam),
+ m_pStringParam(pStringParam)
+ {
+ }
+
+ bool init()
+ {
+ (*m_pNumFuncCalls)++;
+ return true;
+ }
+
+ bool work()
+ {
+ (*m_pNumFuncCalls)++;
+ waitForCommand();
+ return true;
+ }
+
+ void deinit()
+ {
+ (*m_pNumFuncCalls)++;
+ }
+
+ void doSomething(int i, std::string s)
+ {
+ *m_pIntParam = i;
+ *m_pStringParam = s;
+ }
+
+private:
+ int * m_pNumFuncCalls;
+ int * m_pIntParam;
+ std::string * m_pStringParam;
+};
+
+
+class WorkerThreadTest: public Test
+{
+public:
+ WorkerThreadTest()
+ : Test("WorkerThreadTest", 2)
+ {
+ }
+
+ void runTests()
+ {
+ typedef TestWorkerThread::CmdPtr CmdPtr;
+ TestWorkerThread::CQueue cmdQ;
+ boost::thread* pTestThread;
+ int numFuncCalls = 0;
+ int intParam = 0;
+ std::string stringParam;
+ cmdQ.pushCmd(boost::bind(&TestWorkerThread::doSomething, _1, 23, "foo"));
+ cmdQ.pushCmd(boost::bind(&TestWorkerThread::stop, _1));
+ pTestThread = new boost::thread(TestWorkerThread(cmdQ, &numFuncCalls,
+ &intParam, &stringParam));
+ pTestThread->join();
+ delete pTestThread;
+ TEST(numFuncCalls == 3);
+ TEST(intParam == 23);
+ TEST(stringParam == "foo");
+ }
+};
+
+
+class DummyClass
+{
+public:
+ DummyClass()
+ {
+ ObjectCounter::get()->incRef(&typeid(*this));
+ }
+
+ virtual ~DummyClass()
+ {
+ ObjectCounter::get()->decRef(&typeid(*this));
+ }
+
+ int i;
+};
+
+
+class ObjectCounterTest: public Test {
+public:
+ ObjectCounterTest()
+ : Test("ObjectCounterTest", 2)
+ {
+ }
+
+ void runTests()
+ {
+ TEST(ObjectCounter::get()->getCount(&typeid(DummyClass)) == 0);
+ {
+ DummyClass dummy1;
+ DummyClass dummy2;
+ TEST(ObjectCounter::get()->getCount(&typeid(dummy1)) == 2);
+ }
+ TEST(ObjectCounter::get()->getCount(&typeid(DummyClass)) == 0);
+ }
+};
+
+
+// The following pragmas avoid a compiler warning (potential division by 0)
+#ifdef _MSC_VER
+#pragma optimize("", off)
+#pragma warning(push)
+#pragma warning(disable:4723)
+#endif
+class GeomTest: public Test
+{
+public:
+ GeomTest()
+ : Test("GeomTest", 2)
+ {
+ }
+
+ void runTests()
+ {
+ // TODO: Move to a separate math test once we're done here.
+ TEST(almostEqual(invSqrt(1), 1));
+ TEST(almostEqual(invSqrt(4), 0.5));
+
+ {
+ LineSegment l1(glm::vec2(0,0), glm::vec2(2,2));
+ LineSegment l2(glm::vec2(2,0), glm::vec2(0,2));
+ TEST(lineSegmentsIntersect(l1, l2));
+ TEST(lineSegmentsIntersect(l2, l1));
+ }
+ {
+ LineSegment l1(glm::vec2(0,0), glm::vec2(0,2));
+ LineSegment l2(glm::vec2(2,0), glm::vec2(2,2));
+ TEST(!lineSegmentsIntersect(l1, l2));
+ }
+ {
+ LineSegment l1(glm::vec2(0,0), glm::vec2(2,0));
+ LineSegment l2(glm::vec2(0,2), glm::vec2(2,2));
+ TEST(!lineSegmentsIntersect(l1, l2));
+ }
+ {
+ LineSegment l1(glm::vec2(0,0), glm::vec2(2,0));
+ TEST(l1.isPointOver(glm::vec2(1,23)));
+ TEST(l1.isPointOver(glm::vec2(1.9,-5)));
+ TEST(!l1.isPointOver(glm::vec2(-1,1)));
+ TEST(!l1.isPointOver(glm::vec2(3,-1)));
+ }
+ {
+ glm::vec2 pt0(glm::vec2(1,1));
+ glm::vec2 pt1(glm::vec2(1,3));
+ glm::vec2 pt2(glm::vec2(1,-2));
+ vector<glm::vec2> poly;
+ poly.push_back(glm::vec2(0,0));
+ poly.push_back(glm::vec2(2,0));
+ poly.push_back(glm::vec2(2,2));
+ poly.push_back(glm::vec2(0,2));
+ TEST(pointInPolygon(pt0, poly));
+ TEST(!pointInPolygon(pt1, poly));
+ TEST(!pointInPolygon(pt2, poly));
+ poly.push_back(glm::vec2(2,1));
+ TEST(!pointInPolygon(pt0, poly));
+ }
+ {
+ glm::vec2 p1(glm::vec2(0,0));
+ glm::vec2 v1(glm::vec2(1,1));
+ glm::vec2 p2(glm::vec2(2,1));
+ glm::vec2 v2(glm::vec2(1,0));
+ TEST(getLineLineIntersection(p1, v1, p2, v2) == glm::vec2(1,1));
+ }
+ TEST(almostEqual(getRotatedPivot(glm::vec2(10,0), M_PI, glm::vec2(15,5)),
+ glm::vec2(20,10)));
+ TEST(almostEqual(getRotatedPivot(glm::vec2(10,0), M_PI*0.5, glm::vec2(15,5)),
+ glm::vec2(20,0)));
+ TEST(almostEqual(getRotatedPivot(glm::vec2(10,0), M_PI*1.5, glm::vec2(15,5)),
+ glm::vec2(10,10)));
+ TEST(almostEqual(getRotatedPivot(glm::vec2(10,0), M_PI*2, glm::vec2(15,5)),
+ glm::vec2(10,0)));
+ TEST(almostEqual(getRotatedPivot(glm::vec2(23,0), M_PI*0.5), glm::vec2(0,23)));
+
+ {
+ // TODO: More tests
+ FRect(0,0,10,10);
+ }
+ }
+};
+#ifdef _MSC_VER
+#pragma warning(pop)
+#pragma optimize("", on)
+#endif
+
+
+class TriangleTest: public Test
+{
+public:
+ TriangleTest()
+ : Test("TriangleTest", 2)
+ {
+ }
+
+ void runTests()
+ {
+ Triangle tri(glm::vec2(0,0), glm::vec2(4,4), glm::vec2(4,8));
+ TEST(tri.isInside(glm::vec2(3,4)));
+ TEST(!tri.isInside(glm::vec2(1,4)));
+ TEST(!tri.isInside(glm::vec2(2,1)));
+ TEST(!tri.isInside(glm::vec2(-2,5)));
+ TEST(!tri.isInside(glm::vec2(5,5)));
+ tri = Triangle(glm::vec2(0,0), glm::vec2(4,8), glm::vec2(4,4));
+ TEST(tri.isInside(glm::vec2(3,4)));
+
+ glm::vec2 polyArray[] = {glm::vec2(0,0), glm::vec2(8,2), glm::vec2(9,0), glm::vec2(9,3),
+ glm::vec2(1,1), glm::vec2(0,3)};
+
+ Vec2Vector poly = vectorFromCArray(6, polyArray);
+ vector<unsigned int> triangulation;
+ triangulatePolygon(triangulation, poly);
+
+ TEST(triangulation.size() == 4*3);
+ unsigned int baselineIndexes[] = {5,0,4, 1,4,0, 4,1,3, 1,2,3};
+ TEST(triangulation == vectorFromCArray(12, baselineIndexes));
+/*
+ for (unsigned int i=0; i<triangulation.size(); i++) {
+ cerr << i << ":" << triangulation[i] << endl;
+ }
+*/
+ }
+
+};
+
+
+class FileTest: public Test
+{
+public:
+ FileTest()
+ : Test("FileTest", 2)
+ {
+ }
+
+ void runTests()
+ {
+ TEST(getPath("/foo/bar.txt") == "/foo/");
+ TEST(getFilenamePart("/foo/bar.txt") == "bar.txt");
+ }
+};
+
+
+class OSTest: public Test
+{
+public:
+ OSTest()
+ : Test("OSTest", 2)
+ {
+ }
+
+ void runTests()
+ {
+ cerr << getAvgLibPath() << endl;
+ TEST(getAvgLibPath() != "");
+#ifdef __APPLE__
+ TEST(getMemoryUsage() != 0);
+#endif
+ }
+};
+
+
+class StringTest: public Test
+{
+public:
+ StringTest()
+ : Test("StringTest", 2)
+ {
+ }
+
+ void runTests()
+ {
+ TEST(stringToInt("5") == 5);
+ TEST(almostEqual(stringToFloat("5.5"), 5.5f));
+ TEST(stringToBool("False") == false);
+ bool bExceptionThrown = false;
+ try {
+ stringToInt("5a");
+ } catch (const Exception& e) {
+ if (e.getCode() == AVG_ERR_TYPE ) {
+ bExceptionThrown = true;
+ }
+ }
+ TEST(bExceptionThrown);
+ TEST(stringToVec2(" ( 3.4 , 2.1 ) ") == glm::vec2(3.4f, 2.1f));
+ vector<float> v;
+ fromString("(1,2,3,4,5)", v);
+ TEST(v.size() == 5 && v[0] == 1 && v[4] == 5);
+ v.clear();
+ fromString("()", v);
+ TEST(v.size() == 0);
+ }
+};
+
+
+class SplineTest: public Test
+{
+public:
+ SplineTest()
+ : Test("SplineTest", 2)
+ {
+ }
+
+ void runTests()
+ {
+ {
+ float xd[] = {0,1,2,3};
+ vector<float> x = vectorFromCArray(4, xd);
+ float yd[] = {3,2,1,0};
+ vector<float> y = vectorFromCArray(4, yd);
+ CubicSpline spline(x, y);
+ TEST(almostEqual(spline.interpolate(-1), 4));
+ TEST(almostEqual(spline.interpolate(0), 3));
+ TEST(almostEqual(spline.interpolate(0.5), 2.5));
+ TEST(almostEqual(spline.interpolate(3), 0));
+ TEST(almostEqual(spline.interpolate(3.5), -0.5));
+ }
+ {
+ float xd[] = {2,4,6,8};
+ vector<float> x = vectorFromCArray(4, xd);
+ float yd[] = {0,1,3,6};
+ vector<float> y = vectorFromCArray(4, yd);
+ CubicSpline spline(x, y);
+ TEST(almostEqual(spline.interpolate(0), -1));
+ TEST(almostEqual(spline.interpolate(2), 0));
+ TEST(spline.interpolate(3) < 0.5);
+ TEST(spline.interpolate(3) > 0);
+ TEST(spline.interpolate(7) > 4);
+ TEST(spline.interpolate(7) < 5);
+ TEST(almostEqual(spline.interpolate(8), 6));
+ TEST(almostEqual(spline.interpolate(10), 9));
+ }
+ {
+ float xd[] = {0,1,1};
+ vector<float> x = vectorFromCArray(3, xd);
+ float yd[] = {1,2,1};
+ vector<float> y = vectorFromCArray(3, yd);
+ bool bExceptionThrown = false;
+ try {
+ CubicSpline spline(x, y);
+ } catch (const Exception&) {
+ bExceptionThrown = true;
+ }
+ TEST(bExceptionThrown);
+ }
+/*
+ {
+ float xd[] = {0,1,2};
+ vector<float> x = vectorFromCArray(3, xd);
+ float yd[] = {1,2,1};
+ vector<float> y = vectorFromCArray(3, yd);
+ CubicSpline spline(x, y, true);
+ TEST(almostEqual(spline.interpolate(0), 1));
+ TEST(almostEqual(spline.interpolate(0.5), 1.5));
+ TEST(almostEqual(spline.interpolate(2), 1));
+ TEST(almostEqual(spline.interpolate(3), 2));
+ }
+*/
+ }
+};
+
+
+class BezierCurveTest: public Test
+{
+public:
+ BezierCurveTest()
+ : Test("BezierCurveTest", 2)
+ {
+ }
+
+ void runTests()
+ {
+ BezierCurve curve(glm::vec2(0,0), glm::vec2(1,0), glm::vec2(1,1), glm::vec2(0,1));
+ TEST(almostEqual(curve.interpolate(0), glm::vec2(0,0)));
+ TEST(almostEqual(curve.getDeriv(0), glm::vec2(3, 0)));
+ TEST(almostEqual(curve.interpolate(1), glm::vec2(0,1)));
+ TEST(almostEqual(curve.getDeriv(1), glm::vec2(-3, 0)));
+ TEST(almostEqual(curve.interpolate(0.5), glm::vec2(0.75,0.5)));
+ }
+};
+
+
+class WideLineTest: public Test
+{
+public:
+ WideLineTest()
+ : Test("WideLineTest", 2)
+ {
+ }
+
+ void runTests()
+ {
+ WideLine line(glm::vec2(0,0), glm::vec2(4,3), 2);
+ TEST(almostEqual(line.getLen(), 5));
+ }
+};
+
+
+class Listener
+{
+public:
+ Listener(Signal<Listener>& signal)
+ : m_Signal(signal),
+ m_bFuncCalled(false)
+ {
+ }
+
+ virtual ~Listener()
+ {}
+
+ virtual void func()
+ {
+ m_bFuncCalled = true;
+ }
+
+ bool funcCalled() const
+ {
+ return m_bFuncCalled;
+ }
+
+ void reset()
+ {
+ m_bFuncCalled = false;
+ }
+
+protected:
+ Signal<Listener>& m_Signal;
+
+private:
+ bool m_bFuncCalled;
+};
+
+
+class DisconnectingSelfListener: public Listener
+{
+public:
+ DisconnectingSelfListener(Signal<Listener>& signal)
+ : Listener(signal)
+ {
+ }
+
+ virtual void func()
+ {
+ Listener::func();
+ m_Signal.disconnect(this);
+ }
+};
+
+
+class DisconnectingOtherListener: public Listener
+{
+public:
+ DisconnectingOtherListener(Signal<Listener>& signal, Listener* pOther)
+ : Listener(signal),
+ m_pOther(pOther)
+ {
+ }
+
+ virtual void func()
+ {
+ Listener::func();
+ if (m_pOther) {
+ m_Signal.disconnect(m_pOther);
+ m_pOther = 0;
+ }
+ }
+
+private:
+ Listener* m_pOther;
+};
+
+
+class ConnectingOtherListener: public Listener
+{
+public:
+ ConnectingOtherListener(Signal<Listener>& signal, Listener* pOther)
+ : Listener(signal),
+ m_pOther(pOther)
+ {
+ }
+
+ virtual void func()
+ {
+ Listener::func();
+ if (m_pOther) {
+ m_Signal.connect(m_pOther);
+ m_pOther = 0;
+ }
+ }
+
+private:
+ Listener* m_pOther;
+};
+
+
+class SignalTest: public Test
+{
+public:
+ SignalTest()
+ : Test("SignalTest", 2)
+ {
+ }
+
+ void runTests()
+ {
+ Signal<Listener> s(&Listener::func);
+ Listener l1(s);
+ Listener l2(s);
+ s.connect(&l1);
+ s.connect(&l2);
+ s.emit();
+ TEST(l1.funcCalled() && l2.funcCalled());
+ l1.reset();
+ l2.reset();
+
+ s.disconnect(&l1);
+ s.emit();
+ TEST(!(l1.funcCalled()) && l2.funcCalled());
+ l2.reset();
+
+ {
+ DisconnectingSelfListener disconnecter(s);
+ s.connect(&disconnecter);
+ s.emit();
+ TEST(l2.funcCalled() && disconnecter.funcCalled());
+ TEST(s.getNumListeners() == 1);
+ l2.reset();
+ disconnecter.reset();
+
+ s.emit();
+ TEST(l2.funcCalled() && !(disconnecter.funcCalled()));
+ l2.reset();
+ }
+ {
+ DisconnectingOtherListener disconnecter(s, &l2);
+ s.connect(&disconnecter);
+ s.emit();
+ TEST(l2.funcCalled() && disconnecter.funcCalled());
+ TEST(s.getNumListeners() == 1);
+ l2.reset();
+ disconnecter.reset();
+
+ s.emit();
+ TEST(!(l2.funcCalled()) && disconnecter.funcCalled());
+ s.disconnect(&disconnecter);
+ }
+ {
+ ConnectingOtherListener connecter(s, &l2);
+ s.connect(&connecter);
+ s.emit();
+ TEST(l2.funcCalled() && connecter.funcCalled());
+ TEST(s.getNumListeners() == 2);
+ l2.reset();
+ connecter.reset();
+
+ s.emit();
+ TEST(l2.funcCalled() && connecter.funcCalled());
+ }
+ }
+};
+
+
+class BacktraceTest: public Test
+{
+public:
+ BacktraceTest()
+ : Test("BacktraceTest", 2)
+ {
+ }
+
+ void runTests()
+ {
+ vector<string> sFuncs;
+ getBacktrace(sFuncs);
+#ifndef _WIN32
+ TEST(sFuncs[0].find("runTests") != string::npos);
+#endif
+ }
+};
+
+
+class PolygonTest: public Test
+{
+public:
+ PolygonTest()
+ : Test("PolygonTest", 2)
+ {
+ }
+
+ void runTests()
+ {
+ glm::vec2 polyArray[] = {glm::vec2(30,0), glm::vec2(40,20), glm::vec2(60,30),
+ glm::vec2(40,40), glm::vec2(30,60), glm::vec2(20,40), glm::vec2(0,30),
+ glm::vec2(20,20)};
+
+ Vec2Vector poly = vectorFromCArray(8, polyArray);
+ vector<unsigned int> triangulation;
+ triangulatePolygon(triangulation, poly);
+
+ TEST(triangulation.size() == 6*3);
+ unsigned int baselineIndexes[] = {6,7,5, 5,7,1, 7,0,1, 5,1,3, 3,1,2, 4,5,3};
+ TEST(triangulation == vectorFromCArray(18, baselineIndexes));
+/*
+ for (unsigned int i=0; i<triangulation.size(); i++) {
+ cerr << i << ":" << triangulation[i] << endl;
+ }/
+*/
+ }
+
+};
+
+
+class XmlParserTest: public Test
+{
+public:
+ XmlParserTest()
+ : Test("XmlParserTest", 2)
+ {
+ }
+
+ void runTests()
+ {
+ string sXmlString = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
+ "<shiporder orderid=\"889923\">"
+ " <orderperson>John Smith</orderperson>"
+ "</shiporder>";
+
+ {
+ string sSchema = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
+ "<xs:schema xmlns:xs=\"http://www.w3.org/2001/XMLSchema\">"
+ "<xs:element name=\"shiporder\">"
+ " <xs:complexType>"
+ " <xs:sequence>"
+ " <xs:element name=\"orderperson\" type=\"xs:string\"/>"
+ " </xs:sequence>"
+ " <xs:attribute name=\"orderid\" type=\"xs:string\" use=\"required\"/>"
+ " </xs:complexType>"
+ "</xs:element>"
+ "</xs:schema>";
+
+ XMLParser parser;
+ parser.setSchema(sSchema, "shiporder.xsd");
+ parser.parse(sXmlString, "shiporder.xml");
+ }
+ {
+ string sDTD =
+ "<!ELEMENT shiporder (orderperson)* >"
+ "<!ATTLIST shiporder"
+ " orderid CDATA #IMPLIED>"
+ "<!ELEMENT orderperson (#PCDATA) >";
+ XMLParser parser;
+ parser.setDTD(sDTD, "shiporder.dtd");
+ parser.parse(sXmlString, "shiporder.xml");
+ }
+ }
+};
+
+
+class StandardLoggerTest: public Test
+{
+public:
+ StandardLoggerTest()
+ : Test("StandardLoggerTest", 2)
+ {
+ }
+
+ void runTests()
+ {
+ std::stringstream buffer;
+ std::streambuf *sbuf = std::cerr.rdbuf();
+ Logger *logger = Logger::get();
+ {
+ std::cerr.rdbuf(buffer.rdbuf());
+ string msg("Test log message");
+ AVG_TRACE(Logger::category::NONE, Logger::severity::WARNING, msg);
+ std::cerr.rdbuf(sbuf);
+ TEST(buffer.str().find(msg) != string::npos);
+ buffer.str(string());
+
+ std::cerr.rdbuf(buffer.rdbuf());
+ AVG_TRACE(Logger::category::NONE, Logger::severity::DEBUG, msg);
+ std::cerr.rdbuf(sbuf);
+ std::cout << buffer.str();
+ TEST(buffer.str().find(msg) == string::npos);
+ buffer.str(string());
+ }
+ {
+ std::cerr.rdbuf(buffer.rdbuf());
+ category_t CUSTOM_CAT = logger->configureCategory("CUSTOM_CAT 1");
+ string msg("CUSTOM_CAT LOG");
+ AVG_TRACE(CUSTOM_CAT, Logger::severity::WARNING, msg);
+ std::cerr.rdbuf(sbuf);
+ TEST(buffer.str().find(msg) != string::npos);
+ buffer.str(string());
+ }
+ {
+ std::cerr.rdbuf(buffer.rdbuf());
+ category_t CUSTOM_CAT = logger->configureCategory("CUSTOM_CAT 1",
+ Logger::severity::CRITICAL);
+ string msg_info("CUSTOM_CAT LOG INFO");
+ AVG_TRACE(CUSTOM_CAT, Logger::severity::WARNING, msg_info);
+ std::cerr.rdbuf(sbuf);
+ TEST(buffer.str().find(msg_info) == string::npos);
+ buffer.str(string());
+
+ std::cerr.rdbuf(buffer.rdbuf());
+ string msg_critical("CUSTOM_CAT LOG CRITICAL");
+ AVG_TRACE(CUSTOM_CAT, Logger::severity::CRITICAL, msg_critical);
+ std::cerr.rdbuf(sbuf);
+ TEST(buffer.str().find(msg_critical) != string::npos);
+ buffer.str(string());
+ }
+ }
+};
+
+class BaseTestSuite: public TestSuite
+{
+public:
+ BaseTestSuite()
+ : TestSuite("BaseTestSuite")
+ {
+ addTest(TestPtr(new DAGTest));
+ addTest(TestPtr(new QueueTest));
+ addTest(TestPtr(new WorkerThreadTest));
+ addTest(TestPtr(new ObjectCounterTest));
+ addTest(TestPtr(new GeomTest));
+ addTest(TestPtr(new TriangleTest));
+ addTest(TestPtr(new FileTest));
+ addTest(TestPtr(new OSTest));
+ addTest(TestPtr(new StringTest));
+ addTest(TestPtr(new SplineTest));
+ addTest(TestPtr(new BezierCurveTest));
+ addTest(TestPtr(new SignalTest));
+ addTest(TestPtr(new BacktraceTest));
+ addTest(TestPtr(new PolygonTest));
+ addTest(TestPtr(new XmlParserTest));
+ addTest(TestPtr(new StandardLoggerTest));
+ }
+};
+
+
+int main(int nargs, char** args)
+{
+ BaseTestSuite suite;
+ suite.runTests();
+ bool bOK = suite.isOk();
+
+ if (bOK) {
+ return 0;
+ } else {
+ return 1;
+ }
+}
+