OpenWalnut  1.5.0dev
WWorkerThread_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 WWORKERTHREAD_TEST_H
26 #define WWORKERTHREAD_TEST_H
27 
28 #include <memory>
29 #include <string>
30 
31 #include <cxxtest/TestSuite.h>
32 
33 #include "../WSharedObject.h"
34 #include "../WWorkerThread.h"
35 
36 /**
37  * Tests the WWorkerThread class.
38  */
39 class WWorkerThreadTest : public CxxTest::TestSuite
40 {
41  /**
42  * A threaded function.
43  */
44  class FuncType
45  {
46  public:
47  /**
48  * Constructor, initialize some stuff.
49  *
50  * \param value An int value.
51  */
52  FuncType( int value ) // NOLINT
53  : m_input( new int( value ) ) // NOLINT
54  {
55  // init stuff here
56  m_result.getWriteTicket()->get() = 0;
57  m_stopped.getWriteTicket()->get() = false;
58 
59  if( value < 0 )
60  {
61  value = -value;
62  }
63  }
64 
65  /**
66  * This is the actual thread function.
67  *
68  * \param shutdown A flag indicating the thread is supposed to stop.
69  */
70  void operator() ( std::size_t, std::size_t, WBoolFlag const& shutdown )
71  {
72  for( int i = 1; i <= *m_input.get() && !shutdown(); ++i )
73  {
74  m_result.getWriteTicket()->get() += i;
75  }
76  if( shutdown() )
77  {
78  m_stopped.getWriteTicket()->get() = true;
79  }
80  sleep( 1 );
81  }
82 
83  /**
84  * Check if the thread was ordered to stop.
85  * \return true, if the thread was ordered to stop
86  */
87  bool stopped()
88  {
89  return m_stopped.getReadTicket()->get();
90  }
91 
92  /**
93  * A method to extract the result.
94  *
95  * \return The result of the threaded computation.
96  */
97  int getResult()
98  {
99  return m_result.getReadTicket()->get();
100  }
101 
102  /**
103  * Reset everything.
104  */
105  void reset()
106  {
107  m_result.getWriteTicket()->get() = 0;
108  }
109 
110  private:
111  //! the input data
112  std::shared_ptr< int const > m_input;
113 
114  //! the result
116 
117  //! thread stopped?
119  };
120 
121  /**
122  * A function that throws exceptions.
123  */
125  {
126  public:
127  /**
128  * The function.
129  */
130  void operator() ( std::size_t, std::size_t, WBoolFlag& )
131  {
132  throw WException( std::string( "Test!" ) );
133  }
134  };
135 
136 public:
137  /**
138  * Test if calculation with a single thread works.
139  */
140  void testSingleThread( void )
141  {
142  m_stopped = false;
143 
144  std::shared_ptr< FuncType > func( new FuncType( 6 ) );
145  WWorkerThread< FuncType > w( func, 0, 1 );
146  w.subscribeStopSignal( boost::bind( &WWorkerThreadTest::stopTestDone, this ) );
147 
148  w.run();
149  w.wait();
150 
151  // the result should be 1 + 2 + .. + 6 = 21
152  TS_ASSERT_EQUALS( func->getResult(), 21 );
153  TS_ASSERT_EQUALS( m_stopped, true );
154  }
155 
156  /**
157  * Test if the thread gets shutdown correctly.
158  */
160  {
161  m_stopped = false;
162 
163  std::shared_ptr< FuncType > func( new FuncType( 100000000 ) );
164  WWorkerThread< FuncType > w( func, 0, 1 );
165  w.subscribeStopSignal( boost::bind( &WWorkerThreadTest::stopTestDone, this ) );
166 
167  w.run();
168  w.requestStop();
169  w.wait();
170 
171  TS_ASSERT( func->stopped() );
172  TS_ASSERT_EQUALS( m_stopped, true );
173  }
174 
175  /**
176  * Test if multiple threads correctly compute the result.
177  */
179  {
180  std::shared_ptr< FuncType > func( new FuncType( 5 ) );
181  WWorkerThread< FuncType > w0( func, 0, 3 );
182  WWorkerThread< FuncType > w1( func, 1, 3 );
183  WWorkerThread< FuncType > w2( func, 2, 3 );
184 
185  w0.run();
186  w1.run();
187  w2.run();
188  w0.wait();
189  w1.wait();
190  w2.wait();
191 
192  TS_ASSERT_EQUALS( func->getResult(), 45 );
193  }
194 
195 // unset the WASSERT_AS_CASSERT flag (just in case), so WAssert throws a WException
196 #ifdef WASSERT_AS_CASSERT
197 #define WASSERT_FLAG_CHANGED
198 #undef WASSERT_AS_CASSERT
199 #endif
200  /**
201  * Providing a zero-Pointer as function should cause an exception.
202  */
204  {
205  std::shared_ptr< FuncType > func;
206  TS_ASSERT_THROWS( WWorkerThread< FuncType > w( func, 0, 1 ), const WException& );
207  }
208 
209  /**
210  * An invalid thread id should cause an exception.
211  */
213  {
214  std::shared_ptr< FuncType > func( new FuncType( 5 ) );
215  TS_ASSERT_THROWS( WWorkerThread< FuncType > w( func, 1, 0 ), const WException& );
216  }
217 // restore WASSERT_AS_CASSERT flag
218 #ifdef WASSERT_FLAG_CHANGED
219 #define WASSERT_AS_CASSERT
220 #undef WASSERT_FLAG_CHANGED
221 #endif
222 
223  /**
224  * Test if exceptions get handled correctly.
225  */
227  {
228  m_exceptionHandled = false;
229 
230  std::shared_ptr< ExceptionalFuncType > func( new ExceptionalFuncType );
231  WWorkerThread< ExceptionalFuncType > w( func, 0, 1 );
232  w.subscribeExceptionSignal( boost::bind( &WWorkerThreadTest::handleException, this, boost::placeholders::_1 ) );
233 
234  w.run();
235  w.wait();
236 
237  TS_ASSERT_EQUALS( m_exceptionHandled, true );
238  }
239 
240 private:
241  /**
242  * A utility function.
243  */
245  {
246  m_stopped = true;
247  }
248 
249  /**
250  * Another one.
251  *
252  * \param e An exception.
253  */
254  void handleException( WException const& e )
255  {
256  if( strcmp( e.what(), "Test!" ) == 0 )
257  {
258  m_exceptionHandled = true;
259  }
260  }
261 
262  //! the thread was stopped?
263  bool m_stopped;
264 
265  //! the exception was handled?
267 };
268 
269 #endif // WWORKERTHREAD_TEST_H
Basic exception handler.
Definition: WException.h:39
virtual const char * what() const
Returns the message string set on throw.
Definition: WException.cpp:90
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.
virtual void run()
Run thread.
virtual void requestStop()
This method's purpose is to request a stop without waiting for it.
void wait(bool requestFinish=false)
Wait for the thread to be finished.
A function that throws exceptions.
void operator()(std::size_t, std::size_t, WBoolFlag &)
The function.
std::shared_ptr< int const > m_input
the input data
WSharedObject< int > m_result
the result
bool stopped()
Check if the thread was ordered to stop.
FuncType(int value)
Constructor, initialize some stuff.
int getResult()
A method to extract the result.
void reset()
Reset everything.
void operator()(std::size_t, std::size_t, WBoolFlag const &shutdown)
This is the actual thread function.
WSharedObject< bool > m_stopped
thread stopped?
Tests the WWorkerThread class.
void testSingleThread(void)
Test if calculation with a single thread works.
void testThreadId()
An invalid thread id should cause an exception.
void testNoFunction()
Providing a zero-Pointer as function should cause an exception.
void handleException(WException const &e)
Another one.
bool m_exceptionHandled
the exception was handled?
void testStopThread()
Test if the thread gets shutdown correctly.
bool m_stopped
the thread was stopped?
void testExceptions()
Test if exceptions get handled correctly.
void stopTestDone()
A utility function.
void testMultipleThreads()
Test if multiple threads correctly compute the result.
A worker thread that belongs to a.
Definition: WWorkerThread.h:43
void subscribeStopSignal(StopFunction func)
Subscribe a function to the stop signal.
void subscribeExceptionSignal(ExceptionFunction func)
Subscribe a function to the exception signal.