From 6af42bb2c86715baee9022309ceba0ac8f5a18c0 Mon Sep 17 00:00:00 2001
From: Jeff Feasel <jfeasel@csa-iot.org>
Date: Sat, 22 Feb 2025 16:08:25 +0000
Subject: [PATCH 1/2] Initial

---
 .github/workflows/examples-esp32.yaml | 2 +-
 .github/workflows/qemu.yaml           | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/.github/workflows/examples-esp32.yaml b/.github/workflows/examples-esp32.yaml
index 3d3112d2972ecd..3aa14b43c74075 100644
--- a/.github/workflows/examples-esp32.yaml
+++ b/.github/workflows/examples-esp32.yaml
@@ -121,7 +121,7 @@ jobs:
         name: ESP32_1
 
         runs-on: ubuntu-latest
-        if: github.actor != 'restyled-io[bot]' &&  github.repository_owner == 'espressif'
+        if: github.actor != 'restyled-io[bot]'
 
         container:
             image: ghcr.io/project-chip/chip-build-esp32:94
diff --git a/.github/workflows/qemu.yaml b/.github/workflows/qemu.yaml
index f5868fa184ed24..fa33c8d836c56a 100644
--- a/.github/workflows/qemu.yaml
+++ b/.github/workflows/qemu.yaml
@@ -38,7 +38,7 @@ jobs:
             BUILD_TYPE: esp32-qemu
 
         runs-on: ubuntu-latest
-        if: github.actor != 'restyled-io[bot]' && github.repository_owner == 'espressif'
+        if: github.actor != 'restyled-io[bot]'
 
         container:
             image: ghcr.io/project-chip/chip-build-esp32-qemu:94

From c8cb4e61fa6e1ca18cd121d4faac7569f2728c94 Mon Sep 17 00:00:00 2001
From: Jeff Feasel <jfeasel@csa-iot.org>
Date: Sat, 22 Feb 2025 18:01:34 +0000
Subject: [PATCH 2/2] Enable platform tests

---
 src/BUILD.gn                                     |  2 +-
 .../GenericPlatformManagerImpl_FreeRTOS.ipp      | 16 ++++++++++++----
 src/platform/tests/BUILD.gn                      |  5 +++++
 src/platform/tests/TestPlatformMgr.cpp           | 16 +++++++++++++---
 src/platform/tests/TestPlatformTime.cpp          |  6 ++++++
 src/test_driver/esp32/CMakeLists.txt             |  1 +
 6 files changed, 38 insertions(+), 8 deletions(-)

diff --git a/src/BUILD.gn b/src/BUILD.gn
index 8eac76615c63c8..859e2e5356fb80 100644
--- a/src/BUILD.gn
+++ b/src/BUILD.gn
@@ -119,7 +119,7 @@ if (chip_build_tests) {
       tests += [ "${chip_root}/src/lib/dnssd/minimal_mdns/tests" ]
     }
 
