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