Details
-
Improvement
-
Status: Closed
-
Major - P3
-
Resolution: Fixed
-
None
-
Fully Compatible
-
Repl 2019-08-26
-
0
Description
The Math.random() function in JavaScript isn't seeded, so the mongo shell provides a Random.rand() function that can be seeded using the Random.srand() function. The C++ function that underlies Random.rand() uses the rand_r() function on POSIX systems and the rand() function on Windows. The RAND_MAX value used to scale the results to be a floating-point number between 0 and 1 is platform-specific. This means that even for the same seed, the pseudo-random number generator will produce different sequences on Windows, Linux, and OS X.
The Random.setRandomSeed() function seeds the pseudo-random number generator with a value generated by a SecureRandom instance. Some of our more complex JavaScript integration tests use a pseudo-random number generator to vary the test data and/or operations to make the test case more interesting each time. Having the pseudo-random number generator in the mongo shell be platform-independent would greatly aid in reproducing the exact test setup without requiring using the same platform as what the test failure occurred on.
#if !defined(_WIN32)
|
ThreadLocalValue<unsigned int> _randomSeed; |
#endif
|
|
BSONObj JSSrand(const BSONObj& a, void* data) { |
unsigned int seed; |
// grab the least significant bits of either the supplied argument or |
// a random number from SecureRandom. |
if (a.nFields() == 1 && a.firstElement().isNumber()) |
seed = static_cast<unsigned int>(a.firstElement().numberLong()); |
else { |
std::unique_ptr<SecureRandom> rand(SecureRandom::create()); |
seed = static_cast<unsigned int>(rand->nextInt64()); |
}
|
#if !defined(_WIN32)
|
_randomSeed.set(seed);
|
#else
|
srand(seed); |
#endif
|
return BSON("" << static_cast<double>(seed)); |
}
|
|
BSONObj JSRand(const BSONObj& a, void* data) { |
uassert(12519, "rand accepts no arguments", a.nFields() == 0); |
unsigned r;
|
#if !defined(_WIN32)
|
r = rand_r(&_randomSeed.getRef());
|
#else
|
r = rand(); |
#endif
|
return BSON("" << double(r) / (double(RAND_MAX) + 1)); |
}
|