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));
99 RawAddr location{
nullptr};
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 =
"please look elsewhere";
156 auto lambda = [payload]{
return RawAddr(&payload); };
158 RawAddr location = lambda();
159 CHECK (location == &lambda);
161 std::function funWrap{lambda};
163 CHECK (not isSameObject (funWrap, lambda));
165 location = funWrap();
166 CHECK (util::isCloseBy (location, funWrap));
173 CHECK (util::isCloseBy (funWrap, lambda));
189 int unrelated{
rani()};
196 virtual RawAddr peek()
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)
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>
322 buildInit (FUN&& fun2install)
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);
350 installInitialiser(fun, buildInit([](
int){
return 0; }));
353 template<
typename FUN,
typename =disable_if_self<LazyDemo, FUN>>
358 installInitialiser(fun, buildInit (forward<FUN> (someFun)));
361 template<
typename FUN>
363 attach (FUN&& someFun)
365 installInitialiser(fun, buildInit (forward<FUN> (someFun)));
389 CHECK (not dd.isInit());
393 CHECK (0 == dd.fun(22));
404 CHECK (not dd.isInit());
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; });
435 CHECK (not dd.isInit());
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; });
466 CHECK (not dd.isInit() and dd.seed == 3);
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));
void verify_TargetRelocation()
elaborate setup used for integration test
»Trojan Function« builder.
void verify_trojanLambda()
Mix-in for lazy/delayed initialisation of an embedded functor.
static auto generateTrap(DEL *delegate)
Invocation: build a Lambda to activate the »Trap« and then to forward the invocation to the actual fu...
int rani(uint bound=_iBOUND())
#define VERIFY_ERROR(ERROR_ID, ERRONEOUS_STATEMENT)
Macro to verify that a statement indeed raises an exception.
constexpr auto isFunMember(FUN)
Helper to pick up a member field for verification.
Implementation namespace for support and library code.
Building block to allow delayed initialisation of infrastructure tied to a functor.
void verify_complexUsageWithCopy()
Simplistic test class runner.
Tiny helper functions and shortcuts to be used everywhere Consider this header to be effectively incl...
void verify_inlineStorage()
A collection of frequently used helper functions to support unit testing.
const ptrdiff_t FUNCTOR_PAYLOAD_OFFSET
void verify_lazyInitialisation()
void verify_triggerMechanism()
bool isSameObject(A const &a, B const &b)
compare plain object identity, based directly on the referee's memory identities. ...