From 23cba02d544e7e79e2eaf78f2f960aee4a88dadf Mon Sep 17 00:00:00 2001 From: Charlie Kushelevsky Date: Tue, 16 Jul 2024 11:28:58 -0700 Subject: [PATCH] !fix: working on python proccessor --- CMakeLists.txt | 1 + src/ensembles.cpp | 8 +- tests/file_google_tests.cpp | 17 +- tests/fixed_google_tests.cpp | 216 ---------------- tests/inputs/example.txt | 6 +- tests/overlap_google_tests.cpp | 420 ++++++++++++++++++++++++++++++++ tests/scheduler_proccessor.py | 62 ++--- tests/scheduler_test_flog.cpp | 174 +++++++++++++ tests/scheduler_test_system.cpp | 90 +++++++ tests/scheduler_test_system.hpp | 93 ++++++- 10 files changed, 813 insertions(+), 274 deletions(-) create mode 100644 tests/overlap_google_tests.cpp create mode 100644 tests/scheduler_test_flog.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 3d51dc00..36e61f11 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -19,6 +19,7 @@ set(GTEST_SOURCE_FILES src/scheduler.cpp tests/fixed_google_tests.cpp tests/file_google_tests.cpp + tests/overlap_google_tests.cpp ) diff --git a/src/ensembles.cpp b/src/ensembles.cpp index 2ab95a5e..9dc49fb5 100644 --- a/src/ensembles.cpp +++ b/src/ensembles.cpp @@ -1,12 +1,6 @@ /** * @file ensembles.cpp - * @author your name (you@domain.com) - * @brief - * @version 1 - * @date 2024-06-10 - * - * @copyright Copyright (c) 2024 - * + * @brief Contains efinitions of ensembles */ #include "ensembles.hpp" #ifndef TEST_VERSION diff --git a/tests/file_google_tests.cpp b/tests/file_google_tests.cpp index d0b99718..a0584bdc 100644 --- a/tests/file_google_tests.cpp +++ b/tests/file_google_tests.cpp @@ -173,7 +173,7 @@ class SchedulerTestsFromFiles : public ::testing::TestWithParam { if(!strcmp(nextEvent->taskName, input.delays[i].taskName.c_str()) && - (nextEvent->state.measurementCount == + (nextEvent->state.measurementCount - 1 == input.delays[i].iteration)) { if (input.delays[i].isBefore) @@ -328,21 +328,10 @@ class SchedulerTestsFromFiles : public ::testing::TestWithParam } - /** - * @brief Run task and update time with delay and check values - * - * This function checks the correct task is being run, and the start time - * and end time is correct. The delay is added after the task is run. - * - * - * @param expectedTaskName expected task name character - * @param expectedStart time to check start time with - * @param expectedEnd time to check end time with - * @param additionalTime the amount of delay to add - */ + /** - * @brief Run task and update time and check values + * @brief Run task, update time, and check values * * This function checks the correct task is being run, and the start time * and end time is correct diff --git a/tests/fixed_google_tests.cpp b/tests/fixed_google_tests.cpp index add08ff8..9ff9a95b 100644 --- a/tests/fixed_google_tests.cpp +++ b/tests/fixed_google_tests.cpp @@ -814,219 +814,3 @@ TEST_F(SchedulerFixedTests, LargeIntervalsSmallDurations) } -/** - * @brief Testing no overlap with A before B - * - * A *********** - * B ********** - */ -TEST_F(SchedulerFixedTests, NoOverlapBefore) -{ - schedule2(); - - deploymentSchedule[0].state.deploymentStartTime = 0; - deploymentSchedule[0].ensembleDelay = 0; - deploymentSchedule[0].maxDuration = 300; - deploymentSchedule[0].ensembleInterval = 1000; - - deploymentSchedule[1].state.deploymentStartTime = 0; - deploymentSchedule[1].ensembleDelay = 500; - deploymentSchedule[1].maxDuration = 200; - deploymentSchedule[1].ensembleInterval = 1000; - - int i = 1; - uint32_t start = deploymentSchedule[i].state.deploymentStartTime + - deploymentSchedule[i].ensembleDelay; - uint32_t end = start + deploymentSchedule[i].maxDuration; - bool overlap = SCH_willOverlap(deploymentSchedule.data(), i, 0, start); - ASSERT_FALSE(overlap); -} - - - -/** - * @brief Testing overlap with end of A and start of B - * - * A *********** - * B *********** - */ -TEST_F(SchedulerFixedTests, OverlapBefore) -{ - schedule2(); - - deploymentSchedule[0].state.deploymentStartTime = 0; - deploymentSchedule[0].state.nextRunTime = 250; - deploymentSchedule[0].maxDuration = 300; - deploymentSchedule[0].ensembleInterval = 1000; - - - deploymentSchedule[1].state.deploymentStartTime = 0; - deploymentSchedule[1].state.nextRunTime = 500; - deploymentSchedule[1].maxDuration = 200; - deploymentSchedule[1].ensembleInterval = 1000; - - - int i = 1; - uint32_t start = deploymentSchedule[i].state.nextRunTime; - uint32_t end = start + deploymentSchedule[i].maxDuration; - bool overlap = SCH_willOverlap(deploymentSchedule.data(), i, 0, start); - ASSERT_TRUE(overlap); -} - - -/* -A *********** -B ********** -*/ -/** - * @brief Testing no overlap with A after B - * - */ -TEST_F(SchedulerFixedTests, NoOverlapAfter) -{ - schedule2(); - - deploymentSchedule[0].state.deploymentStartTime = 0; - deploymentSchedule[0].ensembleDelay = 800; - deploymentSchedule[0].maxDuration = 300; - deploymentSchedule[0].ensembleInterval = 1000; - - deploymentSchedule[1].state.deploymentStartTime = 0; - deploymentSchedule[1].ensembleDelay = 500; - deploymentSchedule[1].maxDuration = 200; - deploymentSchedule[1].ensembleInterval = 1000; - - int i = 1; - uint32_t start = deploymentSchedule[i].state.deploymentStartTime + - deploymentSchedule[i].ensembleDelay; - uint32_t end = start + deploymentSchedule[i].maxDuration; - bool overlap = SCH_willOverlap(deploymentSchedule.data(), i, 0, start); - ASSERT_FALSE(overlap); -} - -/** - * @brief Testing overlap with end of B and start of A - * - * A *********** - * B ********** - */ -TEST_F(SchedulerFixedTests, OverlapAfter) -{ - schedule2(); - - deploymentSchedule[0].state.deploymentStartTime = 0; - deploymentSchedule[0].state.nextRunTime = 650; - deploymentSchedule[0].maxDuration = 300; - deploymentSchedule[0].ensembleInterval = 1000; - - - deploymentSchedule[1].state.deploymentStartTime = 0; - deploymentSchedule[1].state.nextRunTime = 500; - deploymentSchedule[1].maxDuration = 200; - deploymentSchedule[1].ensembleInterval = 1000; - - - int i = 1; - uint32_t start = deploymentSchedule[i].state.nextRunTime; - uint32_t end = start + deploymentSchedule[i].maxDuration; - bool overlap = SCH_willOverlap(deploymentSchedule.data(), i, 0, start); - ASSERT_TRUE(overlap); -} - - -/** - * @brief Testing for overlap when B starts after A starts and before A ends - * - * A ***************** - * B ********** - * - */ -TEST_F(SchedulerFixedTests, InsideOverlap) -{ - schedule2(); - - deploymentSchedule[0].state.deploymentStartTime = 0; - deploymentSchedule[0].state.nextRunTime = 0; - deploymentSchedule[0].maxDuration = 800; - deploymentSchedule[0].ensembleInterval = 1000; - - - deploymentSchedule[1].state.deploymentStartTime = 0; - deploymentSchedule[1].state.nextRunTime = 500; - deploymentSchedule[1].maxDuration = 200; - deploymentSchedule[1].ensembleInterval = 1000; - - - int i = 1; - uint32_t start = deploymentSchedule[i].state.nextRunTime; - uint32_t end = start + deploymentSchedule[i].maxDuration; - bool overlap = SCH_willOverlap(deploymentSchedule.data(), i, 0, start); - ASSERT_TRUE(overlap); -} - - -/** - * @brief Testing no overlap edge case when B starts as A ends - * - * A ********* - * B ********** - */ -TEST_F(SchedulerFixedTests, Boundary1) -{ - schedule2(); - - deploymentSchedule[0].state.deploymentStartTime = 0; - deploymentSchedule[0].state.nextRunTime = 0; - deploymentSchedule[0].maxDuration = 500; - deploymentSchedule[0].ensembleInterval = 1000; - - deploymentSchedule[1].state.deploymentStartTime = 0; - deploymentSchedule[1].state.nextRunTime = 500; - deploymentSchedule[1].maxDuration = 200; - deploymentSchedule[1].ensembleInterval = 1000; - - - int i = 1; - uint32_t start = deploymentSchedule[i].state.nextRunTime; - uint32_t end = start + deploymentSchedule[i].maxDuration; - bool overlap = SCH_willOverlap(deploymentSchedule.data(), i, 0, start); - ASSERT_FALSE(overlap); -} - - -/** - * @brief Testing no overlap edge case when A starts as B ends - * - * A ********* - * B ********** - */ -TEST_F(SchedulerFixedTests, Boundary2) -{ - schedule2(); - - deploymentSchedule[0].state.deploymentStartTime = 0; - deploymentSchedule[0].ensembleDelay = 700; - deploymentSchedule[0].maxDuration = 300; - deploymentSchedule[0].ensembleInterval = 1000; - - - deploymentSchedule[1].state.deploymentStartTime = 0; - deploymentSchedule[1].ensembleDelay = 500; - deploymentSchedule[1].maxDuration = 200; - deploymentSchedule[1].ensembleInterval = 1000; - - - int i = 1; - uint32_t start = deploymentSchedule[i].state.deploymentStartTime + - deploymentSchedule[i].ensembleDelay; - uint32_t end = start + deploymentSchedule[i].maxDuration; - bool overlap = SCH_willOverlap(deploymentSchedule.data(), i, 0, start); - ASSERT_FALSE(overlap); - SCH_getNextEvent(deploymentSchedule.data(), &nextEvent, - &nextEventTime, millis()); - runAndCheckEvent("B", 500, 700); - SCH_getNextEvent(deploymentSchedule.data(), &nextEvent, - &nextEventTime, millis()); - runAndCheckEvent("A", 700, 1000); -} - diff --git a/tests/inputs/example.txt b/tests/inputs/example.txt index 691b504b..f4070a44 100644 --- a/tests/inputs/example.txt +++ b/tests/inputs/example.txt @@ -6,10 +6,10 @@ ENSEMBLES #taskname|interval|duration or taskname|interval|duration|maxDelay A|2000|200 B|2000|400|1000 C|500|100 -DELAYS #"taskname|iteration|delay" or "taskname|iteration|delay|before" (after implied) +DELAYS #0 indexed: "taskname|iteration|delay" or "taskname|iteration|delay|before" (after implied) A|0|100|before B|3|200 -EXPECTED #"taskname|start|end| -A|0|200 +EXPECTED #"taskname|start|end" +A|100|300 B|300|700 C|700|800 \ No newline at end of file diff --git a/tests/overlap_google_tests.cpp b/tests/overlap_google_tests.cpp new file mode 100644 index 00000000..8def967a --- /dev/null +++ b/tests/overlap_google_tests.cpp @@ -0,0 +1,420 @@ +/** + * @file gtest.cpp + * @author Charlie Kushelevsky (ckushelevsky@ucsd.edu) + * @brief Google Tests for scheduler.cpp + */ +#include +#include "scheduler_test_system.hpp" +#include "test_ensembles.hpp" +#include +#include +#include +#include +#include +#include + +class SchedulerOverlapTests : public ::testing::Test +{ +protected: + //! holds the deployment schedule created in @ref SchedulerTest() + std::vector deploymentSchedule; + //! pointer for next event in deploymentSchedule + DeploymentSchedule_t* nextEvent; + //! next time any event will be run + uint32_t nextEventTime; + //! holds actual values for testing + std::vector actual; + //! holds expected values for testing + std::vector expected; + + //! output file for expected values + std::ofstream expectedFile; + //! output file for actual values + std::ofstream actualFile; + + + //! filename for writing expected test output + std::string expectedFileName; + //! filename for writing actual test output + std::string actualFileName; + //! holds test name across functions + std::string testName; + + + + //! for writing test output + bool useCompareLogs; + + static std::unique_ptr files; + + static void SetUpTestSuite() + { + files = std::make_unique("expected_overlap_tests.log", + "actual_overlap_tests.log"); + } + static void TearDownTestSuite() + { + files->closeFiles(); + } + + /** + * @brief Construct a new Scheduler Test object + * + * Creates a deployment schedule with three ensembles: + * Ensemble A runs every 2000ms with a max duration of 400ms + * Ensemble B runs every 2000ms with a max duration of 200ms + * Ensemble C runs every 2000ms with a max duration of 600ms + */ + SchedulerOverlapTests() + { + deploymentSchedule = { + { SS_ensembleAFunc, //measure + SS_ensembleAInit, //init + 1, // measurementsToAccumulate + 0, // ensembleDelay + 2000, //ensembleInterval + 400, //maxDuration + UINT32_MAX, //maxDelay + "A", //taskName + {0} //state + }, + + {SS_ensembleBFunc, SS_ensembleBInit, 1, 0, 2000, 200, UINT32_MAX, "B",{0}}, + { nullptr, nullptr, 0, 0, 0, 0, 0, "", {0}} + }; + } + + + + + + + /** + * @brief Add expected log to vector + * @param task the name of the task being run + * @param start the start time + * @param end the end tim + */ + inline void appendExpectedFile(std::string task, + uint32_t start, + uint32_t end) + { + expected.emplace_back(task, start, end); + } + /** + * @brief Add actual log to vector + * @param task the name of the task being run + * @param start the start time + * @param end the end tim + */ + inline void appendActualFile(std::string task, + uint32_t start, + uint32_t end) + { + actual.emplace_back(task, start, end); + } + /** + * @brief Sets up the test envirnoment before each test + * + */ + void SetUp() override + { + actual.clear(); + expected.clear(); + + const ::testing::TestInfo* const test_info = + ::testing::UnitTest::GetInstance()->current_test_info(); + + testName = std::string(test_info->name()); + + nextEvent = nullptr; // ensures that first call to scheduler is correct + nextEventTime = 0; // time handling + setTime(0); // time handling see @ref tests/scheduler_test_system.cpp + SCH_initializeSchedule(deploymentSchedule.data(), millis()); + useCompareLogs = false; + + + } + + /** + * @brief Cleans the test envirnoment after each test + * + */ + void TearDown() override + { + files->writeTest(testName,expected,actual); + } + + + + /** + * @brief Run task and update time with delay and check values + * + * This function checks the correct task is being run, and the start time + * and end time is correct. The delay is added after the task is run. + * + * + * @param expectedTaskName expected task name character + * @param expectedStart time to check start time with + * @param expectedEnd time to check end time with + * @param additionalTime the amount of delay to add + */ + + /** + * @brief Run task and update time and check values + * + * This function checks the correct task is being run, and the start time + * and end time is correct + * + * + * @param expectedTaskName expected task name character + * @param expectedStart time to check start time with + * @param expectedEnd time to check end time with + */ + inline void runAndCheckEvent(std::string expectedTaskName, + uint32_t expectedStart, + uint32_t expectedEnd) + { + runAndCheckEventWithDelays(expectedTaskName, expectedStart, + expectedEnd, 0, 0); + } + void runAndCheckEventWithDelays(std::string expectedTaskName, + uint32_t expectedStart, + uint32_t expectedEnd, + uint32_t preceedingDelay, + uint32_t trailingDelay) + { + ASSERT_NE(nextEvent, nullptr) << "Scheduler returned nullptr."; + std::stringstream failMessage; + failMessage << "runAndCheckEvent failed:\n" + << "Expected \t Actual\n" + << expectedTaskName << "\t\t" << nextEvent->taskName << "\n" + << expectedStart << "\t\t" << nextEventTime + preceedingDelay + << "\n" + << expectedEnd << "\t\t" << nextEventTime + nextEvent->maxDuration; + + ASSERT_EQ(expectedTaskName, nextEvent->taskName) << failMessage.str(); + + setTime(nextEventTime); + addTime(preceedingDelay); + ASSERT_EQ(expectedStart, millis()) << failMessage.str(); + addTime(nextEvent->maxDuration); + addTime(trailingDelay); + ASSERT_EQ(expectedEnd, millis()) << failMessage.str(); + appendExpectedFile(expectedTaskName, expectedStart, expectedEnd); + appendActualFile(nextEvent->taskName, nextEventTime, millis()); + } + + +}; +std::unique_ptr SchedulerOverlapTests::files; +/** + * @brief Testing no overlap with A before B + * + * A *********** + * B ********** + */ +TEST_F(SchedulerOverlapTests, NoOverlapBefore) +{ + + + deploymentSchedule[0].state.deploymentStartTime = 0; + deploymentSchedule[0].ensembleDelay = 0; + deploymentSchedule[0].maxDuration = 300; + deploymentSchedule[0].ensembleInterval = 1000; + + deploymentSchedule[1].state.deploymentStartTime = 0; + deploymentSchedule[1].ensembleDelay = 500; + deploymentSchedule[1].maxDuration = 200; + deploymentSchedule[1].ensembleInterval = 1000; + + int i = 1; + uint32_t start = deploymentSchedule[i].state.deploymentStartTime + + deploymentSchedule[i].ensembleDelay; + uint32_t end = start + deploymentSchedule[i].maxDuration; + bool overlap = SCH_willOverlap(deploymentSchedule.data(), i, 0, start); + ASSERT_FALSE(overlap); +} + + + +/** + * @brief Testing overlap with end of A and start of B + * + * A *********** + * B *********** + */ +TEST_F(SchedulerOverlapTests, OverlapBefore) +{ + + + deploymentSchedule[0].state.deploymentStartTime = 0; + deploymentSchedule[0].state.nextRunTime = 250; + deploymentSchedule[0].maxDuration = 300; + deploymentSchedule[0].ensembleInterval = 1000; + + + deploymentSchedule[1].state.deploymentStartTime = 0; + deploymentSchedule[1].state.nextRunTime = 500; + deploymentSchedule[1].maxDuration = 200; + deploymentSchedule[1].ensembleInterval = 1000; + + + int i = 1; + uint32_t start = deploymentSchedule[i].state.nextRunTime; + uint32_t end = start + deploymentSchedule[i].maxDuration; + bool overlap = SCH_willOverlap(deploymentSchedule.data(), i, 0, start); + ASSERT_TRUE(overlap); +} + + +/* +A *********** +B ********** +*/ +/** + * @brief Testing no overlap with A after B + * + */ +TEST_F(SchedulerOverlapTests, NoOverlapAfter) +{ + + deploymentSchedule[0].state.deploymentStartTime = 0; + deploymentSchedule[0].ensembleDelay = 800; + deploymentSchedule[0].maxDuration = 300; + deploymentSchedule[0].ensembleInterval = 1000; + + deploymentSchedule[1].state.deploymentStartTime = 0; + deploymentSchedule[1].ensembleDelay = 500; + deploymentSchedule[1].maxDuration = 200; + deploymentSchedule[1].ensembleInterval = 1000; + + int i = 1; + uint32_t start = deploymentSchedule[i].state.deploymentStartTime + + deploymentSchedule[i].ensembleDelay; + uint32_t end = start + deploymentSchedule[i].maxDuration; + bool overlap = SCH_willOverlap(deploymentSchedule.data(), i, 0, start); + ASSERT_FALSE(overlap); +} + +/** + * @brief Testing overlap with end of B and start of A + * + * A *********** + * B ********** + */ +TEST_F(SchedulerOverlapTests, OverlapAfter) +{ + + deploymentSchedule[0].state.deploymentStartTime = 0; + deploymentSchedule[0].state.nextRunTime = 650; + deploymentSchedule[0].maxDuration = 300; + deploymentSchedule[0].ensembleInterval = 1000; + + + deploymentSchedule[1].state.deploymentStartTime = 0; + deploymentSchedule[1].state.nextRunTime = 500; + deploymentSchedule[1].maxDuration = 200; + deploymentSchedule[1].ensembleInterval = 1000; + + + int i = 1; + uint32_t start = deploymentSchedule[i].state.nextRunTime; + uint32_t end = start + deploymentSchedule[i].maxDuration; + bool overlap = SCH_willOverlap(deploymentSchedule.data(), i, 0, start); + ASSERT_TRUE(overlap); +} + + +/** + * @brief Testing for overlap when B starts after A starts and before A ends + * + * A ***************** + * B ********** + * + */ +TEST_F(SchedulerOverlapTests, InsideOverlap) +{ + + deploymentSchedule[0].state.deploymentStartTime = 0; + deploymentSchedule[0].state.nextRunTime = 0; + deploymentSchedule[0].maxDuration = 800; + deploymentSchedule[0].ensembleInterval = 1000; + + + deploymentSchedule[1].state.deploymentStartTime = 0; + deploymentSchedule[1].state.nextRunTime = 500; + deploymentSchedule[1].maxDuration = 200; + deploymentSchedule[1].ensembleInterval = 1000; + + + int i = 1; + uint32_t start = deploymentSchedule[i].state.nextRunTime; + uint32_t end = start + deploymentSchedule[i].maxDuration; + bool overlap = SCH_willOverlap(deploymentSchedule.data(), i, 0, start); + ASSERT_TRUE(overlap); +} + + +/** + * @brief Testing no overlap edge case when B starts as A ends + * + * A ********* + * B ********** + */ +TEST_F(SchedulerOverlapTests, Boundary1) +{ + deploymentSchedule[0].state.deploymentStartTime = 0; + deploymentSchedule[0].state.nextRunTime = 0; + deploymentSchedule[0].maxDuration = 500; + deploymentSchedule[0].ensembleInterval = 1000; + + deploymentSchedule[1].state.deploymentStartTime = 0; + deploymentSchedule[1].state.nextRunTime = 500; + deploymentSchedule[1].maxDuration = 200; + deploymentSchedule[1].ensembleInterval = 1000; + + + int i = 1; + uint32_t start = deploymentSchedule[i].state.nextRunTime; + uint32_t end = start + deploymentSchedule[i].maxDuration; + bool overlap = SCH_willOverlap(deploymentSchedule.data(), i, 0, start); + ASSERT_FALSE(overlap); +} + + +/** + * @brief Testing no overlap edge case when A starts as B ends + * + * A ********* + * B ********** + */ +TEST_F(SchedulerOverlapTests, Boundary2) +{ + + deploymentSchedule[0].state.deploymentStartTime = 0; + deploymentSchedule[0].ensembleDelay = 700; + deploymentSchedule[0].maxDuration = 300; + deploymentSchedule[0].ensembleInterval = 1000; + + + deploymentSchedule[1].state.deploymentStartTime = 0; + deploymentSchedule[1].ensembleDelay = 500; + deploymentSchedule[1].maxDuration = 200; + deploymentSchedule[1].ensembleInterval = 1000; + + + int i = 1; + uint32_t start = deploymentSchedule[i].state.deploymentStartTime + + deploymentSchedule[i].ensembleDelay; + uint32_t end = start + deploymentSchedule[i].maxDuration; + bool overlap = SCH_willOverlap(deploymentSchedule.data(), i, 0, start); + ASSERT_FALSE(overlap); + SCH_getNextEvent(deploymentSchedule.data(), &nextEvent, + &nextEventTime, millis()); + runAndCheckEvent("B", 500, 700); + SCH_getNextEvent(deploymentSchedule.data(), &nextEvent, + &nextEventTime, millis()); + runAndCheckEvent("A", 700, 1000); +} + diff --git a/tests/scheduler_proccessor.py b/tests/scheduler_proccessor.py index 5e9a6bb1..c02515c1 100644 --- a/tests/scheduler_proccessor.py +++ b/tests/scheduler_proccessor.py @@ -9,7 +9,7 @@ import cv2 import json from pathlib import Path - +import glob def comparelogs(): actual_json, expected_json = parse_logs() @@ -101,39 +101,43 @@ def plot_gantt(tasks, title, dir='/outputs/', max_duration=0,tasks_len=0): def parse_logs(return_max=False): - tasks = [] - with open('expected.log') as f: - expected_json = json.load(f) - with open('actual.log') as f: - actual_json = json.load(f) + root = 'outputs/' + pattern = 'actual_' + for filepath in glob.iglob('outputs/actual*.log'): + with open(filepath.replace("actual","expected")) as f: + expected_json = json.load(f) + with open(filepath) as f: + actual_json = json.load(f) + + - for k in expected_json.keys(): - expected_raw = expected_json[k] - actual_raw = actual_json[k] - expected_json[k] = [] - actual_json[k] = [] - for v in expected_raw: - l = v.split('|') - label = l[0] - start_time = int(l[1]) - end_time = int(l[2]) - duration = end_time - start_time - expected_json[k].append({'label': label, 'start': start_time, \ - 'duration': duration}) - for v in actual_raw: - l = v.split('|') - label = l[0] - start_time = int(l[1]) - end_time = int(l[2]) - duration = end_time - start_time - actual_json[k].append({'label': label, 'start': start_time, \ - 'duration': duration}) - + for k in expected_json.keys(): + expected_raw = expected_json[k] + actual_raw = actual_json[k] + expected_json[k] = [] + actual_json[k] = [] + for v in expected_raw: + l = v.split('|') + label = l[0] + start_time = int(l[1]) + end_time = int(l[2]) + duration = end_time - start_time + expected_json[k].append({'label': label, 'start': start_time, \ + 'duration': duration}) + for v in actual_raw: + l = v.split('|') + label = l[0] + start_time = int(l[1]) + end_time = int(l[2]) + duration = end_time - start_time + actual_json[k].append({'label': label, 'start': start_time, \ + 'duration': duration}) + return actual_json, expected_json - + diff --git a/tests/scheduler_test_flog.cpp b/tests/scheduler_test_flog.cpp new file mode 100644 index 00000000..4e29e32f --- /dev/null +++ b/tests/scheduler_test_flog.cpp @@ -0,0 +1,174 @@ +#include "flog.hpp" +#include "conio.hpp" +#include "consts.hpp" +#include "scheduler_test_system.hpp" +#include +#include + + + + + + +typedef struct FLOG_Entry_ +{ + uint32_t timestamp_ms; + uint16_t errorCode; + FLOG_VALUE_TYPE param; +}__attribute__((packed)) FLOG_Entry_t; + +typedef struct FLOG_Data_ +{ + uint32_t numEntries; + uint32_t nNumEntries; + FLOG_Entry_t flogEntries[FLOG_NUM_ENTRIES]; +}FLOG_Data_t; + +typedef struct FLOG_Message_ +{ + FLOG_CODE_e code; + const char* message; +}FLOG_Message_t; + +FLOG_Data_t flogData; +static char FLOG_unknownMessage[256]; + +static const char* FLOG_FindMessage(FLOG_CODE_e code); +static int FLOG_IsInitialized(void); + +const FLOG_Message_t FLOG_Message[] = { + {FLOG_SYS_START, "System Start"}, + {FLOG_SYS_BADSRAM, "Bad SRAM"}, + {FLOG_SYS_STARTSTATE, "Starting State"}, + {FLOG_SYS_INITSTATE, "Initializing State"}, + {FLOG_SYS_EXECSTATE, "Executing State Body"}, + {FLOG_SYS_EXITSTATE, "Exiting State"}, + {FLOG_SYS_UNKNOWNSTATE, "Unknown State"}, + {FLOG_RESET_REASON, "Reset Reason"}, + {FLOG_CHARGER_REMOVED, "Charger removed"}, + + {FLOG_CAL_BURST, "Calibrate Burst"}, + {FLOG_CAL_INIT, "Calibrate Initialization"}, + {FLOG_CAL_START_RUN, "Calibrate Start RUN"}, + {FLOG_CAL_LIMIT, "Calibrate Limit of Cycles"}, + {FLOG_CAL_DONE, "Calibration complete"}, + {FLOG_CAL_EXIT, "Calbiration Exit"}, + {FLOG_CAL_SLEEP, "Calibration Sleep"}, + {FLOG_CAL_TEMP, "Calibration Temp Measurement"}, + + {FLOG_MAG_ID_MISMATCH, "Compass ID Mismatch"}, + {FLOG_MAG_MEAS_TO, "Compass Measurement Timeout"}, + {FLOG_MAG_TEST_FAIL, "Compass Self-Test Failure"}, + {FLOG_MAG_MEAS_OVRFL, "Compass Measurement Overflow"}, + {FLOG_MAG_I2C_FAIL, "Compass I2C Failure"}, + {FLOG_MAG_MODE_FAIL, "Compass Mode Set Fail"}, + {FLOG_ICM_FAIL, "ICM Fail"}, + + {FLOG_RIDE_INIT_TIMEOUT, "Ride init Timeout"}, + + {FLOG_UPLOAD_NO_UPLOAD, "Upload - No Upload Flag set"}, + {FLOG_UPL_BATT_LOW, "Upload Battery low"}, + {FLOG_UPL_FOLDER_COUNT, "Upload file count"}, + {FLOG_UPL_CONNECT_FAIL, "Upload connect fail"}, + {FLOG_UPL_OPEN_FAIL, "Upload open last session fail"}, + {FLOG_UPL_PUB_FAIL, "Upload Publish fail"}, + + {FLOG_GPS_INIT_FAIL, "GPS Init Fail"}, + {FLOG_GPS_START_FAIL, "GPS Start Fail"}, + + {FLOG_TEMP_FAIL, "Temp Start Fail"}, + + {FLOG_FS_OPENDIR_FAIL, "opendir fail"}, + {FLOG_FS_STAT_FAIL, "stat fail"}, + {FLOG_SYS_MOUNT_FAIL, "Mounting fail"}, + {FLOG_FS_MKDIR_FAIL, "mkdir fail"}, + {FLOG_FS_CREAT_FAIL, "file create fail"}, + {FLOG_FS_OPEN_FAIL, "file open fail"}, + {FLOG_FS_WRITE_FAIL, "file write fail"}, + {FLOG_FS_CLOSE_FAIL, "file close fail"}, + {FLOG_FS_FTRUNC_FAIL, "file ftrunc fail"}, + {FLOG_FS_READ_FAIL, "file ftrunc fail"}, + {FLOG_REC_SETUP_FAIL, "Recorder setup failed"}, + {FLOG_REC_SESSION_CLOSED, "Write to Closed Session"}, + + {FLOG_CELL_DISCONN_FAIL, "Cellular failed to disconnect"}, + + {FLOG_SW_NULLPTR, "Software Null Pointer"}, + {FLOG_DEBUG, "debug point"}, + {FLOG_NULL, NULL} +}; + +void FLOG_Initialize(void) +{ + if (flogData.nNumEntries != ~flogData.numEntries) + { + FLOG_ClearLog(); + } +} +void FLOG_AddError(FLOG_CODE_e errorCode, FLOG_VALUE_TYPE parameter) +{ + FLOG_Entry_t* pEntry; + + if (!FLOG_IsInitialized()) + { + FLOG_Initialize(); + } + + pEntry = &flogData.flogEntries[(flogData.numEntries) & (FLOG_NUM_ENTRIES - 1)]; + pEntry->timestamp_ms = millis(); + pEntry->errorCode = errorCode; + pEntry->param = parameter; + flogData.numEntries++; + flogData.nNumEntries = ~flogData.numEntries; +} + +void FLOG_DisplayLog(void) +{ + uint32_t i; + if (!FLOG_IsInitialized()) + { + SF_OSAL_printf("Fault Log not initialized!" __NL__); + return; + } + + i = 0; + if (flogData.numEntries > FLOG_NUM_ENTRIES) + { + SF_OSAL_printf("Fault Log overrun!" __NL__); + i = flogData.numEntries - FLOG_NUM_ENTRIES; + } + + for (; i < flogData.numEntries; i++) + { + SF_OSAL_printf("%8d %32s, parameter: 0x%08" FLOG_PARAM_FMT __NL__, + flogData.flogEntries[i & (FLOG_NUM_ENTRIES - 1)].timestamp_ms, + FLOG_FindMessage((FLOG_CODE_e) + flogData.flogEntries[i & (FLOG_NUM_ENTRIES - 1)].errorCode), + flogData.flogEntries[i & (FLOG_NUM_ENTRIES - 1)].param); + } + SF_OSAL_printf("" __NL__); +} +void FLOG_ClearLog(void) +{ + memset(&flogData, 0, sizeof(FLOG_Data_t)); + flogData.nNumEntries = ~flogData.numEntries; +} + +static const char* FLOG_FindMessage(FLOG_CODE_e code) +{ + const FLOG_Message_t* pEntry; + for (pEntry = FLOG_Message; pEntry->code; pEntry++) + { + if (pEntry->code == code) + { + return pEntry->message; + } + } + sprintf(FLOG_unknownMessage, "Unknown FLOG Code: 0x%04X", code); + return FLOG_unknownMessage; +} + +static int FLOG_IsInitialized(void) +{ + return flogData.nNumEntries == ~flogData.numEntries; +} \ No newline at end of file diff --git a/tests/scheduler_test_system.cpp b/tests/scheduler_test_system.cpp index cdc52523..1d78c80c 100644 --- a/tests/scheduler_test_system.cpp +++ b/tests/scheduler_test_system.cpp @@ -30,6 +30,14 @@ std::ostream& operator<<(std::ostream &strm, const TestLog &value) { << value.start << "|" << value.end << "\""; } +int SF_OSAL_sprintf(char* buffer, size_t size, const char* fmt, ...) +{ + va_list vargs; + va_start(vargs, fmt); + int nBytes = vsnprintf(buffer, size, fmt, vargs); + va_end(vargs); + return nBytes; +} /** * @brief prints to stdout @@ -88,3 +96,85 @@ void delay(uint32_t time) addTime(time); } +FileWriter::FileWriter(std::string expectedFileName, std::string actualFileName) +{ + this->expectedFileName = expectedFileName; + this->actualFileName = actualFileName; + std::ofstream expectedFile(expectedFileName,std::ios::out | + std::ios::trunc); + + std::ofstream actualFile(actualFileName,std::ios::out | + std::ios::trunc); + + if (actualFile.is_open() && expectedFile.is_open()) + { + actualFile << "{"; + expectedFile << "{"; + } + actualFile.close(); + expectedFile.close(); +} +void FileWriter::writeTest(std::string testName, + std::vector expected,std::vector actual) +{ + std::ofstream actualFile(actualFileName, std::ios::out | + std::ios::app); + std::ofstream expectedFile(expectedFileName, std::ios::out | + std::ios::app); + static bool firstTest = true; + if (firstTest == false) + { + expectedFile << ","; + actualFile << ","; + } + else + { + firstTest = false; + } + expectedFile << "\n\t\"" << testName << "\": ["; + if (!expected.empty()) + { + + + for (int i = 0; i < expected.size() - 1; i++) + { + expectedFile << expected[i] << ", "; + } + expectedFile << expected.back(); + } + expectedFile << "]"; + + expectedFile.close(); + + + actualFile << "\n\t\"" << testName << "\": ["; + if (!expected.empty()) + { + + + for (int i = 0; i < expected.size() - 1; i++) + { + actualFile << expected[i] << ", "; + } + actualFile << expected.back(); + } + actualFile << "]"; + actualFile.close(); +} +void FileWriter::closeFiles() +{ + std::ofstream actualFile(actualFileName, std::ios::out | + std::ios::app); + std::ofstream expectedFile(expectedFileName, std::ios::out | + std::ios::app); + + if (actualFile.is_open() && expectedFile.is_open()) + { + actualFile << "\n}"; + expectedFile << "\n}"; + } + + actualFile.close(); + expectedFile.close(); +} +EnsembleInput::EnsembleInput(std::string taskName,uint32_t interval, uint32_t duration, uint32_t delay) : taskName(taskName), interval(interval), duration(duration), delay(delay){}; \ No newline at end of file diff --git a/tests/scheduler_test_system.hpp b/tests/scheduler_test_system.hpp index e8022890..3e0592f9 100644 --- a/tests/scheduler_test_system.hpp +++ b/tests/scheduler_test_system.hpp @@ -8,10 +8,25 @@ #include #include #include +#include +#include -typedef uint32_t system_tick_t;// time unit required by Particle -static int testTime = 0;// simulates current time +//! time unit required by Particle +typedef uint32_t system_tick_t; + +/** + * @brief prints to stdout + * + * @param buffer destination for formatted string + * @param fmt format to print + * @param variables to print + * @return number of characters if successful + * @return ferror if error occurs + */ +int SF_OSAL_sprintf(char* buffer, size_t size, const char* fmt, ...); + +static int testTime = 0;//! simulates current time /** * @brief adds time to the current time * @@ -46,7 +61,7 @@ uint32_t millis(); */ struct TestLog { - char name; //!< name of the task + std::string name; //!< name of the task uint32_t start; //!< expected start time uint32_t end; //!< expected end time /** @@ -56,8 +71,8 @@ struct TestLog * @param start expected start time * @param end expected end time */ - TestLog(char name, uint32_t start, uint32_t end) : name(name), - start(start), end(end){} + TestLog(std::string name, uint32_t start, uint32_t end) : name(name), + start(start), end(end){} /** * @brief comparator for google tests EXPECT_TRUE * @@ -68,6 +83,74 @@ struct TestLog bool operator==(const TestLog& rhs); }; +struct Delay +{ + std::string taskName; //!< name of the task + uint32_t iteration; + uint32_t delay; + bool isBefore; + +}; +struct EnsembleInput +{ + EnsembleInput(std::string taskName,uint32_t interval, uint32_t duration, uint32_t delay); + std::string taskName; //!< name of the task + uint32_t interval; + uint32_t duration; + uint32_t delay; +}; +struct TestInput +{ + uint32_t start; + uint32_t end; + std::vector ensembles; + std::vector expectedValues; + std::vector delays; + std::string serialize() const { + std::stringstream ss; + ss << "TestInput: { Start: " << start << ", End: " << end << "\n"; + + ss << " Ensembles: [\n"; + for (const auto& ensemble : ensembles) { + ss << " { TaskName: " << ensemble.taskName + << ", Interval: " << ensemble.interval + << ", Duration: " << ensemble.duration + << ", Delay: " << ensemble.delay << " }\n"; + } + ss << " ]\n"; + + ss << " ExpectedValues: [\n"; + for (const auto& exp : expectedValues) { + ss << " { Name: " << exp.name + << ", Start: " << exp.start + << ", End: " << exp.end << " }\n"; + } + ss << " ]\n"; + + ss << " Delays: [\n"; + for (const auto& delay : delays) { + ss << " { TaskName: " << delay.taskName + << ", Iteration: " << delay.iteration + << ", Delay: " << delay.delay + << ", IsBefore: " << (delay.isBefore ? "true" : "false") << " }\n"; + } + ss << " ]\n"; + + ss << "}"; + return ss.str(); + } + +}; std::ostream& operator<<(std::ostream &strm, const TestLog &value); +struct FileWriter +{ + std::string expectedFileName; + std::string actualFileName; + + FileWriter(std::string expectedFileName, std::string actualFileName); + void writeTest(std::string testName, + std::vector expected, std::vector actual); + void closeFiles(); +}; #endif //__SCHEDULER__TEST__HPP_ \ No newline at end of file