239 lines
5.9 KiB
C++
239 lines
5.9 KiB
C++
/*
|
||
* 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_ */
|