Added multiple test cases.

This commit is contained in:
dario 2024-01-07 15:56:02 +01:00
parent 3acc17a7dc
commit d8b4258b20
10 changed files with 348 additions and 59 deletions

View File

@ -24,6 +24,6 @@
#include <sta/tacos/configs/default.hpp>
#define STA_TACOS_WATCHDOG_FREQUENCY 1000
#define STA_TACOS_NUM_STATES 3
#define STA_TACOS_NUM_STATES 8
#endif // STA_CONFIG_HPP

View File

@ -1,6 +1,6 @@
#ifndef STA_TASTY_CONFIG_HPP
#define STA_TASTY_CONFIG_HPP
#define TASTY_CASE_1
#define TASTY_CASE_5
#endif // STA_TASTY_CONFIG_HPP

View File

@ -18,6 +18,12 @@ namespace sta
* @param rslt The result of the test case.
*/
void test_case(const char * file, uint32_t line, bool rslt);
/**
* @brief Send a message signaling the end of a test case.
*
*/
void test_terminate();
} // namespace tasty
} // namespace sta
@ -28,6 +34,12 @@ namespace sta
*/
#define STA_TASTY_ASSERT(expr) ( (void)( sta::tasty::test_case(__FILE__, __LINE__, expr) ) )
/**
* @brief Send a message signaling the end of a test case.
*
*/
#define STA_TASTY_TERMINATE() ( (void)( sta::tasty::test_terminate() ) )
#endif // STA_DEBUGGING_ENABLED

View File

@ -1,81 +1,54 @@
/**
* A simple testcase that checks if threads are correctly terminated after state transitions
* by creating the following threads:
*
* - DummyThread: A thread that does nothing and runs only for state 0.
* - ToggleThread: A thread that switches between states 0 and 1.
* - Supervisor: A thread which supervises the system's behavior.
*
* This test case fails if Dummy doesn't run in state 0 or runs in state 1.
* Tests if the standard state transition works correctly.
*/
#include <sta/tasty/config.hpp>
#ifdef TASTY_CASE_1
#include <memory>
#include <sta/tacos.hpp>
#include <sta/debug/debug.hpp>
#include <sta/tasty/utils.hpp>
#include <sta/tasty/tasks/toggle.hpp>
#include <sta/tasty/tasks/supervisor.hpp>
namespace sta
{
namespace tasty
{
class DummyThread : public tacos::TacosThread
class DummyThread
{
private:
/* data */
public:
DummyThread()
: tacos::TacosThread("Dummy", osPriorityNormal)
: tacos::TacosThread{"Dummy", osPriorityNormal}
{}
void func() override
void func() override
{
// Nothing to do here.
STA_TASTY_ASSERT(tacos::getState() == 0);
// Transitioning from 0 to 1 should work correclty.
tacos::setState(0, 1);
STA_TASTY_ASSERT(tacos::getState() == 1);
// Transitioning from 0 to 5 should fail because we are in state 1.
tacos::setState(0, 5);
STA_TASTY_ASSERT(tacos::getState() == 1);
// Transitioning from 7 to 0 should fail aswell
tacos::setState(7, 0);
STA_TASTY_ASSERT(tacos::getState() == 1);
// Transitioning from 4 to 5 should also fail.
tacos::setState(5, 4);
STA_TASTY_ASSERT(tacos::getState() == 1);
STA_TASTY_TERMINATE();
}
};
/**
* @brief Global pointer to the dummy thread.
*
*/
std::shared_ptr<DummyThread> dummy;
/**
* @brief Checker function that is called repeatedly by the supervisor thread.
*
*/
void checkDummy()
{
// Wait for the next state change to happen
tacos::Statemachine::stateChangeEvent.wait(tacos::EventFlags::ALL, osWaitForever);
// Wait a little bit longer because Dummy needs time to terminate.
osDelay(10);
// Test if dummy is only running if the state is 0.
if (tacos::getState() == 0)
{
STA_TASTY_ASSERT(dummy->isRunning());
}
else
{
STA_TASTY_ASSERT(!dummy->isRunning());
}
}
void onTastyInit()
{
std::list<TastyCheck> checks = { &checkDummy };
dummy = tacos::addThread<DummyThread>({0});
tacos::addThread<Supervisor>({0, 1}, checks);
tacos::addThread<ToggleThread>({0, 1}, 1000);
tacos::addThread<DummyThread>({0, 1, 2, 3, 4, 5, 6, 7});
}
}
} // namespace tasty
} // namespace sta
#endif // TASTY_CASE_1
#endif // TASTY_CASE_1

