1 |
|
|
// |
2 |
|
|
// Created by 4c3y (acey) on 21.09.22. |
3 |
|
|
// |
4 |
|
|
|
5 |
|
|
#ifndef LOG_TEST_COMMON_ASYNC_TESTS_H_ |
6 |
|
|
#define LOG_TEST_COMMON_ASYNC_TESTS_H_ |
7 |
|
|
|
8 |
|
|
#if __cplusplus >= 201703L |
9 |
|
|
#include <mutex> |
10 |
|
|
#endif |
11 |
|
|
|
12 |
|
|
#include <test_utils.h> |
13 |
|
|
#include <thread> |
14 |
|
|
|
15 |
|
|
#define GET_CLASS_NAME(class_ptr, status) abi::__cxa_demangle(typeid(class_ptr).name(), nullptr, nullptr, status) |
16 |
|
|
|
17 |
|
|
enum CompareType { |
18 |
|
|
EQUAL, |
19 |
|
|
IS_SUBSTRING, |
20 |
|
|
REMOVE_NUMBERS_FROM_STRING |
21 |
|
|
}; |
22 |
|
|
|
23 |
|
|
enum StreamType { |
24 |
|
|
STDOUT, |
25 |
|
|
STDERR |
26 |
|
|
}; |
27 |
|
|
|
28 |
|
|
struct AsyncTest { |
29 |
|
|
std::string class_name; |
30 |
|
|
std::string expected_output; |
31 |
|
|
std::function<void()> fn; |
32 |
|
|
CompareType compare_type; |
33 |
|
|
StreamType stream_type; |
34 |
|
|
}; |
35 |
|
|
|
36 |
|
|
extern std::vector<AsyncTest> generateTests(); |
37 |
|
|
static std::vector<AsyncTest> tests = generateTests(); |
38 |
|
|
|
39 |
|
|
class TestResult { |
40 |
|
|
public: |
41 |
|
192 |
static inline TestResult &getInstance() { |
42 |
✓✓✓✗
|
192 |
static TestResult instance{}; |
43 |
|
192 |
return instance; |
44 |
|
|
} |
45 |
|
|
|
46 |
|
|
/** |
47 |
|
|
* Returns test result by test name |
48 |
|
|
* @param test_name |
49 |
|
|
* @return true on success otherwise false |
50 |
|
|
*/ |
51 |
|
96 |
inline bool get(const std::string &test_name) { |
52 |
|
|
#if __cplusplus >= 201703L |
53 |
✓✗ |
192 |
std::scoped_lock<std::mutex> lock(test_result_mutex_); |
54 |
|
|
#elif __cplusplus >= 201103L |
55 |
|
|
std::lock_guard<std::mutex> lock(test_result_mutex_); |
56 |
|
|
#endif |
57 |
|
|
|
58 |
✓✗ |
96 |
LOG_INIT(*test_argv); |
59 |
✓✓ |
96 |
if (!started_) { |
60 |
|
5 |
started_ = true; |
61 |
✓✗ |
5 |
startAll(); |
62 |
|
|
} |
63 |
|
|
|
64 |
✓✗✗✓
|
96 |
if (test_results.find(test_name) == test_results.end()) { |
65 |
|
|
return false; |
66 |
|
|
} |
67 |
|
|
|
68 |
✓✗ |
96 |
bool res = test_results.at(test_name); |
69 |
|
96 |
return res; |
70 |
|
|
} |
71 |
|
|
|
72 |
|
|
private: |
73 |
|
5 |
static inline void startAll() { |
74 |
|
10 |
std::vector<std::thread> thread_pool{}; |
75 |
✓✓ |
101 |
for (const auto &t: tests) { |
76 |
✓✗ |
96 |
thread_pool.emplace_back(&TestResult::startTimed, &TestResult::getInstance(), t); |
77 |
|
|
} |
78 |
|
|
|
79 |
✓✓ |
101 |
for (auto &t: thread_pool) { |
80 |
✓✗ |
96 |
t.join(); |
81 |
|
|
} |
82 |
|
5 |
} |
83 |
|
|
|
84 |
|
2880 |
static inline void startCapture(StreamType stream_type) { |
85 |
✓✓✗ |
2880 |
switch (stream_type) { |
86 |
|
1620 |
case STDOUT: testing::internal::CaptureStdout(); |
87 |
|
1620 |
return; |
88 |
|
1260 |
case STDERR: testing::internal::CaptureStderr(); |
89 |
|
1260 |
return; |
90 |
|
|
} |
91 |
|
|
} |
92 |
|
|
|
93 |
|
2880 |
static inline std::string stopCapture(StreamType stream_type) { |
94 |
✓✓✗ |
2880 |
switch (stream_type) { |
95 |
|
1620 |
case STDOUT: return testing::internal::GetCapturedStdout(); |
96 |
|
|
|
97 |
|
1260 |
case STDERR: return testing::internal::GetCapturedStderr(); |
98 |
|
|
} |
99 |
|
|
abort(); |
100 |
|
|
} |
101 |
|
|
|
102 |
|
96 |
inline void startTimed(const AsyncTest &a) { |
103 |
|
96 |
bool test_status = true; |
104 |
|
|
|
105 |
✓✓ |
2976 |
for (int i = 0; i < 30; i++) { |
106 |
✓✗ |
2880 |
stdout_capture_mutex_.lock(); |
107 |
✓✗ |
2880 |
startCapture(a.stream_type); |
108 |
✓✗ |
2880 |
a.fn(); |
109 |
✓✗ |
5760 |
std::string output = stopCapture(a.stream_type); |
110 |
|
2880 |
stdout_capture_mutex_.unlock(); |
111 |
|
|
|
112 |
✓✓✓✓
|
2880 |
if ((i == 0 || i % 4 == 0)) { |
113 |
✓✗✗✓
|
768 |
if (!compare(a.compare_type, output, a.expected_output)) { |
114 |
|
|
std::cout << a.class_name << " failed. Output: " << output << " expected output: " << a.expected_output |
115 |
|
|
<< std::endl; |
116 |
|
|
test_status = false; |
117 |
|
|
} |
118 |
✓✗✓✗ ✗✓ |
2112 |
} else if (!compare(a.compare_type, output, "")) { |
119 |
|
|
std::cout << a.class_name << " failed. Output: " << output << " expected output: " << "\"\"" << std::endl; |
120 |
|
|
test_status = false; |
121 |
|
|
} |
122 |
✓✗ |
2880 |
usleep(250000.); |
123 |
|
|
} |
124 |
|
96 |
insert(a.class_name, test_status); |
125 |
|
96 |
} |
126 |
|
|
|
127 |
|
|
//gtest assertions only work on main thread |
128 |
|
2880 |
static inline bool compare(CompareType compare_type, const std::string &output, const std::string &expected_output) { |
129 |
✓✓✓✗
|
2880 |
switch (compare_type) { |
130 |
|
900 |
case EQUAL:return compareEquality(output, expected_output); |
131 |
|
1380 |
case IS_SUBSTRING: return compareSubstring(output, expected_output); |
132 |
|
600 |
case REMOVE_NUMBERS_FROM_STRING: return compareRemoveNumbersFromString(output, expected_output); |
133 |
|
|
default:return false; |
134 |
|
|
} |
135 |
|
|
} |
136 |
|
|
|
137 |
|
1380 |
static inline bool compareSubstring(const std::string &output, const std::string &expected_output) { |
138 |
✓✓ |
1380 |
if (expected_output.empty()) { |
139 |
|
1132 |
return output.empty(); |
140 |
|
|
} |
141 |
|
248 |
return isSubstring(output, expected_output); |
142 |
|
|
}; |
143 |
|
|
|
144 |
|
900 |
static inline bool compareEquality(const std::string &output, const std::string &expected_output) { |
145 |
|
900 |
return output == expected_output; |
146 |
|
|
}; |
147 |
|
|
|
148 |
|
600 |
static inline bool compareRemoveNumbersFromString(const std::string &output, const std::string &expected_output) { |
149 |
✓✗ |
600 |
return expected_output == removeNumbersFromString(output); |
150 |
|
|
} |
151 |
|
|
|
152 |
|
96 |
inline void insert(const std::string &test_name, bool test_status) { |
153 |
✓✗ |
96 |
test_results.insert({test_name, test_status}); |
154 |
|
96 |
} |
155 |
|
|
|
156 |
|
5 |
TestResult() = default; |
157 |
|
|
|
158 |
|
|
bool started_{false}; |
159 |
|
|
std::mutex test_result_mutex_; |
160 |
|
|
std::mutex stdout_capture_mutex_; |
161 |
|
|
std::map<std::string, bool> test_results; |
162 |
|
|
}; |
163 |
|
|
|
164 |
|
|
#endif //LOG_TEST_COMMON_ASYNC_TESTS_H_ |