Преглед на файлове

Enhance unit tests for TaskScheduler library

Anatoli Arkhipenko преди 4 месеца
родител
ревизия
bcfe4c0124
променени са 1 файла, в които са добавени 184 реда и са изтрити 5 реда
  1. 184 5
      tests/test-scheduler.cpp

+ 184 - 5
tests/test-scheduler.cpp

@@ -1,27 +1,57 @@
-// test_scheduler.cpp
+// test_scheduler.cpp - Unit tests for TaskScheduler library
+// This file contains comprehensive tests for the TaskScheduler cooperative multitasking library
+// Tests cover basic scheduler operations, task lifecycle, timing accuracy, and edge cases
+
 #include <gtest/gtest.h>
 #include "Arduino.h"
 #include "TaskScheduler.h"
 
-// Define the global test output vector
+// Global test state - used to capture and verify callback executions
 std::vector<std::string> test_output;
 
-// Test callback functions
+/**
+ * @brief Simple callback function for Task 1 testing
+ * 
+ * Records execution in the global test_output vector for verification.
+ * Used primarily for single-task execution tests and timing verification.
+ * Outputs execution timestamp for debugging timing-related issues.
+ */
 void task1_callback() {
     test_output.push_back("Task1 executed");
     std::cout << "Task1 executed at " << millis() << "ms" << std::endl;
 }
 
+/**
+ * @brief Simple callback function for Task 2 testing
+ * 
+ * Records execution with Task2 identifier to distinguish from other tasks
+ * in multi-task scheduling tests. Essential for verifying proper task
+ * isolation and execution ordering in concurrent scenarios.
+ */
 void task2_callback() {
     test_output.push_back("Task2 executed");
     std::cout << "Task2 executed at " << millis() << "ms" << std::endl;
 }
 
+/**
+ * @brief Simple callback function for Task 3 testing
+ * 
+ * Third task callback used in execution order tests and multi-task scenarios.
+ * Helps verify that the scheduler can handle multiple concurrent tasks
+ * and execute them in the correct chronological order.
+ */
 void task3_callback() {
     test_output.push_back("Task3 executed");
     std::cout << "Task3 executed at " << millis() << "ms" << std::endl;
 }
 
