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