diff --git a/tests/gui/bus-term-test.cpp b/tests/gui/bus-term-test.cpp index 740e494e8..e99ad34d2 100644 --- a/tests/gui/bus-term-test.cpp +++ b/tests/gui/bus-term-test.cpp @@ -28,6 +28,7 @@ #include "lib/test/run.hpp" #include "lib/test/test-helper.hpp" #include "lib/sync.hpp" +#include "lib/sync-classlock.hpp" #include "backend/thread-wrapper.hpp" #include "gui/ctrl/bus-term.hpp" #include "gui/ctrl/state-manager.hpp" @@ -46,13 +47,18 @@ #include "lib/luid.h" #include "lib/util.hpp" +#include + +using boost::lexical_cast; using lib::Sync; +using lib::ClassLock; using backend::ThreadJoinable; using lib::iter_stl::dischargeToSnapshot; using lib::IterQueue; using lib::IterStack; using std::function; +using util::contains; using util::isnil; using util::_Fmt; @@ -89,11 +95,13 @@ namespace test { namespace {// test data... - // --------random-dispatch-test------ - uint const MAX_RAND_NUMBS = 200; - uint const MAX_RAND_BORGS = 500; - uint const MAX_RAND_DELAY = 1000; - // --------random-dispatch-test------ + // --------random-diff-test------ + uint const MAX_RAND_BORGS = 100; // stay below 400, verification export grows quadratic + uint const MAX_RAND_NUMBS = 500; + uint const MAX_RAND_DELAY = 5000; // throttle generation, since diff application is slower + // --------random-diff-test------ + + int generator_instances = 0; } @@ -110,13 +118,14 @@ namespace test { * This test enacts the fundamental generic communication patterns * to verify the messaging behaviour * - attaching a \ref BusTerm - * - generating a command invocation + * - detaching on element destruction + * - generate a command invocation * - argument passing * - capture a _state mark_ * - replay a _state mark_ * - cast messages and error states downstream * - generic operating of interface states - * - detaching on element destruction + * - multithreaded integration test of diff mutation * * @see AbstractTangible_test * @see gui::model::Tangible @@ -134,7 +143,7 @@ namespace test { replayStateMark(); verifyNotifications(); clearStates(); - pushDiff(); ///////////////////////////////////////////////////////////////////////////TICKET #1066 + pushDiff(); } @@ -532,18 +541,22 @@ namespace test { } - /** @test integration test of mutation by diff message + + + + /** + * @test integration test of mutation by diff message * Since this test focuses on the bus side of standard interactions, * it seems indicated to emulate the complete invocation situation, * which involves passing thread boundraries. The main thread running * this test shall enact the role of the UI event thread (since the * UI-Bus in the real application is confined to this UI thread). * Thus we'll start another thread to enact the role of the Session, - * to produce a diff message and "cast" it towards the UI. + * to produce diff messages and "cast" them towards the UI. * @note a defining property of this whole interaction is the fact that - * the diff is _pulled asynchronously,_ which means the actual diff - * generation happens on callback from the UI. Access to any "session" - * data needs to be protected by lock in such a situation. + * the diff is _pulled asynchronously,_ which means the actual diff + * generation happens on callback from the UI. Access to any "session" + * data needs to be protected by lock in such a situation. */ void pushDiff() @@ -555,6 +568,7 @@ namespace test { , ThreadJoinable { // shared data + uint64_t borgChecksum_ = 0; IterStack sessionBorgs_; // access to shared session data @@ -562,18 +576,19 @@ namespace test { scheduleBorg (uint id) { Lock sync(this); + borgChecksum_ += id; sessionBorgs_.push(id); - cout << "Sess: scheduledBorgs... "< interface @@ -587,14 +602,22 @@ namespace test { , TreeDiffLanguage , DiffSource { - uint id_; + uint generatorID_; SessionThread& theCube_; IterQueue steps_; BorgGenerator (SessionThread& motherShip, uint id) - : id_{id} + : generatorID_{id} , theCube_{motherShip} - { } + { + ClassLock sync; + ++generator_instances; + } + ~BorgGenerator() + { + ClassLock sync; + --generator_instances; + } /* == Interface IterSource == */ @@ -603,61 +626,62 @@ namespace test { firstResult () override { REQUIRE (not steps_); - cout << "Gen-"< notifyGUI) + + /** + * launch the Session Thread and start injecting Borg + */ + SessionThread(function notifyGUI) : ThreadJoinable{"BusTerm_test: asynchronous diff mutation" , [=]() { uint cnt = rand() % MAX_RAND_BORGS; - cout << "Sess: produce "< (borgID); + string childID = borg.getID().getSym(); + CHECK (contains (childID, borgID)); + CHECK (contains (childID, " of ")); // e.g. "3 of 5" + + CHECK (nexusLog.verifyCall("routeAdd").arg(rootMock.getID(), memLocation(rootMock)) // rootMock was attached to Nexus + .beforeCall("change") .argMatch(rootMock.getID(), // diff message sent via UI-Bus + "after.+_ATTRIBS_.+" // verify diff pattern generated for each Borg + "ins.+"+childID+".+" + "mut.+"+childID+".+" + "ins.+borgID.+"+borgID+".+" + "emu.+"+childID) + .beforeCall("routeAdd").arg(borg.getID(), memLocation(borg)) // Borg was inserted as child and attached to Nexus + .beforeEvent("applied diff to "+string(rootMock.getID())) + ); + } + + CHECK (rootMock.attrib["α"] == "Quadrant"); // attribute alpha was preserved while injecting all those Borg + + + // sanity checks + CHECK (borgChecksum == session.borgChecksum_); // no Borgs got lost + CHECK (0 == generator_instances); // no generator instance leaks + + + cout << "____Event-Log_________________\n" << util::join(rootMock.getLog(), "\n") << "\n───╼━━━━━━━━━╾────────────────"< - + @@ -5551,7 +5551,8 @@ - + + @@ -5813,8 +5814,8 @@ - - + + @@ -10869,8 +10870,8 @@ - - + + @@ -10973,7 +10974,7 @@ - + @@ -11033,7 +11034,7 @@ - + @@ -11267,12 +11268,13 @@ - + + - - + + @@ -11293,7 +11295,8 @@ - + + @@ -11397,8 +11400,9 @@ - + + @@ -11484,7 +11488,8 @@ - + + @@ -16718,7 +16723,7 @@ - + @@ -16729,7 +16734,7 @@ - + @@ -16848,10 +16853,11 @@ - - - - + + + + + @@ -16859,12 +16865,12 @@ - + - + @@ -16914,9 +16920,9 @@ - + - + @@ -16935,12 +16941,19 @@ - - + + - - - + + + + + + + + + +