diff --git a/doc/technical/howto/crackNuts.txt b/doc/technical/howto/crackNuts.txt index d92ac46f2..be6b46601 100644 --- a/doc/technical/howto/crackNuts.txt +++ b/doc/technical/howto/crackNuts.txt @@ -92,7 +92,7 @@ special test setup:: It can be very helpful to use _policy based design_ for some complex evaluation or algorithm, even in cases where it is clear that the actual usage will only ever involve one specific data type and configuration. Not only does such a structured approach help with clarifying the design itself, - since the core of the evaluation logic can be abstracted from data representation, but only the + since the core of the evaluation logic can be abstracted from data representation -- yet also the testing and verification of correctness is simplified, as the test can be written to use simple, human-readable data (strings, symbols), and, furthermore, many kinds of instrumentation can be included into the test data to gain detailed insight what is happening in the test subject. diff --git a/tests/47engine.tests b/tests/47engine.tests index 2820b2ef8..8bd929ce0 100644 --- a/tests/47engine.tests +++ b/tests/47engine.tests @@ -17,7 +17,7 @@ return: 0 END -TEST "Buffer provider integration" BufferProviderLoad_test <; + using MockConnectState = OutputSlot::AllocState; + + FakeSlot() + : OutputSlot{std::make_unique (NUM_CONNECTIONS, Connections::fill())} + { } + }; + using asset::Pipe; using asset::PPipe; using asset::Struct; @@ -175,11 +194,11 @@ namespace test { modelPorts_.push_back (ModelPort(pipeB)); // prepare corresponding placeholder DataSink (a fake active output connection) - UNIMPLEMENTED ("need mock/fake OutputSlot"); -#if false //////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1410 : disabled code to disentangle BufferProvider implementation - dataSinks_.emplace_back().activate (std::make_shared()); - dataSinks_.emplace_back().activate (std::make_shared()); -#endif /////////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1410 : (end) disabled code + FakeSlot fakeSlot; + dataSinks_.clear(); + lib::explore(fakeSlot.getOpenedSinks()) + .effuse (dataSinks_); + // Note: keeps FakeSlot alive (due to embedded ref-count)... } diff --git a/tests/test.conf b/tests/test.conf index 9695c65e1..b5ce5580f 100755 --- a/tests/test.conf +++ b/tests/test.conf @@ -1,4 +1,4 @@ LOGSUPPRESS='^\(\*\*[0-9]*\*\* \)\?[0-9]\{10,\}[:!] \(TRACE\|INFO\|NOTICE\|WARNING\|ERR\|TODO\|PLANNED\|FIXME\|DEPRECATED\|UNIMPLEMENTED\|RESOURCE_ANNOUNCE\|RESOURCE_ENTER\|RESOURCE_STATE\|RESOURCE_LEAVE\):' -LIMIT_CPU=10 +LIMIT_CPU=25 LIMIT_VSZ=$((8 * 1014 * 1024)) diff --git a/tests/vault/mem/buffer-provider-load-test.cpp b/tests/vault/mem/buffer-provider-load-test.cpp index 8e3c8438e..eeef3bc24 100644 --- a/tests/vault/mem/buffer-provider-load-test.cpp +++ b/tests/vault/mem/buffer-provider-load-test.cpp @@ -54,10 +54,11 @@ namespace test { namespace { // ========== Test Setup ========== - const size_t MANY_THREADS = 100; ///< press concurrently const size_t FULL_LOAD_CORES = 4; ///< workers to use for a _full load run_ const size_t MAX_SCALE = 5; ///< maximum scale step for randomised buffer types + size_t MANY_THREADS = 100; ///< press concurrently with an overload of threads + const size_t NOT_SO_MANY = 16; ///< a _light variant_ for use in the standard test suite /** seed a per-thread random generator */ inline Random @@ -302,13 +303,15 @@ namespace test { * - the prime goal is to demonstrate correctness, balancing memory demand * mostly through lock-free queues, without loosing any allocation. */ - class BufferProviderLoad_test : public Test + class BufferProviderLoad_test : public Test { virtual void - run (Arg) + run (Arg arg) { seedRand(); + if ("quick" == firstTok (arg)) + MANY_THREADS = NOT_SO_MANY; demonstrate_EngineSetup(); verify_massiveOverload(); diff --git a/wiki/thinkPad.ichthyo.mm b/wiki/thinkPad.ichthyo.mm index 136bb0c5c..f0f327d7a 100644 --- a/wiki/thinkPad.ichthyo.mm +++ b/wiki/thinkPad.ichthyo.mm @@ -1,6 +1,6 @@ - + @@ -84243,6 +84243,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
+ @@ -87497,6 +87498,8 @@ Date:   Thu Apr 20 18:53:17 2023 +0200

+ + @@ -90356,7 +90359,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- + @@ -90369,6 +90372,219 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
+ + + + + + +

+ zeigt schmerzhaft den Stand des Lumiera-Projekts an +

+ +
+ + + +

+ In den ersten Jahren war ich so verloren, daß ich es nicht einmal geschafft habe, Komponenten-übergreifende Tests aufzubauen. Zumindest in der Hinsicht bin ich inzwischen weiter gekommen... +

+

+ Sobald es aber in Richtung Integration geht, stehe ich immer noch vor einer übergroßen Aufgabe: es fehlt an allen Enden. Die Problematik zeigt sich besonders scharf in den high-level-Services, für die ich top-down vorgehen muß: mir fehlt der induktive Gegenpart, und ich scheitere regelmäßig daran, geeignete Fakes / Mocks für Teilkomponenten bereitzustellen. Entweder die Fakes sind nicht brauchbar, oder ich stecke unendlich viel Zeit rein und sie sind danch trotzdem nicht brauchbar. Und dieses Muster wiederholt sich über verschiedenste Ansätze seit Jahren so. Ich vergesse oft sogar meine eigenen Integrations-Schemata. Nicht einmal in der Mindmap finde ich da eine klare Integrations-Route; nur Stückwerk, das ich irgendwann beiseite legen muß, und dann komplett vergesse. +

+

+ Was mich bisher gerettet hat, war meine sagenhafte Sturheit. Ich versuch's immer wieder, und wenigstens ein Stückwerk bleibt jeweils in irgend einer Ecke hängen.... +

+ +
+ +
+ + + + + + +

+ Den Rahmen habe ich seinerzeit durch Deduktion gewonnen, aus dem bis dahin entwickelten Verständnis des High-Level-Models. Dieser Rahmen scheint auch 10+ Jahre später immer noch valide zu sein (»Playback Vertical Slice«). +

+

+ Doch ich konnte keine Tests schreiben, um meine neuen Service-Komponenten wenigstens mal zu konstruieren — denn selbst die einfachsten inhaltlichen Zusammenhänge mußte ich mir „aus den Fingern saugen“. Dafür habe ich wieder auf das (grundsätzlich bewährte) Muster mit einem Fake-Kontext zurückgegriffen. In diesem Fall war das die DummyPlayConnection, welche alle fingierten Platzhalter bereitstellen sollte, damit man irgendwas zum Verschalten und Aktivieren hat. Damals habe ich, im weiteren Verlauf, auch einen SimulatedBuilderContext erfunden, um einen plausiblen Hintergrund bereitzustellen, gegen den ein geFAKEter Build-Vorgang aufgebaut werden könnte (letzteres ist dann aber nie passiert)... +

+ +
+ +
+ + + + +

+ Im Frühjahr 2023 waren bereits die Ziele für das »Playback Vertical Slice« absehbar. Jedoch wollte ich zunächst einige Altlasten aufräumen. Das waren damals meine letzten Monate bei der Baaderbank, denn ich hatte beschlossen, mich nun ganz dem Lumiera-Projekt zu widmen (und von Erspartem zu leben).... +

+

+ Besonders problematisch hatte ich das Monaden-Framework empfunden, das ich nebenbei in früheren Jahren hochgezogen hatte (fehlgeleitet vom allgemeinen Hype um funktionale Sprachen): Problematisch deshalb, weil der einzige Use-Case die Job-Planung war, welche im Rahmen dieses Frameworks gewissermaßen »freischwebend« aufgehängt war. Ich hatte Sorge, daß sich diese Struktur festsetzt. Daher habe ich den Ansatz gewählt, meinen später entwickelten Pipeline-Builder (dann umbenannt in IterExplorer) als neues Rückgrad zu verwenden, um die „eigentlich schon fertig entwickelte“ Job-Planung (was auch immer das heißen mag, denn es war freischwebend) auf dieser Basis zu re-implementieren. Und aus dem nun schon abgesteckten Horizont für das »Playback Vertical Slice« ergaben sich nun wesentlich konkretere Ankerpunkte, im Besonderen das JobTicket. +

+

+ Und um diese Strukturen aufbauen zu können, habe ich sukzessive eine Hierarchie von Mock-Implementierungen mit aufgebaut, welche jeweils (im Vorgriff auf das »Playback Vertical Slice«) die noch fehlenden Elemente der Segmentation, das Node-Network, und die Job-Invocation als Mocks mit Fake-Logik bereitstellen. Das bedeutet, diese Objekte lassen sich jeweils einfach direkt im Test-Scope konstruieren (enthalten also viel stillschweigende Magie), bieten dann die echten Interfaces, mit einem Fake-Verhalten, und außerdem zusätzliche Instrumentierung, um nach dem Test die Aufrufe zumindest gundlegend zu verifizieren. +

+

+ Dieses Framework konnte komplett abgeschlossen werden (das war wohl der erste solche Erfolg, und gab Hoffnung...); es stützt sich aber auf die Kontext-Hilfsmittel der DummyPlayConnection ab, und ist insofern doch immer noch etwas fragil. +

+ +
+ +
+
+ + + + + +

+ Test-Fake: DummyPlayConnection +

+ +
+ + + + + +
+ + + + +

+ Test-Framework: MockDispatcher +

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+ Diese Instrumentierung war heillos verknotet mit dem DiagnosticBufferSlot +

+ +
+ + + + + + + + + + + + + +

+ using DummyPlaybackSetup =  play::test::DummyPlayConnection<PlayTestFrames_Strategy>; +

+ +
+
+
+ + + + + + + + + + +

+ hier wurde ein vector<DataSink> aufgebaut +

+ +
+
+
+
+ + + + + + +

+ ...dann wäre es ja doch noch gut gewesen, daß ich die gestern überarbeitet habe... +

+ +
+ +
+ + + + +

+ einfach kopiert vom OutputAllocState_test +

+ +
+ +
+ + + + + + + + +

+ Ha: wir kommen vorwärts.... +

+

+ +

+

+ size_t getBufferSize() const  override { UNIMPLEMENTED ("getBufferSize()");  } +

+ +
+ +
+
+
+
+
+
+
+
@@ -119820,10 +120036,11 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension) + - + @@ -152015,7 +152232,7 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension) - +