123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102 |
- // Copyright 2018 The Chromium Authors. All rights reserved.
- // Use of this source code is governed by a BSD-style license that can be
- // found in the LICENSE file.
- #include "base/bind.h"
- #include "base/callback.h"
- #include "media/learning/impl/test_random_number_generator.h"
- #include "testing/gtest/include/gtest/gtest.h"
- namespace media {
- class RandomNumberGeneratorTest : public testing::Test {
- public:
- RandomNumberGeneratorTest() : rng_(0) {}
- void GenerateAndVerify(base::RepeatingCallback<int64_t()> generate,
- int64_t lower_inclusive,
- int64_t upper_inclusive) {
- const size_t n = 10000;
- std::map<int64_t, size_t> counts;
- for (size_t i = 0; i < n; i++)
- counts[generate.Run()]++;
- // Verify that it's uniform over |lower_inclusive| and
- // |upper_inclusive|, at least approximately.
- size_t min_counts = counts[lower_inclusive];
- size_t max_counts = min_counts;
- size_t total_counts = min_counts;
- for (int64_t i = lower_inclusive + 1; i <= upper_inclusive; i++) {
- size_t c = counts[i];
- if (c < min_counts)
- min_counts = c;
- if (c > max_counts)
- max_counts = c;
- total_counts += c;
- }
- // See if the min and the max are too far from the expected counts.
- // Note that this will catch only egregious problems. Also note that
- // random variation might actually exceed these limits fairly often.
- // It's only because the test rng has no variation that we know it
- // won't happen. However, there might be reasonable implementation
- // changes that trip these tests (deterministically!); manual
- // verification of the result is needed in those cases.
- //
- // These just catch things like "rng range is off by one", etc.
- size_t expected_counts = n / (upper_inclusive - lower_inclusive + 1);
- EXPECT_LT(max_counts, expected_counts * 1.05);
- EXPECT_GT(max_counts, expected_counts * 0.95);
- EXPECT_LT(min_counts, expected_counts * 1.05);
- EXPECT_GT(min_counts, expected_counts * 0.95);
- // Verify that the counts between the limits accounts for all of them.
- // Otherwise, some rng values were out of range.
- EXPECT_EQ(total_counts, n);
- }
- // We use TestRandomNumberGenerator, since we really want to test the base
- // class method implementations with a predictable random source.
- TestRandomNumberGenerator rng_;
- };
- TEST_F(RandomNumberGeneratorTest, ExclusiveUpTo) {
- // Try Generate with something that's not a divisor of max_int, to try to
- // catch any bias. I.e., an implementation like "rng % range" should fail
- // this test.
- //
- // Unfortunately, it won't.
- //
- // With uint64_t random values, it's unlikely that we would ever notice such a
- // problem. For example, a range of size three would just remove ~three from
- // the upper range of the rng, and it's unlikely that we'd ever pick the three
- // highest values anyway. If, instead, we make |range| really big, then we're
- // not going to sample enough points to notice the deviation from uniform.
- //
- // However, we still look for issues like "off by one".
- const uint64_t range = 5;
- GenerateAndVerify(base::BindRepeating(
- [](RandomNumberGenerator* rng, uint64_t range) {
- return static_cast<int64_t>(rng->Generate(range));
- },
- &rng_, range),
- 0, range - 1);
- }
- TEST_F(RandomNumberGeneratorTest, DoublesStayInRange) {
- const double limit = 1000.5;
- int num_non_integer = 0;
- for (int i = 0; i < 1000; i++) {
- double v = rng_.GenerateDouble(limit);
- EXPECT_GE(v, 0.);
- EXPECT_LT(v, limit);
- // Also count how many non-integers we get.
- num_non_integer += (v != static_cast<int>(v));
- }
- // Expect a lot of non-integers.
- EXPECT_GE(num_non_integer, 900);
- }
- } // namespace media
|