SDFM_CONTROL/EFC_PlatformC28x_Test/AtomicTest.hpp

239 lines
5.9 KiB
C++
Raw Permalink Normal View History

/*
* AtomicTest.hpp
*
* Created on: 25 сент. 2078 г.
* Author: leonid
*/
#ifndef ATOMICTEST_HPP_
#define ATOMICTEST_HPP_
#include "UnitTestInterface.hh"
#include "AsyncRunnerInterface.hh"
namespace umlib { namespace tests {
template<class AtomicFlagImlementation>
class AtomicFlagTest : public UnitTestInterface {
typedef AtomicFlagImlementation AtomicFlagImpl;
public:
AtomicFlagTest( AsyncRunnerInterface & runner );
~AtomicFlagTest();
void run( TestResult & test_result );
private:
AsyncRunnerInterface & runner;
void test_create( TestResult & test_result );
void test_create_volatile( TestResult & test_result );
void test_set_after_test_and_set( TestResult & test_result );
void test_set_after_test_and_set_volatile( TestResult & test_result );
void test_clear_after_create( TestResult & test_result );
void test_clear_after_create_volatile( TestResult & test_result );
void test_clear( TestResult & test_result );
void test_clear_volatile( TestResult & test_result );
void test_once_set( TestResult & test_result );
void test_once_set_volatile( TestResult & test_result );
struct AtomicFlagTrySet : public TaskInterface {
AtomicFlagImpl flag;
volatile bool on_task = false;
volatile bool on_main = false;
void reset() {
on_task = false;
on_main = false;
flag.clear();
}
void do_task() {
on_task = not flag.test_and_set();
}
void do_main() {
on_main = not flag.test_and_set();
}
bool fault() {
return (on_task and on_main) or
(not on_task and not on_main);
}
};
};
}
}
template<class AtomicFlagImlementation>
inline umlib::tests::AtomicFlagTest<AtomicFlagImlementation>::AtomicFlagTest( AsyncRunnerInterface & new_runner ) : runner(new_runner) {}
template<class AtomicFlagImlementation>
inline umlib::tests::AtomicFlagTest<AtomicFlagImlementation>::~AtomicFlagTest() {}
template<class AtomicFlagImlementation>
inline void umlib::tests::AtomicFlagTest<AtomicFlagImlementation>::run( TestResult & test_result ) {
test_create( test_result );
test_create_volatile( test_result );
test_set_after_test_and_set( test_result );
test_set_after_test_and_set_volatile( test_result );
test_clear(test_result);
test_clear_volatile(test_result);
test_clear_after_create(test_result);
test_clear_after_create_volatile(test_result);
test_once_set(test_result);
}
template<class AtomicFlagImlementation>
inline void umlib::tests::AtomicFlagTest<AtomicFlagImlementation>::test_create(
TestResult & test_result ) {
AtomicFlagImpl flag;
test_result.assert_false( flag.test_and_set(), "AtomicFlag is clear after create");
}
template<class AtomicFlagImlementation>
inline void umlib::tests::AtomicFlagTest<AtomicFlagImlementation>::test_create_volatile(
TestResult & test_result) {
volatile AtomicFlagImpl flag;
test_result.assert_false( flag.test_and_set(), "Volatile AtomicFlag is clear after create");
}
template<class AtomicFlagImlementation>
inline void umlib::tests::AtomicFlagTest<AtomicFlagImlementation>::test_set_after_test_and_set(
TestResult & test_result ) {
AtomicFlagImpl flag;
(void) flag.test_and_set();
test_result.assert_true( flag.test_and_set(), "AtomicFlag is set after *test_and_set*");
}
template<class AtomicFlagImlementation>
inline void umlib::tests::AtomicFlagTest<AtomicFlagImlementation>::test_set_after_test_and_set_volatile(
TestResult & test_result ) {
volatile AtomicFlagImpl flag;
(void) flag.test_and_set();
test_result.assert_true( flag.test_and_set(), "Volatile AtomicFlag is set after *test_and_set*");
}
template<class AtomicFlagImlementation>
inline void umlib::tests::AtomicFlagTest<AtomicFlagImlementation>::test_clear(
TestResult & test_result ) {
AtomicFlagImpl flag;
(void) flag.test_and_set();
flag.clear();
test_result.assert_false( flag.test_and_set(), "AtomicFlag is clear after *clear*");
}
template<class AtomicFlagImlementation>
inline void umlib::tests::AtomicFlagTest<AtomicFlagImlementation>::test_clear_volatile(
TestResult & test_result ) {
volatile AtomicFlagImpl flag;
(void) flag.test_and_set();
flag.clear();
test_result.assert_false( flag.test_and_set(), "AtomicFlag is clear after *clear*");
}
template<class AtomicFlagImlementation>
inline void umlib::tests::AtomicFlagTest<AtomicFlagImlementation>::test_clear_after_create(
TestResult & test_result ) {
AtomicFlagImpl flag;
flag.clear();
test_result.assert_false( flag.test_and_set(), "AtomicFlag is clear after create and *clear*");
}
template<class AtomicFlagImlementation>
inline void umlib::tests::AtomicFlagTest<AtomicFlagImlementation>::test_clear_after_create_volatile(
TestResult & test_result ) {
volatile AtomicFlagImpl flag;
flag.clear();
test_result.assert_false( flag.test_and_set(), "Volatile AtomicFlag is clear after create and *clear*");
}
namespace umlib { namespace tests { namespace detail {
}}}
template<class AtomicFlagImlementation>
inline void umlib::tests::AtomicFlagTest<AtomicFlagImlementation>::test_once_set(
TestResult & test_result ) {
AtomicFlagTrySet flag_check;
uint32_t tick = 0;
bool fault = false;
do {
flag_check.reset();
runner.run_after( &flag_check, tick++ );
flag_check.do_main();
runner.cancel();
fault = fault or flag_check.fault();
} while( runner.is_ran() ); //and not fault
test_result.assert_false(fault, "AtomicFlag provide atomically test_and_set");
}
template<class AtomicFlagImlementation>
inline void umlib::tests::AtomicFlagTest<AtomicFlagImlementation>::test_once_set_volatile(
TestResult &test_result)
{
}
#endif /* ATOMICTEST_HPP_ */