OpenWalnut  1.4.0
WThreadedFunction_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 WTHREADEDFUNCTION_TEST_H
26 #define WTHREADEDFUNCTION_TEST_H
27 
28 #include <string>
29 
30 #include <cxxtest/TestSuite.h>
31 
32 #include "../WThreadedFunction.h"
33 #include "../WSharedObject.h"
34 
35 /**
36  * \class WThreadedFunctionTest
37  *
38  * Tests the WThreadedFunction class.
39  */
40 class WThreadedFunctionTest : public CxxTest::TestSuite
41 {
42  /**
43  * A threaded function.
44  */
45  class FuncType
46  {
47  public:
48  /**
49  * Constructor, initialize some stuff.
50  *
51  * \param value An int value.
52  */
53  FuncType( int value ) // NOLINT
54  : m_input( new int( value ) ) // NOLINT
55  {
56  // init stuff here
57  m_result.getWriteTicket()->get() = 0;
58  m_stopped.getWriteTicket()->get() = false;
59 
60  if( value < 0 )
61  {
62  value = -value;
63  }
64  }
65 
66  /**
67  * This is the actual thread function.
68  *
69  * \param shutdown A flag indicating the thread is supposed to stop.
70  */
71  void operator() ( std::size_t, std::size_t, WBoolFlag const& shutdown )
72  {
73  for( int i = 1; i <= *m_input.get() && !shutdown(); ++i )
74  {
75  m_result.getWriteTicket()->get() += i;
76  }
77  if( shutdown() )
78  {
79  m_stopped.getWriteTicket()->get() = true;
80  }
81  sleep( 1 );
82  }
83 
84  /**
85  * Check if the thread was ordered to stop.
86  *
87  * \return true, if the thread was ordered to stop
88  */
89  bool stopped()
90  {
91  return m_stopped.getReadTicket()->get();
92  }
93 
94  /**
95  * A method to extract the result.
96  *
97  * \return The result of the threaded computation.
98  */
99  int getResult()
100  {
101  return m_result.getReadTicket()->get();
102  }
103 
104  /**
105  * Reset everything.
106  */
107  void reset()
108  {
109  m_result.getWriteTicket()->get() = 0;
110  }
111 
112  private:
113  //! the input data
114  boost::shared_ptr< int const > m_input;
115 
116  //! the result
118 
119  //! thread stopped?
121  };
122 
123  /**
124  * A function that throws exceptions.
125  */
127  {
128  public:
129  /**
130  * The function.
131  */
132  void operator() ( std::size_t, std::size_t, WBoolFlag& )
133  {
134  throw WException( std::string( "Test!" ) );
135  }
136  };
137 
138 public:
139  /**
140  * A function computed by multiple threads should correctly set
141  * its status and compute the correct results.
142  */
144  {
145  boost::shared_ptr< FuncType > func( new FuncType( 5 ) );
146  // test 1 thread
147  {
148  WThreadedFunction< FuncType > f( 1, func );
149 
150  TS_ASSERT_EQUALS( f.status(), W_THREADS_INITIALIZED );
151  f.run();
152  TS_ASSERT_EQUALS( f.status(), W_THREADS_RUNNING );
153  f.wait();
154  TS_ASSERT_EQUALS( f.status(), W_THREADS_FINISHED );
155 
156  TS_ASSERT_EQUALS( func->getResult(), 15 );
157  func->reset();
158 
159  f.run();
160  TS_ASSERT_EQUALS( f.status(), W_THREADS_RUNNING );
161  f.wait();
162 
163  TS_ASSERT_EQUALS( func->getResult(), 15 );
164 
165  f.run();
166  TS_ASSERT_EQUALS( f.status(), W_THREADS_RUNNING );
167  f.wait();
168 
169  TS_ASSERT_EQUALS( func->getResult(), 30 );
170  func->reset();
171  }
172  // test 2 threads
173  {
174  WThreadedFunction< FuncType > f( 2, func );
175 
176  TS_ASSERT_EQUALS( f.status(), W_THREADS_INITIALIZED );
177  f.run();
178  TS_ASSERT_EQUALS( f.status(), W_THREADS_RUNNING );
179  f.wait();
180  TS_ASSERT_EQUALS( f.status(), W_THREADS_FINISHED );
181 
182  TS_ASSERT_EQUALS( func->getResult(), 30 );
183  func->reset();
184  }
185  // test 5 threads
186  {
187  WThreadedFunction< FuncType > f( 5, func );
188 
189  TS_ASSERT_EQUALS( f.status(), W_THREADS_INITIALIZED );
190  f.run();
191  TS_ASSERT_EQUALS( f.status(), W_THREADS_RUNNING );
192  f.wait();
193  TS_ASSERT_EQUALS( f.status(), W_THREADS_FINISHED );
194 
195  TS_ASSERT_EQUALS( func->getResult(), 75 );
196  func->reset();
197  }
198  }
199 
200  /**
201  * Status should be set correctly when threads are ordered to stop.
202  */
204  {
205  boost::shared_ptr< FuncType > func( new FuncType( 100000000 ) );
206  WThreadedFunction< FuncType > f( 6, func );
207 
208  TS_ASSERT_EQUALS( f.status(), W_THREADS_INITIALIZED );
209  f.run();
210  TS_ASSERT_EQUALS( f.status(), W_THREADS_RUNNING );
211  f.stop();
212  TS_ASSERT_EQUALS( f.status(), W_THREADS_STOP_REQUESTED );
213  f.wait();
214  TS_ASSERT_EQUALS( f.status(), W_THREADS_ABORTED );
215 
216  TS_ASSERT( func->stopped() );
217  func->reset();
218  }
219 
220  /**
221  * The stop condition should be notified correctly.
222  */
224  {
225  boost::shared_ptr< FuncType > func( new FuncType( 5 ) );
226  WThreadedFunction< FuncType > f( 6, func );
227 
228  TS_ASSERT_EQUALS( f.status(), W_THREADS_INITIALIZED );
229  f.run();
230  TS_ASSERT_EQUALS( f.status(), W_THREADS_RUNNING );
231  f.getThreadsDoneCondition()->wait();
232  TS_ASSERT_EQUALS( f.status(), W_THREADS_FINISHED );
233 
234  TS_ASSERT_EQUALS( func->getResult(), 90 );
235  func->reset();
236  }
237 
238  /**
239  * Exceptions should lead to the status beeing changed to W_THREADS_ABORTED. Also,
240  * exceptions should be forwarded to the exception handler.
241  */
243  {
244  boost::shared_ptr< ExceptionalFuncType > func( new ExceptionalFuncType );
247 
248  m_exceptionCounter.getWriteTicket()->get() = 0;
249 
250  f.run();
251  f.wait();
252 
253  TS_ASSERT_EQUALS( f.status(), W_THREADS_ABORTED );
254  TS_ASSERT_EQUALS( m_exceptionCounter.getReadTicket()->get(), 7 );
255  }
256 
257 private:
258  /**
259  * Exception callback.
260  */
262  {
264  }
265 
266  //! a counter
268 };
269 
270 #endif // WTHREADEDFUNCTION_TEST_H
WSharedObject< bool > m_stopped
thread stopped?
WSharedObject< int > m_result
the result
Creates threads that computes a function in a multithreaded fashion.
FuncType(int value)
Constructor, initialize some stuff.
Tests the WThreadedFunction class.
virtual void run()
Starts the threads.
void operator()(std::size_t, std::size_t, WBoolFlag const &shutdown)
This is the actual thread function.
boost::shared_ptr< int const > m_input
the input data
int getResult()
A method to extract the result.
WSharedObject< int > m_exceptionCounter
a counter
void handleException(WException const &)
Exception callback.
void testExceptionHandling()
Exceptions should lead to the status beeing changed to W_THREADS_ABORTED.
ReadTicket getReadTicket() const
Returns a ticket to get read access to the contained data.
WriteTicket getWriteTicket(bool suppressNotify=false) const
Returns a ticket to get write access to the contained data.
void testStopCondition()
The stop condition should be notified correctly.
void testMultipleThreads()
A function computed by multiple threads should correctly set its status and compute the correct resul...
boost::shared_ptr< WCondition > getThreadsDoneCondition()
Returns a condition that gets fired when all threads have finished.
WThreadedFunctionStatus status()
Get the status of the threads.
void testStopThreads()
Status should be set correctly when threads are ordered to stop.
Basic exception handler.
Definition: WException.h:38
void subscribeExceptionSignal(ExceptionFunction func)
Subscribe a function to an exception signal.
virtual void wait()
Wait for all threads to stop.
void operator()(std::size_t, std::size_t, WBoolFlag &)
The function.
virtual void stop()
Request all threads to stop.
A function that throws exceptions.
bool stopped()
Check if the thread was ordered to stop.