Lumiera  0.pre.03
»edityourfreedom«
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
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) Lumiera.org
5  2015, Hermann Vosseler <Ichthyostega@web.de>
6 
7  This program is free software; you can redistribute it and/or
8  modify it under the terms of the GNU General Public License as
9  published by the Free Software Foundation; either version 2 of
10  the License, or (at your option) any later version.
11 
12  This program is distributed in the hope that it will be useful,
13  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  GNU General Public License for more details.
16 
17  You should have received a copy of the GNU General Public License
18  along with this program; if not, write to the Free Software
19  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 
21 * *****************************************************/
22 
23 
47 #include "lib/test/run.hpp"
48 #include "lib/test/test-helper.hpp"
49 #include "lib/test/event-log.hpp"
50 #include "test/mock-elm.hpp"
51 #include "test/test-nexus.hpp"
52 #include "lib/idi/genfunc.hpp"
53 #include "lib/idi/entry-id.hpp"
56 #include "lib/diff/tree-diff.hpp"
57 #include "lib/time/timevalue.hpp"
58 #include "lib/format-cout.hpp"
59 #include "lib/symbol.hpp"
60 #include "lib/error.hpp"
61 #include "lib/util.hpp"
62 
63 #include <sigc++/signal.h>
64 
65 
66 using lib::Symbol;
67 using util::isnil;
68 using util::toString;
69 using lib::time::Time;
70 using gui::test::MockElm;
72 using lib::idi::EntryID;
73 using lib::diff::Rec;
74 using lib::diff::MakeRec;
75 using lib::diff::GenNode;
76 using lib::diff::DataCap;
80 
81 
82 
83 namespace gui {
84 namespace model{
85 namespace test {
86 
87  using lumiera::error::LERR_(WRONG_TYPE);
88  using ID = lib::idi::BareEntryID const&;
89 
90  namespace { // test fixture...
91 
92  /* === dummy operation to be invoked through the command system === */
93 
94  int dummyState = 0;
95 
96  void
97  operate (int val)
98  {
99  dummyState = val;
100  }
101 
102  int
103  capture (int)
104  {
105  return dummyState;
106  }
107 
108  void
109  undoIt (int, int oldState)
110  {
111  dummyState = oldState;
112  }
113 
114 
115 
116  const Symbol DUMMY_CMD_ID{"test.AbstractTangibleTest_dummy_command"};
117 
118 
125  void
126  processCommandInvocation (GenNode const& commandMsg)
127  {
128  REQUIRE (string{DUMMY_CMD_ID} == commandMsg.idi.getSym());
129 
130  auto cmd = Command::get (DUMMY_CMD_ID);
131  auto arg = commandMsg.data.get<Rec>().scope()->data.get<int>();
132  cmd.bind (arg);
133  cmd();
134  }
135 
136 
137  }//(End) test fixture
138 
139 
140 
141 
142 
143 
144  /***********************************************************************/
173  class AbstractTangible_test : public Test
174  {
175 
176  virtual void
178  {
180  invokeCommand();
181  markState();
182  notify();
183  mutate();
184  }
185 
186 
209  void
211  {
213  MockElm mock("dummy");
214 
215  CHECK (mock.verify("ctor"));
216  CHECK (mock.verifyEvent("create","dummy"));
217  CHECK (mock.verify("ctor").arg("dummy","TestNexus").on(&mock));
218 
219  CHECK ("dummy" == mock.getID().getSym());
220  CHECK (EntryID<MockElm>("dummy") == mock.getID());
221 
222  CHECK (!mock.verifyCall("reset"));
223 
224  // start manipulating state....
225  mock.slotExpand();
226  CHECK (mock.isExpanded());
227 
228  mock.reset();
229  CHECK (mock.verify("reset"));
230  CHECK (mock.verifyCall("reset"));
231  CHECK (mock.verifyCall("reset").on(&mock));
232  CHECK (mock.verifyCall("reset").on("dummy"));
233  CHECK (mock.verifyEvent("reset"));
234  CHECK (mock.verify("reset").after("ctor"));
235  CHECK (mock.verify("ctor").before("reset"));
236  CHECK (mock.ensureNot("reset").before("ctor"));
237  CHECK (mock.ensureNot("ctor").after("reset"));
238 
239  CHECK (mock.verify("reset").beforeEvent("reset"));
240  CHECK (mock.verifyCall("reset").beforeEvent("reset"));
241  CHECK (!mock.verifyCall("reset").afterEvent("reset"));
242 
243  CHECK (!mock.isTouched());
244  CHECK (!mock.isExpanded());
245 
246  mock.markMsg("qui dolorem ipsum quia dolor sit amet consectetur adipisci velit.");
247  CHECK (mock.verifyMark("Message", "dolor"));
248  CHECK (mock.verifyCall("doMsg"));
249  CHECK (mock.verifyCall("doMsg").arg("lorem ipsum"));
250  CHECK (mock.verifyCall("doMsg").argMatch("dolor.+dolor\\s+"));
251  CHECK (mock.verifyMatch("Rec\\(mark.+ID = Message.+\\{.+lorem ipsum"));
252 
253  EventLog log = mock.getLog();
254  log.verify("ctor")
255  .before("reset")
256  .before("lorem ipsum");
257 
258  // create further mock elements...
259  MockElm foo("foo"), bar("bar");
260  foo.verify("ctor").arg("foo");
261  bar.verify("ctor").arg("bar");
262 
263  bar.ensureNot("foo");
264  log.ensureNot("foo");
265  mock.ensureNot("foo");
266  CHECK (!foo.ensureNot("foo"));
267 
268  // now join the logs together,
269  // allowing to watch the combined events
270  bar.joinLog(mock);
271  foo.joinLog(mock);
272  CHECK (log.verifyEvent("logJoin","bar")
273  .beforeEvent("logJoin","foo"));
274 
275  CHECK (mock.verifyEvent("logJoin","bar")
276  .beforeEvent("logJoin","foo"));
277  CHECK (mock.verifyEvent("create","foo"));
278  CHECK (log.verifyEvent("create","foo"));
279  CHECK (log.verifyEvent("create","dummy")
280  .beforeEvent("create","bar")
281  .beforeEvent("create","foo"));
282 
283 
284  mock.kill();
285  foo.markMsg("dummy killed");
286  CHECK (log.verifyEvent("destroy","dummy")
287  .beforeCall("doMsg").on("foo"));
288 
289  // Access the log on the Test-Nexus hub
290  EventLog nexusLog = gui::test::Nexus::getLog();
291  CHECK (nexusLog.verifyEvent("destroy","dummy")
292  .beforeEvent("dummy successfully zombificated"));
293 
294  mock.slotExpand(); // attempt to operate the zombie
295  CHECK (nexusLog.verifyEvent("dummy successfully zombificated")
296  .beforeCall("note").on("ZombieNexus").arg("defunct-dummy", "expand")
297  .beforeEvent("error","sent note message to ZombieNexus"));
298 
299 
300  cout << "____Event-Log_________________\n"
301  << util::join(mock.getLog(), "\n")
302  << "\n───╼━━━━━━━━━╾────────────────"<<endl;
303 
304  cout << "____Nexus-Log_________________\n"
306  << "\n───╼━━━━━━━━━╾────────────────"<<endl;
307  }
308 
309 
310 
311  void
313  {
316 
317  // Setup test stage: define a command/action "in Proc"
318  CommandDef (DUMMY_CMD_ID)
319  .operation (operate)
320  .captureUndo (capture)
321  .undoOperation (undoIt);
322 
323  gui::test::Nexus::setCommandHandler (&processCommandInvocation);
324 
325  // the UI element to trigger this command invocation
326  MockElm mock("uiElm");
327 
328  int prevState = dummyState;
329  int concreteParam = 1 +rand() % 100;
330 
331  // on bus no traces from this command yet...
332  CHECK (nexusLog.ensureNot(string(DUMMY_CMD_ID)));
333 
334 
335  // message to bind parameter data and finally trigger the command
336  mock.invoke (DUMMY_CMD_ID, concreteParam);
337  CHECK (dummyState == concreteParam); // command was indeed invoked
338  CHECK (nexusLog.verifyCall("act").arg("«int»|" +toString(concreteParam))
339  .beforeEvent("bind and trigger command \""+DUMMY_CMD_ID));
340 
341  // verify proper binding, including UNDO state capture
342  Command::get (DUMMY_CMD_ID).undo();
343  CHECK (dummyState == prevState);
344 
345  cout << "____Nexus-Log_________________\n"
346  << util::join(nexusLog, "\n")
347  << "\n───╼━━━━━━━━━╾────────────────"<<endl;
348 
349 
350  // reset to default (NOP) handler
352  }
353 
354 
373  void
375  {
378 
379  sigc::signal<void> trigger_expand;
380  sigc::signal<void> trigger_collapse;
381 
382  MockElm mock("target");
383  ID targetID = mock.getID();
384 
385  trigger_expand.connect (sigc::mem_fun(mock, &Tangible::slotExpand));
386  trigger_collapse.connect (sigc::mem_fun(mock, &Tangible::slotCollapse));
387 
388  CHECK (not mock.isTouched());
389  CHECK (not mock.isExpanded());
390  CHECK (mock.ensureNot("expanded"));
391  CHECK (nexusLog.ensureNot("state-mark"));
392 
393  trigger_expand(); // emit signal
394 
395  CHECK (mock.isTouched());
396  CHECK (mock.isExpanded());
397  CHECK (mock.verifyCall("expand").arg(true)
398  .beforeEvent("expanded"));
399 
400  // and now the important part: state mark notification was sent over the bus...
401  CHECK (nexusLog.verifyCall("note").arg(targetID, GenNode{"expand", true})
402  .before("handling state-mark"));
403 
404 
405  trigger_collapse(); // emit other signal
406  CHECK (not mock.isExpanded());
407  CHECK (mock.isTouched());
408 
409  CHECK (mock.verifyEvent("create", "target")
410  .beforeEvent("expanded")
411  .beforeEvent("collapsed"));
412  CHECK (nexusLog.verifyCall("note").arg(targetID, GenNode{"expand", true})
413  .before("handling state-mark")
414  .beforeCall("note").arg(targetID, GenNode{"expand", false})
415  .before("handling state-mark"));
416 
417  trigger_collapse();
418  CHECK (not mock.isExpanded());
419 
420  // but note: redundant state changes do not cause sending of further state marks
421  CHECK (mock.ensureNot("collapsed")
422  .beforeCall("expand")
423  .beforeEvent("collapsed"));
424  CHECK (nexusLog.ensureNot("handling state-mark")
425  .beforeCall("note").arg(targetID, GenNode{"expand", false})
426  .before("handling state-mark")
427  .beforeCall("note").arg(targetID, GenNode{"expand", false}));
428 
429 
430 
431  // Second part: replay of a state mark via UI-Bus....
432  auto stateMark = GenNode{"expand", true};
433  auto& uiBus = gui::test::Nexus::testUI();
434 
435  CHECK (not mock.isExpanded());
436  CHECK (mock.ensureNot("mark"));
437 
438  uiBus.mark (targetID, stateMark);
439 
440  CHECK (nexusLog.verifyCall("mark").arg(targetID, stateMark)
441  .before("delivered mark to "+string(targetID)).arg(stateMark));
442 
443  CHECK (mock.verifyMark("expand", "true")
444  .beforeCall("expand").arg(true)
445  .beforeEvent("expanded"));
446  CHECK (mock.isExpanded());
447  CHECK (mock.isTouched());
448 
449  // the default handler defined in model::Tangible
450  // already supports some rather generic state changes,
451  // like e.g. a reset to the element's default state.
452  // Note that the actual implementation doReset()
453  // is a virtual function, here implemented in MockElm.
454  uiBus.mark (targetID, GenNode{"reset", true});
455  // note: payload is irrelevant for "reset" mark
456 
457  // and we're back to pristine state...
458  CHECK (not mock.isTouched());
459  CHECK (not mock.isExpanded());
460  CHECK (mock.verifyMark("reset", "true")
461  .afterEvent("expanded")
462  .beforeCall("reset")
463  .beforeEvent("reset"));
464 
465 
466  cout << "____Event-Log_________________\n"
467  << util::join(mock.getLog(), "\n")
468  << "\n───╼━━━━━━━━━╾────────────────"<<endl;
469 
470  cout << "____Nexus-Log_________________\n"
471  << util::join(nexusLog, "\n")
472  << "\n───╼━━━━━━━━━╾────────────────"<<endl;
473  }
474 
475 
480  void
482  {
485 
486  MockElm mock("target");
487  ID targetID = mock.getID();
488  auto& uiBus = gui::test::Nexus::testUI();
489 
490  CHECK (mock.ensureNot("Flash"));
491  CHECK (mock.ensureNot("Error"));
492  CHECK (mock.ensureNot("Message"));
493  CHECK (isnil(mock.getMessage()));
494  CHECK (isnil(mock.getError()));
495  CHECK (not mock.isError());
496 
497  // now send a "Flash" mark via UI-Bus....
498  uiBus.mark (targetID, GenNode{"Flash", true });
499  CHECK (mock.verifyMark("Flash"));
500 
501  CHECK (mock.ensureNot("Error"));
502  CHECK (mock.ensureNot("Message"));
503  CHECK (isnil(mock.getMessage()));
504  CHECK (isnil(mock.getError()));
505 
506  uiBus.mark (targetID, GenNode{"Error", "getting serious"});
507  CHECK (mock.verifyMark("Error", "serious"));
508  CHECK (mock.isError());
509  CHECK ("getting serious" == mock.getError());
510  CHECK (isnil(mock.getMessage()));
511 
512  uiBus.mark (targetID, GenNode{"Message", "by mistake"});
513  CHECK (mock.verifyMark("Message", "mistake"));
514  CHECK ("by mistake" == mock.getMessage());
515  CHECK ("getting serious" == mock.getError());
516 
517  CHECK (mock.verify("target")
518  .before("Flash")
519  .before("serious")
520  .before("mistake"));
521 
522  // type mismatch: when receiving a "Message" mark, we expect a string payload
523  VERIFY_ERROR(WRONG_TYPE, uiBus.mark(targetID, GenNode{"Message", Time::NEVER }))
524 
525  // the type error happens while resolving the payload,
526  // and thus the actual "doMsg()" function on the target was not invoked
527  CHECK (mock.ensureNot(string(Time::NEVER)));
528  CHECK (nexusLog.verifyCall("mark").arg(targetID, Time::NEVER));
529  CHECK (nexusLog.ensureNot("delivered mark").arg(Time::NEVER));
530  CHECK ("getting serious" == mock.getError());
531 
532  mock.reset();
533  CHECK (isnil(mock.getMessage()));
534  CHECK (isnil(mock.getError()));
535  CHECK (not mock.isError());
536 
537 
538  cout << "____Event-Log_________________\n"
539  << util::join(mock.getLog(), "\n")
540  << "\n───╼━━━━━━━━━╾────────────────"<<endl;
541 
542  cout << "____Nexus-Log_________________\n"
543  << util::join(nexusLog, "\n")
544  << "\n───╼━━━━━━━━━╾────────────────"<<endl;
545  }
546 
547 
548 
576  void
578  {
581 
582  MockElm rootMock("root");
583  ID rootID = rootMock.getID();
584 
585  rootMock.attrib["α"] = "Centauri";
586  CHECK ("Centauri" == rootMock.attrib["α"]);
587  CHECK (isnil (rootMock.scope));
588 
589 
590  // simulated source for structural diff
592  {
593  const GenNode
594  ATTRIB_AL = GenNode("α", "quadrant"),
595  ATTRIB_PI = GenNode("π", 3.14159265),
596  CHILD_1 = MakeRec().genNode("a"),
597  CHILD_2 = MakeRec().genNode("b");
598 
599  auto
600  generateDiff()
601  {
602  using lib::diff::Ref;
603 
604  return MutationMessage{ after(Ref::ATTRIBS) // start after the existing attributes (of root)
605  , ins(CHILD_1) // insert first child (with name "a")
606  , ins(CHILD_2) // insert second child (with name "b")
607  , set(ATTRIB_AL) // assign a new value to attribute "α" <- "quadrant"
608  , mut(CHILD_2) // open nested scope of child "b" for recursive mutation
609  , ins(ATTRIB_PI) // ..within nested scope, add a new attribute "π" := 3.14159265
610  , emu(CHILD_2) // leave nested scope
611  };
612  }
613  }
614  diffSrc;
615 
616 
617  auto& uiBus = gui::test::Nexus::testUI();
618 
619 
620  // send a Diff message via UI-Bus to the rootMock
621  uiBus.change(rootID, diffSrc.generateDiff());
622 
623 
624  // Verify the rootMock has been properly altered....
625  MockElm& childA = *rootMock.scope[0];
626  MockElm& childB = *rootMock.scope[1];
627 
628  CHECK (2 == rootMock.scope.size()); // we've got two children now
629  CHECK (rootMock.attrib["α"] == "quadrant"); // alpha attribute has been reassigned
630  CHECK (childA.getID() == diffSrc.CHILD_1.idi); // children have the expected IDs
631  CHECK (childB.getID() == diffSrc.CHILD_2.idi);
632  CHECK (childB.attrib["π"] == "3.1415927"); // and the second child got attribute Pi
633 
634 
635  CHECK (rootMock.verifyEvent("create","root")
636  .beforeCall("buildMutator").on(&rootMock)
637  .beforeEvent("diff","root accepts mutation...") // start of diff mutation
638  .beforeEvent("diff","create child \"a\"") // insert first child
639  .beforeEvent("create", "a")
640  .beforeEvent("diff","create child \"b\"") // insert second child
641  .beforeEvent("create", "b")
642  .beforeEvent("diff","set Attib α <-quadrant") // assign value to existing attribute α
643  .beforeCall("buildMutator").on(&childB) // establish nested mutator for second child
644  .beforeEvent("diff","b accepts mutation...")
645  .beforeEvent("diff",">>Scope>> b") // recursively mutate second child
646  .beforeEvent("diff","++Attib++ π = 3.1415927")); // insert new attribute π within nested scope
647 
648 
649  CHECK (nexusLog.verifyCall("routeAdd").arg(rootMock.getID(), memLocation(rootMock)) // rootMock was attached to Nexus
650  .beforeCall("change") .argMatch(rootMock.getID(),
651  "after.+ins.+ins.+set.+mut.+ins.+emu") // diff message sent via UI-Bus
652  .beforeCall("routeAdd").arg(childA.getID(), memLocation(childA)) // first new child was attached to Nexus
653  .beforeCall("routeAdd").arg(childB.getID(), memLocation(childB)) // second new child was attached to Nexus
654  .beforeEvent("applied diff to "+string(rootMock.getID()))
655  );
656 
657  cout << "____Event-Log_________________\n"
658  << util::join(rootMock.getLog(), "\n")
659  << "\n───╼━━━━━━━━━╾────────────────"<<endl;
660 
661  cout << "____Nexus-Log_________________\n"
662  << util::join(nexusLog, "\n")
663  << "\n───╼━━━━━━━━━╾────────────────"<<endl;
664  }
665 
666 
667 
668  static string
670  {
671  return lib::idi::instanceTypeID (&uiElm);
672  }
673  };
674 
675 
677  LAUNCHER (AbstractTangible_test, "unit gui");
678 
679 
680 }}} // namespace gui::model::test
type erased baseclass for building a combined hash and symbolic ID.
Definition: entry-id.hpp:135
Rec::Mutator MakeRec
Definition: gen-node.hpp:135
bool isExpanded() const
Definition: mock-elm.hpp:386
Generic Message with an embedded diff, to describe changes to model elements.
Record< GenNode > Rec
Definition: gen-node.hpp:133
auto operation(FUN operation_to_define)
static ctrl::BusTerm & testUI()
get a connection point to a UI backbone faked for test
Definition: test-nexus.cpp:375
Automatically use custom string conversion in C++ stream output.
std::vector< PMockElm > scope
Definition: mock-elm.hpp:369
Constructor for a specially crafted 'ref GenNode'.
Definition: gen-node.hpp:732
bool isError() const
Definition: mock-elm.hpp:392
string getMessage() const
Definition: mock-elm.hpp:398
void undoIt(int, int64_t oldVal)
Support for verifying the occurrence of events from unit tests.
std::string toString(TY const &val) noexcept
get some string representation of any object, reliably.
Definition: format-obj.hpp:174
EventMatch ensureNot(string match) const
Definition: mock-elm.hpp:442
Definition: run.hpp:49
A fake UI backbone for investigations and unit testing.
Lumiera GTK UI implementation root.
Definition: guifacade.cpp:47
Helper to log and verify the occurrence of events.
Definition: event-log.hpp:557
static void setCommandHandler(CommandHandler=CommandHandler())
install a closure (custom handler function) to deal with any command invocations encountered in the t...
Definition: test-nexus.cpp:417
typed symbolic and hash ID for asset-like position accounting.
Definition: entry-id.hpp:128
#define VERIFY_ERROR(ERROR_ID, ERRONEOUS_STATEMENT)
Macro to verify a statement indeed raises an exception.
lib::idi::BareEntryID const & ID
EventMatch & arg(ARGS const &...args)
refine filter to additionally require specific arguments
Definition: event-log.hpp:452
string join(CON &&coll, string const &delim=", ")
enumerate a collection's contents, separated by delimiter.
Opaque message to effect a structural change on a target, which is likewise only known in an abstract...
Helper class used solely for defining a Command-Object.
EventLog const & getLog() const
Definition: mock-elm.hpp:473
EventLog & joinLog(MockElm &otherMock)
Definition: mock-elm.hpp:479
string const & getSym() const
Definition: entry-id.hpp:165
EventMatch & beforeCall(string match)
find a match for some function invocation after the current point of reference
Definition: event-log.hpp:390
Generic functions to build identification schemes.
void slotExpand()
Expand this element and remember the expanded state.
Definition: tangible.cpp:153
bool isTouched() const
Definition: mock-elm.hpp:380
EventMatch & before(string match)
find a match (substring match) of the given text in an EventLog entry after the current position ...
Definition: event-log.hpp:336
void slotCollapse()
Collapse or minimise this element and remember the collapsed state.
Definition: tangible.cpp:165
Token or Atom with distinct identity.
Definition: symbol.hpp:116
std::map< string, string > attrib
Definition: mock-elm.hpp:368
LAUNCHER(AbstractTangible_test,"unit gui")
Register this test class...
std::vector< string > & Arg
Definition: run.hpp:54
#define MARK_TEST_FUN
Macro to mark the current test function in STDOUT.
#define LERR_(_NAME_)
Definition: error.hpp:58
void invoke(Symbol cmdID, ARGS &&...)
Marker types to indicate a literal string and a Symbol.
Simple test class runner.
Tiny helper functions and shortcuts to be used everywhere Consider this header to be effectively incl...
EventMatch verify(string match) const
Definition: mock-elm.hpp:412
A collection of frequently used helper functions to support unit testing.
static Command get(Symbol cmdID)
Access existing command for use.
Definition: command.cpp:127
EventMatch verifyMark(string id) const
special verification match on a "state mark" message to this element
Definition: mock-elm.hpp:449
EventMatch verifyCall(string match) const
Definition: mock-elm.hpp:436
bool isnil(lib::time::Duration const &dur)
Definition: timevalue.hpp:642
A token language to represent structural changes in a tree like hierarchical data structure...
Lumiera error handling (C++ interface).
string instanceTypeID(const TY *const obj)
designation of an distinct object instance
Definition: genfunc.hpp:125
Interface common to all UI elements of relevance for the Lumiera application.
Definition: tangible.hpp:164
static const Time NEVER
border condition marker value. NEVER >= any time value
Definition: timevalue.hpp:241
static const Ref ATTRIBS
symbolic ID ref "_ATTRIBS_"
Definition: gen-node.hpp:757
EventMatch verify(string match) const
start a query to match for some substring.
Definition: event-log.hpp:839
EventMatch verifyEvent(string match) const
Definition: mock-elm.hpp:424
Handle object representing a single Command instance to be used by client code.
Definition: command.hpp:125
static lib::test::EventLog const & getLog()
Definition: test-nexus.cpp:381
Bare symbolic and hash ID used for accounting of asset like entries.
Mock UI element or controller.
Definition: mock-elm.hpp:109
EventMatch & afterEvent(string match)
Definition: event-log.hpp:417
Actually defining a command and binding it to execution parameters.
a family of time value like entities and their relationships.
EventMatch & beforeEvent(string match)
find a match for an "event" after the current point of reference
Definition: event-log.hpp:368
ExecResult undo()
Definition: command.hpp:246
A generic interface element instrumented for unit testing.
void reset()
invoke the generic reset hook
Definition: tangible.cpp:60
generic data element node within a tree
Definition: gen-node.hpp:213
static lib::test::EventLog const & startNewLog()
Definition: test-nexus.cpp:387
EventMatch & on(string targetID)
refine filter to additionally match the 'this' attribute
Definition: event-log.hpp:519
ID getID() const
Definition: mock-elm.hpp:374
string getError() const
Definition: mock-elm.hpp:404