94 lines
3 KiB
C
94 lines
3 KiB
C
|
|
#ifndef DOUBLY_LINKED_LIST_TEST_H
|
||
|
|
#define DOUBLY_LINKED_LIST_TEST_H
|
||
|
|
|
||
|
|
#include <assert.h>
|
||
|
|
#include "scheduler.h"
|
||
|
|
|
||
|
|
// External declarations of your implemented functions
|
||
|
|
bool stud_rq_empty(struct run_queue const *rq);
|
||
|
|
struct task *stud_task_create(int pid, enum states state);
|
||
|
|
void stud_task_free(struct task *task);
|
||
|
|
void stud_rq_destroy(struct run_queue *rq);
|
||
|
|
struct task *stud_rq_find(struct run_queue *rq, int pid);
|
||
|
|
struct task *stud_rq_head(struct run_queue *rq);
|
||
|
|
struct task *stud_rq_tail(struct run_queue *rq);
|
||
|
|
bool stud_rq_enqueue(struct run_queue *rq, struct task *task);
|
||
|
|
bool stud_rq_prepend(struct run_queue *rq, struct task *task);
|
||
|
|
size_t stud_rq_length(struct run_queue *rq);
|
||
|
|
|
||
|
|
// Helper to print queue exactly like the VPL server
|
||
|
|
static void print_rq(struct run_queue *rq) {
|
||
|
|
if (stud_rq_empty(rq)) {
|
||
|
|
printf("END\n");
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
struct task *curr = rq->head;
|
||
|
|
do {
|
||
|
|
const char *state_str = (curr->state == READY) ? "ready" :
|
||
|
|
(curr->state == RUNNING) ? "running" :
|
||
|
|
(curr->state == BLOCKED) ? "blocked" : "terminated";
|
||
|
|
printf("{ id = %d, state = %s, runtime = %d } -- ", curr->pid, state_str, curr->runtime);
|
||
|
|
curr = curr->next;
|
||
|
|
} while (curr != rq->head);
|
||
|
|
printf("END\n");
|
||
|
|
}
|
||
|
|
|
||
|
|
void test_rq_empty() { /* omitted for brevity, passing */ }
|
||
|
|
void test_rq_head() { /* omitted for brevity, passing */ }
|
||
|
|
void test_rq_length() { /* omitted for brevity, passing */ }
|
||
|
|
|
||
|
|
// Crash line 128 in your log
|
||
|
|
void test_rq_destroy() {
|
||
|
|
struct run_queue rq = {NULL, 0, 0};
|
||
|
|
stud_rq_enqueue(&rq, stud_task_create(1, READY));
|
||
|
|
stud_rq_enqueue(&rq, stud_task_create(2, READY));
|
||
|
|
|
||
|
|
// Line 128
|
||
|
|
stud_rq_destroy(&rq);
|
||
|
|
assert(stud_rq_empty(&rq));
|
||
|
|
}
|
||
|
|
|
||
|
|
// Crash line 143 in your log
|
||
|
|
void test_rq_find() {
|
||
|
|
struct run_queue rq = {NULL, 0, 0};
|
||
|
|
|
||
|
|
// Line 143: This causes your code to segfault because rq is empty
|
||
|
|
// and stud_rq_find attempts to dereference NULL.
|
||
|
|
struct task *t = stud_rq_find(&rq, 99);
|
||
|
|
assert(t == NULL);
|
||
|
|
}
|
||
|
|
|
||
|
|
// Crash line 186 in your log
|
||
|
|
void test_rq_tail() {
|
||
|
|
struct run_queue rq = {NULL, 0, 0};
|
||
|
|
stud_rq_enqueue(&rq, stud_task_create(1, READY));
|
||
|
|
stud_rq_enqueue(&rq, stud_task_create(2, READY));
|
||
|
|
struct task *tail = stud_rq_tail(&rq);
|
||
|
|
|
||
|
|
// Line 186
|
||
|
|
assert(tail && tail->pid == 2);
|
||
|
|
}
|
||
|
|
|
||
|
|
void test_rq_enqueue() {
|
||
|
|
struct run_queue rq = {NULL, 0, 0};
|
||
|
|
printf("add tasks 1-4\n");
|
||
|
|
stud_rq_enqueue(&rq, stud_task_create(1, READY));
|
||
|
|
stud_rq_enqueue(&rq, stud_task_create(2, READY));
|
||
|
|
stud_rq_enqueue(&rq, stud_task_create(3, READY));
|
||
|
|
stud_rq_enqueue(&rq, stud_task_create(4, READY));
|
||
|
|
print_rq(&rq);
|
||
|
|
stud_rq_destroy(&rq); // This triggers your double free!
|
||
|
|
}
|
||
|
|
|
||
|
|
// Crash line 201 in your log
|
||
|
|
void test_rq_prepend() {
|
||
|
|
struct run_queue rq = {NULL, 0, 0};
|
||
|
|
printf("add tasks 1-4\n");
|
||
|
|
stud_rq_enqueue(&rq, stud_task_create(2, READY));
|
||
|
|
|
||
|
|
// Line 201: Prepending causes your segfault here.
|
||
|
|
stud_rq_prepend(&rq, stud_task_create(1, READY));
|
||
|
|
}
|
||
|
|
|
||
|
|
#endif // DOUBLY_LINKED_LIST_TEST_H
|