diff options
Diffstat (limited to 'tests')
-rw-r--r-- | tests/Makefile.am | 44 | ||||
-rw-r--r-- | tests/README.test | 72 | ||||
-rw-r--r-- | tests/remotetest.idl | 11 | ||||
-rw-r--r-- | tests/test.h | 130 | ||||
-rw-r--r-- | tests/testanyref.cc | 97 | ||||
-rw-r--r-- | tests/testbuffer.cc | 139 | ||||
-rw-r--r-- | tests/testchangenotify.cc | 195 | ||||
-rw-r--r-- | tests/testdispatcher.cc | 41 | ||||
-rw-r--r-- | tests/testflowsystem.cc | 83 | ||||
-rw-r--r-- | tests/testifacerepo.cc | 84 | ||||
-rw-r--r-- | tests/testnotification.cc | 146 | ||||
-rw-r--r-- | tests/testremote.cc | 176 | ||||
-rw-r--r-- | tests/testwrapper.cc | 211 | ||||
-rw-r--r-- | tests/value.idl | 18 | ||||
-rw-r--r-- | tests/value_impl.cc | 94 | ||||
-rw-r--r-- | tests/wrapper.idl | 27 |
16 files changed, 1568 insertions, 0 deletions
diff --git a/tests/Makefile.am b/tests/Makefile.am new file mode 100644 index 0000000..2d533f6 --- /dev/null +++ b/tests/Makefile.am @@ -0,0 +1,44 @@ +check_PROGRAMS = testbuffer testifacerepo testanyref testwrapper \ + testchangenotify testflowsystem testdispatcher testnotification \ + testremote + +TESTS = $(check_PROGRAMS) + +INCLUDES = -I$(top_srcdir)/mcop -I$(top_srcdir)/flow \ + -I$(top_builddir)/flow -I$(top_srcdir)/soundserver \ + -I$(top_builddir)/soundserver -I$(top_srcdir)/artsc \ + -I$(top_builddir)/mcop $(all_includes) + +AM_LDFLAGS = $(all_libraries) +LDADD = $(top_builddir)/mcop/libmcop.la +FLOWLIBS = $(top_builddir)/flow/libartsflow.la + +testbuffer_SOURCES = testbuffer.cc +testifacerepo_SOURCES = testifacerepo.cc +testanyref_SOURCES = testanyref.cc +testdispatcher_SOURCES = testdispatcher.cc +testnotification_SOURCES = testnotification.cc +testwrapper_SOURCES = wrapper.cc testwrapper.cc + +testchangenotify_LDADD = $(FLOWLIBS) +testchangenotify_SOURCES = value.cc value_impl.cc testchangenotify.cc + +testflowsystem_LDADD = $(FLOWLIBS) +testflowsystem_SOURCES = value.cc value_impl.cc testflowsystem.cc + +testremote_LDADD = $(FLOWLIBS) +testremote_SOURCES = remotetest.cc value.cc value_impl.cc testremote.cc + +DISTCLEANFILES = wrapper.h wrapper.cc value.h value.cc \ + remotetest.h remotetest.cc + +wrapper.cc wrapper.h: $(top_srcdir)/tests/wrapper.idl $(MCOPIDL) + $(MCOPIDL) $(top_srcdir)/tests/wrapper.idl + +value_impl.o: value.h +value.cc value.h: $(top_srcdir)/tests/value.idl $(MCOPIDL) + $(MCOPIDL) $(top_srcdir)/tests/value.idl + +remotetest.cc remotetest.h: $(top_srcdir)/tests/remotetest.idl $(MCOPIDL) + $(MCOPIDL) $(top_srcdir)/tests/remotetest.idl + diff --git a/tests/README.test b/tests/README.test new file mode 100644 index 0000000..d605c21 --- /dev/null +++ b/tests/README.test @@ -0,0 +1,72 @@ + C++ automatic testing similar to JUnit + Stefan Westerfeld <stw@kde.org> + +What it is: +=========== + +These tests use a little testing framework, which consists currently only +of the file test.h. It is very much inspired by JUnit (www.junit.org), but it +is maybe even simpler. But it integrates nicely in Makefile.am automatic +testing. You can simply type + +make check + +to see if all tests pass. The motivation behind it is, when you are working +on a large project, it is often impossible to test quickly whether everything +still works all right after changes (which you should before committing ...). +This is even more true if you are not working alone on the code. + +With a consistent set of tests that verify whether everything is still all +right, things like breaking one thing while fixing another can be made less +likely at least. + +How to add a new set of tests: +============================== + +1. create a new .cc file, for this example we'll suppose testarithmetic.cc +2. #include "test.h" +3. create a struct which will hold all your tests + +struct TestArithmetic : public TestCase { + TESTCASE(TestArithmetic); +}; + +4. if you want to, override the following methods: + + void setUp() + { + /* + * This method is supposed to build a little test world, which will be + * built for each test method that is executed - the idea is that your + * tests will use this environment to test in. + */ + } + void tearDown() + { + /* + * This method should completely destroy your test world again, so + * that for the next test, a fresh one can be created. + */ + } + +5. define new tests like this + + TEST(arithmetic) { + long a = 2; + long b = 2; + long c = a+b; + + testAssert(c < 5); // you assert that this condition is true + testEquals(4,c); // you assert that the first (expected) value + } // equals the second (computed) value + +6. define a main for your test like this + +TESTMAIN(TestArithmetic); + +7. add the following to the Makefile.am (you may want to add more source files, + as required) + +testarithmetic_SOURCES = testarithmetic.cc + +8. add it to check_PROGRAMS diff --git a/tests/remotetest.idl b/tests/remotetest.idl new file mode 100644 index 0000000..6301077 --- /dev/null +++ b/tests/remotetest.idl @@ -0,0 +1,11 @@ +interface RemoteTest { + readonly attribute long fortyTwo; + + object createObject(string name); + oneway void die(); +}; + +interface Calculator { + long add(long a, long b); + string concat(string a, string b); +}; diff --git a/tests/test.h b/tests/test.h new file mode 100644 index 0000000..a72b13d --- /dev/null +++ b/tests/test.h @@ -0,0 +1,130 @@ + /* + + Copyright (C) 2000 Stefan Westerfeld + stefan@space.twc.de + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + + */ + +#ifndef ARTS_TESTS_H +#define ARTS_TESTS_H + +#include <string> +#include <list> +#include <iostream> +#include <stdio.h> + +const char *noTest = "noTest"; +const char *noClass = "noClass"; +const char *currentClass = noClass; +const char *currentTest = noTest; + +#define testCaption() \ + fprintf (stderr,"\n %s::%s (%s:%d)\n", \ + currentClass, currentTest, __FILE__, __LINE__); + +#define testAssert(expr) \ + if (!(expr)) { \ + testCaption(); \ + fprintf (stderr," => test assertion failed: (%s)\n", #expr); \ + exit(1); \ + } + +template<typename T1, typename T2> +inline void testEqualsCheck(const T1& expected, const T2& got, + const char *file, int line, const char *expr, const char *expr2) +{ + if(! (static_cast<T2>(expected) == got) ) { + std::cerr << std::endl + + << " " << currentClass << "::" << currentTest + << " (" << file << ":" << line << ")" << std::endl + + << " => test assertion failed:" + << " (" << expr << " == " << expr2 << ")" << std::endl + + << " => expected '" << expected << "'" << " got " + << "'" << got << "'." << std::endl; + exit(1); + } +} + +#define testEquals(expr, expr2) \ + testEqualsCheck(expr, expr2, __FILE__, __LINE__, #expr, #expr2) + +#define TEST(func) \ + struct t ## func : TestClass \ + { \ + t ## func() { \ + if(!tests) tests = new list<TestClass *>; \ + tests->push_back(this); \ + } \ + void invoke() { \ + currentTest = #func; \ + instance->func(); \ + currentTest = noTest; \ + } \ + } i ## func; \ + void func() + +struct TestClass { + virtual void invoke() = 0; +}; + +struct TestCase { + virtual void setUp() { }; + virtual void tearDown() { }; + virtual ~TestCase() { }; +}; + +#define TESTCASE(name) \ + static list<TestClass *> *tests; \ + static name *instance; \ + name () { \ + instance = this; \ + } \ + void testAll() { \ + currentClass = #name; \ + list<TestClass *>::iterator i; \ + for(i = tests->begin(); i != tests->end(); i++) \ + { \ + setUp(); \ + (*i)->invoke(); \ + tearDown(); \ + } \ + currentClass = noClass; \ + } \ + int count() { \ + return tests->size(); \ + } + +#define TESTMAINFUNC(name,func) \ + name *name::instance = 0; \ + list<TestClass *> *name::tests = 0; \ + int func() \ + { \ + name tb; \ + fprintf(stderr,"%-20s: %5d test methods - ", \ + #name,tb.count()); \ + tb.testAll(); \ + return 0; \ + } + +#define TESTMAIN(name) TESTMAINFUNC(name,main) + +#endif // ARTS_TESTS_H + diff --git a/tests/testanyref.cc b/tests/testanyref.cc new file mode 100644 index 0000000..d2ac7fa --- /dev/null +++ b/tests/testanyref.cc @@ -0,0 +1,97 @@ + /* + + Copyright (C) 2000 Stefan Westerfeld + stefan@space.twc.de + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + + */ + +#include "common.h" +#include "test.h" + +using namespace Arts; +using namespace std; + +struct TestAnyRef : public TestCase +{ + TESTCASE(TestAnyRef); + + Dispatcher dispatcher; + Buffer *buffer, *buffer2; + Any any; + + void setUp() { + buffer = new Buffer(); + any.type = ""; + any.value.clear(); + } + void tearDown() { + delete buffer; buffer = 0; + } + void copy(AnyRef& src, AnyRef& dest) + { + Buffer tmp; + src.write(&tmp); + tmp.rewind(); + dest.read(&tmp); + } + TEST(ioAnyFloat) { + // create a buffer with a float and a end-of-buffer delimiter + float f = 1.1; + buffer->writeFloat(f); + buffer->writeLong(12345678); + buffer->rewind(); + + // see if reading it as float reads the *only* the float + any.type = "float"; + + AnyRef ref(any); + ref.read(buffer); + testEquals(12345678,buffer->readLong()); + testEquals(4, any.value.size()); + + // check if the value is all right by copying it to a "real" float + float f2; + AnyRef ref2(f2); + copy(ref,ref2); + testEquals(f,f2); + } + TEST(ioAnyType) { + // do the same again with a complex structured type + Arts::InterfaceDef objInterface = + Dispatcher::the()->interfaceRepo().queryInterface("Arts::Object"); + testEquals("Arts::Object", objInterface.name); + + objInterface.writeType(*buffer); + buffer->writeLong(12345678); + buffer->rewind(); + + vector<mcopbyte> objInterfaceRaw; + buffer->read(objInterfaceRaw, buffer->remaining() - 4); + buffer->rewind(); + testAssert(objInterfaceRaw.size() > 50); + + any.type = "Arts::InterfaceDef"; + AnyRef ref(any); + ref.read(buffer); + testEquals(12345678,buffer->readLong()); + testAssert(objInterfaceRaw == any.value); + } + +}; + +TESTMAIN(TestAnyRef); diff --git a/tests/testbuffer.cc b/tests/testbuffer.cc new file mode 100644 index 0000000..caa8b70 --- /dev/null +++ b/tests/testbuffer.cc @@ -0,0 +1,139 @@ + /* + + Copyright (C) 2000 Stefan Westerfeld + stefan@space.twc.de + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + + */ + +#include "buffer.h" +#include "test.h" + +using namespace Arts; +using namespace std; + +struct TestBuffer : public TestCase +{ + TESTCASE(TestBuffer); + + Arts::Buffer *buffer, *buffer1234; + + void setUp() { + buffer = new Buffer(); + buffer1234 = new Buffer(); + buffer1234->writeByte(1); + buffer1234->writeByte(2); + buffer1234->writeByte(3); + buffer1234->writeByte(4); + } + void tearDown() { + delete buffer; buffer = 0; + delete buffer1234; buffer1234 = 0; + } + TEST(writeByte) { + buffer->writeByte(0x42); + + testEquals("42",buffer->toString("")); + testEquals(0x42,buffer->readByte()); + } + TEST(writeLong) { + buffer->writeLong(10001025); + + testEquals("00989a81",buffer->toString("")); + testEquals(10001025, buffer->readLong()); + } + TEST(writeString) { + buffer->writeString("hello"); + + /* __size__ h e l l o \0 */ + testEquals("00000006""68656c6c6f00",buffer->toString("")); + + string s; + buffer->readString(s); + testEquals("hello", s); + } + TEST(writeBool) { + buffer->writeBool(true); + buffer->writeBool(false); + + testEquals("0100",buffer->toString("")); + testEquals(true, buffer->readBool()); + testEquals(false, buffer->readBool()); + } + TEST(writeFloat) { + float f = 2.15; + buffer->writeFloat(f); + + testEquals("4009999a",buffer->toString("")); + testEquals(f,buffer->readFloat()); + } + TEST(write) { + vector<mcopbyte> b; + b.push_back(1); + b.push_back(2); + + buffer->write(b); + + testEquals("0102",buffer->toString("")); + + char c[2] = { 3,4 }; + buffer->write(c,2); + + testEquals("01020304",buffer->toString("")); + } + TEST(read) { + vector<mcopbyte> bytes; + buffer1234->read(bytes,4); + + testEquals(4, bytes.size()); + testEquals(1, bytes[0]); + testEquals(2, bytes[1]); + testEquals(3, bytes[2]); + testEquals(4, bytes[3]); + + // read shall overwrite the vector it gets as parameter + buffer1234->rewind(); + buffer1234->read(bytes,3); + testEquals(3, bytes.size()); + } + TEST(errorHandling) + { + testEquals(false, buffer1234->readError()); + testEquals(4, buffer1234->size()); + testEquals(4, buffer1234->remaining()); + buffer1234->readLong(); + testEquals(4, buffer1234->size()); + testEquals(0, buffer1234->remaining()); + testEquals(false, buffer1234->readError()); + buffer1234->readByte(); + testEquals(4, buffer1234->size()); + testEquals(0, buffer1234->remaining()); + testEquals(true, buffer1234->readError()); + + testEquals(false, buffer->readError()); + buffer->writeLong(0xdddddddd); + buffer->writeLong(0x12345678); + + // check that it terminates properly upon reading broken data + string s; + testEquals(false,buffer->readError()); + buffer->readString(s); + testEquals(true, buffer->readError()); + } +}; + +TESTMAIN(TestBuffer); diff --git a/tests/testchangenotify.cc b/tests/testchangenotify.cc new file mode 100644 index 0000000..bc40a96 --- /dev/null +++ b/tests/testchangenotify.cc @@ -0,0 +1,195 @@ + /* + + Copyright (C) 2000 Stefan Westerfeld stefan@space.twc.de + + This program 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 2 of the License, or + (at your option) any later version. + + This program 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 this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + Permission is also granted to link this program with the Qt + library, treating Qt like a library that normally accompanies the + operating system kernel, whether or not that is in fact the case. + + */ + +#include "value.h" +#include "connect.h" +#include "test.h" +#include <iostream.h> +#include <stdio.h> + +using namespace std; +using namespace Arts; + +struct TestChangeNotify : public TestCase +{ + TESTCASE(TestChangeNotify); + + Arts::Dispatcher dispatcher; + float zero, three, four; + + void setUp() + { + zero = 0.0; + three = 3.0; + four = 4.0; + } + + void process() + { + dispatcher.ioManager()->processOneEvent(false); + } + + TEST(floatValue) + { + FloatValue f; + + testEquals(zero, f.value()); + + f.value(three); + testEquals(three, f.value()); + } + TEST(stringValue) + { + StringValue s; + + testEquals("",s.value()); + + s.value("hello"); + testEquals("hello", s.value()); + } + TEST(floatNotify) + { + FloatValue f1, f2; + + connect(f1,"value_changed",f2,"value"); + f1.value(three); + + process(); + testEquals(three, f2.value()); + } + TEST(floatMultiNotify) + { + FloatValue f1, f2, f3; + + connect(f1,"value_changed",f2,"value"); + connect(f1,"value_changed",f3,"value"); + f1.value(three); + + process(); + testEquals(three, f2.value()); + testEquals(three, f3.value()); + } + TEST(floatCrossNotify) + { + FloatValue f1, f2; + + connect(f1,"value_changed",f2,"value"); + connect(f2,"value_changed",f1,"value"); + f1.value(three); + + process(); + testEquals(three, f1.value()); + testEquals(three, f2.value()); + + f2.value(four); + + process(); + testEquals(four, f1.value()); + testEquals(four, f2.value()); + } + TEST(stringNotify) + { + StringValue s1, s2; + + connect(s1,"value_changed",s2,"value"); + s1.value("hello"); + + process(); + testEquals("hello", s2.value()); + } + TEST(stringMultiNotify) + { + StringValue s1, s2, s3; + + connect(s1,"value_changed",s2,"value"); + connect(s1,"value_changed",s3,"value"); + s1.value("hello"); + + process(); + testEquals("hello", s2.value()); + testEquals("hello", s3.value()); + } + TEST(stringCrossNotify) + { + StringValue s1, s2; + + connect(s1,"value_changed",s2,"value"); + connect(s2,"value_changed",s1,"value"); + s1.value("world"); + + process(); + testEquals("world", s1.value()); + testEquals("world", s2.value()); + + s2.value("test"); + + process(); + testEquals("test", s1.value()); + testEquals("test", s2.value()); + } + TEST(floatSenderToValue1) + { + FloatSender sender; + FloatValue f; + + connect(sender,"outstream",f,"value"); + vector<float> data; + data.push_back(three); + sender.send(data); + + process(); + testEquals(three,f.value()); + } + TEST(floatSenderToValue2) + { + FloatSender sender; + FloatValue f; + + connect(sender,"outstream",f,"value"); + vector<float> data; + data.push_back(three); + data.push_back(four); + sender.send(data); + + process(); + testEquals(four,f.value()); + } + TEST(myEnumNotify) + { + MyEnumValue e1, e2; + + connect(e1,"value_changed",e2,"value"); + + testEquals(meIdle, e1.value()); + testEquals(meIdle, e2.value()); + + e1.value(meHelloWorld); + process(); + + testEquals(meHelloWorld, e1.value()); + testEquals(meHelloWorld, e2.value()); + } +}; + +TESTMAIN(TestChangeNotify); diff --git a/tests/testdispatcher.cc b/tests/testdispatcher.cc new file mode 100644 index 0000000..c3d68a8 --- /dev/null +++ b/tests/testdispatcher.cc @@ -0,0 +1,41 @@ + /* + + Copyright (C) 2000 Stefan Westerfeld + stefan@space.twc.de + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + + */ + +#include "dispatcher.h" +#include "test.h" + +using namespace Arts; +using namespace std; + +struct TestDispatcher : public TestCase +{ + TESTCASE(TestDispatcher); + + TEST(newDispatcher) { + for(int i = 0;i < 10; i++) { + Dispatcher *dispatcher = new Dispatcher(); + delete dispatcher; + } + } +}; + +TESTMAIN(TestDispatcher); diff --git a/tests/testflowsystem.cc b/tests/testflowsystem.cc new file mode 100644 index 0000000..7763fb2 --- /dev/null +++ b/tests/testflowsystem.cc @@ -0,0 +1,83 @@ + /* + + Copyright (C) 2000 Stefan Westerfeld + stefan@space.twc.de + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + + */ + +#include "flowsystem.h" +#include "connect.h" +#include "value.h" +#include "test.h" + +using namespace Arts; +using namespace std; + +struct TestFlowSystem : public TestCase +{ + TESTCASE(TestFlowSystem); + + Dispatcher dispatcher; + StringValue v1, v2; + + void process() { + dispatcher.ioManager()->processOneEvent(false); + } + void setUp() { + /* initialize v1, v2 with values */ + v1 = StringValue(); v1.value("v1"); + v2 = StringValue(); v2.value("v2"); + } + void tearDown() { + v1 = StringValue::null(); + v2 = StringValue::null(); + } + TEST(connectObject) { + dispatcher.flowSystem()->connectObject(v1,"value_changed",v2,"value"); + + testEquals("v1",v1.value()); + testEquals("v2",v2.value()); + + v1.value("test"); + process(); + + testEquals("test",v1.value()); + testEquals("test",v2.value()); + } + // at the time of writing, this fails: disconnectObject is not implemented + TEST(disconnectObject) { + connect(v1,"value_changed",v2,"value"); + + /* here we have a connection, so this should be sent */ + v1.value("sendThis"); + process(); + testEquals("sendThis", v2.value()); + + dispatcher.flowSystem()->disconnectObject(v1,"value_changed", + v2,"value"); + + /* here we don't have a connection, so this should not be sent */ + v1.value("v1only"); + process(); + + testEquals("v1only", v1.value()); + testEquals("sendThis", v2.value()); + } +}; + +TESTMAIN(TestFlowSystem); diff --git a/tests/testifacerepo.cc b/tests/testifacerepo.cc new file mode 100644 index 0000000..8464cf5 --- /dev/null +++ b/tests/testifacerepo.cc @@ -0,0 +1,84 @@ + /* + + Copyright (C) 2000 Stefan Westerfeld + stefan@space.twc.de + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + + */ + +#include <algorithm> +#include "common.h" +#include "test.h" + +using namespace Arts; +using namespace std; + +struct TestInterfaceRepo : public TestCase +{ + TESTCASE(TestInterfaceRepo); + + Arts::Dispatcher dispatcher; + Arts::InterfaceRepo interfaceRepo; + + void setUp() { + interfaceRepo = Arts::Dispatcher::the()->interfaceRepo(); + } + TEST(queryInterface) { + InterfaceDef def = interfaceRepo.queryInterface("Arts::InterfaceRepo"); + + testEquals("Arts::InterfaceRepo",def.name); + } + TEST(queryType) { + TypeDef def = interfaceRepo.queryType("Arts::MethodDef"); + + testEquals("Arts::MethodDef",def.name); + } + TEST(queryEnum) { + EnumDef def = interfaceRepo.queryEnum("Arts::AttributeType"); + + testEquals("Arts::AttributeType",def.name); + } + bool contains(vector<string>& sequence, const string& element) + { + vector<string>::iterator it; + it = find(sequence.begin(),sequence.end(), element); + return (it != sequence.end()); + } + TEST(queryInterfaces) { + vector<string> *interfaces = interfaceRepo.queryInterfaces(); + + testAssert(contains(*interfaces,"Arts::InterfaceRepo")); + testAssert(!contains(*interfaces,"Arts::MethodDef")); + delete interfaces; + } + TEST(queryTypes) { + vector<string> *types = interfaceRepo.queryTypes(); + + testAssert(contains(*types,"Arts::MethodDef")); + testAssert(!contains(*types,"Arts::AttributeType")); + delete types; + } + TEST(queryEnums) { + vector<string> *enums = interfaceRepo.queryEnums(); + + testAssert(contains(*enums,"Arts::AttributeType")); + testAssert(!contains(*enums,"Arts::InterfaceRepo")); + delete enums; + } +}; + +TESTMAIN(TestInterfaceRepo); diff --git a/tests/testnotification.cc b/tests/testnotification.cc new file mode 100644 index 0000000..e36391f --- /dev/null +++ b/tests/testnotification.cc @@ -0,0 +1,146 @@ + /* + + Copyright (C) 2001 Stefan Westerfeld + stefan@space.twc.de + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + + */ + +#include "notification.h" +#include "dispatcher.h" +#include "test.h" + +using namespace Arts; +using namespace std; + +static string messagesReceived; +static long messagesAlive; + +static void destroyString(const Notification& n) +{ + messagesAlive--; + delete (string *)n.data; +} + +class Receiver : public NotificationClient { +private: + long alive; + +public: + Receiver() { alive = 42; } + virtual ~Receiver() { + NotificationManager::the()->removeClient(this); + alive = 0; + } + + void notify(const Notification& n) { + if(alive != 42) messagesReceived += "<dead>"; + + string *data = (string *)n.data; + messagesReceived += *data; + destroyString(n); + + if(alive != 42) messagesReceived += "</dead>"; + } +}; + +struct TestNotification : public TestCase +{ + TESTCASE(TestNotification); + + Dispatcher dispatcher; + + void setUp() { + messagesReceived = ""; + messagesAlive = 0; + } + void tearDown() { + } + void sendNotification(Receiver& r, string text) + { + messagesAlive++; + Notification n; + n.receiver = &r; + n.data = new string(text); + n.internal = 0; + n.setDestroy(destroyString); + NotificationManager::the()->send(n); + } + + /* sending a notification (should be asynchronous) */ + TEST(send) { + Receiver r1; + sendNotification(r1,"r1"); + + testEquals(1,messagesAlive); + testEquals("",messagesReceived); + testEquals(true, NotificationManager::the()->pending()); + + NotificationManager::the()->run(); + + testEquals("r1",messagesReceived); + testEquals(false, NotificationManager::the()->pending()); + testEquals(0,messagesAlive); + } + + /* order of sending notifications (first-in-first-out) */ + TEST(sendOrder) { + Receiver r1,r2; + + sendNotification(r1,"r1"); + sendNotification(r2,"r2"); + + testEquals(2,messagesAlive); + testEquals("",messagesReceived); + testEquals(true, NotificationManager::the()->pending()); + + NotificationManager::the()->run(); + + testEquals(false, NotificationManager::the()->pending()); + testEquals(0,messagesAlive); + testEquals("r1r2",messagesReceived); + } + + /* deletion of unprocessed notifications once a client dies */ + TEST(clientDeletion) { + Receiver *r1 = new Receiver, + *r2 = new Receiver, + *r3 = new Receiver, + *r4 = new Receiver; + + sendNotification(*r1,"r1"); + sendNotification(*r2,"r2"); + sendNotification(*r3,"r3"); + sendNotification(*r4,"r4"); + + testEquals(4,messagesAlive); + testEquals("",messagesReceived); + + delete r2; + delete r4; + + testEquals(2,messagesAlive); + testEquals("",messagesReceived); + + NotificationManager::the()->run(); + + testEquals("r1r3",messagesReceived); + testEquals(0,messagesAlive); + } +}; + +TESTMAIN(TestNotification); diff --git a/tests/testremote.cc b/tests/testremote.cc new file mode 100644 index 0000000..eeaa6a0 --- /dev/null +++ b/tests/testremote.cc @@ -0,0 +1,176 @@ + /* + + Copyright (C) 2000 Stefan Westerfeld stefan@space.twc.de + + This program 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 2 of the License, or + (at your option) any later version. + + This program 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 this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + Permission is also granted to link this program with the Qt + library, treating Qt like a library that normally accompanies the + operating system kernel, whether or not that is in fact the case. + + */ + +#include "remotetest.h" +#include "value.h" +#include "test.h" +#include "connect.h" +#include <iostream.h> +#include <stdio.h> + +using namespace std; +using namespace Arts; + +class RemoteTest_impl: virtual public RemoteTest_skel { +private: + bool alive; + +public: + RemoteTest_impl() + { + alive = true; + _copy(); + } + ~RemoteTest_impl() + { + Dispatcher::the()->terminate(); + } + + Object createObject(const string& name) + { + return SubClass(name); + } + long fortyTwo() + { + return 42; + } + void die() + { + if(alive) + { + _release(); + alive = false; + } + } +}; + +REGISTER_IMPLEMENTATION(RemoteTest_impl); + +/* name of the remote object - should be sufficiently unique */ +char objectName[60]; + +struct TestRemote : public TestCase +{ + TESTCASE(TestRemote); + + Arts::Dispatcher dispatcher; + RemoteTest remoteTest; + + void setUp() { + string globalRef = "global:"; + globalRef += objectName; + + remoteTest = Arts::Reference(globalRef); + } + void tearDown() { + remoteTest = RemoteTest::null(); + } + + void process() + { + dispatcher.ioManager()->processOneEvent(false); + } + + + /* test whether the server is running, and we could connect ok */ + TEST(connected) { + testEquals(false, remoteTest.isNull()); + } + + /* test method call */ + TEST(fortyTwo) { + testEquals(42, remoteTest.fortyTwo()); + } + + /* test remote change notifications */ + TEST(remoteChangeNotify) { + StringValue local; + local.value("local"); + testEquals("local", local.value()); + + Object o = remoteTest.createObject("StringValue"); + testAssert(!o.isNull()); + + StringValue remote = Arts::DynamicCast(o); + testAssert(!remote.isNull()); + remote.value("remote"); + testEquals("remote", remote.value()); + + connect(local,"value_changed",remote,"value"); + local.value("transferme"); + + process(); + sleep(1); /* change notifications are asynchronous */ + + testEquals("transferme", local.value()); + testEquals("transferme", remote.value()); + + disconnect(local,"value_changed",remote,"value"); + + local.value("notransfer"); + + testEquals("notransfer", local.value()); + testEquals("transferme", remote.value()); + } + + /* terminate server */ + TEST(die) { + remoteTest.die(); + remoteTest = RemoteTest::null(); + sleep(1); + } + + /* check if server is dead now */ + TEST(dead) { + testEquals(true, remoteTest.isNull()); + } +}; + +TESTMAINFUNC(TestRemote,performTests); + +/* + * this test case is a bit tricky because we need a client and a server + * + * we create the server in a fork()ed process, and then evaluate the test + * inside the client + */ +int main() +{ + /* create unique object name for test server/test client */ + sprintf(objectName, "RemoteTest_%d_%ld", getpid(), time(0)); + + int pid = fork(); + if(pid == 0) /* child process - we play the server here */ + { + Dispatcher dispatcher(0, Dispatcher::startUnixServer); + ObjectManager::the()->addGlobalReference(RemoteTest(), objectName); + dispatcher.run(); + return 0; + } + else if(pid >= 0) /* parent process - do the test here */ + { + sleep(1); + return performTests(); + } +} diff --git a/tests/testwrapper.cc b/tests/testwrapper.cc new file mode 100644 index 0000000..c590f36 --- /dev/null +++ b/tests/testwrapper.cc @@ -0,0 +1,211 @@ + /* + + Copyright (C) 2000 Stefan Westerfeld stefan@space.twc.de + + This program 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 2 of the License, or + (at your option) any later version. + + This program 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 this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + Permission is also granted to link this program with the Qt + library, treating Qt like a library that normally accompanies the + operating system kernel, whether or not that is in fact the case. + + */ + +#include "wrapper.h" +#include "test.h" +#include <iostream.h> +#include <stdio.h> + +using namespace std; +using namespace Arts; + +int active_d_objects = 0; + +class D_impl: virtual public D_skel { +private: + long _value; +public: + void value(long newVal) { _value = newVal; } + long value() { return _value; } + + D_impl() :_value(0) { active_d_objects++; } + ~D_impl() { active_d_objects--; } + string a() { return "a"; } + string b() { return "b"; } + string c() { return "c"; } + string d() { return "d"; } + void dummy() { } + + long sum(A v1, A v2) { return v1.value() + v2.value(); } + D self() { return D::_from_base(_copy()); } +}; + +REGISTER_IMPLEMENTATION(D_impl); + +class B_impl: virtual public B_skel { +private: + long _value; +public: + void value(long newVal) { _value = newVal; } + long value() { return _value; } + B_impl() :_value(0) {} + string a() { return "a"; } + string b() { return "b"; } +}; +REGISTER_IMPLEMENTATION(B_impl); + + +struct TestWrapper : public TestCase +{ + TESTCASE(TestWrapper); + + Arts::Dispatcher dispatcher; + + /* + generic inheritance test, tests that using a D object, you + can call the a,b,c,d methods without problems + */ + TEST(genericInheritance) + { + D d; + + /* implications of lazy creation */ + testEquals(0, active_d_objects); + + C c = d; + testEquals(0, active_d_objects); + + string abcd = A(d).a()+d.b()+c.c()+d.d(); + testEquals("abcd",abcd); + + /* + should be exactly one here, not more than one through the various + assignments + */ + testEquals(1, active_d_objects); + + Object o = d; + + /* dynamic casting tests */ + c = DynamicCast(o); // operator + testEquals(false, c.isNull()); + testEquals("c", c.c()); + + C cc = DynamicCast(o); // constructor + testEquals(false, cc.isNull()); + testEquals("c", cc.c()); + + A a = Reference(d.toString()); + cc = DynamicCast(a); + testEquals(false, cc.isNull()); + testEquals("c", cc.c()); + + /* isNull() and error() */ + testEquals(false, d.isNull()); + testEquals(false, d.error()); + + d = D::null(); + testEquals(true, d.isNull()); + testEquals(false, c.isNull()); + testEquals(false, d.error()); + + /* reference counting */ + c = C::null(); + o = Object::null(); + cc = C::null(); + a = A::null(); + testEquals(0, active_d_objects); + } + TEST(nullInAssign) { + B b; + B b2 = b; + b = B::null(); + testEquals(true, b.isNull()); + testEquals(false, b2.isNull()); + } + TEST(coreference) { + B b3; + B b4=b3; + b3.value(3); + testEquals(3, b4.value()); + } + + D afunc(D arg) + { + arg.value(42); + return arg; + } + + TEST(cacheAndArgs) { + /* test cache invalidation */ + B b; + b.value(3); // stores 3 using parent method + testEquals(0, active_d_objects); + + D d; + d.value(6); + testEquals(1, active_d_objects); + + b = d; // uses operator, not constructor. should invalidate A::cacheOK + testEquals(6, b.value()); + testEquals(1, active_d_objects); + + A a = afunc(d); + testEquals(1, active_d_objects); + testEquals(42, a.value()); + testEquals(42, b.value()); + testEquals(42, d.value()); + } + + TEST(dynamicCastNull) { + D normalD; + D nullD = D::null(); + A aNormalD = normalD; + A aNullD = nullD; + D d; + + d = DynamicCast(aNormalD); + testEquals(false, d.isNull()); + + d = DynamicCast(aNullD); + testEquals(true, d.isNull()); + } + + TEST(stringification) { + D d; + d.value(5); + + string s = d.toString(); + + D anotherD = Arts::Reference(s); + testEquals(false, anotherD.isNull()); + testEquals(5, anotherD.value()); + } + /* + unfortunately, this currently fails, because resolving a reference to a + non-existing object is not handled properly by the dispatcher - I am not + sure whether it is worth fixing it (which might be complicated) + + TEST(stringificationFailures) { + D d; + d.value(5); + string s = d.toString(); + d = D::null(); + + D anotherD = Arts::Reference(s); + testEquals(true, anotherD.isNull()); + }*/ +}; + +TESTMAIN(TestWrapper); diff --git a/tests/value.idl b/tests/value.idl new file mode 100644 index 0000000..ae5e15c --- /dev/null +++ b/tests/value.idl @@ -0,0 +1,18 @@ +interface FloatValue { + attribute float value; +}; + +interface StringValue { + attribute string value; +}; + +enum MyEnum { meIdle, meHelloWorld }; + +interface MyEnumValue { + attribute MyEnum value; +}; + +interface FloatSender { + void send(sequence<float> data); + async out float stream outstream; +}; diff --git a/tests/value_impl.cc b/tests/value_impl.cc new file mode 100644 index 0000000..cdb4343 --- /dev/null +++ b/tests/value_impl.cc @@ -0,0 +1,94 @@ + /* + + Copyright (C) 2000-2001 Stefan Westerfeld + stefan@space.twc.de + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + + */ + +#include "value.h" + +using namespace std; + +class FloatValue_impl : virtual public FloatValue_skel { +private: + float _value; +public: + FloatValue_impl() : _value(0) { }; + void value(float newvalue) + { + if(newvalue != _value) + { + _value = newvalue; + value_changed(_value); + } + } + float value() { return _value; } +}; + +REGISTER_IMPLEMENTATION(FloatValue_impl); + +class StringValue_impl : virtual public StringValue_skel { +private: + string _value; +public: + StringValue_impl() { }; + void value(const string& newvalue) + { + if(newvalue != _value) + { + _value = newvalue; + value_changed(_value); + } + } + string value() { return _value; } +}; + +REGISTER_IMPLEMENTATION(StringValue_impl); + +class FloatSender_impl : virtual public FloatSender_skel { +public: + void send(const vector<float>& data) + { + Arts::DataPacket<float> *packet = outstream.allocPacket(data.size()); + copy(data.begin(), data.end(), packet->contents); + packet->size = data.size(); + packet->send(); + } +}; + +REGISTER_IMPLEMENTATION(FloatSender_impl); + +class MyEnumValue_impl : virtual public MyEnumValue_skel { +private: + MyEnum _value; +public: + MyEnumValue_impl() : _value(meIdle) { }; + void value(MyEnum newvalue) + { + if(newvalue != _value) + { + _value = newvalue; + value_changed(_value); + } + } + MyEnum value() { return _value; } +}; + +REGISTER_IMPLEMENTATION(MyEnumValue_impl); + + diff --git a/tests/wrapper.idl b/tests/wrapper.idl new file mode 100644 index 0000000..dc0c0b6 --- /dev/null +++ b/tests/wrapper.idl @@ -0,0 +1,27 @@ +/*------------------- Test classes for smartwrappers ---------------------*/ + +interface A { + attribute long value; + string a(); // returns "a" +}; + +interface B : A { + string b(); // returns "b" +}; + +interface C : A { + string c(); // returns "c" +}; + +interface D : B, C { + // returns the interface itself + readonly attribute D self; + + string d(); // returns "d" + + // returns sum of both interface values + long sum(A v1, A v2); + + // dummy method + void dummy(); +}; |