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
EternalNucleus eternalNucleus;
Random::Seed defaultNucleus{defaultGen};
}
SeedNucleus::~SeedNucleus() { }
Random defaultGen{eternalNucleus};
Random entropyGen{entropyNucleus};
SeedNucleus&
seedFromDefaultGen()
{
return defaultNucleus;
}
SeedNucleus::~SeedNucleus() { }
void
randomiseRandomness()
@ -88,4 +95,5 @@ namespace lib {
defaultGen.reseed(entropyNucleus);
}
} // namespace lib

View file

@ -81,8 +81,29 @@ namespace lib {
/** inject controlled randomisation */
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.
*/
@ -106,6 +127,10 @@ namespace lib {
/** inject true randomness into the #defaultGen */
void randomiseRandomness();
/** draw seed another Generator from the default RandomSequencer */
SeedNucleus& seedFromDefaultGen();
/* ===== Implementation details ===== */

View file

@ -36,7 +36,7 @@
#include "lib/util.hpp"
#include <boost/algorithm/string.hpp>
#include <memory>
#include <optional>
#include <sstream>
#include <string>
#include <memory>
@ -48,12 +48,14 @@ namespace test {
using std::map;
using std::vector;
using std::optional;
using std::shared_ptr;
using boost::algorithm::trim;
using util::isnil;
using util::contains;
using util::typeStr;
using lib::SeedNucleus;
using lib::Random;
typedef map<string, Launcher*> TestMap;
@ -97,7 +99,22 @@ namespace 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;
}
@ -192,17 +209,19 @@ namespace test {
}
/** draw a new random seed from a common nucleus, and re-seed the default-Gen. */
void
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
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 CREATED="1509151309866" ID="ID_1109789284" MODIFIED="1576282358112" TEXT="sollte es als als Basis iter implementieren">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<head/>
<body>
<p>
...und die IterSource dann nur &#252;ber WrapIter definieren.
@ -16158,9 +16156,7 @@
<icon BUILTIN="button_ok"/>
<node CREATED="1523222214579" ID="ID_1568226158" MODIFIED="1576282358106" STYLE="fork" TEXT="Feststellung: keine Status-R&#xfc;ckmeldung">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<head/>
<body>
<p>
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="1485546285407" ID="ID_1129769291" MODIFIED="1557498707221">
<richcontent TYPE="NODE"><html>
<head>
</head>
<head/>
<body>
<p>
mu&#223; kein <b>Manager</b>&#160;sein
@ -17498,9 +17492,7 @@
</node>
<node CREATED="1486751116251" HGAP="140" ID="ID_113005643" MODIFIED="1557498707222" VSHIFT="61">
<richcontent TYPE="NODE"><html>
<head>
</head>
<head/>
<body>
<p>
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="1664308866802" ID="ID_993068829" MODIFIED="1664308941471" TEXT="die Alloc-Zuteiltung f&#xfc;r die Kiner passiert irgendwann sp&#xe4;ter">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<head/>
<body>
<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
@ -46521,9 +46511,7 @@
<node CREATED="1448078308690" ID="ID_185716114" MODIFIED="1518487921085" TEXT="Aktionen">
<node CREATED="1448078344541" ID="ID_1781183546" MODIFIED="1576282358016" TEXT="Subjekt einer Aktion">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<head/>
<body>
<p>
...ist <i>immer</i>&#160;ein <b>tangible</b>
@ -46885,9 +46873,7 @@
</body>
</html></richcontent>
<richcontent TYPE="NOTE"><html>
<head>
</head>
<head/>
<body>
<p>
ganz bewu&#223;t verzichten wir darauf,
@ -47469,9 +47455,7 @@
<icon BUILTIN="button_ok"/>
<node CREATED="1455895664140" ID="ID_639070488" MODIFIED="1455895669295">
<richcontent TYPE="NODE"><html>
<head>
</head>
<head/>
<body>
<p>
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="1455928275316" ID="ID_702364156" MODIFIED="1512926191928">
<richcontent TYPE="NODE"><html>
<head>
</head>
<head/>
<body>
<p>
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="1455931008750" ID="ID_643730154" MODIFIED="1575133327378" TEXT="Mutator enth&#xe4;lt Closures">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<head/>
<body>
<p>
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">
<icon BUILTIN="yes"/>
<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?">
<icon BUILTIN="help"/>
<node CREATED="1731247770927" ID="ID_886572495" MODIFIED="1731247837299" TEXT="sieht nach Dependency-Injection aus und ist effektiv global">
<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>