diff --git a/.gitignore b/.gitignore index 496ee2c..afc9798 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,7 @@ -.DS_Store \ No newline at end of file +.DS_Store +tests/.tmp +.pytest_cache +.vscode +__pycache__ +.vscode +.ruff_cache diff --git a/Exercises/Response-Time Analysis/.vscode/launch.json b/Exercises/Response-Time Analysis/.vscode/launch.json index 6211b38..0f57c54 100644 --- a/Exercises/Response-Time Analysis/.vscode/launch.json +++ b/Exercises/Response-Time Analysis/.vscode/launch.json @@ -5,7 +5,7 @@ "name": "Debug C++", "type": "cppdbg", "request": "launch", - "program": "${workspaceFolder}/build/real_time_analysis", + "program": "${workspaceFolder}/build/response_time_analysis", "args": ["${workspaceFolder}/exercise-TC2.csv"], "stopAtEntry": false, "cwd": "${workspaceFolder}", @@ -22,4 +22,4 @@ "preLaunchTask": "build" } ] -} \ No newline at end of file +} diff --git a/Exercises/Response-Time Analysis/.vscode/tasks.json b/Exercises/Response-Time Analysis/.vscode/tasks.json index 3f864fb..96a19f5 100644 --- a/Exercises/Response-Time Analysis/.vscode/tasks.json +++ b/Exercises/Response-Time Analysis/.vscode/tasks.json @@ -7,9 +7,9 @@ "command": "g++", "args": [ "-g", - "${workspaceFolder}/src/real_time_analysis.cpp", + "${workspaceFolder}/src/response_time_analysis.cpp", "-o", - "${workspaceFolder}/build/real_time_analysis" + "${workspaceFolder}/build/response_time_analysis" ], "group": { "kind": "build", @@ -18,4 +18,4 @@ "problemMatcher": ["$gcc"] } ] -} \ No newline at end of file +} diff --git a/Exercises/Response-Time Analysis/build/real_time_analysis b/Exercises/Response-Time Analysis/build/response_time_analysis old mode 100644 new mode 100755 similarity index 54% rename from Exercises/Response-Time Analysis/build/real_time_analysis rename to Exercises/Response-Time Analysis/build/response_time_analysis index 9013645..c819722 Binary files a/Exercises/Response-Time Analysis/build/real_time_analysis and b/Exercises/Response-Time Analysis/build/response_time_analysis differ diff --git a/Exercises/Response-Time Analysis/src/real_time_analysis.cpp b/Exercises/Response-Time Analysis/src/response_time_analysis.cpp similarity index 75% rename from Exercises/Response-Time Analysis/src/real_time_analysis.cpp rename to Exercises/Response-Time Analysis/src/response_time_analysis.cpp index fbb2d2a..5651015 100644 --- a/Exercises/Response-Time Analysis/src/real_time_analysis.cpp +++ b/Exercises/Response-Time Analysis/src/response_time_analysis.cpp @@ -11,8 +11,8 @@ struct Task { string id; int BCET; int WCET; - int period; - int deadline; + int period; + int deadline; int priority; // Lower number => higher priority for RMS, if you wish }; @@ -36,10 +36,10 @@ void readTasksCSV(const string& filename, vector& tasks) getline(ss, token, ','); // Task ID task.id = token; - getline(ss, token, ','); // WCET - task.WCET = stoi(token); getline(ss, token, ','); // BCET task.BCET = stoi(token); + getline(ss, token, ','); // WCET + task.WCET = stoi(token); getline(ss, token, ','); // Period task.period = stoi(token); getline(ss, token, ','); // Deadline @@ -56,31 +56,28 @@ void RTA_test(vector& tasks) { // Sort tasks by priority (lower number means higher priority) sort(tasks.begin(), tasks.end(), [](const Task& a, const Task& b) { - return a.priority < b.priority; // Ensure lower priority number = higher priority + return a.priority < b.priority; }); - for (size_t task = 0; task < tasks.size(); task++) + for (size_t i = 0; i < tasks.size(); i++) { - int R = tasks[task].WCET; + int R = tasks[i].WCET; int last_R = -1; bool schedulable = true; - int I = 0; // Reset interference for each iteration while (R != last_R) { last_R = R; - - // Compute interference from higher-priority tasks - for (size_t j = 0; j < task; j++) + int I = 0; + for (size_t j = 0; j < i; j++) { I += ceil((double)R / tasks[j].period) * tasks[j].WCET; } + R = tasks[i].WCET + I; - R = I + tasks[task].WCET; - - if (R > tasks[task].deadline) + if (R > tasks[i].deadline) { - cout << "Task " << tasks[task].id << " is not schedulable." << endl; + cout << "Task " << tasks[i].id << " is not schedulable with WCRT." << endl; schedulable = false; break; } @@ -88,11 +85,12 @@ void RTA_test(vector& tasks) if (schedulable) { - cout << "Task " << tasks[task].id << " is schedulable with WCRT = " << R << endl; + cout << "Task " << tasks[i].id << " is schedulable with WCRT = " << R << endl; } } } + int main(int argc, char* argv[]) { if (argc != 2) { @@ -107,4 +105,4 @@ int main(int argc, char* argv[]) RTA_test(tasks); return 0; -} \ No newline at end of file +} diff --git a/Exercises/Very Simple Simulator/.vscode/c_cpp_properties.json b/Exercises/Very Simple Simulator/.vscode/c_cpp_properties.json deleted file mode 100644 index 8f6a31f..0000000 --- a/Exercises/Very Simple Simulator/.vscode/c_cpp_properties.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "configurations": [ - { - "name": "Linux", - "includePath": [ - "${workspaceFolder}/**" - ], - "defines": [], - "compilerPath": "/usr/bin/g++", - "cStandard": "c11", - "cppStandard": "c++17", - "intelliSenseMode": "gcc-x64" - } - ], - "version": 4 -} \ No newline at end of file diff --git a/Exercises/Very Simple Simulator/.vscode/launch.json b/Exercises/Very Simple Simulator/.vscode/launch.json deleted file mode 100644 index 204b3a0..0000000 --- a/Exercises/Very Simple Simulator/.vscode/launch.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "version": "0.2.0", - "configurations": [ - { - "name": "Debug C++", - "type": "cppdbg", - "request": "launch", - "program": "${workspaceFolder}/build/very_simple_simulator", - "args": ["${workspaceFolder}/exercise-TC2.csv"], - "stopAtEntry": false, - "cwd": "${workspaceFolder}", - "environment": [], - "externalConsole": false, - "MIMode": "gdb", - "setupCommands": [ - { - "description": "Enable pretty-printing for gdb", - "text": "-enable-pretty-printing", - "ignoreFailures": true - } - ], - "preLaunchTask": "build" - } - ] -} \ No newline at end of file diff --git a/Exercises/Very Simple Simulator/.vscode/settings.json b/Exercises/Very Simple Simulator/.vscode/settings.json deleted file mode 100644 index 0cba2e6..0000000 --- a/Exercises/Very Simple Simulator/.vscode/settings.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "files.associations": { - "iostream": "cpp" - } -} \ No newline at end of file diff --git a/Exercises/Very Simple Simulator/.vscode/tasks.json b/Exercises/Very Simple Simulator/.vscode/tasks.json deleted file mode 100644 index 11023fd..0000000 --- a/Exercises/Very Simple Simulator/.vscode/tasks.json +++ /dev/null @@ -1,43 +0,0 @@ -{ - "version": "2.0.0", - "tasks": [ - { - "label": "build", - "type": "shell", - "command": "g++", - "args": [ - "-g", - "${workspaceFolder}/src/very_simple_simulator.cpp", - "-o", - "${workspaceFolder}/build/very_simple_simulator" - ], - "group": "build", - "problemMatcher": [ - "$gcc" - ] - }, - { - "type": "cppbuild", - "label": "C/C++: g++ build active file", - "command": "/usr/bin/g++", - "args": [ - "-fdiagnostics-color=always", - "-g", - "${file}", - "-o", - "${fileDirname}/${fileBasenameNoExtension}" - ], - "options": { - "cwd": "${fileDirname}" - }, - "problemMatcher": [ - "$gcc" - ], - "group": { - "kind": "build", - "isDefault": true - }, - "detail": "Task generated by Debugger." - } - ] -} \ No newline at end of file diff --git a/Exercises/Very Simple Simulator/build/very_simple_simulator b/Exercises/Very Simple Simulator/build/very_simple_simulator deleted file mode 100644 index e41076a..0000000 Binary files a/Exercises/Very Simple Simulator/build/very_simple_simulator and /dev/null differ diff --git a/Exercises/Very Simple Simulator/02225_Exercise.pdf b/Exercises/VerySimpleSimulator/02225_Exercise.pdf similarity index 100% rename from Exercises/Very Simple Simulator/02225_Exercise.pdf rename to Exercises/VerySimpleSimulator/02225_Exercise.pdf diff --git a/Exercises/Very Simple Simulator/README.txt b/Exercises/VerySimpleSimulator/README.txt similarity index 99% rename from Exercises/Very Simple Simulator/README.txt rename to Exercises/VerySimpleSimulator/README.txt index f028b24..294350d 100644 --- a/Exercises/Very Simple Simulator/README.txt +++ b/Exercises/VerySimpleSimulator/README.txt @@ -3,7 +3,7 @@ README.txt The files in the Exerercise/Content tab are test cases are provided as a starting point for the 02225 DRTS exercise. They are in CSV (Comma-Separated Values) format and contain the model parameters for periodic tasks: - + - Task: Task name - BCET: Best-case execution time - WCET: Worst-case execution time diff --git a/Exercises/VerySimpleSimulator/build/very_simple_simulator b/Exercises/VerySimpleSimulator/build/very_simple_simulator new file mode 100755 index 0000000..12e9167 Binary files /dev/null and b/Exercises/VerySimpleSimulator/build/very_simple_simulator differ diff --git a/Exercises/Very Simple Simulator/exercise-TC1.csv b/Exercises/VerySimpleSimulator/exercise-TC1.csv similarity index 85% rename from Exercises/Very Simple Simulator/exercise-TC1.csv rename to Exercises/VerySimpleSimulator/exercise-TC1.csv index 89e3ebe..03e6cf2 100644 --- a/Exercises/Very Simple Simulator/exercise-TC1.csv +++ b/Exercises/VerySimpleSimulator/exercise-TC1.csv @@ -5,4 +5,4 @@ T3,1,1,10,10,2 T4,1,2,12,12,3 T5,1,2,15,15,4 T6,1,3,20,20,5 -T7,1,4,30,30,6 \ No newline at end of file +T7,1,4,30,30,6 diff --git a/Exercises/VerySimpleSimulator/exercise-TC1_s.csv b/Exercises/VerySimpleSimulator/exercise-TC1_s.csv new file mode 100644 index 0000000..6183855 --- /dev/null +++ b/Exercises/VerySimpleSimulator/exercise-TC1_s.csv @@ -0,0 +1,8 @@ +Task,WCRT,Deadline,Status +T1,1,6,true +T2,54,60,true +T3,2,10,true +T4,4,12,true +T5,6,15,true +T6,10,20,true +T7,28,30,true diff --git a/Exercises/Very Simple Simulator/exercise-TC2.csv b/Exercises/VerySimpleSimulator/exercise-TC2.csv similarity index 86% rename from Exercises/Very Simple Simulator/exercise-TC2.csv rename to Exercises/VerySimpleSimulator/exercise-TC2.csv index 2427ced..407f27f 100644 --- a/Exercises/Very Simple Simulator/exercise-TC2.csv +++ b/Exercises/VerySimpleSimulator/exercise-TC2.csv @@ -9,4 +9,4 @@ T7,4,6,75,75,7 T8,5,9,100,100,8 T9,3,12,120,120,9 T10,5,11,150,150,10 -T11,6,15,300,300,11 \ No newline at end of file +T11,6,15,300,300,11 diff --git a/Exercises/Very Simple Simulator/exercise-TC3.csv b/Exercises/VerySimpleSimulator/exercise-TC3.csv similarity index 86% rename from Exercises/Very Simple Simulator/exercise-TC3.csv rename to Exercises/VerySimpleSimulator/exercise-TC3.csv index 8cd09de..2330943 100644 --- a/Exercises/Very Simple Simulator/exercise-TC3.csv +++ b/Exercises/VerySimpleSimulator/exercise-TC3.csv @@ -7,4 +7,4 @@ T5,1,22,200,200,5 T6,5,27,300,300,6 T7,8,29,320,320,7 T8,10,34,400,400,8 -T9,22,35,480,480,9 \ No newline at end of file +T9,22,35,480,480,9 diff --git a/Exercises/VerySimpleSimulator/src/jobs.py b/Exercises/VerySimpleSimulator/src/jobs.py new file mode 100644 index 0000000..d984372 --- /dev/null +++ b/Exercises/VerySimpleSimulator/src/jobs.py @@ -0,0 +1,43 @@ +from dataclasses import dataclass +import numpy as np + + +# struct to keep track of the jobs +@dataclass +class Jobs: + task: np.array + release_time: int + remaining_time: int + response_time: int + + +# function to check if every job is done +def check_remaining_jobs(jobs: np.array) -> bool: + """ + Checks if there are any jobs remaining to be executed. + Parameters: + jobs (np.array): The list of jobs to check. + Returns: + bool: True if there are jobs remaining, False otherwise. + """ + for job in jobs: + if job.remaining_time > 0: + return True + return False + + +# function to check if the job is ready to be executed +def get_ready_list(jobs: np.array, current_time: int) -> np.array: + """ + Get the list of jobs that are ready to be executed. + Args: + jobs (np.array): An array of job objects. Each job object is expected to have 'release_time' and 'remaining_time' attributes. + current_time (int): The current time against which the jobs' readiness is evaluated. + Returns: + np.array: An array of job objects that are ready to be executed. A job is considered ready if its release_time is less than or equal to the current_time and its remaining_time is greater than 0. + """ + ready_job: np.array = [] + for job in jobs: + if job.release_time <= current_time and job.remaining_time > 0: + ready_job.append(job) + return ready_job diff --git a/Exercises/VerySimpleSimulator/src/task_handler.py b/Exercises/VerySimpleSimulator/src/task_handler.py new file mode 100644 index 0000000..d4dbbaf --- /dev/null +++ b/Exercises/VerySimpleSimulator/src/task_handler.py @@ -0,0 +1,26 @@ +import pandas as pd +import numpy as np + + +def output_result_csv(ouput_path: str, wcrt_dict: dict, tasks: np.array) -> None: + """ + Writes the worst-case response time dictionary to a CSV file. + Parameters: + output_path (str): The file path to write the CSV file to. + wcrt_dict (dict): The dictionary containing the worst-case response times for each task. + """ + # Create a list to store the results + results = [] + + for job in tasks: + task = job["Task"] + wcrt = wcrt_dict[task] + deadline = job["Deadline"] + status = "true" if wcrt <= deadline else "false" + results.append([task, wcrt, deadline, status]) + + # Create a DataFrame from the results + results_df = pd.DataFrame(results, columns=["Task", "WCRT", "Deadline", "Status"]) + + # Save the DataFrame to a CSV file + results_df.to_csv(ouput_path.removesuffix(".csv") + "_s.csv", index=False) diff --git a/Exercises/Very Simple Simulator/src/very_simple_simulator.cpp b/Exercises/VerySimpleSimulator/src/very_simple_simulator.cpp similarity index 51% rename from Exercises/Very Simple Simulator/src/very_simple_simulator.cpp rename to Exercises/VerySimpleSimulator/src/very_simple_simulator.cpp index 399bd1e..9235b30 100644 --- a/Exercises/Very Simple Simulator/src/very_simple_simulator.cpp +++ b/Exercises/VerySimpleSimulator/src/very_simple_simulator.cpp @@ -11,9 +11,9 @@ struct Task { string id; int BCET; int WCET; - int period; - int deadline; - int priority; // Lower number => higher priority for RMS, if you wish + int period; + int deadline; + int priority; // Lower number => higher priority for RMS }; // Define the Job structure @@ -28,7 +28,7 @@ struct Job { void readTasksCSV(const string& filename, vector& tasks) { ifstream file(filename); - if (!file.is_open()) + if (!file.is_open()) { cerr << "Error: Could not open file " << filename << endl; return; @@ -45,10 +45,10 @@ void readTasksCSV(const string& filename, vector& tasks) getline(ss, token, ','); // Task ID task.id = token; - getline(ss, token, ','); // WCET - task.WCET = stoi(token); getline(ss, token, ','); // BCET task.BCET = stoi(token); + getline(ss, token, ','); // WCET + task.WCET = stoi(token); getline(ss, token, ','); // Period task.period = stoi(token); getline(ss, token, ','); // Deadline @@ -59,27 +59,25 @@ void readTasksCSV(const string& filename, vector& tasks) tasks.push_back(task); } file.close(); -} -// Function to check if all jobs are completed -bool allJobsCompleted(const vector& jobs) -{ - for (const auto& job : jobs) { - if (job.remainingTime > 0) { - return false; - } - } - return true; + sort(tasks.begin(), tasks.end(), [](const Task& a, const Task& b) { + return a.id < b.id; + }); } // Function to find the job with the highest priority Job *highest_priority(vector& readyList) { + if (readyList.empty()) + { + return nullptr; + } + return *min_element( readyList.begin(), readyList.end(), [](Job* a, Job* b) { - return a->task.priority < b->task.priority; + return a->task.priority < b->task.priority; } ); } @@ -96,9 +94,15 @@ vector get_ready(vector& jobs, int currentTime) return readyList; } +int advanceTime() +{ + return 1; +} + int main(int argc, char* argv[]) { - if (argc != 2) { + if (argc != 2) + { cerr << "Usage: " << argv[0] << " " << endl; return 1; } @@ -107,75 +111,81 @@ int main(int argc, char* argv[]) vector tasks; readTasksCSV(filename, tasks); - int n = 1000; + // Simulation time (n cycles) + int n = 1000; int currentTime = 0; + // List of all jobs that are in the system vector jobs; - jobs.reserve(tasks.size()); - for (const auto& t : tasks) { - jobs.push_back({t, 0, t.WCET, 0}); - } + // Initialize next release time for each task (all tasks start at time 0) + vector nextReleaseTimes(tasks.size(), 0); + + // We also maintain worst-case response times (WCRT) for each task. vector worstCaseResponseTimes(tasks.size(), 0); - while (currentTime < n && !allJobsCompleted(jobs)) + // Simulation loop + while (currentTime <= n) { - // Release new jobs at the start of each period - for (const auto& t : tasks) + // For each task, if it is time to release a new job, create it. + for (size_t i = 0; i < tasks.size(); ++i) { - if (currentTime != 0 && currentTime % t.period == 0) { - jobs.push_back({t, currentTime, t.WCET, 0}); + if (currentTime >= nextReleaseTimes[i]) + { + Job newJob { tasks[i], currentTime, tasks[i].WCET, 0 }; + jobs.push_back(newJob); + nextReleaseTimes[i] += tasks[i].period; } } - // Get the list of ready jobs vector readyList = get_ready(jobs, currentTime); - - // If no jobs are ready, increment the current time - if (readyList.empty()) - { - currentTime++; - continue; - } - - // Get the job with the highest priority Job* currentJob = highest_priority(readyList); if (currentJob != nullptr) { - // Execute the job for one time unit - currentJob->remainingTime--; - currentTime++; - - // If the job is completed, update its response time - if (currentJob->remainingTime <= 0) + int delta = advanceTime(); + currentTime += delta; + currentJob->remainingTime -= delta; + + // If the job has completed execution, calculate its response time and update WCRT + if (currentJob->remainingTime <= 0) { currentJob->responseTime = currentTime - currentJob->releaseTime; - int taskIndex = distance( - tasks.begin(), - find_if(tasks.begin(), tasks.end(), [&](const Task& tk){ - return tk.id == currentJob->task.id; - }) - ); - worstCaseResponseTimes[taskIndex] = max( - worstCaseResponseTimes[taskIndex], - currentJob->responseTime - ); + + // Find the corresponding task index + auto it = find_if(tasks.begin(), tasks.end(), [&](const Task& t) { + return t.id == currentJob->task.id; + }); + + if (it != tasks.end()) + { + size_t taskIndex = distance(tasks.begin(), it); + worstCaseResponseTimes[taskIndex] = max( + worstCaseResponseTimes[taskIndex], + currentJob->responseTime + ); + } } } else { - currentJob->remainingTime--; - currentTime++; + // If no job is ready, just advance time + int delta = advanceTime(); + currentTime += delta; } } // Output the worst-case response times for each task - for (size_t i = 0; i < tasks.size(); ++i) + cout << "Task\tWCRT\tDeadline\tStatus" << endl; + cout << "---------------------------------" << endl; + for (size_t i = 0; i < tasks.size(); ++i) { - cout << "Task " << tasks[i].id - << " WCRT: " << worstCaseResponseTimes[i] << endl; + string status = (worstCaseResponseTimes[i] <= tasks[i].deadline) ? "✓" : "✗"; + cout << " " << tasks[i].id << "\t" + << worstCaseResponseTimes[i] << "\t" + << tasks[i].deadline << "\t\t" + << status << endl; } return 0; -} \ No newline at end of file +} diff --git a/Exercises/VerySimpleSimulator/src/very_simple_simulator.py b/Exercises/VerySimpleSimulator/src/very_simple_simulator.py new file mode 100644 index 0000000..4fcef44 --- /dev/null +++ b/Exercises/VerySimpleSimulator/src/very_simple_simulator.py @@ -0,0 +1,64 @@ +import pandas as pd +import numpy as np +from Exercises.VerySimpleSimulator.src.jobs import ( + Jobs, + check_remaining_jobs, + get_ready_list, +) +from Exercises.VerySimpleSimulator.src.task_handler import output_result_csv + + +def run_cycle(input_path: str) -> None: + # Print the contents of the CSV file + # Task BCET(best case execution time) WCET(worst case execution time) Period Deadline Priority + tasks = pd.read_csv(input_path) + tasks_dict = tasks.to_dict(orient="records") + + # init number of cycles and current time + num_cycles: int = 1000 + current_time: int = 0 + + # init the tasks + jobs_queue: np.array = [] + for task in tasks_dict: + jobs_queue.append(Jobs(task, 0, task["WCET"], 0)) + + # init the worst case dictionary example[T0, 0; T1,0; ...] + # wcrt_dict = {tasks.values[i][0]: 0 for i in range(len(tasks))} + wcrt_dict = {task: 0.0 for task in tasks["Task"]} + + while current_time <= num_cycles and check_remaining_jobs(jobs_queue): + # release job at the start of the period + for task in tasks_dict: + if current_time % task["Period"] == 0 and current_time != 0: + jobs_queue.append(Jobs(task, current_time, task["WCET"], 0)) + + ready_job = get_ready_list(jobs_queue, current_time) + highest_priority_job = None + if ready_job: + highest_priority_job = min(ready_job, key=lambda job: job.task["Priority"]) + + if highest_priority_job: + # advance by 1 + current_time += 1 + # compute the task + highest_priority_job.remaining_time -= 1 + # check if the task is done + if highest_priority_job.remaining_time <= 0: + highest_priority_job.response_time = ( + current_time - highest_priority_job.release_time + ) + wcrt_dict[highest_priority_job.task["Task"]] = max( + wcrt_dict[highest_priority_job.task["Task"]], + highest_priority_job.response_time, + ) + for i, job in enumerate(jobs_queue): + if job.task["Priority"] == highest_priority_job.task["Priority"]: + jobs_queue.pop(i) + break + else: + current_time += 1 + + # Convert wcrt_dict values to float + wcrt_dict = {k: float(v) for k, v in wcrt_dict.items()} + output_result_csv(input_path, wcrt_dict, tasks_dict) diff --git a/tests/res/files/ex1.csv b/tests/res/files/ex1.csv new file mode 100644 index 0000000..a9aed26 --- /dev/null +++ b/tests/res/files/ex1.csv @@ -0,0 +1,8 @@ +Task,BCET,WCET,Period,Deadline,Priority +T1,0,1,6,6,1 +T2,3,4,60,60,7 +T3,1,1,10,10,2 +T4,1,2,12,12,3 +T5,1,2,15,15,4 +T6,1,3,20,20,5 +T7,1,4,30,30,6 diff --git a/tests/res/files/ex1_s.csv b/tests/res/files/ex1_s.csv new file mode 100644 index 0000000..82d76d8 --- /dev/null +++ b/tests/res/files/ex1_s.csv @@ -0,0 +1,8 @@ +Task,WCRT,Deadline,Status +T1,1.0,6,true +T2,54.0,60,true +T3,2.0,10,true +T4,4.0,12,true +T5,6.0,15,true +T6,10.0,20,true +T7,28.0,30,true diff --git a/tests/res/files/ex2.csv b/tests/res/files/ex2.csv new file mode 100644 index 0000000..be4deef --- /dev/null +++ b/tests/res/files/ex2.csv @@ -0,0 +1,12 @@ +Task,BCET,WCET,Period,Deadline,Priority +T1,0,1,15,15,1 +T2,1,2,20,20,2 +T3,2,3,25,25,3 +T4,2,4,30,30,4 +T5,3,5,50,50,5 +T6,3,5,60,60,6 +T7,4,6,75,75,7 +T8,5,9,100,100,8 +T9,3,12,120,120,9 +T10,5,11,150,150,10 +T11,6,15,300,300,11 diff --git a/tests/res/files/ex2_s.csv b/tests/res/files/ex2_s.csv new file mode 100644 index 0000000..27cee2c --- /dev/null +++ b/tests/res/files/ex2_s.csv @@ -0,0 +1,12 @@ +Task,WCRT,Deadline,Status +T1,1.0,15,true +T2,3.0,20,true +T3,6.0,25,true +T4,10.0,30,true +T5,15.0,50,true +T6,23.0,60,true +T7,37.0,75,true +T8,49.0,100,true +T9,98.0,120,true +T10,197.0,150,false +T11,580.0,300,false diff --git a/tests/res/files/ex3.csv b/tests/res/files/ex3.csv new file mode 100644 index 0000000..7bfe7f1 --- /dev/null +++ b/tests/res/files/ex3.csv @@ -0,0 +1,10 @@ +Task,BCET,WCET,Period,Deadline,Priority +T1,1,3,40,40,1 +T2,2,7,80,80,2 +T3,1,13,100,100,3 +T4,3,18,160,160,4 +T5,1,22,200,200,5 +T6,5,27,300,300,6 +T7,8,29,320,320,7 +T8,10,34,400,400,8 +T9,22,35,480,480,9 diff --git a/tests/res/files/ex3_s.csv b/tests/res/files/ex3_s.csv new file mode 100644 index 0000000..bd4875b --- /dev/null +++ b/tests/res/files/ex3_s.csv @@ -0,0 +1,10 @@ +Task,WCRT,Deadline,Status +T1,3.0,40,true +T2,10.0,80,true +T3,23.0,100,true +T4,44.0,160,true +T5,66.0,200,true +T6,116.0,300,true +T7,148.0,320,true +T8,258.0,400,true +T9,296.0,480,true diff --git a/tests/res/inputs/ex1.csv b/tests/res/inputs/ex1.csv new file mode 100644 index 0000000..a9aed26 --- /dev/null +++ b/tests/res/inputs/ex1.csv @@ -0,0 +1,8 @@ +Task,BCET,WCET,Period,Deadline,Priority +T1,0,1,6,6,1 +T2,3,4,60,60,7 +T3,1,1,10,10,2 +T4,1,2,12,12,3 +T5,1,2,15,15,4 +T6,1,3,20,20,5 +T7,1,4,30,30,6 diff --git a/tests/res/inputs/ex2.csv b/tests/res/inputs/ex2.csv new file mode 100644 index 0000000..e69de29 diff --git a/tests/res/inputs/ex3.csv b/tests/res/inputs/ex3.csv new file mode 100644 index 0000000..e69de29 diff --git a/tests/res/solutions/ex1_s.csv b/tests/res/solutions/ex1_s.csv new file mode 100644 index 0000000..82d76d8 --- /dev/null +++ b/tests/res/solutions/ex1_s.csv @@ -0,0 +1,8 @@ +Task,WCRT,Deadline,Status +T1,1.0,6,true +T2,54.0,60,true +T3,2.0,10,true +T4,4.0,12,true +T5,6.0,15,true +T6,10.0,20,true +T7,28.0,30,true diff --git a/tests/res/solutions/ex2_s.csv b/tests/res/solutions/ex2_s.csv new file mode 100644 index 0000000..27cee2c --- /dev/null +++ b/tests/res/solutions/ex2_s.csv @@ -0,0 +1,12 @@ +Task,WCRT,Deadline,Status +T1,1.0,15,true +T2,3.0,20,true +T3,6.0,25,true +T4,10.0,30,true +T5,15.0,50,true +T6,23.0,60,true +T7,37.0,75,true +T8,49.0,100,true +T9,98.0,120,true +T10,197.0,150,false +T11,580.0,300,false diff --git a/tests/res/solutions/ex3_s.csv b/tests/res/solutions/ex3_s.csv new file mode 100644 index 0000000..bd4875b --- /dev/null +++ b/tests/res/solutions/ex3_s.csv @@ -0,0 +1,10 @@ +Task,WCRT,Deadline,Status +T1,3.0,40,true +T2,10.0,80,true +T3,23.0,100,true +T4,44.0,160,true +T5,66.0,200,true +T6,116.0,300,true +T7,148.0,320,true +T8,258.0,400,true +T9,296.0,480,true diff --git a/tests/test_exercises.py b/tests/test_exercises.py new file mode 100644 index 0000000..c9fe4a3 --- /dev/null +++ b/tests/test_exercises.py @@ -0,0 +1,67 @@ +import os +import pandas as pd +from Exercises.VerySimpleSimulator.src.very_simple_simulator import run_cycle + + +def test_exercise_1(): + run_test("ex1") + + +def test_exercise_2(): + run_test("ex2") + + +def test_exercise_3(): + run_test("ex3") + + +def run_test(filename: str): + solution_file = os.path.join(get_res_path(), "solutions", f"{filename}_s.csv") + + input_file = os.path.join(get_res_path(), "files", f"{filename}.csv") + output_file = os.path.join(get_res_path(), "files", f"{filename}_s.csv") + + run_cycle(input_file) + + output_df = pd.read_csv(output_file) + solution_df = pd.read_csv(solution_file) + + print(f"Output dataframe shape: {output_df.shape}") + print(f"Solution dataframe shape: {solution_df.shape}") + if not output_df.shape == solution_df.shape: + print("Error: dataframe shape are different") + assert False + + print("Output dataframe:") + print(output_df) + print("==============================") + + print("Solution dataframe:") + print(solution_df) + print("==============================") + assert output_df.equals(solution_df) + + +def get_root(): + """ + Get the project root + """ + return os.path.dirname(os.path.dirname(__file__)) + + +def get_res_path(): + """ + Get the absoulte path of the tests/res folder + """ + return os.path.join(get_root(), "tests", "res") + + +def get_tmp_path(): + """ + Get the absoulte path of the tests/.tmp folder. + If it doesn't exist it creates it + """ + tmp_path = os.path.join(get_root(), "tests", ".tmp") + if not os.path.exists(tmp_path): + os.makedirs(tmp_path) + return tmp_path diff --git a/tests/test_main.py b/tests/test_main.py deleted file mode 100644 index 52c2135..0000000 --- a/tests/test_main.py +++ /dev/null @@ -1,2 +0,0 @@ -def test_main(): - assert True \ No newline at end of file