MicroLogger/tests/main.cc
2025-06-22 18:11:55 +00:00

119 lines
3.1 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));
}
TEST(SingleThread, Add) {
std::ostringstream s;
vptyp::Logger l(s);
std::queue<std::pair<std::string, int64_t>> prev;
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(1);
decorator("apprx", 12);
decorator("size", 2);
sleep(1);
// results
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};
while (res != lineView.npos && !prev.empty()) {
auto nextAwaiting = prev.front();
res = lineView.find(nextAwaiting.first);
if (res != lineView.npos)
prev.pop();
std::cout << nextAwaiting.first << std::endl;
}
std::cout << "n" << std::endl;
}
EXPECT_EQ(prev.empty(), true);
}
TEST(MultiThread, Configure) {
vptyp::Logger l;
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;
vptyp::Logger l(s);
std::mutex mtx;
std::queue<std::pair<std::string, int64_t>> prev;
l.configure({"apprx", "size", "time"});
auto decorator = [&l, &prev, &mtx](std::string field, int value) {
for (auto i = 0; i < 5; ++i) {
l.add(field, value);
{
std::lock_guard g(mtx);
prev.push({field, value});
}
}
};
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
auto d = s.rdbuf()->view();
std::string_view view;
while (view = d.substr(0, d.find('\n')), view.size() > 0) {
if (prev.empty())
break;
size_t res{0};
while (res != view.npos) {
auto nextAwaiting = prev.front();
res = view.find(nextAwaiting.first);
if (res != view.npos)
prev.pop();
}
}
EXPECT_EQ(prev.empty(), true);
}
int main(int argc, char** argv) {
testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}