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

Reply via email to