Lumiera 0.pre.04~rc.1
»edit your freedom«
Loading...
Searching...
No Matches
abstract-tangible-test.cpp
Go to the documentation of this file.
1/*
2 AbstractTangible(Test) - cover the operations of any tangible UI element
3
4 Copyright (C)
5 2015, Hermann Vosseler <Ichthyostega@web.de>
6
7  **Lumiera** is free software; you can redistribute it and/or modify it
8  under the terms of the GNU General Public License as published by the
9  Free Software Foundation; either version 2 of the License, or (at your
10  option) any later version. See the file COPYING for further details.
11
12* *****************************************************************/
13
14
38#include "lib/test/run.hpp"
41#include "test/mock-elm.hpp"
42#include "test/test-nexus.hpp"
43#include "lib/idi/genfunc.hpp"
44#include "lib/idi/entry-id.hpp"
49#include "lib/format-cout.hpp"
50#include "lib/symbol.hpp"
51#include "lib/error.hpp"
52#include "lib/util.hpp"
53
54#include <sigc++/signal.h>
55
56
57using lib::Symbol;
58using util::isnil;
59using util::toString;
60using lib::time::Time;
64using lib::diff::Rec;
71
72
73
74namespace stage {
75namespace model {
76namespace test {
77
78 using LERR_(WRONG_TYPE);
79 using ID = lib::idi::BareEntryID const&;
80
81 namespace { // test fixture...
82
83 /* === dummy operation to be invoked through the command system === */
84
85 int dummyState = 0;
86
87 void
88 operate (int val)
89 {
90 dummyState = val;
91 }
92
93 int
94 capture (int)
95 {
96 return dummyState;
97 }
98
99 void
100 undoIt (int, int oldState)
101 {
102 dummyState = oldState;
103 }
104
105
106
107 const Symbol DUMMY_CMD_ID{"test.AbstractTangibleTest_dummy_command"};
108
109
116 void
118 {
119 REQUIRE (string{DUMMY_CMD_ID} == commandMsg.idi.getSym());
120
122 auto arg = commandMsg.data.get<Rec>().scope()->data.get<int>();
123 cmd.bind (arg);
124 cmd();
125 }
126
127
128 }//(End) test fixture
129
130
131
132
133
134
135 /***********************************************************************/
164 class AbstractTangible_test : public Test
165 {
166
167 virtual void
168 run (Arg)
169 {
170 seedRand();
171
174 markState();
175 revealer();
176 notify();
177 mutate();
178 }
179
180
203 void
205 {
207 MockElm mock("dummy");
208
209 CHECK (mock.verify("ctor"));
210 CHECK (mock.verifyEvent("create","dummy"));
211 CHECK (mock.verify("ctor").arg("dummy","TestNexus").on(&mock));
212
213 CHECK ("dummy" == mock.getID().getSym());
214 CHECK (EntryID<MockElm>("dummy") == mock.getID());
215
216 CHECK (!mock.verifyCall("reset"));
217
218 // start manipulating state....
219 mock.slotExpand();
220 CHECK (mock.isExpanded());
221
222 mock.reset();
223 CHECK (mock.verify("reset"));
224 CHECK (mock.verifyCall("reset"));
225 CHECK (mock.verifyCall("reset").on(&mock));
226 CHECK (mock.verifyCall("reset").on("dummy"));
227 CHECK (mock.verifyEvent("reset"));
228 CHECK (mock.verify("reset").after("ctor"));
229 CHECK (mock.verify("ctor").before("reset"));
230 CHECK (mock.ensureNot("reset").before("ctor"));
231 CHECK (mock.ensureNot("ctor").after("reset"));
232
233 CHECK (mock.verify("reset").beforeEvent("reset"));
234 CHECK (mock.verifyCall("reset").beforeEvent("reset"));
235 CHECK (!mock.verifyCall("reset").afterEvent("reset"));
236
237 CHECK (!mock.isTouched());
238 CHECK (!mock.isExpanded());
239
240 mock.markMsg("qui dolorem ipsum quia dolor sit amet consectetur adipisci velit.");
241 CHECK (mock.verifyMark("Message", "dolor"));
242 CHECK (mock.verifyCall("doMsg"));
243 CHECK (mock.verifyCall("doMsg").arg("lorem ipsum"));
244 CHECK (mock.verifyCall("doMsg").argMatch("dolor.+dolor\\s+"));
245 CHECK (mock.verifyMatch("Rec\\(mark.+ID = Message.+\\{.+lorem ipsum"));
246
247 EventLog log = mock.getLog();
248 log.verify("ctor")
249 .before("reset")
250 .before("lorem ipsum");
251
252 // create further mock elements...
253 MockElm foo("foo"), bar("bar");
254 foo.verify("ctor").arg("foo");
255 bar.verify("ctor").arg("bar");
256
257 bar.ensureNot("foo");
258 log.ensureNot("foo");
259 mock.ensureNot("foo");
260 CHECK (!foo.ensureNot("foo"));
261
262 // now join the logs together,
263 // allowing to watch the combined events
264 bar.joinLog(mock);
265 foo.joinLog(mock);
266 CHECK (log.verifyEvent("logJoin","bar")
267 .beforeEvent("logJoin","foo"));
268
269 CHECK (mock.verifyEvent("logJoin","bar")
270 .beforeEvent("logJoin","foo"));
271 CHECK (mock.verifyEvent("create","foo"));
272 CHECK (log.verifyEvent("create","foo"));
273 CHECK (log.verifyEvent("create","dummy")
274 .beforeEvent("create","bar")
275 .beforeEvent("create","foo"));
276
277
278 mock.kill();
279 foo.markMsg("dummy killed");
280 CHECK (log.verifyEvent("destroy","dummy")
281 .beforeCall("doMsg").on("foo"));
282
283 // Access the log on the Test-Nexus hub
285 CHECK (nexusLog.verifyEvent("destroy","dummy")
286 .beforeEvent("dummy successfully zombificated"));
287
288 mock.slotExpand(); // attempt to operate the zombie
289 CHECK (nexusLog.verifyEvent("dummy successfully zombificated")
290 .beforeCall("note").on("ZombieNexus").arg("defunct-dummy", "expand")
291 .beforeEvent("error","sent note message to ZombieNexus"));
292
293
294 cout << "____Event-Log_________________\n"
295 << util::join(mock.getLog(), "\n")
296 << "\n───╼━━━━━━━━━╾────────────────"<<endl;
297
298 cout << "____Nexus-Log_________________\n"
300 << "\n───╼━━━━━━━━━╾────────────────"<<endl;
301 }
302
303
304
305 void
307 {
310
311 // Setup test stage: define a command/action "in Steam"
312 CommandDef (DUMMY_CMD_ID)
313 .operation (operate)
314 .captureUndo (capture)
315 .undoOperation (undoIt);
316
317 stage::test::Nexus::setCommandHandler (&processCommandInvocation);
318
319 // the UI element to trigger this command invocation
320 MockElm mock("uiElm");
321
322 int prevState = dummyState;
323 int concreteParam = 1 + rani(100);
324
325 // on bus no traces from this command yet...
326 CHECK (nexusLog.ensureNot(string(DUMMY_CMD_ID)));
327
328
329 // message to bind parameter data and finally trigger the command
330 mock.invoke (DUMMY_CMD_ID, concreteParam);
331 CHECK (dummyState == concreteParam); // command was indeed invoked
332 CHECK (nexusLog.verifyCall("act").arg("«int»|" +toString(concreteParam))
333 .beforeEvent("bind and trigger command \""+DUMMY_CMD_ID));
334
335 // verify proper binding, including UNDO state capture
336 Command::get (DUMMY_CMD_ID).undo();
337 CHECK (dummyState == prevState);
338
339 cout << "____Nexus-Log_________________\n"
340 << util::join(nexusLog, "\n")
341 << "\n───╼━━━━━━━━━╾────────────────"<<endl;
342
343
344 // reset to default (NOP) handler
346 }
347
348
363 void
365 {
368
369 sigc::signal<void> trigger_expand;
370 sigc::signal<void> trigger_collapse;
371
372 MockElm mock("target");
373 ID targetID = mock.getID();
374
375 trigger_expand.connect (sigc::mem_fun(mock, &Tangible::slotExpand));
376 trigger_collapse.connect (sigc::mem_fun(mock, &Tangible::slotCollapse));
377
378 CHECK (not mock.isTouched());
379 CHECK (not mock.isExpanded());
380 CHECK (mock.ensureNot("expanded"));
381 CHECK (nexusLog.ensureNot("state-mark"));
382
383 trigger_expand(); // emit signal
384
385 CHECK (mock.isTouched());
386 CHECK (mock.isExpanded());
387 CHECK (mock.verifyCall("expand").arg(true)
388 .beforeEvent("expanded"));
389
390 // and now the important part: state mark notification was sent over the bus...
391 CHECK (nexusLog.verifyCall("note").arg(targetID, GenNode{"expand", true})
392 .before("handling state-mark"));
393
394
395 trigger_collapse(); // emit other signal
396 CHECK (not mock.isExpanded());
397 CHECK (mock.isTouched());
398
399 CHECK (mock.verifyEvent("create", "target")
400 .beforeEvent("expanded")
401 .beforeEvent("collapsed"));
402 CHECK (nexusLog.verifyCall("note").arg(targetID, GenNode{"expand", true})
403 .before("handling state-mark")
404 .beforeCall("note").arg(targetID, GenNode{"expand", false})
405 .before("handling state-mark"));
406
407 trigger_collapse();
408 CHECK (not mock.isExpanded());
409
410 // but note: redundant state changes do not cause sending of further state marks
411 CHECK (mock.ensureNot("collapsed")
412 .beforeCall("expand")
413 .beforeEvent("collapsed"));
414 CHECK (nexusLog.ensureNot("handling state-mark")
415 .beforeCall("note").arg(targetID, GenNode{"expand", false})
416 .before("handling state-mark")
417 .beforeCall("note").arg(targetID, GenNode{"expand", false}));
418
419
420
421 // Second part: replay of a state mark via UI-Bus....
422 auto stateMark = GenNode{"expand", true};
423 auto& uiBus = stage::test::Nexus::testUI();
424
425 CHECK (not mock.isExpanded());
426 CHECK (mock.ensureNot("mark"));
427
428 uiBus.mark (targetID, stateMark);
429
430 CHECK (nexusLog.verifyCall("mark").arg(targetID, stateMark)
431 .before("delivered mark to "+string(targetID)).arg(stateMark));
432
433 CHECK (mock.verifyMark("expand", "true")
434 .beforeCall("expand").arg(true)
435 .beforeEvent("expanded"));
436 CHECK (mock.isExpanded());
437 CHECK (mock.isTouched());
438
439 // the default handler defined in model::Tangible
440 // already supports some rather generic state changes,
441 // like e.g. a reset to the element's default state.
442 // Note that the actual implementation doReset()
443 // is a virtual function, here implemented in MockElm.
444 uiBus.mark (targetID, GenNode{"reset", true});
445 // note: payload is irrelevant for "reset" mark
446
447 // and we're back to pristine state...
448 CHECK (not mock.isTouched());
449 CHECK (not mock.isExpanded());
450 CHECK (mock.verifyMark("reset", "true")
451 .afterEvent("expanded")
452 .beforeCall("reset")
453 .beforeEvent("reset"));
454
455
456 cout << "____Event-Log_________________\n"
457 << util::join(mock.getLog(), "\n")
458 << "\n───╼━━━━━━━━━╾────────────────"<<endl;
459
460 cout << "____Nexus-Log_________________\n"
461 << util::join(nexusLog, "\n")
462 << "\n───╼━━━━━━━━━╾────────────────"<<endl;
463 }
464
465
470 void
472 {
475
476 MockElm mock("target");
477 ID targetID = mock.getID();
478
479 sigc::signal<void> trigger_reveal;
480 trigger_reveal.connect (sigc::mem_fun(mock, &Tangible::slotReveal));
481
482 CHECK (not mock.isTouched());
483 CHECK (not mock.isExpanded());
484 CHECK (mock.ensureNot("reveal"));
485 CHECK (mock.ensureNot("expanded"));
486 CHECK (nexusLog.ensureNot("state-mark"));
487
488 bool revealed = false;
489 mock.installRevealer([&]()
490 { // NOTE: our mock "implementation" of the »reveal yourself« functionality
491 mock.slotExpand(); // explicitly prompts the element to expand itself,
492 revealed = true; // and then via closure sets a flag we can verify.
493 });
494
495 trigger_reveal();
496
497 CHECK (true == revealed);
498 CHECK (mock.isExpanded());
499 CHECK (mock.verifyEvent("create","target")
500 .beforeCall("reveal")
501 .beforeCall("expand").arg(true)
502 .beforeEvent("expanded"));
503
504 // invoking the slotExpand() also emitted a state mark to persist that expansion state...
505 CHECK (nexusLog.verifyCall("note").arg(targetID, GenNode{"expand", true})
506 .before("handling state-mark"));
507
508
509 // second test: the same can be achieved via UI-Bus message...
510 revealed = false;
511 auto stateMark = GenNode{"reveal", 47}; // (payload argument irrelevant)
512 auto& uiBus = stage::test::Nexus::testUI();
513 CHECK (nexusLog.ensureNot("reveal"));
514
515 uiBus.mark (targetID, stateMark); // send the state mark message to reveal the element
516
517 CHECK (true == revealed);
518 CHECK (mock.verifyMark("reveal", 47)
519 .afterEvent("expanded")
520 .beforeCall("reveal")
521 .beforeCall("expand").arg(true));
522
523 CHECK (nexusLog.verifyCall("mark").arg(targetID, stateMark)
524 .after("handling state-mark")
525 .before("reveal")
526 .beforeEvent("delivered mark"));
527
528 // Note the fine point: the target element /was/ already expanded
529 // and thus there is no second "expanded" event, nor is there a
530 // second state mark emitted into the UI-Bus...
531 CHECK (mock.ensureNot("expanded")
532 .afterCall("reveal")
533 .afterEvent("expanded"));
534 CHECK (nexusLog.ensureNot("note")
535 .afterCall("mark").arg(targetID, stateMark)
536 .after("handling state-mark"));
537
538
539
540 cout << "____Event-Log_________________\n"
541 << util::join(mock.getLog(), "\n")
542 << "\n───╼━━━━━━━━━╾────────────────"<<endl;
543
544 cout << "____Nexus-Log_________________\n"
545 << util::join(nexusLog, "\n")
546 << "\n───╼━━━━━━━━━╾────────────────"<<endl;
547 }
548
549
554 void
556 {
559
560 MockElm mock("target");
561 ID targetID = mock.getID();
562 auto& uiBus = stage::test::Nexus::testUI();
563
564 CHECK (mock.ensureNot("Flash"));
565 CHECK (mock.ensureNot("Error"));
566 CHECK (mock.ensureNot("Message"));
567 CHECK (isnil(mock.getMessage()));
568 CHECK (isnil(mock.getError()));
569 CHECK (not mock.isError());
570
571 // now send a "Flash" mark via UI-Bus....
572 uiBus.mark (targetID, GenNode{"Flash", true });
573 CHECK (mock.verifyMark("Flash"));
574
575 CHECK (mock.ensureNot("Error"));
576 CHECK (mock.ensureNot("Message"));
577 CHECK (isnil(mock.getMessage()));
578 CHECK (isnil(mock.getError()));
579
580 uiBus.mark (targetID, GenNode{"Error", "getting serious"});
581 CHECK (mock.verifyMark("Error", "serious"));
582 CHECK (mock.isError());
583 CHECK ("getting serious" == mock.getError());
584 CHECK (isnil(mock.getMessage()));
585
586 uiBus.mark (targetID, GenNode{"Message", "by mistake"});
587 CHECK (mock.verifyMark("Message", "mistake"));
588 CHECK ("by mistake" == mock.getMessage());
589 CHECK ("getting serious" == mock.getError());
590
591 CHECK (mock.verify("target")
592 .before("Flash")
593 .before("serious")
594 .before("mistake"));
595
596 // type mismatch: when receiving a "Message" mark, we expect a string payload
597 VERIFY_ERROR(WRONG_TYPE, uiBus.mark(targetID, GenNode{"Message", Time::NEVER }))
598
599 // the type error happens while resolving the payload,
600 // and thus the actual "doMsg()" function on the target was not invoked
601 CHECK (mock.ensureNot(string(Time::NEVER)));
602 CHECK (nexusLog.verifyCall("mark").arg(targetID, Time::NEVER));
603 CHECK (nexusLog.ensureNot("delivered mark").arg(Time::NEVER));
604 CHECK ("getting serious" == mock.getError());
605
606 mock.reset();
607 CHECK (isnil(mock.getMessage()));
608 CHECK (isnil(mock.getError()));
609 CHECK (not mock.isError());
610
611
612 cout << "____Event-Log_________________\n"
613 << util::join(mock.getLog(), "\n")
614 << "\n───╼━━━━━━━━━╾────────────────"<<endl;
615
616 cout << "____Nexus-Log_________________\n"
617 << util::join(nexusLog, "\n")
618 << "\n───╼━━━━━━━━━╾────────────────"<<endl;
619 }
620
621
622
652 void
654 {
657
658 MockElm rootMock("root");
659 ID rootID = rootMock.getID();
660
661 rootMock.attrib["α"] = "Centauri";
662 CHECK ("Centauri" == rootMock.attrib["α"]);
663 CHECK (isnil (rootMock.scope));
664
665
666 // simulated source for structural diff
668 {
669 const GenNode
670 ATTRIB_AL = GenNode("α", "quadrant"),
671 ATTRIB_PI = GenNode("π", 3.14159265),
672 CHILD_1 = MakeRec().genNode("a"),
673 CHILD_2 = MakeRec().genNode("b");
674
675 auto
676 generateDiff()
677 {
678 using lib::diff::Ref;
679
680 return MutationMessage{ after(Ref::ATTRIBS) // start after the existing attributes (of root)
681 , ins(CHILD_1) // insert first child (with name "a")
682 , ins(CHILD_2) // insert second child (with name "b")
683 , set(ATTRIB_AL) // assign a new value to attribute "α" <- "quadrant"
684 , mut(CHILD_2) // open nested scope of child "b" for recursive mutation
685 , ins(ATTRIB_PI) // ..within nested scope, add a new attribute "π" := 3.14159265
686 , emu(CHILD_2) // leave nested scope
687 };
688 }
689 }
690 diffSrc;
691
692
693 auto& uiBus = stage::test::Nexus::testUI();
694
695
696 // send a Diff message via UI-Bus to the rootMock
697 uiBus.change(rootID, diffSrc.generateDiff());
698
699
700 // Verify the rootMock has been properly altered....
701 MockElm& childA = *rootMock.scope[0];
702 MockElm& childB = *rootMock.scope[1];
703
704 CHECK (2 == rootMock.scope.size()); // we've got two children now
705 CHECK (rootMock.attrib["α"] == "quadrant"); // alpha attribute has been reassigned
706 CHECK (childA.getID() == diffSrc.CHILD_1.idi); // children have the expected IDs
707 CHECK (childB.getID() == diffSrc.CHILD_2.idi);
708 CHECK (childB.attrib["π"] == "3.1415927"); // and the second child got attribute Pi
709
710
711 CHECK (rootMock.verifyEvent("create","root")
712 .beforeCall("buildMutator").on(&rootMock)
713 .beforeEvent("diff","root accepts mutation...") // start of diff mutation
714 .beforeEvent("diff","create child \"a\"") // insert first child
715 .beforeEvent("create", "a")
716 .beforeEvent("diff","create child \"b\"") // insert second child
717 .beforeEvent("create", "b")
718 .beforeEvent("diff","set Attrib α <-quadrant") // assign value to existing attribute α
719 .beforeCall("buildMutator").on(&childB) // establish nested mutator for second child
720 .beforeEvent("diff","b accepts mutation...")
721 .beforeEvent("diff",">>Scope>> b") // recursively mutate second child
722 .beforeEvent("diff","++Attrib++ π = 3.1415927")); // insert new attribute π within nested scope
723
724
725 CHECK (nexusLog.verifyCall("routeAdd").arg(rootMock.getID(), memLocation(rootMock)) // rootMock was attached to Nexus
726 .beforeCall("change") .argMatch(rootMock.getID(),
727 "after.+ins.+ins.+set.+mut.+ins.+emu") // diff message sent via UI-Bus
728 .beforeCall("routeAdd").arg(childA.getID(), memLocation(childA)) // first new child was attached to Nexus
729 .beforeCall("routeAdd").arg(childB.getID(), memLocation(childB)) // second new child was attached to Nexus
730 .beforeEvent("applied diff to "+string(rootMock.getID()))
731 );
732
733 cout << "____Event-Log_________________\n"
734 << util::join(rootMock.getLog(), "\n")
735 << "\n───╼━━━━━━━━━╾────────────────"<<endl;
736
737 cout << "____Nexus-Log_________________\n"
738 << util::join(nexusLog, "\n")
739 << "\n───╼━━━━━━━━━╾────────────────"<<endl;
740 }
741
742
743
744 static string
746 {
747 return lib::idi::instanceTypeID (&uiElm);
748 }
749 };
750
751
754
755
756}}}// namespace stage::model::test
Token or Atom with distinct identity.
Definition symbol.hpp:120
object-like record of data.
Definition record.hpp:142
type erased baseclass for building a combined hash and symbolic ID.
Definition entry-id.hpp:134
string const & getSym() const
Definition entry-id.hpp:169
Helper to log and verify the occurrence of events.
EventMatch verify(string match) const
start a query to match for some substring.
EventMatch verifyEvent(string match) const
start a query to match for some event.
EventMatch ensureNot(string match) const
start a query to ensure the given expression does not match.
EventMatch & afterCall(string match)
find a function invocation backwards, before the current point of reference
EventMatch & arg(ARGS const &...args)
refine filter to additionally require specific arguments
EventMatch & before(string match)
find a match (substring match) of the given text in an EventLog entry after the current position
EventMatch & beforeEvent(string match)
find a match for an "event" after the current point of reference
EventMatch & afterEvent(string match)
EventMatch & on(string targetID)
refine filter to additionally match the ‘'this’` attribute
EventMatch & beforeCall(string match)
find a match for some function invocation after the current point of reference
Lumiera's internal time value datatype.
static const Time NEVER
border condition marker value. NEVER >= any time value
Interface common to all UI elements of relevance for the Lumiera application.
Definition tangible.hpp:160
void slotReveal()
Cause the element to be brought into sight.
Definition tangible.cpp:213
void invoke(Symbol cmdID, ARGS &&...)
void slotCollapse()
Collapse or minimise this element and remember the collapsed state.
Definition tangible.cpp:173
void installRevealer(Revealer::RevealeItFun)
Configure the (optional) functionality to bring the UI-Element into sight.
Definition tangible.hpp:288
void reset()
invoke the generic reset hook
Definition tangible.cpp:65
void slotExpand()
Expand this element and remember the expanded state.
Definition tangible.cpp:161
Mock UI element or controller.
Definition mock-elm.hpp:101
bool isError() const
Definition mock-elm.hpp:378
string getMessage() const
Definition mock-elm.hpp:384
string getError() const
Definition mock-elm.hpp:390
EventMatch verifyMark(string id) const
special verification match on a "state mark" message to this element
Definition mock-elm.hpp:435
EventLog const & getLog() const
Definition mock-elm.hpp:459
EventMatch verify(string match) const
Definition mock-elm.hpp:398
bool isExpanded() const
Definition mock-elm.hpp:372
std::map< string, string > attrib
Definition mock-elm.hpp:354
std::vector< PMockElm > scope
Definition mock-elm.hpp:355
EventMatch verifyCall(string match) const
Definition mock-elm.hpp:422
EventMatch verifyEvent(string match) const
Definition mock-elm.hpp:410
bool isTouched() const
Definition mock-elm.hpp:366
EventMatch ensureNot(string match) const
Definition mock-elm.hpp:428
EventLog & joinLog(MockElm &otherMock)
Definition mock-elm.hpp:465
static ctrl::BusTerm & testUI()
get a connection point to a UI backbone faked for test
static void setCommandHandler(CommandHandler=CommandHandler())
install a closure (custom handler function) to deal with any command invocations encountered in the t...
static lib::test::EventLog const & getLog()
static lib::test::EventLog const & startNewLog()
Helper class used solely for defining a Command-Object.
auto operation(FUN operation_to_define)
Handle object representing a single Command instance to be used by client code.
Definition command.hpp:120
static Command get(Symbol cmdID)
Access existing command for use.
Definition command.cpp:120
Actually defining a command and binding it to execution parameters.
Bare symbolic and hash ID used for accounting of asset like entries.
Lumiera error handling (C++ interface).
#define LERR_(_NAME_)
Definition error.hpp:45
Support for verifying the occurrence of events from unit tests.
Automatically use custom string conversion in C++ stream output.
Generic functions to build identification schemes.
A generic interface element instrumented for unit testing.
Generic Message with an embedded diff, to describe changes to model elements.
string instanceTypeID(const TY *const obj)
designation of an distinct object instance
Definition genfunc.hpp:116
void processCommandInvocation(GenNode const &commandMsg)
dummy Command handler, which can be hooked up to the TestNexus and causes a real command invocation o...
lib::idi::BareEntryID const & ID
Lumiera GTK UI implementation root.
Definition guifacade.cpp:37
Test runner and basic definitions for tests.
std::string toString(TY const &val) noexcept
get some string representation of any object, reliably.
string join(COLL &&coll, string const &delim=", ")
enumerate a collection's contents, separated by delimiter.
bool isnil(lib::time::Duration const &dur)
Simplistic test class runner.
#define LAUNCHER(_TEST_CLASS_, _GROUPS_)
Definition run.hpp:116
generic data element node within a tree
Definition gen-node.hpp:224
Opaque message to effect a structural change on a target, which is likewise only known in an abstract...
Constructor for a specially crafted 'ref GenNode'.
Definition gen-node.hpp:843
static const Ref ATTRIBS
symbolic ID ref "_ATTRIBS_"
Definition gen-node.hpp:866
typed symbolic and hash ID for asset-like position accounting.
Definition entry-id.hpp:219
Marker types to indicate a literal string and a Symbol.
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.
#define MARK_TEST_FUN
Macro to mark the current test function in STDOUT.
A fake UI backbone for investigations and unit testing.
a family of time value like entities and their relationships.
A token language to represent structural changes in a tree like hierarchical data structure.
Tiny helper functions and shortcuts to be used everywhere Consider this header to be effectively incl...