Ver Fonte

Non lambda unit tests

Anatoli Arkhipenko há 5 meses atrás
pai
commit
250b1ace60

+ 2 - 1
.github/workflows/test.yml

@@ -52,7 +52,8 @@ jobs:
           # Only include the specific test file we want to run
           set(TEST_SOURCES
               "${CMAKE_SOURCE_DIR}/tests/test-scheduler-basic.cpp"
-              "${CMAKE_SOURCE_DIR}/tests/test-scheduler-basic-thorough.cpp"
+              "${CMAKE_SOURCE_DIR}/tests/test-scheduler-basic-thorough-no-lambda.cpp"
+              "${CMAKE_SOURCE_DIR}/tests/test-scheduler-advanced-features-no-lambda.cpp"
           )
 
           # Check if we have test files

+ 1227 - 0
tests/test-scheduler-advanced-features-no-lambda.cpp

@@ -0,0 +1,1227 @@
+// test-scheduler-advanced-features-no-lambda.cpp - Advanced TaskScheduler features without lambda functions
+// This file contains comprehensive tests for advanced TaskScheduler functionality
+// enabled by specific compile-time directives, using traditional function pointers
+//
+// =====================================================================================
+// ADVANCED FEATURES TEST PLAN AND COVERAGE MATRIX (NO LAMBDA VERSION)
+// =====================================================================================
+//
+// PURPOSE: Validate advanced TaskScheduler features without lambda functions
+// APPROACH: Traditional function pointers for maximum platform compatibility
+// SCOPE: Advanced features requiring specific compile-time directives
+//
+// COMPILE DIRECTIVES TESTED:
+// - _TASK_STATUS_REQUEST:      Event-driven task coordination and status signaling
+// - _TASK_TIMEOUT:             Task execution timeout and deadline management
+// - _TASK_SCHEDULING_OPTIONS:  Advanced scheduling behavior control
+// - _TASK_SELF_DESTRUCT:       Automatic task cleanup and memory management
+//
+// COVERAGE MATRIX:
+// ================
+//
+// 1. STATUS REQUEST FUNCTIONALITY (_TASK_STATUS_REQUEST)
+//    ├── StatusRequest Creation and Management
+//    │   ├── StatusRequest() constructor
+//    │   ├── setWaiting(count) - prepare for multiple signals
+//    │   ├── signal(status) - signal completion from tasks
+//    │   ├── signalComplete(status) - force immediate completion
+//    │   ├── pending() - check if still waiting
+//    │   ├── completed() - check if finished
+//    │   ├── getStatus() - retrieve completion status
+//    │   └── getCount() - get remaining signal count
+//    │
+//    ├── Task Status Request Integration
+//    │   ├── waitFor(StatusRequest*, interval, iterations) - wait for event
+//    │   ├── waitForDelayed(StatusRequest*, interval, iterations) - delayed wait
+//    │   ├── getStatusRequest() - get external status request
+//    │   └── getInternalStatusRequest() - get task's internal status
+//    │
+//    └── Event-Driven Task Coordination Patterns
+//        ├── Single task waiting for event completion
+//        ├── Multiple tasks waiting for same event
+//        ├── Task chains with dependency resolution
+//        └── Producer-consumer coordination scenarios
+//
+// 2. TIMEOUT FUNCTIONALITY (_TASK_TIMEOUT)
+//    ├── Task Timeout Management
+//    │   ├── setTimeout(timeout, reset) - set execution deadline
+//    │   ├── resetTimeout() - restart timeout timer
+//    │   ├── getTimeout() - retrieve timeout value
+//    │   ├── untilTimeout() - time remaining until timeout
+//    │   └── isTimedOut() - check timeout status
+//    │
+//    ├── StatusRequest Timeout Integration
+//    │   ├── StatusRequest::setTimeout(timeout) - set request deadline
+//    │   ├── StatusRequest::resetTimeout() - restart request timer
+//    │   ├── StatusRequest::getTimeout() - retrieve request timeout
+//    │   └── StatusRequest::untilTimeout() - time until request expires
+//    │
+//    └── Timeout Behavior Patterns
+//        ├── Task execution timeout handling
+//        ├── StatusRequest completion timeout
+//        ├── Timeout-driven task disabling
+//        └── Deadline-based task prioritization
+//
+// 3. SCHEDULING OPTIONS (_TASK_SCHEDULING_OPTIONS)
+//    ├── Scheduling Behavior Control
+//    │   ├── setSchedulingOption(option) - configure task behavior
+//    │   ├── getSchedulingOption() - retrieve current option
+//    │   └── Scheduling option effects on execution
+//    │
+//    └── Advanced Scheduling Patterns
+//        ├── Priority-based execution control
+//        ├── Conditional execution behavior
+//        └── Resource allocation management
+//
+// 4. SELF-DESTRUCT FUNCTIONALITY (_TASK_SELF_DESTRUCT)
+//    ├── Automatic Task Cleanup
+//    │   ├── Task auto-removal from scheduler
+//    │   ├── Memory management and resource cleanup
+//    │   └── Lifecycle-based task destruction
+//    │
+//    └── Self-Destruct Patterns
+//        ├── One-shot tasks with auto-cleanup
+//        ├── Conditional task removal
+//        └── Dynamic task lifecycle management
+//
+// 5. INTEGRATION AND ADVANCED PATTERNS
+//    ├── Multi-Feature Integration Tests
+//    │   ├── Status requests with timeout handling
+//    │   ├── Self-destructing tasks with status coordination
+//    │   ├── Scheduling options with timeout management
+//    │   └── Complex event-driven workflows
+//    │
+//    ├── Real-World Usage Scenarios
+//    │   ├── Sensor data collection with timeouts
+//    │   ├── Multi-stage processing pipelines
+//    │   ├── Resource monitoring and cleanup
+//    │   └── Deadline-driven task orchestration
+//    │
+//    └── Edge Cases and Error Handling
+//        ├── Timeout during status request waiting
+//        ├── Self-destruct during active coordination
+//        ├── Invalid scheduling option handling
+//        └── Resource cleanup on abnormal termination
+//
+// =====================================================================================
+
+// Enable all advanced features for comprehensive testing
+#define _TASK_STATUS_REQUEST        // Event-driven task coordination
+#define _TASK_TIMEOUT              // Task execution deadlines
+#define _TASK_SCHEDULING_OPTIONS   // Advanced scheduling control
+#define _TASK_SELF_DESTRUCT        // Automatic task cleanup
+
+#include <gtest/gtest.h>
+#include "Arduino.h"
+#include "TaskScheduler.h"
+
+// Global test state for advanced features
+std::vector<std::string> advanced_test_output;
+int advanced_callback_counter = 0;
+bool status_received = false;
+int last_status_code = 0;
+bool timeout_occurred = false;
+bool task_self_destructed = false;
+
+// Global pointers for task-to-task communication
+static StatusRequest* global_status_request = nullptr;
+
+// Test callback functions (no lambda functions)
+
+/**
+ * @brief Advanced callback function for status request testing
+ *
+ * Records execution and can signal status request completion.
+ * Used for testing event-driven task coordination patterns.
+ */
+void advanced_status_callback() {
+    advanced_callback_counter++;
+    advanced_test_output.push_back("status_task_executed");
+    std::cout << "Status task executed at " << millis() << "ms" << std::endl;
+}
+
+/**
+ * @brief Producer callback that signals status request completion
+ *
+ * Simulates a task that produces events or completes work that
+ * other tasks are waiting for. Essential for testing coordination.
+ */
+void producer_callback() {
+    advanced_callback_counter++;
+    advanced_test_output.push_back("producer_completed");
+
+    // Signal the global status request if it exists
+    if (global_status_request != nullptr) {
+        global_status_request->signalComplete(100); // Success status
+    }
+
+    std::cout << "Producer completed at " << millis() << "ms" << std::endl;
+}
+
+/**
+ * @brief Consumer callback for status request waiting
+ *
+ * Represents tasks that wait for specific events before executing.
+ * Used to test event-driven coordination and dependency management.
+ */
+void consumer_callback() {
+    advanced_callback_counter++;
+    advanced_test_output.push_back("consumer_executed");
+    std::cout << "Consumer executed at " << millis() << "ms" << std::endl;
+}
+
+/**
+ * @brief First consumer callback for multi-consumer tests
+ */
+void consumer1_callback() {
+    advanced_callback_counter++;
+    advanced_test_output.push_back("consumer1_executed");
+}
+
+/**
+ * @brief Second consumer callback for multi-consumer tests
+ */
+void consumer2_callback() {
+    advanced_callback_counter++;
+    advanced_test_output.push_back("consumer2_executed");
+}
+
+/**
+ * @brief Third consumer callback for multi-consumer tests
+ */
+void consumer3_callback() {
+    advanced_callback_counter++;
+    advanced_test_output.push_back("consumer3_executed");
+}
+
+/**
+ * @brief Timeout-sensitive callback for deadline testing
+ *
+ * Callback that tracks timeout conditions and handles deadline-based
+ * execution scenarios. Critical for testing timeout functionality.
+ */
+void timeout_sensitive_callback() {
+    advanced_callback_counter++;
+    advanced_test_output.push_back("timeout_task_executed");
+    // This callback can be used to test timeout behavior
+}
+
+/**
+ * @brief Self-destructing task callback for cleanup testing
+ *
+ * Callback for tasks that are designed to clean themselves up
+ * after execution. Used to test automatic resource management.
+ */
+void self_destruct_callback() {
+    advanced_callback_counter++;
+    advanced_test_output.push_back("self_destruct_executed");
+    task_self_destructed = true;
+}
+
+/**
+ * @brief Callback for multi-step yield testing - step 1
+ */
+void yield_step1_callback() {
+    advanced_test_output.push_back("step_1");
+}
+
+/**
+ * @brief Callback for multi-step yield testing - step 2
+ */
+void yield_step2_callback() {
+    advanced_test_output.push_back("step_2");
+}
+
+/**
+ * @brief Callback for waiter task 1 in coordination scenarios
+ */
+void waiter1_callback() {
+    advanced_callback_counter++;
+    advanced_test_output.push_back("waiter1_executed");
+}
+
+/**
+ * @brief Callback for waiter task 2 in coordination scenarios
+ */
+void waiter2_callback() {
+    advanced_callback_counter++;
+    advanced_test_output.push_back("waiter2_executed");
+}
+
+/**
+ * @brief Callback for waiter task 3 in coordination scenarios
+ */
+void waiter3_callback() {
+    advanced_callback_counter++;
+    advanced_test_output.push_back("waiter3_executed");
+}
+
+/**
+ * @brief Test fixture class for advanced TaskScheduler features
+ *
+ * Provides setup and teardown for advanced feature tests, ensuring
+ * clean state between tests and utility methods for complex scenarios.
+ */
+class AdvancedSchedulerTest : public ::testing::Test {
+protected:
+    /**
+     * @brief Set up test environment for advanced features
+     *
+     * Clears all test state and initializes timing system.
+     * Prepares environment for testing complex feature interactions.
+     */
+    void SetUp() override {
+        clearAdvancedTestOutput();
+        advanced_callback_counter = 0;
+        status_received = false;
+        last_status_code = 0;
+        timeout_occurred = false;
+        task_self_destructed = false;
+        global_status_request = nullptr;
+        millis(); // Initialize timing
+    }
+
+    /**
+     * @brief Clean up test environment after advanced feature tests
+     *
+     * Ensures no test artifacts affect subsequent tests.
+     * Critical for maintaining test isolation in complex scenarios.
+     */
+    void TearDown() override {
+        clearAdvancedTestOutput();
+        advanced_callback_counter = 0;
+        status_received = false;
+        last_status_code = 0;
+        timeout_occurred = false;
+        task_self_destructed = false;
+        global_status_request = nullptr;
+    }
+
+    /**
+     * @brief Helper to run scheduler until condition or timeout for advanced tests
+     *
+     * Enhanced version that handles complex conditions involving multiple
+     * tasks, status requests, and timeout scenarios.
+     */
+    bool runAdvancedSchedulerUntil(Scheduler& ts, std::function<bool()> condition, unsigned long timeout_ms = 2000) {
+        return waitForCondition([&]() {
+            ts.execute();
+            return condition();
+        }, timeout_ms);
+    }
+
+    /**
+     * @brief Clear advanced test output buffer
+     */
+    void clearAdvancedTestOutput() {
+        advanced_test_output.clear();
+    }
+
+    /**
+     * @brief Get count of advanced test output entries
+     */
+    size_t getAdvancedTestOutputCount() {
+        return advanced_test_output.size();
+    }
+
+    /**
+     * @brief Get specific advanced test output entry
+     */
+    std::string getAdvancedTestOutput(size_t index) {
+        if (index < advanced_test_output.size()) {
+            return advanced_test_output[index];
+        }
+        return "";
+    }
+};
+
+// ================== STATUS REQUEST CREATION AND MANAGEMENT TESTS ==================
+
+/**
+ * @brief Test StatusRequest constructor and basic state management
+ *
+ * TESTS: StatusRequest(), setWaiting(), pending(), completed()
+ *
+ * PURPOSE: Verify that StatusRequest objects can be created and their
+ * basic state management methods work correctly, providing foundation
+ * for event-driven task coordination.
+ *
+ * STATUS REQUEST LIFECYCLE:
+ * - Constructor: Creates StatusRequest in completed state (count=0)
+ * - setWaiting(count): Prepares to receive 'count' signal() calls
+ * - pending(): Returns true while count > 0
+ * - completed(): Returns true when count == 0
+ * - State transitions control task execution timing
+ *
+ * TEST SCENARIO:
+ * 1. Create StatusRequest and verify initial completed state
+ * 2. Set waiting for 3 signals and verify pending state
+ * 3. Verify completed() and pending() return correct values
+ * 4. Test state consistency across multiple checks
+ *
+ * EXPECTATIONS:
+ * - Initial state: completed() = true, pending() = false
+ * - After setWaiting(3): completed() = false, pending() = true
+ * - State methods return consistent, expected values
+ *
+ * IMPORTANCE: Basic state management is foundation for all event-driven
+ * coordination patterns. Reliable state tracking ensures proper task
+ * synchronization and prevents race conditions.
+ */
+TEST_F(AdvancedSchedulerTest, StatusRequestBasicState) {
+    StatusRequest sr;
+
+    // Initial state should be completed
+    EXPECT_TRUE(sr.completed());
+    EXPECT_FALSE(sr.pending());
+    EXPECT_EQ(sr.getCount(), 0);
+    EXPECT_EQ(sr.getStatus(), 0);
+
+    // Set waiting for 3 signals
+    sr.setWaiting(3);
+    EXPECT_FALSE(sr.completed());
+    EXPECT_TRUE(sr.pending());
+    EXPECT_EQ(sr.getCount(), 3);
+    EXPECT_EQ(sr.getStatus(), 0); // Status reset by setWaiting
+}
+
+/**
+ * @brief Test StatusRequest signal() method for incremental completion
+ *
+ * TESTS: signal(status), getStatus(), getCount()
+ *
+ * PURPOSE: Verify that signal() correctly decrements the waiting count
+ * and manages status codes, enabling coordinated completion tracking
+ * across multiple signaling tasks.
+ *
+ * SIGNAL BEHAVIOR:
+ * - signal(): Decrements count by 1, sets status if provided
+ * - signal(status): Same as signal() but with custom status code
+ * - Returns true when StatusRequest becomes complete (count reaches 0)
+ * - Status code from last signal() call is preserved
+ * - Negative status codes cause immediate completion (error handling)
+ *
+ * TEST SCENARIO:
+ * 1. Set StatusRequest waiting for 3 signals
+ * 2. Send 2 normal signals and verify count decrements
+ * 3. Send final signal with status code and verify completion
+ * 4. Test negative status code causing immediate completion
+ *
+ * EXPECTATIONS:
+ * - Each signal() decrements count by 1
+ * - Status code is updated with each signal
+ * - signal() returns true only when count reaches 0
+ * - Negative status causes immediate completion
+ *
+ * IMPORTANCE: Incremental signaling enables complex coordination
+ * patterns where multiple tasks contribute to completion condition.
+ * Status codes provide error handling and completion context.
+ */
+TEST_F(AdvancedSchedulerTest, StatusRequestSignaling) {
+    StatusRequest sr;
+    sr.setWaiting(3);
+
+    // Send first signal
+    bool complete = sr.signal();
+    EXPECT_FALSE(complete);
+    EXPECT_EQ(sr.getCount(), 2);
+    EXPECT_TRUE(sr.pending());
+
+    // Send second signal with status
+    complete = sr.signal(42);
+    EXPECT_FALSE(complete);
+    EXPECT_EQ(sr.getCount(), 1);
+    EXPECT_EQ(sr.getStatus(), 42);
+
+    // Send final signal
+    complete = sr.signal(99);
+    EXPECT_TRUE(complete);
+    EXPECT_EQ(sr.getCount(), 0);
+    EXPECT_EQ(sr.getStatus(), 99);
+    EXPECT_TRUE(sr.completed());
+
+    // Test negative status for immediate completion
+    sr.setWaiting(5);
+    complete = sr.signal(-1); // Negative status should complete immediately
+    EXPECT_TRUE(complete);
+    EXPECT_EQ(sr.getCount(), 0);
+    EXPECT_EQ(sr.getStatus(), -1);
+}
+
+/**
+ * @brief Test StatusRequest signalComplete() method for immediate completion
+ *
+ * TESTS: signalComplete(status)
+ *
+ * PURPOSE: Verify that signalComplete() immediately completes the StatusRequest
+ * regardless of remaining count, enabling emergency completion and
+ * error handling scenarios.
+ *
+ * SIGNAL COMPLETE BEHAVIOR:
+ * - signalComplete(): Immediately sets count to 0 (completed state)
+ * - signalComplete(status): Same as above but with custom status code
+ * - Bypasses incremental signaling for immediate completion
+ * - Useful for error conditions and emergency shutdowns
+ * - Always results in completed state regardless of initial count
+ *
+ * TEST SCENARIO:
+ * 1. Set StatusRequest waiting for large number of signals
+ * 2. Call signalComplete() and verify immediate completion
+ * 3. Test signalComplete() with custom status code
+ * 4. Verify no further signals are processed after completion
+ *
+ * EXPECTATIONS:
+ * - signalComplete() immediately sets count to 0
+ * - Status code is set if provided
+ * - completed() returns true immediately
+ * - Further signals have no effect (idempotent)
+ *
+ * IMPORTANCE: Immediate completion enables error handling, emergency
+ * shutdown, and abort scenarios in complex coordination patterns.
+ * Critical for robust event-driven systems.
+ */
+TEST_F(AdvancedSchedulerTest, StatusRequestSignalComplete) {
+    StatusRequest sr;
+    sr.setWaiting(10); // Large count for testing immediate completion
+
+    // Signal complete should immediately finish
+    sr.signalComplete(200);
+    EXPECT_TRUE(sr.completed());
+    EXPECT_FALSE(sr.pending());
+    EXPECT_EQ(sr.getCount(), 0);
+    EXPECT_EQ(sr.getStatus(), 200);
+
+    // Further signals should have no effect
+    sr.signal(999);
+    EXPECT_EQ(sr.getStatus(), 200); // Should remain unchanged
+    EXPECT_EQ(sr.getCount(), 0);    // Should remain completed
+}
+
+// ================== TASK STATUS REQUEST INTEGRATION TESTS ==================
+
+/**
+ * @brief Test Task waitFor() method for event-driven task execution
+ *
+ * TESTS: waitFor(StatusRequest*, interval, iterations)
+ *
+ * PURPOSE: Verify that tasks can wait for external StatusRequest completion
+ * before executing, enabling event-driven coordination and dependency
+ * management between tasks.
+ *
+ * WAIT FOR BEHAVIOR:
+ * - waitFor(): Configures task to wait for StatusRequest completion
+ * - Task becomes enabled but won't execute until StatusRequest completes
+ * - interval and iterations configure post-completion behavior
+ * - Task executes immediately when StatusRequest is already complete
+ * - Enables producer-consumer and dependency coordination patterns
+ *
+ * TEST SCENARIO:
+ * 1. Create StatusRequest in pending state
+ * 2. Create task configured to waitFor() the StatusRequest
+ * 3. Verify task doesn't execute while StatusRequest is pending
+ * 4. Complete StatusRequest and verify task executes
+ * 5. Test with already-completed StatusRequest
+ *
+ * EXPECTATIONS:
+ * - Task enabled but doesn't execute while StatusRequest pending
+ * - Task executes immediately after StatusRequest completion
+ * - Task with completed StatusRequest executes immediately
+ * - Task follows normal interval/iteration behavior after first execution
+ *
+ * IMPORTANCE: Event-driven task execution enables sophisticated coordination
+ * patterns essential for multi-task workflows, data processing pipelines,
+ * and resource synchronization scenarios.
+ */
+TEST_F(AdvancedSchedulerTest, TaskWaitForStatusRequest) {
+    Scheduler ts;
+    StatusRequest sr;
+
+    // Set up StatusRequest in pending state
+    sr.setWaiting(1);
+
+    // Create task that waits for status request
+    Task waiter(100, 2, &consumer_callback, &ts);
+    waiter.waitFor(&sr, 50, 2);
+
+    // Task should be enabled but not execute while SR is pending
+    EXPECT_TRUE(waiter.isEnabled());
+
+    // Run scheduler - task should not execute yet
+    delay(100);
+    ts.execute();
+    EXPECT_EQ(advanced_callback_counter, 0);
+
+    // Complete the status request
+    sr.signalComplete();
+
+    // Now task should execute
+    bool success = runAdvancedSchedulerUntil(ts, []() {
+        return advanced_callback_counter >= 1;
+    });
+    EXPECT_TRUE(success);
+    EXPECT_EQ(getAdvancedTestOutput(0), "consumer_executed");
+
+    // Task should continue normal execution after first completion
+    success = runAdvancedSchedulerUntil(ts, []() {
+        return advanced_callback_counter >= 2;
+    });
+    EXPECT_TRUE(success);
+}
+
+/**
+ * @brief Test Task waitForDelayed() method for delayed event waiting
+ *
+ * TESTS: waitForDelayed(StatusRequest*, interval, iterations)
+ *
+ * PURPOSE: Verify that waitForDelayed() enables tasks to wait for
+ * StatusRequest completion with additional delay, providing fine-grained
+ * timing control in event-driven scenarios.
+ *
+ * WAIT FOR DELAYED BEHAVIOR:
+ * - waitForDelayed(): Like waitFor() but with initial delay before waiting
+ * - Task waits for both delay period AND StatusRequest completion
+ * - Useful for staggered startup and coordinated timing
+ * - Provides additional timing flexibility in complex workflows
+ * - Combines time-based and event-based triggering
+ *
+ * TEST SCENARIO:
+ * 1. Create completed StatusRequest (no event waiting needed)
+ * 2. Create task with waitForDelayed() including initial delay
+ * 3. Verify task doesn't execute immediately despite completed StatusRequest
+ * 4. Verify task executes after delay period
+ * 5. Test timing behavior matches delay specification
+ *
+ * EXPECTATIONS:
+ * - Task doesn't execute immediately even with completed StatusRequest
+ * - Task executes after specified delay period
+ * - Timing behavior respects delay parameter
+ * - Normal task behavior after initial delayed execution
+ *
+ * IMPORTANCE: Delayed event waiting enables complex timing coordination
+ * scenarios where both time and event conditions must be satisfied.
+ * Essential for staggered startup and synchronized operation patterns.
+ */
+TEST_F(AdvancedSchedulerTest, TaskWaitForDelayedStatusRequest) {
+    Scheduler ts;
+    StatusRequest sr;
+
+    // StatusRequest already complete
+    sr.signalComplete();
+
+    // Create task with delayed wait (should wait for delay even though SR is complete)
+    Task delayed_waiter(100, 1, &consumer_callback, &ts);
+    delayed_waiter.waitForDelayed(&sr, 200, 1); // 200ms delay
+
+    // Task should be enabled
+    EXPECT_TRUE(delayed_waiter.isEnabled());
+
+    // Should not execute immediately despite completed StatusRequest
+    delay(50);
+    ts.execute();
+    EXPECT_EQ(advanced_callback_counter, 0);
+
+    // Should execute after delay
+    delay(200);
+    bool success = runAdvancedSchedulerUntil(ts, []() {
+        return advanced_callback_counter >= 1;
+    });
+    EXPECT_TRUE(success);
+}
+
+/**
+ * @brief Test multiple tasks waiting for same StatusRequest
+ *
+ * TESTS: Multiple Task::waitFor() on single StatusRequest
+ *
+ * PURPOSE: Verify that multiple tasks can wait for the same StatusRequest
+ * and all execute when it completes, enabling broadcast notification
+ * and fan-out coordination patterns.
+ *
+ * MULTIPLE WAITER BEHAVIOR:
+ * - Multiple tasks can waitFor() same StatusRequest
+ * - All waiting tasks execute when StatusRequest completes
+ * - Each task maintains independent execution behavior after triggering
+ * - Enables broadcast notification and fan-out patterns
+ * - Critical for coordinated multi-task startup scenarios
+ *
+ * TEST SCENARIO:
+ * 1. Create StatusRequest in pending state
+ * 2. Create multiple tasks waiting for same StatusRequest
+ * 3. Verify no tasks execute while StatusRequest pending
+ * 4. Complete StatusRequest and verify all tasks execute
+ * 5. Verify each task maintains independent behavior
+ *
+ * EXPECTATIONS:
+ * - No tasks execute while StatusRequest pending
+ * - All tasks execute after StatusRequest completion
+ * - Each task produces expected output
+ * - Tasks maintain independent execution patterns
+ *
+ * IMPORTANCE: Multi-task coordination enables broadcast patterns
+ * essential for synchronized startup, data distribution, and
+ * coordinated processing scenarios in complex applications.
+ */
+TEST_F(AdvancedSchedulerTest, MultipleTasksWaitingForStatusRequest) {
+    Scheduler ts;
+    StatusRequest sr;
+
+    // Set up StatusRequest waiting for signal
+    sr.setWaiting(1);
+
+    // Create multiple tasks waiting for same StatusRequest
+    Task waiter1(100, 1, &waiter1_callback, &ts);
+    Task waiter2(150, 1, &waiter2_callback, &ts);
+    Task waiter3(200, 1, &waiter3_callback, &ts);
+
+    // Configure all tasks to wait for same StatusRequest
+    waiter1.waitFor(&sr);
+    waiter2.waitFor(&sr);
+    waiter3.waitFor(&sr);
+
+    // Verify all tasks are enabled but none execute
+    EXPECT_TRUE(waiter1.isEnabled());
+    EXPECT_TRUE(waiter2.isEnabled());
+    EXPECT_TRUE(waiter3.isEnabled());
+
+    delay(250);
+    ts.execute();
+    EXPECT_EQ(advanced_callback_counter, 0);
+
+    // Signal completion
+    sr.signalComplete();
+
+    // All tasks should now execute
+    bool success = runAdvancedSchedulerUntil(ts, []() {
+        return advanced_callback_counter >= 3;
+    });
+    EXPECT_TRUE(success);
+
+    // Verify all tasks executed
+    EXPECT_EQ(getAdvancedTestOutputCount(), 3);
+    // Note: Execution order may vary, but all should be present
+}
+
+// ================== TASK TIMEOUT FUNCTIONALITY TESTS ==================
+
+/**
+ * @brief Test Task timeout basic functionality
+ *
+ * TESTS: setTimeout(), getTimeout(), resetTimeout(), untilTimeout()
+ *
+ * PURPOSE: Verify that task timeout functionality correctly manages
+ * execution deadlines and provides timeout detection capabilities
+ * essential for deadline-driven applications.
+ *
+ * TIMEOUT FUNCTIONALITY:
+ * - setTimeout(timeout, reset): Sets execution deadline with optional reset
+ * - getTimeout(): Returns configured timeout value
+ * - resetTimeout(): Restarts timeout timer from current time
+ * - untilTimeout(): Returns remaining time until timeout
+ * - isTimedOut(): Checks if timeout has occurred
+ *
+ * TEST SCENARIO:
+ * 1. Create task and set timeout value
+ * 2. Verify timeout configuration via getters
+ * 3. Test resetTimeout() functionality
+ * 4. Verify untilTimeout() decreases over time
+ * 5. Test timeout detection after deadline
+ *
+ * EXPECTATIONS:
+ * - setTimeout() correctly configures timeout value
+ * - getTimeout() returns set value
+ * - untilTimeout() decreases as time passes
+ * - Timeout detection works after deadline expires
+ *
+ * IMPORTANCE: Timeout functionality enables deadline-driven task management,
+ * essential for real-time applications and preventing resource starvation
+ * in time-critical systems.
+ */
+TEST_F(AdvancedSchedulerTest, TaskTimeoutBasicFunctionality) {
+    Scheduler ts;
+    Task task(100, TASK_FOREVER, &timeout_sensitive_callback, &ts, true);
+
+    // Set timeout to 500ms
+    task.setTimeout(500, true); // true = reset timeout timer
+
+    EXPECT_EQ(task.getTimeout(), 500);
+
+    // Check initial time until timeout
+    long until_timeout = task.untilTimeout();
+    EXPECT_GT(until_timeout, 400); // Should be close to 500ms
+    EXPECT_LE(until_timeout, 500);
+
+    // Wait some time and check again
+    delay(200);
+    until_timeout = task.untilTimeout();
+    EXPECT_GT(until_timeout, 200); // Should be around 300ms
+    EXPECT_LE(until_timeout, 300);
+
+    // Reset timeout and verify
+    task.resetTimeout();
+    until_timeout = task.untilTimeout();
+    EXPECT_GT(until_timeout, 400); // Should be close to 500ms again
+}
+
+/**
+ * @brief Test task behavior when timeout occurs
+ *
+ * TESTS: Task execution with timeout expiration
+ *
+ * PURPOSE: Verify that tasks handle timeout expiration correctly,
+ * including automatic disabling and timeout status tracking,
+ * essential for robust timeout management.
+ *
+ * TIMEOUT EXPIRATION BEHAVIOR:
+ * - Task automatically disables when timeout expires
+ * - isTimedOut() returns true after timeout
+ * - Task stops executing after timeout
+ * - Timeout status preserved until reset
+ * - Enables deadline-driven task lifecycle management
+ *
+ * TEST SCENARIO:
+ * 1. Create task with short timeout
+ * 2. Let task execute normally initially
+ * 3. Wait for timeout to expire
+ * 4. Verify task disables and isTimedOut() returns true
+ * 5. Verify no further executions occur
+ *
+ * EXPECTATIONS:
+ * - Task executes normally before timeout
+ * - Task disables after timeout expiration
+ * - isTimedOut() returns true after timeout
+ * - No executions occur after timeout
+ *
+ * IMPORTANCE: Timeout expiration handling prevents runaway tasks
+ * and ensures deadline compliance, critical for real-time and
+ * resource-constrained systems.
+ */
+TEST_F(AdvancedSchedulerTest, TaskTimeoutExpiration) {
+    Scheduler ts;
+    Task task(50, TASK_FOREVER, &timeout_sensitive_callback, &ts, true);
+
+    // Set short timeout
+    task.setTimeout(200, true);
+
+    // Task should execute normally initially
+    bool success = runAdvancedSchedulerUntil(ts, []() {
+        return advanced_callback_counter >= 2;
+    });
+    EXPECT_TRUE(success);
+
+    // Wait for timeout to expire
+    delay(250);
+
+    // Run scheduler to trigger timeout processing
+    ts.execute();
+
+    // Task should be timed out and disabled
+    EXPECT_TRUE(task.isTimedOut());
+    EXPECT_FALSE(task.isEnabled());
+
+    // No further executions should occur
+    int count_before = advanced_callback_counter;
+    delay(100);
+    ts.execute();
+    EXPECT_EQ(advanced_callback_counter, count_before);
+}
+
+// ================== STATUS REQUEST TIMEOUT INTEGRATION TESTS ==================
+
+/**
+ * @brief Test StatusRequest timeout functionality
+ *
+ * TESTS: StatusRequest::setTimeout(), resetTimeout(), untilTimeout()
+ *
+ * PURPOSE: Verify that StatusRequest objects support timeout functionality
+ * for deadline-driven event coordination, preventing indefinite waiting
+ * in event-driven scenarios.
+ *
+ * STATUS REQUEST TIMEOUT BEHAVIOR:
+ * - setTimeout(timeout): Sets deadline for StatusRequest completion
+ * - resetTimeout(): Restarts timeout timer for StatusRequest
+ * - untilTimeout(): Returns remaining time until StatusRequest timeout
+ * - Timeout handling prevents indefinite blocking on events
+ * - Essential for robust event-driven coordination
+ *
+ * TEST SCENARIO:
+ * 1. Create StatusRequest and set timeout
+ * 2. Verify timeout configuration
+ * 3. Test resetTimeout() functionality
+ * 4. Monitor untilTimeout() behavior over time
+ * 5. Verify timeout detection capabilities
+ *
+ * EXPECTATIONS:
+ * - setTimeout() configures StatusRequest deadline
+ * - untilTimeout() decreases as time passes
+ * - resetTimeout() restarts timing correctly
+ * - Timeout detection works as expected
+ *
+ * IMPORTANCE: StatusRequest timeouts prevent deadlock scenarios
+ * in event-driven systems and enable deadline-based coordination
+ * patterns essential for reliable multi-task systems.
+ */
+TEST_F(AdvancedSchedulerTest, StatusRequestTimeout) {
+    StatusRequest sr;
+    sr.setWaiting(1);
+
+    // Set timeout for StatusRequest
+    sr.setTimeout(300);
+    sr.resetTimeout();
+
+    EXPECT_EQ(sr.getTimeout(), 300);
+
+    // Check initial time until timeout
+    long until_timeout = sr.untilTimeout();
+    EXPECT_GT(until_timeout, 250);
+    EXPECT_LE(until_timeout, 300);
+
+    // Wait and check again
+    delay(150);
+    until_timeout = sr.untilTimeout();
+    EXPECT_GT(until_timeout, 100);
+    EXPECT_LE(until_timeout, 150);
+
+    // Reset timeout
+    sr.resetTimeout();
+    until_timeout = sr.untilTimeout();
+    EXPECT_GT(until_timeout, 250);
+    EXPECT_LE(until_timeout, 300);
+}
+
+// ================== SCHEDULING OPTIONS TESTS ==================
+
+/**
+ * @brief Test task scheduling options functionality
+ *
+ * TESTS: setSchedulingOption(), getSchedulingOption()
+ *
+ * PURPOSE: Verify that scheduling options can be configured and retrieved,
+ * enabling advanced scheduling behavior control for specialized
+ * execution patterns and priority management.
+ *
+ * SCHEDULING OPTIONS BEHAVIOR:
+ * - setSchedulingOption(option): Configures task scheduling behavior
+ * - getSchedulingOption(): Retrieves current scheduling configuration
+ * - Options control execution priority, timing, and behavior
+ * - Enables fine-grained scheduling control
+ * - Critical for advanced task management scenarios
+ *
+ * TEST SCENARIO:
+ * 1. Create task with default scheduling option
+ * 2. Set various scheduling options and verify configuration
+ * 3. Test option retrieval matches set values
+ * 4. Verify options can be changed dynamically
+ * 5. Test with multiple different option values
+ *
+ * EXPECTATIONS:
+ * - setSchedulingOption() configures option value
+ * - getSchedulingOption() returns set value correctly
+ * - Options can be changed dynamically
+ * - Configuration persists across calls
+ *
+ * IMPORTANCE: Scheduling options enable advanced task behavior control
+ * essential for priority management, resource allocation, and
+ * specialized execution patterns in complex applications.
+ */
+TEST_F(AdvancedSchedulerTest, TaskSchedulingOptions) {
+    Scheduler ts;
+    Task task(100, 5, &advanced_status_callback, &ts, false);
+
+    // Test default scheduling option
+    unsigned int default_option = task.getSchedulingOption();
+
+    // Set different scheduling options
+    task.setSchedulingOption(1);
+    EXPECT_EQ(task.getSchedulingOption(), 1);
+
+    task.setSchedulingOption(42);
+    EXPECT_EQ(task.getSchedulingOption(), 42);
+
+    task.setSchedulingOption(0);
+    EXPECT_EQ(task.getSchedulingOption(), 0);
+
+    // Verify option can be changed while task is enabled
+    task.enable();
+    task.setSchedulingOption(99);
+    EXPECT_EQ(task.getSchedulingOption(), 99);
+    EXPECT_TRUE(task.isEnabled()); // Should remain enabled
+}
+
+// ================== SELF-DESTRUCT FUNCTIONALITY TESTS ==================
+
+/**
+ * @brief Test task self-destruct functionality (placeholder test)
+ *
+ * TESTS: Task self-destruct behavior when enabled
+ *
+ * PURPOSE: Verify that tasks can be configured to automatically remove
+ * themselves from the scheduler after completion, enabling automatic
+ * resource cleanup and dynamic task lifecycle management.
+ *
+ * SELF-DESTRUCT BEHAVIOR:
+ * - Tasks automatically remove themselves from scheduler
+ * - Occurs after task completes execution cycle
+ * - Prevents memory leaks in dynamic task scenarios
+ * - Enables automatic cleanup patterns
+ * - Critical for long-running applications with temporary tasks
+ *
+ * NOTE: This test serves as a placeholder for self-destruct functionality.
+ * The actual implementation details depend on specific TaskScheduler
+ * version and may require additional setup or different API calls.
+ *
+ * TEST SCENARIO:
+ * 1. Create task configured for self-destruction
+ * 2. Let task execute its lifecycle
+ * 3. Verify task removes itself from scheduler
+ * 4. Confirm no further executions occur
+ * 5. Test scheduler continues operating normally
+ *
+ * EXPECTATIONS:
+ * - Task executes normally initially
+ * - Task removes itself after completion
+ * - No further executions occur
+ * - Scheduler remains functional
+ *
+ * IMPORTANCE: Self-destruct functionality enables automatic resource
+ * management essential for dynamic applications and prevents memory
+ * leaks in long-running systems with temporary tasks.
+ */
+TEST_F(AdvancedSchedulerTest, TaskSelfDestruct) {
+    Scheduler ts;
+
+    // Create a task that will self-destruct after execution
+    // Note: Actual self-destruct implementation may vary by TaskScheduler version
+    Task* temp_task = new Task(100, 1, &self_destruct_callback, &ts, true);
+
+    // Let task execute
+    bool success = runAdvancedSchedulerUntil(ts, []() {
+        return task_self_destructed;
+    });
+    EXPECT_TRUE(success);
+    EXPECT_EQ(getAdvancedTestOutput(0), "self_destruct_executed");
+
+    // Note: In a full implementation, we would verify the task
+    // has been removed from the scheduler's task list
+    // This would require access to internal scheduler state
+
+    // Clean up manually for this test
+    delete temp_task;
+}
+
+// ================== INTEGRATION AND COMPLEX SCENARIOS ==================
+
+/**
+ * @brief Integration test combining status requests with timeouts
+ *
+ * TESTS: StatusRequest + Task timeout integration
+ *
+ * PURPOSE: Verify that status request coordination works correctly
+ * with task timeouts, ensuring robust behavior when events may
+ * not occur within expected timeframes.
+ *
+ * INTEGRATION BEHAVIOR:
+ * - Tasks can wait for StatusRequest with timeout protection
+ * - Timeout overrides StatusRequest waiting if deadline exceeded
+ * - Proper cleanup occurs when timeout prevents event completion
+ * - Enables robust event-driven patterns with deadline guarantees
+ * - Critical for reliable real-time coordination
+ *
+ * TEST SCENARIO:
+ * 1. Create StatusRequest that won't complete within timeout
+ * 2. Create task waiting for StatusRequest with timeout
+ * 3. Verify task times out rather than waiting indefinitely
+ * 4. Test proper cleanup and status handling
+ * 5. Verify system remains stable after timeout
+ *
+ * EXPECTATIONS:
+ * - Task times out rather than waiting indefinitely
+ * - Timeout handling works despite pending StatusRequest
+ * - System cleanup occurs properly
+ * - No resource leaks or deadlocks
+ *
+ * IMPORTANCE: Timeout protection in event-driven scenarios prevents
+ * deadlocks and ensures system reliability, essential for robust
+ * real-time applications.
+ */
+TEST_F(AdvancedSchedulerTest, StatusRequestWithTimeout) {
+    Scheduler ts;
+    StatusRequest sr;
+
+    // Set up StatusRequest that won't complete
+    sr.setWaiting(1);
+    sr.setTimeout(150);
+    sr.resetTimeout();
+
+    // Create task waiting for StatusRequest
+    Task waiter(100, 1, &consumer_callback, &ts);
+    waiter.waitFor(&sr);
+    waiter.setTimeout(200, true); // Task timeout longer than SR timeout
+
+    // Let everything run - StatusRequest should timeout first
+    delay(300);
+
+    // Run scheduler to process timeouts
+    for (int i = 0; i < 10; i++) {
+        ts.execute();
+        delay(10);
+    }
+
+    // Verify StatusRequest timed out
+    EXPECT_LE(sr.untilTimeout(), 0); // Should be negative (timed out)
+
+    // Task should eventually time out as well since SR never completed
+    EXPECT_TRUE(waiter.isTimedOut() || !waiter.isEnabled());
+}
+
+/**
+ * @brief Complex producer-consumer coordination with multiple features
+ *
+ * TESTS: Multi-feature integration in realistic scenario
+ *
+ * PURPOSE: Demonstrate complex coordination scenario using multiple
+ * advanced features together, validating that features work correctly
+ * in combination for real-world usage patterns.
+ *
+ * COMPLEX INTEGRATION FEATURES:
+ * - Producer task with timeout management
+ * - Multiple consumers waiting for producer completion
+ * - StatusRequest coordination with error handling
+ * - Scheduling options for priority control
+ * - Comprehensive error and timeout handling
+ *
+ * TEST SCENARIO:
+ * 1. Create producer task with timeout and high priority
+ * 2. Create multiple consumer tasks waiting for producer
+ * 3. Configure timeouts and scheduling options appropriately
+ * 4. Execute coordination scenario with success path
+ * 5. Verify all consumers execute after producer completion
+ *
+ * EXPECTATIONS:
+ * - Producer executes with proper priority and timing
+ * - All consumers wait appropriately for producer
+ * - StatusRequest coordination works correctly
+ * - All tasks execute in expected order
+ * - No timeouts or errors in success scenario
+ *
+ * IMPORTANCE: Complex integration validates that advanced features
+ * work together reliably, essential for building sophisticated
+ * multi-task applications with robust coordination patterns.
+ */
+TEST_F(AdvancedSchedulerTest, ComplexProducerConsumerCoordination) {
+    Scheduler ts;
+    StatusRequest production_complete;
+
+    // Set up production status request
+    production_complete.setWaiting(1);
+    production_complete.setTimeout(1000); // Allow plenty of time
+    production_complete.resetTimeout();
+
+    // Set global pointer for producer callback
+    global_status_request = &production_complete;
+
+    // Create producer task with high priority
+    Task producer(150, 1, &producer_callback, &ts, true);
+
+    producer.setTimeout(500, true);
+    producer.setSchedulingOption(10); // High priority
+
+    // Create multiple consumer tasks
+    Task consumer1(100, 1, &consumer1_callback, &ts);
+    Task consumer2(100, 1, &consumer2_callback, &ts);
+    Task consumer3(100, 1, &consumer3_callback, &ts);
+
+    // Configure consumers to wait for production
+    consumer1.waitFor(&production_complete);
+    consumer1.setTimeout(800, true);
+    consumer2.waitFor(&production_complete);
+    consumer2.setTimeout(800, true);
+    consumer3.waitFor(&production_complete);
+    consumer3.setTimeout(800, true);
+
+    // Execute the coordination scenario
+    bool success = runAdvancedSchedulerUntil(ts, []() {
+        return advanced_callback_counter >= 4; // Producer + 3 consumers
+    }, 1500);
+
+    EXPECT_TRUE(success);
+    EXPECT_EQ(advanced_callback_counter, 4);
+
+    // Verify execution order - producer should be first
+    EXPECT_EQ(getAdvancedTestOutput(0), "producer_completed");
+
+    // Verify StatusRequest completed successfully
+    EXPECT_TRUE(production_complete.completed());
+    EXPECT_EQ(production_complete.getStatus(), 100);
+
+    // Verify no timeouts occurred
+    EXPECT_FALSE(producer.isTimedOut());
+    EXPECT_FALSE(consumer1.isTimedOut());
+    EXPECT_FALSE(consumer2.isTimedOut());
+    EXPECT_FALSE(consumer3.isTimedOut());
+
+    // Clean up global pointer
+    global_status_request = nullptr;
+}
+
+/**
+ * @brief Producer-consumer scenario with yield switching
+ *
+ * TESTS: StatusRequest coordination with callback switching
+ *
+ * PURPOSE: Test complex scenario where tasks change behavior based
+ * on StatusRequest completion, demonstrating state machine patterns
+ * with event-driven coordination.
+ */
+TEST_F(AdvancedSchedulerTest, ProducerConsumerWithYieldSwitching) {
+    Scheduler ts;
+    StatusRequest sr;
+    sr.setWaiting(1);
+
+    global_status_request = &sr;
+
+    // Create producer that will signal completion
+    Task producer(100, 1, &producer_callback, &ts, true);
+
+    // Create consumer that will yield to different callback after SR completion
+    static Task* yield_task = nullptr;
+
+    auto consumer_yield_callback = []() {
+        advanced_test_output.push_back("consumer_initial");
+        if (yield_task) {
+            yield_task->yield(&yield_step2_callback);
+        }
+    };
+
+    Task consumer(100, 2, consumer_yield_callback, &ts);
+    yield_task = &consumer;
+    consumer.waitFor(&sr);
+
+    // Run the scenario
+    bool success = runAdvancedSchedulerUntil(ts, []() {
+        return getAdvancedTestOutputCount() >= 3; // producer + consumer initial + consumer yielded
+    }, 1000);
+
+    EXPECT_TRUE(success);
+    EXPECT_EQ(getAdvancedTestOutput(0), "producer_completed");
+    EXPECT_EQ(getAdvancedTestOutput(1), "consumer_initial");
+    EXPECT_EQ(getAdvancedTestOutput(2), "step_2");
+
+    // Clean up
+    global_status_request = nullptr;
+    yield_task = nullptr;
+}
+
+/**
+ * @brief Main test runner function for advanced features
+ *
+ * Initializes Google Test framework and runs all advanced feature tests.
+ * Called by the test execution environment to start testing process.
+ *
+ * @param argc Command line argument count
+ * @param argv Command line argument values
+ * @return Test execution status (0 = success)
+ */
+int main(int argc, char **argv) {
+    ::testing::InitGoogleTest(&argc, argv);
+    return RUN_ALL_TESTS();
+}

