OpenWalnut  1.4.0
WConditionSet_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 WCONDITIONSET_TEST_H
26 #define WCONDITIONSET_TEST_H
27 
28 #include <iostream>
29 
30 #include <boost/thread.hpp>
31 #include <cxxtest/TestSuite.h>
32 
33 #include "../WConditionSet.h"
34 #include "../WCondition.h"
35 
36 /**
37  * Helper class.
38  */
39 class Callable
40 {
41 public:
42  /**
43  * Flag set to true when thread starts
44  */
45  bool flag;
46 
47  /**
48  * The condition to be used for signalling.
49  */
50  WCondition* c;
51 
52  /**
53  * Thread main method.
54  */
55  void threadMain()
56  {
57  flag = true;
58 
59  // let the test's thread reach its "wait" call first
60  boost::this_thread::sleep( boost::posix_time::seconds( 1 ) );
61  c->notify();
62  };
63 };
64 
65 /**
66  * Test WConditionSet
67  */
68 class WConditionSetTest : public CxxTest::TestSuite
69 {
70 public:
71  /**
72  * An instantiation should never throw an exception, as well as tear down.
73  */
74  void testInstantiation( void )
75  {
76  WConditionSet* c = NULL;
77 
78  TS_ASSERT_THROWS_NOTHING( c = new WConditionSet() );
79  TS_ASSERT_THROWS_NOTHING( delete c );
80  }
81 
82  /**
83  * Tests add and remove methods. Also check double remove/add.
84  */
85  void testAddRemove( void )
86  {
87  WConditionSet* cs = new WConditionSet();
88 
89  // create some conditions
90  boost::shared_ptr< WCondition > c1( new WCondition() );
91  boost::shared_ptr< WCondition > c2( new WCondition() );
92  boost::shared_ptr< WCondition > c3( new WCondition() );
93 
94  // add them
95  TS_ASSERT_THROWS_NOTHING( cs->add( c1 ) );
96  // adding it a second time should not cause any exception
97  TS_ASSERT_THROWS_NOTHING( cs->add( c1 ) );
98  TS_ASSERT_THROWS_NOTHING( cs->add( c2 ) );
99 
100  // the size should now be 2
101  TS_ASSERT( cs->m_conditionSet.size() == 2 );
102 
103  // try to remove a condition which is NOT inside the condition set
104  TS_ASSERT_THROWS_NOTHING( cs->remove( c3 ) );
105  TS_ASSERT( cs->m_conditionSet.size() == 2 );
106 
107  // remove a condition inside the set
108  TS_ASSERT_THROWS_NOTHING( cs->remove( c1 ) );
109  TS_ASSERT( cs->m_conditionSet.size() == 1 );
110 
111  // remove a condition inside the set
112  TS_ASSERT_THROWS_NOTHING( cs->remove( c2 ) );
113  TS_ASSERT( cs->m_conditionSet.size() == 0 );
114 
115  delete cs;
116  }
117 
118  /**
119  * Tests whether the condition set really reacts on fired conditions.
120  */
121  void testWait( void )
122  {
123  WConditionSet* cs = new WConditionSet();
124 
125  // create some conditions
126  boost::shared_ptr< WCondition > c1( new WCondition() );
127  boost::shared_ptr< WCondition > c2( new WCondition() );
128 
129  // disable resetable feature
130  cs->setResetable( false, false );
131  cs->add( c1 );
132  cs->add( c2 );
133 
134  // create a thread which fires a condition in the set for us
135  Callable t;
136  t.flag = false;
137  t.c = c1.get();
138 
139  // start a thread
140  boost::thread thread = boost::thread( boost::bind( &Callable::threadMain, &t ) );
141 
142  // wait for condition
143  cs->wait();
144 
145  // ugly but this is the only way to test it.
146  TS_ASSERT( true );
147 
148  // reset it
149  cs->reset();
150  TS_ASSERT( !cs->m_fired );
151 
152  // ensure that a condition which has been removed does NOT fire the condition set
153  cs->remove( c2 );
154  c2->notify();
155  TS_ASSERT( !cs->m_fired );
156 
157  // the other one should fire the set
158  c1->notify();
159  TS_ASSERT( cs->m_fired );
160 
161  delete cs;
162  }
163 
164  /**
165  * Tests the resetable feature.
166  */
167  void testWaitResetable( void )
168  {
169  WConditionSet* cs = new WConditionSet();
170 
171  // create some conditions
172  boost::shared_ptr< WCondition > c1( new WCondition() );
173  boost::shared_ptr< WCondition > c2( new WCondition() );
174 
175  // disable resetable feature
176  cs->setResetable( true, true );
177  cs->add( c1 );
178  cs->add( c2 );
179 
180  // notify a condition
181  c2->notify();
182 
183  // after the notification, m_fired should be true
184  TS_ASSERT( cs->m_fired );
185 
186  // wait should return instantly
187  cs->wait(); // how to test it? it just freezes the test if it does not work ;-) also some kind of error notification :-)
188 
189  // as the condition set has auto-reset enabled: m_fired should be false again
190  TS_ASSERT( !cs->m_fired );
191 
192  // if resetable without auto-reset:
193  cs->setResetable( true, false );
194 
195  // notify again
196  c2->notify();
197 
198  // m_fired should be true
199  TS_ASSERT( cs->m_fired );
200 
201  // wait should return instantly
202  cs->wait(); // how to test it? it just freezes the test if it does not work ;-) also some kind of error notification :-)
203 
204  // m_fired should stay true
205  TS_ASSERT( cs->m_fired );
206 
207  delete cs;
208  }
209 
210  /**
211  * Ensures reset() never throws something.
212  */
214  {
215  WConditionSet* cs = new WConditionSet();
216 
217  cs->setResetable( false, false );
218 
219  // just ensure it does not throw something
220  TS_ASSERT_THROWS_NOTHING( cs->reset() );
221 
222  delete cs;
223  }
224 };
225 
226 #endif // WCONDITIONSET_TEST_H
227 
virtual void remove(boost::shared_ptr< WCondition > condition)
Removes the specified condition.
virtual void wait() const
Wait for the condition.
bool flag
Flag set to true when thread starts.
virtual void add(boost::shared_ptr< WCondition > condition)
Adds another condition to the set of conditions to wait for.
void threadMain()
Thread main method.
Helper class.
void testWaitResetable(void)
Tests the resetable feature.
void testWait(void)
Tests whether the condition set really reacts on fired conditions.
virtual void reset() const
Resets the internal fire state.
Class allowing multiple conditions to be used for one waiting cycle.
Definition: WConditionSet.h:42
void setResetable(bool resetable=true, bool autoReset=true)
Sets the resetable flag.
bool m_fired
Flag denoting whether one condition fired in the past.
ConditionConnectionMap m_conditionSet
Set of conditions to be waited for.
Test WConditionSet.
Class to encapsulate boost::condition_variable_any.
Definition: WCondition.h:39
WCondition * c
The condition to be used for signalling.
void testResetOnNotResetable(void)
Ensures reset() never throws something.
virtual void notify()
Notifies all waiting threads.
Definition: WCondition.cpp:44
void testInstantiation(void)
An instantiation should never throw an exception, as well as tear down.
void testAddRemove(void)
Tests add and remove methods.