summaryrefslogtreecommitdiffstats
path: root/tests
diff options
context:
space:
mode:
authortpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2010-01-05 00:01:18 +0000
committertpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2010-01-05 00:01:18 +0000
commit42995d7bf396933ee60c5f89c354ea89cf13df0d (patch)
treecfdcea0ac57420e7baf570bfe435e107bb842541 /tests
downloadarts-42995d7bf396933ee60c5f89c354ea89cf13df0d.tar.gz
arts-42995d7bf396933ee60c5f89c354ea89cf13df0d.zip
Copy of aRts for Trinity modifications
git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/dependencies/arts@1070145 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'tests')
-rw-r--r--tests/Makefile.am44
-rw-r--r--tests/README.test72
-rw-r--r--tests/remotetest.idl11
-rw-r--r--tests/test.h130
-rw-r--r--tests/testanyref.cc97
-rw-r--r--tests/testbuffer.cc139
-rw-r--r--tests/testchangenotify.cc195
-rw-r--r--tests/testdispatcher.cc41
-rw-r--r--tests/testflowsystem.cc83
-rw-r--r--tests/testifacerepo.cc84
-rw-r--r--tests/testnotification.cc146
-rw-r--r--tests/testremote.cc176
-rw-r--r--tests/testwrapper.cc211
-rw-r--r--tests/value.idl18
-rw-r--r--tests/value_impl.cc94
-rw-r--r--tests/wrapper.idl27
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();
+};