This is an automated email from the ASF dual-hosted git repository.

alexey pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/kudu.git


The following commit(s) were added to refs/heads/master by this push:
     new 026516a70 [util] improve MaintenanceManagerTest.TestRunningInstances
026516a70 is described below

commit 026516a704d071b5b8e3cc1cd7f7d66a649a0b2d
Author: Alexey Serbin <[email protected]>
AuthorDate: Thu Jan 30 10:01:26 2025 -0800

    [util] improve MaintenanceManagerTest.TestRunningInstances
    
    This patch introduces a ScopedCleanup instance to unregister maintenance
    operations registered by MaintenanceManagerTest.RunningInstances if
    ASSERT_EVENTUALLY triggers.  Also, the scenario is now more resilient to
    scheduler anomalies.  The motivation for this patch was a report
    on test failures [1] with the following TSAN warning due to CHECK()
    in MaintenanceOp::~MaintenanceOp():
    
      WARNING: ThreadSanitizer: data race on vptr (ctor/dtor vs virtual call)
    
    [1] 
http://dist-test.cloudera.org/job?job_id=jenkins-slave.1738131961.3963207
    
    Change-Id: I95f34e7cb8d37a0da4445012de40abfb2fe6f00e
    Reviewed-on: http://gerrit.cloudera.org:8080/22427
    Reviewed-by: Abhishek Chennaka <[email protected]>
    Tested-by: Kudu Jenkins
---
 src/kudu/util/maintenance_manager-test.cc | 59 +++++++++++++++++++++++--------
 1 file changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/kudu/util/maintenance_manager-test.cc 
b/src/kudu/util/maintenance_manager-test.cc
index ca16374b3..a00a7d61a 100644
--- a/src/kudu/util/maintenance_manager-test.cc
+++ b/src/kudu/util/maintenance_manager-test.cc
@@ -18,6 +18,7 @@
 #include "kudu/util/maintenance_manager.h"
 
 #include <algorithm>
+#include <array>
 #include <atomic>
 #include <cmath>
 #include <cstddef>
@@ -614,32 +615,60 @@ TEST_F(MaintenanceManagerTest, 
TestPrioritizeLogRetentionUnderMemoryPressure) {
 }
 
 // Test retrieving a list of an op's running instances
-TEST_F(MaintenanceManagerTest, TestRunningInstances) {
+TEST_F(MaintenanceManagerTest, RunningInstances) {
   TestMaintenanceOp op("op", MaintenanceOp::HIGH_IO_USAGE);
   op.set_perf_improvement(10);
   op.set_remaining_runs(2);
   op.set_sleep_time(MonoDelta::FromSeconds(1));
+
   manager_->RegisterOp(&op);
+  auto unregistrant = MakeScopedCleanup([&] {
+    manager_->UnregisterOp(&op);
+  });
 
   // Check that running instances are added to the maintenance manager's 
collection,
-  // and fields are getting filled.
+  // and fields are populated.
+  MaintenanceManagerStatusPB status_pb;
+  std::array<const MaintenanceManagerStatusPB_OpInstancePB*, 2> instances{ 
nullptr, nullptr };
   ASSERT_EVENTUALLY([&]() {
-      MaintenanceManagerStatusPB status_pb;
-      manager_->GetMaintenanceManagerStatusDump(&status_pb);
-      ASSERT_EQ(status_pb.running_operations_size(), 2);
-      const MaintenanceManagerStatusPB_OpInstancePB& instance1 = 
status_pb.running_operations(0);
-      const MaintenanceManagerStatusPB_OpInstancePB& instance2 = 
status_pb.running_operations(1);
-      ASSERT_EQ(instance1.name(), op.name());
-      ASSERT_NE(instance1.thread_id(), instance2.thread_id());
-    });
+    // Due to scheduler anomalies and other uncontrollable factors, the main
+    // thread might be put off CPU for some time, so at this point one or even
+    // two operations may be completed already.
+    manager_->GetMaintenanceManagerStatusDump(&status_pb);
+    const auto num_running = status_pb.running_operations_size();
+    ASSERT_GE(num_running, 0);
+    const auto num_completed = status_pb.completed_operations_size();
+    ASSERT_GE(num_completed, 0);
+
+    ASSERT_EQ(2, num_running + num_completed);
+    if (num_running == 2) {
+      instances[0] = &status_pb.running_operations(0);
+      instances[1] = &status_pb.running_operations(1);
+    } else if (num_completed == 2) {
+      instances[0] = &status_pb.completed_operations(0);
+      instances[1] = &status_pb.completed_operations(1);
+    } else {
+      instances[0] = &status_pb.running_operations(0);
+      instances[1] = &status_pb.completed_operations(0);
+    }
+  });
+  ASSERT_NE(nullptr, instances[0]);
+  ASSERT_NE(nullptr, instances[1]);
+  ASSERT_EQ(op.name(), instances[0]->name());
+  ASSERT_EQ(op.name(), instances[1]->name());
+  ASSERT_NE(instances[0]->thread_id(), instances[1]->thread_id());
 
-  // Wait for instances to complete.
-  manager_->UnregisterOp(&op);
+  // When unregistering operations, the maintenance manager waits for them
+  // to complete.
+  unregistrant.run();
 
   // Check that running instances are removed from collection after completion.
-  MaintenanceManagerStatusPB status_pb;
-  manager_->GetMaintenanceManagerStatusDump(&status_pb);
-  ASSERT_EQ(status_pb.running_operations_size(), 0);
+  {
+    MaintenanceManagerStatusPB status_pb;
+    manager_->GetMaintenanceManagerStatusDump(&status_pb);
+    ASSERT_EQ(0, status_pb.running_operations_size());
+    ASSERT_EQ(2, status_pb.completed_operations_size());
+  }
 }
 
 // Test adding operations and make sure that the history of recently completed

Reply via email to