View File

@ -1,16 +1,57 @@
/**
* Check if timed transitions work correctly.
*/
#include <sta/tasty/config.hpp>
#ifdef TASTY_CASE_2
#include <sta/tacos.hpp>
#include <sta/tasty/utils.hpp>
namespace sta
{
namespace tasty
{
class DummyThread
{
private:
/* data */
public:
DummyThread()
: tacos::TacosThread{"Dummy", osPriorityNormal}
{}
void func() override
{
STA_TASTY_ASSERT(tacos::getState() == 0);
// Schedule a state transition in 100 ticks.
tacos::setStateTimed(0, 1, 100);
// The state transition shouldn't have happened yet...
STA_TASTY_ASSERT(tacos::getState() == 0);
this->sleep(50);
// ... and still not
STA_TASTY_ASSERT(tacos::getState() == 0);
this->sleep(48);
// ... and still not
STA_TASTY_ASSERT(tacos::getState() == 0);
this->sleep(3);
// Now it should have happened
STA_TASTY_ASSERT(tacos::getState() == 1);
STA_TASTY_TERMINATE();
}
};
void onTastyInit()
{
tacos::addThread<DummyThread>({0, 1, 2, 3, 4, 5, 6, 7});
}
} // namespace tasty
} // namespace sta

66
src/cases/case3.cpp Normal file
View File

@ -0,0 +1,66 @@
/**
* Check if the lockout timer works correctly.
*/
#include <sta/tasty/config.hpp>
#ifdef TASTY_CASE_3
#include <sta/tacos.hpp>
#include <sta/tasty/utils.hpp>
namespace sta
{
namespace tasty
{
class DummyThread
{
private:
/* data */
public:
DummyThread()
: tacos::TacosThread{"Dummy", osPriorityNormal}
{}
void func() override
{
STA_TASTY_ASSERT(tacos::getState() == 0);
// Trigger a state transition with lockout of 100 ticks.
tacos::setState(0, 1, 100);
// The state transition should have been executed correctly.
STA_TASTY_ASSERT(tacos::getState() == 1);
// This state transition should get blocked.
tacos::setState(1, 3);
STA_TASTY_ASSERT(tacos::getState() == 1);
this->sleep(50);
// This state transition should get blocked.
tacos::setState(1, 4);
STA_TASTY_ASSERT(tacos::getState() == 1);
this->sleep(48);
// This state transition should get blocked.
tacos::setState(1, 2);
STA_TASTY_ASSERT(tacos::getState() == 0);
this->sleep(3);
// This state transition should get executed correctly.
tacos::setState(1, 7);
STA_TASTY_ASSERT(tacos::getState() == 7);
STA_TASTY_TERMINATE();
}
};
void onTastyInit()
{
tacos::addThread<DummyThread>({0, 1, 2, 3, 4, 5, 6, 7});
}
} // namespace tasty
} // namespace sta
#endif // TASTY_CASE_3

61
src/cases/case4.cpp Normal file
View File

@ -0,0 +1,61 @@
/**
* Test lockout timers in combination with timed transitions.
*/
#include <sta/tasty/config.hpp>
#ifdef TASTY_CASE_4
#include <sta/tacos.hpp>
#include <sta/tasty/utils.hpp>
namespace sta
{
namespace tasty
{
class DummyThread
{
private:
/* data */
public:
DummyThread()
: tacos::TacosThread{"Dummy", osPriorityNormal}
{}
void func() override
{
STA_TASTY_ASSERT(tacos::getState() == 0);
// Trigger a state transition with lockout of 100 ticks.
tacos::setState(0, 1, 100);
// Schedule a state transition to be executed after 50 ticks.
tacos::setStateTimed(1, 2, 50);
// This should have no effect.
STA_TASTY_ASSERT(tacos::getState() == 1);
// Wait for 50 ticks.
this->sleep(50);
// The state transition should have been blocked by the lockout timer
STA_TASTY_ASSERT(tacos::getState() == 1);
// Schedule a state transition to be executed in 51 ticks.
tacos::setStateTimed(1, 2, 51);
this->sleep(51);
// This state transition should get through.
STA_TASTY_ASSERT(tacos::getState() == 2);
STA_TASTY_TERMINATE();
}
};
void onTastyInit()
{
tacos::addThread<DummyThread>({0, 1, 2, 3, 4, 5, 6, 7});
}
} // namespace tasty
} // namespace sta
#endif // TASTY_CASE_4

