1 // Copyright 2021 The Tint Authors.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include "fuzzers/random_generator.h"
16 
17 #include <memory>
18 
19 #include "gtest/gtest.h"
20 
21 #include "fuzzers/mersenne_twister_engine.h"
22 
23 namespace tint {
24 namespace fuzzers {
25 namespace {
26 
27 /// Implementation of RandomGeneratorEngine that just returns a stream of
28 /// monotonically increasing numbers.
29 class MonotonicEngine : public RandomGeneratorEngine {
30  public:
31   uint32_t RandomUInt32(uint32_t, uint32_t) override { return next_++; }
32 
33   uint64_t RandomUInt64(uint64_t, uint64_t) override { return next_++; }
34 
35   void RandomNBytes(uint8_t*, size_t) override {
36     assert(false && "MonotonicDelegate does not implement RandomNBytes");
37   }
38 
39  private:
40   uint32_t next_ = 0;
41 };
42 
43 class RandomGeneratorTest : public testing::Test {
44  public:
45   void SetUp() override { rng_ = std::make_unique<RandomGenerator>(0); }
46 
47   void TearDown() override {}
48 
49  protected:
50   std::unique_ptr<RandomGenerator> rng_;
51 };
52 
53 #ifndef NDEBUG
TEST_F(RandomGeneratorTest, GetUInt32ReversedBoundsCrashes)54 TEST_F(RandomGeneratorTest, GetUInt32ReversedBoundsCrashes) {
55   EXPECT_DEATH(rng_->GetUInt32(10, 5), ".*");
56 }
57 
TEST_F(RandomGeneratorTest, GetUInt32EmptyBoundsCrashes)58 TEST_F(RandomGeneratorTest, GetUInt32EmptyBoundsCrashes) {
59   EXPECT_DEATH(rng_->GetUInt32(5, 5), ".*");
60 }
61 
TEST_F(RandomGeneratorTest, GetUInt32ZeroBoundCrashes)62 TEST_F(RandomGeneratorTest, GetUInt32ZeroBoundCrashes) {
63   EXPECT_DEATH(rng_->GetUInt32(0u), ".*");
64 }
65 #endif  // NDEBUG
66 
TEST_F(RandomGeneratorTest, GetUInt32SingularReturnsOneValue)67 TEST_F(RandomGeneratorTest, GetUInt32SingularReturnsOneValue) {
68   {
69     uint32_t result = rng_->GetUInt32(5u, 6u);
70     ASSERT_EQ(5u, result);
71   }
72   {
73     uint32_t result = rng_->GetUInt32(1u);
74     ASSERT_EQ(0u, result);
75   }
76 }
77 
TEST_F(RandomGeneratorTest, GetUInt32StaysInBounds)78 TEST_F(RandomGeneratorTest, GetUInt32StaysInBounds) {
79   {
80     uint32_t result = rng_->GetUInt32(5u, 10u);
81     ASSERT_LE(5u, result);
82     ASSERT_GT(10u, result);
83   }
84   {
85     uint32_t result = rng_->GetUInt32(10u);
86     ASSERT_LE(0u, result);
87     ASSERT_GT(10u, result);
88   }
89 }
90 
91 #ifndef NDEBUG
TEST_F(RandomGeneratorTest, GetUInt64ReversedBoundsCrashes)92 TEST_F(RandomGeneratorTest, GetUInt64ReversedBoundsCrashes) {
93   EXPECT_DEATH(rng_->GetUInt64(10, 5), ".*");
94 }
95 
TEST_F(RandomGeneratorTest, GetUInt64EmptyBoundsCrashes)96 TEST_F(RandomGeneratorTest, GetUInt64EmptyBoundsCrashes) {
97   EXPECT_DEATH(rng_->GetUInt64(5, 5), ".*");
98 }
99 
TEST_F(RandomGeneratorTest, GetUInt64ZeroBoundCrashes)100 TEST_F(RandomGeneratorTest, GetUInt64ZeroBoundCrashes) {
101   EXPECT_DEATH(rng_->GetUInt64(0u), ".*");
102 }
103 #endif  // NDEBUG
104 
TEST_F(RandomGeneratorTest, GetUInt64SingularReturnsOneValue)105 TEST_F(RandomGeneratorTest, GetUInt64SingularReturnsOneValue) {
106   {
107     uint64_t result = rng_->GetUInt64(5u, 6u);
108     ASSERT_EQ(5u, result);
109   }
110   {
111     uint64_t result = rng_->GetUInt64(1u);
112     ASSERT_EQ(0u, result);
113   }
114 }
115 
TEST_F(RandomGeneratorTest, GetUInt64StaysInBounds)116 TEST_F(RandomGeneratorTest, GetUInt64StaysInBounds) {
117   {
118     uint64_t result = rng_->GetUInt64(5u, 10u);
119     ASSERT_LE(5u, result);
120     ASSERT_GT(10u, result);
121   }
122   {
123     uint64_t result = rng_->GetUInt64(10u);
124     ASSERT_LE(0u, result);
125     ASSERT_GT(10u, result);
126   }
127 }
128 
TEST_F(RandomGeneratorTest, GetByte)129 TEST_F(RandomGeneratorTest, GetByte) {
130   rng_->GetByte();
131 }
132 
133 #ifndef NDEBUG
TEST_F(RandomGeneratorTest, GetNBytesNullDataBufferCrashes)134 TEST_F(RandomGeneratorTest, GetNBytesNullDataBufferCrashes) {
135   EXPECT_DEATH(rng_->GetNBytes(nullptr, 5), ".*");
136 }
137 #endif  // NDEBUG
138 
TEST_F(RandomGeneratorTest, GetNBytes)139 TEST_F(RandomGeneratorTest, GetNBytes) {
140   std::vector<uint8_t> data;
141   for (uint32_t i = 25; i < 1000u; i = i + 25) {
142     data.resize(i);
143     rng_->GetNBytes(data.data(), data.size());
144   }
145 }
146 
TEST_F(RandomGeneratorTest, GetBool)147 TEST_F(RandomGeneratorTest, GetBool) {
148   rng_->GetBool();
149 }
150 
TEST_F(RandomGeneratorTest, GetWeightedBoolZeroAlwaysFalse)151 TEST_F(RandomGeneratorTest, GetWeightedBoolZeroAlwaysFalse) {
152   ASSERT_FALSE(rng_->GetWeightedBool(0));
153 }
154 
TEST_F(RandomGeneratorTest, GetWeightedBoolHundredAlwaysTrue)155 TEST_F(RandomGeneratorTest, GetWeightedBoolHundredAlwaysTrue) {
156   ASSERT_TRUE(rng_->GetWeightedBool(100));
157 }
158 
159 #ifndef NDEBUG
TEST_F(RandomGeneratorTest, GetWeightedBoolAboveHundredCrashes)160 TEST_F(RandomGeneratorTest, GetWeightedBoolAboveHundredCrashes) {
161   EXPECT_DEATH(rng_->GetWeightedBool(101), ".*");
162   EXPECT_DEATH(rng_->GetWeightedBool(500), ".*");
163 }
164 #endif  // NDEBUG
165 
TEST_F(RandomGeneratorTest, GetWeightedBool)166 TEST_F(RandomGeneratorTest, GetWeightedBool) {
167   for (uint32_t i = 0; i <= 100; i++) {
168     rng_ =
169         std::make_unique<RandomGenerator>(std::make_unique<MonotonicEngine>());
170     for (uint32_t j = 0; j <= 100; j++) {
171       if (j < i) {
172         ASSERT_TRUE(rng_->GetWeightedBool(i));
173       } else {
174         ASSERT_FALSE(rng_->GetWeightedBool(i));
175       }
176     }
177   }
178 }
179 
180 #ifndef NDEBUG
TEST_F(RandomGeneratorTest, GetRandomElementEmptyVectorCrashes)181 TEST_F(RandomGeneratorTest, GetRandomElementEmptyVectorCrashes) {
182   std::vector<uint8_t> v;
183   EXPECT_DEATH(rng_->GetRandomElement(v), ".*");
184 }
185 #endif  // NDEBUG
186 
TEST_F(RandomGeneratorTest, GetRandomElement)187 TEST_F(RandomGeneratorTest, GetRandomElement) {
188   std::vector<uint32_t> v;
189   for (uint32_t i = 25; i < 100u; i = i + 25) {
190     rng_ =
191         std::make_unique<RandomGenerator>(std::make_unique<MonotonicEngine>());
192     v.resize(i);
193     std::iota(v.begin(), v.end(), 0);
194     for (uint32_t j = 0; j < i; j++) {
195       EXPECT_EQ(j, rng_->GetRandomElement(v));
196     }
197   }
198 }
199 
200 }  // namespace
201 }  // namespace fuzzers
202 }  // namespace tint
203