OpenWalnut 1.2.5
WConditionSet_test.h
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 
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends