-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathstress-test-example.cpp
113 lines (96 loc) · 3.71 KB
/
stress-test-example.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
#include <algorithm>
#include <iostream>
#include <random>
#include <vector>
/*
* The code that you want to test
*/
template <class RandIt, class T>
bool BinarySearch(RandIt begin, RandIt end, const T& value) {
while (begin < end) {
auto middle = begin + std::distance(begin, end) / 2;
if (*middle < value) {
begin = middle + 2; // Oops. There is a bug.
} else if (*middle == value) {
return true;
} else {
end = middle;
}
}
return false;
}
/*
* Brute force solution of the task. O(n) time instead of O(log(n)). But this solutions is very
* simple.
*/
template <class ForwardIt, class T>
bool BruteForceSearch(ForwardIt begin, ForwardIt end, const T& value) {
return std::find(begin, end, value) != end;
}
/*
* In C++ we use random library to generate random numbers.
*
* From Stroustrup's PPP book:
* The standard library random number facilities are based on two fundamental notions:
* - Engines. An engine is a function object that generates a uniformly distributed sequence of
* integer values.
* - Distributions. A distribution is a function object that generates a sequence of values
* according to a mathematical formula given a sequence of values from an engine as inputs.
*
* https://en.cppreference.com/w/cpp/header/random
*/
std::vector<int> GenerateArray(size_t size, int min_value, int max_value) {
// 43 is seed of generator. For the same seed, the same sequence of random numbers will be
// generated.
// I use static so that a new generator is not created every time the function is called.
// Otherwise, the beginning of the sequences will be the same.
static std::mt19937 generator{43};
// Distribution. The generated numbers will be in the range [min_value, max_value].
std::uniform_int_distribution distribution{min_value, max_value};
std::vector<int> result(size);
for (auto& value : result) {
// To get a random value, we send a generator to the distribution.
value = distribution(generator);
}
return result;
}
void CompareSolutions(const std::vector<int>& array, int search_value) {
auto fast_solution = BinarySearch(array.begin(), array.end(), search_value);
auto brute_solution = BruteForceSearch(array.begin(), array.end(), search_value);
if (fast_solution != brute_solution) {
std::cerr << "\nTest failed!" << std::endl << "Input data: ";
std::for_each(array.begin(), array.end(), [](auto item) {
std::cerr << item << " ";
});
std::cerr << "\nSearch value: " << search_value << std::endl;
std::abort();
}
}
void RunStressTest() {
constexpr size_t kMinSize = 0;
constexpr size_t kMaxSize = 30;
constexpr int kMinValue = -1000;
constexpr int kMaxValue = 1000;
constexpr size_t kIterationCount = 100;
std::mt19937 generator{42};
std::uniform_int_distribution size_distribution{kMinSize, kMaxSize};
std::uniform_int_distribution value_distribution{kMinValue, kMaxValue};
std::cerr << "Completed iterations: ";
for (size_t iteration = 0; iteration < kIterationCount; ++iteration) {
auto array = GenerateArray(size_distribution(generator), kMinValue, kMaxValue);
std::sort(array.begin(), array.end());
std::cerr << iteration << " ";
size_t check_count = size_distribution(generator);
for (size_t current_check = 0; current_check < check_count; ++current_check) {
CompareSolutions(array, value_distribution(generator));
}
}
std::cerr << "\nTests passed!" << std::endl;
}
/*
* In order to catch runtime-errors as well, run a stress test under ASAN.
*/
int main() {
RunStressTest();
return 0;
}