From 9d02c7977c92754259cc29aa78e809e8ff8d4e73 Mon Sep 17 00:00:00 2001 From: Shan Zhou <11672456+Shan-Zhou@users.noreply.github.com> Date: Sun, 13 Sep 2026 16:59:00 +0900 Subject: [PATCH] test: eliminate race conditions and fix flaky tailing tests with WaitForLines --- .../DebugViewppTest/DebugView++Test.cpp | 54 +++++++++++++------ 1 file changed, 39 insertions(+), 15 deletions(-) diff --git a/application/DebugViewppTest/DebugView++Test.cpp b/application/DebugViewppTest/DebugView++Test.cpp index 9e80f604..552d5159 100644 --- a/application/DebugViewppTest/DebugView++Test.cpp +++ b/application/DebugViewppTest/DebugView++Test.cpp @@ -620,6 +620,31 @@ void RemoveLinesFromFile(const std::string& filename, int linesToRemove) Win32::HFile(GetTestFileName()).resize(offset); } +Lines WaitForLines(ActiveExecutorClient& executor, LogSources& logsources, size_t expectedCount, + std::chrono::milliseconds timeout = std::chrono::milliseconds(2000), + std::chrono::milliseconds interval = std::chrono::milliseconds(50)) +{ + Lines accumulated; + const auto startTime = std::chrono::steady_clock::now(); + while (accumulated.size() < expectedCount) + { + Lines batch; + executor.Call([&] { batch = logsources.GetLines(); }); + accumulated.insert(accumulated.end(), + std::make_move_iterator(batch.begin()), + std::make_move_iterator(batch.end())); + + if (accumulated.size() >= expectedCount) + break; + + if (std::chrono::steady_clock::now() - startTime >= timeout) + break; + + std::this_thread::sleep_for(interval); + } + return accumulated; +} + BOOST_AUTO_TEST_CASE(LogSourceAnyFileReader) { using namespace std::chrono_literals; @@ -628,10 +653,8 @@ BOOST_AUTO_TEST_CASE(LogSourceAnyFileReader) auto filename = CreateTestFile(); executor->Call([&] { logsources.SetAutoNewLine(true); }); executor->Call([&] { logsources.AddAnyFileReader(WStr(filename), true); }); - std::this_thread::sleep_for(200ms); - Lines lines; - executor->Call([&] { lines = logsources.GetLines(); }); + auto lines = WaitForLines(*executor, logsources, 5); BOOST_TEST(lines.size() == 5); } @@ -643,20 +666,24 @@ BOOST_AUTO_TEST_CASE(LogSourceAnyFileReaderResychronizeShrinkingFile) auto filename = CreateTestFile(); executor->Call([&] { logsources.SetAutoNewLine(true); }); executor->Call([&] { logsources.AddAnyFileReader(WStr(filename), true); }); - std::this_thread::sleep_for(200ms); - Lines lines; - executor->Call([&] { lines = logsources.GetLines(); }); + auto lines = WaitForLines(*executor, logsources, 5); BOOST_TEST(lines.size() == 5); RemoveLinesFromFile(GetTestFileName(), 2); + auto shrinkLines = WaitForLines(*executor, logsources, 1); + BOOST_TEST(shrinkLines.size() == 1); + if (!shrinkLines.empty()) + { + BOOST_TEST(shrinkLines.at(0).message.find("file shrank") != std::string::npos); + } + AppendToTestFile(); AppendToTestFile(); AppendToTestFile(); - std::this_thread::sleep_for(200ms); - executor->Call([&] { lines = logsources.GetLines(); }); - BOOST_TEST(lines.size() == 4); + auto appendLines = WaitForLines(*executor, logsources, 3); + BOOST_TEST(appendLines.size() == 3); } std::string GetTestFileAsString() @@ -737,11 +764,9 @@ BOOST_AUTO_TEST_CASE(LogSourceAnyFileReaderEmptyLines) auto filename = CreateAsciiTestFile(); executor->Call([&] { logsources.SetAutoNewLine(true); }); executor->Call([&] { logsources.AddAnyFileReader(WStr(filename), true); }); - std::this_thread::sleep_for(200ms); { - Lines lines; - executor->Call([&] { lines = logsources.GetLines(); }); + auto lines = WaitForLines(*executor, logsources, 4); BOOST_TEST(lines.size() == 4); BOOST_TEST(lines.at(0).message.find("tailing") != std::string::npos); BOOST_TEST(lines.at(1).message.find("first") != std::string::npos); @@ -766,9 +791,8 @@ BOOST_AUTO_TEST_CASE(LogSourceLoopbackOrdering) executor->Call([&] { logsources.AddMessage("Loopback message 2"); }); executor->Call([&] { logsources.AddMessage("Loopback message 3"); }); executor->Call([&] { logsources.AddAnyFileReader(WStr(filename), true); }); - std::this_thread::sleep_for(200ms); - Lines lines; - executor->Call([&] { lines = logsources.GetLines(); }); + + auto lines = WaitForLines(*executor, logsources, 7); BOOST_TEST(lines.at(0).message == "Loopback message 1"); BOOST_TEST(lines.at(1).message == "Loopback message 2");