Adds a Random class to support --gtest_shuffle (by Josh Kelley); Makes the scons script build in a deterministic order (by Zhanyong Wan).
This commit is contained in:
parent
e5373af0cb
commit
2534ae201e
@ -748,6 +748,28 @@ String GetCurrentOsStackTraceExceptTop(UnitTest* unit_test, int skip_count);
|
||||
// A helper for suppressing warnings on unreachable code in some macros.
|
||||
bool AlwaysTrue();
|
||||
|
||||
// A simple Linear Congruential Generator for generating random
|
||||
// numbers with a uniform distribution. Unlike rand() and srand(), it
|
||||
// doesn't use global state (and therefore can't interfere with user
|
||||
// code). Unlike rand_r(), it's portable. An LCG isn't very random,
|
||||
// but it's good enough for our purposes.
|
||||
class Random {
|
||||
public:
|
||||
static const UInt32 kMaxRange = 1u << 31;
|
||||
|
||||
explicit Random(UInt32 seed) : state_(seed) {}
|
||||
|
||||
void Reseed(UInt32 seed) { state_ = seed; }
|
||||
|
||||
// Generates a random number from [0, range). Crashes if 'range' is
|
||||
// 0 or greater than kMaxRange.
|
||||
UInt32 Generate(UInt32 range);
|
||||
|
||||
private:
|
||||
UInt32 state_;
|
||||
GTEST_DISALLOW_COPY_AND_ASSIGN_(Random);
|
||||
};
|
||||
|
||||
} // namespace internal
|
||||
} // namespace testing
|
||||
|
||||
|
@ -155,11 +155,6 @@ class SConstructHelper:
|
||||
'/OPT:NOICF',
|
||||
]
|
||||
)
|
||||
# Tell SCons to build depdendencies in random order (apart from the
|
||||
# actual dependency order). This helps ensure we don't introduce
|
||||
# build files that "accidentally" work sometimes (e.g. when you are
|
||||
# building some targets) and not other times.
|
||||
debug_env.SetOption('random', 1)
|
||||
return debug_env
|
||||
|
||||
def MakeWinOptimizedEnvironment(self, base_environment, name):
|
||||
|
21
src/gtest.cc
21
src/gtest.cc
@ -260,6 +260,25 @@ GTEST_DEFINE_bool_(
|
||||
|
||||
namespace internal {
|
||||
|
||||
// Generates a random number from [0, range), using a Linear
|
||||
// Congruential Generator (LCG). Crashes if 'range' is 0 or greater
|
||||
// than kMaxRange.
|
||||
UInt32 Random::Generate(UInt32 range) {
|
||||
// These constants are the same as are used in glibc's rand(3).
|
||||
state_ = (1103515245U*state_ + 12345U) % kMaxRange;
|
||||
|
||||
GTEST_CHECK_(range > 0)
|
||||
<< "Cannot generate a number in the range [0, 0).";
|
||||
GTEST_CHECK_(range <= kMaxRange)
|
||||
<< "Generation of a number in [0, " << range << ") was requested, "
|
||||
<< "but this can only generate numbers in [0, " << kMaxRange << ").";
|
||||
|
||||
// Converting via modulus introduces a bit of downward bias, but
|
||||
// it's simple, and a linear congruential generator isn't too good
|
||||
// to begin with.
|
||||
return state_ % range;
|
||||
}
|
||||
|
||||
// g_help_flag is true iff the --help flag or an equivalent form is
|
||||
// specified on the command line.
|
||||
static bool g_help_flag = false;
|
||||
@ -3815,7 +3834,7 @@ static void TearDownEnvironment(Environment* env) { env->TearDown(); }
|
||||
// considered to be failed, but the rest of the tests will still be
|
||||
// run. (We disable exceptions on Linux and Mac OS X, so the issue
|
||||
// doesn't apply there.)
|
||||
// When parameterized tests are enabled, it explands and registers
|
||||
// When parameterized tests are enabled, it expands and registers
|
||||
// parameterized tests first in RegisterParameterizedTests().
|
||||
// All other functions called from RunAllTests() may safely assume that
|
||||
// parameterized tests are ready to be counted and run.
|
||||
|
@ -183,6 +183,7 @@ using testing::internal::TestProperty;
|
||||
using testing::internal::TestResult;
|
||||
using testing::internal::TestResultAccessor;
|
||||
using testing::internal::ThreadLocal;
|
||||
using testing::internal::UInt32;
|
||||
using testing::internal::Vector;
|
||||
using testing::internal::WideStringToUtf8;
|
||||
using testing::internal::kTestTypeIdInGoogleTest;
|
||||
@ -499,6 +500,49 @@ TEST(WideStringToUtf8Test, ConcatenatesCodepointsCorrectly) {
|
||||
}
|
||||
#endif // !GTEST_WIDE_STRING_USES_UTF16_
|
||||
|
||||
// Tests the Random class.
|
||||
|
||||
TEST(RandomDeathTest, GeneratesCrashesOnInvalidRange) {
|
||||
testing::internal::Random random(42);
|
||||
EXPECT_DEATH_IF_SUPPORTED(
|
||||
random.Generate(0),
|
||||
"Cannot generate a number in the range \\[0, 0\\)");
|
||||
EXPECT_DEATH_IF_SUPPORTED(
|
||||
random.Generate(testing::internal::Random::kMaxRange + 1),
|
||||
"Generation of a number in \\[0, 2147483649\\) was requested, "
|
||||
"but this can only generate numbers in \\[0, 2147483648\\)");
|
||||
}
|
||||
|
||||
TEST(RandomTest, GeneratesNumbersWithinRange) {
|
||||
const UInt32 kRange = 10000;
|
||||
testing::internal::Random random(12345);
|
||||
for (int i = 0; i < 10; i++) {
|
||||
EXPECT_LT(random.Generate(kRange), kRange) << " for iteration " << i;
|
||||
}
|
||||
|
||||
testing::internal::Random random2(testing::internal::Random::kMaxRange);
|
||||
for (int i = 0; i < 10; i++) {
|
||||
EXPECT_LT(random2.Generate(kRange), kRange) << " for iteration " << i;
|
||||
}
|
||||
}
|
||||
|
||||
TEST(RandomTest, RepeatsWhenReseeded) {
|
||||
const int kSeed = 123;
|
||||
const int kArraySize = 10;
|
||||
const UInt32 kRange = 10000;
|
||||
UInt32 values[kArraySize];
|
||||
|
||||
testing::internal::Random random(kSeed);
|
||||
for (int i = 0; i < kArraySize; i++) {
|
||||
values[i] = random.Generate(kRange);
|
||||
}
|
||||
|
||||
random.Reseed(kSeed);
|
||||
for (int i = 0; i < kArraySize; i++) {
|
||||
EXPECT_EQ(values[i], random.Generate(kRange)) << " for iteration " << i;
|
||||
}
|
||||
}
|
||||
|
||||
// Tests the Vector class template.
|
||||
|
||||
// Tests Vector::Clear().
|
||||
|
Loading…
Reference in New Issue
Block a user