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