Library: implement test access to hidden global RandomSequencer

this seems to be the ''classical problem situation''
where a »clean« Dependency-Injection would require to waste storage
for a pointer to the same global resource in each and every distinct test class.

Since the Test-Suite is effectively global — even more so now due to
the reliance on "the" global `RandomSequencer` (PNRG) — we'll have to
bite the bullet and access a global static variable hidden behind teh scenes.
This commit is contained in:
Fischlurch 2024-11-10 16:22:46 +01:00
parent c13d6d45f4
commit cffa2cd6c2
4 changed files with 98 additions and 39 deletions

View file

@ -72,14 +72,21 @@ namespace lib {
/// @todo this one should somehow be configurable /// @todo this one should somehow be configurable
EternalNucleus eternalNucleus; EternalNucleus eternalNucleus;
Random::Seed defaultNucleus{defaultGen};
} }
SeedNucleus::~SeedNucleus() { }
Random defaultGen{eternalNucleus}; Random defaultGen{eternalNucleus};
Random entropyGen{entropyNucleus}; Random entropyGen{entropyNucleus};
SeedNucleus&
seedFromDefaultGen()
{
return defaultNucleus;
}
SeedNucleus::~SeedNucleus() { }
void void
randomiseRandomness() randomiseRandomness()
@ -88,4 +95,5 @@ namespace lib {
defaultGen.reseed(entropyNucleus); defaultGen.reseed(entropyNucleus);
} }
} // namespace lib } // namespace lib

View file

@ -81,8 +81,29 @@ namespace lib {
/** inject controlled randomisation */ /** inject controlled randomisation */
void reseed (SeedNucleus&); void reseed (SeedNucleus&);
/** wrapper to use this generator for seeding other generators */
class Seed;
}; };
template<class GEN>
class RandomSequencer<GEN>::Seed
: public SeedNucleus
{
RandomSequencer& srcGen_;
public:
Seed(RandomSequencer& parent)
: srcGen_{parent}
{ }
uint64_t
getSeed() override
{
return srcGen_.u64();
}
};
/** /**
* PRNG engine to use by default: 64bit mersenne twister. * PRNG engine to use by default: 64bit mersenne twister.
*/ */
@ -106,6 +127,10 @@ namespace lib {
/** inject true randomness into the #defaultGen */ /** inject true randomness into the #defaultGen */
void randomiseRandomness(); void randomiseRandomness();
/** draw seed another Generator from the default RandomSequencer */
SeedNucleus& seedFromDefaultGen();
/* ===== Implementation details ===== */ /* ===== Implementation details ===== */

View file

@ -36,7 +36,7 @@
#include "lib/util.hpp" #include "lib/util.hpp"
#include <boost/algorithm/string.hpp> #include <boost/algorithm/string.hpp>
#include <memory> #include <optional>
#include <sstream> #include <sstream>
#include <string> #include <string>
#include <memory> #include <memory>
@ -48,12 +48,14 @@ namespace test {
using std::map; using std::map;
using std::vector; using std::vector;
using std::optional;
using std::shared_ptr; using std::shared_ptr;
using boost::algorithm::trim; using boost::algorithm::trim;
using util::isnil; using util::isnil;
using util::contains; using util::contains;
using util::typeStr; using util::typeStr;
using lib::SeedNucleus;
using lib::Random; using lib::Random;
typedef map<string, Launcher*> TestMap; typedef map<string, Launcher*> TestMap;
@ -97,7 +99,22 @@ namespace test {
(*group)[testID] = test; (*group)[testID] = test;
} }
}; };
class SuiteSeedNucleus
: public SeedNucleus
{
optional<uint64_t> fixedSeed_;
uint64_t
getSeed() override
{
return fixedSeed_? *fixedSeed_
: lib::entropyGen.u64();
}
};
/* ===== global implementation state ===== */
SuiteSeedNucleus suiteSeed;
Registry testcases; Registry testcases;
} }
@ -192,17 +209,19 @@ namespace test {
} }
/** draw a new random seed from a common nucleus, and re-seed the default-Gen. */
void void
Test::seedRand() Test::seedRand()
{ {
UNIMPLEMENTED ("draw a new random seed from a common nucleus, and re-seed the default-Gen"); lib::defaultGen.reseed (suiteSeed);
} }
/** build a dedicated new RandomGen, seeded from the default-Gen */
Random Random
Test::makeRandGen() Test::makeRandGen()
{ {
UNIMPLEMENTED ("build a dedicated new RandomGen, seeded from the default-Gen"); return Random{lib::seedFromDefaultGen()};
} }

