Files
klubhaus-doorbell/libraries/FastLED/tests/test_ui_title_bug.cpp
2026-02-12 00:45:31 -08:00

120 lines
4.3 KiB
C++

// g++ --std=c++11 test.cpp
#include "test.h"
#include "test.h"
#include "fl/ui.h"
#include "platforms/shared/ui/json/ui.h"
#include "platforms/shared/ui/json/ui_internal.h"
#include "platforms/shared/ui/json/number_field.h"
#include "platforms/shared/ui/json/dropdown.h"
#include "platforms/shared/ui/json/title.h"
#include "platforms/shared/ui/json/description.h"
#include "platforms/shared/ui/json/audio.h"
#include "platforms/shared/ui/json/help.h"
#include "platforms/shared/ui/json/button.h"
#include "platforms/shared/ui/json/slider.h"
#include "platforms/shared/ui/json/checkbox.h"
#include "platforms/shared/ui/json/json_console.h"
#include "fl/sstream.h"
#include <cstring>
#include "fl/json.h"
#include "fl/ui.h"
#include "fl/namespace.h"
FASTLED_USING_NAMESPACE
TEST_CASE("UI Bug - Memory Corruption") {
// This test simulates the conditions that might lead to memory corruption
// in the UI system, particularly when components are destroyed while
// the JsonUiManager still holds references to them.
// Set up a handler to capture UI updates
fl::string capturedJsonOutput;
auto updateEngineState = fl::setJsonUiHandlers(
[&](const char* jsonStr) {
if (jsonStr) {
capturedJsonOutput = jsonStr;
}
}
);
CHECK(updateEngineState);
// Create UI components - these will be automatically registered
// with the JsonUiManager through their constructors
{
// Create components in a scope to test proper destruction
fl::UITitle title("Simple control of an xy path");
fl::UIDescription description("This is more of a test for new features.");
fl::UISlider offset("Offset", 0.0f, 0.0f, 1.0f, 0.01f);
fl::UISlider steps("Steps", 100.0f, 1.0f, 200.0f, 1.0f);
fl::UISlider length("Length", 1.0f, 0.0f, 1.0f, 0.01f);
// Process pending updates to serialize the components
fl::processJsonUiPendingUpdates();
// Verify that the components were properly serialized
CHECK(!capturedJsonOutput.empty());
// Simulate an update from the UI side
const char* updateJson = R"({
"Offset": 0.5,
"Steps": 150.0,
"Length": 0.75
})";
// Process the update - this should update the component values
updateEngineState(updateJson);
// Process pending updates again to verify everything still works
fl::processJsonUiPendingUpdates();
} // Components go out of scope here and should be properly destroyed
// // Create new components to verify the system is still functional
// fl::JsonTitleImpl newTitle("NewTitle", "New UI component");
// fl::processJsonUiPendingUpdates();
// // Verify that the new component is properly serialized
// CHECK(!capturedJsonOutput.empty());
// CHECK(capturedJsonOutput.find("NewTitle") != fl::string::npos);
// // Test component destruction with pending updates
// {
// fl::JsonSliderImpl tempSlider("TempSlider", 0.5f, 0.0f, 1.0f, 0.01f);
// fl::processJsonUiPendingUpdates();
// // Send an update for the component that's about to be destroyed
// const char* updateJson = R"({"TempSlider": 0.8})";
// updateEngineState(updateJson);
// // Component goes out of scope here - should be properly cleaned up
// // even with pending updates
// }
// // Verify that the system is still functional after component destruction
// fl::processJsonUiPendingUpdates();
// // Test with null update handler to verify cleanup
// auto nullUpdateEngineState = fl::setJsonUiHandlers(fl::function<void(const char*)>{});
// CHECK(!nullUpdateEngineState);
// // Reinstall handler
// updateEngineState = fl::setJsonUiHandlers(
// [&](const char* jsonStr) {
// if (jsonStr) {
// capturedJsonOutput = jsonStr;
// }
// }
// );
// CHECK(updateEngineState);
// // Final verification that the system works correctly
// fl::JsonDescriptionImpl finalDescription("Final verification description");
// fl::processJsonUiPendingUpdates();
// CHECK(!capturedJsonOutput.empty());
// CHECK(capturedJsonOutput.find("Final verification description") != fl::string::npos);
}