+/**
+ * @brief Callback for testing repeating task functionality
+ * 
+ * Uses static counter to track execution number, enabling verification
+ * of proper iteration counting and repeated execution behavior.
+ * Critical for testing tasks with limited iteration counts and infinite tasks.
+ */
 void repeating_callback() {
     static int counter = 0;
     counter++;
@@ -29,19 +59,51 @@ void repeating_callback() {
     std::cout << "Repeating task #" << counter << " executed at " << millis() << "ms" << std::endl;
 }
 
+/**
+ * @brief Test fixture class for TaskScheduler unit tests
+ * 
+ * Provides common setup and teardown functionality for all scheduler tests.
+ * Ensures clean test state between test runs and provides utility methods
+ * for common test operations like running scheduler with timeout conditions.
+ */
 class SchedulerTest : public ::testing::Test {
 protected:
+    /**
+     * @brief Set up test environment before each test
+     * 
+     * Clears any previous test output and initializes timing system.
+     * Called automatically by Google Test framework before each test method.
+     * Ensures each test starts with a clean, predictable state.
+     */
     void SetUp() override {
         clearTestOutput();
         // Reset time by creating new static start point
         millis(); // Initialize timing
     }
     
+    /**
+     * @brief Clean up test environment after each test
+     * 
+     * Clears test output to prevent interference between tests.
+     * Called automatically by Google Test framework after each test method.
+     * Ensures no test artifacts affect subsequent tests.
+     */
     void TearDown() override {
         clearTestOutput();
     }
     
-    // Helper to run scheduler until condition is met or timeout
+    /**
+     * @brief Helper method to run scheduler until condition is met or timeout
+     * 
+     * Executes the scheduler repeatedly until either the specified condition
+     * returns true or the timeout period expires. Essential for testing
+     * time-dependent scheduler behavior without creating infinite loops.
+     * 
+     * @param ts Reference to the Scheduler object to execute
+     * @param condition Lambda function that returns true when test condition is met
+     * @param timeout_ms Maximum time to wait before giving up (default: 1000ms)
+     * @return true if condition was met within timeout, false otherwise
+     */
     bool runSchedulerUntil(Scheduler& ts, std::function<bool()> condition, unsigned long timeout_ms = 1000) {
         return waitForCondition([&]() {
             ts.execute();
@@ -50,11 +112,25 @@ protected:
     }
 };
 
+/**
+ * @brief Test basic scheduler object creation
+ * 
+ * Verifies that a Scheduler object can be instantiated without throwing
+ * exceptions or causing crashes. This is the most fundamental test that
+ * ensures the library can be used at all.
+ */
 TEST_F(SchedulerTest, BasicSchedulerCreation) {
     Scheduler ts;
     EXPECT_TRUE(true); // Scheduler creation should not throw
 }
 
+/**
+ * @brief Test scheduler behavior in initial empty state
+ * 
+ * Verifies that calling execute() on an empty scheduler (no tasks added)
+ * behaves safely and doesn't produce any unexpected output or crashes.
+ * Important for validating scheduler robustness in edge cases.
+ */
 TEST_F(SchedulerTest, SchedulerInitialState) {
     Scheduler ts;
     
@@ -63,6 +139,15 @@ TEST_F(SchedulerTest, SchedulerInitialState) {
     EXPECT_EQ(getTestOutputCount(), 0);
 }
 
+/**
+ * @brief Test execution of a single task
+ * 
+ * Creates one task scheduled to run once after 100ms and verifies:
+ * 1. Task executes within reasonable timeout period
+ * 2. Task executes exactly once
+ * 3. Callback produces expected output
+ * This test validates core task scheduling functionality.
+ */
 TEST_F(SchedulerTest, SingleTaskExecution) {
     Scheduler ts;
     
@@ -77,6 +162,16 @@ TEST_F(SchedulerTest, SingleTaskExecution) {
     EXPECT_EQ(getTestOutput(0), "Task1 executed");
 }
 
+/**
+ * @brief Test concurrent execution of multiple tasks
+ * 
+ * Creates three tasks with different execution delays (50ms, 100ms, 150ms)
+ * and verifies:
+ * 1. All tasks execute within timeout
+ * 2. Tasks execute in chronological order (not creation order)
+ * 3. Each task produces correct output
+ * Critical for validating multi-task scheduling and execution ordering.
+ */
 TEST_F(SchedulerTest, MultipleTaskExecution) {
     Scheduler ts;
     
@@ -95,6 +190,16 @@ TEST_F(SchedulerTest, MultipleTaskExecution) {
     EXPECT_EQ(getTestOutput(2), "Task3 executed");
 }
 
+/**
+ * @brief Test task with limited number of iterations
+ * 
+ * Creates a task configured to run exactly 3 times with 80ms intervals
+ * and verifies:
+ * 1. Task executes the correct number of times
+ * 2. Executions are properly numbered/sequenced
+ * 3. Task stops after reaching iteration limit
+ * Validates the iteration counting mechanism.
+ */
 TEST_F(SchedulerTest, RepeatingTaskExecution) {
     Scheduler ts;
     
@@ -111,6 +216,16 @@ TEST_F(SchedulerTest, RepeatingTaskExecution) {
     EXPECT_EQ(getTestOutput(2), "Repeating task #3");
 }
 
+/**
+ * @brief Test task configured for infinite execution
+ * 
+ * Creates a task with TASK_FOREVER iterations and runs scheduler for
+ * a fixed time period (250ms) to verify:
+ * 1. Task continues executing indefinitely
+ * 2. Execution frequency matches expected interval (50ms)
+ * 3. Task doesn't stop after arbitrary number of executions
+ * Tests the infinite iteration functionality.
+ */
 TEST_F(SchedulerTest, InfiniteRepeatingTask) {
     Scheduler ts;
     
@@ -129,6 +244,16 @@ TEST_F(SchedulerTest, InfiniteRepeatingTask) {
     EXPECT_LE(getTestOutputCount(), 7);
 }
 
+/**
+ * @brief Test task enable/disable functionality
+ * 
+ * Creates a task in disabled state, verifies it doesn't execute,
+ * then enables it and verifies execution occurs. Tests:
+ * 1. Disabled tasks don't execute even if scheduler runs
+ * 2. Enabling a task allows it to execute on next scheduler pass
+ * 3. Task state changes are properly handled
+ * Critical for dynamic task management.
+ */
 TEST_F(SchedulerTest, TaskEnableDisable) {
     Scheduler ts;
     
@@ -151,6 +276,16 @@ TEST_F(SchedulerTest, TaskEnableDisable) {
     EXPECT_EQ(getTestOutput(0), "Task1 executed");
 }
 
+/**
+ * @brief Test disabling a task while it's actively running
+ * 
+ * Creates an infinite repeating task, lets it execute several times,
+ * then disables it and verifies no further executions occur. Tests:
+ * 1. Running tasks can be disabled mid-execution
+ * 2. Disabled tasks immediately stop executing
+ * 3. Task state changes take effect on next scheduler pass
+ * Important for dynamic task control scenarios.
+ */
 TEST_F(SchedulerTest, TaskDisableDuringExecution) {
     Scheduler ts;
     
@@ -177,6 +312,16 @@ TEST_F(SchedulerTest, TaskDisableDuringExecution) {
     EXPECT_EQ(getTestOutputCount(), executions_before_disable);
 }
 
+/**
+ * @brief Test scheduler behavior with no registered tasks
+ * 
+ * Runs scheduler execute() method multiple times when no tasks are
+ * registered and verifies:
+ * 1. No crashes or exceptions occur
+ * 2. No unexpected output is generated
+ * 3. Scheduler handles empty task list gracefully
+ * Edge case test for scheduler robustness.
+ */
 TEST_F(SchedulerTest, SchedulerWithNoTasks) {
     Scheduler ts;
     
@@ -189,6 +334,17 @@ TEST_F(SchedulerTest, SchedulerWithNoTasks) {
     EXPECT_EQ(getTestOutputCount(), 0);
 }
 
+/**
+ * @brief Test correct execution order of tasks with different schedules
+ * 
+ * Creates three tasks with deliberately mixed creation order vs execution order:
+ * - task_late: 200ms delay (should execute last)
+ * - task_early: 50ms delay (should execute first)  
+ * - task_mid: 100ms delay (should execute second)
+ * 
+ * Verifies scheduler executes tasks in chronological order, not creation order.
+ * Critical for validating proper task scheduling algorithm implementation.
+ */
 TEST_F(SchedulerTest, TaskExecutionOrder) {
     Scheduler ts;
     
@@ -209,6 +365,18 @@ TEST_F(SchedulerTest, TaskExecutionOrder) {
     EXPECT_EQ(getTestOutput(2), "Task3 executed");  // Third (200ms)
 }
 
+/**
+ * @brief Test scheduler performance with large number of concurrent tasks
+ * 
+ * Creates 10 tasks with slightly staggered execution times (100ms + i*10ms)
+ * and verifies:
+ * 1. All tasks execute successfully within timeout
+ * 2. No performance degradation causes task loss
+ * 3. Scheduler can handle realistic task loads
+ * 
+ * Stress test for scheduler scalability and performance under load.
+ * Uses smart pointers to manage task memory automatically.
+ */
 TEST_F(SchedulerTest, SchedulerHandlesLargeNumberOfTasks) {
     Scheduler ts;
     std::vector<std::unique_ptr<Task>> tasks;
@@ -226,7 +394,18 @@ TEST_F(SchedulerTest, SchedulerHandlesLargeNumberOfTasks) {
     EXPECT_EQ(getTestOutputCount(), 10);
 }
 
+/**
+ * @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();
-}
+}