provide a mock handler for commands and state marks
in the real system, this will be the task of the CoreService, while here, in test mode, we allow to install handling closures from the unit-test-code
This commit is contained in:
parent
16a70ce9f8
commit
540151b56b
5 changed files with 121 additions and 28 deletions
|
|
@ -103,8 +103,12 @@ namespace ctrl{
|
|||
/** add a new down-link connection to the routing table
|
||||
* @param identity the [endpoint-ID](\ref BusTerm::endpointID_) used
|
||||
* to address the new element to be connected to the bus.
|
||||
* @param newNode to add the address (!) into the routing table
|
||||
* @return backlink for the new Tangible's BusTerm to
|
||||
* attach itself to the Nexus.
|
||||
* @note at call time, the second param, the newNode will typically
|
||||
* be just a Tangible (and not a subclass yet),
|
||||
* since this function is invoked from ctor.
|
||||
*/
|
||||
virtual BusTerm&
|
||||
routeAdd (ID identity, Tangible& newNode) override
|
||||
|
|
|
|||
|
|
@ -193,6 +193,7 @@ namespace test{
|
|||
or entry.getType() == "destroy"
|
||||
or entry.getType() == "logJoin"
|
||||
)
|
||||
and !isnil(entry.scope())
|
||||
and contains (*entry.scope(), match);
|
||||
};
|
||||
}
|
||||
|
|
@ -210,6 +211,7 @@ namespace test{
|
|||
or entry.getType() == classifier
|
||||
or (entry.hasAttribute("ID") and contains (entry.get("ID"), classifier))
|
||||
)
|
||||
and !isnil(entry.scope())
|
||||
and contains (*entry.scope(), match);
|
||||
};
|
||||
}
|
||||
|
|
@ -682,9 +684,9 @@ namespace test{
|
|||
EventLog&
|
||||
event (string text)
|
||||
{
|
||||
log({"type=event", text});
|
||||
return *this;
|
||||
}
|
||||
log ("event", ArgSeq{}, ArgSeq{text}); // we use this ctor variant to ensure
|
||||
return *this; // that text is not misinterpreted as attribute,
|
||||
} // which might happen when text contains a '='
|
||||
|
||||
/** log some event, with additional ID or classifier
|
||||
* @param classifier info to be saved into the `ID` attribute
|
||||
|
|
@ -693,7 +695,7 @@ namespace test{
|
|||
EventLog&
|
||||
event (string classifier, string text)
|
||||
{
|
||||
log({"type=event", "ID="+classifier, text});
|
||||
log ("event", ArgSeq{"ID="+classifier}, ArgSeq{text});
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@
|
|||
//#include <map>
|
||||
|
||||
using lib::idi::EntryID;
|
||||
using lib::idi::BareEntryID;
|
||||
using gui::test::MockElm;
|
||||
using lib::diff::GenNode;
|
||||
//using boost::lexical_cast;
|
||||
|
|
@ -111,14 +112,14 @@ namespace test {
|
|||
attachNewBusTerm ()
|
||||
{
|
||||
// our dummy will be linked with this identity
|
||||
EntryID<MockElm> elmID{"zeitgeist"};
|
||||
BareEntryID elmID = EntryID<MockElm>{"zeitgeist"};
|
||||
|
||||
// Access the log on the Test-Nexus hub
|
||||
EventLog nexusLog = gui::test::Nexus::startNewLog();
|
||||
CHECK (nexusLog.ensureNot("zeitgeist"));
|
||||
|
||||
MockElm mock(elmID);
|
||||
CHECK (nexusLog.verifyCall("routeAdd").on("TestNexus").arg(elmID,"MockElm")
|
||||
CHECK (nexusLog.verifyCall("routeAdd").on("TestNexus").arg(elmID,"Tangible") // Note: invoked from ctor, so it is just a tangible at the moment
|
||||
.beforeEvent("TestNexus", "added route to bID-zeitgeist"));
|
||||
|
||||
EventLog elmLog = mock.getLog();
|
||||
|
|
@ -135,7 +136,7 @@ namespace test {
|
|||
// invoke action on element to cause upstream message (with a "state mark")
|
||||
mock.slotCollapse();
|
||||
CHECK (elmLog.verifyEvent("collapsed"));
|
||||
CHECK (nexusLog.verifyCall("note").on("TestNexus").arg("zeitgeist", "collapse"));
|
||||
CHECK (nexusLog.verifyCall("note").on("TestNexus").arg(elmID, "collapse"));
|
||||
|
||||
// send a state mark down to the mock element
|
||||
gui::test::Nexus::testUI().mark (elmID, GenNode("Flash", 23));
|
||||
|
|
@ -159,7 +160,7 @@ namespace test {
|
|||
|
||||
|
||||
cout << "____Probe-Log_________________\n"
|
||||
<< util::join(mock.getLog(), "\n")
|
||||
<< util::join(elmLog, "\n")
|
||||
<< "\n───╼━━━━━━━━━╾────────────────"<<endl;
|
||||
|
||||
cout << "____Nexus-Log_________________\n"
|
||||
|
|
|
|||
|
|
@ -55,8 +55,12 @@ using std::cerr;
|
|||
using std::endl;
|
||||
using std::string;
|
||||
|
||||
using lib::test::EventLog;
|
||||
using lib::Variant;
|
||||
using lib::diff::Rec;
|
||||
using lib::diff::GenNode;
|
||||
using lib::diff::DataValues;
|
||||
using lib::idi::instanceTypeID;
|
||||
using lib::test::EventLog;
|
||||
using gui::ctrl::BusTerm;
|
||||
using util::_Fmt;
|
||||
//using util::contains;
|
||||
|
|
@ -67,10 +71,6 @@ namespace test{
|
|||
|
||||
namespace { // internal details
|
||||
|
||||
using lib::Variant;
|
||||
using lib::diff::Rec;
|
||||
using lib::diff::DataValues;
|
||||
|
||||
using BusHub = gui::ctrl::Nexus;
|
||||
|
||||
|
||||
|
|
@ -123,12 +123,19 @@ namespace test{
|
|||
{
|
||||
EventLog log_{this};
|
||||
|
||||
using CommandHandler = test::Nexus::CommandHandler;
|
||||
using StateMarkHandler = test::Nexus::StateMarkHandler;
|
||||
|
||||
CommandHandler commandHandler_;
|
||||
StateMarkHandler stateMarkHandler_;
|
||||
|
||||
|
||||
|
||||
virtual void
|
||||
act (GenNode const& command)
|
||||
{
|
||||
log_.call(this, "act", command);
|
||||
BusHub::act (command);
|
||||
commandHandler_(command);
|
||||
log_.event("TestNexus", _Fmt("%s command \"%s\"%s")
|
||||
% invocationStage(command)
|
||||
% command.idi.getSym()
|
||||
|
|
@ -139,7 +146,7 @@ namespace test{
|
|||
note (ID subject, GenNode const& mark) override
|
||||
{
|
||||
log_.call(this, "note", subject, mark);
|
||||
BusHub::note (subject, mark);
|
||||
stateMarkHandler_(subject, mark);
|
||||
log_.event("TestNexus", _Fmt("processed note from %s |%s") % subject % mark);
|
||||
}
|
||||
|
||||
|
|
@ -151,19 +158,14 @@ namespace test{
|
|||
log_.event("TestNexus", _Fmt("delivered mark to %s |%s") % subject % mark);
|
||||
}
|
||||
|
||||
virtual operator string() const
|
||||
{
|
||||
return getID().getSym()+"."+lib::idi::instanceTypeID(this);
|
||||
}
|
||||
|
||||
virtual BusTerm&
|
||||
routeAdd (ID identity, Tangible& newNode) override
|
||||
{
|
||||
log_.call(this, "routeAdd", identity, newNode);
|
||||
log_.call(this, "routeAdd", identity, instanceTypeID(&newNode));
|
||||
BusHub::routeAdd (identity, newNode);
|
||||
log_.event("TestNexus", _Fmt("added route to %s |%s| table-size=%2d")
|
||||
% identity
|
||||
% lib::idi::instanceTypeID(&newNode)
|
||||
% instanceTypeID(&newNode)
|
||||
% BusHub::size());
|
||||
return *this;
|
||||
}
|
||||
|
|
@ -176,11 +178,19 @@ namespace test{
|
|||
log_.event("TestNexus", _Fmt("removed route to %s | table-size=%2d") % node % BusHub::size());
|
||||
}
|
||||
|
||||
virtual operator string() const
|
||||
{
|
||||
return getID().getSym()+"."+instanceTypeID(this);
|
||||
}
|
||||
|
||||
|
||||
public:
|
||||
TestNexus()
|
||||
: BusHub(*this, lib::idi::EntryID<TestNexus>("mock-UI"))
|
||||
{ }
|
||||
{
|
||||
installCommandHandler();
|
||||
installStateMarkHandler();
|
||||
}
|
||||
|
||||
// standard copy operations
|
||||
|
||||
|
|
@ -190,6 +200,33 @@ namespace test{
|
|||
{
|
||||
return log_;
|
||||
}
|
||||
|
||||
void
|
||||
installCommandHandler (CommandHandler newHandler =CommandHandler())
|
||||
{
|
||||
if (newHandler)
|
||||
commandHandler_ = newHandler;
|
||||
else
|
||||
commandHandler_ =
|
||||
[=](GenNode const& cmd)
|
||||
{
|
||||
log_.warn(_Fmt("NOT handling command-message %s in test-mode") % cmd);
|
||||
};
|
||||
}
|
||||
|
||||
void
|
||||
installStateMarkHandler (StateMarkHandler newHandler =StateMarkHandler())
|
||||
{
|
||||
if (newHandler)
|
||||
stateMarkHandler_ = newHandler;
|
||||
else
|
||||
stateMarkHandler_ =
|
||||
[=](ID subject, GenNode const& mark)
|
||||
{
|
||||
log_.warn(_Fmt("NOT handling state-mark %s passed from %s in test-mode")
|
||||
% mark % subject);
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
/** singleton instance of the [TestNexus]
|
||||
|
|
@ -198,6 +235,7 @@ namespace test{
|
|||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @internal a defunct interface backbone.
|
||||
* All UI-Bus operations are implemented NOP, but warning on STDRR
|
||||
|
|
@ -244,11 +282,6 @@ namespace test{
|
|||
cerr << "mark message -> ZombieNexus" <<endl;
|
||||
}
|
||||
|
||||
virtual operator string() const
|
||||
{
|
||||
return getID().getSym()+"."+lib::idi::instanceTypeID(this);
|
||||
}
|
||||
|
||||
virtual BusTerm&
|
||||
routeAdd (ID identity, Tangible& newNode) override
|
||||
{
|
||||
|
|
@ -266,6 +299,11 @@ namespace test{
|
|||
cerr << "disconnect("<<string(node)<<" -> ZombieNexus" <<endl;
|
||||
}
|
||||
|
||||
virtual operator string() const
|
||||
{
|
||||
return getID().getSym()+"."+instanceTypeID(this);
|
||||
}
|
||||
|
||||
|
||||
public:
|
||||
/** fabricate a "dead terminal", marked as deceased, viciously connected to itself.
|
||||
|
|
@ -319,6 +357,42 @@ namespace test{
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
* install a closure (custom handler function)
|
||||
* to deal with any command invocations encountered
|
||||
* in the test-UI-Bus. In the real Lumiera-UI, the UI-Bus
|
||||
* is wired with a [core service handler](\ref core-service.hpp),
|
||||
* which processes command messages by actually triggering
|
||||
* command invocation on the Session within Proc-Layer
|
||||
* @note when called without arguments, a default handler
|
||||
* will be installed, which just logs and discards
|
||||
* any command invocation message.
|
||||
* @warning when you install a closure from within unit test code,
|
||||
* be sure to re-install the default handler prior to leaving
|
||||
* the definition scope; since the "test nexus" is actually
|
||||
* implemented as singleton, an installed custom handler
|
||||
* will outlive the immediate usage scope, possibly
|
||||
* leading to segfault
|
||||
*/
|
||||
void
|
||||
Nexus::setCommandHandler (CommandHandler newHandler)
|
||||
{
|
||||
testNexus().installCommandHandler (newHandler);
|
||||
}
|
||||
|
||||
/**
|
||||
* similar to the [custom command handler](::setCommandHandler)
|
||||
* this hook allows to install a closure to intercept any
|
||||
* "state mark" messages passed over the test-UI-Bus
|
||||
*/
|
||||
void
|
||||
Nexus::setStateMarkHandler(StateMarkHandler newHandler)
|
||||
{
|
||||
testNexus().installStateMarkHandler (newHandler);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @return a defunct BusTerm with up-link to [ZombieNexus]
|
||||
|
|
|
|||
|
|
@ -47,9 +47,12 @@
|
|||
|
||||
#include "lib/error.hpp"
|
||||
#include "gui/ctrl/bus-term.hpp"
|
||||
#include "gui/model/tangible.hpp"
|
||||
#include "lib/test/event-log.hpp"
|
||||
#include "lib/diff/gen-node.hpp"
|
||||
|
||||
#include <boost/noncopyable.hpp>
|
||||
#include <functional>
|
||||
#include <string>
|
||||
|
||||
|
||||
|
|
@ -81,6 +84,15 @@ namespace test{
|
|||
|
||||
static lib::test::EventLog const& getLog();
|
||||
static lib::test::EventLog const& startNewLog();
|
||||
|
||||
|
||||
/* == allow to set custom handlers for commands and state changes == */
|
||||
|
||||
using CommandHandler = std::function<void(lib::diff::GenNode const&)>;
|
||||
using StateMarkHandler = std::function<void(lib::idi::BareEntryID, lib::diff::GenNode const&)>;
|
||||
|
||||
static void setCommandHandler (CommandHandler =CommandHandler());
|
||||
static void setStateMarkHandler (StateMarkHandler =StateMarkHandler());
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue