Procházet zdrojové kódy

test: Fix possible race in pthread C++ test

Also use TEST_ASSERT_EQUAL to get better debugging

Debugging intermittent UT failures on S2 release config

In the old version, the 300ms delay in between the two kinds of test
was supposed to keep the tasks in lockstep so it didn't matter that
global_sp was protected by two muxes.

However it seems like sometimes they could get out of sync -
I think because of a race in the sleep_until test. If the
second counter ticks over at that exact moment sleeping starts,
then the task doesn't sleep and will immediately keep running
 for the next iteration, possibly racing the other tasks.
Angus Gratton před 6 roky
rodič
revize
852462f4e2
1 změnil soubory, kde provedl 40 přidání a 35 odebrání
  1. 40 35
      components/pthread/test/test_pthread_cxx.cpp

+ 40 - 35
components/pthread/test/test_pthread_cxx.cpp

@@ -12,47 +12,50 @@
 #include "esp_log.h"
 const static char *TAG = "pthread_test";
 
-static std::shared_ptr<int> global_sp;
 static std::mutex           mtx;
+static std::shared_ptr<int> global_sp_mtx; // protected by mux
+
 static std::recursive_mutex recur_mtx;
+static std::shared_ptr<int> global_sp_recur_mtx; // protected by recursive mux
 
 static void thread_do_nothing() {}
 
 static void thread_main()
 {
-    int i = 0;
     std::cout << "thread_main CXX " << std::hex <<  std::this_thread::get_id() << std::endl;
-    std::chrono::milliseconds dur = std::chrono::milliseconds(300);
-
-    while (i < 3) {
-        int old_val, new_val;
-
-        // mux test
-        mtx.lock();
-        old_val = *global_sp;
-        std::this_thread::yield();
-        (*global_sp)++;
-        std::this_thread::yield();
-        new_val = *global_sp;
-        mtx.unlock();
-        std::cout << "thread " << std::hex << std::this_thread::get_id() << ": " << i++ << " val= " << *global_sp << std::endl;
-        TEST_ASSERT_TRUE(new_val == old_val + 1);
-
-        // sleep_for test
-        std::this_thread::sleep_for(dur);
-
-        // recursive mux test
-        recur_mtx.lock();
-        recur_mtx.lock();
-        old_val = *global_sp;
-        std::this_thread::yield();
-        (*global_sp)++;
-        std::this_thread::yield();
-        new_val = *global_sp;
-        recur_mtx.unlock();
-        recur_mtx.unlock();
-        std::cout << "thread " << std::hex << std::this_thread::get_id() << ": " << i++ << " val= " << *global_sp << std::endl;
-        TEST_ASSERT_TRUE(new_val == old_val + 1);
+    std::chrono::milliseconds dur = std::chrono::milliseconds(10);
+
+    for (int i = 0; i < 10; i++) {
+        for (int j = 0; j < 10; j++) {
+            int old_val, new_val;
+
+            // mux test
+            mtx.lock();
+            old_val = *global_sp_mtx;
+            std::this_thread::yield();
+            (*global_sp_mtx)++;
+            std::this_thread::yield();
+            new_val = *global_sp_mtx;
+            mtx.unlock();
+            std::cout << "thread " << std::hex << std::this_thread::get_id() << ": nrec " << i << " val= " << *global_sp_mtx << std::endl;
+            TEST_ASSERT_EQUAL(old_val + 1, new_val);
+
+            // sleep_for test
+            std::this_thread::sleep_for(dur);
+
+            // recursive mux test
+            recur_mtx.lock();
+            recur_mtx.lock();
+            old_val = *global_sp_recur_mtx;
+            std::this_thread::yield();
+            (*global_sp_recur_mtx)++;
+            std::this_thread::yield();
+            new_val = *global_sp_recur_mtx;
+            recur_mtx.unlock();
+            recur_mtx.unlock();
+            std::cout << "thread " << std::hex << std::this_thread::get_id() << ": rec " << i << " val= " << *global_sp_recur_mtx << std::endl;
+            TEST_ASSERT_EQUAL(old_val + 1, new_val);
+        }
 
         // sleep_until test
         using std::chrono::system_clock;
@@ -65,7 +68,8 @@ static void thread_main()
 
 TEST_CASE("pthread C++", "[pthread]")
 {
-    global_sp.reset(new int(1));
+    global_sp_mtx.reset(new int(1));
+    global_sp_recur_mtx.reset(new int(-1000));
 
     std::thread t1(thread_do_nothing);
     t1.join();
@@ -86,7 +90,8 @@ TEST_CASE("pthread C++", "[pthread]")
         t4.join();
     }
 
-    global_sp.reset(); // avoid reported leak
+    global_sp_mtx.reset(); // avoid reported leak
+    global_sp_recur_mtx.reset();
 }
 
 static void task_test_sandbox()