#include #include #include #include #include // 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>& 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 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> 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 howManyConfigured; // auto fConfig = [&l, &howManyConfigured] { // bool res{false}; // EXPECT_NO_THROW(res = l.configure({"apprx", "size", "time"})); // howManyConfigured.fetch_add(static_cast(res)); // }; // // simulate race condition configure // std::vector 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> 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 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> 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 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(); }