Files
oemcrypto/util/test/cdm_random_unittest.cpp
Fred Gylys-Colwell 4de11d11e8 Initial v16 ODK Library
This commit has the initial ODK library.  Partners may use this code
to begin integrating the ODK library into their platform.  The
functionality is not complete, but this should help partners get an
early start playing with build files.
2019-10-04 16:47:20 -07:00

148 lines
4.0 KiB
C++

// Copyright 2019 Google LLC. All Rights Reserved. This file and proprietary
// source code may only be used and distributed under the Widevine Master
// License Agreement.
#include <stdlib.h>
#include <chrono>
#include <limits>
#include <string>
#include <thread>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include "cdm_random.h"
namespace wvcdm {
namespace {
// Random data vector lengths.
constexpr size_t kVectorLength = 1024;
constexpr size_t kMaxRandomDataLength =
CdmRandomGenerator::kMaxRandomDataLength;
constexpr size_t kAboveMaxRandomDataLength = std::numeric_limits<size_t>::max();
constexpr size_t kRandomTrialCount = 100;
constexpr size_t kThreadCount = 16;
constexpr unsigned int kSeeds[] = {0, 1337, 1565904109, 776964657};
class CdmRandomGeneratorTest : public testing::TestWithParam<unsigned int> {};
} // namespace
TEST_P(CdmRandomGeneratorTest, AllMethods) {
const unsigned int seed = GetParam();
CdmRandomGenerator rng;
rng.Seed();
rng.Seed(seed);
rng.Rand();
rng();
rng.RandomInRange(1234, 1000000);
rng.RandomInRange(1000000);
rng.RandomData(kVectorLength);
rng.RandomBool();
}
TEST_P(CdmRandomGeneratorTest, RandomInRange) {
const unsigned int seed = GetParam();
CdmRandomGenerator rng(seed);
for (size_t i = 0; i < kRandomTrialCount; ++i) {
const int rand_int = rng.Rand();
EXPECT_GE(rand_int, 0);
EXPECT_LE(rand_int, RAND_MAX);
}
// Range size of 1.
const uint64_t rand_u64_1 = rng.RandomInRange(100, 100);
EXPECT_EQ(rand_u64_1, 100ul);
// Range size of 2.
const uint64_t rand_u64_2 = rng.RandomInRange(1234, 1235);
EXPECT_GE(rand_u64_2, 1234ul);
EXPECT_LE(rand_u64_2, 1235ul);
// Small range.
const uint64_t rand_u64_3 = rng.RandomInRange(10);
EXPECT_LE(rand_u64_3, 10ul);
// Max range, mainly checking that nothing crashes.
rng.RandomInRange(0, std::numeric_limits<uint64_t>::max());
// Invalid range representation. Should swap the bounds.
const uint64_t rand_u64_4 = rng.RandomInRange(1235, 1234);
EXPECT_GE(rand_u64_4, 1234ul);
EXPECT_LE(rand_u64_4, 1235ul);
}
TEST_P(CdmRandomGeneratorTest, RandomDataLength) {
const unsigned int seed = GetParam();
CdmRandomGenerator rng(seed);
const std::string empty_data = rng.RandomData(0);
EXPECT_EQ(empty_data.size(), 0ul);
const std::string data = rng.RandomData(kVectorLength);
EXPECT_EQ(data.size(), kVectorLength);
const std::string max_data = rng.RandomData(kMaxRandomDataLength);
EXPECT_EQ(max_data.size(), kMaxRandomDataLength);
// Requesting data above the maximum length will result in an error,
// returning an empty string.
const std::string error_data = rng.RandomData(kAboveMaxRandomDataLength);
EXPECT_EQ(error_data.size(), 0ul);
}
TEST_P(CdmRandomGeneratorTest, Reproducibility) {
const unsigned int seed = GetParam();
CdmRandomGenerator rng(seed);
const std::string random_data_1 = rng.RandomData(kVectorLength);
// Reset generator.
rng.Seed(seed);
const std::string random_data_2 = rng.RandomData(kVectorLength);
EXPECT_EQ(random_data_1, random_data_2);
}
TEST_P(CdmRandomGeneratorTest, ThreadSafety) {
const unsigned int seed = GetParam();
CdmRandomGenerator rng(seed);
bool barrier = true;
auto thread_job = [&]() {
while (barrier) {
std::this_thread::sleep_for(std::chrono::microseconds(1));
}
for (size_t i = 0; i < kRandomTrialCount; ++i) {
rng.Rand();
}
};
std::vector<std::thread> threads;
for (size_t i = 0; i < kThreadCount; ++i) {
threads.push_back(std::thread(thread_job));
}
std::this_thread::sleep_for(std::chrono::microseconds(100));
barrier = false;
for (auto& thread : threads) {
thread.join();
}
}
INSTANTIATE_TEST_CASE_P(VariousSeeds, CdmRandomGeneratorTest,
testing::ValuesIn(kSeeds));
TEST(CdmRandomTest, AllMethods) {
CdmRandom::Rand();
CdmRandom::RandomInRange(1234, 1000000);
CdmRandom::RandomInRange(1000000);
CdmRandom::RandomData(kVectorLength);
CdmRandom::RandomBool();
}
} // namespace wvcdm