OpenWalnut
1.2.5
|
00001 //--------------------------------------------------------------------------- 00002 // 00003 // Project: OpenWalnut ( http://www.openwalnut.org ) 00004 // 00005 // Copyright 2009 OpenWalnut Community, BSV@Uni-Leipzig and CNCF@MPI-CBS 00006 // For more information see http://www.openwalnut.org/copying 00007 // 00008 // This file is part of OpenWalnut. 00009 // 00010 // OpenWalnut is free software: you can redistribute it and/or modify 00011 // it under the terms of the GNU Lesser General Public License as published by 00012 // the Free Software Foundation, either version 3 of the License, or 00013 // (at your option) any later version. 00014 // 00015 // OpenWalnut is distributed in the hope that it will be useful, 00016 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00017 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00018 // GNU Lesser General Public License for more details. 00019 // 00020 // You should have received a copy of the GNU Lesser General Public License 00021 // along with OpenWalnut. If not, see <http://www.gnu.org/licenses/>. 00022 // 00023 //--------------------------------------------------------------------------- 00024 00025 #ifndef WFLAG_TEST_H 00026 #define WFLAG_TEST_H 00027 00028 #include <iostream> 00029 00030 #include <boost/thread.hpp> 00031 #include <cxxtest/TestSuite.h> 00032 00033 #include "../WFlag.h" 00034 #include "../WConditionOneShot.h" 00035 00036 /** 00037 * Helper class. 00038 */ 00039 class Callable 00040 { 00041 public: 00042 00043 /** 00044 * The flag to be tested 00045 */ 00046 WFlag<bool>* flag; 00047 00048 /** 00049 * True if the thread finishes. 00050 */ 00051 bool finished; 00052 00053 /** 00054 * Constructor. To init the Flag. 00055 */ 00056 Callable() 00057 { 00058 finished = false; 00059 flag = new WFlag< bool >( new WConditionOneShot(), false ); 00060 } 00061 00062 /** 00063 * Thread function. 00064 */ 00065 void threadMain() 00066 { 00067 // just wait 00068 flag->wait(); 00069 finished = true; 00070 }; 00071 }; 00072 00073 /** 00074 * Test WFlag 00075 */ 00076 class WFlagTest : public CxxTest::TestSuite 00077 { 00078 public: 00079 /** 00080 * A temporary holder for some value. 00081 */ 00082 bool m_testTemporary; 00083 00084 /** 00085 * Helper function which simply sets the value above to true. It is used to test some conditions here. 00086 */ 00087 void setTemporary() 00088 { 00089 m_testTemporary = true; 00090 } 00091 00092 /** 00093 * An instantiation should never throw an exception, as well as tear down. 00094 */ 00095 void testInstantiation( void ) 00096 { 00097 WFlag< bool >* flag = 0; 00098 00099 TS_ASSERT_THROWS_NOTHING( flag = new WFlag< bool >( new WConditionOneShot(), false ) ); 00100 TS_ASSERT_THROWS_NOTHING( delete flag ); 00101 } 00102 00103 /** 00104 * Test whether notification is working. 00105 */ 00106 void testWaitNotify() 00107 { 00108 Callable t; 00109 // the flag should be false now 00110 // NOTE: the syntax to get the value of the flag looks ugly here, but you normally do not use pointers 00111 TS_ASSERT( !( *t.flag )() ); 00112 00113 // start a thread 00114 boost::thread thread = boost::thread( boost::bind( &Callable::threadMain, &t ) ); 00115 00116 // set value equal to the one already set 00117 ( *t.flag )( false ); 00118 // this should NOT notify the thread since the set value is not different to the initial one 00119 TS_ASSERT( !t.finished ); 00120 00121 // notify 00122 ( *t.flag )( true ); 00123 thread.join(); 00124 00125 TS_ASSERT( ( *t.flag )() ); 00126 } 00127 00128 /** 00129 * Test whether change condition is fired. 00130 */ 00131 void testChangeCondition() 00132 { 00133 m_testTemporary = false; 00134 00135 // create a condition 00136 WConditionOneShot* c = new WConditionOneShot(); 00137 c->subscribeSignal( boost::bind( &WFlagTest::setTemporary, this ) ); 00138 00139 // use own condition here 00140 WFlag< bool >* flag = new WFlag< bool >( c, false ); 00141 00142 // change value 00143 flag->set( !flag->get( true ) ); 00144 00145 // condition fired? 00146 // Remember: the condition calls the above member function when fired 00147 TS_ASSERT( m_testTemporary ); 00148 00149 // setting with the suppression flag enabled should not fire the condition: 00150 m_testTemporary = false; 00151 // change value 00152 flag->set( !flag->get( true ), true ); 00153 TS_ASSERT( !m_testTemporary ); 00154 00155 // setting without a change of value should also not call the condition 00156 flag->set( flag->get( true ) ); 00157 TS_ASSERT( !m_testTemporary ); 00158 } 00159 00160 /** 00161 * Test whether change flag is set and reset. 00162 */ 00163 void testChangeFlagAndReset() 00164 { 00165 // create a flag 00166 WFlag< bool >* flag = new WFlag< bool >( new WConditionOneShot(), false ); 00167 00168 // after creation, the change flag always is true 00169 TS_ASSERT( flag->changed() ); 00170 00171 // getting the value does not change the flag 00172 bool v = flag->get(); 00173 TS_ASSERT( !v ); 00174 TS_ASSERT( flag->changed() ); 00175 00176 // getting the value with the argument "true" should reset the change flag 00177 v = flag->get( true ); 00178 TS_ASSERT( !flag->changed() ); 00179 00180 delete flag; 00181 } 00182 00183 /** 00184 * Test whether copy construction/cloning is working. 00185 */ 00186 void testCopyConstruction() 00187 { 00188 // create a flag 00189 WFlag< bool >* flag = new WFlag< bool >( new WConditionOneShot(), false ); 00190 00191 // clone 00192 WFlag< bool >* flagClone = new WFlag< bool >( *flag ); 00193 00194 // check that value, flag and so on are the same 00195 TS_ASSERT( flag->get() == flagClone->get() ); 00196 TS_ASSERT( flag->changed() == flagClone->changed() ); 00197 00198 // the first should not influence the clone 00199 flag->get( true ); 00200 TS_ASSERT( flag->changed() != flagClone->changed() ); 00201 flagClone->set( !flagClone->get( true ) ); 00202 TS_ASSERT( flag->get() != flagClone->get() ); 00203 00204 // the conditions need to be different 00205 // This is because the flag is another one and you won't expect to wake up if someone changes a Flag you do not know 00206 TS_ASSERT( flag->getCondition() != flagClone->getCondition() ); 00207 TS_ASSERT( flag->getValueChangeCondition() != flagClone->getValueChangeCondition() ); 00208 } 00209 }; 00210 00211 #endif // WFLAG_TEST_H 00212 00213