/* * 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 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 inline umlib::tests::AtomicFlagTest::AtomicFlagTest( AsyncRunnerInterface & new_runner ) : runner(new_runner) {} template inline umlib::tests::AtomicFlagTest::~AtomicFlagTest() {} template inline void umlib::tests::AtomicFlagTest::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 inline void umlib::tests::AtomicFlagTest::test_create( TestResult & test_result ) { AtomicFlagImpl flag; test_result.assert_false( flag.test_and_set(), "AtomicFlag is clear after create"); } template inline void umlib::tests::AtomicFlagTest::test_create_volatile( TestResult & test_result) { volatile AtomicFlagImpl flag; test_result.assert_false( flag.test_and_set(), "Volatile AtomicFlag is clear after create"); } template inline void umlib::tests::AtomicFlagTest::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 inline void umlib::tests::AtomicFlagTest::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 inline void umlib::tests::AtomicFlagTest::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 inline void umlib::tests::AtomicFlagTest::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 inline void umlib::tests::AtomicFlagTest::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 inline void umlib::tests::AtomicFlagTest::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 inline void umlib::tests::AtomicFlagTest::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 inline void umlib::tests::AtomicFlagTest::test_once_set_volatile( TestResult &test_result) { } #endif /* ATOMICTEST_HPP_ */