From eaa12499f3a743e34c2fe6eae4fcc75c62922adf Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Fri, 22 Jan 2016 12:19:25 +0100 Subject: [PATCH] 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 --- src/gui/ctrl/bus-controller.cpp | 3 +- src/gui/ctrl/nexus.hpp | 2 +- src/lib/idi/genfunc.hpp | 15 +++ tests/gui/bus-term-test.cpp | 16 ++- tests/gui/test/placeholder-command.hpp | 138 +++++++++++++++++++++++++ tests/gui/test/test-nexus.cpp | 29 +++++- tests/gui/test/test-nexus.hpp | 3 +- 7 files changed, 195 insertions(+), 11 deletions(-) create mode 100644 tests/gui/test/placeholder-command.hpp diff --git a/src/gui/ctrl/bus-controller.cpp b/src/gui/ctrl/bus-controller.cpp index 8a8869773..5610ac628 100644 --- a/src/gui/ctrl/bus-controller.cpp +++ b/src/gui/ctrl/bus-controller.cpp @@ -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) diff --git a/src/gui/ctrl/nexus.hpp b/src/gui/ctrl/nexus.hpp index 5f563fe24..42b880e65 100644 --- a/src/gui/ctrl/nexus.hpp +++ b/src/gui/ctrl/nexus.hpp @@ -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 diff --git a/src/lib/idi/genfunc.hpp b/src/lib/idi/genfunc.hpp index b0b35f987..d4678bb5d 100644 --- a/src/lib/idi/genfunc.hpp +++ b/src/lib/idi/genfunc.hpp @@ -145,6 +145,21 @@ namespace idi { return format::instance_format (namePrefix(), instanceCounter.inc()); } + /** 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 + inline string + generateExtendedID(string prefix ="") + { + static TypedCounter instanceCounter; + return format::instance_format (prefix + typeFullID(), instanceCounter.inc()); + } + /** * @return a standard hash value, based on the full (mangled) C++ type name */ diff --git a/tests/gui/bus-term-test.cpp b/tests/gui/bus-term-test.cpp index c3dd6426c..976dfe7f8 100644 --- a/tests/gui/bus-term-test.cpp +++ b/tests/gui/bus-term-test.cpp @@ -177,7 +177,7 @@ namespace test { commandInvocation () { MARK_TEST_FUN - auto cmd = gui::test::Nexus::prepareMockCmd(); + auto cmd = gui::test::Nexus::prepareMockCmd(); //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───╼━━━━━━━━━╾────────────────"< + + 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 +//#include +#include +#include + + +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 + class PlaceholderCommand + { + static lib::test::EventLog log_; + + /** @internal ID-string specific for the instance `ARGS` */ + static string + thisTypeInstance() + { + return lib::idi::generateExtendedID(); + } + + + /** a dummy command "operation */ + static void + operate (ARGS ...args) + { + log_.call(thisTypeInstance(), "operate", std::forward(args)...); + } + + static string + capture (ARGS ...args) + { + using VecS = std::vector; + return "Memento⧏" + util::join (util::stringify (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 + lib::test::EventLog PlaceholderCommand::log_{"test-dummy-"+thisTypeInstance()}; + + + + +}} // namespace gui::test +#endif /*GUI_TEST_PLACEHOLDER_COMMAND_H*/ diff --git a/tests/gui/test/test-nexus.cpp b/tests/gui/test/test-nexus.cpp index aac7a0b9c..df027e2e7 100644 --- a/tests/gui/test/test-nexus.cpp +++ b/tests/gui/test/test-nexus.cpp @@ -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 +#include 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 idStringBuffer; ////////////////////////////////TICKET #158 replace by symbol table + } + + Symbol + internedString (string&& idString) + { + idStringBuffer.emplace_back (std::forward (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; - } // internal details + }//(End) internal details diff --git a/tests/gui/test/test-nexus.hpp b/tests/gui/test/test-nexus.hpp index 2bb14e05e..89aed1ef8 100644 --- a/tests/gui/test/test-nexus.hpp +++ b/tests/gui/test/test-nexus.hpp @@ -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::fabricateNewInstance(getLog())}; } template