#include #include "test_base.h" #include "../primitive.h" #include "../r.h" class A { public: A(Int i) : i(i) { /*std::cout << "A(" << i << ") ctor" << std::endl;*/ } ~A() { /*std::cout << "A(" << i << ") dtor" << std::endl;*/ } Int i; }; Int bc = 0L; Int bd = 0L; Int cc = 0L; Int cd = 0L; class B { public: B(int i) : i(i) { ++bc; } virtual ~B() { ++bd; } virtual Int getI() { return i; } protected: Int i; }; class C : public B { public: C(int i) : B(i) { ++cc; } virtual ~C() { ++cd; } virtual Int getI() { return i + 1; } }; void test(); int main() { int retVal = -1; try { std::cout << "**** Testing references ****" << std::endl; test(); std::cout << "Test SUCCEEDED!" << std::endl; retVal = 0; } catch (TestFailed& ex) { std::cout << "Failed" << std::endl << "Test FAILED: " << ex.what() << std::endl; } catch (...) { std::cout << "Failed" << std::endl << "Test FAILED with unknown exception" << std::endl; } return retVal; } void test() { StringStream ss; std::cout << "Basic tests"; R a = Ref::mk(5); auto fun = [&ss](R a2, Int refCount, Int val) { ss.empty() << "a2->i (with val " << val << ") == " << a2->i << ", should be " << val << "!"; assertEq(a2->i, val, ss.str()); Int refc = a2.refCount(); ss.empty() << "a2.refCount() (with val " << val << ") == " << refc <<" should be " << refCount << "!"; assertEq(a2.refCount(), refc, ss.str()); }; Int deref = a->i; ss.empty() << "a->i (with val " << 5l << ") == " << deref << ", should be " << 5l << "!"; assertEq(deref, 5l, ss.str()); Int refc = a.refCount(); ss.empty() << "a.refCount() (with val " << 5l << ") == " << refc <<" should be " << 1l << "!"; assertEq(refc, 1l, ss.str()); fun(Ref::mk(7), 1, 7); fun(a, 2, 5); deref = a->i; ss.empty() << "a->i (with val " << 5l << ") == " << deref << ", should be " << 5l << "!"; assertEq(deref, 5l, ss.str()); refc = a.refCount(); ss.empty() << "a.refCount() (with val " << 5l << ") == " << refc <<" should be " << 1l << "!"; assertEq(refc, 1l, ss.str()); std::cout << "Success" << std::endl << "null reference tests"; R b; assertEq(b.isNull(), true, "b.isNull returned false instead of true"); auto funDeref = [&b] () { A& a = *b; }; auto funRefCount = [&b] () { Int i = b.refCount(); }; assertException::thrown(funDeref, "Dereferencing null ref did not throw exception"); assertException::thrown(funRefCount, "Getting reference count for null ref did not throw exception"); std::cout << "Success" << std::endl << "operator= tests"; { R c; c = a; deref = a->i; ss.empty() << "a->i (with val " << 5l << ") == " << deref << ", should be " << 5l << "!"; assertEq(deref, 5l, ss.str()); refc = a.refCount(); ss.empty() << "a.refCount() (in subblock, with val " << 5l << ") == " << refc <<" should be " << 2l << "!"; assertEq(refc, 2l, ss.str()); deref = c->i; ss.empty() << "c->i (with val " << 5l << ") == " << deref << ", should be " << 5l << "!"; assertEq(deref, 5l, ss.str()); refc = c.refCount(); ss.empty() << "c.refCount() (with val " << 5l << ") == " << refc <<" should be " << 2l << "!"; assertEq(refc, 2l, ss.str()); c->i = 20l; } deref = a->i; ss.empty() << "a->i (with val " << 20l << ") == " << deref << ", should be " << 20l << "!"; assertEq(deref, 20l, ss.str()); refc = a.refCount(); ss.empty() << "a.refCount() (with val " << 5l << ") == " << refc <<" should be " << 1l << "!"; assertEq(refc, 1l, ss.str()); std::cout << "Success" << std::endl << "plimorphism tests"; { R c = Ref::mk(10L); assertEq(bc, 1L, "B should be created but it is not"); assertEq(cc, 1L, "C should be created but it is not"); deref = c->getI(); ss.empty() << "c->getI() should return 11L but it returns " << deref; assertEq(deref, 11L, ss.str()); } assertEq(bd, 1L, "B should be destroyed but it is not"); assertEq(cd, 1L, "C should be destroyed but it is not"); /*std::cout << "Success" << std::endl << "self-referencing tests"; R d = d; auto funDerefSelf = [&d]() { Int val = d.deref(); }; auto funRefCountSelf = [&d]() { Int refCount = d.refCount(); }; assertException::thrown(funRefCountSelf, "Reference counting of self-initialized ref did not throw exception"); assertException::thrown(funDerefSelf, "Dereferencing self-initialized ref did not throw exception"); d = Ref::mk(2); deref = d.deref(); ss.empty() << "d.deref() (with val " << 2l << ") == " << deref << ", should be " << 2l << "!"; assertEq(deref, 2l, ss.str()); refc = d.refCount(); ss.empty() << "d.refCount() (with val " << 2l << ") == " << refc <<" should be " << 1l << "!"; assertEq(refc, 1l, ss.str());*/ std::cout << "Success" << std::endl; }