-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathasync_logger_lib_test_improved.cc
162 lines (137 loc) · 5.52 KB
/
async_logger_lib_test_improved.cc
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
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
#include "async_logger_improved.h"
#include "gtest/gtest.h"
#include <climits>
#include <sys/types.h>
#include <unistd.h>
#include <values.h>
#include <condition_variable>
#include <iostream>
using namespace std;
namespace async_logger {
namespace local_test {
FOLLY_SDT_DECLARE_SEMAPHORE(async_logger_improved, operation_end);
// See $HOME/gitsrc/googletest/googletest/docs/advanced.html
// https://stackoverflow.com/questions/4810516/c-redirecting-stdout
class AsyncLoggerCharTest : public testing::TestWithParam<string> {
protected:
AsyncLoggerCharTest()
: logger(new alogger::async_logger), inputstr(new string),
oldCoutStreamBuf(cout.rdbuf()), strCout(new ostringstream) {
cout.rdbuf(strCout->rdbuf());
logger->log("main_thread");
test1 = new thread([this]() { logger->log("testing thread 1"); });
}
~AsyncLoggerCharTest() {
delete logger;
/* Check output from async_logger thread. */
for (size_t idx = 0; idx < inputstr->length(); ++idx) {
EXPECT_NE(string::npos, strCout->str().find("Argument " + to_string(idx) +
" = " + inputstr->at(idx)));
}
delete test1;
EXPECT_NE(string::npos, strCout->str().find("testing thread 1"));
/* Check for ctor log message. */
EXPECT_NE(string::npos, strCout->str().find("main_thread\n"));
EXPECT_NE(string::npos, strCout->str().find("\nMain ending\n"));
// Restore output to stdout.
cout.rdbuf(oldCoutStreamBuf);
cerr << "Output buffer is: " << endl << strCout->str() << endl;
delete strCout;
delete inputstr;
}
alogger::async_logger *logger;
thread *test1;
string *inputstr;
private:
streambuf *oldCoutStreamBuf;
ostringstream *strCout;
};
TEST_P(AsyncLoggerCharTest, CheckLogOutput) {
/* Log the "command-line" parameters. */
*inputstr = GetParam();
for (size_t idx = 0; idx < inputstr->length(); ++idx) {
logger->log("Argument " + to_string(idx) + " = " + inputstr->at(idx));
}
test1->join();
logger->log("\nMain ending\n");
}
/* Arguments are, in order, an arbitrary choice, the test class name, and the
* parameter values. */
INSTANTIATE_TEST_SUITE_P(HereAreSomeChars, AsyncLoggerCharTest,
testing::Values("", "a",
"abcdefghijklmnopqrstuvwxyz"));
// Might there be some clever way to make a single test class templated so that
// the string and vector<double> test classes are instances of it?
class AsyncLoggerDoubleTest : public testing::TestWithParam<vector<double>> {
protected:
AsyncLoggerDoubleTest()
: logger(new alogger::async_logger), inputvec(new vector<double>),
oldCoutStreamBuf(cout.rdbuf()), strCout(new ostringstream) {
cout.rdbuf(strCout->rdbuf());
// Print out PID for use with USDT tracing tools following
// bcc/examples/usdt_sample/usdt_sample_app1/main.cpp.
cerr << "pid: " << getpid() << endl;
logger->log("main_thread");
test1 = new thread([this]() { logger->log("testing thread 1"); });
}
~AsyncLoggerDoubleTest() {
delete logger;
delete test1;
/* Check output from async_logger thread.
Numerical integration functions have their own tests in the Cpp-Exercises
repository at from which they originate. See
https://github.com/chaiken/Cpp-exercises/blob/master/template_integrate_lib_test.cc
*/
for (size_t idx = 0; idx < inputvec->size(); ++idx) {
EXPECT_NE(string::npos, strCout->str().find("Interval: {0," +
to_string(inputvec->at(idx)) +
"}, Result: "));
const size_t result_start =
(strCout->str().find("Result: ") + strlen("Result: "));
const std::string calc_result{strCout->str().substr(result_start)};
// calc_num is 0.0 if the conversion fails.
double calc_num = strtod(calc_result.c_str(), nullptr);
// How to enable: start test in one console; in another attach a probe.
// For example,
// cd $(PATH TO BCC SOURCE)
// clang-format off
// sudo python3 examples/usdt_sample/scripts/latency.py -p=$(pidof async_logger_lib_test_improved)
// clang-format on
if (FOLLY_SDT_IS_ENABLED(async_logger_improved, operation_end)) {
// Comparing DBL_MAX does not work, because comparing doubles is stupid.
EXPECT_NE(1.797693e+308, calc_num);
} else {
EXPECT_EQ(1.797693e+308, calc_num);
}
}
EXPECT_NE(string::npos, strCout->str().find("testing thread 1"));
/* Check for ctor log message. */
EXPECT_NE(string::npos, strCout->str().find("\nMain ending\n"));
// Restore output to stdout.
cout.rdbuf(oldCoutStreamBuf);
cerr << "Output buffer is: " << endl << strCout->str() << endl;
delete strCout;
delete inputvec;
}
alogger::async_logger *logger;
thread *test1;
vector<double> *inputvec;
private:
streambuf *oldCoutStreamBuf;
ostringstream *strCout;
};
TEST_P(AsyncLoggerDoubleTest, CheckLogOutput) {
*inputvec = GetParam();
for (size_t idx = 0; idx < inputvec->size(); ++idx) {
logger->log(inputvec->at(idx));
}
test1->join();
logger->log("\nMain ending\n");
}
const array<double, 4u> a({14.7, -6.11, 142.4e-3, 3.14159});
const array<double, 4u> b({123.0, 0.123, -11.236, 41.8});
INSTANTIATE_TEST_SUITE_P(HereAreSomeNumbers, AsyncLoggerDoubleTest,
testing::Values(vector<double>(a.begin(), a.end()),
vector<double>(b.begin(), b.end())));
} // namespace local_test
} // namespace async_logger