/** * @file test_scheduler.c * @brief Unit tests for scheduler */ #include "unity.h" #include "kernel.h" #include "scheduler.h" #include "task.h" #include /* Test task handles */ static TaskHandle_t test_tasks[10]; static volatile uint32_t task_execution_count[10]; static volatile uint32_t task_execution_order[100]; static volatile uint32_t execution_index = 0; /* Test task functions */ static void test_task_0(void* params) { (void)params; while (1) { task_execution_count[0]++; task_execution_order[execution_index++] = 0; kernel_delay(10); } } static void test_task_1(void* params) { (void)params; while (1) { task_execution_count[1]++; task_execution_order[execution_index++] = 1; kernel_delay(20); } } static void test_task_2(void* params) { (void)params; while (1) { task_execution_count[2]++; task_execution_order[execution_index++] = 2; kernel_delay(50); } } /* Test Setup */ void setUp(void) { /* Reset test state */ memset((void*)task_execution_count, 0, sizeof(task_execution_count)); execution_index = 0; /* Initialize kernel */ kernel_init(); } /* Test Teardown */ void tearDown(void) { /* Stop kernel */ kernel_stop(); } /* ============================================================================ * Test Cases * ============================================================================ */ /** * @brief Test scheduler initialization */ void test_scheduler_init(void) { SchedulerConfig_t config = { .type = SCHEDULER_PRIORITY_PREEMPTIVE, .time_slice_ticks = 10, .enable_deadline_monitoring = true }; scheduler_init(&config); /* Verify scheduler is initialized */ TEST_ASSERT_NOT_NULL(scheduler_get_current_task()); } /** * @brief Test task creation and scheduling */ void test_task_creation(void) { TaskConfig_t config = { .name = "test_task", .function = test_task_0, .parameters = NULL, .stack_size = 1024, .priority = 1, .period_ticks = 0 }; test_tasks[0] = task_create(&config); TEST_ASSERT_NOT_NULL(test_tasks[0]); TEST_ASSERT_EQUAL(1, task_get_priority(test_tasks[0])); TEST_ASSERT_EQUAL(TASK_READY, task_get_state(test_tasks[0])); } /** * @brief Test priority-based scheduling */ void test_priority_scheduling(void) { /* Create tasks with different priorities */ TaskConfig_t config1 = { .name = "high_priority", .function = test_task_0, .parameters = NULL, .stack_size = 1024, .priority = 0, .period_ticks = 10 }; TaskConfig_t config2 = { .name = "low_priority", .function = test_task_1, .parameters = NULL, .stack_size = 1024, .priority = 5, .period_ticks = 10 }; test_tasks[0] = task_create(&config1); test_tasks[1] = task_create(&config2); /* Start kernel */ kernel_start(); /* Let tasks run for 100ms */ kernel_delay(100); /* High priority task should execute more */ TEST_ASSERT_GREATER_THAN(task_execution_count[1], task_execution_count[0]); } /** * @brief Test round-robin scheduling */ void test_round_robin_scheduling(void) { /* Create two tasks with same priority */ TaskConfig_t config1 = { .name = "task_a", .function = test_task_0, .parameters = NULL, .stack_size = 1024, .priority = 3, .period_ticks = 0 }; TaskConfig_t config2 = { .name = "task_b", .function = test_task_1, .parameters = NULL, .stack_size = 1024, .priority = 3, .period_ticks = 0 }; test_tasks[0] = task_create(&config1); test_tasks[1] = task_create(&config2); kernel_start(); kernel_delay(100); /* Both tasks should execute */ TEST_ASSERT_GREATER_THAN(0, task_execution_count[0]); TEST_ASSERT_GREATER_THAN(0, task_execution_count[1]); } /** * @brief Test scheduler statistics */ void test_scheduler_statistics(void) { SchedulerStatistics_t stats; scheduler_get_statistics(&stats); TEST_ASSERT_GREATER_THAN(0, stats.context_switches); TEST_ASSERT_GREATER_OR_EQUAL(0, stats.preemptions); } /** * @brief Test scheduler lock/unlock */ void test_scheduler_lock_unlock(void) { /* Lock scheduler */ scheduler_lock(); /* Try to yield */ scheduler_yield(); /* Unlock scheduler */ scheduler_unlock(); TEST_ASSERT_TRUE(true); } /* ============================================================================ * Test Runner * ============================================================================ */ int main(void) { UNITY_BEGIN(); RUN_TEST(test_scheduler_init); RUN_TEST(test_task_creation); RUN_TEST(test_priority_scheduling); RUN_TEST(test_round_robin_scheduling); RUN_TEST(test_scheduler_statistics); RUN_TEST(test_scheduler_lock_unlock); return UNITY_END(); }