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_ */
|