UI-Bus command handling protocol unit test PASS

still TODO: the ability to use immutable types
within the command framework. In theory, this
shouldn't be had to implement, since we're creating
a new opaque value holder within the command registry
anyway, so it should be sufficient to refrain from
re-assigning a new value tuple. This is relevant,
since e.g. our time framework is built on immutable
value types.
This commit is contained in:
Fischlurch 2016-02-06 01:28:39 +01:00
parent deb7a6758c
commit dfc28ca2a0
5 changed files with 93 additions and 57 deletions

View file

@ -176,10 +176,12 @@ namespace test {
}
/** @test perform the full command binding and invocation protocol */
void
commandInvocation ()
{
MARK_TEST_FUN
gui::test::Nexus::startNewLog();
auto cmd = gui::test::Nexus::prepareMockCmd<string, LuidH>(); //TimeSpan /////////////TODO
MockElm mock("uiElm");
@ -203,14 +205,9 @@ namespace test {
CHECK (cmd.canExec());
CHECK (gui::test::Nexus::wasBound(cmd, text, luid)); ////////TODO clip,
////////////////////////////////////////////////////////////////////////////////////////////////////TODO WIP
cout << "____Nexus-Log_________________\n"
<< util::join(gui::test::Nexus::getLog(), "\n")
<< "\n───╼━━━━━━━━━╾────────────────"<<endl;
////////////////////////////////////////////////////////////////////////////////////////////////////TODO WIP
CHECK (not gui::test::Nexus::wasInvoked(cmd));
CHECK (not gui::test::Nexus::wasInvoked(cmd, text, luid)); ////////TODO clip,
CHECK (not gui::test::Nexus::wasBound(cmd, string("lololo")));
CHECK (not gui::test::Nexus::wasBound(cmd, "lololo"));
mock.issueCommand(cmd);
@ -228,6 +225,10 @@ namespace test {
CHECK (not gui::test::Nexus::wasInvoked(cmdX));
CHECK (not gui::test::Nexus::wasInvoked(cmdY));
cout << "____Nexus-Log_________________\n"
<< util::join(gui::test::Nexus::getLog(), "\n")
<< "\n───╼━━━━━━━━━╾────────────────"<<endl;
}
@ -235,6 +236,11 @@ namespace test {
captureStateMark ()
{
UNIMPLEMENTED ("message to capture interface state");
////////////////////////////////////////////////////////////////////////////////////////////////////TODO WIP
cout << "____Nexus-Log_________________\n"
<< util::join(gui::test::Nexus::getLog(), "\n")
<< "\n───╼━━━━━━━━━╾────────────────"<<endl;
////////////////////////////////////////////////////////////////////////////////////////////////////TODO WIP
}

View file

@ -79,25 +79,36 @@ namespace test{
* suitably to be bound into a Proc-Layer command. The actual
* command "operation" just logs invocation into a statically
* obtained \ref EventLog Event-Log instance.
* @note by design, in Lumiera the actual command functions are stateless.
* For this reason, the command framework provides no way to associate
* an _instance_ of some kind of "command object" with the (conceptual)
* command binding or prototype, thus we're unable to log anything
* beyond the concrete argument types and values on invocation.
*/
template<typename...ARGS>
class PlaceholderCommand
{
static lib::test::EventLog log_;
/** @internal ID-string specific for the instance `ARGS` */
/** @internal unique ID-string specific for the instance `ARGS` */
static string
thisTypeInstance()
uniqueTypeInstance()
{
return lib::idi::generateExtendedID<PlaceholderCommand>();
}
static string
fullTypeID()
{
return lib::idi::typeFullID<PlaceholderCommand>();
}
/** a dummy command "operation */
static void
operate (ARGS ...args)
{
log_.call(thisTypeInstance(), "operate", std::forward<ARGS>(args)...);
log_.call(fullTypeID(), "operate", std::forward<ARGS>(args)...);
}
static string
@ -110,7 +121,7 @@ namespace test{
static void
undo (ARGS ..., string memento)
{
log_.call(thisTypeInstance(), "undo", memento);
log_.call(fullTypeID(), "undo", memento);
}
@ -119,7 +130,7 @@ namespace test{
fabricateNewInstance (lib::test::EventLog const& invocationLog)
{
log_ = invocationLog;
return proc::control::CommandDef(internedString (thisTypeInstance()))
return proc::control::CommandDef(internedString (uniqueTypeInstance()))
.operation(PlaceholderCommand::operate)
.captureUndo(PlaceholderCommand::capture)
.undoOperation(PlaceholderCommand::undo);
@ -129,7 +140,7 @@ namespace test{
template<typename...ARGS>
lib::test::EventLog PlaceholderCommand<ARGS...>::log_{"test-dummy-"+thisTypeInstance()};
lib::test::EventLog PlaceholderCommand<ARGS...>::log_{"test-dummy-"+fullTypeID()};

View file

@ -435,6 +435,14 @@ namespace test{
namespace { // install a diagnostic dummy-command-handler
/**
* Compact diagnostic dummy command handler.
* Used as disposable one-way off object.
* Is both a lib::Variant visitor (to receive the
* contents of the "`act`" message, and implements
* the HandlingPattern interface to receive and
* invoke the prepared command closure.
*/
class SimulatedCommandHandler
: public Variant<DataValues>::Predicate
, public HandlingPattern
@ -468,7 +476,7 @@ namespace test{
}
/* ==== CommandHandler ==== */
/* ==== CommandHandler / Visitor ==== */
/** Case-1: the message provides parameter data to bind to the command */
bool
@ -483,7 +491,7 @@ namespace test{
bool
handle (int const&) override
{
log_.event("TestNexus", "trigger "+string(command_));
log_.call ("TestNexus", "exec-command", command_);
return command_.exec (*this);
}
@ -514,22 +522,11 @@ namespace test{
{
log_.event("TestNexus", "HANDLING Command-Message for "+string(command_));
if (not cmdMsg.data.accept (*this))
if (cmdMsg.data.accept (*this))
log_.event("TestNexus", "SUCCESS handling "+command_.getID());
else
log_.warn(_Fmt("FAILED to handle command-message %s in test-mode") % cmdMsg);
}
bool
invokedExec()
{
return log_.verifyCall("exec").on(this);
}
bool
invokedUndo()
{
return log_.verifyCall("undo").on(this)
.afterCall("exec");
}
};
}//(End)diagnostic dummy-command-handler
@ -547,13 +544,6 @@ namespace test{
bool
Nexus::wasInvoked (Cmd cmd)
{
UNIMPLEMENTED ("verify the given command was indeed invoked at least once");
}
/**

View file

@ -146,9 +146,9 @@ namespace test{
* is also opaque, to allow to send arbitrary binding data. The remedy
* is to rely on diff::DataCap's `operator string()`, so we can at least
* match with the transport format of the Data. A precise and complete
* matching is only possible after our probe-command was actually invoked,
* since we're controlling the implementation of that probe-command and
* can thus record arbitrary data embedded therein.
* matching would only possible after actually invoking our probe-command,
* since we're controlling the implementation of that probe-command.
* Right now (2016) this implementation was deemed adequate
*/
template<typename...ARGS>
inline bool
@ -158,14 +158,45 @@ namespace test{
return getLog()
.verifyMatch("TestNexus.+HANDLING Command-Message for .+" +cmd.getID())
.beforeCall("bind-command").on("TestNexus").arg(string(DataCap(args))...);
.beforeCall("bind-command").on("TestNexus")
.arg(string(DataCap(args))...);
}
/**
* Test predicate: verify actual command invocation by string match on test log.
* This match ensures that
* - first the installed command handler processed the '`act`' message
* - then the installed (mock) command handling pattern triggered invocation
* - and finally our installed mock command function received the call
* @remarks again arguments are verified by string match; but now we're looking
* on the concrete arguments as seen from within the command `operate` function.
* These may differ from the transport values, which are used to initialise
* the concrete arguments.
*/
template<typename...ARGS>
inline bool
Nexus::wasInvoked (Cmd cmd, ARGS const& ...args)
{
UNIMPLEMENTED("verify the denoted command was indeed invoked and received the given concrete Arguments (String-match)");
return getLog()
.verifyMatch("TestNexus.+HANDLING Command-Message for .+" +cmd.getID())
.beforeCall("exec-command").on("TestNexus").arg(cmd.getID())
.beforeCall("exec").on("MockHandlingPattern")
.beforeCall("operate").arg(util::toString(args)...)
.beforeEvent("TestNexus", "SUCCESS handling "+cmd.getID());
}
/**
* Test predicate: verify at least one actual invocation happened for the given commend,
* without matching any concrete arguments
*/
inline bool
Nexus::wasInvoked (Cmd cmd)
{
return getLog()
.verifyMatch("TestNexus.+HANDLING Command-Message for .+" +cmd.getID())
.beforeCall("exec-command").on("TestNexus").arg(cmd.getID())
.beforeCall("operate")
.beforeEvent("TestNexus", "SUCCESS handling "+cmd.getID());
}

View file

@ -694,8 +694,7 @@
</li>
</ul>
</body>
</html>
</richcontent>
</html></richcontent>
<icon BUILTIN="button_ok"/>
</node>
</node>
@ -718,16 +717,15 @@
wie Session- und State-Managment, Commands etc.
</p>
</body>
</html>
</richcontent>
</html></richcontent>
</node>
<node CREATED="1453545968166" ID="ID_399884859" MODIFIED="1453546095559" TEXT="Command-Handler">
<icon BUILTIN="pencil"/>
<node CREATED="1453545968166" ID="ID_399884859" MODIFIED="1454718147309" TEXT="Command-Handler">
<node CREATED="1453546129537" ID="ID_1926242869" MODIFIED="1453546137220" TEXT="empf&#xe4;ngt &quot;act&quot;-Nachrichten">
<node CREATED="1453546367201" ID="ID_1473684366" MODIFIED="1453546575633" TEXT="&quot;bang&quot; -&gt; HandlingPattern">
<icon BUILTIN="button_ok"/>
</node>
<node CREATED="1453546381255" ID="ID_1252400934" MODIFIED="1453546392585" TEXT="&quot;bind&quot; -&gt; Bindung">
<node CREATED="1453546381255" ID="ID_1252400934" MODIFIED="1454711253322" TEXT="&quot;bind&quot; -&gt; Bindung">
<icon BUILTIN="button_ok"/>
<node CREATED="1453546393573" ID="ID_857178151" MODIFIED="1453546568844" TEXT="Paradigmen-Mismatch">
<icon BUILTIN="messagebox_warning"/>
</node>
@ -762,8 +760,7 @@
Compiler-Bug <font color="#c80219">Gcc-#63723</font>
</p>
</body>
</html>
</richcontent>
</html></richcontent>
</node>
<node CREATED="1453639033250" ID="ID_1669831951" LINK="http://stackoverflow.com/questions/26705199/how-can-i-write-a-type-trait-to-check-if-a-type-is-convertible-to-another-by-a-n" MODIFIED="1453639049952" TEXT="s.a. Stackoverflow"/>
<node CREATED="1453639055478" ID="ID_1560466275" MODIFIED="1453639078468">
@ -776,8 +773,7 @@
gel&#246;st in GCC-5 --&#160;<i>backport unwahrscheinlich</i>
</p>
</body>
</html>
</richcontent>
</html></richcontent>
</node>
<node CREATED="1453639119142" ID="ID_1472487058" MODIFIED="1453639126177" TEXT="inzwischen hartgecodet">
<icon BUILTIN="clanbomber"/>
@ -800,8 +796,7 @@
pro m&#246;glichem Umwandlungs-Pfad
</p>
</body>
</html>
</richcontent>
</html></richcontent>
</node>
</node>
<node CREATED="1453590628419" ID="ID_1314031268" MODIFIED="1453590885601">
@ -817,8 +812,7 @@
und layern nur die tats&#228;chlich m&#246;glichen Umwandlungen dr&#252;ber
</p>
</body>
</html>
</richcontent>
</html></richcontent>
<icon BUILTIN="info"/>
</node>
<node CREATED="1453590667630" ID="ID_792450888" MODIFIED="1453590699782" TEXT="&#xfc;berpr&#xfc;ft: mit -O3 und strip bleibt erstaunlich wenig &#xfc;brig"/>
@ -831,8 +825,12 @@
<icon BUILTIN="hourglass"/>
</node>
<node CREATED="1453546183561" ID="ID_1080090125" MODIFIED="1453546187900" TEXT="Mock-Variante">
<node CREATED="1453546195240" ID="ID_1905175534" MODIFIED="1453546196971" TEXT="loggen"/>
<node CREATED="1453546197727" ID="ID_606855270" MODIFIED="1453546207402" TEXT="verifizierbar machen"/>
<node CREATED="1453546195240" ID="ID_1905175534" MODIFIED="1454711242234" TEXT="loggen">
<icon BUILTIN="button_ok"/>
</node>
<node CREATED="1453546197727" ID="ID_606855270" MODIFIED="1454711245274" TEXT="verifizierbar machen">
<icon BUILTIN="button_ok"/>
</node>
<node CREATED="1453546215117" ID="ID_31965862" MODIFIED="1453546220236" TEXT="pseudo-Command">
<icon BUILTIN="button_ok"/>
</node>