Library: add new API for random seeding

...to the base-class of all tests
 * `seedRand()` shall be invoked by every test using randomisation
   * it will draw a new seed for the implicit default-PRNG
   * it will document this seed value
   * but when a seed was given via cmdline, it will inject that instead
 * `makeRandGen()` will create a new dedicated generator instance,
   attached (by seeding) to the current default-PRNG

It is not clear yet how to pass the actual `SeedNucleus`, which
for obvious reasons must be maintained by the `test::Suite`
This commit is contained in:
Fischlurch 2024-11-10 00:40:20 +01:00
parent 92bc044e9e
commit c13d6d45f4
9 changed files with 83 additions and 63 deletions

View file

@ -36,8 +36,8 @@
#ifndef TESTHELPER_RUN_H
#define TESTHELPER_RUN_H
#include "steam/common.hpp"
#include "include/logging.h"
#include "lib/error.hpp"
#include "lib/random.hpp"
#include "lib/test/suite.hpp"
#include "lib/util.hpp"
@ -62,8 +62,11 @@ namespace test {
class Test
{
public:
virtual ~Test() {}
virtual void run(Arg arg) = 0;
virtual ~Test() = default;
virtual void run(Arg arg) = 0;
void seedRand();
lib::Random makeRandGen();
};
@ -72,7 +75,7 @@ namespace test {
class Launcher
{
public:
virtual ~Launcher() {}
virtual ~Launcher() = default;
virtual shared_ptr<Test> makeInstance() =0;
};

View file

@ -27,13 +27,12 @@
#include "include/logging.h"
#include "lib/hash-standard.hpp"
#include "lib/error.hpp"
#include "lib/format-cout.hpp"
#include "lib/test/suite.hpp"
#include "lib/test/run.hpp"
#include "lib/cmdline.hpp"
#include "lib/error.hpp"
#include "lib/random.hpp"
#include "lib/util.hpp"
#include <boost/algorithm/string.hpp>
@ -55,6 +54,7 @@ namespace test {
using util::isnil;
using util::contains;
using util::typeStr;
using lib::Random;
typedef map<string, Launcher*> TestMap;
typedef shared_ptr<TestMap> PTestMap;
@ -192,6 +192,21 @@ namespace test {
}
void
Test::seedRand()
{
UNIMPLEMENTED ("draw a new random seed from a common nucleus, and re-seed the default-Gen");
}
Random
Test::makeRandGen()
{
UNIMPLEMENTED ("build a dedicated new RandomGen, seeded from the default-Gen");
}
/** run all testcases contained in this Suite.
* The first argument in the commandline, if present,
* will select one single testcase with a matching ID.
@ -244,10 +259,13 @@ namespace test {
/** print to stdout an enumeration of all testcases in this suite,
* in a format suitable for use with Cehteh's ./test.sh
* in a format suitable for use with Cehteh's ./test.sh
* @todo this function war rarely used and is kind of broken by the fact
* that Nobug-assertions terminate the program instead of throwing,
* rendering the feature to integrate output mostly useless.
*/
void
Suite::describe ()
Suite::describe()
{
lib::Cmdline noCmdline("");
PTestMap tests = testcases.getGroup(groupID_);

View file

@ -90,7 +90,8 @@
//#include "vault/gear/block-flow.hpp"
//#include "vault/gear/activity-lang.hpp"
//#include "lib/symbol.hpp"
#include "lib/nocopy.hpp"
#include "lib/time/timevalue.hpp"
#include "lib/nocopy.hpp"
#include "lib/util.hpp"
#include "lib/format-cout.hpp"

View file

@ -30,6 +30,7 @@
#include "lib/util.hpp"
#include <cstdlib>
#include <climits>
#include <memory>
using test::Test;

View file

@ -29,6 +29,7 @@
#include "lib/format-cout.hpp"
#include "lib/ios-savepoint.hpp"
#include <iomanip>
#include <string>

View file

@ -25,6 +25,7 @@
*/
#include "lib/symbol.hpp"
#include "lib/test/run.hpp"
#include "lib/meta/util.hpp"
#include "lib/meta/typelist.hpp"

View file

@ -25,6 +25,7 @@
*/
#include "lib/symbol.hpp"
#include "lib/test/run.hpp"
#include "lib/meta/util.hpp"

View file

@ -32,6 +32,7 @@
#include <boost/lexical_cast.hpp>
#include <functional>
#include <memory>
#include <string>
@ -42,7 +43,8 @@ namespace test{
using boost::lexical_cast;
using util::isSameObject;
using util::isnil;
using std::shared_ptr;
using std::function;
using std::string;
using std::bind;

View file

@ -14781,9 +14781,7 @@
<node CREATED="1508809741418" ID="ID_1013369537" MODIFIED="1509070755705" TEXT="Verdacht: irgendwo move mit dangling storage?"/>
<node CREATED="1509070756935" ID="ID_1331980374" MODIFIED="1576282358114" TEXT="nein! Nur eine Referenz vom Temporary">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<head/>
<body>
<p>
...merke
@ -15005,9 +15003,7 @@
<icon BUILTIN="broken-line"/>
<node CREATED="1515298602326" ID="ID_13919667" MODIFIED="1515298692557" TEXT="R&#xfc;ckgabe ist Value...">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<head/>
<body>
<p>
...und das hei&#223;t.
@ -16596,9 +16592,7 @@
<icon BUILTIN="help"/>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1487208182655" ID="ID_1220225827" MODIFIED="1518487921076">
<richcontent TYPE="NODE"><html>
<head>
</head>
<head/>
<body>
<p>
brauche ein <i>aktuelles</i>&#160;Modell-Element
@ -18879,9 +18873,7 @@
<node CREATED="1664486367173" ID="ID_203408708" MODIFIED="1664486380447" TEXT="und das Widget mu&#xdf; dann intern daf&#xfc;r sorgen, da&#xdf; es seinen Content da reinbekommt"/>
<node CREATED="1664486398329" ID="ID_1798174878" MODIFIED="1664486423313" TEXT="GTK wird selber niemals ein Widget &quot;stauchen&quot;">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<head/>
<body>
<p>
wenn, dann mu&#223; man das dynamisch implementieren...
@ -21603,9 +21595,7 @@
</node>
<node CREATED="1575561914272" ID="ID_1374284644" MODIFIED="1575561939182">
<richcontent TYPE="NODE"><html>
<head>
</head>
<head/>
<body>
<p>
fragt sich <i>von wem </i>wir dieses Hookable f&#252;r einen andern Typ bekommen
@ -25914,9 +25904,7 @@
<icon BUILTIN="forward"/>
<node CREATED="1540346412629" ID="ID_1434445651" MODIFIED="1557498707226">
<richcontent TYPE="NODE"><html>
<head>
</head>
<head/>
<body>
<p>
abstrahiert den Zugang zum <i>zugeh&#246;rigen Widget</i>
@ -57123,9 +57111,9 @@
<node COLOR="#435e98" CREATED="1729979325607" ID="ID_677674501" MODIFIED="1729979344958" TEXT="useFrameTable"/>
</node>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1730904143330" ID="ID_25783469" MODIFIED="1730904275397" TEXT="#1378 controlled random seed for tests">
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1730904143330" ID="ID_25783469" MODIFIED="1731205578435" TEXT="#1378 controlled random seed for tests">
<linktarget COLOR="#c4145f" DESTINATION="ID_25783469" ENDARROW="Default" ENDINCLINATION="6546;452;" ID="Arrow_ID_1019579428" SOURCE="ID_1500320757" STARTARROW="None" STARTINCLINATION="1769;146;"/>
<icon BUILTIN="flag-yellow"/>
<icon BUILTIN="pencil"/>
<node CREATED="1730931170413" HGAP="34" ID="ID_480480032" MODIFIED="1731119671920" TEXT="diverse Zweifel &lt;random&gt; betreffend" VSHIFT="44">
<arrowlink COLOR="#968bb0" DESTINATION="ID_607929754" ENDARROW="Default" ENDINCLINATION="-1401;152;" ID="Arrow_ID_682771755" STARTARROW="None" STARTINCLINATION="-1300;91;"/>
<icon BUILTIN="messagebox_warning"/>
@ -57248,8 +57236,7 @@
</li>
</ul>
</body>
</html>
</richcontent>
</html></richcontent>
</node>
<node CREATED="1731118532378" ID="ID_1249119445" MODIFIED="1731118574223">
<richcontent TYPE="NODE"><html>
@ -57259,8 +57246,7 @@
<u>damit wird klar</u>: das aktuelle SeedNucleus-Interface is <i>zun&#228;chst gut genug</i>&#160;(KISS)
</p>
</body>
</html>
</richcontent>
</html></richcontent>
<icon BUILTIN="idea"/>
</node>
</node>
@ -57297,8 +57283,8 @@
<node CREATED="1731118832589" ID="ID_732098473" MODIFIED="1731119409643" TEXT="brauche eine reseed()-Operation um einen Seed wiederherzustellen">
<node CREATED="1731118937690" ID="ID_876325939" MODIFIED="1731118961825" TEXT="der C++ - Standard bietet de-facto diese Operation auf allen enthaltenen Engines"/>
<node CREATED="1731118962605" ID="ID_1749223447" MODIFIED="1731118982278" TEXT="notfalls k&#xf6;nnte man aber auch ein in-place Destroy / re-Construct machen"/>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1731119637225" ID="ID_955411605" MODIFIED="1731119733338" TEXT="reseed()-Operation auf unser RandomSequencer-Interface &#xfc;bernehmen">
<icon BUILTIN="flag-yellow"/>
<node COLOR="#338800" CREATED="1731119637225" ID="ID_955411605" MODIFIED="1731205571101" TEXT="reseed()-Operation auf unser RandomSequencer-Interface &#xfc;bernehmen">
<icon BUILTIN="button_ok"/>
</node>
<node CREATED="1731187281299" ID="ID_1511041306" MODIFIED="1731187308599" TEXT="daf&#xfc;r f&#xe4;llt die randomise()-Operation weg">
<icon BUILTIN="yes"/>
@ -57325,7 +57311,7 @@
</node>
</node>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1731119762690" ID="ID_1637478235" MODIFIED="1731119834979" TEXT="Entwurf: lib::test::Test::useRandom()">
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1731119762690" ID="ID_1637478235" MODIFIED="1731205613988" TEXT="Entwurf: Zufalls-Generator in lib::test::Test">
<icon BUILTIN="idea"/>
<node CREATED="1731119858173" ID="ID_1447736454" MODIFIED="1731119870919" TEXT="verwendet einen eingebetteten SeedNucleus"/>
<node COLOR="#5b280f" CREATED="1731120003113" ID="ID_1177767927" MODIFIED="1731176382320" TEXT="jeder Aufruf erzeugt ein neues RandomSequencer-Objekt">
@ -57408,6 +57394,24 @@
</node>
</node>
</node>
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1731208110582" ID="ID_991761175" MODIFIED="1731208117297" TEXT="Implementierung">
<icon BUILTIN="pencil"/>
<node BACKGROUND_COLOR="#f0d5c5" COLOR="#990033" CREATED="1731208120755" ID="ID_1347870232" MODIFIED="1731208132196" TEXT="wo wird der SeedNucleus angesiedelt?">
<icon BUILTIN="help"/>
<node CREATED="1731208158296" ID="ID_1282528205" MODIFIED="1731208169202" TEXT="von der Struktur her geh&#xf6;rt der in die Suite"/>
<node BACKGROUND_COLOR="#f8f1cb" COLOR="#a50125" CREATED="1731208171087" ID="ID_913749404" MODIFIED="1731208197128" TEXT="zur Ausf&#xfc;hrungszeit ist aber der Options-Parser schon nicht mehr zug&#xe4;nglich">
<icon BUILTIN="messagebox_warning"/>
</node>
<node CREATED="1731208198122" ID="ID_556038851" MODIFIED="1731208233810" TEXT="also w&#xe4;re das wohl als Konstruktor-Parametrisierung explizit zu setzen"/>
<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>
</node>
</node>
</node>
</node>
</node>
</node>
@ -91852,8 +91856,7 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
nun den Umbau anzugehen
</p>
</body>
</html>
</richcontent>
</html></richcontent>
<arrowlink COLOR="#6f2328" DESTINATION="ID_442258905" ENDARROW="Default" ENDINCLINATION="366;-47;" ID="Arrow_ID_1067356199" STARTARROW="None" STARTINCLINATION="5;52;"/>
</node>
</node>
@ -91925,8 +91928,7 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
der Header sollte optional sein (und hinter den Daten liegen), aber die Gegenwart eines Headers sollte explizit erkennbar sein
</p>
</body>
</html>
</richcontent>
</html></richcontent>
</node>
<node CREATED="1730900658104" ID="ID_1382506504" MODIFIED="1730900815598" TEXT="brauche Daten-Pr&#xfc;fsumme auch nach Manipulation">
<richcontent TYPE="NOTE"><html>
@ -138181,8 +138183,7 @@ std::cout &lt;&lt; tmpl.render({&quot;what&quot;, &quot;World&quot;}) &lt;&lt; s
2015-04-16</time></a>
</p>
</body>
</html>
</richcontent>
</html></richcontent>
<node CREATED="1730927161676" ID="ID_1870117805" MODIFIED="1730927175433" TEXT="die Autorin von PCG">
<arrowlink COLOR="#a9b4c1" DESTINATION="ID_595255954" ENDARROW="Default" ENDINCLINATION="228;0;" ID="Arrow_ID_1247304219" STARTARROW="None" STARTINCLINATION="228;25;"/>
<icon BUILTIN="idea"/>
@ -138196,8 +138197,7 @@ std::cout &lt;&lt; tmpl.render({&quot;what&quot;, &quot;World&quot;}) &lt;&lt; s
&#187;Simple C++&#171; Dimitrij Mijoski&#160;&#160;2021-11<br /><br />
</p>
</body>
</html>
</richcontent>
</html></richcontent>
</node>
<node CREATED="1730921869936" ID="ID_897784412" MODIFIED="1730921874684" TEXT="Streitpunkte">
<node CREATED="1730921876360" ID="ID_1711092381" MODIFIED="1730922258576" TEXT="Wahrscheinlichkeit bestimmte (feste) Zahlen zu ziehen">
@ -138208,8 +138208,7 @@ std::cout &lt;&lt; tmpl.render({&quot;what&quot;, &quot;World&quot;}) &lt;&lt; s
Letztlich werde ich aus der Diskussion zu diesem Aspekt nicht klug. Zumindest aber sind nicht alle m&#246;glichen Ergebniszahlen sofort zu Beginn gleich wahrscheinlich; es wird auch immer wieder ein Zusammenhang impliziert mit dem Umfang des <i>internal state</i>, der beim Mersenne-Twister extrem gro&#223; ist (624 int). Festzuhalten bleibt, da&#223; ein PRNG eine gweisse <b>predictability</b> haben kann, und das hei&#223;t, man sollte sich niemals auf das Auftreten / nicht-auftreten bestimmter Zahlen verlassen. Die Eigenschaften zeigen sich erst im statistischen Durchschnitt. Will man eine echte Zufallszahl, mu&#223; man eine echte Zufallszahl nehmen
</p>
</body>
</html>
</richcontent>
</html></richcontent>
</node>
<node CREATED="1730922284177" ID="ID_1548923616" MODIFIED="1730922467479" TEXT="Der Zustandsraum f&#xfc;r m&#xf6;gliche Sequenzen ist durch den Seed begrenzt">
<richcontent TYPE="NOTE"><html>
@ -138219,8 +138218,7 @@ std::cout &lt;&lt; tmpl.render({&quot;what&quot;, &quot;World&quot;}) &lt;&lt; s
...das hei&#223;t, nur wenn man tats&#228;chlich mit 624 ints seeded, erreicht man alle m&#246;glichen Sequenzen. Wobei aber bereits zwei ints (2^64) f&#252;r die meisten praktischen Probleme mehr als genug sein sollte; problematisch wird das nur bei Simulationen und L&#246;sungssuche durch Monte-Carlo.
</p>
</body>
</html>
</richcontent>
</html></richcontent>
</node>
<node CREATED="1730922568811" ID="ID_1106941071" MODIFIED="1730922708295" TEXT="std::seed_seq mu&#xdf; eine Heap-Allokation machen">
<richcontent TYPE="NOTE"><html>
@ -138230,8 +138228,7 @@ std::cout &lt;&lt; tmpl.render({&quot;what&quot;, &quot;World&quot;}) &lt;&lt; s
...darauf wird nirgends hingeweisen, und es gibt ein Interface, um einen Allokator einzuf&#252;hren. Kritisiert wird auch generell das Interface f&#252;r std::seed_seq &#8212; die Stichhaltigkeit dieser Kritik kann ich nicht beurteilen (anders als da&#223; es nicht &#8222;einfach&#8220; ist)
</p>
</body>
</html>
</richcontent>
</html></richcontent>
<icon BUILTIN="clanbomber"/>
</node>
<node CREATED="1730922731765" ID="ID_648439878" MODIFIED="1730923152857" TEXT="die Standard-Implementierungen bieten keine gute Auswahl">
@ -138242,8 +138239,7 @@ std::cout &lt;&lt; tmpl.render({&quot;what&quot;, &quot;World&quot;}) &lt;&lt; s
Es l&#228;uft darauf hinaus, den Mersenne-Twister in Form von std::mt19937 als &#187;default&#171; zu verwenden. Und der ist langsam, braucht viel Speicher und ist kompliziert zu seeden. Au&#223;erdem sind die gebotenen Distributions-Funktionen allesamt nicht portabel (sondern implementation-defined). Leider werden dann in der Diskussion (Reddit, Stackoverflow) diverse Favoriten genannt, f&#252;r die es dann stets auch wieder (ohne tiefere Expertise schwer nachpr&#252;fbare) Einw&#228;nde gibt. Die einzige Alternative, gegen die niemand wirklich etwas einzuwenden hatte (au&#223;er da&#223; es angeblich modernere / schnellere / coolere Alternativen g&#228;be) ist der allseits bekannte Jenkins jsf32
</p>
</body>
</html>
</richcontent>
</html></richcontent>
</node>
</node>
</node>
@ -143271,8 +143267,7 @@ unsigned int ThreadIdAsInt = *static_cast&lt;unsigned int*&gt;(static_cast&lt;vo
...und zwar f&#252;r den Fall, da&#223; jemand eine in-sich geschlossene Quelldatei aus dem Projekt heraus kopiert; alle Hinweise direkt in der Datei erh&#246;hen die Wahrscheinlichkeit, da&#223; die Lizenzinformation nicht verlorengeht. Hinweise &#252;ber Haftungsausschlu&#223; und wo man die Lizenz bekommt sind nur eine Empfehlung und haben keine rechtliche Wirkung. Diese ensteht durch die Ver&#246;ffentlichung, und dazu gen&#252;gt ein Statement im Root des Quellbaumes. Diese Einsch&#228;tzung geht sogar aus den Hinweisen im Appendix der GPL selber hervor. Auch auf den Seiten der FSF wird zwar stark nahegelegt, den kopletten Pr&#228;ambel-Text einzuf&#252;gen, aber es handelt sich daber ohne jeden Zweifel nur um eine Empfehlung
</p>
</body>
</html>
</richcontent>
</html></richcontent>
</node>
<node CREATED="1731199834786" ID="ID_1475726687" MODIFIED="1731200681377" TEXT="ein Copyright-Claim mit initialem Jahr">
<richcontent TYPE="NOTE"><html>
@ -143282,8 +143277,7 @@ unsigned int ThreadIdAsInt = *static_cast&lt;unsigned int*&gt;(static_cast&lt;vo
Wenn dieser Claim in jeder Quelldatei eigens gepflegt wird, erh&#246;ht das die Sicherheit der Verbindung von Copyright und Lizensierung. Allerdings auch nur, wenn dieser Claim korrekt ist. Es gen&#252;gt, den Zeitpunkt der allerersten signifikanten Sch&#246;pfung und Ver&#246;ffentlichung aufzuf&#252;hren, denn alle weiteren Beitr&#228;ge sind dann bereits durch die GPL gedeckt. Empfohlen wird, sp&#228;tere signifikante Beitr&#228;ge gesondert mit Jahreszahl aufzuf&#252;hren. Jahresbereiche sind nur sinnvoll, wenn in jedem der eingeschlossenen Jahre tats&#228;chlich etwas beigetragen wurde.
</p>
</body>
</html>
</richcontent>
</html></richcontent>
</node>
<node CREATED="1731199847273" ID="ID_555409518" MODIFIED="1731200959379" TEXT="ein Statement zur Lizenz">
<richcontent TYPE="NOTE"><html>
@ -143293,8 +143287,7 @@ unsigned int ThreadIdAsInt = *static_cast&lt;unsigned int*&gt;(static_cast&lt;vo
Notwendig w&#228;re das nicht, aber hilfreich, wenn die Datei herausgel&#246;st wird. Es gen&#252;gt ein Hinweis auf die exakte Form der Lizenz. Man kenn &quot;this Program&quot; durch den expliziten Namen ersetzen. Man kann dazu noch auf die COPYING-Datei verweisen. Alle weiteren Infos, z.B. ein Haftungsausschlu&#223; sind nur empfohlen und &#228;ndern nicht die rechtliche Wirkung der Lizenz, unter der ver&#246;ffentlicht wurde
</p>
</body>
</html>
</richcontent>
</html></richcontent>
</node>
</node>
<node CREATED="1731200854085" ID="ID_1145620984" MODIFIED="1731200878179" TEXT="Vorschlag">
@ -143338,8 +143331,7 @@ unsigned int ThreadIdAsInt = *static_cast&lt;unsigned int*&gt;(static_cast&lt;vo
<font face="Monospaced">*/ </font>
</p>
</body>
</html>
</richcontent>
</html></richcontent>
<icon BUILTIN="edit"/>
</node>
</node>