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