00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #ifndef WTHREADEDFUNCTION_TEST_H
00026 #define WTHREADEDFUNCTION_TEST_H
00027
00028 #include <string>
00029
00030 #include <cxxtest/TestSuite.h>
00031
00032 #include "../WThreadedFunction.h"
00033 #include "../WSharedObject.h"
00034
00035
00036
00037
00038
00039
00040 class WThreadedFunctionTest : public CxxTest::TestSuite
00041 {
00042
00043
00044
00045 class FuncType
00046 {
00047 public:
00048
00049
00050
00051
00052
00053 FuncType( int value )
00054 : m_input( new int( value ) )
00055 {
00056
00057 m_result.getWriteTicket()->get() = 0;
00058 m_stopped.getWriteTicket()->get() = false;
00059
00060 if( value < 0 )
00061 {
00062 value = -value;
00063 }
00064 }
00065
00066
00067
00068
00069
00070
00071 void operator() ( std::size_t, std::size_t, WBoolFlag const& shutdown )
00072 {
00073 for( int i = 1; i <= *m_input.get() && !shutdown(); ++i )
00074 {
00075 m_result.getWriteTicket()->get() += i;
00076 }
00077 if( shutdown() )
00078 {
00079 m_stopped.getWriteTicket()->get() = true;
00080 }
00081 sleep( 1 );
00082 }
00083
00084
00085
00086
00087
00088
00089 bool stopped()
00090 {
00091 return m_stopped.getReadTicket()->get();
00092 }
00093
00094
00095
00096
00097
00098
00099 int getResult()
00100 {
00101 return m_result.getReadTicket()->get();
00102 }
00103
00104
00105
00106
00107 void reset()
00108 {
00109 m_result.getWriteTicket()->get() = 0;
00110 }
00111
00112 private:
00113
00114
00115 boost::shared_ptr< int const > m_input;
00116
00117
00118 WSharedObject< int > m_result;
00119
00120
00121 WSharedObject< bool > m_stopped;
00122 };
00123
00124
00125
00126
00127 class ExceptionalFuncType
00128 {
00129 public:
00130
00131
00132
00133 void operator() ( std::size_t, std::size_t, WBoolFlag& )
00134 {
00135 throw WException( std::string( "Test!" ) );
00136 }
00137 };
00138
00139 public:
00140
00141
00142
00143
00144 void testMultipleThreads()
00145 {
00146 boost::shared_ptr< FuncType > func( new FuncType( 5 ) );
00147
00148 {
00149 WThreadedFunction< FuncType > f( 1, func );
00150
00151 TS_ASSERT_EQUALS( f.status(), W_THREADS_INITIALIZED );
00152 f.run();
00153 TS_ASSERT_EQUALS( f.status(), W_THREADS_RUNNING );
00154 f.wait();
00155 TS_ASSERT_EQUALS( f.status(), W_THREADS_FINISHED );
00156
00157 TS_ASSERT_EQUALS( func->getResult(), 15 );
00158 func->reset();
00159
00160 f.run();
00161 TS_ASSERT_EQUALS( f.status(), W_THREADS_RUNNING );
00162 f.wait();
00163
00164 TS_ASSERT_EQUALS( func->getResult(), 15 );
00165
00166 f.run();
00167 TS_ASSERT_EQUALS( f.status(), W_THREADS_RUNNING );
00168 f.wait();
00169
00170 TS_ASSERT_EQUALS( func->getResult(), 30 );
00171 func->reset();
00172 }
00173
00174 {
00175 WThreadedFunction< FuncType > f( 2, func );
00176
00177 TS_ASSERT_EQUALS( f.status(), W_THREADS_INITIALIZED );
00178 f.run();
00179 TS_ASSERT_EQUALS( f.status(), W_THREADS_RUNNING );
00180 f.wait();
00181 TS_ASSERT_EQUALS( f.status(), W_THREADS_FINISHED );
00182
00183 TS_ASSERT_EQUALS( func->getResult(), 30 );
00184 func->reset();
00185 }
00186
00187 {
00188 WThreadedFunction< FuncType > f( 5, func );
00189
00190 TS_ASSERT_EQUALS( f.status(), W_THREADS_INITIALIZED );
00191 f.run();
00192 TS_ASSERT_EQUALS( f.status(), W_THREADS_RUNNING );
00193 f.wait();
00194 TS_ASSERT_EQUALS( f.status(), W_THREADS_FINISHED );
00195
00196 TS_ASSERT_EQUALS( func->getResult(), 75 );
00197 func->reset();
00198 }
00199 }
00200
00201
00202
00203
00204 void testStopThreads()
00205 {
00206 boost::shared_ptr< FuncType > func( new FuncType( 100000000 ) );
00207 WThreadedFunction< FuncType > f( 6, func );
00208
00209 TS_ASSERT_EQUALS( f.status(), W_THREADS_INITIALIZED );
00210 f.run();
00211 TS_ASSERT_EQUALS( f.status(), W_THREADS_RUNNING );
00212 f.stop();
00213 TS_ASSERT_EQUALS( f.status(), W_THREADS_STOP_REQUESTED );
00214 f.wait();
00215 TS_ASSERT_EQUALS( f.status(), W_THREADS_ABORTED );
00216
00217 TS_ASSERT( func->stopped() );
00218 func->reset();
00219 }
00220
00221
00222
00223
00224 void testStopCondition()
00225 {
00226 boost::shared_ptr< FuncType > func( new FuncType( 5 ) );
00227 WThreadedFunction< FuncType > f( 6, func );
00228
00229 TS_ASSERT_EQUALS( f.status(), W_THREADS_INITIALIZED );
00230 f.run();
00231 TS_ASSERT_EQUALS( f.status(), W_THREADS_RUNNING );
00232 f.getThreadsDoneCondition()->wait();
00233 TS_ASSERT_EQUALS( f.status(), W_THREADS_FINISHED );
00234
00235 TS_ASSERT_EQUALS( func->getResult(), 90 );
00236 func->reset();
00237 }
00238
00239
00240
00241
00242
00243 void testExceptionHandling()
00244 {
00245 boost::shared_ptr< ExceptionalFuncType > func( new ExceptionalFuncType );
00246 WThreadedFunction< ExceptionalFuncType > f( 7, func );
00247 f.subscribeExceptionSignal( boost::bind( &WThreadedFunctionTest::handleException, this, _1 ) );
00248
00249 m_exceptionCounter.getWriteTicket()->get() = 0;
00250
00251 f.run();
00252 f.wait();
00253
00254 TS_ASSERT_EQUALS( f.status(), W_THREADS_ABORTED );
00255 TS_ASSERT_EQUALS( m_exceptionCounter.getReadTicket()->get(), 7 );
00256 }
00257
00258 private:
00259
00260
00261
00262 void handleException( WException const& )
00263 {
00264 ++m_exceptionCounter.getWriteTicket()->get();
00265 }
00266
00267
00268 WSharedObject< int > m_exceptionCounter;
00269 };
00270
00271 #endif // WTHREADEDFUNCTION_TEST_H