-    if (chip_device_platform != "esp32" && chip_device_platform != "ameba") {
+    if (chip_device_platform != "ameba") {
       tests += [ "${chip_root}/src/platform/tests" ]
     }
 
diff --git a/src/include/platform/internal/GenericPlatformManagerImpl_FreeRTOS.ipp b/src/include/platform/internal/GenericPlatformManagerImpl_FreeRTOS.ipp
index 383e14fed3a680..43440dfb016c55 100644
--- a/src/include/platform/internal/GenericPlatformManagerImpl_FreeRTOS.ipp
+++ b/src/include/platform/internal/GenericPlatformManagerImpl_FreeRTOS.ipp
@@ -55,9 +55,7 @@ CHIP_ERROR GenericPlatformManagerImpl_FreeRTOS<ImplClass>::_InitChipStack(void)
     mChipTimerActive = false;
 
     // We support calling Shutdown followed by InitChipStack, because some tests
-    // do that.  To keep things simple for existing consumers, we keep not
-    // destroying our lock and queue in shutdown, but rather check whether they
-    // already exist here before trying to create them.
+    // do that.
 
     if (mChipStackLock == NULL)
     {
@@ -245,7 +243,7 @@ void GenericPlatformManagerImpl_FreeRTOS<ImplClass>::_RunEventLoop(void)
 
         BaseType_t eventReceived = pdFALSE;
         {
-            // Unlock the CHIP stack, allowing other threads to enter CHIP while
+        // Unlock the CHIP stack, allowing other threads to enter CHIP while
             // the event loop thread is sleeping.
             StackUnlock unlock;
             eventReceived = xQueueReceive(mChipEventQueue, &event, waitTime);
@@ -417,6 +415,16 @@ template <class ImplClass>
 void GenericPlatformManagerImpl_FreeRTOS<ImplClass>::_Shutdown(void)
 {
     GenericPlatformManagerImpl<ImplClass>::_Shutdown();
+
+    if (mChipEventQueue != NULL) {
+        vQueueDelete(mChipEventQueue);
+        mChipEventQueue = NULL;
+    }
+
+    if (mChipStackLock != NULL) {
+        vSemaphoreDelete(mChipStackLock);
+        mChipStackLock = NULL;
+    }
 }
 
 template <class ImplClass>
diff --git a/src/platform/tests/BUILD.gn b/src/platform/tests/BUILD.gn
index ba092e2f7ee5dd..f0823325790817 100644
--- a/src/platform/tests/BUILD.gn
+++ b/src/platform/tests/BUILD.gn
@@ -60,6 +60,11 @@ if (chip_device_platform != "none" && chip_device_platform != "fake") {
         "TestConfigurationMgr.cpp",
         "TestPlatformTime.cpp",
       ]
+
+      if (chip_device_platform == "esp32") {
+        # On esp32-qemu SleepMillis can sometimes undersleep by as much as 10ms.
+        defines = [ "CONFIG_WIDER_SLEEP_MARGIN" ]
+      }
     }
 
     if (chip_enable_openthread) {
diff --git a/src/platform/tests/TestPlatformMgr.cpp b/src/platform/tests/TestPlatformMgr.cpp
index 51ec10bf8766dc..5410fc58f0d245 100644
--- a/src/platform/tests/TestPlatformMgr.cpp
+++ b/src/platform/tests/TestPlatformMgr.cpp
@@ -85,6 +85,10 @@ TEST_F(TestPlatformMgr, BasicEventLoopTask)
     {
         EXPECT_EQ(PlatformMgr().StartEventLoopTask(), CHIP_NO_ERROR);
 
+        // Sleep for a short time to allow the event loop to start.
+        // Without this some platforms (e.g. esp32-qemu) will error.
+        chip::test_utils::SleepMillis(10);
+
         std::atomic<int> counterSync{ 2 };
 
         // Verify that the event loop will not exit until we tell it to by
@@ -148,10 +152,10 @@ TEST_F(TestPlatformMgr, BasicRunEventLoop)
 
     PlatformMgr().ScheduleWork(StopTheLoop);
 
-    EXPECT_FALSE(stopRan);
+     EXPECT_FALSE(stopRan);
     PlatformMgr().RunEventLoop();
-    EXPECT_TRUE(stopRan);
-    EXPECT_EQ(stopResult, CHIP_NO_ERROR);
+     EXPECT_TRUE(stopRan);
+     EXPECT_EQ(stopResult, CHIP_NO_ERROR);
 
     PlatformMgr().Shutdown();
 }
@@ -207,9 +211,15 @@ TEST_F(TestPlatformMgr, RunEventLoopStopBeforeSleep)
 
 TEST_F(TestPlatformMgr, TryLockChipStack)
 {
+    EXPECT_EQ(PlatformMgr().InitChipStack(), CHIP_NO_ERROR);
+
     bool locked = PlatformMgr().TryLockChipStack();
+    EXPECT_TRUE(locked);
+
     if (locked)
         PlatformMgr().UnlockChipStack();
+
+    PlatformMgr().Shutdown();
 }
 
 static int sEventRecieved = 0;
diff --git a/src/platform/tests/TestPlatformTime.cpp b/src/platform/tests/TestPlatformTime.cpp
index ad7a59052b21f4..7e69b36b30a649 100644
--- a/src/platform/tests/TestPlatformTime.cpp
+++ b/src/platform/tests/TestPlatformTime.cpp
@@ -42,7 +42,12 @@ using namespace chip::Logging;
 using namespace chip::System;
 using namespace chip::System::Clock::Literals;
 
+#ifdef CONFIG_WIDER_SLEEP_MARGIN
+// On esp32-qemu SleepMillis can sometimes undersleep by as much as 10ms.
+constexpr Clock::Milliseconds64 kTestTimeMarginMs = 10_ms64;
+#else
 constexpr Clock::Milliseconds64 kTestTimeMarginMs = 2_ms64;
+#endif
 constexpr Clock::Microseconds64 kTestTimeMarginUs = 500_us64;
 
 // =================================
@@ -108,6 +113,7 @@ TEST(TestDevice, GetMonotonicMilliseconds)
                         ChipLogValueX64(Tstart.count()), ChipLogValueX64(Tend.count()), ChipLogValueX64(Tdelta.count()),
                         ChipLogValueX64(Tdelay.count()));
 
+        //printf("+++x Tstart=%llu, Tend=%llu, Tdelta=%llu, (Tdelay=%llu - margin=%llu)=%llu\n", Tstart.count(), Tend.count(), Tdelta.count(), Tdelay.count(), margin.count(), (Tdelay - margin).count());
         // verify that timers don't fire early
         EXPECT_GT(Tdelta, (Tdelay - margin));
         // verify they're not too late
diff --git a/src/test_driver/esp32/CMakeLists.txt b/src/test_driver/esp32/CMakeLists.txt
index c1707cf082f555..1dea06ff1c6c77 100644
--- a/src/test_driver/esp32/CMakeLists.txt
+++ b/src/test_driver/esp32/CMakeLists.txt
@@ -53,6 +53,7 @@ esp32_unit_test(NAME testMinimalMdnsCore LIBRARY MinimalMdnsCoreTests)
 esp32_unit_test(NAME testMinimalMdnsRecords LIBRARY MinimalMdnsRecordsTests)
 esp32_unit_test(NAME testMinimalMdnsResponders LIBRARY MinimalMdnsRespondersTests)
 esp32_unit_test(NAME testMdns LIBRARY MdnsTests)
+esp32_unit_test(NAME testPlatform LIBRARY PlatformTests)
 esp32_unit_test(NAME testRetransmit LIBRARY RetransmitTests)
 esp32_unit_test(NAME testSetupPayload LIBRARY SetupPayloadTests)
 esp32_unit_test(NAME testSystemLayer LIBRARY SystemLayerTests)