157 lines
4.2 KiB
C++
157 lines
4.2 KiB
C++
#include <gtest/gtest.h>
|
|
#include <boost/lockfree/queue.hpp>
|
|
#include <logger.hh>
|
|
#include <queue>
|
|
#include <thread>
|
|
|
|
// TEST(SingleThread, Configuration) {
|
|
// vptyp::Logger l;
|
|
// EXPECT_NO_THROW(l.configure({"apprx", "size", "time"}));
|
|
// EXPECT_NO_THROW(l.add("apprx", 123));
|
|
// EXPECT_ANY_THROW(l.add("not in configuration", 123));
|
|
// }
|
|
|
|
void outBufferCheck(std::ostringstream& s,
|
|
std::queue<std::pair<std::string, int64_t>>& prev) {
|
|
std::string_view outBufferView = s.rdbuf()->view();
|
|
std::string_view lineView;
|
|
auto startPos = 0;
|
|
while (startPos < outBufferView.length() &&
|
|
(lineView = outBufferView.substr(startPos, outBufferView.find('\n')),
|
|
lineView.size() > 0)) {
|
|
std::cout << lineView << std::endl;
|
|
if (prev.empty())
|
|
break;
|
|
startPos = outBufferView.find('\n') + 1;
|
|
size_t res{0};
|
|
std::set<std::string_view> s;
|
|
while (res != lineView.npos && !prev.empty()) {
|
|
auto nextAwaiting = prev.front();
|
|
|
|
res = lineView.find(nextAwaiting.first);
|
|
if (res != lineView.npos) {
|
|
s.emplace(nextAwaiting.first);
|
|
prev.pop();
|
|
}
|
|
// std::cout << nextAwaiting.first << std::endl;
|
|
}
|
|
// std::cout << "n" << std::endl;
|
|
}
|
|
EXPECT_EQ(prev.empty(), true);
|
|
}
|
|
|
|
// TEST(SingleThread, Add) {
|
|
// std::ostringstream s;
|
|
// std::queue<std::pair<std::string, int64_t>> prev;
|
|
// {
|
|
// vptyp::Logger l(s);
|
|
|
|
// l.configure({"apprx", "size", "time"});
|
|
|
|
// auto decorator = [&l, &prev](std::string field, int value) {
|
|
// l.add(field, value);
|
|
// prev.push({field, value});
|
|
// };
|
|
|
|
// decorator("size", 1);
|
|
// decorator("time", 1);
|
|
// sleep(2); // twice of logger sleep
|
|
// decorator("apprx", 12);
|
|
// decorator("size", 2);
|
|
// sleep(2);
|
|
// }
|
|
|
|
// // results
|
|
// outBufferCheck(s, prev);
|
|
// }
|
|
|
|
// TEST(MultiThread, Configure) {
|
|
// vptyp::Logger l(std::cout);
|
|
// std::atomic<size_t> howManyConfigured;
|
|
// auto fConfig = [&l, &howManyConfigured] {
|
|
// bool res{false};
|
|
// EXPECT_NO_THROW(res = l.configure({"apprx", "size", "time"}));
|
|
// howManyConfigured.fetch_add(static_cast<size_t>(res));
|
|
// };
|
|
// // simulate race condition configure
|
|
// std::vector<std::jthread> threads(10);
|
|
// for (auto& thread : threads) {
|
|
// thread = std::jthread(fConfig);
|
|
// }
|
|
// threads.clear();
|
|
// EXPECT_EQ(howManyConfigured.load(), 1);
|
|
// }
|
|
|
|
TEST(MultiThread, Add) {
|
|
std::ostringstream s;
|
|
std::queue<std::pair<std::string, int64_t>> prev;
|
|
std::mutex mtx;
|
|
{
|
|
vptyp::Logger l(s);
|
|
l.configure({"apprx", "size", "time"});
|
|
|
|
auto decorator = [&l, &prev, &mtx](std::string field, int value) {
|
|
for (auto i = 0; i < 1 << 20; ++i) {
|
|
l.add(field, value);
|
|
{
|
|
std::lock_guard g(mtx);
|
|
prev.push({field, value});
|
|
}
|
|
std::this_thread::yield();
|
|
}
|
|
};
|
|
|
|
std::vector<std::jthread> threads(3);
|
|
threads[0] = std::jthread(decorator, "apprx", rand() % 100);
|
|
threads[1] = std::jthread(decorator, "size", rand() % 100);
|
|
threads[2] = std::jthread(decorator, "time", rand() % 100);
|
|
|
|
threads.clear();
|
|
sleep(1);
|
|
}
|
|
|
|
// results
|
|
outBufferCheck(s, prev);
|
|
}
|
|
|
|
TEST(MultiThread, Add16Threads) {
|
|
std::ostringstream s;
|
|
std::queue<std::pair<std::string, int64_t>> prev;
|
|
std::mutex mtx;
|
|
{
|
|
vptyp::Logger l(s);
|
|
l.configure({"field0", "field1", "field2", "field3", "field4", "field5",
|
|
"field6", "field7", "field8", "field9", "field10", "field11",
|
|
"field12", "field13", "field14", "field15"});
|
|
|
|
auto decorator = [&l, &prev, &mtx](std::string field, int value) {
|
|
for (auto i = 0; i < 1 << 20; ++i) {
|
|
l.add(field, value);
|
|
{
|
|
std::lock_guard g(mtx);
|
|
prev.push({field, value});
|
|
}
|
|
std::this_thread::yield();
|
|
}
|
|
};
|
|
|
|
std::vector<std::jthread> threads(16);
|
|
|
|
// Create 16 threads, each with its own unique field
|
|
for (int i = 0; i < 16; ++i) {
|
|
std::string field = "field" + std::to_string(i);
|
|
threads[i] = std::jthread(decorator, field, rand() % 100);
|
|
}
|
|
|
|
threads.clear();
|
|
sleep(1);
|
|
}
|
|
|
|
// results
|
|
outBufferCheck(s, prev);
|
|
}
|
|
|
|
int main(int argc, char** argv) {
|
|
testing::InitGoogleTest(&argc, argv);
|
|
return RUN_ALL_TESTS();
|
|
} |