52
src/cases/case5.cpp Normal file
View File

@ -0,0 +1,52 @@
/**
*
*/
#include <sta/tasty/config.hpp>
#ifdef TASTY_CASE_5
#include <sta/tacos.hpp>
#include <sta/tasty/utils.hpp>
namespace sta
{
namespace tasty
{
class DummyThread
{
private:
/* data */
public:
DummyThread()
: tacos::TacosThread{"Dummy", osPriorityNormal}
{}
void func() override
{
STA_TASTY_ASSERT(tacos::getState() == 0);
// Schedule a state transition in 50 ticks.
tacos::setStateTimed(0, 1, 50);
this->sleep(10);
// Force a state transition now. This should override the timed transition.
tacos::setState(0, 2);
STA_TASTY_ASSERT(tacos::getState() == 2);
this->sleep(41);
// The timed transition should have triggered now but shouldn't have any effect.
STA_TASTY_ASSERT(tacos::getState() == 2);
STA_TASTY_TERMINATE();
}
};
void onTastyInit()
{
tacos::addThread<DummyThread>({0, 1, 2, 3, 4, 5, 6, 7});
}
} // namespace tasty
} // namespace sta
#endif // TASTY_CASE_5

79
src/cases/case7.cpp Normal file
View File

@ -0,0 +1,79 @@
/**
* A simple testcase that checks if threads are correctly terminated after state transitions
* by creating the following threads:
*
* - DummyThread: A thread that does nothing and runs only for state 0.
* - ToggleThread: A thread that switches between states 0 and 1.
* - Supervisor: A thread which supervises the system's behavior.
*
* This test case fails if Dummy doesn't run in state 0 or runs in state 1.
*/
#include <sta/tasty/config.hpp>
#ifdef TASTY_CASE_7
#include <memory>
#include <sta/tacos.hpp>
#include <sta/debug/debug.hpp>
#include <sta/tasty/utils.hpp>
#include <sta/tasty/tasks/toggle.hpp>
#include <sta/tasty/tasks/supervisor.hpp>
namespace sta
{
namespace tasty
{
class DummyThread : public tacos::TacosThread
{
public:
DummyThread()
: tacos::TacosThread("Dummy", osPriorityNormal)
{}
void func() override
{
// Nothing to do here.
}
};
/**
* @brief Global pointer to the dummy thread.
*
*/
std::shared_ptr<DummyThread> dummy;
/**
* @brief Checker function that is called repeatedly by the supervisor thread.
*
*/
void checkDummy()
{
// Wait for the next state change to happen
tacos::Statemachine::stateChangeEvent.wait(tacos::EventFlags::ALL, osWaitForever);
// Wait a little bit longer because Dummy needs time to terminate.
osDelay(10);
// Test if dummy is only running if the state is 0.
if (tacos::getState() == 0)
{
STA_TASTY_ASSERT(dummy->isRunning());
}
else
{
STA_TASTY_ASSERT(!dummy->isRunning());
}
}
void onTastyInit()
{
std::list<TastyCheck> checks = { &checkDummy };
dummy = tacos::addThread<DummyThread>({0});
tacos::addThread<Supervisor>({0, 1}, checks);
tacos::addThread<ToggleThread>({0, 1}, 1000);
}
}
} // namespace sta
#endif // TASTY_CASE_7

View File

@ -12,6 +12,11 @@ namespace sta
{
STA_DEBUG_PRINTF("[%s|%d|%d]", file, line, rslt);
}
void test_terminate()
{
STA_DEBUG_PRINTLN("[T]");
}
} // namespace tasty
} // namespace sta