OpenWalnut 1.2.5

WFlag_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 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 
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends