From 5e9b115283be895518e4408e4f3de805cbcdc8aa Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Mon, 4 Dec 2023 23:31:21 +0100 Subject: [PATCH] Chain-Load: verify correct operation of planning logic - test setup without actual scheduler - wire the callbacks such to verify + all nodes are touched + levels are processed to completion + the planning chunk stops at the expected level + all node dependencies are properly reported through the callbacks --- tests/vault/gear/test-chain-load-test.cpp | 77 ++++++++++++++++++++++- tests/vault/gear/test-chain-load.hpp | 24 +++---- wiki/thinkPad.ichthyo.mm | 45 ++++++++----- 3 files changed, 118 insertions(+), 28 deletions(-) diff --git a/tests/vault/gear/test-chain-load-test.cpp b/tests/vault/gear/test-chain-load-test.cpp index caf785e78..5601a596d 100644 --- a/tests/vault/gear/test-chain-load-test.cpp +++ b/tests/vault/gear/test-chain-load-test.cpp @@ -927,10 +927,16 @@ namespace test { - /** @test TODO setup for running a chain-load as scheduled task + /** @test setup for running a chain-load as scheduled task * - running an isolated Node recalculation * - dispatch of this recalculation packaged as render job - * @todo WIP 12/23 🔁 define ⟶ 🔁 implement + * - verify the planning job, which processes nodes in batches; + * for the test, the callback-λ will not invoke the Scheduler, + * but rather use the instructions to create clone nodes; + * if all nodes are processed and all dependency connections + * properly reported through the callback-λ, then calculating + * this clone network should reproduce the original hash. + * @todo WIP 12/23 ✔ define ⟶ ✔ implement */ void verify_scheduling_setup() @@ -986,6 +992,73 @@ namespace test { job3.triggerJob(); // Hash calculations are *not* idempotent CHECK (e.hash != 0x6A5924BA3389D7C); + + + // use the »planing job« to organise the calculations: + // Let the callbacks create a clone — which at the end should generate the same hash + array clone; + size_t lastTouched(-1); + size_t lastLevel(-1); + bool shallContinue{false}; + auto getNodeIdx = [&](Node* n) { return n - &nodes[0]; }; + + // callback-λ rigged for test.... + // Instead of invoking the Scheduler, here we replicate the node structure + auto disposeStep = [&](size_t idx, size_t level) + { + Node& n = clone[idx]; + n.clear(); + n.level = level; + lastTouched = idx; + }; + auto setDependency = [&](Node* pred, Node* succ) + { + size_t predIdx = getNodeIdx(pred); + size_t succIdx = getNodeIdx(succ); + // replicate this relation into the clone array + clone[predIdx].addSucc(clone[succIdx]); + }; + auto continuation = [&](size_t levelDone, bool work_left) + { + lastLevel = levelDone; + shallContinue = work_left; + }; + // build a JobFunctor for the planning step(s) + RandomChainPlanFunctor<16> planJob{nodes.front(), nodes.size() + ,disposeStep + ,setDependency + ,continuation}; + Job jobP1{planJob + ,InvocationInstanceID() + ,planJob.encodeLevel(1)}; + Job jobP2{planJob + ,InvocationInstanceID() + ,planJob.encodeLevel(3)}; + + jobP1.triggerJob(); + CHECK (lastTouched = 2); + CHECK (lastLevel = 1); + Node* lastN = &clone[lastTouched]; + CHECK (lastN->level == lastLevel); + CHECK ( isnil (lastN->succ)); + CHECK (not isnil (lastN->pred)); + CHECK (shallContinue); + + jobP2.triggerJob(); + CHECK (lastTouched = 3); + CHECK (lastLevel = 3); + lastN = &clone[lastTouched]; + CHECK (lastN->level == 2); + CHECK (lastN->level < lastLevel); + CHECK ( isnil (lastN->succ)); + CHECK (not isnil (lastN->pred)); + CHECK (not shallContinue); + + // all clone nodes should be wired properly now + CHECK (lastN->hash == 0); + for (Node& n : clone) + n.calculate(); + CHECK (lastN->hash == 0x6A5924BA3389D7C); } }; diff --git a/tests/vault/gear/test-chain-load.hpp b/tests/vault/gear/test-chain-load.hpp index 764a5921a..ed4ac2e67 100644 --- a/tests/vault/gear/test-chain-load.hpp +++ b/tests/vault/gear/test-chain-load.hpp @@ -1136,31 +1136,31 @@ namespace test { using Node = typename TestChainLoad::Node; function scheduleCalcJob_; - function markDependency_; + function markDependency_; function continuation_; - size_t chunkSize_; size_t maxCnt_; - Node* nodes_; - size_t currIdx_{0}; + + size_t currIdx_{0}; // Note: this test-JobFunctor is statefull public: template - RandomChainPlanFunctor(size_t chunkSize, size_t maxLevel, - Node& nodeArray, + RandomChainPlanFunctor(Node& nodeArray, size_t nodeCnt, CAL&& schedule, DEP&& markDepend, CON&& continuation) : scheduleCalcJob_{forward (schedule)} - , markDependency_{forward (markDepend)} - , continuation_{continuation} - , chunkSize_{chunkSize} - , maxCnt_{maxLevel} + , markDependency_{forward (markDepend)} + , continuation_{forward (continuation)} + , maxCnt_{nodeCnt} , nodes_{&nodeArray} { } - /** render job invocation to trigger one Node recalculation */ + /** render job invocation to trigger one batch of scheduling; + * the installed callback-λ should actually place a job with + * RandomChainCalcFunctor for each node, and also inform the + * Scheduler about dependency relations between jobs. */ void invokeJobOperation (JobParameter param) override { @@ -1171,7 +1171,7 @@ namespace test { if (n->level > targetLevel) break; scheduleCalcJob_(currIdx_, n->level); - for (Node* pred: n.pred) + for (Node* pred: n->pred) markDependency_(pred,n); } continuation_(targetLevel, currIdx_ < maxCnt_); diff --git a/wiki/thinkPad.ichthyo.mm b/wiki/thinkPad.ichthyo.mm index 2ae04b792..9a23f9eba 100644 --- a/wiki/thinkPad.ichthyo.mm +++ b/wiki/thinkPad.ichthyo.mm @@ -57667,8 +57667,7 @@ - + @@ -100610,13 +100609,18 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
+ + + + + - - + + @@ -100635,7 +100639,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- + @@ -100675,8 +100679,8 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- - + + @@ -100892,16 +100896,17 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- + - + - + + @@ -100935,9 +100940,9 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- + - + @@ -100953,8 +100958,20 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- - + + + + + + + + + + + + + +