OpenWalnut  1.2.5
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
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  /**
44  * Flag set to true when thread starts
45  */
46  bool flag;
47 
48  /**
49  * The condition to be used for signalling.
50  */
51  WCondition* c;
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  /**
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 = boost::shared_ptr< WCondition >( new WCondition() );
93  boost::shared_ptr< WCondition > c2 = boost::shared_ptr< WCondition >( new WCondition() );
94  boost::shared_ptr< WCondition > c3 = boost::shared_ptr< WCondition >( 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 = boost::shared_ptr< WCondition >( new WCondition() );
129  boost::shared_ptr< WCondition > c2 = boost::shared_ptr< WCondition >( 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 = boost::shared_ptr< WCondition >( new WCondition() );
175  boost::shared_ptr< WCondition > c2 = boost::shared_ptr< WCondition >( 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