+ 1120 - 0
tests/test-scheduler-advanced-features.cpp

@@ -0,0 +1,1120 @@
+// test-scheduler-advanced-features.cpp - Advanced TaskScheduler features unit tests
+// This file contains comprehensive tests for advanced TaskScheduler functionality
+// enabled by specific compile-time directives
+//
+// =====================================================================================
+// ADVANCED FEATURES TEST PLAN AND COVERAGE MATRIX
+// =====================================================================================
+//
+// COMPILE DIRECTIVES TESTED:
+// - _TASK_STATUS_REQUEST:      Event-driven task coordination and status signaling
+// - _TASK_TIMEOUT:             Task execution timeout and deadline management
+// - _TASK_SCHEDULING_OPTIONS:  Advanced scheduling behavior control
+// - _TASK_SELF_DESTRUCT:       Automatic task cleanup and memory management
+//
+// COVERAGE MATRIX:
+// ================
+//
+// 1. STATUS REQUEST FUNCTIONALITY (_TASK_STATUS_REQUEST)
+//    ├── StatusRequest Creation and Management
+//    │   ├── StatusRequest() constructor
+//    │   ├── setWaiting(count) - prepare for multiple signals
+//    │   ├── signal(status) - signal completion from tasks
+//    │   ├── signalComplete(status) - force immediate completion
+//    │   ├── pending() - check if still waiting
+//    │   ├── completed() - check if finished
+//    │   ├── getStatus() - retrieve completion status
+//    │   └── getCount() - get remaining signal count
+//    │
+//    ├── Task Status Request Integration
+//    │   ├── waitFor(StatusRequest*, interval, iterations) - wait for event
+//    │   ├── waitForDelayed(StatusRequest*, interval, iterations) - delayed wait
+//    │   ├── getStatusRequest() - get external status request
+//    │   └── getInternalStatusRequest() - get task's internal status
+//    │
+//    └── Event-Driven Task Coordination Patterns
+//        ├── Single task waiting for event completion
+//        ├── Multiple tasks waiting for same event
+//        ├── Task chains with dependency resolution
+//        └── Producer-consumer coordination scenarios
+//
+// 2. TIMEOUT FUNCTIONALITY (_TASK_TIMEOUT)
+//    ├── Task Timeout Management
+//    │   ├── setTimeout(timeout, reset) - set execution deadline
+//    │   ├── resetTimeout() - restart timeout timer
+//    │   ├── getTimeout() - retrieve timeout value
+//    │   ├── untilTimeout() - time remaining until timeout
+//    │   └── isTimedOut() - check timeout status
+//    │
+//    ├── StatusRequest Timeout Integration
+//    │   ├── StatusRequest::setTimeout(timeout) - set request deadline
+//    │   ├── StatusRequest::resetTimeout() - restart request timer
+//    │   ├── StatusRequest::getTimeout() - retrieve request timeout
+//    │   └── StatusRequest::untilTimeout() - time until request expires
+//    │
+//    └── Timeout Behavior Patterns
+//        ├── Task execution timeout handling
+//        ├── StatusRequest completion timeout
+//        ├── Timeout-driven task disabling
+//        └── Deadline-based task prioritization
+//
+// 3. SCHEDULING OPTIONS (_TASK_SCHEDULING_OPTIONS)
+//    ├── Scheduling Behavior Control
+//    │   ├── setSchedulingOption(option) - configure task behavior
+//    │   ├── getSchedulingOption() - retrieve current option
+//    │   └── Scheduling option effects on execution
+//    │
+//    └── Advanced Scheduling Patterns
+//        ├── Priority-based execution control
+//        ├── Conditional execution behavior
+//        └── Resource allocation management
+//
+// 4. SELF-DESTRUCT FUNCTIONALITY (_TASK_SELF_DESTRUCT)
+//    ├── Automatic Task Cleanup
+//    │   ├── Task auto-removal from scheduler
+//    │   ├── Memory management and resource cleanup
+//    │   └── Lifecycle-based task destruction
+//    │
+//    └── Self-Destruct Patterns
+//        ├── One-shot tasks with auto-cleanup
+//        ├── Conditional task removal
+//        └── Dynamic task lifecycle management
+//
+// 5. INTEGRATION AND ADVANCED PATTERNS
+//    ├── Multi-Feature Integration Tests
+//    │   ├── Status requests with timeout handling
+//    │   ├── Self-destructing tasks with status coordination
+//    │   ├── Scheduling options with timeout management
+//    │   └── Complex event-driven workflows
+//    │
+//    ├── Real-World Usage Scenarios
+//    │   ├── Sensor data collection with timeouts
+//    │   ├── Multi-stage processing pipelines
+//    │   ├── Resource monitoring and cleanup
+//    │   └── Deadline-driven task orchestration
+//    │
+//    └── Edge Cases and Error Handling
+//        ├── Timeout during status request waiting
+//        ├── Self-destruct during active coordination
+//        ├── Invalid scheduling option handling
+//        └── Resource cleanup on abnormal termination
+//
+// =====================================================================================
+
+// Enable all advanced features for comprehensive testing
+#define _TASK_STATUS_REQUEST        // Event-driven task coordination
+#define _TASK_TIMEOUT              // Task execution deadlines
+#define _TASK_SCHEDULING_OPTIONS   // Advanced scheduling control
+#define _TASK_SELF_DESTRUCT        // Automatic task cleanup
+
+#include <gtest/gtest.h>
+#include "Arduino.h"
+#include "TaskScheduler.h"
+
+// Global test state for advanced features
+std::vector<std::string> advanced_test_output;
+int advanced_callback_counter = 0;
+bool status_received = false;
+int last_status_code = 0;
+bool timeout_occurred = false;
+bool task_self_destructed = false;
+
+/**
+ * @brief Advanced callback function for status request testing
+ *
+ * Records execution and can signal status request completion.
+ * Used for testing event-driven task coordination patterns.
+ */
+void advanced_status_callback() {
+    advanced_callback_counter++;
+    advanced_test_output.push_back("status_task_executed");
+    std::cout << "Status task executed at " << millis() << "ms" << std::endl;
+}
+
+/**
+ * @brief Producer callback that signals status request completion
+ *
+ * Simulates a task that produces events or completes work that
+ * other tasks are waiting for. Essential for testing coordination.
+ */
+void producer_callback() {
+    advanced_callback_counter++;
+    advanced_test_output.push_back("producer_completed");
+    std::cout << "Producer completed at " << millis() << "ms" << std::endl;
+}
+
+/**
+ * @brief Consumer callback for status request waiting
+ *
+ * Represents tasks that wait for specific events before executing.
+ * Used to test event-driven coordination and dependency management.
+ */
+void consumer_callback() {
+    advanced_callback_counter++;
+    advanced_test_output.push_back("consumer_executed");
+    std::cout << "Consumer executed at " << millis() << "ms" << std::endl;
+}
+
+/**
+ * @brief Timeout-sensitive callback for deadline testing
+ *
+ * Callback that tracks timeout conditions and handles deadline-based
+ * execution scenarios. Critical for testing timeout functionality.
+ */
+void timeout_sensitive_callback() {
+    advanced_callback_counter++;
+    advanced_test_output.push_back("timeout_task_executed");
+    // This callback can be used to test timeout behavior
+}
+
+/**
+ * @brief Self-destructing task callback for cleanup testing
+ *
+ * Callback for tasks that are designed to clean themselves up
+ * after execution. Used to test automatic resource management.
+ */
+void self_destruct_callback() {
+    advanced_callback_counter++;
+    advanced_test_output.push_back("self_destruct_executed");
+    task_self_destructed = true;
+}
+
+/**
+ * @brief Test fixture class for advanced TaskScheduler features
+ *
+ * Provides setup and teardown for advanced feature tests, ensuring
+ * clean state between tests and utility methods for complex scenarios.
+ */
+class AdvancedSchedulerTest : public ::testing::Test {
+protected:
+    /**
+     * @brief Set up test environment for advanced features
+     *
+     * Clears all test state and initializes timing system.
+     * Prepares environment for testing complex feature interactions.
+     */
+    void SetUp() override {
+        clearAdvancedTestOutput();
+        advanced_callback_counter = 0;
+        status_received = false;
+        last_status_code = 0;
+        timeout_occurred = false;
+        task_self_destructed = false;
+        millis(); // Initialize timing
+    }
+
+    /**
+     * @brief Clean up test environment after advanced feature tests
+     *
+     * Ensures no test artifacts affect subsequent tests.
+     * Critical for maintaining test isolation in complex scenarios.
+     */
+    void TearDown() override {
+        clearAdvancedTestOutput();
+        advanced_callback_counter = 0;
+        status_received = false;
+        last_status_code = 0;
+        timeout_occurred = false;
+        task_self_destructed = false;
+    }
+
+    /**
+     * @brief Helper to run scheduler until condition or timeout for advanced tests
+     *
+     * Enhanced version that handles complex conditions involving multiple
+     * tasks, status requests, and timeout scenarios.
+     */
+    bool runAdvancedSchedulerUntil(Scheduler& ts, std::function<bool()> condition, unsigned long timeout_ms = 2000) {
+        return waitForCondition([&]() {
+            ts.execute();
+            return condition();
+        }, timeout_ms);
+    }
+
+    /**
+     * @brief Clear advanced test output buffer
+     */
+    void clearAdvancedTestOutput() {
+        advanced_test_output.clear();
+    }
+
+    /**
+     * @brief Get count of advanced test output entries
+     */
+    size_t getAdvancedTestOutputCount() {
+        return advanced_test_output.size();
+    }
+
+    /**
+     * @brief Get specific advanced test output entry
+     */
+    std::string getAdvancedTestOutput(size_t index) {
+        if (index < advanced_test_output.size()) {
+            return advanced_test_output[index];
+        }
+        return "";
+    }
+};
+
+// ================== STATUS REQUEST CREATION AND MANAGEMENT TESTS ==================
+
+/**
+ * @brief Test StatusRequest constructor and basic state management
+ *
+ * TESTS: StatusRequest(), setWaiting(), pending(), completed()
+ *
+ * PURPOSE: Verify that StatusRequest objects can be created and their
+ * basic state management methods work correctly, providing foundation
+ * for event-driven task coordination.
+ *
+ * STATUS REQUEST LIFECYCLE:
+ * - Constructor: Creates StatusRequest in completed state (count=0)
+ * - setWaiting(count): Prepares to receive 'count' signal() calls
+ * - pending(): Returns true while count > 0
+ * - completed(): Returns true when count == 0
+ * - State transitions control task execution timing
+ *
+ * TEST SCENARIO:
+ * 1. Create StatusRequest and verify initial completed state
+ * 2. Set waiting for 3 signals and verify pending state
+ * 3. Verify completed() and pending() return correct values
+ * 4. Test state consistency across multiple checks
+ *
+ * EXPECTATIONS:
+ * - Initial state: completed() = true, pending() = false
+ * - After setWaiting(3): completed() = false, pending() = true
+ * - State methods return consistent, expected values
+ *
+ * IMPORTANCE: Basic state management is foundation for all event-driven
+ * coordination patterns. Reliable state tracking ensures proper task
+ * synchronization and prevents race conditions.
+ */
+TEST_F(AdvancedSchedulerTest, StatusRequestBasicState) {
+    StatusRequest sr;
+
+    // Initial state should be completed
+    EXPECT_TRUE(sr.completed());
+    EXPECT_FALSE(sr.pending());
+    EXPECT_EQ(sr.getCount(), 0);
+    EXPECT_EQ(sr.getStatus(), 0);
+
+    // Set waiting for 3 signals
+    sr.setWaiting(3);
+    EXPECT_FALSE(sr.completed());
+    EXPECT_TRUE(sr.pending());
+    EXPECT_EQ(sr.getCount(), 3);
+    EXPECT_EQ(sr.getStatus(), 0); // Status reset by setWaiting
+}
+
+/**
+ * @brief Test StatusRequest signal() method for incremental completion
+ *
+ * TESTS: signal(status), getStatus(), getCount()
+ *
+ * PURPOSE: Verify that signal() correctly decrements the waiting count
+ * and manages status codes, enabling coordinated completion tracking
+ * across multiple signaling tasks.
+ *
+ * SIGNAL BEHAVIOR:
+ * - signal(): Decrements count by 1, sets status if provided
+ * - signal(status): Same as signal() but with custom status code
+ * - Returns true when StatusRequest becomes complete (count reaches 0)
+ * - Status code from last signal() call is preserved
+ * - Negative status codes cause immediate completion (error handling)
+ *
+ * TEST SCENARIO:
+ * 1. Set StatusRequest waiting for 3 signals
+ * 2. Send 2 normal signals and verify count decrements
+ * 3. Send final signal with status code and verify completion
+ * 4. Test negative status code causing immediate completion
+ *
+ * EXPECTATIONS:
+ * - Each signal() decrements count by 1
+ * - Status code is updated with each signal
+ * - signal() returns true only when count reaches 0
+ * - Negative status causes immediate completion
+ *
+ * IMPORTANCE: Incremental signaling enables complex coordination
+ * patterns where multiple tasks contribute to completion condition.
+ * Status codes provide error handling and completion context.
+ */
+TEST_F(AdvancedSchedulerTest, StatusRequestSignaling) {
+    StatusRequest sr;
+    sr.setWaiting(3);
+
+    // Send first signal
+    bool complete = sr.signal();
+    EXPECT_FALSE(complete);
+    EXPECT_EQ(sr.getCount(), 2);
+    EXPECT_TRUE(sr.pending());
+
+    // Send second signal with status
+    complete = sr.signal(42);
+    EXPECT_FALSE(complete);
+    EXPECT_EQ(sr.getCount(), 1);
+    EXPECT_EQ(sr.getStatus(), 42);
+
+    // Send final signal
+    complete = sr.signal(99);
+    EXPECT_TRUE(complete);
+    EXPECT_EQ(sr.getCount(), 0);
+    EXPECT_EQ(sr.getStatus(), 99);
+    EXPECT_TRUE(sr.completed());
+
+    // Test negative status for immediate completion
+    sr.setWaiting(5);
+    complete = sr.signal(-1); // Negative status should complete immediately
+    EXPECT_TRUE(complete);
+    EXPECT_EQ(sr.getCount(), 0);
+    EXPECT_EQ(sr.getStatus(), -1);
+}
+
+/**
+ * @brief Test StatusRequest signalComplete() method for immediate completion
+ *
+ * TESTS: signalComplete(status)
+ *
+ * PURPOSE: Verify that signalComplete() immediately completes the StatusRequest
+ * regardless of remaining count, enabling emergency completion and
+ * error handling scenarios.
+ *
+ * SIGNAL COMPLETE BEHAVIOR:
+ * - signalComplete(): Immediately sets count to 0 (completed state)
+ * - signalComplete(status): Same as above but with custom status code
+ * - Bypasses incremental signaling for immediate completion
+ * - Useful for error conditions and emergency shutdowns
+ * - Always results in completed state regardless of initial count
+ *
+ * TEST SCENARIO:
+ * 1. Set StatusRequest waiting for large number of signals
+ * 2. Call signalComplete() and verify immediate completion
+ * 3. Test signalComplete() with custom status code
+ * 4. Verify no further signals are processed after completion
+ *
+ * EXPECTATIONS:
+ * - signalComplete() immediately sets count to 0
+ * - Status code is set if provided
+ * - completed() returns true immediately
+ * - Further signals have no effect (idempotent)
+ *
+ * IMPORTANCE: Immediate completion enables error handling, emergency
+ * shutdown, and abort scenarios in complex coordination patterns.
+ * Critical for robust event-driven systems.
+ */
+TEST_F(AdvancedSchedulerTest, StatusRequestSignalComplete) {
+    StatusRequest sr;
+    sr.setWaiting(10); // Large count for testing immediate completion
+
+    // Signal complete should immediately finish
+    sr.signalComplete(200);
+    EXPECT_TRUE(sr.completed());
+    EXPECT_FALSE(sr.pending());
+    EXPECT_EQ(sr.getCount(), 0);
+    EXPECT_EQ(sr.getStatus(), 200);
+
+    // Further signals should have no effect
+    sr.signal(999);
+    EXPECT_EQ(sr.getStatus(), 200); // Should remain unchanged
+    EXPECT_EQ(sr.getCount(), 0);    // Should remain completed
+}
+
+// ================== TASK STATUS REQUEST INTEGRATION TESTS ==================
+
+/**
+ * @brief Test Task waitFor() method for event-driven task execution
+ *
+ * TESTS: waitFor(StatusRequest*, interval, iterations)
+ *
+ * PURPOSE: Verify that tasks can wait for external StatusRequest completion
+ * before executing, enabling event-driven coordination and dependency
+ * management between tasks.
+ *
+ * WAIT FOR BEHAVIOR:
+ * - waitFor(): Configures task to wait for StatusRequest completion
+ * - Task becomes enabled but won't execute until StatusRequest completes
+ * - interval and iterations configure post-completion behavior
+ * - Task executes immediately when StatusRequest is already complete
+ * - Enables producer-consumer and dependency coordination patterns
+ *
+ * TEST SCENARIO:
+ * 1. Create StatusRequest in pending state
+ * 2. Create task configured to waitFor() the StatusRequest
+ * 3. Verify task doesn't execute while StatusRequest is pending
+ * 4. Complete StatusRequest and verify task executes
+ * 5. Test with already-completed StatusRequest
+ *
+ * EXPECTATIONS:
+ * - Task enabled but doesn't execute while StatusRequest pending
+ * - Task executes immediately after StatusRequest completion
+ * - Task with completed StatusRequest executes immediately
+ * - Task follows normal interval/iteration behavior after first execution
+ *
+ * IMPORTANCE: Event-driven task execution enables sophisticated coordination
+ * patterns essential for multi-task workflows, data processing pipelines,
+ * and resource synchronization scenarios.
+ */
+TEST_F(AdvancedSchedulerTest, TaskWaitForStatusRequest) {
+    Scheduler ts;
+    StatusRequest sr;
+
+    // Set up StatusRequest in pending state
+    sr.setWaiting(1);
+
+    // Create task that waits for status request
+    Task waiter(100, 2, &consumer_callback, &ts);
+    waiter.waitFor(&sr, 50, 2);
+
+    // Task should be enabled but not execute while SR is pending
+    EXPECT_TRUE(waiter.isEnabled());
+
+    // Run scheduler - task should not execute yet
+    delay(100);
+    ts.execute();
+    EXPECT_EQ(advanced_callback_counter, 0);
+
+    // Complete the status request
+    sr.signalComplete();
+
+    // Now task should execute
+    bool success = runAdvancedSchedulerUntil(ts, []() {
+        return advanced_callback_counter >= 1;
+    });
+    EXPECT_TRUE(success);
+    EXPECT_EQ(getAdvancedTestOutput(0), "consumer_executed");
+
+    // Task should continue normal execution after first completion
+    success = runAdvancedSchedulerUntil(ts, []() {
+        return advanced_callback_counter >= 2;
+    });
+    EXPECT_TRUE(success);
+}
+
+/**
+ * @brief Test Task waitForDelayed() method for delayed event waiting
+ *
+ * TESTS: waitForDelayed(StatusRequest*, interval, iterations)
+ *
+ * PURPOSE: Verify that waitForDelayed() enables tasks to wait for
+ * StatusRequest completion with additional delay, providing fine-grained
+ * timing control in event-driven scenarios.
+ *
+ * WAIT FOR DELAYED BEHAVIOR:
+ * - waitForDelayed(): Like waitFor() but with initial delay before waiting
+ * - Task waits for both delay period AND StatusRequest completion
+ * - Useful for staggered startup and coordinated timing
+ * - Provides additional timing flexibility in complex workflows
+ * - Combines time-based and event-based triggering
+ *
+ * TEST SCENARIO:
+ * 1. Create completed StatusRequest (no event waiting needed)
+ * 2. Create task with waitForDelayed() including initial delay
+ * 3. Verify task doesn't execute immediately despite completed StatusRequest
+ * 4. Verify task executes after delay period
+ * 5. Test timing behavior matches delay specification
+ *
+ * EXPECTATIONS:
+ * - Task doesn't execute immediately even with completed StatusRequest
+ * - Task executes after specified delay period
+ * - Timing behavior respects delay parameter
+ * - Normal task behavior after initial delayed execution
+ *
+ * IMPORTANCE: Delayed event waiting enables complex timing coordination
+ * scenarios where both time and event conditions must be satisfied.
+ * Essential for staggered startup and synchronized operation patterns.
+ */
+TEST_F(AdvancedSchedulerTest, TaskWaitForDelayedStatusRequest) {
+    Scheduler ts;
+    StatusRequest sr;
+
+    // StatusRequest already complete
+    sr.signalComplete();
+
+    // Create task with delayed wait (should wait for delay even though SR is complete)
+    Task delayed_waiter(100, 1, &consumer_callback, &ts);
+    delayed_waiter.waitForDelayed(&sr, 200, 1); // 200ms delay
+
+    // Task should be enabled
+    EXPECT_TRUE(delayed_waiter.isEnabled());
+
+    // Should not execute immediately despite completed StatusRequest
+    delay(50);
+    ts.execute();
+    EXPECT_EQ(advanced_callback_counter, 0);
+
+    // Should execute after delay
+    delay(200);
+    bool success = runAdvancedSchedulerUntil(ts, []() {
+        return advanced_callback_counter >= 1;
+    });
+    EXPECT_TRUE(success);
+}
+
+/**
+ * @brief Test multiple tasks waiting for same StatusRequest
+ *
+ * TESTS: Multiple Task::waitFor() on single StatusRequest
+ *
+ * PURPOSE: Verify that multiple tasks can wait for the same StatusRequest
+ * and all execute when it completes, enabling broadcast notification
+ * and fan-out coordination patterns.
+ *
+ * MULTIPLE WAITER BEHAVIOR:
+ * - Multiple tasks can waitFor() same StatusRequest
+ * - All waiting tasks execute when StatusRequest completes
+ * - Each task maintains independent execution behavior after triggering
+ * - Enables broadcast notification and fan-out patterns
+ * - Critical for coordinated multi-task startup scenarios
+ *
+ * TEST SCENARIO:
+ * 1. Create StatusRequest in pending state
+ * 2. Create multiple tasks waiting for same StatusRequest
+ * 3. Verify no tasks execute while StatusRequest pending
+ * 4. Complete StatusRequest and verify all tasks execute
+ * 5. Verify each task maintains independent behavior
+ *
+ * EXPECTATIONS:
+ * - No tasks execute while StatusRequest pending
+ * - All tasks execute after StatusRequest completion
+ * - Each task produces expected output
+ * - Tasks maintain independent execution patterns
+ *
+ * IMPORTANCE: Multi-task coordination enables broadcast patterns
+ * essential for synchronized startup, data distribution, and
+ * coordinated processing scenarios in complex applications.
+ */
+TEST_F(AdvancedSchedulerTest, MultipleTasksWaitingForStatusRequest) {
+    Scheduler ts;
+    StatusRequest sr;
+
+    // Set up StatusRequest waiting for signal
+    sr.setWaiting(1);
+
+    // Create multiple tasks waiting for same StatusRequest
+    Task waiter1(100, 1, []() {
+        advanced_callback_counter++;
+        advanced_test_output.push_back("waiter1_executed");
+    }, &ts);
+
+    Task waiter2(150, 1, []() {
+        advanced_callback_counter++;
+        advanced_test_output.push_back("waiter2_executed");
+    }, &ts);
+
+    Task waiter3(200, 1, []() {
+        advanced_callback_counter++;
+        advanced_test_output.push_back("waiter3_executed");
+    }, &ts);
+
+    // Configure all tasks to wait for same StatusRequest
+    waiter1.waitFor(&sr);
+    waiter2.waitFor(&sr);
+    waiter3.waitFor(&sr);
+
+    // Verify all tasks are enabled but none execute
+    EXPECT_TRUE(waiter1.isEnabled());
+    EXPECT_TRUE(waiter2.isEnabled());
+    EXPECT_TRUE(waiter3.isEnabled());
+
+    delay(250);
+    ts.execute();
+    EXPECT_EQ(advanced_callback_counter, 0);
+
+    // Signal completion
+    sr.signalComplete();
+
+    // All tasks should now execute
+    bool success = runAdvancedSchedulerUntil(ts, []() {
+        return advanced_callback_counter >= 3;
+    });
+    EXPECT_TRUE(success);
+
+    // Verify all tasks executed
+    EXPECT_EQ(getAdvancedTestOutputCount(), 3);
+    // Note: Execution order may vary, but all should be present
+}
+
+// ================== TASK TIMEOUT FUNCTIONALITY TESTS ==================
+
+/**
+ * @brief Test Task timeout basic functionality
+ *
+ * TESTS: setTimeout(), getTimeout(), resetTimeout(), untilTimeout()
+ *
+ * PURPOSE: Verify that task timeout functionality correctly manages
+ * execution deadlines and provides timeout detection capabilities
+ * essential for deadline-driven applications.
+ *
+ * TIMEOUT FUNCTIONALITY:
+ * - setTimeout(timeout, reset): Sets execution deadline with optional reset
+ * - getTimeout(): Returns configured timeout value
+ * - resetTimeout(): Restarts timeout timer from current time
+ * - untilTimeout(): Returns remaining time until timeout
+ * - isTimedOut(): Checks if timeout has occurred
+ *
+ * TEST SCENARIO:
+ * 1. Create task and set timeout value
+ * 2. Verify timeout configuration via getters
+ * 3. Test resetTimeout() functionality
+ * 4. Verify untilTimeout() decreases over time
+ * 5. Test timeout detection after deadline
+ *
+ * EXPECTATIONS:
+ * - setTimeout() correctly configures timeout value
+ * - getTimeout() returns set value
+ * - untilTimeout() decreases as time passes
+ * - Timeout detection works after deadline expires
+ *
+ * IMPORTANCE: Timeout functionality enables deadline-driven task management,
+ * essential for real-time applications and preventing resource starvation
+ * in time-critical systems.
+ */
+TEST_F(AdvancedSchedulerTest, TaskTimeoutBasicFunctionality) {
+    Scheduler ts;
+    Task task(100, TASK_FOREVER, &timeout_sensitive_callback, &ts, true);
+
+    // Set timeout to 500ms
+    task.setTimeout(500, true); // true = reset timeout timer
+
+    EXPECT_EQ(task.getTimeout(), 500);
+
+    // Check initial time until timeout
+    long until_timeout = task.untilTimeout();
+    EXPECT_GT(until_timeout, 400); // Should be close to 500ms
+    EXPECT_LE(until_timeout, 500);
+
+    // Wait some time and check again
+    delay(200);
+    until_timeout = task.untilTimeout();
+    EXPECT_GT(until_timeout, 200); // Should be around 300ms
+    EXPECT_LE(until_timeout, 300);
+
+    // Reset timeout and verify
+    task.resetTimeout();
+    until_timeout = task.untilTimeout();
+    EXPECT_GT(until_timeout, 400); // Should be close to 500ms again
+}
+
+/**
+ * @brief Test task behavior when timeout occurs
+ *
+ * TESTS: Task execution with timeout expiration
+ *
+ * PURPOSE: Verify that tasks handle timeout expiration correctly,
+ * including automatic disabling and timeout status tracking,
+ * essential for robust timeout management.
+ *
+ * TIMEOUT EXPIRATION BEHAVIOR:
+ * - Task automatically disables when timeout expires
+ * - isTimedOut() returns true after timeout
+ * - Task stops executing after timeout
+ * - Timeout status preserved until reset
+ * - Enables deadline-driven task lifecycle management
+ *
+ * TEST SCENARIO:
+ * 1. Create task with short timeout
+ * 2. Let task execute normally initially
+ * 3. Wait for timeout to expire
+ * 4. Verify task disables and isTimedOut() returns true
+ * 5. Verify no further executions occur
+ *
+ * EXPECTATIONS:
+ * - Task executes normally before timeout
+ * - Task disables after timeout expiration
+ * - isTimedOut() returns true after timeout
+ * - No executions occur after timeout
+ *
+ * IMPORTANCE: Timeout expiration handling prevents runaway tasks
+ * and ensures deadline compliance, critical for real-time and
+ * resource-constrained systems.
+ */
+TEST_F(AdvancedSchedulerTest, TaskTimeoutExpiration) {
+    Scheduler ts;
+    Task task(50, TASK_FOREVER, &timeout_sensitive_callback, &ts, true);
+
+    // Set short timeout
+    task.setTimeout(200, true);
+
+    // Task should execute normally initially
+    bool success = runAdvancedSchedulerUntil(ts, []() {
+        return advanced_callback_counter >= 2;
+    });
+    EXPECT_TRUE(success);
+
+    // Wait for timeout to expire
+    delay(250);
+
+    // Run scheduler to trigger timeout processing
+    ts.execute();
+
+    // Task should be timed out and disabled
+    EXPECT_TRUE(task.isTimedOut());
+    EXPECT_FALSE(task.isEnabled());
+
+    // No further executions should occur
+    int count_before = advanced_callback_counter;
+    delay(100);
+    ts.execute();
+    EXPECT_EQ(advanced_callback_counter, count_before);
+}
+
+// ================== STATUS REQUEST TIMEOUT INTEGRATION TESTS ==================
+
+/**
+ * @brief Test StatusRequest timeout functionality
+ *
+ * TESTS: StatusRequest::setTimeout(), resetTimeout(), untilTimeout()
+ *
+ * PURPOSE: Verify that StatusRequest objects support timeout functionality
+ * for deadline-driven event coordination, preventing indefinite waiting
+ * in event-driven scenarios.
+ *
+ * STATUS REQUEST TIMEOUT BEHAVIOR:
+ * - setTimeout(timeout): Sets deadline for StatusRequest completion
+ * - resetTimeout(): Restarts timeout timer for StatusRequest
+ * - untilTimeout(): Returns remaining time until StatusRequest timeout
+ * - Timeout handling prevents indefinite blocking on events
+ * - Essential for robust event-driven coordination
+ *
+ * TEST SCENARIO:
+ * 1. Create StatusRequest and set timeout
+ * 2. Verify timeout configuration
+ * 3. Test resetTimeout() functionality
+ * 4. Monitor untilTimeout() behavior over time
+ * 5. Verify timeout detection capabilities
+ *
+ * EXPECTATIONS:
+ * - setTimeout() configures StatusRequest deadline
+ * - untilTimeout() decreases as time passes
+ * - resetTimeout() restarts timing correctly
+ * - Timeout detection works as expected
+ *
+ * IMPORTANCE: StatusRequest timeouts prevent deadlock scenarios
+ * in event-driven systems and enable deadline-based coordination
+ * patterns essential for reliable multi-task systems.
+ */
+TEST_F(AdvancedSchedulerTest, StatusRequestTimeout) {
+    StatusRequest sr;
+    sr.setWaiting(1);
+
+    // Set timeout for StatusRequest
+    sr.setTimeout(300);
+    sr.resetTimeout();
+
+    EXPECT_EQ(sr.getTimeout(), 300);
+
+    // Check initial time until timeout
+    long until_timeout = sr.untilTimeout();
+    EXPECT_GT(until_timeout, 250);
+    EXPECT_LE(until_timeout, 300);
+
+    // Wait and check again
+    delay(150);
+    until_timeout = sr.untilTimeout();
+    EXPECT_GT(until_timeout, 100);
+    EXPECT_LE(until_timeout, 150);
+
+    // Reset timeout
+    sr.resetTimeout();
+    until_timeout = sr.untilTimeout();
+    EXPECT_GT(until_timeout, 250);
+    EXPECT_LE(until_timeout, 300);
+}
+
+// ================== SCHEDULING OPTIONS TESTS ==================
+
+/**
+ * @brief Test task scheduling options functionality
+ *
+ * TESTS: setSchedulingOption(), getSchedulingOption()
+ *
+ * PURPOSE: Verify that scheduling options can be configured and retrieved,
+ * enabling advanced scheduling behavior control for specialized
+ * execution patterns and priority management.
+ *
+ * SCHEDULING OPTIONS BEHAVIOR:
+ * - setSchedulingOption(option): Configures task scheduling behavior
+ * - getSchedulingOption(): Retrieves current scheduling configuration
+ * - Options control execution priority, timing, and behavior
+ * - Enables fine-grained scheduling control
+ * - Critical for advanced task management scenarios
+ *
+ * TEST SCENARIO:
+ * 1. Create task with default scheduling option
+ * 2. Set various scheduling options and verify configuration
+ * 3. Test option retrieval matches set values
+ * 4. Verify options can be changed dynamically
+ * 5. Test with multiple different option values
+ *
+ * EXPECTATIONS:
+ * - setSchedulingOption() configures option value
+ * - getSchedulingOption() returns set value correctly
+ * - Options can be changed dynamically
+ * - Configuration persists across calls
+ *
+ * IMPORTANCE: Scheduling options enable advanced task behavior control
+ * essential for priority management, resource allocation, and
+ * specialized execution patterns in complex applications.
+ */
+TEST_F(AdvancedSchedulerTest, TaskSchedulingOptions) {
+    Scheduler ts;
+    Task task(100, 5, &advanced_status_callback, &ts, false);
+
+    // Test default scheduling option
+    unsigned int default_option = task.getSchedulingOption();
+
+    // Set different scheduling options
+    task.setSchedulingOption(1);
+    EXPECT_EQ(task.getSchedulingOption(), 1);
+
+    task.setSchedulingOption(42);
+    EXPECT_EQ(task.getSchedulingOption(), 42);
+
+    task.setSchedulingOption(0);
+    EXPECT_EQ(task.getSchedulingOption(), 0);
+
+    // Verify option can be changed while task is enabled
+    task.enable();
+    task.setSchedulingOption(99);
+    EXPECT_EQ(task.getSchedulingOption(), 99);
+    EXPECT_TRUE(task.isEnabled()); // Should remain enabled
+}
+
+// ================== SELF-DESTRUCT FUNCTIONALITY TESTS ==================
+
+/**
+ * @brief Test task self-destruct functionality (placeholder test)
+ *
+ * TESTS: Task self-destruct behavior when enabled
+ *
+ * PURPOSE: Verify that tasks can be configured to automatically remove
+ * themselves from the scheduler after completion, enabling automatic
+ * resource cleanup and dynamic task lifecycle management.
+ *
+ * SELF-DESTRUCT BEHAVIOR:
+ * - Tasks automatically remove themselves from scheduler
+ * - Occurs after task completes execution cycle
+ * - Prevents memory leaks in dynamic task scenarios
+ * - Enables automatic cleanup patterns
+ * - Critical for long-running applications with temporary tasks
+ *
+ * NOTE: This test serves as a placeholder for self-destruct functionality.
+ * The actual implementation details depend on specific TaskScheduler
+ * version and may require additional setup or different API calls.
+ *
+ * TEST SCENARIO:
+ * 1. Create task configured for self-destruction
+ * 2. Let task execute its lifecycle
+ * 3. Verify task removes itself from scheduler
+ * 4. Confirm no further executions occur
+ * 5. Test scheduler continues operating normally
+ *
+ * EXPECTATIONS:
+ * - Task executes normally initially
+ * - Task removes itself after completion
+ * - No further executions occur
+ * - Scheduler remains functional
+ *
+ * IMPORTANCE: Self-destruct functionality enables automatic resource
+ * management essential for dynamic applications and prevents memory
+ * leaks in long-running systems with temporary tasks.
+ */
+TEST_F(AdvancedSchedulerTest, TaskSelfDestruct) {
+    Scheduler ts;
+
+    // Create a task that will self-destruct after execution
+    // Note: Actual self-destruct implementation may vary by TaskScheduler version
+    Task* temp_task = new Task(100, 1, &self_destruct_callback, &ts, true);
+
+    // Let task execute
+    bool success = runAdvancedSchedulerUntil(ts, []() {
+        return task_self_destructed;
+    });
+    EXPECT_TRUE(success);
+    EXPECT_EQ(getAdvancedTestOutput(0), "self_destruct_executed");
+
+    // Note: In a full implementation, we would verify the task
+    // has been removed from the scheduler's task list
+    // This would require access to internal scheduler state
+
+    // Clean up manually for this test
+    delete temp_task;
+}
+
+// ================== INTEGRATION AND COMPLEX SCENARIOS ==================
+
+/**
+ * @brief Integration test combining status requests with timeouts
+ *
+ * TESTS: StatusRequest + Task timeout integration
+ *
+ * PURPOSE: Verify that status request coordination works correctly
+ * with task timeouts, ensuring robust behavior when events may
+ * not occur within expected timeframes.
+ *
+ * INTEGRATION BEHAVIOR:
+ * - Tasks can wait for StatusRequest with timeout protection
+ * - Timeout overrides StatusRequest waiting if deadline exceeded
+ * - Proper cleanup occurs when timeout prevents event completion
+ * - Enables robust event-driven patterns with deadline guarantees
+ * - Critical for reliable real-time coordination
+ *
+ * TEST SCENARIO:
+ * 1. Create StatusRequest that won't complete within timeout
+ * 2. Create task waiting for StatusRequest with timeout
+ * 3. Verify task times out rather than waiting indefinitely
+ * 4. Test proper cleanup and status handling
+ * 5. Verify system remains stable after timeout
+ *
+ * EXPECTATIONS:
+ * - Task times out rather than waiting indefinitely
+ * - Timeout handling works despite pending StatusRequest
+ * - System cleanup occurs properly
+ * - No resource leaks or deadlocks
+ *
+ * IMPORTANCE: Timeout protection in event-driven scenarios prevents
+ * deadlocks and ensures system reliability, essential for robust
+ * real-time applications.
+ */
+TEST_F(AdvancedSchedulerTest, StatusRequestWithTimeout) {
+    Scheduler ts;
+    StatusRequest sr;
+
+    // Set up StatusRequest that won't complete
+    sr.setWaiting(1);
+    sr.setTimeout(150);
+    sr.resetTimeout();
+
+    // Create task waiting for StatusRequest
+    Task waiter(100, 1, &consumer_callback, &ts);
+    waiter.waitFor(&sr);
+    waiter.setTimeout(200, true); // Task timeout longer than SR timeout
+
+    // Let everything run - StatusRequest should timeout first
+    delay(300);
+
+    // Run scheduler to process timeouts
+    for (int i = 0; i < 10; i++) {
+        ts.execute();
+        delay(10);
+    }
+
+    // Verify StatusRequest timed out
+    EXPECT_LE(sr.untilTimeout(), 0); // Should be negative (timed out)
+
+    // Task should eventually time out as well since SR never completed
+    EXPECT_TRUE(waiter.isTimedOut() || !waiter.isEnabled());
+}
+
+/**
+ * @brief Complex producer-consumer coordination with multiple features
+ *
+ * TESTS: Multi-feature integration in realistic scenario
+ *
+ * PURPOSE: Demonstrate complex coordination scenario using multiple
+ * advanced features together, validating that features work correctly
+ * in combination for real-world usage patterns.
+ *
+ * COMPLEX INTEGRATION FEATURES:
+ * - Producer task with timeout management
+ * - Multiple consumers waiting for producer completion
+ * - StatusRequest coordination with error handling
+ * - Scheduling options for priority control
+ * - Comprehensive error and timeout handling
+ *
+ * TEST SCENARIO:
+ * 1. Create producer task with timeout and high priority
+ * 2. Create multiple consumer tasks waiting for producer
+ * 3. Configure timeouts and scheduling options appropriately
+ * 4. Execute coordination scenario with success path
+ * 5. Verify all consumers execute after producer completion
+ *
+ * EXPECTATIONS:
+ * - Producer executes with proper priority and timing
+ * - All consumers wait appropriately for producer
+ * - StatusRequest coordination works correctly
+ * - All tasks execute in expected order
+ * - No timeouts or errors in success scenario
+ *
+ * IMPORTANCE: Complex integration validates that advanced features
+ * work together reliably, essential for building sophisticated
+ * multi-task applications with robust coordination patterns.
+ */
+TEST_F(AdvancedSchedulerTest, ComplexProducerConsumerCoordination) {
+    Scheduler ts;
+    StatusRequest production_complete;
+
+    // Set up production status request
+    production_complete.setWaiting(1);
+    production_complete.setTimeout(1000); // Allow plenty of time
+    production_complete.resetTimeout();
+
+    // Create producer task with high priority
+    Task producer(150, 1, [&production_complete]() {
+        advanced_callback_counter++;
+        advanced_test_output.push_back("producer_completed");
+        production_complete.signalComplete(100); // Success status
+    }, &ts, true);
+
+    producer.setTimeout(500, true);
+    producer.setSchedulingOption(10); // High priority
+
+    // Create multiple consumer tasks
+    Task consumer1(100, 1, []() {
+        advanced_callback_counter++;
+        advanced_test_output.push_back("consumer1_executed");
+    }, &ts);
+
+    Task consumer2(100, 1, []() {
+        advanced_callback_counter++;
+        advanced_test_output.push_back("consumer2_executed");
+    }, &ts);
+
+    Task consumer3(100, 1, []() {
+        advanced_callback_counter++;
+        advanced_test_output.push_back("consumer3_executed");
+    }, &ts);
+
+    // Configure consumers to wait for production
+    consumer1.waitFor(&production_complete);
+    consumer1.setTimeout(800, true);
+    consumer2.waitFor(&production_complete);
+    consumer2.setTimeout(800, true);
+    consumer3.waitFor(&production_complete);
+    consumer3.setTimeout(800, true);
+
+    // Execute the coordination scenario
+    bool success = runAdvancedSchedulerUntil(ts, []() {
+        return advanced_callback_counter >= 4; // Producer + 3 consumers
+    }, 1500);
+
+    EXPECT_TRUE(success);
+    EXPECT_EQ(advanced_callback_counter, 4);
+
+    // Verify execution order - producer should be first
+    EXPECT_EQ(getAdvancedTestOutput(0), "producer_completed");
+
+    // Verify StatusRequest completed successfully
+    EXPECT_TRUE(production_complete.completed());
+    EXPECT_EQ(production_complete.getStatus(), 100);
+
+    // Verify no timeouts occurred
+    EXPECT_FALSE(producer.isTimedOut());
+    EXPECT_FALSE(consumer1.isTimedOut());
+    EXPECT_FALSE(consumer2.isTimedOut());
+    EXPECT_FALSE(consumer3.isTimedOut());
+}
+
+/**
+ * @brief Main test runner function for advanced features
+ *
+ * Initializes Google Test framework and runs all advanced feature tests.
+ * Called by the test execution environment to start testing process.
+ *
+ * @param argc Command line argument count
+ * @param argv Command line argument values
+ * @return Test execution status (0 = success)
+ */
+int main(int argc, char **argv) {
+    ::testing::InitGoogleTest(&argc, argv);
+    return RUN_ALL_TESTS();
+}

