OpenWalnut  1.4.0
WProperties_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 WPROPERTIES_TEST_H
00026 #define WPROPERTIES_TEST_H
00027 
00028 #include <string>
00029 
00030 #include <cxxtest/TestSuite.h>
00031 
00032 #include "../WProperties.h"
00033 #include "../exceptions/WPropertyNotUnique.h"
00034 #include "../exceptions/WPropertyUnknown.h"
00035 #include "../exceptions/WPropertyNameMalformed.h"
00036 
00037 /**
00038  * Test WProperties
00039  */
00040 class WPropertiesTest : public CxxTest::TestSuite
00041 {
00042 public:
00043     /**
00044      * A temporary holder for some value.
00045      */
00046     bool m_testTemporary1;
00047 
00048     /**
00049      * A temporary holder for some value.
00050      */
00051     bool m_testTemporary2;
00052 
00053     /**
00054      * Helper function which simply sets the value above to true. It is used to test some conditions here.
00055      */
00056     void setTemporary1()
00057     {
00058         m_testTemporary1 = true;
00059     }
00060 
00061     /**
00062      * Helper function which simply sets the value above to true. It is used to test some conditions here.
00063      */
00064     void setTemporary2()
00065     {
00066         m_testTemporary2 = true;
00067     }
00068 
00069     /**
00070      * Test instantiation, also test name and description and type (from WPropertyBase)
00071      */
00072     void testInstantiation( void )
00073     {
00074         boost::shared_ptr< WProperties > p;
00075         TS_ASSERT_THROWS_NOTHING( p =  boost::shared_ptr< WProperties >( new WProperties( "hey", "you" ) ) );
00076 
00077         // test names
00078         TS_ASSERT( p->getName() == "hey" );
00079         TS_ASSERT( p->getDescription() == "you" );
00080         TS_ASSERT( p->getType() == PV_GROUP );
00081 
00082         TS_ASSERT_THROWS_NOTHING( p.reset() );
00083     }
00084 
00085     /**
00086      * Test the add features, also tests the type of properties added
00087      */
00088     void testAdd( void )
00089     {
00090         WException::disableBacktrace(); // in tests, turn of backtrace globally
00091 
00092         boost::shared_ptr< WProperties > p( new WProperties( "hey", "you" ) );
00093 
00094         // add some new properties
00095         boost::shared_ptr< WPropertyBase > p1 = p->addProperty( "1", "test1", true );
00096         boost::shared_ptr< WPropertyBase > p2 = p->addProperty( "2", "test2", 1 );
00097         boost::shared_ptr< WPropertyBase > p3 = p->addProperty( "3", "test3", 1.0 );
00098 
00099         // add a malformed (name) property
00100         // The name is malformed since the "/" is used as group separator
00101         TS_ASSERT_THROWS( p->addProperty( "4/5", "test4", 1.0 ), WPropertyNameMalformed );
00102 
00103         // this should have created 3 props
00104         TS_ASSERT( p->m_properties.getReadTicket()->get().size() == 3 );
00105 
00106         // ensure that it has created the correct types:
00107         TS_ASSERT( p1->getType() == PV_BOOL );
00108         TS_ASSERT( p2->getType() == PV_INT );
00109         TS_ASSERT( p3->getType() == PV_DOUBLE );
00110 
00111         // try to add another property with the same name ( regardless of actual type )
00112         TS_ASSERT_THROWS( p->addProperty( "1", "test1", 1.0 ), WPropertyNotUnique );
00113     }
00114 
00115     /**
00116      * Test the clear() method
00117      */
00118     void testClear( void )
00119     {
00120         WException::disableBacktrace(); // in tests, turn of backtrace globally
00121 
00122         boost::shared_ptr< WProperties > p( new WProperties( "hey", "you" ) );
00123 
00124         // add some new properties
00125         boost::shared_ptr< WPropertyBase > p1 = p->addProperty( "1", "test1", true );
00126         boost::shared_ptr< WPropertyBase > p2 = p->addProperty( "2", "test2", 1 );
00127         boost::shared_ptr< WPropertyBase > p3 = p->addProperty( "3", "test3", 1.0 );
00128 
00129         // this should have created 3 props
00130         TS_ASSERT( p->m_properties.getReadTicket()->get().size() == 3 );
00131 
00132         // clear
00133         TS_ASSERT_THROWS_NOTHING( p->clear() );
00134         TS_ASSERT( p->m_properties.getReadTicket()->get().size() == 0 );
00135 
00136         // multiple clear should not cause any error
00137         TS_ASSERT_THROWS_NOTHING( p->clear() );
00138     }
00139 
00140     /**
00141      * Test the removeProperty() method
00142      */
00143     void testRemove( void )
00144     {
00145         WException::disableBacktrace(); // in tests, turn of backtrace globally
00146 
00147         boost::shared_ptr< WProperties > p( new WProperties( "hey", "you" ) );
00148 
00149         // add some new properties
00150         boost::shared_ptr< WPropertyBase > p1 = p->addProperty( "1", "test1", true );
00151         boost::shared_ptr< WPropertyBase > p2 = p->addProperty( "2", "test2", 1 );
00152         boost::shared_ptr< WPropertyBase > p3 = p->addProperty( "3", "test3", 1.0 );
00153 
00154         // this should have created 3 props
00155         TS_ASSERT( p->m_properties.getReadTicket()->get().size() == 3 );
00156 
00157         // remove a property
00158         TS_ASSERT_THROWS_NOTHING( p->removeProperty( p2 ) );
00159         TS_ASSERT( p->m_properties.getReadTicket()->get().size() == 2 );
00160 
00161         // remove a prop which is not in the list
00162         TS_ASSERT_THROWS_NOTHING( p->removeProperty( p2 ) );
00163         TS_ASSERT( p->m_properties.getReadTicket()->get().size() == 2 );
00164     }
00165 
00166     /**
00167      * Tests whether the properties children can be set by the WProperties::set call using a other WProperties instance
00168      */
00169     void testRecursiveSetByProperty( void )
00170     {
00171         WException::disableBacktrace(); // in tests, turn of backtrace globally
00172 
00173         // some props we can use as target
00174         boost::shared_ptr< WProperties > t( new WProperties( "hey", "you" ) );
00175 
00176         // add some new properties
00177         WPropBool tp1 = t->addProperty( "p1", "", true );
00178         WPropInt tp2 = t->addProperty( "p2", "", 1 );
00179         WPropGroup tg1 = t->addPropertyGroup( "g1", "" );
00180         WPropDouble tp3 = tg1->addProperty( "p3", "", 1.0 );
00181         WPropDouble tp4 = t->addProperty( "p4", "", 10.0 );
00182 
00183         // create a group we can use as source
00184         boost::shared_ptr< WProperties > s( new WProperties( "hey", "you" ) );
00185 
00186         // add some new properties
00187         WPropBool sp1 = s->addProperty( "p1", "", false );
00188         WPropInt sp2 = s->addProperty( "p2__", "", 10 ); // NOTE: the name is different
00189         WPropGroup sg1 = s->addPropertyGroup( "g1", "" );
00190         WPropDouble sp3 = sg1->addProperty( "p3", "", 2.0 );
00191         WPropInt sp4 = s->addProperty( "p4", "", 2 );
00192 
00193         // let us set t using the values in s
00194         t->set( s );
00195 
00196         // lets check the values:
00197         // tp1 should be set to the value of sp1
00198         TS_ASSERT( tp1->get() == sp1->get() );
00199         // tp2 should be untouched as no corresponding property exists in s
00200         TS_ASSERT( tp2->get() == 1 );
00201         // the child of the group g1 should be set to sp3
00202         TS_ASSERT( tp3->get() == sp3->get() );
00203         // tp4 must not be sp4 even if the names match. The type is a mismatch
00204         TS_ASSERT( tp4->get() == 10.0 );
00205     }
00206 
00207     /**
00208      * Test the features to find and get properties.
00209      */
00210     void testGetAndExistsAndFind( void )
00211     {
00212         WException::disableBacktrace(); // in tests, turn of backtrace globally
00213 
00214         boost::shared_ptr< WProperties > p( new WProperties( "hey", "you" ) );
00215 
00216         // add some new properties
00217         boost::shared_ptr< WPropertyBase > p1 = p->addProperty( "1", "test1", true );
00218         boost::shared_ptr< WPropertyBase > p2 = p->addProperty( "2", "test2", 1 );
00219         boost::shared_ptr< WPropertyBase > p3 = p->addProperty( "3", "test3", 1.0 );
00220 
00221         /////////////
00222         // exists
00223 
00224         // now, try to check whether a property exists:
00225         TS_ASSERT( p->existsProperty( "1" ) );
00226         TS_ASSERT( !p->existsProperty( "shouldNotBeInTheList" ) );
00227 
00228         /////////////
00229         // find
00230 
00231         // same for find. Find does not throw an exception if the property does not exist! It simply returns it or NULL
00232         boost::shared_ptr< WPropertyBase > someProp;
00233         TS_ASSERT_THROWS_NOTHING( someProp = p->findProperty( "1" ) );
00234         // The property exists -> return value is not NULL
00235         TS_ASSERT( someProp );
00236 
00237         // now for an unexisting one
00238         TS_ASSERT_THROWS_NOTHING( someProp = p->findProperty( "shouldNotBeInTheList" ) );
00239         // The property exists -> return value is not NULL
00240         TS_ASSERT( !someProp );
00241 
00242         /////////////
00243         // get
00244 
00245         // the getProperty method throws an exception if the property has not been found.
00246 
00247         // this one exists -> no exception
00248         TS_ASSERT_THROWS_NOTHING( someProp = p->getProperty( "1" ) );
00249         TS_ASSERT( someProp );
00250 
00251         // this one does not exist
00252         TS_ASSERT_THROWS( someProp = p->getProperty( "shouldNotBeInTheList" ), WPropertyUnknown );
00253     }
00254 
00255     /**
00256      * Test the recursive search mechanism.
00257      */
00258     void testGetAndExistsAndFindRecursive( void )
00259     {
00260         boost::shared_ptr< WProperties > p( new WProperties( "hey", "you" ) );
00261         boost::shared_ptr< WProperties > psub = p->addPropertyGroup( "heySub", "you" );
00262 
00263         // add some new properties
00264         boost::shared_ptr< WPropertyBase > p1 = p->addProperty( "1", "test1", true );
00265         boost::shared_ptr< WPropertyBase > p2 = p->addProperty( "2", "test2", 1 );
00266         boost::shared_ptr< WPropertyBase > p3 = psub->addProperty( "3", "test3", 1.0 );
00267         boost::shared_ptr< WPropertyBase > p4 = psub->addProperty( "4", "test4", std::string( "hello" ) );
00268 
00269         // insert a prop with the same name as a sub property
00270         TS_ASSERT_THROWS( p->addProperty( "heySub", "test1", true ), WPropertyNotUnique );
00271 
00272         /////////////
00273         // exists
00274 
00275         // try to find a property of a group in the parent: should fail
00276         TS_ASSERT( !p->existsProperty( "3" ) );
00277         TS_ASSERT( !p->existsProperty( "4" ) );
00278         TS_ASSERT( psub->existsProperty( "3" ) );
00279         TS_ASSERT( psub->existsProperty( "4" ) );
00280         TS_ASSERT( !psub->existsProperty( "1" ) );
00281         TS_ASSERT( !psub->existsProperty( "2" ) );
00282 
00283         // search it with the proper name:
00284         TS_ASSERT( p->existsProperty( "heySub/3" ) );
00285         TS_ASSERT( !p->existsProperty( "heySub/1" ) );
00286 
00287         /////////////
00288         // find
00289 
00290         // search it with the proper name:
00291         TS_ASSERT( p3 == p->findProperty( "heySub/3" ) );
00292         TS_ASSERT( p4 == p->findProperty( "heySub/4" ) );
00293 
00294         // ensure nothing is found if wrong name is specified
00295         TS_ASSERT( boost::shared_ptr< WPropertyBase >() == p->findProperty( "heySub/1" ) );
00296 
00297         /////////////
00298         // get
00299 
00300         TS_ASSERT_THROWS_NOTHING( p->getProperty( "heySub/3" ) );
00301         TS_ASSERT_THROWS_NOTHING( p->getProperty( "heySub/4" ) );
00302 
00303         // ensure nothing is found if wrong name is specified
00304         TS_ASSERT_THROWS( p->getProperty( "heySub/1" ), WPropertyUnknown );
00305     }
00306 
00307     /**
00308      * Tests the cloning functionality.
00309      */
00310     void testClone()
00311     {
00312         /////////////////////
00313         // Clone
00314 
00315         boost::shared_ptr< WProperties > orig( new WProperties( "hey", "you" ) );
00316         boost::shared_ptr< WProperties > clone = orig->clone()->toPropGroup();
00317 
00318         // test that toPropGroup worked and both are different
00319         TS_ASSERT( clone.get() );
00320         TS_ASSERT( orig != clone );
00321 
00322         /////////////////////
00323         // Conditions
00324 
00325         // is there a new condition? This has to be the case, this mainly situated in WPropertyBase
00326         TS_ASSERT( orig->getUpdateCondition() != clone->getUpdateCondition() );
00327 
00328         // update of property list does not modify the original
00329         clone->addProperty( "1", "test1", 1.0 );
00330         TS_ASSERT( clone->m_properties.getReadTicket()->get().size() == 1 );
00331         TS_ASSERT( orig->m_properties.getReadTicket()->get().size() == 0 );
00332 
00333         // does the condition fire on add?
00334         // first, register some callbacks to test it
00335         m_testTemporary1 = false;
00336         m_testTemporary2 = false;
00337         orig->getUpdateCondition()->subscribeSignal( boost::bind( &WPropertiesTest::setTemporary1, this ) );
00338         clone->getUpdateCondition()->subscribeSignal( boost::bind( &WPropertiesTest::setTemporary2, this ) );
00339 
00340         // add a bool property -> conditions fired?
00341         clone->addProperty( "2", "test2", false );
00342 
00343         // the first should not fire, but the condition of the clone
00344         TS_ASSERT( m_testTemporary1 == false );
00345         TS_ASSERT( m_testTemporary2 == true );
00346 
00347         // the same thing but vice versa
00348         m_testTemporary1 = false;
00349         m_testTemporary2 = false;
00350         orig->addProperty( "1", "test1", false );
00351         // this time, the first should fire but not the second
00352         TS_ASSERT( m_testTemporary2 == false );
00353         TS_ASSERT( m_testTemporary1 == true );
00354 
00355         /////////////////////
00356         // cloned list
00357 
00358         // the clone now contains some properties -> clone it again and check the list of contained properties
00359         boost::shared_ptr< WProperties > cloneClone = clone->clone()->toPropGroup();
00360 
00361         // same size?
00362         TS_ASSERT( clone->m_properties.getReadTicket()->get().size() == 2 );
00363         TS_ASSERT( cloneClone->m_properties.getReadTicket()->get().size() == 2 );
00364 
00365         WProperties::PropertySharedContainerType::ReadTicket t = clone->getProperties();
00366 
00367         // iterate the original and check that there exists a cloned property in the cloned one
00368         for( WProperties::PropertyConstIterator iter = t->get().begin(); iter != t->get().end(); ++iter )
00369         {
00370             // ensure there is a corresponding property in cloneClone
00371             boost::shared_ptr< WPropertyBase > p = cloneClone->findProperty( ( *iter )->getName() );
00372             TS_ASSERT( p ); // found?
00373             TS_ASSERT( p != ( *iter ) ); // is it really a clone? (the cloning functionality of WPropertyVariable is tested separately
00374         }
00375     }
00376 };
00377 
00378 #endif  // WPROPERTIES_TEST_H
00379 
00380