Coverage Report

Created: 2023-11-12 09:30

/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