On 25/03/21 13:05 +0000, Jonathan Wakely wrote:
On 24/03/21 22:48 +0100, François Dumont wrote:
I still need to find out why, when running test on
__gnu_debug::basic_string after the std::basic_string one, the
generate(sz) call always returns sz.
The "random" generator will always return the same sequence of numbers
every time you run the test. It uses a default-constructed
std::mt19937 without a seed, so the sequence of random numbers is 100%
reproducable.
This patch allows those random engines to be seeded, so that we can test
with different random numbers.
It's already found a bug:
GLIBCXX_SEED_TEST_RNG=-941908610 make check
RUNTESTFLAGS=conformance.exp=23_containers/forward_list/requirements/exception/generation_prohibited.cc
Using random seed 3353058686
FAIL:
23_containers/forward_list/requirements/exception/generation_prohibited.cc
execution test
We need to investigate that.
Any objections to pushing this?
commit 172f60c7067155beaa3c8c768677f7c26b7d4da9
Author: Jonathan Wakely <jwak...@redhat.com>
Date: Thu Mar 25 13:51:08 2021
libstdc++: Allow seeding random engines in testsuite
The testsuite utilities that use random numbers use a
default-constructed mersenne_twister_engine, meaning the values are
reproducable. This adds support for seeding them, controlledby an
environment variable. Defining GLIBCXX_SEED_TEST_RNG=val in the
environment will cause the engines to be seeded with atoi(val) if that
is non-zero, or with a value read from std::random_device otherwise.
libstdc++-v3/ChangeLog:
* testsuite/util/exception/safety.h (setup_base::generate):
Support seeding random engine.
* testsuite/util/testsuite_containergen.h (test_containers):
Likewise.
diff --git a/libstdc++-v3/testsuite/util/exception/safety.h b/libstdc++-v3/testsuite/util/exception/safety.h
index 6c91e740e0d..16a784e4908 100644
--- a/libstdc++-v3/testsuite/util/exception/safety.h
+++ b/libstdc++-v3/testsuite/util/exception/safety.h
@@ -22,6 +22,8 @@
#include <testsuite_container_traits.h>
#include <ext/throw_allocator.h>
+#include <cstdlib> // getenv, atoi
+#include <cstdio> // printf, fflush
// Container requirement testing.
namespace __gnu_test
@@ -33,27 +35,34 @@ namespace __gnu_test
typedef std::uniform_int_distribution<size_type> distribution_type;
typedef std::mt19937 engine_type;
+ static engine_type
+ get_engine()
+ {
+ engine_type engine;
+ if (const char* v = std::getenv("GLIBCXX_SEED_TEST_RNG"))
+ {
+ // A single seed value is much smaller than the mt19937 state size,
+ // but we're not trying to be cryptographically secure here.
+ unsigned s = std::atoi(v);
+ if (s == 0)
+ s = std::random_device{}();
+ std::printf("Using random seed %u\n", s);
+ std::fflush(stdout);
+ engine.seed(s);
+ }
+ return engine;
+ }
+
// Return randomly generated integer on range [0, __max_size].
static size_type
generate(size_type __max_size)
{
- // Make the generator static...
- const engine_type engine;
- const distribution_type distribution;
- static auto generator = std::bind(distribution, engine,
- std::placeholders::_1);
+ using param_type = typename distribution_type::param_type;
- // ... but set the range for this particular invocation here.
- const typename distribution_type::param_type p(0, __max_size);
- size_type random = generator(p);
- if (random < distribution.min() || random > distribution.max())
- std::__throw_out_of_range_fmt(__N("setup_base::generate\n"
- "random number generated is: %zu "
- "out of range [%zu, %zu]\n"),
- (size_t)random,
- (size_t)distribution.min(),
- (size_t)distribution.max());
- return random;
+ // Make the engine and distribution static...
+ static engine_type engine = get_engine();
+ static distribution_type distribution;
+ return distribution(engine, param_type{0, __max_size});
}
// Given an instantiating type, return a unique value.
diff --git a/libstdc++-v3/testsuite/util/testsuite_containergen.h b/libstdc++-v3/testsuite/util/testsuite_containergen.h
index a2156733ec6..5bbe620d59d 100644
--- a/libstdc++-v3/testsuite/util/testsuite_containergen.h
+++ b/libstdc++-v3/testsuite/util/testsuite_containergen.h
@@ -20,6 +20,8 @@
#include <testsuite_container_traits.h>
#include <random>
+#include <cstdlib> // getenv, atoi
+#include <cstdio> // printf, fflush
namespace __gnu_test
{
@@ -63,6 +65,18 @@ namespace __gnu_test
{
std::mt19937_64 random_gen;
+ if (const char* v = std::getenv("GLIBCXX_SEED_TEST_RNG"))
+ {
+ // A single seed value is much smaller than the mt19937 state size,
+ // but we're not trying to be cryptographically secure here.
+ unsigned s = std::atoi(v);
+ if (s == 0)
+ s = std::random_device{}();
+ std::printf("Using random seed %u\n", s);
+ std::fflush(stdout);
+ random_gen.seed(s);
+ }
+
#ifdef SIMULATOR_TEST
int loops = 10;
#else