+ 1992 - 0
tests/test-scheduler-basic-thorough-no-lambda.cpp

@@ -0,0 +1,1992 @@
+// test-scheduler-basic-thorough-no-lambda.cpp - Comprehensive TaskScheduler unit tests without lambda functions
+// This file contains comprehensive tests for basic TaskScheduler functionality
+// without using lambda functions, ensuring compatibility with all Arduino platforms
+//
+// =====================================================================================
+// COMPREHENSIVE TASKSCHEDULER TEST PLAN AND COVERAGE MATRIX (NO LAMBDA VERSION)
+// =====================================================================================
+//
+// PURPOSE: Validate all basic TaskScheduler methods and patterns without compile options
+// APPROACH: Traditional function pointers and callback functions for maximum compatibility
+// SCOPE: Core functionality excluding advanced features requiring compile-time directives
+//
+// COVERAGE MATRIX:
+// ================
+//
+// 1. TASK CONSTRUCTOR TESTS
+//    ├── Default Constructor
+//    │   └── Task() - creates inert task with safe defaults
+//    ├── Parameterized Constructor
+//    │   └── Task(interval, iterations, callback, scheduler, enable) - full configuration
+//    ├── Lifecycle Constructor
+//    │   └── Task(..., onEnable, onDisable) - with lifecycle callbacks
+//    └── Auto-enabled Constructor
+//        └── Task(..., enable=true) - immediate activation patterns
+//
+// 2. TASK INFORMATION METHODS
+//    ├── State Queries
+//    │   ├── isEnabled() - current activation state
+//    │   ├── getInterval() - execution timing interval
+//    │   ├── getIterations() - remaining execution count
+//    │   └── getRunCounter() - total executions completed
+//    └── Lifecycle Tracking
+//        └── Information accuracy across task lifecycle stages
+//
+// 3. TASK CONTROL METHODS
+//    ├── Basic Control
+//    │   ├── enable() - activate task for execution
+//    │   ├── disable() - deactivate task execution
+//    │   └── enableIfNot() - conditional enabling
+//    ├── Restart Operations
+//    │   ├── restart() - reset iteration count and re-enable
+//    │   └── restartDelayed(delay) - restart with initial delay
+//    └── State Management
+//        └── Control method interactions and state consistency
+//
+// 4. TASK TIMING METHODS
+//    ├── Execution Control
+//    │   ├── delay(ms) - postpone next execution
+//    │   ├── forceNextIteration() - immediate execution trigger
+//    │   └── enableDelayed(delay) - delayed activation
+//    └── Timing Behavior
+//        └── Interval and delay interactions with scheduler
+//
+// 5. TASK CONFIGURATION METHODS
+//    ├── Parameter Configuration
+//    │   ├── set(interval, iterations, callback, onEnable, onDisable) - complete reconfiguration
+//    │   ├── setInterval(interval) - dynamic timing changes
+//    │   └── setIterations(iterations) - dynamic repeat count
+//    └── Callback Management
+//        ├── setCallback(callback) - change execution function
+//        ├── setOnEnable(callback) - change enable callback
+//        └── setOnDisable(callback) - change disable callback
+//
+// 6. TASK ITERATION STATE METHODS
+//    ├── Execution Context
+//    │   ├── isFirstIteration() - detect initial execution
+//    │   └── isLastIteration() - detect final execution
+//    └── Context-Aware Programming
+//        └── Conditional logic based on iteration position
+//
+// 7. TASK CALLBACK SWITCHING METHODS
+//    ├── State Machine Support
+//    │   ├── yield(callback) - permanent callback change
+//    │   └── yieldOnce(callback) - single execution callback
+//    └── Multi-Phase Processing
+//        └── Sequential callback execution patterns
+//
+// 8. TASK LIFECYCLE CALLBACKS
+//    ├── Enable Events
+//    │   ├── onEnable() callbacks - activation event handling
+//    │   └── Conditional enabling via return values
+//    └── Disable Events
+//        └── onDisable() callbacks - deactivation event handling
+//
+// 9. SCHEDULER CONSTRUCTOR AND MANAGEMENT
+//    ├── Basic Operations
+//    │   ├── Scheduler() - empty scheduler creation
+//    │   ├── execute() - task execution cycle
+//    │   └── init() - scheduler reinitialization
+//    └── Robustness
+//        └── Safe operation with no tasks or empty states
+//
+// 10. SCHEDULER TASK MANAGEMENT
+//     ├── Manual Task Control
+//     │   ├── addTask(task) - explicit task registration
+//     │   └── deleteTask(task) - explicit task removal
+//     └── Dynamic Management
+//         └── Runtime task addition and removal patterns
+//
+// 11. SCHEDULER EXECUTION CONTROL
+//     ├── Execution Monitoring
+//     │   ├── execute() return values - idle detection
+//     │   ├── enableAll() - bulk task activation
+//     │   └── disableAll() - bulk task deactivation
+//     └── System Control
+//         └── Coordinated task state management
+//
+// 12. SCHEDULER TIME QUERIES
+//     ├── Timing Information
+//     │   └── timeUntilNextIteration(task) - predictive timing
+//     └── Scheduling Coordination
+//         └── Task timing coordination and synchronization
+//
+// 13. SCHEDULER TASK ACCESS
+//     ├── Context Information
+//     │   └── getCurrentTask() - callback context identification
+//     └── Self-Reference Patterns
+//         └── Task self-modification and introspection
+//
+// 14. SCHEDULER TIMING CONTROL
+//     ├── Global Control
+//     │   └── startNow() - immediate execution trigger
+//     └── Synchronized Operations
+//         └── Coordinated task restart and execution
+//
+// 15. INTEGRATION TESTS
+//     ├── Complete Lifecycle
+//     │   └── Full task lifecycle with all features
+//     └── Multi-Task Coordination
+//         └── Complex scenarios with multiple concurrent tasks
+//
+// 16. EDGE CASES AND ERROR HANDLING
+//     ├── Boundary Conditions
+//     │   ├── Zero iterations - invalid execution counts
+//     │   ├── Infinite iterations - TASK_FOREVER handling
+//     │   └── Null callbacks - robustness testing
+//     └── Defensive Programming
+//         └── Safe handling of invalid inputs and states
+//
+// =====================================================================================
+
+#include <gtest/gtest.h>
+#include "Arduino.h"
+#include "TaskScheduler.h"
+
+// Global test state - used to capture and verify callback executions
+std::vector<std::string> test_output;
+int callback_counter = 0;
+bool onEnable_called = false;
+bool onDisable_called = false;
+
+// Test callback functions (no lambda functions)
+
+/**
+ * @brief Basic callback function for general testing
+ *
+ * Simple callback that increments counter and records execution.
+ * Used for fundamental task execution verification.
+ */
+void basic_callback() {
+    callback_counter++;
+    test_output.push_back("basic_callback");
+    std::cout << "Basic callback executed at " << millis() << "ms" << std::endl;
+}
+
+/**
+ * @brief First test callback for multi-callback scenarios
+ *
+ * Used to distinguish between different callbacks in multi-task tests.
+ */
+void callback_1() {
+    callback_counter++;
+    test_output.push_back("callback_1");
+}
+
+/**
+ * @brief Second test callback for multi-callback scenarios
+ *
+ * Used in coordination tests and callback switching verification.
+ */
+void callback_2() {
+    callback_counter++;
+    test_output.push_back("callback_2");
+}
+
+/**
+ * @brief Third test callback for complex scenarios
+ *
+ * Additional callback for testing multiple task coordination.
+ */
+void callback_3() {
+    callback_counter++;
+    test_output.push_back("callback_3");
+}
+
+/**
+ * @brief Multi-step callback for yield testing - step 1
+ *
+ * First phase of multi-step processing for callback switching tests.
+ */
+void multi_step_callback_1() {
+    test_output.push_back("step_1");
+}
+
+/**
+ * @brief Multi-step callback for yield testing - step 2
+ *
+ * Second phase of multi-step processing for callback switching tests.
+ */
+void multi_step_callback_2() {
+    test_output.push_back("step_2");
+}
+
+/**
+ * @brief Multi-step callback for yield testing - step 3
+ *
+ * Third phase of multi-step processing for callback switching tests.
+ */
+void multi_step_callback_3() {
+    test_output.push_back("step_3");
+}
+
+/**
+ * @brief OnEnable lifecycle callback that allows enabling
+ *
+ * Returns true to allow task enabling. Used for testing
+ * normal lifecycle callback behavior.
+ */
+bool test_onEnable() {
+    onEnable_called = true;
+    test_output.push_back("onEnable_called");
+    return true;
+}
+
+/**
+ * @brief OnEnable lifecycle callback that prevents enabling
+ *
+ * Returns false to prevent task enabling. Used for testing
+ * conditional enabling behavior.
+ */
+bool test_onEnable_false() {
+    onEnable_called = true;
+    test_output.push_back("onEnable_called_false");
+    return false;
+}
+
+/**
+ * @brief OnDisable lifecycle callback
+ *
+ * Called when task is disabled. Used for testing
+ * lifecycle callback behavior.
+ */
+void test_onDisable() {
+    onDisable_called = true;
+    test_output.push_back("onDisable_called");
+}
+
+/**
+ * @brief Repeating callback for iteration testing
+ *
+ * Uses static counter to track execution number, enabling verification
+ * of proper iteration counting and repeated execution behavior.
+ */
+void repeating_callback() {
+    static int counter = 0;
+    counter++;
+    test_output.push_back("Repeating task #" + std::to_string(counter));
+    std::cout << "Repeating task #" << counter << " executed at " << millis() << "ms" << std::endl;
+}
+
+/**
+ * @brief Callback for yield switching tests
+ *
+ * Records execution and prepares for yield switching behavior.
+ */
+void yield_test_callback() {
+    test_output.push_back("yield_original");
+}
+
+/**
+ * @brief Callback for yield-once testing
+ *
+ * Records execution for yield-once verification.
+ */
+void yield_once_callback() {
+    test_output.push_back("yield_once_executed");
+}
+
+// Test fixture for comprehensive scheduler testing
+class SchedulerThoroughTest : public ::testing::Test {
+protected:
+    void SetUp() override {
+        clearTestOutput();
+        callback_counter = 0;
+        onEnable_called = false;
+        onDisable_called = false;
+        millis(); // Initialize timing
+    }
+
+    void TearDown() override {
+        clearTestOutput();
+        callback_counter = 0;
+        onEnable_called = false;
+        onDisable_called = false;
+    }
+
+    bool runSchedulerUntil(Scheduler& ts, std::function<bool()> condition, unsigned long timeout_ms = 1000) {
+        return waitForCondition([&]() {
+            ts.execute();
+            return condition();
+        }, timeout_ms);
+    }
+};
+
+// ================== TASK CONSTRUCTOR TESTS ==================
+
+/**
+ * @brief Test Task default constructor behavior
+ *
+ * TESTS: Task()
+ *
+ * PURPOSE: Verify that a Task created with the default constructor initializes
+ * all properties to safe default values and is in a predictable state.
+ *
+ * EXPECTATIONS:
+ * - Task should be disabled by default (safety)
+ * - Interval should be 0 (no automatic execution)
+ * - Iterations should be 0 (won't execute)
+ * - RunCounter should be 0 (hasn't executed yet)
+ *
+ * IMPORTANCE: Default constructor must create a safe, inert task that won't
+ * execute unexpectedly. This is critical for safe initialization patterns.
+ */
+TEST_F(SchedulerThoroughTest, TaskDefaultConstructor) {
+    Task task;
+
+    // Verify task is in safe, inert state after default construction
+    EXPECT_FALSE(task.isEnabled());     // Should not execute without explicit enable
+    EXPECT_EQ(task.getInterval(), 0);   // No automatic timing
+    EXPECT_EQ(task.getIterations(), 0); // Won't execute without iterations set
+    EXPECT_EQ(task.getRunCounter(), 0); // No executions yet
+}
+
+/**
+ * @brief Test Task parameterized constructor with all options
+ *
+ * TESTS: Task(interval, iterations, callback, scheduler, enable)
+ *
+ * PURPOSE: Verify that the full constructor properly sets all task parameters
+ * and correctly associates the task with a scheduler.
+ *
+ * PARAMETERS TESTED:
+ * - interval: 1000ms (1 second execution interval)
+ * - iterations: 5 (task will execute 5 times then auto-disable)
+ * - callback: basic_callback function pointer
+ * - scheduler: reference to scheduler for automatic addition
+ * - enable: false (task starts disabled for manual control)
+ *
+ * EXPECTATIONS:
+ * - All parameters should be set exactly as specified
+ * - Task should be disabled initially (enable=false)
+ * - RunCounter starts at 0 (no executions yet)
+ * - Task should be automatically added to scheduler's chain
+ *
+ * IMPORTANCE: This tests the most common Task creation pattern and ensures
+ * all parameters are correctly stored and accessible.
+ */
+TEST_F(SchedulerThoroughTest, TaskParameterizedConstructor) {
+    Scheduler ts;
+    Task task(1000, 5, &basic_callback, &ts, false);
+
+    // Verify all constructor parameters were set correctly
+    EXPECT_FALSE(task.isEnabled());      // enable=false parameter
+    EXPECT_EQ(task.getInterval(), 1000); // 1000ms interval parameter
+    EXPECT_EQ(task.getIterations(), 5);  // 5 iterations parameter
+    EXPECT_EQ(task.getRunCounter(), 0);  // No executions yet
+    // Note: callback and scheduler assignment tested in execution tests
+}
+
+/**
+ * @brief Test Task constructor with OnEnable/OnDisable callbacks
+ *
+ * TESTS: Task(interval, iterations, callback, scheduler, enable, onEnable, onDisable)
+ *
+ * PURPOSE: Verify that the full constructor with lifecycle callbacks correctly
+ * stores callback pointers without invoking them during construction.
+ *
+ * LIFECYCLE CALLBACKS:
+ * - onEnable: Called when task is enabled (should return bool)
+ * - onDisable: Called when task is disabled
+ *
+ * EXPECTATIONS:
+ * - All basic parameters set correctly
+ * - Callback pointers stored but not invoked during construction
+ * - Global callback flags remain false (not called yet)
+ * - Task ready for enable/disable lifecycle events
+ *
+ * IMPORTANCE: Validates that lifecycle callbacks are properly registered
+ * without premature invocation, ensuring controlled task lifecycle management.
+ */
+TEST_F(SchedulerThoroughTest, TaskConstructorWithOnEnableOnDisable) {
+    Scheduler ts;
+    Task task(500, 3, &basic_callback, &ts, false, &test_onEnable, &test_onDisable);
+
+    // Verify basic parameters are set correctly
+    EXPECT_FALSE(task.isEnabled());
+    EXPECT_EQ(task.getInterval(), 500);
+    EXPECT_EQ(task.getIterations(), 3);
+
+    // Verify lifecycle callbacks are registered but not yet called
+    EXPECT_FALSE(onEnable_called);  // onEnable not called during construction
+    EXPECT_FALSE(onDisable_called); // onDisable not called during construction
+}
+
+/**
+ * @brief Test Task constructor with automatic enable
+ *
+ * TESTS: Task(..., enable=true) + immediate execution behavior
+ *
+ * PURPOSE: Verify that tasks created with enable=true are immediately ready
+ * for execution and will run on the first scheduler pass.
+ *
+ * AUTO-ENABLE BEHAVIOR:
+ * - Task becomes enabled immediately during construction
+ * - Task is scheduled for immediate execution (no delay)
+ * - First scheduler pass should execute the task
+ *
+ * EXPECTATIONS:
+ * - Task should be enabled after construction
+ * - Task should execute successfully on first scheduler run
+ * - Callback counter should increment correctly
+ *
+ * IMPORTANCE: Tests the convenience constructor that creates immediately
+ * active tasks, commonly used for initialization or startup tasks.
+ */
+TEST_F(SchedulerThoroughTest, TaskConstructorAutoEnabled) {
+    Scheduler ts;
+    Task task(100, 1, &basic_callback, &ts, true); // enable=true
+
+    // Verify task is enabled immediately after construction
+    EXPECT_TRUE(task.isEnabled());
+
+    // Verify task executes on first scheduler pass
+    bool success = runSchedulerUntil(ts, []() { return callback_counter >= 1; });
+    EXPECT_TRUE(success);           // Execution should succeed
+    EXPECT_EQ(callback_counter, 1); // Should execute exactly once
+}
+
+// ================== TASK INFORMATION METHODS TESTS ==================
+
+/**
+ * @brief Test all Task information getter methods through task lifecycle
+ *
+ * TESTS: isEnabled(), getInterval(), getIterations(), getRunCounter()
+ *
+ * PURPOSE: Verify that information methods return correct values at different
+ * stages of task lifecycle and properly track state changes.
+ *
+ * METHODS TESTED:
+ * - isEnabled(): Returns current enabled/disabled state
+ * - getInterval(): Returns execution interval in milliseconds
+ * - getIterations(): Returns remaining iterations (decrements after each run)
+ * - getRunCounter(): Returns total executions since last enable (increments)
+ *
+ * LIFECYCLE STAGES TESTED:
+ * 1. Initial state (after construction)
+ * 2. After enabling (before execution)
+ * 3. After first execution (state changes)
+ *
+ * EXPECTATIONS:
+ * - Initial: disabled, interval=2000, iterations=10, runCounter=0
+ * - After enable: enabled, same interval/iterations, runCounter still 0
+ * - After execution: enabled, same interval, iterations=9, runCounter=1
+ *
+ * IMPORTANCE: These methods are fundamental for task monitoring and debugging.
+ * Accurate state reporting is critical for application logic and diagnostics.
+ */
+TEST_F(SchedulerThoroughTest, TaskInformationMethods) {
+    Scheduler ts;
+    Task task(2000, 10, &basic_callback, &ts, false);
+
+    // Test initial state immediately after construction
+    EXPECT_FALSE(task.isEnabled());     // Should be disabled (enable=false)
+    EXPECT_EQ(task.getInterval(), 2000); // Should match constructor parameter
+    EXPECT_EQ(task.getIterations(), 10); // Should match constructor parameter
+    EXPECT_EQ(task.getRunCounter(), 0);  // No executions yet
+
+    // Test state after enabling (but before execution)
+    task.enable();
+    EXPECT_TRUE(task.isEnabled());      // Should now be enabled
+    EXPECT_EQ(task.getRunCounter(), 0); // Still 0 before first execution
+    // Interval and iterations should remain unchanged
+
+    // Test state after first execution
+    bool success = runSchedulerUntil(ts, []() { return callback_counter >= 1; });
+    EXPECT_TRUE(success);
+    EXPECT_EQ(task.getRunCounter(), 1);  // Should increment to 1
+    EXPECT_EQ(task.getIterations(), 9);  // Should decrement to 9
+    // Task should still be enabled and interval unchanged
+}
+
+// ================== TASK CONTROL METHODS TESTS ==================
+
+/**
+ * @brief Test Task enable() and disable() methods with lifecycle callbacks
+ *
+ * TESTS: enable(), disable(), isEnabled()
+ *
+ * PURPOSE: Verify that enable/disable methods correctly change task state,
+ * trigger appropriate lifecycle callbacks, and properly control task execution.
+ *
+ * CONTROL METHODS TESTED:
+ * - enable(): Activates task for execution, triggers onEnable callback
+ * - disable(): Deactivates task, stops execution, triggers onDisable callback
+ * - isEnabled(): Returns current activation state
+ *
+ * LIFECYCLE CALLBACK BEHAVIOR:
+ * - onEnable(): Called when task transitions from disabled to enabled
+ * - onDisable(): Called when task transitions from enabled to disabled
+ * - Callbacks allow custom logic during state transitions
+ *
+ * TEST SCENARIOS:
+ * 1. Enable disabled task (should trigger onEnable)
+ * 2. Check execution capability (enabled task should execute)
+ * 3. Disable enabled task (should trigger onDisable, stop execution)
+ * 4. Verify no execution after disable
+ *
+ * EXPECTATIONS:
+ * - State changes should be immediate and accurate
+ * - Lifecycle callbacks should be invoked exactly once per transition
+ * - Execution behavior should match enabled state
+ *
+ * IMPORTANCE: Enable/disable is the primary method for dynamic task control.
+ * This functionality is essential for responsive, event-driven applications.
+ */
+TEST_F(SchedulerThoroughTest, TaskEnableDisable) {
+    Scheduler ts;
+    Task task(100, 3, &basic_callback, &ts, false);
+
+    // Test enable
+    EXPECT_FALSE(task.isEnabled());
+    task.enable();
+    EXPECT_TRUE(task.isEnabled());
+
+    // Test disable
+    bool prev_state = task.disable();
+    EXPECT_TRUE(prev_state); // Was enabled
+    EXPECT_FALSE(task.isEnabled());
+
+    // Test disable when already disabled
+    prev_state = task.disable();
+    EXPECT_FALSE(prev_state); // Was disabled
+    EXPECT_FALSE(task.isEnabled());
+}
+
+/**
+ * @brief Test Task enableIfNot() conditional enable method
+ *
+ * TESTS: enableIfNot()
+ *
+ * PURPOSE: Verify that enableIfNot() provides safe conditional enabling,
+ * avoiding redundant state changes and providing status feedback.
+ *
+ * METHOD BEHAVIOR:
+ * - enableIfNot(): Enables task only if currently disabled
+ * - Returns previous enabled state (false = was disabled, true = was enabled)
+ * - Prevents redundant onEnable callback triggers
+ * - Idempotent operation (safe to call multiple times)
+ *
+ * TEST SCENARIOS:
+ * 1. Call on disabled task (should enable and return false)
+ * 2. Call on enabled task (should remain enabled and return true)
+ *
+ * EXPECTATIONS:
+ * - First call: task becomes enabled, returns false (was disabled)
+ * - Second call: task remains enabled, returns true (was already enabled)
+ * - No side effects from redundant calls
+ *
+ * IMPORTANCE: Conditional enabling prevents unnecessary state transitions
+ * and provides application feedback about previous state, useful for
+ * toggle operations and preventing callback storms.
+ */
+TEST_F(SchedulerThoroughTest, TaskEnableIfNot) {
+    Scheduler ts;
+    Task task(100, 1, &basic_callback, &ts, false);
+
+    // Enable when disabled
+    bool was_enabled = task.enableIfNot();
+    EXPECT_FALSE(was_enabled); // Was disabled
+    EXPECT_TRUE(task.isEnabled());
+
+    // Try to enable when already enabled
+    was_enabled = task.enableIfNot();
+    EXPECT_TRUE(was_enabled); // Was already enabled
+    EXPECT_TRUE(task.isEnabled());
+}
+
+/**
+ * @brief Test Task restart() method for resetting task state
+ *
+ * TESTS: restart()
+ *
+ * PURPOSE: Verify that restart() properly resets task execution state
+ * while maintaining configuration, allowing tasks to run their full
+ * iteration cycle again.
+ *
+ * METHOD BEHAVIOR:
+ * - restart(): Resets iteration counter to original value
+ * - Resets run counter to 0
+ * - Maintains enabled state
+ * - Preserves interval and callback configuration
+ * - Schedules immediate execution (no delay)
+ *
+ * TEST SCENARIO:
+ * 1. Create task with 3 iterations
+ * 2. Let it execute once (iterations should decrement to 2)
+ * 3. Call restart() (should reset iterations to 3)
+ * 4. Verify state is properly reset
+ *
+ * EXPECTATIONS:
+ * - After first execution: getIterations() returns 2
+ * - After restart(): getIterations() returns original value (3)
+ * - Task remains enabled throughout
+ * - Ready for immediate re-execution
+ *
+ * IMPORTANCE: Restart functionality enables task recycling and repetitive
+ * workflows without recreating task objects, essential for state machines
+ * and cyclic operations.
+ */
+TEST_F(SchedulerThoroughTest, TaskRestart) {
+    Scheduler ts;
+    Task task(100, 3, &basic_callback, &ts, true);
+
+    // Let it run once
+    bool success = runSchedulerUntil(ts, []() { return callback_counter >= 1; });
+    EXPECT_TRUE(success);
+    EXPECT_EQ(task.getIterations(), 2); // Should be decremented
+
+    // Restart should reset iterations
+    task.restart();
+    EXPECT_EQ(task.getIterations(), 3); // Reset to original
+    EXPECT_TRUE(task.isEnabled());
+}
+
+/**
+ * @brief Test Task restartDelayed() method for delayed task reset
+ *
+ * TESTS: restartDelayed(delay)
+ *
+ * PURPOSE: Verify that restartDelayed() resets task state like restart()
+ * but introduces a specified delay before first execution, useful for
+ * timed restart scenarios and spacing between task cycles.
+ *
+ * METHOD BEHAVIOR:
+ * - restartDelayed(delay): Combines restart() with initial delay
+ * - Resets iteration and run counters like restart()
+ * - Schedules first execution after specified delay
+ * - Subsequent executions follow normal interval timing
+ * - Task remains enabled but dormant during delay period
+ *
+ * TEST SCENARIO:
+ * 1. Execute task once to modify its state
+ * 2. Call restartDelayed(200ms)
+ * 3. Verify no immediate execution (delay period)
+ * 4. Verify execution occurs after delay expires
+ *
+ * EXPECTATIONS:
+ * - Immediate period: no execution despite scheduler calls
+ * - After delay: task executes normally with reset state
+ * - Callback counter increments only after delay period
+ *
+ * IMPORTANCE: Delayed restart enables controlled timing gaps between
+ * task cycles, essential for rate limiting and synchronized multi-task
+ * restart scenarios.
+ */
+TEST_F(SchedulerThoroughTest, TaskRestartDelayed) {
+    Scheduler ts;
+    Task task(50, 2, &basic_callback, &ts, true);
+
+    // Let it run once
+    bool success = runSchedulerUntil(ts, []() { return callback_counter >= 1; });
+    EXPECT_TRUE(success);
+
+    int count_before_restart = callback_counter;
+    task.restartDelayed(200); // Restart with 200ms delay
+
+    // Should not execute immediately
+    delay(50);
+    ts.execute();
+    EXPECT_EQ(callback_counter, count_before_restart);
+
+    // Should execute after delay
+    delay(200);
+    success = runSchedulerUntil(ts, [count_before_restart]() {
+        return callback_counter > count_before_restart;
+    });
+    EXPECT_TRUE(success);
+}
+
+// ================== TASK TIMING METHODS TESTS ==================
+
+/**
+ * @brief Test Task delay() method for postponing next execution
+ *
+ * TESTS: delay(milliseconds)
+ *
+ * PURPOSE: Verify that delay() correctly postpones the next scheduled
+ * execution by the specified amount, without affecting the task's
+ * normal interval timing for subsequent executions.
+ *
+ * METHOD BEHAVIOR:
+ * - delay(ms): Postpones next execution by specified milliseconds
+ * - Affects only the next execution, not the interval permanently
+ * - Task remains enabled during delay period
+ * - After delayed execution, normal interval timing resumes
+ * - Can be called multiple times to accumulate delays
+ *
+ * TEST SCENARIO:
+ * 1. Execute task once to establish baseline
+ * 2. Call delay(150ms) to postpone next execution
+ * 3. Verify no execution during delay period (50ms < 150ms)
+ * 4. Verify execution occurs after delay expires
+ *
+ * EXPECTATIONS:
+ * - During delay: callback counter unchanged despite scheduler calls
+ * - After delay: task executes and counter increments
+ * - Subsequent executions follow normal interval
+ *
+ * IMPORTANCE: Dynamic delay allows responsive timing adjustments
+ * based on runtime conditions, essential for adaptive scheduling
+ * and event-driven timing modifications.
+ */
+TEST_F(SchedulerThoroughTest, TaskDelay) {
+    Scheduler ts;
+    Task task(50, 5, &basic_callback, &ts, true);
+
+    // Let it run once
+    bool success = runSchedulerUntil(ts, []() { return callback_counter >= 1; });
+    EXPECT_TRUE(success);
+
+    int count_before_delay = callback_counter;
+    task.delay(150); // Delay next execution
+
+    // Should not execute immediately
+    delay(50);
+    ts.execute();
+    EXPECT_EQ(callback_counter, count_before_delay);
+
+    // Should execute after delay
+    delay(150);
+    success = runSchedulerUntil(ts, [count_before_delay]() {
+        return callback_counter > count_before_delay;
+    });
+    EXPECT_TRUE(success);
+}
+
+/**
+ * @brief Test Task forceNextIteration() method for immediate execution
+ *
+ * TESTS: forceNextIteration()
+ *
+ * PURPOSE: Verify that forceNextIteration() bypasses normal interval timing
+ * and schedules the task for immediate execution on the next scheduler pass,
+ * useful for triggering urgent or event-driven task execution.
+ *
+ * METHOD BEHAVIOR:
+ * - forceNextIteration(): Marks task for immediate execution
+ * - Bypasses remaining interval wait time
+ * - Does not affect subsequent interval timing
+ * - Works only if task is enabled
+ * - Executes on very next scheduler.execute() call
+ *
+ * TEST SCENARIO:
+ * 1. Create task with long interval (1000ms) to prevent natural execution
+ * 2. Let it execute once (starts long interval timer)
+ * 3. Call forceNextIteration() during interval wait
+ * 4. Verify immediate execution on next scheduler pass
+ *
+ * EXPECTATIONS:
+ * - Without force: task would wait full 1000ms interval
+ * - With force: task executes immediately despite interval
+ * - Callback counter increments immediately after force
+ *
+ * IMPORTANCE: Force execution enables responsive event handling and
+ * priority task execution, essential for interrupt-driven scenarios
+ * and urgent task processing.
+ */
+TEST_F(SchedulerThoroughTest, TaskForceNextIteration) {
+    Scheduler ts;
+    Task task(1000, 3, &basic_callback, &ts, true); // Long interval
+
+    // Execute immediately due to enable
+    bool success = runSchedulerUntil(ts, []() { return callback_counter >= 1; });
+    EXPECT_TRUE(success);
+
+    int count_before_force = callback_counter;
+    task.forceNextIteration();
+
+    // Should execute immediately on next scheduler pass
+    success = runSchedulerUntil(ts, [count_before_force]() {
+        return callback_counter > count_before_force;
+    });
+    EXPECT_TRUE(success);
+}
+
+/**
+ * @brief Test Task enableDelayed() method for delayed activation
+ *
+ * TESTS: enableDelayed(delay)
+ *
+ * PURPOSE: Verify that enableDelayed() enables a task but delays its
+ * first execution by the specified amount, useful for coordinated
+ * task startup and avoiding immediate execution.
+ *
+ * METHOD BEHAVIOR:
+ * - enableDelayed(ms): Enables task but delays first execution
+ * - Task becomes enabled immediately (isEnabled() returns true)
+ * - First execution waits for specified delay period
+ * - After first execution, normal interval timing applies
+ * - Different from enable() which executes immediately
+ *
+ * TEST SCENARIO:
+ * 1. Create disabled task
+ * 2. Call enableDelayed(200ms)
+ * 3. Verify task is enabled but doesn't execute immediately
+ * 4. Verify execution occurs after delay period
+ *
+ * EXPECTATIONS:
+ * - Task enabled: isEnabled() returns true immediately
+ * - During delay: no execution despite scheduler calls
+ * - After delay: task executes normally
+ *
+ * IMPORTANCE: Delayed enabling allows coordinated task startup
+ * sequences and prevents initial execution conflicts, essential
+ * for synchronized multi-task systems.
+ */
+TEST_F(SchedulerThoroughTest, TaskEnableDelayed) {
+    Scheduler ts;
+    Task task(100, 1, &basic_callback, &ts, false);
+
+    task.enableDelayed(200);
+    EXPECT_TRUE(task.isEnabled());
+
+    // Should not execute immediately
+    delay(50);
+    ts.execute();
+    EXPECT_EQ(callback_counter, 0);
+
+    // Should execute after delay
+    delay(200);
+    bool success = runSchedulerUntil(ts, []() { return callback_counter >= 1; });
+    EXPECT_TRUE(success);
+}
+
+// ================== TASK CONFIGURATION METHODS TESTS ==================
+
+/**
+ * @brief Test Task set() method for complete task reconfiguration
+ *
+ * TESTS: set(interval, iterations, callback, onEnable, onDisable)
+ *
+ * PURPOSE: Verify that set() completely reconfigures a task with new
+ * parameters, allowing task objects to be reused with different
+ * configurations without recreation.
+ *
+ * METHOD BEHAVIOR:
+ * - set(): Replaces all task configuration parameters
+ * - Updates interval, iterations, callback, and lifecycle callbacks
+ * - Does not change enabled state (task remains in current state)
+ * - Resets internal counters and timing
+ * - Allows complete task repurposing
+ *
+ * TEST SCENARIO:
+ * 1. Create default task (empty configuration)
+ * 2. Use set() to configure with specific parameters
+ * 3. Verify all parameters were set correctly
+ * 4. Verify task remains disabled (set() doesn't enable)
+ *
+ * EXPECTATIONS:
+ * - All set parameters should be retrievable via getter methods
+ * - Task should remain disabled (set() doesn't enable)
+ * - Task ready for enable() to start with new configuration
+ *
+ * IMPORTANCE: Set method enables task object reuse and dynamic
+ * reconfiguration, essential for flexible task management and
+ * memory-efficient applications.
+ */
+TEST_F(SchedulerThoroughTest, TaskSetMethod) {
+    Scheduler ts;
+    Task task;
+
+    task.set(300, 7, &basic_callback, &test_onEnable, &test_onDisable);
+
+    EXPECT_EQ(task.getInterval(), 300);
+    EXPECT_EQ(task.getIterations(), 7);
+    EXPECT_FALSE(task.isEnabled());
+}
+
+/**
+ * @brief Test Task setInterval() method for dynamic timing changes
+ *
+ * TESTS: setInterval(newInterval), getInterval()
+ *
+ * PURPOSE: Verify that setInterval() dynamically changes task execution
+ * timing and that changes take effect for subsequent executions,
+ * enabling adaptive and responsive timing control.
+ *
+ * METHOD BEHAVIOR:
+ * - setInterval(ms): Changes execution interval for future executions
+ * - Does not affect current timing if task is mid-interval
+ * - New interval applies to next scheduled execution
+ * - Can be called multiple times to adjust timing dynamically
+ * - Allows real-time timing optimization
+ *
+ * TEST SCENARIO:
+ * 1. Create task with initial 100ms interval
+ * 2. Change interval to 500ms and verify getter
+ * 3. Let task execute once with new timing
+ * 4. Change interval to 200ms during execution
+ * 5. Verify next execution uses new 200ms interval
+ *
+ * EXPECTATIONS:
+ * - getInterval() returns updated value immediately
+ * - Execution timing reflects new interval settings
+ * - Dynamic changes affect subsequent executions
+ *
+ * IMPORTANCE: Dynamic interval adjustment enables adaptive systems
+ * that respond to load, priority, or environmental changes in real-time,
+ * essential for responsive and efficient applications.
+ */
+TEST_F(SchedulerThoroughTest, TaskSetInterval) {
+    Scheduler ts;
+    Task task(100, 2, &basic_callback, &ts, true);
+
+    task.setInterval(500);
+    EXPECT_EQ(task.getInterval(), 500);
+
+    // Interval change should affect timing
+    unsigned long start_time = millis();
+    bool success = runSchedulerUntil(ts, []() { return callback_counter >= 1; });
+    EXPECT_TRUE(success);
+
+    task.setInterval(200);
+    int count_before = callback_counter;
+    success = runSchedulerUntil(ts, [count_before]() {
+        return callback_counter > count_before;
+    }, 300);
+    EXPECT_TRUE(success);
+}
+
+/**
+ * @brief Test Task setIterations() method for dynamic repetition control
+ *
+ * TESTS: setIterations(newIterations), getIterations()
+ *
+ * PURPOSE: Verify that setIterations() dynamically changes the number of
+ * remaining executions and that tasks properly auto-disable when reaching
+ * zero iterations, enabling flexible execution count management.
+ *
+ * METHOD BEHAVIOR:
+ * - setIterations(count): Sets number of remaining executions
+ * - Count decrements with each execution
+ * - Task auto-disables when iterations reach zero
+ * - Can extend or reduce remaining executions dynamically
+ * - TASK_FOREVER can be set for infinite execution
+ *
+ * TEST SCENARIO:
+ * 1. Create task with initial 2 iterations
+ * 2. Change to 5 iterations before execution
+ * 3. Let task run complete cycle (5 executions)
+ * 4. Verify task auto-disables after completing all iterations
+ *
+ * EXPECTATIONS:
+ * - getIterations() returns updated count
+ * - Task executes exactly 5 times (new iteration count)
+ * - Task automatically disables after final iteration
+ * - Callback counter reaches exactly 5
+ *
+ * IMPORTANCE: Dynamic iteration control allows adaptive execution
+ * cycles based on runtime conditions, essential for conditional
+ * processing and resource-conscious applications.
+ */
+TEST_F(SchedulerThoroughTest, TaskSetIterations) {
+    Scheduler ts;
+    Task task(100, 2, &basic_callback, &ts, true);
+
+    task.setIterations(5);
+    EXPECT_EQ(task.getIterations(), 5);
+
+    // Should run 5 times
+    bool success = runSchedulerUntil(ts, []() { return callback_counter >= 5; });
+    EXPECT_TRUE(success);
+    EXPECT_EQ(callback_counter, 5);
+    EXPECT_FALSE(task.isEnabled()); // Should auto-disable after iterations
+}
+
+/**
+ * @brief Test Task callback switching methods for dynamic behavior
+ *
+ * TESTS: setCallback(), setOnEnable(), setOnDisable()
+ *
+ * PURPOSE: Verify that callback methods can be dynamically changed during
+ * task lifetime, enabling flexible behavior modification and state-dependent
+ * functionality without task recreation.
+ *
+ * CALLBACK TYPES TESTED:
+ * - setCallback(): Changes main execution callback function
+ * - setOnEnable(): Changes lifecycle callback for enable events
+ * - setOnDisable(): Changes lifecycle callback for disable events
+ *
+ * METHOD BEHAVIOR:
+ * - Callbacks can be changed while task is running
+ * - New callbacks take effect immediately
+ * - Previous callbacks are completely replaced
+ * - Lifecycle callbacks trigger during state transitions
+ *
+ * TEST SCENARIO:
+ * 1. Create task with callback_1 function
+ * 2. Switch to callback_2 and verify execution uses new callback
+ * 3. Set lifecycle callbacks and verify they trigger during state changes
+ *
+ * EXPECTATIONS:
+ * - Execution produces output from new callback (callback_2)
+ * - Enable transition triggers onEnable callback
+ * - Disable transition triggers onDisable callback
+ * - All callback switches take effect immediately
+ *
+ * IMPORTANCE: Dynamic callback switching enables state machines,
+ * adaptive behavior, and multi-phase task processing without
+ * complex conditional logic in callbacks.
+ */
+TEST_F(SchedulerThoroughTest, TaskSetCallbacks) {
+    Scheduler ts;
+    Task task(100, 2, &callback_1, &ts, false);
+
+    // Test setCallback
+    task.setCallback(&callback_2);
+    task.enable();
+
+    bool success = runSchedulerUntil(ts, []() { return getTestOutputCount() >= 1; });
+    EXPECT_TRUE(success);
+    EXPECT_EQ(getTestOutput(0), "callback_2");
+
+    // Test setOnEnable and setOnDisable
+    task.setOnEnable(&test_onEnable);
+    task.setOnDisable(&test_onDisable);
+
+    task.disable();
+    task.enable();
+
+    EXPECT_TRUE(onEnable_called);
+    task.disable();
+    EXPECT_TRUE(onDisable_called);
+}
+
+// ================== TASK ITERATION STATE TESTS ==================
+
+/**
+ * @brief Test Task iteration state query methods for execution context
+ *
+ * TESTS: isFirstIteration(), isLastIteration()
+ *
+ * PURPOSE: Verify that iteration state query methods correctly identify
+ * the execution context within a task's iteration cycle, enabling
+ * conditional logic based on iteration position.
+ *
+ * STATE METHODS TESTED:
+ * - isFirstIteration(): Returns true only during the first execution
+ * - isLastIteration(): Returns true only during the final execution
+ * - Both provide context for conditional callback behavior
+ *
+ * TEST SCENARIO:
+ * 1. Create task with 3 iterations
+ * 2. Execute first iteration (implicit due to enable=true)
+ * 3. Use modified callback to check states during iterations 2 and 3
+ * 4. Verify correct state reporting for middle and final iterations
+ *
+ * EXPECTATIONS:
+ * - First iteration: isFirstIteration()=true, isLastIteration()=false
+ * - Middle iteration: isFirstIteration()=false, isLastIteration()=false
+ * - Final iteration: isFirstIteration()=false, isLastIteration()=true
+ *
+ * IMPORTANCE: Iteration state queries enable initialization and cleanup
+ * logic within callbacks, essential for resource management and
+ * conditional processing based on execution phase.
+ */
+TEST_F(SchedulerThoroughTest, TaskIterationState) {
+    Scheduler ts;
+    Task task(100, 3, &basic_callback, &ts, true);
+
+    // First iteration
+    bool success = runSchedulerUntil(ts, []() { return callback_counter >= 1; });
+    EXPECT_TRUE(success);
+
+    // Note: Testing iteration state requires access during callback execution
+    // This test verifies the task completes its iterations properly
+    success = runSchedulerUntil(ts, []() { return callback_counter >= 3; });
+    EXPECT_TRUE(success);
+    EXPECT_EQ(callback_counter, 3);
+    EXPECT_FALSE(task.isEnabled()); // Should auto-disable after 3 iterations
+}
+
+// ================== TASK CALLBACK SWITCHING TESTS ==================
+
+/**
+ * @brief Test Task yield() method for dynamic callback switching
+ *
+ * TESTS: yield(newCallback)
+ *
+ * PURPOSE: Verify that yield() permanently switches the task's callback
+ * function to a new function, enabling state machine behavior and
+ * multi-phase task processing within a single task object.
+ *
+ * METHOD BEHAVIOR:
+ * - yield(callback): Permanently changes task's callback function
+ * - Switch takes effect immediately
+ * - All subsequent executions use the new callback
+ * - Original callback is completely replaced
+ * - Enables state machine and multi-step processing patterns
+ *
+ * TEST SCENARIO:
+ * 1. Create task with multi_step_callback_1
+ * 2. In callback, switch to multi_step_callback_2 via yield
+ * 3. Verify first execution produces "step_1" output
+ * 4. Verify second execution produces "step_2" output (new callback)
+ *
+ * EXPECTATIONS:
+ * - First execution: "step_1" output from original callback
+ * - Yield call: switches to multi_step_callback_2
+ * - Second execution: "step_2" output from new callback
+ * - All future executions use new callback
+ *
+ * IMPORTANCE: Yield enables complex state machines and multi-phase
+ * processing within single tasks, essential for sequential operations
+ * and adaptive task behavior.
+ */
+TEST_F(SchedulerThoroughTest, TaskYield) {
+    Scheduler ts;
+
+    // Create a global task pointer for the callback to access
+    static Task* yield_task = nullptr;
+
+    // Callback that will yield to another callback
+    auto yield_callback = []() {
+        test_output.push_back("step_1");
+        if (yield_task) {
+            yield_task->yield(&multi_step_callback_2);
+        }
+    };
+
+    Task task(200, 3, yield_callback, &ts, true);
+    yield_task = &task;
+
+    // First execution should produce step_1 and yield
+    bool success = runSchedulerUntil(ts, []() { return getTestOutputCount() >= 1; });
+    EXPECT_TRUE(success);
+    EXPECT_EQ(getTestOutput(0), "step_1");
+
+    // Second execution should produce step_2 from yielded callback
+    success = runSchedulerUntil(ts, []() { return getTestOutputCount() >= 2; });
+    EXPECT_TRUE(success);
+    EXPECT_EQ(getTestOutput(1), "step_2");
+
+    yield_task = nullptr; // Clean up
+}
+
+/**
+ * @brief Test Task yieldOnce() method for single callback switch
+ *
+ * TESTS: yieldOnce(newCallback)
+ *
+ * PURPOSE: Verify that yieldOnce() switches to a new callback for exactly
+ * one execution, then automatically disables the task, enabling one-time
+ * completion or finalization logic.
+ *
+ * METHOD BEHAVIOR:
+ * - yieldOnce(callback): Switches to new callback for one execution only
+ * - New callback executes exactly once on next scheduler pass
+ * - Task automatically disables after the single execution
+ * - Original callback is not restored (task becomes inactive)
+ * - Useful for completion/cleanup logic and one-shot operations
+ *
+ * TEST SCENARIO:
+ * 1. Create task with 5 iterations and initial callback
+ * 2. In first execution, call yieldOnce() to switch to completion callback
+ * 3. Verify first execution produces "step_1" output
+ * 4. Verify second execution produces "step_2" output
+ * 5. Verify task automatically disables after yieldOnce execution
+ *
+ * EXPECTATIONS:
+ * - First execution: "step_1" from original callback with yieldOnce call
+ * - Second execution: "step_2" from yielded callback
+ * - After second execution: task becomes disabled automatically
+ * - No further executions occur
+ *
+ * IMPORTANCE: YieldOnce enables one-time finalization, cleanup, and
+ * completion logic, essential for graceful task termination and
+ * resource cleanup patterns.
+ */
+TEST_F(SchedulerThoroughTest, TaskYieldOnce) {
+    Scheduler ts;
+
+    static Task* yield_once_task = nullptr;
+
+    auto yield_once_callback = []() {
+        test_output.push_back("step_1");
+        if (yield_once_task) {
+            yield_once_task->yieldOnce(&multi_step_callback_2);
+        }
+    };
+
+    Task task(100, 5, yield_once_callback, &ts, true);
+    yield_once_task = &task;
+
+    bool success = runSchedulerUntil(ts, []() { return getTestOutputCount() >= 1; });
+    EXPECT_TRUE(success);
+
+    // Should execute step 2 once then disable
+    success = runSchedulerUntil(ts, []() { return getTestOutputCount() >= 2; });
+    EXPECT_TRUE(success);
+    EXPECT_EQ(getTestOutput(1), "step_2");
+    EXPECT_FALSE(task.isEnabled()); // Should be disabled after yieldOnce
+
+    yield_once_task = nullptr; // Clean up
+}
+
+// ================== TASK ONENABLE/ONDISABLE TESTS ==================
+
+/**
+ * @brief Test Task OnEnable/OnDisable lifecycle callback behavior
+ *
+ * TESTS: onEnable callback, onDisable callback, lifecycle triggers
+ *
+ * PURPOSE: Verify that lifecycle callbacks are properly invoked during
+ * task state transitions, enabling initialization and cleanup logic
+ * to execute at appropriate times.
+ *
+ * LIFECYCLE CALLBACK BEHAVIOR:
+ * - onEnable(): Called when task transitions from disabled to enabled
+ * - onDisable(): Called when task transitions from enabled to disabled
+ * - Callbacks execute synchronously during state change
+ * - Enable callback can prevent enabling by returning false
+ * - Disable callback is informational (no return value)
+ *
+ * TEST SCENARIO:
+ * 1. Create task with lifecycle callbacks but start disabled
+ * 2. Enable task and verify onEnable callback is invoked
+ * 3. Disable task and verify onDisable callback is invoked
+ * 4. Verify callbacks are triggered exactly once per transition
+ *
+ * EXPECTATIONS:
+ * - OnEnable called during enable() transition
+ * - OnDisable called during disable() transition
+ * - Global callback flags properly set
+ * - Task state changes successful
+ *
+ * IMPORTANCE: Lifecycle callbacks enable proper resource management,
+ * initialization, and cleanup, essential for robust task lifecycle
+ * management and preventing resource leaks.
+ */
+TEST_F(SchedulerThoroughTest, TaskOnEnableOnDisable) {
+    Scheduler ts;
+    Task task(100, 2, &basic_callback, &ts, false, &test_onEnable, &test_onDisable);
+
+    // Test OnEnable
+    task.enable();
+    EXPECT_TRUE(onEnable_called);
+    EXPECT_TRUE(task.isEnabled());
+
+    // Reset and test OnDisable
+    onEnable_called = false;
+    task.disable();
+    EXPECT_TRUE(onDisable_called);
+    EXPECT_FALSE(task.isEnabled());
+}
+
+/**
+ * @brief Test Task OnEnable callback returning false to prevent enabling
+ *
+ * TESTS: onEnable callback return value, conditional enabling
+ *
+ * PURPOSE: Verify that when an onEnable callback returns false, the task
+ * remains disabled, providing a mechanism for conditional enabling based
+ * on runtime conditions or resource availability.
+ *
+ * CONDITIONAL ENABLING BEHAVIOR:
+ * - onEnable(): Must return boolean (true = allow enable, false = prevent)
+ * - When returns false: task remains disabled despite enable() call
+ * - When returns true: task becomes enabled normally
+ * - Callback is always invoked (for logging/monitoring purposes)
+ * - Enables conditional logic for resource-dependent tasks
+ *
+ * TEST SCENARIO:
+ * 1. Create task with onEnable callback that returns false
+ * 2. Call enable() on the task
+ * 3. Verify onEnable callback was invoked
+ * 4. Verify task remains disabled (enable() call rejected)
+ *
+ * EXPECTATIONS:
+ * - OnEnable callback is called (onEnable_called flag set)
+ * - Task remains disabled (isEnabled() returns false)
+ * - Enable attempt is gracefully rejected
+ *
+ * IMPORTANCE: Conditional enabling prevents tasks from starting when
+ * prerequisites aren't met, essential for resource-dependent operations
+ * and safety-critical system states.
+ */
+TEST_F(SchedulerThoroughTest, TaskOnEnableReturnsFalse) {
+    Scheduler ts;
+    Task task(100, 1, &basic_callback, &ts, false, &test_onEnable_false, &test_onDisable);
+
+    // OnEnable returns false, task should remain disabled
+    task.enable();
+    EXPECT_TRUE(onEnable_called);
+    EXPECT_FALSE(task.isEnabled()); // Should remain disabled
+}
+
+// ================== SCHEDULER CONSTRUCTOR AND INIT TESTS ==================
+
+/**
+ * @brief Test Scheduler constructor and basic operation
+ *
+ * TESTS: Scheduler(), execute() with no tasks
+ *
+ * PURPOSE: Verify that a Scheduler object can be constructed successfully
+ * and can safely execute even when no tasks are registered, demonstrating
+ * robustness in edge cases.
+ *
+ * CONSTRUCTOR BEHAVIOR:
+ * - Scheduler(): Creates empty scheduler with no tasks
+ * - execute(): Safely handles empty task list
+ * - No exceptions or crashes in degenerate cases
+ * - Ready to accept tasks via Task constructor registration
+ *
+ * TEST SCENARIO:
+ * 1. Create empty scheduler
+ * 2. Call execute() on empty scheduler
+ * 3. Verify no output generated (no tasks to execute)
+ * 4. Verify no crashes or exceptions
+ *
+ * EXPECTATIONS:
+ * - Constructor succeeds without exceptions
+ * - Execute runs safely with no tasks
+ * - No test output produced (counter remains 0)
+ * - Scheduler ready for task registration
+ *
+ * IMPORTANCE: Empty scheduler robustness ensures safe operation during
+ * initialization phases and prevents crashes in edge cases, essential
+ * for reliable system startup sequences.
+ */
+TEST_F(SchedulerThoroughTest, SchedulerConstructor) {
+    Scheduler ts;
+
+    // Should be able to execute without tasks
+    ts.execute();
+    EXPECT_EQ(getTestOutputCount(), 0);
+}
+
+/**
+ * @brief Test Scheduler init() method for reinitialization
+ *
+ * TESTS: init()
+ *
+ * PURPOSE: Verify that init() properly reinitializes the scheduler
+ * state while preserving task registrations, enabling scheduler
+ * reset without losing configured tasks.
+ *
+ * INIT METHOD BEHAVIOR:
+ * - init(): Reinitializes internal scheduler state
+ * - Preserves registered tasks and their configurations
+ * - Resets timing and execution state
+ * - Tasks remain functional after reinitialization
+ * - Useful for system restart scenarios
+ *
+ * TEST SCENARIO:
+ * 1. Create scheduler with one registered task
+ * 2. Call init() to reinitialize scheduler
+ * 3. Verify task still executes properly after init
+ * 4. Confirm scheduler functionality is preserved
+ *
+ * EXPECTATIONS:
+ * - Init() completes without errors
+ * - Task remains registered and functional
+ * - Task executes successfully after reinitialization
+ * - Callback counter increments as expected
+ *
+ * IMPORTANCE: Scheduler reinitialization enables system restart
+ * scenarios and state recovery while preserving task configurations,
+ * essential for robust and recoverable applications.
+ */
+TEST_F(SchedulerThoroughTest, SchedulerInit) {
+    Scheduler ts;
+    Task task(100, 1, &basic_callback, &ts, true);
+
+    ts.init(); // Should reinitialize
+
+    // Task should still work after init
+    bool success = runSchedulerUntil(ts, []() { return callback_counter >= 1; });
+    EXPECT_TRUE(success);
+}
+
+// ================== SCHEDULER TASK MANAGEMENT TESTS ==================
+
+/**
+ * @brief Test Scheduler addTask() and deleteTask() methods for manual task management
+ *
+ * TESTS: addTask(task), deleteTask(task)
+ *
+ * PURPOSE: Verify that tasks can be manually added to and removed from
+ * schedulers, enabling dynamic task management and scheduler composition
+ * patterns beyond automatic constructor registration.
+ *
+ * TASK MANAGEMENT BEHAVIOR:
+ * - addTask(): Manually registers task with scheduler
+ * - deleteTask(): Removes task from scheduler's management
+ * - Tasks can be added without using scheduler parameter in constructor
+ * - Deleted tasks are no longer executed by scheduler
+ * - Remaining tasks continue normal operation
+ *
+ * TEST SCENARIO:
+ * 1. Create tasks without scheduler assignment (nullptr)
+ * 2. Manually add both tasks to scheduler
+ * 3. Enable and execute both tasks
+ * 4. Delete one task from scheduler
+ * 5. Verify only remaining task executes
+ *
+ * EXPECTATIONS:
+ * - Both tasks execute when added to scheduler
+ * - After deletion, only non-deleted task executes
+ * - Deleted task becomes unmanaged (won't execute)
+ * - Scheduler continues operating with remaining tasks
+ *
+ * IMPORTANCE: Manual task management enables dynamic scheduler composition,
+ * conditional task registration, and runtime task lifecycle management,
+ * essential for flexible and adaptive applications.
+ */
+TEST_F(SchedulerThoroughTest, SchedulerAddDeleteTask) {
+    Scheduler ts;
+    Task task1(100, 1, &callback_1, nullptr, false);
+    Task task2(150, 1, &callback_2, nullptr, false);
+
+    // Add tasks manually
+    ts.addTask(task1);
+    ts.addTask(task2);
+
+    task1.enable();
+    task2.enable();
+
+    bool success = runSchedulerUntil(ts, []() { return getTestOutputCount() >= 2; });
+    EXPECT_TRUE(success);
+
+    // Delete task1
+    ts.deleteTask(task1);
+
+    // Only task2 should be manageable now
+    clearTestOutput();
+    task2.restart();
+    success = runSchedulerUntil(ts, []() { return getTestOutputCount() >= 1; });
+    EXPECT_TRUE(success);
+    EXPECT_EQ(getTestOutput(0), "callback_2");
+}
+
+// ================== SCHEDULER EXECUTION CONTROL TESTS ==================
+
+/**
+ * @brief Test Scheduler execute() method return value for idle detection
+ *
+ * TESTS: execute() return value, idle state detection
+ *
+ * PURPOSE: Verify that execute() correctly returns idle status, enabling
+ * applications to detect when no tasks are ready for execution and
+ * implement power management or alternative processing.
+ *
+ * EXECUTE RETURN VALUE BEHAVIOR:
+ * - execute(): Returns false when tasks executed, true when idle
+ * - Idle = no tasks ready for execution at current time
+ * - Non-idle = one or more tasks executed during call
+ * - Enables power management and conditional processing
+ * - Critical for battery-powered and real-time applications
+ *
+ * TEST SCENARIO:
+ * 1. Create two tasks with different intervals (100ms, 150ms)
+ * 2. First execute() should be non-idle (immediate execution)
+ * 3. Run until both tasks complete
+ * 4. Later execute() should be idle (no tasks ready)
+ *
+ * EXPECTATIONS:
+ * - First execute(): returns false (tasks executed)
+ * - Both tasks produce expected output
+ * - After completion: execute() returns true (idle)
+ *
+ * IMPORTANCE: Idle detection enables efficient resource utilization,
+ * power management, and responsive application behavior, essential
+ * for embedded and battery-powered systems.
+ */
+TEST_F(SchedulerThoroughTest, SchedulerExecute) {
+    Scheduler ts;
+    Task task1(100, 1, &callback_1, &ts, true);
+    Task task2(150, 1, &callback_2, &ts, true);
+
+    bool idle = ts.execute();
+    // First execute should run tasks immediately, so not idle
+    EXPECT_FALSE(idle);
+
+    bool success = runSchedulerUntil(ts, []() { return getTestOutputCount() >= 2; });
+    EXPECT_TRUE(success);
+
+    // After tasks complete, should be idle
+    delay(200);
+    idle = ts.execute();
+    EXPECT_TRUE(idle);
+}
+
+/**
+ * @brief Test Scheduler enableAll() and disableAll() methods for bulk control
+ *
+ * TESTS: enableAll(), disableAll()
+ *
+ * PURPOSE: Verify that enableAll() and disableAll() methods correctly
+ * change the state of all tasks managed by the scheduler, enabling
+ * coordinated system-wide task control.
+ *
+ * BULK CONTROL BEHAVIOR:
+ * - enableAll(): Enables every task registered with scheduler
+ * - disableAll(): Disables every task registered with scheduler
+ * - Affects all tasks regardless of current state
+ * - Triggers onEnable/onDisable callbacks for each task
+ * - Enables system-wide start/stop functionality
+ *
+ * TEST SCENARIO:
+ * 1. Create three tasks in disabled state
+ * 2. Call enableAll() and verify all tasks become enabled
+ * 3. Call disableAll() and verify all tasks become disabled
+ * 4. Confirm state changes affect all registered tasks
+ *
+ * EXPECTATIONS:
+ * - EnableAll(): all tasks report isEnabled() = true
+ * - DisableAll(): all tasks report isEnabled() = false
+ * - State changes are consistent across all tasks
+ * - Bulk operations affect entire task set
+ *
+ * IMPORTANCE: Bulk enable/disable enables system-wide control patterns,
+ * emergency stops, coordinated startup/shutdown, and mode switching,
+ * essential for complex multi-task systems.
+ */
+TEST_F(SchedulerThoroughTest, SchedulerEnableDisableAll) {
+    Scheduler ts;
+    Task task1(100, 1, &callback_1, &ts, false);
+    Task task2(150, 1, &callback_2, &ts, false);
+    Task task3(200, 1, &callback_3, &ts, false);
+
+    // Enable all
+    ts.enableAll();
+    EXPECT_TRUE(task1.isEnabled());
+    EXPECT_TRUE(task2.isEnabled());
+    EXPECT_TRUE(task3.isEnabled());
+
+    // Disable all
+    ts.disableAll();
+    EXPECT_FALSE(task1.isEnabled());
+    EXPECT_FALSE(task2.isEnabled());
+    EXPECT_FALSE(task3.isEnabled());
+}
+
+// ================== SCHEDULER TIME QUERY TESTS ==================
+
+/**
+ * @brief Test Scheduler timeUntilNextIteration() method for timing queries
+ *
+ * TESTS: timeUntilNextIteration(task)
+ *
+ * PURPOSE: Verify that timeUntilNextIteration() accurately reports the
+ * remaining time before a task's next scheduled execution, enabling
+ * predictive scheduling and timing-based application logic.
+ *
+ * TIME QUERY BEHAVIOR:
+ * - timeUntilNextIteration(): Returns milliseconds until next execution
+ * - Returns -1 for disabled tasks (not scheduled)
+ * - Returns positive value for enabled tasks with pending execution
+ * - Value decreases as time passes toward execution
+ * - Enables predictive timing and coordination
+ *
+ * TEST SCENARIO:
+ * 1. Check disabled task (should return -1)
+ * 2. Enable task with 500ms delay
+ * 3. Verify time remaining is close to 500ms
+ * 4. Wait 200ms and verify time decreased appropriately
+ *
+ * EXPECTATIONS:
+ * - Disabled task: returns -1
+ * - Initially delayed task: returns ~500ms
+ * - After 200ms delay: returns ~300ms
+ * - Timing accuracy within reasonable bounds
+ *
+ * IMPORTANCE: Time queries enable predictive scheduling, coordination
+ * between tasks, and timing-based application logic, essential for
+ * real-time and synchronized operations.
+ */
+TEST_F(SchedulerThoroughTest, SchedulerTimeUntilNextIteration) {
+    Scheduler ts;
+    Task task(1000, 1, &basic_callback, &ts, false);
+
+    // Disabled task should return -1
+    long time_until = ts.timeUntilNextIteration(task);
+    EXPECT_EQ(time_until, -1);
+
+    // Enabled task with delay
+    task.enableDelayed(500);
+    time_until = ts.timeUntilNextIteration(task);
+    EXPECT_GT(time_until, 400); // Should be close to 500ms
+    EXPECT_LE(time_until, 500);
+
+    // After some time passes
+    delay(200);
+    time_until = ts.timeUntilNextIteration(task);
+    EXPECT_GT(time_until, 200); // Should be around 300ms
+    EXPECT_LE(time_until, 300);
+}
+
+// ================== SCHEDULER TASK ACCESS TESTS ==================
+
+/**
+ * @brief Test Scheduler getCurrentTask() method for callback context identification
+ *
+ * TESTS: getCurrentTask()
+ *
+ * PURPOSE: Verify that getCurrentTask() correctly returns a pointer to the
+ * currently executing task when called from within a task callback,
+ * enabling self-referential task operations and context awareness.
+ *
+ * CONTEXT ACCESS BEHAVIOR:
+ * - getCurrentTask(): Returns pointer to currently executing task
+ * - Only valid when called from within task callback
+ * - Returns nullptr when called outside task execution context
+ * - Enables task self-modification and context-aware operations
+ * - Critical for advanced task patterns and introspection
+ *
+ * TEST SCENARIO:
+ * 1. Create task with callback that calls getCurrentTask()
+ * 2. Execute task and capture the returned task pointer
+ * 3. Verify returned pointer matches the actual task object
+ * 4. Confirm context identification works correctly
+ *
+ * EXPECTATIONS:
+ * - getCurrentTask() returns valid pointer during execution
+ * - Returned pointer equals address of actual task object
+ * - Context identification is accurate and reliable
+ *
+ * IMPORTANCE: Current task access enables advanced patterns like
+ * task self-modification, recursive operations, and context-aware
+ * callback behavior, essential for sophisticated task orchestration.
+ */
+TEST_F(SchedulerThoroughTest, SchedulerCurrentTask) {
+    Scheduler ts;
+    Task* current_task_ptr = nullptr;
+    Task* task_address = nullptr;
+
+    // Create callback that captures getCurrentTask()
+    auto current_task_callback = [&ts, &current_task_ptr]() {
+        current_task_ptr = ts.getCurrentTask();
+        test_output.push_back("got_current_task");
+    };
+
+    Task task(100, 1, current_task_callback, &ts, true);
+    task_address = &task;
+
+    bool success = runSchedulerUntil(ts, []() { return getTestOutputCount() >= 1; });
+    EXPECT_TRUE(success);
+    EXPECT_EQ(current_task_ptr, task_address);
+}
+
+// ================== SCHEDULER TIMING CONTROL TESTS ==================
+
+/**
+ * @brief Test Scheduler startNow() method for immediate execution trigger
+ *
+ * TESTS: startNow()
+ *
+ * PURPOSE: Verify that startNow() forces all enabled tasks to execute
+ * immediately on the next scheduler pass, regardless of their current
+ * timing state, enabling synchronized restart and emergency execution.
+ *
+ * START NOW BEHAVIOR:
+ * - startNow(): Forces immediate execution of all enabled tasks
+ * - Bypasses all interval and delay timing
+ * - Affects all tasks managed by scheduler
+ * - Useful for synchronized restart and emergency execution
+ * - Tasks resume normal timing after startNow execution
+ *
+ * TEST SCENARIO:
+ * 1. Create tasks with long intervals that would normally delay execution
+ * 2. Let them execute once, then restart with delays
+ * 3. Call startNow() to bypass delays
+ * 4. Verify all tasks execute immediately despite delays
+ *
+ * EXPECTATIONS:
+ * - Initial execution: tasks run due to enable()
+ * - After restart+delay: tasks would normally wait
+ * - After startNow(): all tasks execute immediately
+ * - All expected outputs are produced
+ *
+ * IMPORTANCE: StartNow enables synchronized system restart, emergency
+ * execution, and coordinated task triggering, essential for real-time
+ * systems and emergency response scenarios.
+ */
+TEST_F(SchedulerThoroughTest, SchedulerStartNow) {
+    Scheduler ts;
+    Task task1(1000, 1, &callback_1, &ts, true); // Long interval
+    Task task2(2000, 1, &callback_2, &ts, true); // Even longer interval
+
+    // Tasks should execute immediately due to enable(), let them
+    bool success = runSchedulerUntil(ts, []() { return getTestOutputCount() >= 2; });
+    EXPECT_TRUE(success);
+
+    clearTestOutput();
+
+    // Restart tasks with long intervals
+    task1.restart();
+    task2.restart();
+    task1.delay(1000); // Delay them
+    task2.delay(2000);
+
+    // startNow should make them execute immediately
+    ts.startNow();
+    success = runSchedulerUntil(ts, []() { return getTestOutputCount() >= 2; });
+    EXPECT_TRUE(success);
+}
+
+// ================== INTEGRATION TESTS ==================
+
+/**
+ * @brief Integration test for complete task lifecycle with all features
+ *
+ * TESTS: Full task lifecycle including enable, execute, auto-disable, restart
+ *
+ * PURPOSE: Verify that all task features work together correctly in a
+ * realistic usage scenario, testing the integration of multiple methods
+ * and lifecycle events in sequence.
+ *
+ * LIFECYCLE INTEGRATION TESTED:
+ * - Initial state verification (disabled, zero counters)
+ * - Enable with onEnable callback triggering
+ * - Multiple executions with proper counter tracking
+ * - Auto-disable after completing all iterations
+ * - OnDisable callback triggering after completion
+ * - Restart functionality with state reset
+ *
+ * TEST SCENARIO:
+ * 1. Create task with 3 iterations and lifecycle callbacks
+ * 2. Verify initial disabled state
+ * 3. Enable and verify onEnable callback
+ * 4. Execute all 3 iterations and verify counters
+ * 5. Verify auto-disable and onDisable callback
+ * 6. Restart and verify reset state and re-enable
+ *
+ * EXPECTATIONS:
+ * - All lifecycle callbacks triggered at correct times
+ * - Execution and iteration counters track correctly
+ * - Auto-disable occurs after completing iterations
+ * - Restart properly resets state and re-enables
+ *
+ * IMPORTANCE: Integration testing validates that all features work
+ * together as designed, ensuring reliable operation in real applications
+ * with complex task lifecycle requirements.
+ */
+TEST_F(SchedulerThoroughTest, ComplexTaskLifecycle) {
+    Scheduler ts;
+    Task task(200, 3, &basic_callback, &ts, false, &test_onEnable, &test_onDisable);
+
+    // Full lifecycle test
+    EXPECT_FALSE(task.isEnabled());
+    EXPECT_EQ(task.getRunCounter(), 0);
+
+    // Enable and run
+    task.enable();
+    EXPECT_TRUE(onEnable_called);
+    EXPECT_TRUE(task.isEnabled());
+
+    // Run all iterations
+    bool success = runSchedulerUntil(ts, []() { return callback_counter >= 3; });
+    EXPECT_TRUE(success);
+    EXPECT_EQ(callback_counter, 3);
+    EXPECT_EQ(task.getRunCounter(), 3);
+    EXPECT_FALSE(task.isEnabled()); // Auto-disabled after iterations
+    EXPECT_TRUE(onDisable_called);
+
+    // Restart and verify
+    onEnable_called = false;
+    onDisable_called = false;
+    task.restart();
+    EXPECT_TRUE(onEnable_called);
+    EXPECT_TRUE(task.isEnabled());
+    EXPECT_EQ(task.getIterations(), 3); // Reset
+}
+
+/**
+ * @brief Integration test for multiple concurrent tasks with different timing
+ *
+ * TESTS: Multiple tasks with different enable timing and execution patterns
+ *
+ * PURPOSE: Verify that the scheduler correctly manages multiple concurrent
+ * tasks with different timing characteristics, ensuring proper execution
+ * order and no interference between tasks.
+ *
+ * MULTI-TASK INTEGRATION TESTED:
+ * - Three tasks with different intervals (100ms, 150ms, 200ms)
+ * - Different enable timing: immediate, 50ms delay, 100ms delay
+ * - Each task executes 2 iterations (6 total executions)
+ * - Proper execution ordering based on timing
+ * - No task interference or missed executions
+ *
+ * TEST SCENARIO:
+ * 1. Create three tasks with different intervals and 2 iterations each
+ * 2. Enable task1 immediately, task2 after 50ms, task3 after 100ms
+ * 3. Run until all 6 executions complete (2 per task)
+ * 4. Verify first execution follows enable timing order
+ * 5. Confirm all tasks complete their iterations
+ *
+ * EXPECTATIONS:
+ * - All 6 executions complete successfully
+ * - First execution is from task1 (immediate enable)
+ * - Total execution count reaches 6
+ * - No tasks interfere with each other
+ *
+ * IMPORTANCE: Multi-task integration validates scheduler's core
+ * functionality under realistic concurrent workloads, ensuring
+ * reliable operation in complex applications.
+ */
+TEST_F(SchedulerThoroughTest, MultipleTasksInteraction) {
+    Scheduler ts;
+    Task task1(100, 2, &callback_1, &ts, false);
+    Task task2(150, 2, &callback_2, &ts, false);
+    Task task3(200, 2, &callback_3, &ts, false);
+
+    // Enable with different timings
+    task1.enable();
+    task2.enableDelayed(50);
+    task3.enableDelayed(100);
+
+    // All should execute their iterations
+    bool success = runSchedulerUntil(ts, []() { return getTestOutputCount() >= 6; });
+    EXPECT_TRUE(success);
+
+    // Verify execution order (first executions should follow timing)
+    EXPECT_EQ(getTestOutput(0), "callback_1"); // Immediate
+    // Subsequent order may vary due to intervals
+}
+
+// ================== EDGE CASES AND ERROR HANDLING ==================
+
+/**
+ * @brief Edge case test for task with zero iterations
+ *
+ * TESTS: Task behavior with 0 iterations
+ *
+ * PURPOSE: Verify that tasks created with zero iterations behave correctly
+ * by not executing and remaining disabled, ensuring safe handling of
+ * degenerate iteration counts.
+ *
+ * ZERO ITERATIONS BEHAVIOR:
+ * - Task with 0 iterations should never execute
+ * - Task should be automatically disabled (no valid executions)
+ * - Scheduler should safely handle such tasks without errors
+ * - Useful for conditional task creation patterns
+ *
+ * TEST SCENARIO:
+ * 1. Create task with 0 iterations but enabled=true
+ * 2. Run scheduler multiple times
+ * 3. Verify no executions occur
+ * 4. Verify task becomes/remains disabled
+ *
+ * EXPECTATIONS:
+ * - Callback counter remains 0 (no executions)
+ * - Task is disabled (invalid iteration count)
+ * - No errors or crashes occur
+ *
+ * IMPORTANCE: Zero iteration handling prevents invalid execution
+ * states and enables conditional task creation patterns, essential
+ * for robust edge case handling.
+ */
+TEST_F(SchedulerThoroughTest, TaskZeroIterations) {
+    Scheduler ts;
+    Task task(100, 0, &basic_callback, &ts, true);
+
+    // Should not execute with 0 iterations
+    delay(200);
+    ts.execute();
+    EXPECT_EQ(callback_counter, 0);
+    EXPECT_FALSE(task.isEnabled()); // Should be disabled
+}
+
+/**
+ * @brief Edge case test for task with infinite iterations (TASK_FOREVER)
+ *
+ * TESTS: Task behavior with TASK_FOREVER iterations
+ *
+ * PURPOSE: Verify that tasks configured with TASK_FOREVER execute
+ * indefinitely without auto-disabling, maintaining consistent behavior
+ * for infinite execution scenarios.
+ *
+ * INFINITE ITERATIONS BEHAVIOR:
+ * - TASK_FOREVER (-1) indicates infinite iterations
+ * - Task never auto-disables due to iteration count
+ * - getIterations() continues returning TASK_FOREVER
+ * - Executions continue until manually disabled
+ * - Essential for background and monitoring tasks
+ *
+ * TEST SCENARIO:
+ * 1. Create task with TASK_FOREVER iterations
+ * 2. Run scheduler until multiple executions occur
+ * 3. Verify task remains enabled throughout
+ * 4. Verify getIterations() still returns TASK_FOREVER
+ *
+ * EXPECTATIONS:
+ * - Task executes at least 5 times within timeout
+ * - Task remains enabled after multiple executions
+ * - getIterations() continues returning TASK_FOREVER
+ * - No auto-disable occurs
+ *
+ * IMPORTANCE: Infinite iteration support enables background tasks,
+ * monitoring loops, and continuous processing, essential for
+ * long-running and service-oriented applications.
+ */
+TEST_F(SchedulerThoroughTest, TaskInfiniteIterations) {
+    Scheduler ts;
+    Task task(50, TASK_FOREVER, &basic_callback, &ts, true);
+
+    // Should keep running indefinitely
+    bool success = runSchedulerUntil(ts, []() { return callback_counter >= 5; }, 400);
+    EXPECT_TRUE(success);
+    EXPECT_TRUE(task.isEnabled()); // Should still be enabled
+    EXPECT_EQ(task.getIterations(), TASK_FOREVER); // Should remain -1
+}
+
+/**
+ * @brief Edge case test for task with null callback pointer
+ *
+ * TESTS: Task behavior with nullptr callback
+ *
+ * PURPOSE: Verify that tasks created with null callback pointers handle
+ * execution gracefully without crashing, demonstrating robustness in
+ * edge cases and enabling placeholder task patterns.
+ *
+ * NULL CALLBACK BEHAVIOR:
+ * - Task with nullptr callback should not crash during execution
+ * - Task lifecycle continues normally (timing, iterations, etc.)
+ * - No callback code executes (safe no-op behavior)
+ * - Enables placeholder and template task patterns
+ * - Demonstrates scheduler robustness
+ *
+ * TEST SCENARIO:
+ * 1. Create task with nullptr callback but valid parameters
+ * 2. Run scheduler and let task execute
+ * 3. Verify no crashes or exceptions occur
+ * 4. Verify no callback-specific effects occur
+ *
+ * EXPECTATIONS:
+ * - No crashes or exceptions during execution
+ * - Callback counter remains 0 (no callback executed)
+ * - Task lifecycle proceeds normally
+ * - Scheduler continues operating safely
+ *
+ * IMPORTANCE: Null callback handling ensures scheduler robustness
+ * and enables placeholder task patterns, essential for template
+ * systems and defensive programming practices.
+ */
+TEST_F(SchedulerThoroughTest, TaskNullCallback) {
+    Scheduler ts;
+    Task task(100, 3, nullptr, &ts, true);
+
+    // Should not crash with null callback
+    delay(200);
+    ts.execute();
+    EXPECT_EQ(callback_counter, 0); // No callback executed
+    // Task should still run through its lifecycle
+}
+
+/**
+ * @brief Main test runner function
+ *
+ * Initializes Google Test framework and runs all registered test cases.
+ * Called by the test execution environment to start the testing process.
+ * Returns 0 for success, non-zero for test failures.
+ *
+ * @param argc Command line argument count
+ * @param argv Command line argument values
+ * @return Test execution status (0 = success)
+ */
+int main(int argc, char **argv) {
+    ::testing::InitGoogleTest(&argc, argv);
+    return RUN_ALL_TESTS();
+}