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