back to UI command invocation: basically implement a placeholder command
based on the previous experiments, this adds a fake operation
and a definition frame to hook this operation as pseudo Proc-Layer command
WIP: the invocation itself is not yet implemented.
We need to build a custom invocation pattern for that,
in order to be able to capture the instance-ID of the command
on invocation
NOTE: also, because of #989, we can not bind a time value for this test
This commit is contained in:
parent
297f986b5f
commit
eaa12499f3
7 changed files with 195 additions and 11 deletions
|
|
@ -146,7 +146,8 @@ namespace ctrl {
|
|||
* the element. Thus, the default implementation is just to pass the
|
||||
* given state mark "up", assuming that it will reach the hub
|
||||
* eventually, which in turn knows hot to reach the element.
|
||||
* @note messages to unreachable elements will be dropped silently.
|
||||
* @return if the target was known and the mark operation dispatched.
|
||||
* @note messages to unreachable elements will be dropped.
|
||||
*/
|
||||
bool
|
||||
BusTerm::mark (ID subject, GenNode const& mark)
|
||||
|
|
|
|||
|
|
@ -88,7 +88,7 @@ namespace ctrl{
|
|||
/** route mark messages down to the individual Tangible.
|
||||
* @note only messages to elements currently registered
|
||||
* in the routing table are dispatched. All other
|
||||
* messages are dropped silently.
|
||||
* messages are dropped without further effect.
|
||||
*/
|
||||
virtual bool
|
||||
mark (ID subject, GenNode const& mark) override
|
||||
|
|
|
|||
|
|
@ -145,6 +145,21 @@ namespace idi {
|
|||
return format::instance_format (namePrefix<TY>(), instanceCounter.inc<TY>());
|
||||
}
|
||||
|
||||
/** build a long type based identifier, with running counter and custom prefix.
|
||||
* @param prefix optional prefix to prepend to the generated ID
|
||||
* @return a ID string based on the full type, followed by an instance number
|
||||
* @warning for one, like \ref generateSymbolicID(), this operation is not really
|
||||
* cheap. And then, since the type ID is slightly abbreviated and then
|
||||
* mangled, there is still the possibility of occasional clashes.
|
||||
*/
|
||||
template<class TY>
|
||||
inline string
|
||||
generateExtendedID(string prefix ="")
|
||||
{
|
||||
static TypedCounter instanceCounter;
|
||||
return format::instance_format (prefix + typeFullID<TY>(), instanceCounter.inc<TY>());
|
||||
}
|
||||
|
||||
/**
|
||||
* @return a standard hash value, based on the full (mangled) C++ type name
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -177,7 +177,7 @@ namespace test {
|
|||
commandInvocation ()
|
||||
{
|
||||
MARK_TEST_FUN
|
||||
auto cmd = gui::test::Nexus::prepareMockCmd<string, TimeSpan, HashVal>();
|
||||
auto cmd = gui::test::Nexus::prepareMockCmd<string, HashVal>(); //TimeSpan /////////////TODO
|
||||
|
||||
MockElm mock("uiElm");
|
||||
|
||||
|
|
@ -186,6 +186,12 @@ namespace test {
|
|||
TimeSpan clip (Time(1,2,3), lib::test::randTime());
|
||||
LuidH luid;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////TODO WIP
|
||||
mock.issueCommand(cmd);
|
||||
cout << "____Nexus-Log_________________\n"
|
||||
<< util::join(gui::test::Nexus::getLog(), "\n")
|
||||
<< "\n───╼━━━━━━━━━╾────────────────"<<endl;
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////TODO WIP
|
||||
// we cannot invoke commands prior to binding arguments
|
||||
VERIFY_ERROR (UNBOUND_ARGUMENTS, mock.issueCommand(cmd) );
|
||||
|
||||
|
|
@ -196,19 +202,19 @@ namespace test {
|
|||
CHECK (not gui::test::Nexus::canInvoke(cmd));
|
||||
|
||||
|
||||
mock.prepareCommand(cmd, Rec({text, clip, luid}));
|
||||
mock.prepareCommand(cmd, Rec({text, luid})); ////////TODO clip,
|
||||
|
||||
CHECK (gui::test::Nexus::canInvoke(cmd));
|
||||
CHECK (gui::test::Nexus::wasBound(cmd, text, clip, luid));
|
||||
CHECK (gui::test::Nexus::wasBound(cmd, text, luid)); ////////TODO clip,
|
||||
CHECK (not gui::test::Nexus::wasInvoked(cmd));
|
||||
CHECK (not gui::test::Nexus::wasInvoked(cmd, text, clip, luid));
|
||||
CHECK (not gui::test::Nexus::wasInvoked(cmd, text, luid)); ////////TODO clip,
|
||||
CHECK (not gui::test::Nexus::wasBound(cmd, "lololo"));
|
||||
|
||||
|
||||
mock.issueCommand(cmd);
|
||||
|
||||
CHECK (gui::test::Nexus::wasInvoked(cmd));
|
||||
CHECK (gui::test::Nexus::wasInvoked(cmd, text, clip, luid));
|
||||
CHECK (gui::test::Nexus::wasInvoked(cmd, text, luid)); ////////TODO clip,
|
||||
CHECK (not gui::test::Nexus::wasInvoked(cmd, " huh ", clip, luid));
|
||||
CHECK (not gui::test::Nexus::wasInvoked(cmd, text, clip));
|
||||
|
||||
|
|
|
|||
138
tests/gui/test/placeholder-command.hpp
Normal file
138
tests/gui/test/placeholder-command.hpp
Normal file
|
|
@ -0,0 +1,138 @@
|
|||
/*
|
||||
PLACEHOLDER-COMMAND.hpp - fake operation to mock command invocation from UI
|
||||
|
||||
Copyright (C) Lumiera.org
|
||||
2016, Hermann Vosseler <Ichthyostega@web.de>
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation; either version 2 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
/** @file placeholder-command.hpp
|
||||
** Generate fake commands with stub operations and the ability to verify invocation.
|
||||
** This helper for unit testing of UI interactions might serve as dummy placeholder,
|
||||
** or be used to mock some operation expected to happen within Proc-Layer. The test::Nexus
|
||||
** offers a convenience front-end to install such an placeholder operation and use it
|
||||
** as counterpart for some tested elements connected to the UI-bus.
|
||||
**
|
||||
** The actual operation is void of any functionality, but might be installed to accept
|
||||
** arbitrary predetermined argument bindings, and to verify invocation and passed arguments.
|
||||
**
|
||||
** @see BusTerm_test
|
||||
** @see test::Nexus::prepareMockCmd
|
||||
**
|
||||
*/
|
||||
|
||||
|
||||
#ifndef GUI_TEST_PLACEHOLDER_COMMAND_H
|
||||
#define GUI_TEST_PLACEHOLDER_COMMAND_H
|
||||
|
||||
|
||||
#include "lib/error.hpp"
|
||||
#include "lib/symbol.hpp"
|
||||
#include "lib/idi/genfunc.hpp"
|
||||
#include "lib/test/event-log.hpp"
|
||||
#include "proc/control/command-def.hpp"
|
||||
#include "lib/format-util.hpp"
|
||||
//#include "lib/diff/gen-node.hpp"
|
||||
|
||||
//#include <boost/noncopyable.hpp>
|
||||
//#include <functional>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
|
||||
namespace gui {
|
||||
namespace test{
|
||||
|
||||
using std::string;
|
||||
using lib::Symbol;
|
||||
|
||||
|
||||
/** place the string persistently in memory.
|
||||
* @internal used as workaround for creating command-IDs on the fly
|
||||
* @todo temporary workaround, shall be replaced by lib::Symbol implementation ///////////////TICKET #157 maintain symbol table for interned strings
|
||||
* @return a C-String marked as lib::Literal, pointing
|
||||
* to the permanent location in heap memory.
|
||||
* @see \ref test-nexus.cpp implementation
|
||||
*/
|
||||
Symbol internedString (string&& idString);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Set of stub command operations.
|
||||
* This is a typed definition frame with some operations,
|
||||
* 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.
|
||||
*/
|
||||
template<typename...ARGS>
|
||||
class PlaceholderCommand
|
||||
{
|
||||
static lib::test::EventLog log_;
|
||||
|
||||
/** @internal ID-string specific for the instance `ARGS` */
|
||||
static string
|
||||
thisTypeInstance()
|
||||
{
|
||||
return lib::idi::generateExtendedID<PlaceholderCommand>();
|
||||
}
|
||||
|
||||
|
||||
/** a dummy command "operation */
|
||||
static void
|
||||
operate (ARGS ...args)
|
||||
{
|
||||
log_.call(thisTypeInstance(), "operate", std::forward<ARGS>(args)...);
|
||||
}
|
||||
|
||||
static string
|
||||
capture (ARGS ...args)
|
||||
{
|
||||
using VecS = std::vector<string>;
|
||||
return "Memento⧏" + util::join (util::stringify<VecS> (args...),"⧓") + "⧐";
|
||||
}
|
||||
|
||||
static void
|
||||
undo (ARGS ..., string memento)
|
||||
{
|
||||
log_.call(thisTypeInstance(), "undo", memento);
|
||||
}
|
||||
|
||||
|
||||
public:
|
||||
static proc::control::Command
|
||||
fabricateNewInstance (lib::test::EventLog const& invocationLog)
|
||||
{
|
||||
log_ = invocationLog;
|
||||
return proc::control::CommandDef(internedString (thisTypeInstance()))
|
||||
.operation(PlaceholderCommand::operate)
|
||||
.captureUndo(PlaceholderCommand::capture)
|
||||
.undoOperation(PlaceholderCommand::undo);
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template<typename...ARGS>
|
||||
lib::test::EventLog PlaceholderCommand<ARGS...>::log_{"test-dummy-"+thisTypeInstance()};
|
||||
|
||||
|
||||
|
||||
|
||||
}} // namespace gui::test
|
||||
#endif /*GUI_TEST_PLACEHOLDER_COMMAND_H*/
|
||||
|
|
@ -44,6 +44,7 @@
|
|||
|
||||
|
||||
#include "lib/error.hpp"
|
||||
#include "lib/symbol.hpp"
|
||||
#include "test/test-nexus.hpp"
|
||||
#include "lib/test/event-log.hpp"
|
||||
#include "gui/ctrl/nexus.hpp"
|
||||
|
|
@ -56,9 +57,11 @@
|
|||
//#include "lib/util.hpp"
|
||||
|
||||
#include <string>
|
||||
#include <deque>
|
||||
|
||||
using std::string;
|
||||
|
||||
using lib::Symbol;
|
||||
using lib::Variant;
|
||||
using lib::diff::Rec;
|
||||
using lib::diff::GenNode;
|
||||
|
|
@ -73,6 +76,20 @@ using util::_Fmt;
|
|||
namespace gui {
|
||||
namespace test{
|
||||
|
||||
namespace { // quick-n-dirty string table implementation
|
||||
|
||||
/** @warning grows eternally, never shrinks */
|
||||
std::deque<string> idStringBuffer; ////////////////////////////////TICKET #158 replace by symbol table
|
||||
}
|
||||
|
||||
Symbol
|
||||
internedString (string&& idString)
|
||||
{
|
||||
idStringBuffer.emplace_back (std::forward<string> (idString));
|
||||
return Symbol (idStringBuffer.back().c_str());
|
||||
}
|
||||
|
||||
|
||||
namespace { // internal details
|
||||
|
||||
using BusHub = gui::ctrl::Nexus;
|
||||
|
|
@ -159,9 +176,15 @@ namespace test{
|
|||
{
|
||||
log_.call(this, "mark", subject, mark);
|
||||
if (BusHub::mark (subject, mark))
|
||||
log_.event ("TestNexus", _Fmt("delivered mark to %s |%s") % subject % mark);
|
||||
{
|
||||
log_.event ("TestNexus", _Fmt("delivered mark to %s |%s") % subject % mark);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
log_.warn (_Fmt("discarding mark to unknown %s |%s") % subject % mark);
|
||||
{
|
||||
log_.warn (_Fmt("discarding mark to unknown %s |%s") % subject % mark);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
virtual BusTerm&
|
||||
|
|
@ -336,7 +359,7 @@ namespace test{
|
|||
|
||||
lib::Depend<ZombieNexus> zombieNexus;
|
||||
|
||||
} // internal details
|
||||
}//(End) internal details
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -48,6 +48,7 @@
|
|||
#include "lib/error.hpp"
|
||||
#include "gui/ctrl/bus-term.hpp"
|
||||
#include "gui/model/tangible.hpp"
|
||||
#include "test/placeholder-command.hpp"
|
||||
#include "lib/test/event-log.hpp"
|
||||
#include "lib/diff/gen-node.hpp"
|
||||
|
||||
|
|
@ -116,7 +117,7 @@ namespace test{
|
|||
inline interact::InvocationTrail
|
||||
Nexus::prepareMockCmd()
|
||||
{
|
||||
UNIMPLEMENTED("pick up arbitrary types and fabricate a mock command accepting those types");
|
||||
return Cmd {PlaceholderCommand<ARGS...>::fabricateNewInstance(getLog())};
|
||||
}
|
||||
|
||||
template<typename...ARGS>
|
||||
|
|
|
|||
Loading…
Reference in a new issue