|
|
|
/*
|
|
|
|
|
|
|
|
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
|
|
|
|
|
|
Permission is also granted to link this program with the TQt
|
|
|
|
library, treating TQt 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);
|