OpenWalnut  1.2.5
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
WFlag_test.h
1 //---------------------------------------------------------------------------
2 //
3 // Project: OpenWalnut ( http://www.openwalnut.org )
4 //
5 // Copyright 2009 OpenWalnut Community, BSV@Uni-Leipzig and CNCF@MPI-CBS
6 // For more information see http://www.openwalnut.org/copying
7 //
8 // This file is part of OpenWalnut.
9 //
10 // OpenWalnut is free software: you can redistribute it and/or modify
11 // it under the terms of the GNU Lesser General Public License as published by
12 // the Free Software Foundation, either version 3 of the License, or
13 // (at your option) any later version.
14 //
15 // OpenWalnut is distributed in the hope that it will be useful,
16 // but WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 // GNU Lesser General Public License for more details.
19 //
20 // You should have received a copy of the GNU Lesser General Public License
21 // along with OpenWalnut. If not, see <http://www.gnu.org/licenses/>.
22 //
23 //---------------------------------------------------------------------------
24 
25 #ifndef WFLAG_TEST_H
26 #define WFLAG_TEST_H
27 
28 #include <iostream>
29 
30 #include <boost/thread.hpp>
31 #include <cxxtest/TestSuite.h>
32 
33 #include "../WFlag.h"
34 #include "../WConditionOneShot.h"
35 
36 /**
37  * Helper class.
38  */
39 class Callable
40 {
41 public:
42 
43  /**
44  * The flag to be tested
45  */
47 
48  /**
49  * True if the thread finishes.
50  */
51  bool finished;
52 
53  /**
54  * Constructor. To init the Flag.
55  */
57  {
58  finished = false;
59  flag = new WFlag< bool >( new WConditionOneShot(), false );
60  }
61 
62  /**
63  * Thread function.
64  */
65  void threadMain()
66  {
67  // just wait
68  flag->wait();
69  finished = true;
70  };
71 };
72 
73 /**
74  * Test WFlag
75  */
76 class WFlagTest : public CxxTest::TestSuite
77 {
78 public:
79  /**
80  * A temporary holder for some value.
81  */
83 
84  /**
85  * Helper function which simply sets the value above to true. It is used to test some conditions here.
86  */
87  void setTemporary()
88  {
89  m_testTemporary = true;
90  }
91 
92  /**
93  * An instantiation should never throw an exception, as well as tear down.
94  */
95  void testInstantiation( void )
96  {
97  WFlag< bool >* flag = 0;
98 
99  TS_ASSERT_THROWS_NOTHING( flag = new WFlag< bool >( new WConditionOneShot(), false ) );
100  TS_ASSERT_THROWS_NOTHING( delete flag );
101  }
102 
103  /**
104  * Test whether notification is working.
105  */
107  {
108  Callable t;
109  // the flag should be false now
110  // NOTE: the syntax to get the value of the flag looks ugly here, but you normally do not use pointers
111  TS_ASSERT( !( *t.flag )() );
112 
113  // start a thread
114  boost::thread thread = boost::thread( boost::bind( &Callable::threadMain, &t ) );
115 
116  // set value equal to the one already set
117  ( *t.flag )( false );
118  // this should NOT notify the thread since the set value is not different to the initial one
119  TS_ASSERT( !t.finished );
120 
121  // notify
122  ( *t.flag )( true );
123  thread.join();
124 
125  TS_ASSERT( ( *t.flag )() );
126  }
127 
128  /**
129  * Test whether change condition is fired.
130  */
132  {
133  m_testTemporary = false;
134 
135  // create a condition
137  c->subscribeSignal( boost::bind( &WFlagTest::setTemporary, this ) );
138 
139  // use own condition here
140  WFlag< bool >* flag = new WFlag< bool >( c, false );
141 
142  // change value
143  flag->set( !flag->get( true ) );
144 
145  // condition fired?
146  // Remember: the condition calls the above member function when fired
147  TS_ASSERT( m_testTemporary );
148 
149  // setting with the suppression flag enabled should not fire the condition:
150  m_testTemporary = false;
151  // change value
152  flag->set( !flag->get( true ), true );
153  TS_ASSERT( !m_testTemporary );
154 
155  // setting without a change of value should also not call the condition
156  flag->set( flag->get( true ) );
157  TS_ASSERT( !m_testTemporary );
158  }
159 
160  /**
161  * Test whether change flag is set and reset.
162  */
164  {
165  // create a flag
166  WFlag< bool >* flag = new WFlag< bool >( new WConditionOneShot(), false );
167 
168  // after creation, the change flag always is true
169  TS_ASSERT( flag->changed() );
170 
171  // getting the value does not change the flag
172  bool v = flag->get();
173  TS_ASSERT( !v );
174  TS_ASSERT( flag->changed() );
175 
176  // getting the value with the argument "true" should reset the change flag
177  v = flag->get( true );
178  TS_ASSERT( !flag->changed() );
179 
180  delete flag;
181  }
182 
183  /**
184  * Test whether copy construction/cloning is working.
185  */
187  {
188  // create a flag
189  WFlag< bool >* flag = new WFlag< bool >( new WConditionOneShot(), false );
190 
191  // clone
192  WFlag< bool >* flagClone = new WFlag< bool >( *flag );
193 
194  // check that value, flag and so on are the same
195  TS_ASSERT( flag->get() == flagClone->get() );
196  TS_ASSERT( flag->changed() == flagClone->changed() );
197 
198  // the first should not influence the clone
199  flag->get( true );
200  TS_ASSERT( flag->changed() != flagClone->changed() );
201  flagClone->set( !flagClone->get( true ) );
202  TS_ASSERT( flag->get() != flagClone->get() );
203 
204  // the conditions need to be different
205  // 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
206  TS_ASSERT( flag->getCondition() != flagClone->getCondition() );
207  TS_ASSERT( flag->getValueChangeCondition() != flagClone->getValueChangeCondition() );
208  }
209 };
210 
211 #endif // WFLAG_TEST_H
212 
213