Files
fahnen_esp32/.pio/libdeps/esp01_1m/FastLED/tests/test_time.cpp

248 lines
7.3 KiB
C++

#include "test.h"
#include "fl/time.h"
#ifdef FASTLED_TESTING
#include <thread>
#include <chrono>
#endif
namespace {
TEST_CASE("fl::time() basic functionality") {
// Test that fl::time() returns a reasonable value
fl::u32 t1 = fl::time();
CHECK(t1 >= 0); // Should always be >= 0
// Test that time advances
std::this_thread::sleep_for(std::chrono::milliseconds(10));
fl::u32 t2 = fl::time();
CHECK(t2 >= t1); // Time should advance or stay the same
// For most test environments, we expect some advancement
// Allow for a reasonable range considering test environment variability
if (t2 > t1) {
fl::u32 elapsed = t2 - t1;
CHECK(elapsed <= 100); // Should not advance more than 100ms in our sleep
}
}
TEST_CASE("fl::time() monotonic behavior") {
// Test that time is generally monotonic (always increases)
fl::u32 last_time = fl::time();
for (int i = 0; i < 10; ++i) {
std::this_thread::sleep_for(std::chrono::milliseconds(1));
fl::u32 current_time = fl::time();
CHECK(current_time >= last_time);
last_time = current_time;
}
}
TEST_CASE("fl::time() return type consistency") {
// Test that the function returns the expected type
auto result = fl::time();
static_assert(std::is_same_v<decltype(result), fl::u32>,
"fl::time() should return fl::u32");
// Test that it's compatible with arithmetic operations
fl::u32 time1 = fl::time();
fl::u32 time2 = time1 + 1000;
fl::u32 delta = time2 - time1;
CHECK_EQ(delta, 1000);
}
#ifdef FASTLED_TESTING
TEST_CASE("MockTimeProvider functionality") {
// Test MockTimeProvider basic functionality
fl::MockTimeProvider mock(1000);
// Test initial time
CHECK_EQ(mock.current_time(), 1000);
CHECK_EQ(mock(), 1000);
// Test advance
mock.advance(500);
CHECK_EQ(mock.current_time(), 1500);
CHECK_EQ(mock(), 1500);
// Test set_time
mock.set_time(2000);
CHECK_EQ(mock.current_time(), 2000);
CHECK_EQ(mock(), 2000);
// Test overflow behavior
mock.set_time(0xFFFFFFFF);
mock.advance(1);
CHECK_EQ(mock.current_time(), 0); // Should wrap around
}
TEST_CASE("fl::time() injection functionality") {
// Clear any existing provider first
fl::clear_time_provider();
SUBCASE("Basic time injection") {
// Test that time injection works correctly
fl::MockTimeProvider mock(5000);
// Create a lambda that captures the mock by reference
auto provider = [&mock]() -> fl::u32 {
return mock.current_time();
};
fl::inject_time_provider(provider);
// Verify injected time is used
CHECK_EQ(fl::time(), 5000);
// Test that changes to mock are reflected
mock.advance(250);
CHECK_EQ(fl::time(), 5250);
mock.set_time(10000);
CHECK_EQ(fl::time(), 10000);
// Clear provider and verify normal behavior resumes
fl::clear_time_provider();
fl::u32 normal_time = fl::time();
// Normal time should be different from our mock time
// (unless we're extremely unlucky with timing)
CHECK(normal_time != 10000);
}
SUBCASE("Lambda injection") {
// Test injection with a custom lambda
fl::u32 custom_time = 12345;
auto provider = [&custom_time]() -> fl::u32 {
return custom_time;
};
fl::inject_time_provider(provider);
CHECK_EQ(fl::time(), 12345);
custom_time = 54321;
CHECK_EQ(fl::time(), 54321);
fl::clear_time_provider();
}
SUBCASE("Multiple clear calls safety") {
// Test that multiple clear calls are safe
fl::clear_time_provider();
fl::clear_time_provider();
fl::clear_time_provider();
// Should still work normally
fl::u32 time1 = fl::time();
std::this_thread::sleep_for(std::chrono::milliseconds(1));
fl::u32 time2 = fl::time();
CHECK(time2 >= time1);
}
SUBCASE("Thread safety test") {
// Basic thread safety test - simplified to avoid race conditions
fl::MockTimeProvider mock(1000);
// Create provider lambda
auto provider = [&mock]() -> fl::u32 {
return mock.current_time();
};
// Test that multiple inject/clear cycles work
for (int i = 0; i < 5; ++i) {
fl::inject_time_provider(provider);
CHECK_EQ(fl::time(), 1000);
fl::clear_time_provider();
// After clearing, fl::time() should return platform time (not mock time)
fl::u32 platform_time = fl::time();
// For the first iteration, we allow the platform time to potentially match mock time
bool time_is_valid = (platform_time != 1000) || (i == 0);
CHECK(time_is_valid);
}
// Final verification
fl::clear_time_provider();
fl::u32 final_time = fl::time();
CHECK(final_time >= 0);
}
// Always clear provider after injection tests
fl::clear_time_provider();
}
TEST_CASE("fl::time() wraparound behavior") {
// Test wraparound behavior with mock time
fl::clear_time_provider();
fl::MockTimeProvider mock(0xFFFFFFFE); // Near maximum
// Create a lambda that captures the mock by reference
auto provider = [&mock]() -> fl::u32 {
return mock.current_time();
};
fl::inject_time_provider(provider);
fl::u32 time1 = fl::time();
CHECK_EQ(time1, 0xFFFFFFFE);
mock.advance(1);
fl::u32 time2 = fl::time();
CHECK_EQ(time2, 0xFFFFFFFF);
mock.advance(1);
fl::u32 time3 = fl::time();
CHECK_EQ(time3, 0); // Should wrap to 0
// Test that elapsed time calculation works across wraparound
mock.set_time(0xFFFFFFFE);
fl::u32 start_time = fl::time();
mock.set_time(2); // Wrapped around
fl::u32 end_time = fl::time();
// Calculate elapsed time with wraparound handling
fl::u32 elapsed = end_time - start_time; // Should naturally wrap
CHECK_EQ(elapsed, 4); // 0xFFFFFFFE -> 0xFFFFFFFF (1) -> 0 (2) -> 1 (3) -> 2 (4)
fl::clear_time_provider();
}
#endif // FASTLED_TESTING
// Test realistic usage patterns
TEST_CASE("fl::time() animation timing patterns") {
// Test a typical animation timing pattern
fl::u32 last_frame = fl::time();
int frame_count = 0;
for (int i = 0; i < 5; ++i) {
std::this_thread::sleep_for(std::chrono::milliseconds(10));
fl::u32 now = fl::time();
if (now - last_frame >= 16) { // ~60 FPS
frame_count++;
last_frame = now;
}
}
// We should have gotten at least a few frames
CHECK(frame_count >= 0);
}
TEST_CASE("fl::time() timeout handling patterns") {
// Test timeout calculation
fl::u32 start = fl::time();
fl::u32 timeout = start + 50; // 50ms timeout
bool completed = false;
while (fl::time() < timeout && !completed) {
std::this_thread::sleep_for(std::chrono::milliseconds(1));
// Simulate some work that might complete
if (fl::time() - start >= 25) {
completed = true;
}
}
CHECK((completed || fl::time() >= timeout));
}
} // anonymous namespace