View file

@ -14875,9 +14875,7 @@
</node> </node>
<node CREATED="1509151309866" ID="ID_1109789284" MODIFIED="1576282358112" TEXT="sollte es als als Basis iter implementieren"> <node CREATED="1509151309866" ID="ID_1109789284" MODIFIED="1576282358112" TEXT="sollte es als als Basis iter implementieren">
<richcontent TYPE="NOTE"><html> <richcontent TYPE="NOTE"><html>
<head> <head/>
</head>
<body> <body>
<p> <p>
...und die IterSource dann nur &#252;ber WrapIter definieren. ...und die IterSource dann nur &#252;ber WrapIter definieren.
@ -16158,9 +16156,7 @@
<icon BUILTIN="button_ok"/> <icon BUILTIN="button_ok"/>
<node CREATED="1523222214579" ID="ID_1568226158" MODIFIED="1576282358106" STYLE="fork" TEXT="Feststellung: keine Status-R&#xfc;ckmeldung"> <node CREATED="1523222214579" ID="ID_1568226158" MODIFIED="1576282358106" STYLE="fork" TEXT="Feststellung: keine Status-R&#xfc;ckmeldung">
<richcontent TYPE="NOTE"><html> <richcontent TYPE="NOTE"><html>
<head> <head/>
</head>
<body> <body>
<p> <p>
das mag &#252;berraschend klingen, das mag &#252;berraschend klingen,
@ -16878,9 +16874,7 @@
<node CREATED="1485457370310" ID="ID_1931452525" MODIFIED="1557498707221" TEXT="GtkWindow sind v&#xf6;llig ausreichend"/> <node CREATED="1485457370310" ID="ID_1931452525" MODIFIED="1557498707221" TEXT="GtkWindow sind v&#xf6;llig ausreichend"/>
<node CREATED="1485546285407" ID="ID_1129769291" MODIFIED="1557498707221"> <node CREATED="1485546285407" ID="ID_1129769291" MODIFIED="1557498707221">
<richcontent TYPE="NODE"><html> <richcontent TYPE="NODE"><html>
<head> <head/>
</head>
<body> <body>
<p> <p>
mu&#223; kein <b>Manager</b>&#160;sein mu&#223; kein <b>Manager</b>&#160;sein
@ -17498,9 +17492,7 @@
</node> </node>
<node CREATED="1486751116251" HGAP="140" ID="ID_113005643" MODIFIED="1557498707222" VSHIFT="61"> <node CREATED="1486751116251" HGAP="140" ID="ID_113005643" MODIFIED="1557498707222" VSHIFT="61">
<richcontent TYPE="NODE"><html> <richcontent TYPE="NODE"><html>
<head> <head/>
</head>
<body> <body>
<p> <p>
Br&#252;cke: <i>gemeinsamer</i>&#160;Controller Br&#252;cke: <i>gemeinsamer</i>&#160;Controller
@ -18756,9 +18748,7 @@
<node CREATED="1664308730228" ID="ID_964535587" MODIFIED="1664308762363" TEXT="zum Zeitpunkt der Alloc-Zuteilung haben die nested-children noch keine Allokation"/> <node CREATED="1664308730228" ID="ID_964535587" MODIFIED="1664308762363" TEXT="zum Zeitpunkt der Alloc-Zuteilung haben die nested-children noch keine Allokation"/>
<node CREATED="1664308866802" ID="ID_993068829" MODIFIED="1664308941471" TEXT="die Alloc-Zuteiltung f&#xfc;r die Kiner passiert irgendwann sp&#xe4;ter"> <node CREATED="1664308866802" ID="ID_993068829" MODIFIED="1664308941471" TEXT="die Alloc-Zuteiltung f&#xfc;r die Kiner passiert irgendwann sp&#xe4;ter">
<richcontent TYPE="NOTE"><html> <richcontent TYPE="NOTE"><html>
<head> <head/>
</head>
<body> <body>
<p> <p>
...was normalerweise ja auch irrelevant ist, denn per Voraussetzung sollte ein Container die Werte von seinen Kindern bereits bei seiner initialen Meldung ber&#252;cksichtigt haben ...was normalerweise ja auch irrelevant ist, denn per Voraussetzung sollte ein Container die Werte von seinen Kindern bereits bei seiner initialen Meldung ber&#252;cksichtigt haben
@ -46521,9 +46511,7 @@
<node CREATED="1448078308690" ID="ID_185716114" MODIFIED="1518487921085" TEXT="Aktionen"> <node CREATED="1448078308690" ID="ID_185716114" MODIFIED="1518487921085" TEXT="Aktionen">
<node CREATED="1448078344541" ID="ID_1781183546" MODIFIED="1576282358016" TEXT="Subjekt einer Aktion"> <node CREATED="1448078344541" ID="ID_1781183546" MODIFIED="1576282358016" TEXT="Subjekt einer Aktion">
<richcontent TYPE="NOTE"><html> <richcontent TYPE="NOTE"><html>
<head> <head/>
</head>
<body> <body>
<p> <p>
...ist <i>immer</i>&#160;ein <b>tangible</b> ...ist <i>immer</i>&#160;ein <b>tangible</b>
@ -46885,9 +46873,7 @@
</body> </body>
</html></richcontent> </html></richcontent>
<richcontent TYPE="NOTE"><html> <richcontent TYPE="NOTE"><html>
<head> <head/>
</head>
<body> <body>
<p> <p>
ganz bewu&#223;t verzichten wir darauf, ganz bewu&#223;t verzichten wir darauf,
@ -47469,9 +47455,7 @@
<icon BUILTIN="button_ok"/> <icon BUILTIN="button_ok"/>
<node CREATED="1455895664140" ID="ID_639070488" MODIFIED="1455895669295"> <node CREATED="1455895664140" ID="ID_639070488" MODIFIED="1455895669295">
<richcontent TYPE="NODE"><html> <richcontent TYPE="NODE"><html>
<head> <head/>
</head>
<body> <body>
<p> <p>
aber was dann wenn out-of-order aber was dann wenn out-of-order
@ -47765,9 +47749,7 @@
<node CREATED="1470772440180" ID="ID_836603881" MODIFIED="1470772503839" TEXT="verify match with next src position"/> <node CREATED="1470772440180" ID="ID_836603881" MODIFIED="1470772503839" TEXT="verify match with next src position"/>
<node CREATED="1455928275316" ID="ID_702364156" MODIFIED="1512926191928"> <node CREATED="1455928275316" ID="ID_702364156" MODIFIED="1512926191928">
<richcontent TYPE="NODE"><html> <richcontent TYPE="NODE"><html>
<head> <head/>
</head>
<body> <body>
<p> <p>
then <i>move</i>&#160;into target then <i>move</i>&#160;into target
@ -47983,9 +47965,7 @@
<node CREATED="1455930971027" ID="ID_1070880241" MODIFIED="1455930980789" TEXT="ist in jedem Einzelfall anders"/> <node CREATED="1455930971027" ID="ID_1070880241" MODIFIED="1455930980789" TEXT="ist in jedem Einzelfall anders"/>
<node CREATED="1455931008750" ID="ID_643730154" MODIFIED="1575133327378" TEXT="Mutator enth&#xe4;lt Closures"> <node CREATED="1455931008750" ID="ID_643730154" MODIFIED="1575133327378" TEXT="Mutator enth&#xe4;lt Closures">
<richcontent TYPE="NOTE"><html> <richcontent TYPE="NOTE"><html>
<head> <head/>
</head>
<body> <body>
<p> <p>
Mutator enth&#228;lt die Bindung auf die konkreten Daten Mutator enth&#228;lt die Bindung auf die konkreten Daten
@ -57406,8 +57386,35 @@
<node BACKGROUND_COLOR="#fdfdcf" COLOR="#ff0000" CREATED="1731208300347" ID="ID_157287510" MODIFIED="1731208332129" TEXT="tats&#xe4;chlich aber brauche ich den Nucleus in der einzelnen Test-Subklasse"> <node BACKGROUND_COLOR="#fdfdcf" COLOR="#ff0000" CREATED="1731208300347" ID="ID_157287510" MODIFIED="1731208332129" TEXT="tats&#xe4;chlich aber brauche ich den Nucleus in der einzelnen Test-Subklasse">
<icon BUILTIN="yes"/> <icon BUILTIN="yes"/>
<node CREATED="1731209451725" ID="ID_774812395" MODIFIED="1731209472619" TEXT="die Suite ist mit dem Nucleus parametrisiert"/> <node CREATED="1731209451725" ID="ID_774812395" MODIFIED="1731209472619" TEXT="die Suite ist mit dem Nucleus parametrisiert"/>
<node BACKGROUND_COLOR="#f0d5c5" COLOR="#990033" CREATED="1731209473303" ID="ID_1979397339" MODIFIED="1731209485557" TEXT="vielleicht l&#xe4;&#xdf;t sich das sogar als Funktor darstellen?"> <node CREATED="1731247770927" ID="ID_886572495" MODIFIED="1731247837299" TEXT="sieht nach Dependency-Injection aus und ist effektiv global">
<icon BUILTIN="help"/> <richcontent TYPE="NOTE"><html>
<head/>
<body>
<p>
das ist der klassische Fall, in dem eine &#187;saubere&#171; Repr&#228;sentation in der einzelnen Testklasse zu massiver Speicherverschwendung f&#252;hrt, weil jede Testklasse einen redundanten Pointer auf den gleichen globalen Kontext bekommt
</p>
</body>
</html>
</richcontent>
</node>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1731251266883" ID="ID_326274878" MODIFIED="1731251304272" TEXT="au&#xdf;erdem brauchen wir einen Seed-Wrapper um einen bestehenden Generator">
<icon BUILTIN="yes"/>
<node CREATED="1731251305887" ID="ID_889654920" MODIFIED="1731251314393" TEXT="und das ist ein &#xe4;hnlich gelagertes Problem"/>
<node CREATED="1731251315053" ID="ID_667235767" MODIFIED="1731251348353" TEXT="das Design mit dem SeedNucleus als virtuelles Interface hat seine Schw&#xe4;chen">
<icon BUILTIN="smily_bad"/>
</node>
<node CREATED="1731251351030" ID="ID_1463644758" MODIFIED="1731251389711" TEXT="die VTable mu&#xdf; f&#xfc;r jede Instanz erneut generiert werden, die als Quelle dienen soll"/>
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#690f14" CREATED="1731251390572" ID="ID_1815150553" MODIFIED="1731251416786" TEXT="damit droht die gleiche Explosion der Subklassen, die ich vermeiden wollte">
<icon BUILTIN="messagebox_warning"/>
</node>
<node CREATED="1731251418640" ID="ID_912804843" MODIFIED="1731251431186" TEXT="Ausweg: nur die M&#xf6;glichkeit anbieten">
<icon BUILTIN="idea"/>
<node CREATED="1731251432526" ID="ID_1542226880" MODIFIED="1731251441316" TEXT="als Adapter / Innere Klasse"/>
<node CREATED="1731251444252" ID="ID_1693694322" MODIFIED="1731251453990" TEXT="erwartungsgem&#xe4;&#xdf; wird das (fast) nie gebraucht"/>
<node COLOR="#338800" CREATED="1731251454674" ID="ID_481118676" MODIFIED="1731251486430" TEXT="nur eine feste globale (versteckte) Instanz : der defaultNucleus">
<icon BUILTIN="button_ok"/>
</node>
</node> </node>
</node> </node>
</node> </node>