OpenWalnut  1.4.0
WThreadedPerVoxelOperation_test.h
00001 //---------------------------------------------------------------------------
00002 //
00003 // Project: OpenWalnut ( http://www.openwalnut.org )
00004 //
00005 // Copyright 2009 OpenWalnut Community, BSV@Uni-Leipzig and CNCF@MPI-CBS
00006 // For more information see http://www.openwalnut.org/copying
00007 //
00008 // This file is part of OpenWalnut.
00009 //
00010 // OpenWalnut is free software: you can redistribute it and/or modify
00011 // it under the terms of the GNU Lesser General Public License as published by
00012 // the Free Software Foundation, either version 3 of the License, or
00013 // (at your option) any later version.
00014 //
00015 // OpenWalnut is distributed in the hope that it will be useful,
00016 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00017 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00018 // GNU Lesser General Public License for more details.
00019 //
00020 // You should have received a copy of the GNU Lesser General Public License
00021 // along with OpenWalnut. If not, see <http://www.gnu.org/licenses/>.
00022 //
00023 //---------------------------------------------------------------------------
00024 
00025 #ifndef WTHREADEDPERVOXELOPERATION_TEST_H
00026 #define WTHREADEDPERVOXELOPERATION_TEST_H
00027 
00028 #include <vector>
00029 
00030 #include <cxxtest/TestSuite.h>
00031 
00032 #include "../../common/WThreadedFunction.h"
00033 #include "../../common/WLogger.h"
00034 #include "../WDataHandlerEnums.h"
00035 #include "../WDataSetSingle.h"
00036 #include "../WThreadedPerVoxelOperation.h"
00037 
00038 /**
00039  * \class WThreadedPerVoxelOperationTest
00040  *
00041  * Test the WThreadedPerVoxelOperation template.
00042  */
00043 class WThreadedPerVoxelOperationTest : public CxxTest::TestSuite
00044 {
00045     //! the test instance of the template
00046     typedef WThreadedPerVoxelOperation< int, 2, float, 3 > TPVO;
00047 
00048     //! the type of valueset used in the test
00049     typedef TPVO::ValueSetType ValueSetType;
00050 
00051     //! the input type of the test function
00052     typedef TPVO::TransmitType ArrayType;
00053 
00054     //! the output type of the test function
00055     typedef TPVO::OutTransmitType OutArrayType;
00056 
00057 public:
00058     /**
00059      * Setup logger and other stuff for each test.
00060      */
00061     void setUp()
00062     {
00063         WLogger::startup();
00064     }
00065 
00066     /**
00067      * Test if everything gets instantiated correctly or if
00068      * incorrect values properly lead to exceptions.
00069      */
00070     void testInstantiation()
00071     {
00072         boost::shared_ptr< WDataSetSingle > ds = buildTestData();
00073 
00074         TS_ASSERT_THROWS( TPVO t( boost::shared_ptr< WDataSetSingle >(),
00075                                   boost::bind( &WThreadedPerVoxelOperationTest::func, this, _1 ) ), WException );
00076         TS_ASSERT_THROWS( TPVO t( ds, TPVO::FunctionType() ), WException );
00077         TS_ASSERT_THROWS( TPVO t( boost::shared_ptr< WDataSetSingle >( new WDataSetSingle( ds->getValueSet(),
00078                                                                                            boost::shared_ptr< WGrid >() ) ),
00079                                   boost::bind( &WThreadedPerVoxelOperationTest::func, this, _1 ) ), WException );
00080         TS_ASSERT_THROWS( TPVO t( boost::shared_ptr< WDataSetSingle >( new WDataSetSingle( boost::shared_ptr< WValueSetBase >(),
00081                                                                                            ds->getGrid() ) ),
00082                                   boost::bind( &WThreadedPerVoxelOperationTest::func, this, _1 ) ), WException );
00083 
00084         TS_ASSERT_THROWS_NOTHING( TPVO t( ds, boost::bind( &WThreadedPerVoxelOperationTest::func, this, _1 ) ) );
00085 
00086         TPVO t( ds, boost::bind( &WThreadedPerVoxelOperationTest::func, this, _1 ) );
00087 
00088         TS_ASSERT_EQUALS( ds->getGrid(), t.m_grid );
00089     }
00090 
00091     /**
00092      * Now test the whole class as a multithreaded function.
00093      */
00094     void testMultithreadedFunction()
00095     {
00096         boost::shared_ptr< WDataSetSingle > ds = buildTestData();
00097         boost::shared_ptr< TPVO > t( new TPVO( ds, boost::bind( &WThreadedPerVoxelOperationTest::func, this, _1 ) ) );
00098 
00099         m_exception = false;
00100         m_threadsDone = false;
00101 
00102         WThreadedFunction< TPVO > f( 5, t );
00103         f.getThreadsDoneCondition()->subscribeSignal( boost::bind( &WThreadedPerVoxelOperationTest::handleThreadsDone, this ) );
00104         f.subscribeExceptionSignal( boost::bind( &WThreadedPerVoxelOperationTest::handleException, this, _1 ) );
00105 
00106         TS_ASSERT_THROWS_NOTHING( f.run() );
00107         TS_ASSERT_THROWS_NOTHING( f.wait() );
00108         TS_ASSERT( !m_exception );
00109         TS_ASSERT( m_threadsDone );
00110 
00111         boost::shared_ptr< WDataSetSingle > res = t->getResult();
00112 
00113         float shouldBe[] = {
00114                               2.0f,  2.0f,   5.0f,
00115                              -5.0f,  4.0f,  -7.0f,
00116                               8.0f,  8.0f,  23.0f,
00117                              -4.0f,  3.0f,  -6.0f,
00118                             -28.0f, 13.0f, -44.0f,
00119                               3.0f,  4.0f,   9.0f,
00120                              -4.0f,  5.0f,  -4.0f,
00121                               2.0f, -4.0f,  -1.0f
00122                            };
00123 
00124         TS_ASSERT( res );
00125         TS_ASSERT( res->getValueSet() );
00126         TS_ASSERT_EQUALS( res->getGrid(), ds->getGrid() );
00127         TS_ASSERT_EQUALS( res->getValueSet()->dimension(), 3 );
00128         TS_ASSERT_EQUALS( res->getValueSet()->order(), 1 );
00129         TS_ASSERT_EQUALS( res->getValueSet()->size(), 8 );
00130 
00131         boost::shared_ptr< WValueSet< float > > vs = boost::dynamic_pointer_cast< WValueSet< float > >( res->getValueSet() );
00132 
00133         TS_ASSERT( vs );
00134         TS_ASSERT( vs->rawData() );
00135         TS_ASSERT_EQUALS( vs->rawDataVectorPointer()->size(), 24 );
00136         TS_ASSERT_SAME_DATA( vs->rawData(), shouldBe, 8 * 3 * sizeof( float ) );
00137     }
00138 
00139 private:
00140     /**
00141      * The test operation.
00142      *
00143      * \param a The subarray of the input valueset that denotes the voxel's data.
00144      * \return The output data as an array.
00145      */
00146     OutArrayType const func( ArrayType const& a ) const
00147     {
00148         OutArrayType o;
00149         o[ 0 ] = static_cast< float >( a[ 1 ] );
00150         o[ 1 ] = static_cast< float >( a[ 0 ] + 1 );
00151         o[ 2 ] = static_cast< float >( a[ 0 ] + 2 * a[ 1 ] );
00152         return o;
00153     }
00154 
00155     /**
00156      * Build a test dataset.
00157      *
00158      * \return The test dataset.
00159      */
00160     boost::shared_ptr< WDataSetSingle > buildTestData()
00161     {
00162         int a[] = { 1, 2, 3, -5, 7, 8, 2, -4, 12, -28, 3, 3, 4, -4, -5, 2 };
00163         boost::shared_ptr< std::vector< int > > v( new std::vector< int >( a, a + 16 ) );
00164         dataType r = DataType< int >::type;
00165         boost::shared_ptr< ValueSetType > vs( new ValueSetType( 1, 2, v, r ) );
00166         boost::shared_ptr< WGridRegular3D > g( new WGridRegular3D( 2, 2, 2 ) );
00167         return boost::shared_ptr< WDataSetSingle >( new WDataSetSingle( vs, g ) );
00168     }
00169 
00170     /**
00171      * Handle an exception.
00172      */
00173     void handleException( WException const& )
00174     {
00175         m_exception = true;
00176     }
00177 
00178     //! a flag that is used to check if any exceptions were thrown
00179     bool m_exception;
00180 
00181     /**
00182      * This function gets called when all threads are done.
00183      */
00184     void handleThreadsDone()
00185     {
00186         m_threadsDone = true;
00187     }
00188 
00189     //! a flag indicating if all threads are done
00190     bool m_threadsDone;
00191 };
00192 
00193 #endif  // WTHREADEDPERVOXELOPERATION_TEST_H