OpenWalnut  1.4.0
WPropertyVariable_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 WPROPERTYVARIABLE_TEST_H
00026 #define WPROPERTYVARIABLE_TEST_H
00027 
00028 #include <string>
00029 
00030 #include <cxxtest/TestSuite.h>
00031 
00032 #include "../WPropertyVariable.h"
00033 #include "../constraints/WPropertyConstraintMin.h"
00034 #include "../constraints/WPropertyConstraintMax.h"
00035 
00036 #include "../exceptions/WPropertyNotUnique.h"
00037 #include "../exceptions/WPropertyUnknown.h"
00038 #include "../exceptions/WPropertyNameMalformed.h"
00039 
00040 /**
00041  * Test WPropertyVariable
00042  */
00043 class WPropertyVariableTest : public CxxTest::TestSuite
00044 {
00045 public:
00046     /**
00047      * A temporary holder for some value.
00048      */
00049     bool m_testTemporary1;
00050 
00051     /**
00052      * A temporary holder for some value.
00053      */
00054     bool m_testTemporary2;
00055 
00056     /**
00057      * Helper function which simply sets the value above to true. It is used to test some conditions here.
00058      */
00059     void setTemporary1()
00060     {
00061         m_testTemporary1 = true;
00062     }
00063 
00064     /**
00065      * Helper function which simply sets the value above to true. It is used to test some conditions here.
00066      */
00067     void setTemporary2()
00068     {
00069         m_testTemporary2 = true;
00070     }
00071 
00072     /**
00073      * Test instantiation, also test name and description and type (from WPropertyBase)
00074      */
00075     void testInstantiation( void )
00076     {
00077         boost::shared_ptr< WPropertyVariable< bool > > p;
00078         TS_ASSERT_THROWS_NOTHING( p =  boost::shared_ptr< WPropertyVariable< bool > >( new WPropertyVariable< bool >( "hey", "you", false ) ) );
00079 
00080         // test names
00081         TS_ASSERT( p->getName() == "hey" );
00082         TS_ASSERT( p->getDescription() == "you" );
00083         TS_ASSERT( p->getType() == PV_BOOL );
00084 
00085         TS_ASSERT_THROWS_NOTHING( p.reset() );
00086     }
00087 
00088     /**
00089      * Tests that only properties with proper names can be created
00090      */
00091     void testNameConvention( void )
00092     {
00093         WException::disableBacktrace(); // in tests, turn of backtrace globally
00094 
00095         boost::shared_ptr< WPropertyVariable< bool > > p;
00096         TS_ASSERT_THROWS( p = boost::shared_ptr< WPropertyVariable< bool > >( new WPropertyVariable< bool >( "hey/you", "you", false ) ),
00097                           WPropertyNameMalformed );
00098     }
00099 
00100     /**
00101      * Tests the cloning functionality.
00102      */
00103     void testClone()
00104     {
00105         WException::disableBacktrace(); // in tests, turn of backtrace globally
00106 
00107         /////////////////////////
00108         // Create an original
00109 
00110         // create an int property
00111         boost::shared_ptr< WPropertyVariable< int > > p =
00112             boost::shared_ptr< WPropertyVariable< int > >( new WPropertyVariable< int >( "hey", "you", false ) );
00113         // add a min/max prop
00114         WPropertyVariable< int >::PropertyConstraintMin cmin = p->setMin( 0 );
00115         WPropertyVariable< int >::PropertyConstraintMax cmax = p->setMax( 9 );
00116         p->set( 5 );
00117 
00118         /////////////////////////
00119         // Clone it
00120 
00121         boost::shared_ptr< WPropertyVariable< int > > clone = p->clone()->toPropInt();
00122 
00123         // some rudimentary tests (from WPropertyBase)
00124         TS_ASSERT( clone );
00125         TS_ASSERT( clone->getType() == PV_INT );
00126         TS_ASSERT( clone->getName() == p->getName() );
00127         TS_ASSERT( clone->getDescription() == p->getDescription() );
00128         TS_ASSERT( clone->getPurpose() == p->getPurpose() );
00129 
00130         // equal value?
00131         TS_ASSERT( p->get() == clone->get() );
00132 
00133         // different conditions?
00134         TS_ASSERT( p->getContraintsChangedCondition() != clone->getContraintsChangedCondition() );
00135         TS_ASSERT( p->getUpdateCondition() != clone->getUpdateCondition() );        // this is from WPropertyBase
00136 
00137         // cloned constraints?
00138         TS_ASSERT( p->getMin() != clone->getMin() ); // the constraints of course need to be cloned too
00139         TS_ASSERT( p->getMax() != clone->getMax() ); // the constraints of course need to be cloned too
00140 
00141         TS_ASSERT( p->getMin()->getMin() == clone->getMin()->getMin()  ); // but their values need to be the same. This somehow tests the clone
00142                                                                           // feature of WPropertyConstrainMin and Max
00143         TS_ASSERT( p->getMax()->getMax() == clone->getMax()->getMax()  ); // but their values need to be the same. This somehow tests the clone
00144                                                                           // feature of WPropertyConstrainMin and Max
00145 
00146         // check independence of both update conditions
00147         p->getUpdateCondition()->subscribeSignal( boost::bind( &WPropertyVariableTest::setTemporary1, this ) );
00148         clone->getUpdateCondition()->subscribeSignal( boost::bind( &WPropertyVariableTest::setTemporary2, this ) );
00149 
00150         // set the value of the clone -> fire condition of clone but not of original
00151         m_testTemporary1 = false;
00152         m_testTemporary2 = false;
00153         clone->set( 4 );
00154         TS_ASSERT( !m_testTemporary1 );
00155         TS_ASSERT( m_testTemporary2 );
00156 
00157         // and test vice versa
00158         m_testTemporary1 = false;
00159         m_testTemporary2 = false;
00160         p->set( 2 );
00161         TS_ASSERT( m_testTemporary1 );
00162         TS_ASSERT( !m_testTemporary2 );
00163 
00164         // do the same for constraints
00165         m_testTemporary1 = false;
00166         m_testTemporary2 = false;
00167         clone->removeConstraint( PC_MIN );
00168         TS_ASSERT( !m_testTemporary1 );
00169         TS_ASSERT( m_testTemporary2 );
00170 
00171         // and vice versa
00172         m_testTemporary1 = false;
00173         m_testTemporary2 = false;
00174         p->removeConstraint( PC_MIN );
00175         TS_ASSERT( m_testTemporary1 );
00176         TS_ASSERT( !m_testTemporary2 );
00177     }
00178 
00179     /**
00180      * Test min/max functionality, including tests for set(), accept() and ensureValidity.
00181      */
00182     void testMinMaxWithSetAndAccept()
00183     {
00184         WException::disableBacktrace(); // in tests, turn of backtrace globally
00185 
00186         // create an int property
00187         boost::shared_ptr< WPropertyVariable< int > > p =
00188             boost::shared_ptr< WPropertyVariable< int > >( new WPropertyVariable< int >( "hey", "you", false ) );
00189 
00190         // by default there should be no min/max property set. Only IF the property was created using a WProperties::addProperty.
00191         WPropertyVariable< int >::PropertyConstraintMin cmin = p->getMin();
00192         WPropertyVariable< int >::PropertyConstraintMax cmax = p->getMax();
00193         TS_ASSERT( !cmin );
00194         TS_ASSERT( !cmax );
00195 
00196         // does set() and accept work if no constraints are there?
00197         TS_ASSERT( p->set( 123 ) );
00198         TS_ASSERT( p->get() == 123 );
00199         TS_ASSERT( p->accept( 12345 ) );
00200 
00201         // add a min prop
00202         cmin = p->setMin( 10 );
00203         cmax = p->setMax( 15 );
00204         TS_ASSERT( cmin );
00205         TS_ASSERT( cmax );
00206 
00207         // compare that getMin/max returns the correct ones
00208         TS_ASSERT( cmin == p->getMin() );
00209         TS_ASSERT( cmax == p->getMax() );
00210 
00211         // try to set a valid value
00212         TS_ASSERT( p->set( 10 ) );
00213         TS_ASSERT( p->get() == 10 );
00214 
00215         // try to set an invalid value
00216         TS_ASSERT( !p->set( 9 ) );
00217         TS_ASSERT( p->get() == 10 );
00218         TS_ASSERT( !p->set( 16 ) );
00219         TS_ASSERT( p->get() == 10 );
00220 
00221         // add another min value. Is the first one removed?
00222         p->setMin( 5 );
00223         p->setMax( 20 );
00224         p->m_constraints->getReadTicket()->get().size();
00225 
00226         // try to set a valid value, which was invalid previously
00227         TS_ASSERT( p->set( 9 ) );
00228         TS_ASSERT( p->get() == 9 );
00229         TS_ASSERT( p->set( 16 ) );
00230         TS_ASSERT( p->get() == 16 );
00231 
00232         // finally, test ensureValidity
00233         // this function helps to restore a property to a valid state after a constraint change
00234 
00235         // currently, the state of p is valid. So ensureValidity should do nothing
00236         TS_ASSERT( p->ensureValidity( 10 ) );
00237         TS_ASSERT( p->get() == 16 );
00238 
00239         // change the min constraint so that 16 gets invalid
00240         TS_ASSERT( p->isValid() );
00241         p->setMin( 17 );
00242         TS_ASSERT( !p->isValid() );
00243         TS_ASSERT( p->get() == 16 );    // setting a new constraint should NOT modify the current value
00244 
00245         // use ensureValidity
00246         TS_ASSERT( p->ensureValidity( 18 ) );
00247         TS_ASSERT( p->get() == 18 );
00248         TS_ASSERT( p->isValid() );
00249 
00250         // what happens if the ensureValidity parameter itself is invalid? It should return false
00251         p->setMin( 19 );
00252         TS_ASSERT( !p->ensureValidity( 16 ) );    // 16 is invalid since minimum is 19
00253         TS_ASSERT( !p->isValid() );                // the value should stay invalid
00254         TS_ASSERT( p->get() == 18 );
00255     }
00256 
00257     /**
00258      * Tests constraint management. Especially add,replace,remove,count,getFirst.
00259      */
00260     void testConstraintManagement( void )
00261     {
00262         WException::disableBacktrace(); // in tests, turn of backtrace globally
00263 
00264         // create an int property
00265         boost::shared_ptr< WPropertyVariable< int > > p =
00266             boost::shared_ptr< WPropertyVariable< int > >( new WPropertyVariable< int >( "hey", "you", false ) );
00267 
00268         // register a condition callback
00269         p->getUpdateCondition()->subscribeSignal( boost::bind( &WPropertyVariableTest::setTemporary1, this ) );
00270 
00271         ////////////////////////////////////
00272         // add
00273 
00274         // add a constraint
00275         m_testTemporary1 = false;
00276         WPropertyVariable< int >::PropertyConstraintMin cmin =
00277             boost::shared_ptr< WPropertyConstraintMin< int > >( new  WPropertyConstraintMin< int >( 10 ) );
00278         p->addConstraint( cmin );
00279         TS_ASSERT( p->m_constraints->getReadTicket()->get().size() == 1 );
00280         TS_ASSERT( m_testTemporary1 );    // the update condition has to be fired on constraint updates
00281 
00282         ////////////////////////////////////
00283         // count, getFirst
00284 
00285         // count constraints
00286         m_testTemporary1 = false;
00287         TS_ASSERT( p->countConstraint( PC_MIN ) == 1 );
00288         TS_ASSERT( p->countConstraint( PC_MAX ) == 0 );
00289 
00290         // get first constraint should return the first constraint of a specified type
00291         TS_ASSERT( cmin == p->getFirstConstraint( PC_MIN ) );
00292         TS_ASSERT( !p->getFirstConstraint( PC_MAX ) );  // there is no max constraint
00293         TS_ASSERT( !m_testTemporary1 );      // these operations should not fire the condition
00294 
00295         ////////////////////////////////////
00296         // replace
00297 
00298         // replace a constraint
00299         m_testTemporary1 = false;
00300         WPropertyVariable< int >::PropertyConstraintMax cmax =
00301             boost::shared_ptr< WPropertyConstraintMax< int > >( new  WPropertyConstraintMax< int >( 15 ) );
00302 
00303         // replace non existent type
00304         TS_ASSERT_THROWS_NOTHING( p->replaceConstraint( cmax, PC_MAX ) );  // since there is no max constraint, replace acts like addConstraint
00305         TS_ASSERT( m_testTemporary1 );
00306 
00307         // replace existent type ( note: there is now a min and a max constraint )
00308         m_testTemporary1 = false;
00309         WPropertyVariable< int >::PropertyConstraintMax cmax2 =
00310             boost::shared_ptr< WPropertyConstraintMax< int > >( new  WPropertyConstraintMax< int >( 20 ) );
00311         p->replaceConstraint( cmax2, PC_MAX );
00312         TS_ASSERT( m_testTemporary1 );
00313         TS_ASSERT( cmax2 == p->getFirstConstraint( PC_MAX ) );
00314 
00315         ////////////////////////////////////
00316         // remove
00317 
00318         // removeConstraints should not fire the condition if nothing is removed
00319         m_testTemporary1 = false;
00320         p->removeConstraint( PC_NOTEMPTY );
00321         TS_ASSERT( !m_testTemporary1 );
00322 
00323         // remove max constraint
00324         m_testTemporary1 = false;
00325         TS_ASSERT( p->countConstraint( PC_MAX ) == 1 );
00326         p->removeConstraint( PC_MAX );
00327         TS_ASSERT( p->countConstraint( PC_MAX ) == 0 );
00328         TS_ASSERT( m_testTemporary1 );  // should have fired
00329 
00330         // remove min constraint with pointer
00331         m_testTemporary1 = false;
00332         TS_ASSERT( p->countConstraint( PC_MIN ) == 1 );
00333         p->removeConstraint( cmin );
00334         TS_ASSERT( p->countConstraint( PC_MIN ) == 0 );
00335         TS_ASSERT( m_testTemporary1 );  // should have fired
00336     }
00337 };
00338 
00339 #endif  // WPROPERTYVARIABLE_TEST_H
00340