Author: Charles Zablit
Date: 2026-08-13T15:00:52+01:00
New Revision: e0ab0d2cda0847b7b6f883356b76eeec35148edd

URL: 
https://github.com/llvm/llvm-project/commit/e0ab0d2cda0847b7b6f883356b76eeec35148edd
DIFF: 
https://github.com/llvm/llvm-project/commit/e0ab0d2cda0847b7b6f883356b76eeec35148edd.diff

LOG: [lldb] Don't assume a category dump order in TimeTest (#213100)

There is no guarantee that the categories are sorted by the time they
took to finish. This is especially flaky on a loaded host, causing the
test to fail.

Find the categories by their name instead. This fixes TimeTest being
flaky (on Windows).

Added: 
    

Modified: 
    lldb/unittests/Utility/TimerTest.cpp

Removed: 
    


################################################################################
diff  --git a/lldb/unittests/Utility/TimerTest.cpp 
b/lldb/unittests/Utility/TimerTest.cpp
index b371ebff4fe77..4b97cd14026d8 100644
--- a/lldb/unittests/Utility/TimerTest.cpp
+++ b/lldb/unittests/Utility/TimerTest.cpp
@@ -6,13 +6,51 @@
 //
 
//===----------------------------------------------------------------------===//
 
-#include "lldb/Utility/StreamString.h"
 #include "lldb/Utility/Timer.h"
+#include "lldb/Utility/StreamString.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Regex.h"
 #include "gtest/gtest.h"
+#include <optional>
 #include <thread>
 
 using namespace lldb_private;
 
+namespace {
+struct CategoryStats {
+  double seconds;
+  double total;
+  double child;
+  int count;
+};
+
+/// Finds the line describing \p category in a DumpCategoryTimes() dump and
+/// parses its statistics. A line looks like:
+///   0.105202764 sec (total: 0.132s; child: 0.027s; count: 1) for CAT1
+std::optional<CategoryStats> ParseCategory(llvm::StringRef dump,
+                                           llvm::StringRef category) {
+  llvm::Regex line_pattern(R"(^([0-9.]+) sec \(total: ([0-9.]+)s; )"
+                           R"(child: ([0-9.]+)s; count: ([0-9]+)\) for 
(.+)$)");
+  for (llvm::StringRef line : llvm::split(dump, '\n')) {
+    llvm::SmallVector<llvm::StringRef, 6> matches;
+    if (!line_pattern.match(line.trim(), &matches))
+      continue;
+    if (matches[5] != category)
+      continue;
+    CategoryStats stats;
+    if (matches[1].getAsDouble(stats.seconds) ||
+        matches[2].getAsDouble(stats.total) ||
+        matches[3].getAsDouble(stats.child) ||
+        matches[4].getAsInteger(10, stats.count))
+      return std::nullopt;
+    return stats;
+  }
+  return std::nullopt;
+}
+} // namespace
+
 TEST(TimerTest, CategoryTimes) {
   Timer::ResetCategoryTimes();
   {
@@ -60,16 +98,14 @@ TEST(TimerTest, CategoryTimes2) {
   }
   StreamString ss;
   Timer::DumpCategoryTimes(ss);
-  double seconds1, seconds2;
-  ASSERT_EQ(2, sscanf(ss.GetData(),
-                      "%lf sec (total: %*fs; child: %*fs; count: %*d) for "
-                      "CAT1%*[\n ]%lf sec for CAT2",
-                      &seconds1, &seconds2))
-      << "String: " << ss.GetData();
-  EXPECT_LT(0.01, seconds1);
-  EXPECT_GT(1, seconds1);
-  EXPECT_LT(0.001, seconds2);
-  EXPECT_GT(0.1, seconds2);
+  std::optional<CategoryStats> cat1 = ParseCategory(ss.GetString(), "CAT1");
+  std::optional<CategoryStats> cat2 = ParseCategory(ss.GetString(), "CAT2");
+  ASSERT_TRUE(cat1.has_value()) << "String: " << ss.GetData();
+  ASSERT_TRUE(cat2.has_value()) << "String: " << ss.GetData();
+  EXPECT_LT(0.01, cat1->seconds);
+  EXPECT_GT(1, cat1->seconds);
+  EXPECT_LT(0.001, cat2->seconds);
+  EXPECT_GT(0.1, cat2->seconds);
 }
 
 TEST(TimerTest, CategoryTimesStats) {
@@ -88,21 +124,14 @@ TEST(TimerTest, CategoryTimesStats) {
       std::this_thread::sleep_for(std::chrono::milliseconds(10));
     }
   }
-  // Example output:
-  // 0.105202764 sec (total: 0.132s; child: 0.027s; count: 1) for CAT1
-  // 0.026772798 sec (total: 0.027s; child: 0.000s; count: 2) for CAT2
   StreamString ss;
   Timer::DumpCategoryTimes(ss);
-  double seconds1, total1, child1, seconds2;
-  int count1, count2;
-  ASSERT_EQ(
-      6, sscanf(ss.GetData(),
-                "%lf sec (total: %lfs; child: %lfs; count: %d) for CAT1%*[\n\r 
]"
-                "%lf sec (total: %*fs; child: %*fs; count: %d) for CAT2",
-                &seconds1, &total1, &child1, &count1, &seconds2, &count2))
-      << "String: " << ss.GetData();
-  EXPECT_NEAR(total1 - child1, seconds1, 0.002);
-  EXPECT_EQ(1, count1);
-  EXPECT_NEAR(child1, seconds2, 0.002);
-  EXPECT_EQ(2, count2);
+  std::optional<CategoryStats> cat1 = ParseCategory(ss.GetString(), "CAT1");
+  std::optional<CategoryStats> cat2 = ParseCategory(ss.GetString(), "CAT2");
+  ASSERT_TRUE(cat1.has_value()) << "String: " << ss.GetData();
+  ASSERT_TRUE(cat2.has_value()) << "String: " << ss.GetData();
+  EXPECT_NEAR(cat1->total - cat1->child, cat1->seconds, 0.002);
+  EXPECT_EQ(1, cat1->count);
+  EXPECT_NEAR(cat1->child, cat2->seconds, 0.002);
+  EXPECT_EQ(2, cat2->count);
 }


        
_______________________________________________
lldb-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to