OpenWalnut
1.4.0
|
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 WCONDITIONSET_TEST_H 00026 #define WCONDITIONSET_TEST_H 00027 00028 #include <iostream> 00029 00030 #include <boost/thread.hpp> 00031 #include <cxxtest/TestSuite.h> 00032 00033 #include "../WConditionSet.h" 00034 #include "../WCondition.h" 00035 00036 /** 00037 * Helper class. 00038 */ 00039 class Callable 00040 { 00041 public: 00042 /** 00043 * Flag set to true when thread starts 00044 */ 00045 bool flag; 00046 00047 /** 00048 * The condition to be used for signalling. 00049 */ 00050 WCondition* c; 00051 00052 /** 00053 * Thread main method. 00054 */ 00055 void threadMain() 00056 { 00057 flag = true; 00058 00059 // let the test's thread reach its "wait" call first 00060 boost::this_thread::sleep( boost::posix_time::seconds( 1 ) ); 00061 c->notify(); 00062 }; 00063 }; 00064 00065 /** 00066 * Test WConditionSet 00067 */ 00068 class WConditionSetTest : public CxxTest::TestSuite 00069 { 00070 public: 00071 /** 00072 * An instantiation should never throw an exception, as well as tear down. 00073 */ 00074 void testInstantiation( void ) 00075 { 00076 WConditionSet* c = NULL; 00077 00078 TS_ASSERT_THROWS_NOTHING( c = new WConditionSet() ); 00079 TS_ASSERT_THROWS_NOTHING( delete c ); 00080 } 00081 00082 /** 00083 * Tests add and remove methods. Also check double remove/add. 00084 */ 00085 void testAddRemove( void ) 00086 { 00087 WConditionSet* cs = new WConditionSet(); 00088 00089 // create some conditions 00090 boost::shared_ptr< WCondition > c1( new WCondition() ); 00091 boost::shared_ptr< WCondition > c2( new WCondition() ); 00092 boost::shared_ptr< WCondition > c3( new WCondition() ); 00093 00094 // add them 00095 TS_ASSERT_THROWS_NOTHING( cs->add( c1 ) ); 00096 // adding it a second time should not cause any exception 00097 TS_ASSERT_THROWS_NOTHING( cs->add( c1 ) ); 00098 TS_ASSERT_THROWS_NOTHING( cs->add( c2 ) ); 00099 00100 // the size should now be 2 00101 TS_ASSERT( cs->m_conditionSet.size() == 2 ); 00102 00103 // try to remove a condition which is NOT inside the condition set 00104 TS_ASSERT_THROWS_NOTHING( cs->remove( c3 ) ); 00105 TS_ASSERT( cs->m_conditionSet.size() == 2 ); 00106 00107 // remove a condition inside the set 00108 TS_ASSERT_THROWS_NOTHING( cs->remove( c1 ) ); 00109 TS_ASSERT( cs->m_conditionSet.size() == 1 ); 00110 00111 // remove a condition inside the set 00112 TS_ASSERT_THROWS_NOTHING( cs->remove( c2 ) ); 00113 TS_ASSERT( cs->m_conditionSet.size() == 0 ); 00114 00115 delete cs; 00116 } 00117 00118 /** 00119 * Tests whether the condition set really reacts on fired conditions. 00120 */ 00121 void testWait( void ) 00122 { 00123 WConditionSet* cs = new WConditionSet(); 00124 00125 // create some conditions 00126 boost::shared_ptr< WCondition > c1( new WCondition() ); 00127 boost::shared_ptr< WCondition > c2( new WCondition() ); 00128 00129 // disable resetable feature 00130 cs->setResetable( false, false ); 00131 cs->add( c1 ); 00132 cs->add( c2 ); 00133 00134 // create a thread which fires a condition in the set for us 00135 Callable t; 00136 t.flag = false; 00137 t.c = c1.get(); 00138 00139 // start a thread 00140 boost::thread thread = boost::thread( boost::bind( &Callable::threadMain, &t ) ); 00141 00142 // wait for condition 00143 cs->wait(); 00144 00145 // ugly but this is the only way to test it. 00146 TS_ASSERT( true ); 00147 00148 // reset it 00149 cs->reset(); 00150 TS_ASSERT( !cs->m_fired ); 00151 00152 // ensure that a condition which has been removed does NOT fire the condition set 00153 cs->remove( c2 ); 00154 c2->notify(); 00155 TS_ASSERT( !cs->m_fired ); 00156 00157 // the other one should fire the set 00158 c1->notify(); 00159 TS_ASSERT( cs->m_fired ); 00160 00161 delete cs; 00162 } 00163 00164 /** 00165 * Tests the resetable feature. 00166 */ 00167 void testWaitResetable( void ) 00168 { 00169 WConditionSet* cs = new WConditionSet(); 00170 00171 // create some conditions 00172 boost::shared_ptr< WCondition > c1( new WCondition() ); 00173 boost::shared_ptr< WCondition > c2( new WCondition() ); 00174 00175 // disable resetable feature 00176 cs->setResetable( true, true ); 00177 cs->add( c1 ); 00178 cs->add( c2 ); 00179 00180 // notify a condition 00181 c2->notify(); 00182 00183 // after the notification, m_fired should be true 00184 TS_ASSERT( cs->m_fired ); 00185 00186 // wait should return instantly 00187 cs->wait(); // how to test it? it just freezes the test if it does not work ;-) also some kind of error notification :-) 00188 00189 // as the condition set has auto-reset enabled: m_fired should be false again 00190 TS_ASSERT( !cs->m_fired ); 00191 00192 // if resetable without auto-reset: 00193 cs->setResetable( true, false ); 00194 00195 // notify again 00196 c2->notify(); 00197 00198 // m_fired should be true 00199 TS_ASSERT( cs->m_fired ); 00200 00201 // wait should return instantly 00202 cs->wait(); // how to test it? it just freezes the test if it does not work ;-) also some kind of error notification :-) 00203 00204 // m_fired should stay true 00205 TS_ASSERT( cs->m_fired ); 00206 00207 delete cs; 00208 } 00209 00210 /** 00211 * Ensures reset() never throws something. 00212 */ 00213 void testResetOnNotResetable( void ) 00214 { 00215 WConditionSet* cs = new WConditionSet(); 00216 00217 cs->setResetable( false, false ); 00218 00219 // just ensure it does not throw something 00220 TS_ASSERT_THROWS_NOTHING( cs->reset() ); 00221 00222 delete cs; 00223 } 00224 }; 00225 00226 #endif // WCONDITIONSET_TEST_H 00227