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