#ifndef SCHEDULER_ROUND_ROBIN_TEST_H #define SCHEDULER_ROUND_ROBIN_TEST_H #include #include "scheduler.h" void stud_RR_start(struct run_queue *rq, int pid); void stud_RR_elect(struct run_queue *rq); void stud_RR_terminate(struct run_queue *rq); void stud_RR_clock_tick(struct run_queue *rq); void stud_RR_wait(struct run_queue *rq); void stud_RR_wake_up(struct run_queue *rq, int pid); void stud_RR(struct run_queue* rq, enum events event, int pid); // Mock implementation of the grader's verifier bool rq_eq(struct run_queue *sol, struct run_queue *stu) { if (sol->n_tasks != stu->n_tasks) return false; if (sol->n_tasks == 0) return true; struct task *c1 = sol->head; struct task *c2 = stu->head; int pos = 0; do { if (c1->pid != c2->pid || c1->state != c2->state) { fprintf(stderr, "Task (%d, %s) error at position %d\n", c2->pid, c2->state == RUNNING ? "running" : "other", pos); return false; } c1 = c1->next; c2 = c2->next; pos++; } while (c1 != sol->head && c2 != stu->head); return true; } // Crash line 73 in your log void test_RR_start() { struct run_queue stu = {NULL, 0, 0}; struct run_queue sol = {NULL, 0, 0}; // Mock expected state // Manually build expected solution queue to compare against stud_rq_enqueue(&sol, stud_task_create(1, RUNNING)); stud_rq_enqueue(&sol, stud_task_create(2, READY)); stud_rq_enqueue(&sol, stud_task_create(3, READY)); printf("add task 1\n"); stud_RR_start(&stu, 1); printf("add task 2\n"); stud_RR_start(&stu, 2); printf("add task 3\n"); stud_RR_start(&stu, 3); printf("add task 1 again\n"); stud_RR_start(&stu, 1); print_rq(&stu); // Line 73 assert(rq_eq(&sol, &stu)); } // Helper to prepopulate a specific queue state for testing the crash logs void prepopulate_queue(struct run_queue *rq) { stud_rq_enqueue(rq, stud_task_create(1, RUNNING)); stud_rq_enqueue(rq, stud_task_create(2, TERMINATED)); stud_rq_enqueue(rq, stud_task_create(3, READY)); stud_rq_enqueue(rq, stud_task_create(4, TERMINATED)); stud_rq_enqueue(rq, stud_task_create(8, READY)); stud_rq_enqueue(rq, stud_task_create(14, BLOCKED)); } // Crash line 109 in your log void test_RR_elect_running() { struct run_queue rq = {NULL, 0, 0}; prepopulate_queue(&rq); print_rq(&rq); printf("electing new task...\n"); // Line 109 stud_RR_elect(&rq); } // Crash line 127 in your log void test_RR_elect_blocked() { struct run_queue rq = {NULL, 0, 0}; prepopulate_queue(&rq); rq.head->state = BLOCKED; // Change 1 to blocked print_rq(&rq); printf("electing new task...\n"); // Line 127 stud_RR_elect(&rq); } // Crash line 148 in your log void test_RR_terminate() { struct run_queue rq = {NULL, 0, 0}; prepopulate_queue(&rq); print_rq(&rq); printf("task terminating...\n"); // Line 148 stud_RR_terminate(&rq); } // Crash line 169 in your log void test_RR_wait() { struct run_queue rq = {NULL, 0, 0}; prepopulate_queue(&rq); print_rq(&rq); printf("task is waiting...\n"); // Line 169 stud_RR_wait(&rq); } // Crash line 190 in your log void test_RR_wake_up() { struct run_queue rq = {NULL, 0, 0}; prepopulate_queue(&rq); print_rq(&rq); printf("task 14 waking up...\n"); // Line 190 stud_RR_wake_up(&rq, 14); } // Crash line 216 in your log void test_RR_clock_tick() { struct run_queue stu = {NULL, 0, 0}; prepopulate_queue(&stu); print_rq(&stu); for(int i=0; i<10; i++) { printf("running clock tick...\n"); stud_RR_clock_tick(&stu); } print_rq(&stu); struct run_queue sol = {NULL, 0, 0}; // Expected solution queue state omitted for brevity // Line 216 // assert(rq_eq(&sol, &stu)); } // Crash line 263 in your log void test_RR_scripted_1() { struct run_queue stu = {NULL, 0, 0}; prepopulate_queue(&stu); print_rq(&stu); for(int i=0; i<5; i++) { printf("running clock tick...\n"); stud_RR_clock_tick(&stu); } print_rq(&stu); printf("task is waiting...\n"); // Line 263 stud_RR(&stu, wait, 0); } #endif // SCHEDULER_ROUND_ROBIN_TEST_H