/** @test verify an extension built on top of the ItemWrapper: * a function which remembers the last result. Here we use * a test function, which picks a member of an vector and * returns a \em reference to it. Thus the cached "result" * can be used to access and change the values within the * original vector. In a real world usage scenario, such a * function could be an (expensive) data structure access. */ void verifyFunctionRefResult() { vector<int> testVec; for (uint i=0; i<10; ++i) testVec.push_back(i); FunctionResult<int&(size_t)> funRes (pickElement_ofVector(testVec)); // function was never invoked, thus the remembered result is NIL CHECK (!funRes); VERIFY_ERROR (BOTTOM_VALUE, *funRes ); int& r5 = funRes (5); CHECK (funRes); // indicates existence of cached result CHECK (5 == r5); CHECK (isSameObject (r5, testVec[5])); int& r5x = *funRes; CHECK (isSameObject (r5, r5x)); CHECK ( isSameObject (r5, *funRes)); int& r7 = funRes (7); CHECK (!isSameObject (r5, *funRes)); CHECK ( isSameObject (r7, *funRes)); -- r5x; ++ *funRes; CHECK (5-1 == testVec[5]); CHECK (7+1 == testVec[7]); CHECK (7+1 == r7); }
/** @test proper handling of move and rvalue references */ void verifySaneMoveHandling() { using Data = shared_ptr<int>; using Wrap = ItemWrapper<Data>; Data data{new int(12345)}; CHECK (1 == data.use_count()); Wrap wrap{data}; CHECK (2 == data.use_count()); CHECK (12345 == **wrap); CHECK (isSameObject (*data, **wrap)); CHECK (!isSameObject (data, *wrap)); Wrap wcopy{wrap}; CHECK (3 == data.use_count()); Wrap wmove{move (wcopy)}; CHECK (3 == data.use_count()); CHECK (not wcopy); CHECK (wmove); wcopy = move(wmove); CHECK (3 == data.use_count()); CHECK (not wmove); CHECK (wcopy); Wrap wmove2{move (data)}; CHECK (0 == data.use_count()); CHECK (3 == wmove2->use_count()); CHECK (not data); CHECK (wmove2); CHECK (wrap); wmove2 = move (wcopy); CHECK (2 == wmove2->use_count()); CHECK (not wcopy); CHECK (wmove2); CHECK (wrap); wmove2 = move (wrap); CHECK (1 == wmove2->use_count()); CHECK (not wrap); CHECK (wmove2); wmove2 = move (wmove); CHECK (not wcopy); CHECK (not wmove); CHECK (not wmove2); }
void verifyCreation_and_Copy() { typedef PV Holder; typedef IMP ImpType; typedef typename PV::Interface Api; long prevSum = _checkSum; uint prevCnt = _created; Holder val = Holder::template build<ImpType>(); CHECK (prevSum+111 == _checkSum); // We got one primary ctor call CHECK (prevCnt+1 <= _created); // Note: usually, the compiler optimises CHECK (prevCnt+2 >= _created); // and skips the spurious copy-operation CHECK (sizeof(Holder) >= sizeof(ImpType)); Api& embedded = val; CHECK (isSameObject(embedded,val)); CHECK (INSTANCEOF(ImpType, &embedded)); prevCnt = _created; Holder val2(val); // invoke copy ctor without knowing the implementation type embedded.apiFunc(); CHECK (val != val2); // invoking the API function had an sideeffect on the state val = val2; // assignment of copy back to the original... CHECK (val == val2); // cancels the side effect CHECK (prevCnt+1 == _created); // one new embedded instance was created by copy ctor }
void produce_simple_values() { using TestFactory = factory::MultiFact<string, theID>; TestFactory theFact; // the first "production line" is wired to a free function theFact.defineProduction (ONE, buildOne); // second "production line" uses a explicit partial closure theFact.defineProduction (TWO, bind (buildSome<theID>, TWO)); // for the third "production line" we set up a function object auto memberFunction = bind (&MultiFact_test::callMe, this, "lalü"); theFact.defineProduction (THR, memberFunction); // and the fourth "production line" uses a lambda, closed with a local reference string backdoor("backdoor"); theFact.defineProduction (FOU, [&] { return backdoor; }); CHECK (!isnil (theFact)); CHECK (theFact(ONE) == "1"); CHECK (theFact(TWO) == "2"); CHECK (theFact(THR) == "lalü"); CHECK (invocations_ == 1); CHECK (theFact(FOU) == "backdoor"); backdoor = "I am " + backdoor.substr(0,4); CHECK (theFact(FOU) == "I am back"); TestFactory anotherFact; CHECK (isnil (anotherFact)); VERIFY_ERROR (INVALID, anotherFact(ONE) ); anotherFact.defineProduction (ONE, memberFunction); CHECK (anotherFact(ONE) == "lalü"); CHECK (invocations_ == 2); CHECK (theFact(THR) == "lalü"); CHECK (invocations_ == 3); CHECK ( theFact.contains (FOU)); CHECK (!anotherFact.contains (FOU)); anotherFact = theFact; CHECK (anotherFact.contains (FOU)); CHECK (!isSameObject(theFact, anotherFact)); CHECK (anotherFact(ONE) == "1"); CHECK (anotherFact(TWO) == "2"); CHECK (anotherFact(THR) == "lalü"); CHECK (anotherFact(FOU) == "I am back"); CHECK (invocations_ == 4); }
/** @test verify the allocation/de-allocation handling as * embedded into the CommandRegistry operation. * Simulates on low level what normally happens * during command lifecycle. */ void checkAllocation (CommandRegistry& registry) { // simulate what normally happens within a CommandDef typedef void Sig_oper(int); typedef long Sig_capt(int); typedef void Sig_undo(int,long); function<Sig_oper> o_Fun (command1::operate); function<Sig_capt> c_Fun (command1::capture); function<Sig_undo> u_Fun (command1::undoIt); CHECK (o_Fun && c_Fun && u_Fun); CHECK (cnt_inst == registry.instance_count()); // when the CommandDef is complete, it issues the // allocation call to the registry behind the scenes.... typedef shared_ptr<CommandImpl> PImpl; PImpl pImpl = registry.newCommandImpl(o_Fun,c_Fun,u_Fun); CHECK (1+cnt_inst == registry.instance_count()); CHECK (pImpl); CHECK (pImpl->isValid()); CHECK (!pImpl->canExec()); CHECK (1 == pImpl.use_count()); // no magic involved, we hold the only instance PImpl clone = registry.createCloneImpl(*pImpl); CHECK (clone->isValid()); CHECK (!clone->canExec()); CHECK (1 == clone.use_count()); CHECK (1 == pImpl.use_count()); CHECK (2+cnt_inst == registry.instance_count()); CHECK (!isSameObject (*pImpl, *clone)); CHECK (*pImpl == *clone); CHECK (!pImpl->canExec()); typedef Types<int> ArgType; TypedArguments<Tuple<ArgType>> arg{Tuple<ArgType>(98765)}; pImpl->setArguments(arg); CHECK (pImpl->canExec()); CHECK (!clone->canExec()); // this proves the clone has indeed a separate identity CHECK (*pImpl != *clone); // discard the first clone and overwrite with a new one clone = registry.createCloneImpl(*pImpl); CHECK (2+cnt_inst == registry.instance_count()); CHECK (*pImpl == *clone); CHECK (clone->canExec()); clone.reset(); pImpl.reset(); // corresponding allocation slots cleared automatically CHECK (cnt_inst == registry.instance_count()); }
Provision& operator= (Provision const& o) { if (!isSameObject(*this, o)) { AdviceLink::operator= (o); setSolution ( NULL ); } return *this; }
/** @test verify especially that we can wrap and handle * a reference "value" in a pointer-like manner */ void verifyWrappedRef () { int x = 5; ItemWrapper<int&> refWrap; CHECK (!refWrap); refWrap = x; CHECK (refWrap); CHECK (5 == *refWrap); CHECK (x == *refWrap); *refWrap += 5; CHECK (x == 10); ItemWrapper<int*> ptrWrap (& *refWrap); CHECK ( isSameObject (**ptrWrap, x)); CHECK (!isSameObject ( *ptrWrap, &x)); **ptrWrap += 13; CHECK (x == 23); }
void produce_smart_pointers() { using TestFactory = factory::MultiFact<Interface, theID, factory::BuildRefcountPtr>; using PIfa = shared_ptr<Interface>; TestFactory theFact; // set up the "production lines" by lambda theFact.defineProduction (ONE, [] { return new Implementation<ONE>; }); theFact.defineProduction (TWO, [] { return new Implementation<TWO>; }); theFact.defineProduction (THR, [] { return new Implementation<THR>; }); theFact.defineProduction (FOU, [] { return new Implementation<FOU>; }); CHECK (!isnil (theFact)); PIfa p1 = theFact(ONE); PIfa p2 = theFact(TWO); PIfa p3 = theFact(THR); PIfa p4 = theFact(FOU); PIfa p11 = theFact(ONE); CHECK ("Impl-1" == string(*p1)); CHECK ("Impl-2" == string(*p2)); CHECK ("Impl-3" == string(*p3)); CHECK ("Impl-4" == string(*p4)); CHECK ("Impl-1" == string(*p11)); CHECK (!isSameObject(*p1, *p11)); PIfa p12(p11); CHECK (isSameObject(*p11, *p12)); CHECK ("Impl-1" == string(*p12)); CHECK (1 == p1.use_count()); CHECK (2 == p11.use_count()); CHECK (2 == p12.use_count()); }
static void operate (PolyVal& elm) { PolyVal myLocalVal(elm); CHECK (elm == myLocalVal); long prevSum = _callSum; long randVal = myLocalVal->apiFunc(); CHECK (prevSum + randVal == _callSum); CHECK (elm != myLocalVal); elm = myLocalVal; CHECK (elm == myLocalVal); CHECK (!isSameObject (elm, myLocalVal)); CHECK (sizeof(myLocalVal) <= MAX_SIZ + polyvalue::Trait<Interface>::ADMIN_OVERHEAD + _ALIGN_); }
virtual void run (Arg) { CHECK (0 == checksum_); TypedAllocationManager allocator; typedef shared_ptr<DummyObj<1>> PD1; typedef shared_ptr<DummyObj<22>> PD22; CHECK (sizeof(DummyObj<1>) != sizeof(DummyObj<22>)); { PD1 pD11 = allocator.create<DummyObj<1> >(); PD1 pD12 = allocator.create<DummyObj<1> >(); PD22 pD21 = allocator.create<DummyObj<22>>(); PD22 pD22 = allocator.create<DummyObj<22>>(); CHECK (pD11); CHECK (pD12); CHECK (pD21); CHECK (pD22); CHECK (1 == pD11.use_count()); CHECK (1 == pD12.use_count()); CHECK (1 == pD21.use_count()); CHECK (1 == pD22.use_count()); CHECK (!isSameObject (*pD11, *pD12)); CHECK (!isSameObject (*pD11, *pD21)); CHECK (!isSameObject (*pD11, *pD22)); CHECK (!isSameObject (*pD12, *pD21)); CHECK (!isSameObject (*pD12, *pD22)); CHECK (!isSameObject (*pD21, *pD22)); PD22 pD2x = pD21; CHECK (pD2x); CHECK (2 == pD21.use_count()); CHECK (2 == pD2x.use_count()); CHECK (isSameObject (*pD21, *pD2x)); CHECK (2 == allocator.numSlots<DummyObj<1> >()); CHECK (2 == allocator.numSlots<DummyObj<22>>()); CHECK (0 == allocator.numSlots<long>()); // query just some unrelated type... } CHECK (0 == allocator.numSlots<DummyObj<1> >()); CHECK (0 == allocator.numSlots<DummyObj<22>>()); CHECK (0 == checksum_); }
void pass_additional_arguments() { using TestFactory = factory::MultiFact<Interface*(string), theID>; TestFactory theFact; // set up the "production lines" theFact.defineProduction (ONE, [](string ) { return new Implementation<ONE>; }); theFact.defineProduction (TWO, [](string ) { return new Implementation<TWO>("X"); }); theFact.defineProduction (THR, [](string id) { return new Implementation<THR>(id); }); theFact.defineProduction (FOU, [](string id) { return new Implementation<FOU>("Z"+id);}); Interface *p1 = theFact(ONE, "irrelevant"), *p2 = theFact(TWO, "ignored"), *p3 = theFact(THR, "idiocy"), *p4 = theFact(FOU, "omg"), *p5 = theFact(FOU, "z"); // does not compile... // theFact(ONE); // theFact(ONE, "foo", bar); CHECK ("Impl-1" == string(*p1)); CHECK ("X2" == string(*p2)); CHECK ("idiocy3"== string(*p3)); CHECK ("Zomg4" == string(*p4)); CHECK ("Zz4" == string(*p5)); CHECK (!isSameObject(*p4, *p5)); CHECK (INSTANCEOF(Implementation<ONE>, p1)); CHECK (INSTANCEOF(Implementation<TWO>, p2)); CHECK (INSTANCEOF(Implementation<THR>, p3)); CHECK (INSTANCEOF(Implementation<FOU>, p4)); CHECK (INSTANCEOF(Implementation<FOU>, p5)); delete p1; delete p2; delete p3; delete p4; delete p5; }
/** @test cover the basic situations of object handling, * especially copy operations and re-assignments */ void checkHandling (TestList& objs) { Opaque oo; CHECK (!oo); CHECK (isnil(oo)); oo = objs[1]; CHECK (oo); CHECK (!isnil(oo)); typedef DD<3> D3; typedef DD<5> D5; D3 d3 (oo.get<D3>() ); CHECK (3 == oo->getIt()); // re-access through Base interface CHECK (!isSameObject (d3, *oo)); VERIFY_ERROR (WRONG_TYPE, oo.get<D5>() ); // direct assignment of target into Buffer oo = D5(); CHECK (oo); CHECK (5 == oo->getIt()); VERIFY_ERROR (WRONG_TYPE, oo.get<D3>() ); // can get a direct reference to contained object D5 &rd5 (oo.get<D5>()); CHECK (isSameObject (rd5, *oo)); CHECK (!isnil(oo)); oo = objs[3]; // copy construction also works on non-empty object CHECK (7 == oo->getIt()); // WARNING: direct ref has been messed up through the backdoor! CHECK (7 == rd5.getIt()); CHECK (isSameObject (rd5, *oo)); uint cnt_before = _create_count; oo.clear(); CHECK (!oo); oo = D5(); // direct assignment also works on empty object CHECK (oo); CHECK (5 == oo->getIt()); CHECK (_create_count == 2 + cnt_before); // one within buff and one for the anonymous temporary D5() // verify that self-assignment is properly detected... cnt_before = _create_count; oo = oo; CHECK (oo); CHECK (_create_count == cnt_before); oo = oo.get<D5>(); CHECK (_create_count == cnt_before); oo = *oo; CHECK (_create_count == cnt_before); CHECK (oo); oo.clear(); CHECK (!oo); CHECK (isnil(oo)); VERIFY_ERROR (BOTTOM_VALUE, oo.get<D5>() ); #if false ///////////////////////////////////////////////////////////////////////////////////////////////TICKET #537 : restore throwing ASSERT VERIFY_ERROR (ASSERTION, oo->getIt() ); #endif ///////////////////////////////////////////////////////////////////////////////////////////////TICKET #537 : restore throwing ASSERT // can't access empty holder... Opaque o1 (oo); CHECK (!o1); Opaque o2 (d3); CHECK (!isSameObject (d3, *o2)); CHECK (3 == o2->getIt()); CHECK (sizeof(Opaque) <= sizeof(Base) + sizeof(void*) + _ALIGN_); }