diff options
| author | Nils Maier <maierman@web.de> | 2014-12-30 18:17:44 +0100 |
|---|---|---|
| committer | Nils Maier <maierman@web.de> | 2015-01-20 22:37:24 +0100 |
| commit | 81bdd5f61a8f8da53e22d68190be700902b7dbae (patch) | |
| tree | f706934a5e5e208d8d09490d216fe03f10b38654 /test | |
| parent | 747131a06c1f1d92a5312a103f4446fabedb6cf7 (diff) | |
Revise getRandom facilities
Use one of the following to provide random bytes:
- Windows CryptGenRandom
- Linux getrandom (syscall interface to urandom, without nasty corner
cases such as file descriptor exhaustion or re-linked /dev/urandom)
- std::device_random (C++ random device, which usually will be urandom)
This also equalizes util::getRandom and SimpleRandomizer (the former
will now use the latter) instead of having essentially two different
PRNG interfaces with potentially different quality.
Closes GH-320
Diffstat (limited to 'test')
| -rw-r--r-- | test/UtilTest.cc | 48 |
1 files changed, 46 insertions, 2 deletions
diff --git a/test/UtilTest.cc b/test/UtilTest.cc index 65b1d9c5..513aeefc 100644 --- a/test/UtilTest.cc +++ b/test/UtilTest.cc @@ -1,5 +1,6 @@ #include "util.h" +#include <cmath> #include <cstring> #include <string> #include <iostream> @@ -1954,11 +1955,54 @@ void UtilTest::testCreateIndexPaths() void UtilTest::testGenerateRandomData() { - unsigned char data1[20]; + using namespace std; + + // Simple sanity check + unsigned char data1[25]; + memset(data1, 0, sizeof(data1)); util::generateRandomData(data1, sizeof(data1)); - unsigned char data2[20]; + + unsigned char data2[25]; + memset(data2, 0, sizeof(data2)); util::generateRandomData(data2, sizeof(data2)); + CPPUNIT_ASSERT(memcmp(data1, data2, sizeof(data1)) != 0); + + // Simple stddev/mean tests + map<uint8_t, size_t> counts; + uint8_t bytes[1 << 20]; + for (auto i = 0; i < 10; ++i) { + util::generateRandomData(bytes, sizeof(bytes)); + for (auto b : bytes) { + counts[b]++; + } + } + CPPUNIT_ASSERT_MESSAGE("Should see all kinds of bytes", counts.size() == 256); + if (counts.size() != 256) { + throw std::domain_error( + "Would have expected to see at one of each possible byte value!"); + } + double sum = accumulate( + counts.begin(), + counts.end(), + 0.0, + [](double total, const decltype(counts)::value_type & elem) { + return total + elem.second; + }); + double mean = sum / counts.size(); + vector<double> diff(counts.size()); + transform( + counts.begin(), + counts.end(), + diff.begin(), + [&](const decltype(counts)::value_type & elem) -> double { + return (double)elem.second - mean; + }); + double sq_sum = inner_product(diff.begin(), diff.end(), diff.begin(), 0.0); + double stddev = sqrt(sq_sum / counts.size()); + cout << "stddev: " << fixed << stddev << endl; + CPPUNIT_ASSERT_MESSAGE("stddev makes sense (lower)", stddev <= 320); + CPPUNIT_ASSERT_MESSAGE("stddev makes sense (upper)", stddev >= 100); } void UtilTest::testFromHex() |
