Invocation: build a complex Render Node network for integration test

Using basically the same topology as in the preceding test, which focused on connectivity. However, in this case we retrieve actual processing functions from the »Test-Rand« ontology in order to perform hash-chaining computations on full data blocks. And, in addition, a »Param Agent Node« is used.
This commit is contained in:
Fischlurch 2025-02-19 19:37:55 +01:00
parent 6c2761b337
commit 93812d5a6d
5 changed files with 175 additions and 51 deletions

View file

@ -90,10 +90,10 @@ namespace test {
verify_TurnoutSystem() verify_TurnoutSystem()
{ {
Time nomTime{rani(10'000),0}; // drive test with a random »nominal Time« <10s with ms granularity Time nomTime{rani(10'000),0}; // drive test with a random »nominal Time« <10s with ms granularity
TurnoutSystem invoker{nomTime}; // a time spec is mandatory, all further parameters are optional TurnoutSystem turoSys{nomTime}; // a time spec is mandatory, all further parameters are optional
CHECK (invoker.getNomTime() == nomTime); // can access those basic params from within the render invocation. CHECK (turoSys.getNomTime() == nomTime); // can access those basic params from within the render invocation.
CHECK (invoker.getProcKey() == ProcessKey{}); CHECK (turoSys.getProcKey() == ProcessKey{});
/* == That's all required for basic usage. == */ /* == That's all required for basic usage. == */
@ -108,14 +108,14 @@ namespace test {
{// Build and connect extension storage block {// Build and connect extension storage block
auto dataBlock = // ...typically placed locally into a nested stack frame auto dataBlock = // ...typically placed locally into a nested stack frame
spec.makeBlockBuilder() spec.makeBlockBuilder()
.buildParamDataBlock(invoker); .buildParamDataBlock(turoSys);
invoker.attachChainBlock (dataBlock); // link extension data block into the TurnoutSystem turoSys.attachChainBlock (dataBlock); // link extension data block into the TurnoutSystem
CHECK (invoker.get(acc0) == someVal); // now able to retrieve data from extension block CHECK (turoSys.get(acc0) == someVal); // now able to retrieve data from extension block
invoker.detachChainBlock (dataBlock); turoSys.detachChainBlock (dataBlock);
} }
// base block continues to be usable... // base block continues to be usable...
CHECK (invoker.getNomTime() == nomTime); CHECK (turoSys.getNomTime() == nomTime);
} }

View file

@ -410,7 +410,7 @@ namespace test {
CHECK (not watch(nFilt).isSrc()); CHECK (not watch(nFilt).isSrc());
CHECK (watch(nSrc).getNodeSpec() == "Test:generate-◎"_expect ); CHECK (watch(nSrc).getNodeSpec() == "Test:generate-◎"_expect );
CHECK (watch(nFilt).getNodeSpec() == "Test:manipulate◁—Test:generate-◎"_expect ); CHECK (watch(nFilt).getNodeSpec() == "Test:manipulate◁—Test:generate-◎"_expect );
CHECK (watch(nFilt).getPortSpec(0) == "manipulate(TestFrame)"_expect ); CHECK (watch(nFilt).getPortSpec(0) == "manipulate(TestFrame)(TestFrame)"_expect );
// prepare to invoke this Node chain... // prepare to invoke this Node chain...
BufferProvider& provider = DiagnosticBufferProvider::build(); BufferProvider& provider = DiagnosticBufferProvider::build();
@ -468,7 +468,7 @@ namespace test {
CHECK (watch(nS1).getNodeSpec() == "Test:generate-◎"_expect ); CHECK (watch(nS1).getNodeSpec() == "Test:generate-◎"_expect );
CHECK (watch(nS2).getNodeSpec() == "Test:generate-◎"_expect ); CHECK (watch(nS2).getNodeSpec() == "Test:generate-◎"_expect );
CHECK (watch(nMix).getNodeSpec() == "Test:combine┉┉{Test:generate}"_expect ); CHECK (watch(nMix).getNodeSpec() == "Test:combine┉┉{Test:generate}"_expect );
CHECK (watch(nMix).getPortSpec(0) == "combine(TestFrame/2)"_expect ); CHECK (watch(nMix).getPortSpec(0) == "combine(TestFrame/2)(TestFrame)"_expect );
// prepare to invoke this Node chain... // prepare to invoke this Node chain...
BufferProvider& provider = DiagnosticBufferProvider::build(); BufferProvider& provider = DiagnosticBufferProvider::build();

View file

@ -21,8 +21,11 @@
#include "steam/engine/node-builder.hpp" #include "steam/engine/node-builder.hpp"
#include "steam/engine/test-rand-ontology.hpp" #include "steam/engine/test-rand-ontology.hpp"
#include "steam/engine/diagnostic-buffer-provider.hpp" #include "steam/engine/diagnostic-buffer-provider.hpp"
#include "lib/test/diagnostic-output.hpp"/////////////////TODO #include "steam/asset/meta/time-grid.hpp"
#include "lib/time/timequant.hpp"
#include "lib/time/timecode.hpp"
#include "lib/util.hpp" #include "lib/util.hpp"
#include "lib/test/diagnostic-output.hpp"/////////////////TODO
#include <array> #include <array>
@ -35,6 +38,10 @@ namespace steam {
namespace engine{ namespace engine{
namespace test { namespace test {
using lib::time::Time;
using lib::time::QuTime;
using lib::time::FrameNr;
using lib::time::FrameCnt;
@ -313,8 +320,9 @@ namespace test {
} }
/** @test TODO Invoke some render nodes as linked together /** @test TODO Invoke some render nodes as linked together
* @todo WIP 12/24 🔁 define ⟶ implement * @todo WIP 2/25 🔁 define ⟶ ✔ implement
*/ */
void void
trigger_node_port_invocation() trigger_node_port_invocation()
@ -323,70 +331,134 @@ namespace test {
auto testMan = testRand().setupManipulator(); auto testMan = testRand().setupManipulator();
auto testMix = testRand().setupCombinator(); auto testMix = testRand().setupCombinator();
/* ont::Flavr SRC_A = 10;
ont::Flavr SRC_B = 20;
// Prepare for Time-Quantisation --> Frame-# or Offset parameter
Symbol SECONDS_GRID = "grid_sec";
steam::asset::meta::TimeGrid::build (SECONDS_GRID, 1);
// Prepare a precomputed parameter for the complete tree
auto selectFrameNo = [&](TurnoutSystem& tuSys){ return FrameNr::quant (tuSys.getNomTime(), SECONDS_GRID); };
auto paramSpec = buildParamSpec()
.addSlot (selectFrameNo);
auto accFrameNo = paramSpec.makeAccessor<0>();
// Prepare mapping- and automation-functions
auto stepFilter = [] (FrameCnt id)-> ont::Param { return util::limited (10, -10 + id, 20); };
auto stepMixer = [] (FrameCnt id)-> double { return util::limited (0, + id, 50) / 50.0; };
// note: binds the accessor for the precomputed FrameNo-parameter
auto autoFilter = [=](TurnoutSystem& tuSys){ return stepFilter (tuSys.get (accFrameNo)); };
auto autoMixer = [=](TurnoutSystem& tuSys){ return stepMixer (tuSys.get (accFrameNo)); };
// A Node with two (source) ports // A Node with two (source) ports
ProcNode n1s{prepareNode("srcA") ProcNode n1s{prepareNode("srcA")
.preparePort() .preparePort()
.invoke("a(int)", src_op) .invoke(testGen.procID(), testGen.makeFun()) // params(frameNo, flavour)
.setParam(5) .closeParam<1>(SRC_A + 0) // --> flavour ≔ SRC_A + port#0
.retrieveParam(accFrameNo)
.completePort() .completePort()
.preparePort() .preparePort()
.invoke("b(int)", src_op) .invoke(testGen.procID(), testGen.makeFun())
.setParam(23) .closeParam<1>(SRC_A + 1) // --> flavour ≔ SRC_A + port#1
.retrieveParam(accFrameNo)
.completePort() .completePort()
.build()}; .build()};
// A node to add some "processing" to each data chain // A node to »filter« the data in chain-A
auto add1_op = [](int* src, int* res){ *res = 1 + *src; };
ProcNode n1f{prepareNode("filterA") ProcNode n1f{prepareNode("filterA")
.preparePort() .preparePort()
.invoke("a+1(int)(int)", add1_op) .invoke(testMan.procID(), testMan.makeFun())
.attachParamFun(autoFilter) // filter-param <-- autoFilter(frameNo)
.connectLead(n1s) .connectLead(n1s)
.completePort() .completePort()
.preparePort() .preparePort()
.invoke("b+1(int)(int)", add1_op) .invoke(testMan.procID(), testMan.makeFun())
.attachParamFun(autoFilter)
.connectLead(n1s) .connectLead(n1s)
.completePort() .completePort()
.build()}; .build()};
// Need a secondary source, this time with three ports
ProcNode n2s{prepareNode("srcB")
.preparePort()
.invoke("a(int)", src_op)
.setParam(7)
.completePort()
.preparePort()
.invoke("b(int)", src_op)
.setParam(13)
.completePort()
.preparePort()
.invoke("c(int)", src_op)
.setParam(17)
.completePort()
.build()};
// Wiring for the Mix, building up three ports
// Since the first source-chain has only two ports, // A secondary source Node, this time with three ports
// for the third result port we'll re-use the second source ProcNode n2s{prepareNode("srcB")
.preparePort()
.invoke(testGen.procID(), testGen.makeFun()) // params(frameNo, flavour)
.closeParam<1>(SRC_B + 0) // --> flavour ≔ SRC_B + port#0
.retrieveParam(accFrameNo)
.completePort()
.preparePort()
.invoke(testGen.procID(), testGen.makeFun())
.closeParam<1>(SRC_B + 1) // --> flavour ≔ SRC_B + port#1
.retrieveParam(accFrameNo)
.completePort()
.preparePort()
.invoke(testGen.procID(), testGen.makeFun())
.closeParam<1>(SRC_B + 2) // --> flavour ≔ SRC_B + port#2
.retrieveParam(accFrameNo)
.completePort()
.build()};
// Wiring for the Mix, building three ports,
// drawing from both source-chains
ProcNode mix{prepareNode("mix") ProcNode mix{prepareNode("mix")
.preparePort() .preparePort()
.invoke("a-mix(int/2)(int)", mix_op) .invoke(testMix.procID(), testMix.makeFun())
.attachParamFun(autoMixer) // mixer-param <-- autoMixer(frameNo)
.connectLead(n1f) .connectLead(n1f)
.connectLead(n2s) .connectLead(n2s)
.completePort() .completePort()
.preparePort() .preparePort()
.invoke("b-mix(int/2)(int)", mix_op) .invoke(testMix.procID(), testMix.makeFun())
.attachParamFun(autoMixer)
.connectLead(n1f) .connectLead(n1f)
.connectLead(n2s) .connectLead(n2s)
.completePort() .completePort()
.preparePort() .preparePort()
.invoke("c-mix(int/2)(int)", mix_op) .invoke(testMix.procID(), testMix.makeFun())
.connectLeadPort(n1f,1) .attachParamFun(autoMixer)
.connectLeadPort(n1f,1) // note: using 2nd port from chain-A, which only has two ports
.connectLead(n2s) .connectLead(n2s)
.completePort() .completePort()
.build()}; .build()};
*/
UNIMPLEMENTED ("operate some render nodes as linked together");
// Set a »Param-Agent«-Node on top to pre-compute the FrameNo
ProcNode parNode{prepareNode("Param")
.preparePort()
.computeParam(paramSpec)
.delegateLead(mix)
.completePort()
.preparePort()
.computeParam(paramSpec)
.delegateLead(mix)
.completePort()
.preparePort()
.computeParam(paramSpec)
.delegateLead(mix)
.completePort()
.build()};
BufferProvider& provider = DiagnosticBufferProvider::build();
const BuffDescr buffDescr = provider.getDescriptorFor(sizeof(TestFrame));
auto invoke = [&](Time nomTime, uint port)
{ // Sequence to invoke a Node...
BuffHandle buff = provider.lockBuffer(buffDescr);
CHECK (not buff.accessAs<TestFrame>().isValid());
buff = parNode.pull (port, buff, nomTime, ProcessKey{});
HashVal checksum = buff.accessAs<TestFrame>().getChecksum();
buff.release();
return checksum;
};
SHOW_EXPR(invoke(Time::ZERO, 1));
} }
}; };

View file

@ -225,8 +225,9 @@ namespace test {
string string
procSpec() procSpec()
{ {
return _Fmt{"%s(%s)"} return _Fmt{"%s(%s)(%s)"}
% (filter? util::showHash(filter):"") % (filter? util::showHash(filter):"")
% streamType
% streamType; % streamType;
} }
}; };
@ -254,7 +255,8 @@ namespace test {
string string
procSpec() procSpec()
{ {
return _Fmt{"(%s/2)"} return _Fmt{"(%s/2)(%s)"}
% streamType
% streamType; % streamType;
} }
}; };

View file

@ -105765,7 +105765,8 @@ StM_bind(Builder&lt;R1&gt; b1, Extension&lt;R1,R2&gt; extension)
<node CREATED="1739227684914" ID="ID_1108065190" MODIFIED="1739227736066" TEXT="und das scaffolding mu&#xdf; im Test-Code verst&#xe4;ndlich bleiben"> <node CREATED="1739227684914" ID="ID_1108065190" MODIFIED="1739227736066" TEXT="und das scaffolding mu&#xdf; im Test-Code verst&#xe4;ndlich bleiben">
<node CREATED="1739228198716" ID="ID_566097177" MODIFIED="1739228220611" TEXT="sollte also m&#xf6;glichst die Standard Node-Builder-F&#xe4;lle nutzen"/> <node CREATED="1739228198716" ID="ID_566097177" MODIFIED="1739228220611" TEXT="sollte also m&#xf6;glichst die Standard Node-Builder-F&#xe4;lle nutzen"/>
</node> </node>
<node CREATED="1739227741390" ID="ID_803165715" MODIFIED="1739227795410" TEXT="aber dieser 3.Testfall kann schon noch ein Zacken komplexer sein"> <node CREATED="1739227741390" ID="ID_803165715" MODIFIED="1739988451652" TEXT="aber dieser 3.Testfall kann schon noch ein Zacken komplexer sein">
<icon BUILTIN="forward"/>
<node CREATED="1739228229334" ID="ID_1295084534" MODIFIED="1739228240372" TEXT="es k&#xf6;nnte schon ein Integrationstest sein"/> <node CREATED="1739228229334" ID="ID_1295084534" MODIFIED="1739228240372" TEXT="es k&#xf6;nnte schon ein Integrationstest sein"/>
<node CREATED="1739228241556" ID="ID_481563144" MODIFIED="1739228254206" TEXT="...der diese ganze Prototyping-Phase besiegelt"/> <node CREATED="1739228241556" ID="ID_481563144" MODIFIED="1739228254206" TEXT="...der diese ganze Prototyping-Phase besiegelt"/>
<node CREATED="1739228257834" ID="ID_980216686" MODIFIED="1739228281727"> <node CREATED="1739228257834" ID="ID_980216686" MODIFIED="1739228281727">
@ -105784,9 +105785,10 @@ StM_bind(Builder&lt;R1&gt; b1, Extension&lt;R1,R2&gt; extension)
<icon BUILTIN="yes"/> <icon BUILTIN="yes"/>
<node CREATED="1739229080787" ID="ID_508301525" MODIFIED="1739229206584" TEXT="komplett &#xfc;ber das Turnout-System steuern"/> <node CREATED="1739229080787" ID="ID_508301525" MODIFIED="1739229206584" TEXT="komplett &#xfc;ber das Turnout-System steuern"/>
<node CREATED="1739229119334" ID="ID_144074931" MODIFIED="1739229138054" TEXT="es gibt ein einfaches Frame-Grid zur &#xdc;bersetzung in Frame-Nr"/> <node CREATED="1739229119334" ID="ID_144074931" MODIFIED="1739229138054" TEXT="es gibt ein einfaches Frame-Grid zur &#xdc;bersetzung in Frame-Nr"/>
<node CREATED="1739229092233" ID="ID_687505824" MODIFIED="1739229232886" TEXT="der ProcessingKey wird testhalber in den Mix-Parameter (0...100) &#xfc;bersetzt"/> <node CREATED="1739229092233" ID="ID_687505824" MODIFIED="1739984911570" TEXT="ausdedem leiten wir einen Offset-Parameter aus der Zeit ab"/>
<node CREATED="1739984916213" ID="ID_114154554" MODIFIED="1739984936785" TEXT="aus dem Offset errechnet der Param-Funktor dann den Mix-Parameter"/>
<node CREATED="1739229243685" ID="ID_1117664884" MODIFIED="1739229263638" TEXT="eine Param-Node demonstriert das Aufbauen synthetischer Parameter"/> <node CREATED="1739229243685" ID="ID_1117664884" MODIFIED="1739229263638" TEXT="eine Param-Node demonstriert das Aufbauen synthetischer Parameter"/>
<node COLOR="#338800" CREATED="1739229265043" FOLDED="true" ID="ID_1535044883" MODIFIED="1739914190981" TEXT="neues Feature: ein Param-Tupel im Builder partiell schlie&#xdf;en"> <node COLOR="#338800" CREATED="1739229265043" FOLDED="true" ID="ID_1535044883" MODIFIED="1739926309278" TEXT="neues Feature: ein Param-Tupel im Builder partiell schlie&#xdf;en">
<icon BUILTIN="forward"/> <icon BUILTIN="forward"/>
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#a60e65" CREATED="1739229289864" ID="ID_719879915" MODIFIED="1739902084019"> <node BACKGROUND_COLOR="#e0ceaa" COLOR="#a60e65" CREATED="1739229289864" ID="ID_719879915" MODIFIED="1739902084019">
<richcontent TYPE="NODE"><html> <richcontent TYPE="NODE"><html>
@ -106413,6 +106415,54 @@ StM_bind(Builder&lt;R1&gt; b1, Extension&lt;R1,R2&gt; extension)
</node> </node>
</node> </node>
</node> </node>
<node CREATED="1739926551533" ID="ID_1744658909" MODIFIED="1739926586194" TEXT="in Schleife aufrufen f&#xfc;r einen Zeitbereich">
<node CREATED="1739926858394" ID="ID_1310843645" MODIFIED="1739926874449" TEXT="jeweils einen Output-Buffer belegen"/>
<node CREATED="1739926876070" ID="ID_1858797669" MODIFIED="1739926959714" TEXT="einen zuf&#xe4;lligen Zeitpunkt ziehen"/>
<node CREATED="1739926961967" ID="ID_763806405" MODIFIED="1739926983118" TEXT="Node aufrufen und Checksumme abgreifen"/>
<node CREATED="1739926984356" ID="ID_1685710106" MODIFIED="1739926999349" TEXT="Sofort die Berechnung bare-bone-wiederholen"/>
<node BACKGROUND_COLOR="#f0d5c5" COLOR="#990033" CREATED="1739927022286" ID="ID_1569493230" MODIFIED="1739927035564" TEXT="was mache ich mit den drei Ports?">
<font NAME="SansSerif" SIZE="12"/>
<icon BUILTIN="help"/>
<node CREATED="1739974041862" ID="ID_152876783" MODIFIED="1739974050013" TEXT="M&#xf6;glichkeit-1 : random ausw&#xe4;hlen"/>
<node CREATED="1739974052425" ID="ID_922254600" MODIFIED="1739974061779" TEXT="M&#xf6;glichkeit-2 : zusammenf&#xfc;hren">
<node CREATED="1739974072046" ID="ID_599872890" MODIFIED="1739974079369" TEXT="das w&#xfc;rde den Test deutlich versch&#xe4;rfen"/>
</node>
</node>
</node>
</node>
</node>
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1739988475500" ID="ID_1619027230" MODIFIED="1739988486611" TEXT="Node-Setup aufbauen">
<icon BUILTIN="pencil"/>
<node COLOR="#338800" CREATED="1739988488649" ID="ID_1937491223" MODIFIED="1739988507621" TEXT="per copy-n-paste aus den vorhergehenden Testf&#xe4;llen">
<icon BUILTIN="ksmiletris"/>
</node>
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1739988510201" ID="ID_658104724" MODIFIED="1739988915058" TEXT="brauche Param-Node">
<icon BUILTIN="pencil"/>
<node CREATED="1739988517197" ID="ID_68703644" MODIFIED="1739988528313" TEXT="definiere eine Param-Spec mit (nur) einem Slot"/>
<node CREATED="1739988529403" ID="ID_11348533" MODIFIED="1739988557117" TEXT="dieser Slot macht die Time &#x27fc; Frame-Quantisierung"/>
<node CREATED="1739989858137" ID="ID_900282341" MODIFIED="1739989865292" TEXT="Accessor speichern"/>
<node CREATED="1739989866288" ID="ID_493861231" MODIFIED="1739989875603" TEXT="Accessor in nachgeschalteter Automation verwenden"/>
<node COLOR="#338800" CREATED="1739989877848" ID="ID_1873390720" MODIFIED="1739989886659" TEXT="Param-Node per NodeBuilder konstruieren">
<icon BUILTIN="button_ok"/>
</node>
</node>
<node COLOR="#338800" CREATED="1739989888437" ID="ID_1096325319" MODIFIED="1739989899313" TEXT="geht durch den Compiler">
<icon BUILTIN="button_ok"/>
</node>
<node CREATED="1739989900451" ID="ID_1706149148" MODIFIED="1739989907994" TEXT="Invocation....">
<node BACKGROUND_COLOR="#fafe99" COLOR="#fa002a" CREATED="1739989909161" ID="ID_1372911486" MODIFIED="1739989918255" TEXT="scheitert mit Exception">
<icon BUILTIN="broken-line"/>
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#690f14" CREATED="1739990057078" ID="ID_820424784" MODIFIED="1739990076825" TEXT="TestFrame: missing or corrupted metadata">
<icon BUILTIN="info"/>
</node>
</node>
<node BACKGROUND_COLOR="#f8f1cb" COLOR="#a50125" CREATED="1739989985056" ID="ID_1521515943" MODIFIED="1739990002894" TEXT="Beobachtung: 3 clean-up-Meldungen vom DiagnosticBufferProvider">
<icon BUILTIN="messagebox_warning"/>
<node CREATED="1739990004438" ID="ID_1675021686" MODIFIED="1739990013969" TEXT="wir verwenden nur zwei Instanzen">
<icon BUILTIN="info"/>
</node>
<node CREATED="1739990015547" ID="ID_75625440" MODIFIED="1739990022949" TEXT="woher kommt die 3.Meldung?"/>
</node>
</node> </node>
</node> </node>
</node> </node>