/proc/self/cwd/test/fuzz/random.h
Line | Count | Source (jump to first uncovered line) |
1 | | #pragma once |
2 | | |
3 | | #include <memory> |
4 | | #include <random> |
5 | | #include <utility> |
6 | | #include <vector> |
7 | | |
8 | | #include "envoy/common/random_generator.h" |
9 | | |
10 | | #include "source/common/common/assert.h" |
11 | | #include "source/common/common/logger.h" |
12 | | |
13 | | namespace Envoy { |
14 | | namespace Random { |
15 | | |
16 | | class PsuedoRandomGenerator64 : public RandomGenerator { |
17 | | public: |
18 | 10.7k | PsuedoRandomGenerator64() = default; |
19 | 10.7k | ~PsuedoRandomGenerator64() override = default; |
20 | | |
21 | 10.7k | void initializeSeed(uint64_t seed) { prng_ = std::make_unique<std::mt19937_64>(seed); } |
22 | | |
23 | | // RandomGenerator |
24 | 39.2k | uint64_t random() override { |
25 | | // Makes sure initializeSeed() was already called |
26 | 39.2k | ASSERT(prng_ != nullptr); |
27 | 39.2k | const uint64_t to_return = (*prng_)(); |
28 | 39.2k | ENVOY_LOG_MISC(trace, "random() returned: {}", to_return); |
29 | 39.2k | return to_return; |
30 | 39.2k | } |
31 | 0 | std::string uuid() override { return ""; } |
32 | | std::unique_ptr<std::mt19937_64> prng_; |
33 | | }; |
34 | | |
35 | | } // namespace Random |
36 | | |
37 | | namespace Fuzz { |
38 | | |
39 | | class ProperSubsetSelector { |
40 | | public: |
41 | | ProperSubsetSelector(const std::vector<uint32_t>& random_bytestring) |
42 | 17.5k | : random_bytestring_(random_bytestring) {} |
43 | | |
44 | | /** |
45 | | * This function does proper subset selection on a certain number of elements. It returns a vector |
46 | | * of vectors of bytes. Each vector of bytes represents the indexes of a single subset. The |
47 | | * "randomness" of the subset that the class will use is determined by a bytestring passed into |
48 | | * the class. Example: call into function with a vector {3, 5} representing subset sizes, and 15 |
49 | | * as number_of_elements. This function would return something such as {{3, 14, 7}, {2, 1, 13, 8, |
50 | | * 6}}. If the sum of the number of elements in each elements in each subset > number of elements, |
51 | | * this will stop constructing subsets once the number of elements has ran out and been already |
52 | | * placed into subsets. So, if you had a vector {3, 5} representing subset sizes, and 2 as number |
53 | | * of elements, the function would return something such as {{5, 3}}. |
54 | | */ |
55 | | |
56 | | std::vector<std::vector<uint32_t>> |
57 | | constructSubsets(const std::vector<uint32_t>& number_of_elements_in_each_subset, |
58 | 17.5k | uint32_t number_of_elements) { |
59 | 17.5k | num_elements_left_ = number_of_elements; |
60 | 17.5k | std::vector<uint32_t> index_vector; |
61 | 17.5k | index_vector.reserve(number_of_elements); |
62 | 24.2M | for (uint32_t i = 0; i < number_of_elements; i++) { |
63 | 24.2M | index_vector.push_back(i); |
64 | 24.2M | } |
65 | 17.5k | std::vector<std::vector<uint32_t>> subsets; |
66 | 17.5k | subsets.reserve(number_of_elements_in_each_subset.size()); |
67 | 52.5k | for (uint32_t i : number_of_elements_in_each_subset) { |
68 | 52.5k | subsets.push_back(constructSubset(i, index_vector)); |
69 | 52.5k | } |
70 | 17.5k | return subsets; |
71 | 17.5k | } |
72 | | |
73 | | private: |
74 | | // Builds a single subset by pulling indexes off index_vector_ |
75 | | std::vector<uint32_t> constructSubset(uint32_t number_of_elements_in_subset, |
76 | 52.5k | std::vector<uint32_t>& index_vector) { |
77 | 52.5k | std::vector<uint32_t> subset; |
78 | | |
79 | 1.20M | for (uint32_t i = 0; i < number_of_elements_in_subset && !(num_elements_left_ == 0); i++) { |
80 | 1.15M | uint32_t index_of_index_vector = |
81 | 1.15M | random_bytestring_.at(index_of_random_bytestring_ % random_bytestring_.size()) % |
82 | 1.15M | num_elements_left_; |
83 | 1.15M | uint32_t index = index_vector.at(index_of_index_vector); |
84 | 1.15M | subset.push_back(index); |
85 | | // Move the index chosen to the end of the vector - will not be chosen again |
86 | 1.15M | std::swap(index_vector[index_of_index_vector], index_vector[num_elements_left_ - 1]); |
87 | 1.15M | --num_elements_left_; |
88 | | |
89 | 1.15M | ++index_of_random_bytestring_; |
90 | 1.15M | } |
91 | | |
92 | 52.5k | return subset; |
93 | 52.5k | } |
94 | | |
95 | | // This bytestring will be iterated through representing randomness in order to choose |
96 | | // subsets |
97 | | std::vector<uint32_t> random_bytestring_; |
98 | | uint32_t index_of_random_bytestring_ = 0; |
99 | | |
100 | | // Used to make subset construction linear time complexity with std::swap - chosen indexes will be |
101 | | // swapped to end of vector, and won't be chosen again due to modding against this integer |
102 | | uint32_t num_elements_left_; |
103 | | }; |
104 | | |
105 | | } // namespace Fuzz |
106 | | } // namespace Envoy |