36 using err::LUMIERA_ERROR_LIFECYCLE;
37 using std::make_unique;
82 auto fun = [&](
uint challenge){
return beacon+challenge; };
84 using Sig = size_t(
uint);
85 CHECK (isFunMember<Sig> (&fun));
90 CHECK (beacon+c == fun(c));
93 using FunType =
decltype(fun);
94 FunType& funRef = fun;
95 CHECK (beacon+c == funRef(c));
100 auto delegate = [&](
RawAddr adr) -> FunType&
105 using Delegate =
decltype(delegate);
106 auto delP = make_unique<Delegate> (delegate);
110 CHECK (beacon+c == (*delP)(
this)(c));
111 CHECK (location ==
this);
115 CHECK (
sizeof(trojanLambda) ==
sizeof(
size_t));
121 CHECK (beacon+c == trojanLambda(c));
122 CHECK (location == &trojanLambda);
125 auto trojanClone = trojanLambda;
128 CHECK (beacon+c == trojanClone(c));
129 CHECK (location == &trojanClone);
130 CHECK (beacon+c == trojanLambda(c));
131 CHECK (location == &trojanLambda);
155 const char* payload =
"I am innocent as a lamb";
156 auto lambda = [payload]{
return RawAddr(&payload); };
159 CHECK (location == &lambda);
161 std::function funWrap{lambda};
163 CHECK (not isSameObject (funWrap, lambda));
165 location = funWrap();
189 int unrelated{
rani()};
198 return &nested.anchor;
203 const ptrdiff_t offNested = []{
205 return captureRawAddrOffset(&probe, &probe.anchor);
209 const ptrdiff_t offBase = captureRawAddrOffset(&here, &here.nested);
212 CHECK (offNested > 0);
215 auto farAway = make_unique<Demo> (here);
218 RawAddr startPoint = farAway->peek();
219 Nested* farNested = relocate<Nested>(startPoint, -offNested);
220 CHECK (here.nested.unrelated == farNested->unrelated);
222 Demo* farSelf = relocate<Demo> (farNested, -offBase);
223 CHECK (here.nested.anchor == farSelf->nested.anchor);
224 CHECK (isSameObject (*farSelf, *farAway));
234 using Fun = std::function<float(
int)>;
239 auto delegate = [&report](
RawAddr insideFun) -> Fun&
241 auto realFun = [&report](
int num)
246 Fun& target = *relocate<Fun>(insideFun, -FUNCTOR_PAYLOAD_OFFSET);
253 theFun =
TrojanFun<float(
int)>::generateTrap (&delegate);
258 int feed{1 +
rani (100)};
259 float res = theFun (feed);
262 CHECK (feed == report + 42);
263 CHECK (res = feed -42 +23.55f);
272 CHECK (feed == report);
273 CHECK (res = feed + 23.55f);
283 using Fun = std::function<float(
int)>;
288 Lazy funny{funny, [&](Lazy* self)
290 Fun& thisFun =
static_cast<Fun&
> (*self);
292 thisFun = [&invoked](
int num)
303 int feed = 1 +
rani(99);
304 CHECK (feed*0.555f == funny(feed));
305 CHECK (1 == invoked);
315 using Fun = std::function<int(
int)>;
320 template<
typename FUN>
324 return [theFun = forward<FUN> (fun2install)]
330 self->fun = [self, prevFun=self->fun, nextFun=theFun]
333 return nextFun (prevFun (i));
337 self->fun = [self, newFun=theFun]
340 return newFun (i + self->seed);
353 template<
typename FUN,
typename =disable_if_self<LazyDemo, FUN>>
361 template<
typename FUN>
393 CHECK (0 == dd.
fun(22));
405 CHECK (dd.
seed == 0);
408 CHECK (23 == dd.
fun(22));
411 CHECK (26 == dd.
fun(22));
421 CHECK (dd.
seed == 3);
422 CHECK (12 == dd.
fun(21));
423 CHECK (13 == dd.
fun(22));
424 CHECK (13 == dd.
fun(23));
426 CHECK (14 == dd.
fun(23));
427 CHECK (14 == dd.
fun(24));
428 CHECK (15 == dd.
fun(25));
432 dd =
LazyDemo{[](
int i){
return i+1; }}
433 .
attach([](
int i){
return i/2; });
436 CHECK (dd.
seed == 3);
439 CHECK (12 == dd.
fun(21));
440 CHECK (13 == dd.
fun(22));
441 CHECK (13 == dd.
fun(23));
443 CHECK (14 == dd.
fun(23));
444 CHECK (14 == dd.
fun(24));
445 CHECK (15 == dd.
fun(25));
448 dd =
LazyDemo{[](
int i){
return i+1; }};
452 d2.attach ([](
int i){
return i/2; });
454 d2.
attach ([](
int i){
return i-1; });
467 CHECK (not d1.isInit() and d1.seed == 5);
468 CHECK (not d2.isInit() and d2.seed == 3);
469 CHECK (not d3.isInit() and d3.seed == 0);
471 CHECK (12 == dd.
fun(23));
472 CHECK (13 == d1.fun(23));
473 CHECK (13 == d2.fun(23));
474 CHECK (24 == d3.fun(23));
Mix-in for lazy/delayed initialisation of an embedded functor.
void installInitialiser(std::function< SIG > &targetFunctor, INI &&initialiser)
»Trojan Function« builder.
static auto generateTrap(DEL *delegate)
Invocation: build a Lambda to activate the »Trap« and then to forward the invocation to the actual fu...
void verify_triggerMechanism()
void verify_complexUsageWithCopy()
void verify_inlineStorage()
void verify_lazyInitialisation()
void verify_trojanLambda()
void verify_TargetRelocation()
Building block to allow delayed initialisation of infrastructure tied to a functor.
Implementation namespace for support and library code.
int rani(uint bound=_iBOUND())
Test runner and basic definitions for tests.
bool isCloseBy(A &&a, B &&b, size_t consideredNearby=50)
determine heuristically if two objects are located „close to each other“ in memory.
bool isSameObject(A const &a, B const &b)
compare plain object identity, based directly on the referee's memory identities.
Simplistic test class runner.
#define LAUNCHER(_TEST_CLASS_, _GROUPS_)
elaborate setup used for integration test
auto buildInit(FUN &&fun2install)
LazyDemo && attach(FUN &&someFun)
std::function< int(int)> Fun
A collection of frequently used helper functions to support unit testing.
#define VERIFY_ERROR(ERROR_ID, ERRONEOUS_STATEMENT)
Macro to verify that a statement indeed raises an exception.
Tiny helper functions and shortcuts to be used everywhere Consider this header to be effectively incl...