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:
parent
deb7a6758c
commit
dfc28ca2a0
5 changed files with 93 additions and 57 deletions
|
|
@ -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
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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()};
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -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());
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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ängt "act"-Nachrichten">
|
||||
<node CREATED="1453546367201" ID="ID_1473684366" MODIFIED="1453546575633" TEXT=""bang" -> HandlingPattern">
|
||||
<icon BUILTIN="button_ok"/>
|
||||
</node>
|
||||
<node CREATED="1453546381255" ID="ID_1252400934" MODIFIED="1453546392585" TEXT=""bind" -> Bindung">
|
||||
<node CREATED="1453546381255" ID="ID_1252400934" MODIFIED="1454711253322" TEXT=""bind" -> 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öst in GCC-5 -- <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ö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ächlich möglichen Umwandlungen drüber
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
</richcontent>
|
||||
</html></richcontent>
|
||||
<icon BUILTIN="info"/>
|
||||
</node>
|
||||
<node CREATED="1453590667630" ID="ID_792450888" MODIFIED="1453590699782" TEXT="überprüft: mit -O3 und strip bleibt erstaunlich wenig ü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>
|
||||
|
|
|
|||
Loading…
Reference in a new issue