$search
00001 /*************************************************************************** 00002 tag: Peter Soetens Tue Apr 5 16:53:26 CEST 2005 property_test.cpp 00003 00004 property_test.cpp - description 00005 ------------------- 00006 begin : Tue April 05 2005 00007 copyright : (C) 2005 Peter Soetens 00008 email : peter.soetens@mech.kuleuven.ac.be 00009 00010 *************************************************************************** 00011 * * 00012 * This program is free software; you can redistribute it and/or modify * 00013 * it under the terms of the GNU General Public License as published by * 00014 * the Free Software Foundation; either version 2 of the License, or * 00015 * (at your option) any later version. * 00016 * * 00017 ***************************************************************************/ 00018 00019 #include <typeinfo> 00020 #include <marsh/PropertyBagIntrospector.hpp> 00021 #include <internal/DataSourceTypeInfo.hpp> 00022 #include <types/PropertyDecomposition.hpp> 00023 #include <Property.hpp> 00024 #include <PropertyBag.hpp> 00025 00026 #include "unit.hpp" 00027 00028 class PropertyTest 00029 { 00030 public: 00031 PropertyBag bag1; 00032 PropertyBag bag2; 00033 PropertyBase* pb; 00034 Property<int>* pi1; 00035 Property<int>* pi2; 00036 Property<int>* pi1ref; 00037 Property<int>* pi2ref; 00038 int intref; 00039 00040 PropertyBag bag; 00041 Property<float> pf; 00042 Property<double> pd; 00043 Property<std::string> ps; 00044 Property<char> pc; 00045 Property<char> pc1; 00046 Property<char> pc2; 00047 Property<char> pc1ref; 00048 Property<char> pc2ref; 00049 00050 Property<PropertyBag> subbag1; 00051 Property<PropertyBag> subbag2; 00052 00053 PropertyTest() 00054 : pf("pf","pfd", -1.0),pd("pd","pdd", +1.0), 00055 ps("ps","psd", "std::string"), 00056 pc("pc","pcd", 'c'), 00057 pc1("pc1","pcd1", 'a'), 00058 pc2("pc2","pcd1", 'b'), 00059 subbag1("s1", "s1d"),subbag2("s2", "s2d") 00060 { 00061 intref = 99; 00062 pi1 = new Property<int>("pi1","pi1d", 0 ); 00063 pi2 = new Property<int>("pi2","pi2d", 0 ); 00064 pi1ref = dynamic_cast< Property<int>* >( pi1->clone() ); 00065 pi2ref = dynamic_cast< Property<int>* >( pi2->clone() ); 00066 00067 pc1ref = pc1; 00068 pc2ref = pc2; 00069 00070 bag.add( pi1 ); 00071 bag.add( pi2 ); 00072 bag.add( &subbag1 ); 00073 subbag1.set().add( &subbag2 ); 00074 subbag1.set().add( &pf ); 00075 subbag1.set().add( &pd ); 00076 00077 subbag2.set().add( &ps ); 00078 subbag2.set().add( &pc ); 00079 00080 } 00081 ~PropertyTest() 00082 { 00083 delete pi1; 00084 delete pi2; 00085 delete pi1ref; 00086 delete pi2ref; 00087 } 00088 }; 00089 00090 bool operator==(const std::vector<double>& a, const std::vector<double>& b) 00091 { 00092 if ( a.size() != b.size() ) { 00093 log(Error) << "Wrong vector sizes : " << a.size() <<" "<< b.size()<<endlog(); 00094 return false; 00095 } 00096 for(unsigned int i =0; i != a.size(); ++i) 00097 { 00098 if (a[i] != b[i]) { 00099 log(Error) << "Wrong vector element: "<<a[i]<<" != "<<b[i]<<" i:" << i<<endlog(); 00100 return false; 00101 } 00102 } 00103 return true; 00104 } 00105 00106 00107 BOOST_FIXTURE_TEST_SUITE( PropertyTestSuite, PropertyTest ) 00108 00109 BOOST_AUTO_TEST_CASE( testCopyUpdate ) 00110 { 00111 *pi1 = intref; 00112 *pi2 = 0; 00113 00114 // update semantics 00115 pi1->update( *pi2 ); 00116 BOOST_REQUIRE_EQUAL( pi2->get(), pi1->get() ); 00117 BOOST_REQUIRE_EQUAL( pi1ref->getName(), pi1->getName() ); 00118 BOOST_REQUIRE_EQUAL( pi1ref->getDescription(), pi1->getDescription() ); 00119 *pi2 = 0; 00120 00121 // update with PropertyBase. 00122 BOOST_CHECK( pi1->update( pi2 ) ); 00123 BOOST_REQUIRE_EQUAL( pi2->get(), pi1->get() ); 00124 BOOST_REQUIRE_EQUAL( pi1ref->getName(), pi1->getName() ); 00125 BOOST_REQUIRE_EQUAL( pi1ref->getDescription(), pi1->getDescription() ); 00126 *pi2 = 0; 00127 00128 // copy semantics 00129 pi1->copy( *pi2 ); 00130 BOOST_REQUIRE_EQUAL( pi2->get(), pi1->get() ); 00131 BOOST_REQUIRE_EQUAL( pi2ref->getName(), pi1->getName() ); 00132 BOOST_REQUIRE_EQUAL( pi2ref->getDescription(), pi1->getDescription() ); 00133 pi1->copy( *pi1ref ); 00134 00135 // copy with PropertyBase. 00136 BOOST_CHECK( pi1->copy( pi2 ) ); 00137 BOOST_REQUIRE_EQUAL( pi2->get(), pi1->get() ); 00138 BOOST_REQUIRE_EQUAL( pi2ref->getName(), pi1->getName() ); 00139 BOOST_REQUIRE_EQUAL( pi2ref->getDescription(), pi1->getDescription() ); 00140 pi1->copy( pi1ref ); 00141 } 00142 00143 BOOST_AUTO_TEST_CASE( testCopyUpdateChar ) 00144 { 00145 pc2 = 'H'; 00146 PropertyBase* pcb2 = &pc2; 00147 00148 // update semantics 00149 pc1.update( pc2 ); 00150 BOOST_REQUIRE_EQUAL( pc2.get(), pc1.get() ); 00151 BOOST_REQUIRE_EQUAL( pc1ref.getName(), pc1.getName() ); 00152 BOOST_REQUIRE_EQUAL( pc1ref.getDescription(), pc1.getDescription() ); 00153 pc2 = 'e'; 00154 00155 // update with PropertyBase. 00156 BOOST_CHECK( pc1.update( pcb2 ) ); 00157 BOOST_REQUIRE_EQUAL( pc2.get(), pc1.get() ); 00158 BOOST_REQUIRE_EQUAL( pc1ref.getName(), pc1.getName() ); 00159 BOOST_REQUIRE_EQUAL( pc1ref.getDescription(), pc1.getDescription() ); 00160 pc2 = 'l'; 00161 00162 // copy semantics 00163 pc1.copy( pc2 ); 00164 BOOST_REQUIRE_EQUAL( pc2.get(), pc1.get() ); 00165 BOOST_REQUIRE_EQUAL( pc2ref.getName(), pc1.getName() ); 00166 BOOST_REQUIRE_EQUAL( pc2ref.getDescription(), pc1.getDescription() ); 00167 pc1.copy( pc1ref ); 00168 00169 // copy with PropertyBase. 00170 BOOST_CHECK( pc1.copy( pcb2 ) ); 00171 BOOST_REQUIRE_EQUAL( pc2.get(), pc1.get() ); 00172 BOOST_REQUIRE_EQUAL( pc2ref.getName(), pc1.getName() ); 00173 BOOST_REQUIRE_EQUAL( pc2ref.getDescription(), pc1.getDescription() ); 00174 pc1.copy( pc1ref ); 00175 } 00176 00177 BOOST_AUTO_TEST_CASE( testUpdateCharClone ) 00178 { 00179 PropertyBag target; 00180 // step 1 : clone a new instance (non deep copy) 00181 PropertyBase* temp = pc1.create(); 00182 // step 2 : deep copy clone with original, will never fail. 00183 BOOST_CHECK( temp->update( &pc1 ) ); 00184 // step 3 : add result to target bag. 00185 target.add( temp ); 00186 } 00187 00188 BOOST_AUTO_TEST_CASE( testfindProperty ) 00189 { 00190 // non recursive search : 00191 BOOST_CHECK( bag.find( "pf" ) == 0 ); 00192 BOOST_CHECK( bag.find( "s1" ) == &subbag1 ); 00193 BOOST_CHECK( bag.find( "pi1" ) == pi1 ); 00194 00195 // recursive search : 00196 BOOST_CHECK( findProperty( bag, "/pf", "/" ) == 0 ); 00197 BOOST_CHECK( findProperty( bag, ".pi1" ) == pi1 ); // default is "." 00198 BOOST_CHECK( findProperty( bag, "s1" ) == &subbag1 ); 00199 BOOST_CHECK( findProperty( bag, "pi1" ) == pi1 ); 00200 BOOST_CHECK( findProperty( bag, "/s1/s2", "/" ) == &subbag2 ); 00201 BOOST_CHECK( findProperty( bag, "/s1/s2/ps", "/" ) == &ps ); 00202 BOOST_CHECK( findProperty( bag, "s1.s2.pc" ) == &pc ); 00203 00204 } 00205 00206 // listProperties( bag, separator ) 00207 BOOST_AUTO_TEST_CASE( testlistProperties ) 00208 { 00209 vector<string> result = listProperties( bag ); 00210 BOOST_CHECK_EQUAL( result.size(), 8); 00211 // this test assumes this order, which is actually not 00212 // guaranteed by PropertyBag: 00213 BOOST_CHECK_EQUAL( result[0], string("pi1")); 00214 BOOST_CHECK_EQUAL( result[1], string("pi2")); 00215 BOOST_CHECK_EQUAL( result[2], string("s1")); 00216 BOOST_CHECK_EQUAL( result[3], string("s1.s2")); 00217 BOOST_CHECK_EQUAL( result[4], string("s1.s2.ps")); 00218 BOOST_CHECK_EQUAL( result[5], string("s1.s2.pc")); 00219 BOOST_CHECK_EQUAL( result[6], string("s1.pf")); 00220 BOOST_CHECK_EQUAL( result[7], string("s1.pd")); 00221 } 00222 00223 // storeProperty( bag, path, item, separator ) 00224 BOOST_AUTO_TEST_CASE( teststoreProperty ) 00225 { 00226 Property<int>* int1 = new Property<int>("int1","",3); 00227 Property<int>* int2 = new Property<int>("int2","",6); 00228 Property<int>* int3 = new Property<int>("int3","",9); 00229 BOOST_CHECK( storeProperty(bag, "pp1", int1 )); 00230 BOOST_CHECK_EQUAL( findProperty(bag, "pp1.int1"), int1 ); 00231 00232 BOOST_CHECK( storeProperty(bag, "pp1.pp2", int2) ); 00233 BOOST_CHECK_EQUAL( findProperty(bag, "pp1.pp2.int2"), int2 ); 00234 00235 BOOST_CHECK( removeProperty( bag, "pp1.pp2.int2") ); 00236 int2 = new Property<int>("int2","",6); 00237 00238 // re-add int2, but with different separator, and lots of them 00239 BOOST_CHECK( storeProperty(bag, "##pp1###pp3##", int2, "#") ); 00240 BOOST_CHECK_EQUAL( findProperty(bag, "pp1#pp3#int2", "#"), int2 ); 00241 00242 // top level store is equivalent to ownProperty: 00243 BOOST_CHECK( storeProperty(bag, "", int3) ); 00244 BOOST_CHECK( findProperty(bag, "int3") ); 00245 BOOST_CHECK_EQUAL( bag.find("int3"), int3 ); 00246 BOOST_CHECK( bag.ownsProperty( int3 ) ); 00247 00248 bag.removeProperty( int3 ); 00249 int3 = new Property<int>("int3","",9); 00250 00251 // same but with separator as path: 00252 BOOST_CHECK( storeProperty(bag, "#", int3,"#") ); 00253 BOOST_CHECK( findProperty(bag, "int3") ); 00254 BOOST_CHECK_EQUAL( bag.find("int3"), int3 ); 00255 BOOST_CHECK( bag.ownsProperty( int3 ) ); 00256 } 00257 00258 // removeProperty( bag, path, item, separator ) 00259 BOOST_AUTO_TEST_CASE( testremoveProperty ) 00260 { 00261 // check for wrong input: 00262 BOOST_CHECK( removeProperty( bag, "qwerty" ) == false ); 00263 BOOST_CHECK( removeProperty( bag, "." ) == false ); 00264 00265 // remove top level prop: 00266 BOOST_CHECK( removeProperty( bag, "pi1" ) ); 00267 BOOST_CHECK( findProperty( bag, "pi1" ) == 0 ); 00268 00269 // remove a leaf prop: 00270 BOOST_CHECK( removeProperty( bag, "s1.s2.pc" ) ); 00271 BOOST_CHECK( findProperty( bag, "s1.s2.pc" ) == 0 ); 00272 00273 // remove a bag: 00274 BOOST_CHECK( removeProperty( bag, "s1.s2" ) ); 00275 BOOST_CHECK( findProperty( bag, "s1.s2" ) == 0 ); 00276 } 00277 00278 BOOST_AUTO_TEST_CASE( testRepository ) 00279 { 00283 BOOST_MESSAGE("----- Testing testRep"); 00284 std::vector<string> names = TypeInfoRepository::Instance()->getTypes(); 00285 for (std::vector<string>::iterator it = names.begin(); it != names.end(); ++it) { 00286 BOOST_MESSAGE("----------- loop names: " << *it); 00287 PropertyBase* target; 00288 Property<PropertyBag> bag("Result","D"); 00289 BOOST_REQUIRE( TypeInfoRepository::Instance()->type( *it ) ); 00290 target = TypeInfoRepository::Instance()->type( *it )->buildProperty("Result", "D"); 00291 if ( target && typeDecomposition( target->getDataSource(), bag.value() ) ) 00292 BOOST_CHECK_MESSAGE( target->getTypeInfo()->composeType( bag.getDataSource() , target->getDataSource() ), "Failed composition for type "+target->getTypeInfo()->getTypeName() ); 00293 deletePropertyBag( bag.value() ); 00294 delete target; 00295 } 00296 00297 } 00298 00299 BOOST_AUTO_TEST_CASE( testComposition ) 00300 { 00304 std::vector<double> init(33, 1.0); 00305 Property<std::vector<double> > pvd("pvd","pvd desc", init); 00306 00307 //std::cout << "\n\n\n "<< std::string( typeid(init).name() ) << "\n\n\n "<<std::endl; 00308 00309 Property<std::vector<double> > pvd2("pvd 2","pvd desc 2"); 00310 00311 BOOST_CHECK( pvd.get() == init ); 00312 BOOST_CHECK( pvd.set() == init ); 00313 00314 BOOST_REQUIRE( pvd.getTypeInfo() ); 00315 BOOST_CHECK( pvd.getTypeInfo() != RTT::detail::DataSourceTypeInfo<RTT::detail::UnknownType>::getTypeInfo() ); 00316 00317 Property<PropertyBag> bag("Result","Rd"); 00318 // Decompose to property bag and back: 00319 BOOST_CHECK( typeDecomposition( pvd.getDataSource(), bag.value() ) ); 00320 BOOST_CHECK( pvd.getTypeInfo()->composeType( bag.getDataSource(), pvd2.getDataSource() ) ); 00321 BOOST_CHECK( pvd == pvd2 ); 00322 pvd2.value().clear(); 00323 deletePropertyBag( bag.value() ); 00324 } 00325 00327 BOOST_AUTO_TEST_CASE( testNewDecomposition ) 00328 { 00332 std::vector<double> init(33, 1.0); 00333 // these are the original sources: 00334 Property<std::vector<double> > pvd("pvd","pvd desc", init); 00335 00336 BOOST_CHECK( pvd.get() == init ); 00337 BOOST_CHECK( pvd.set() == init ); 00338 00339 BOOST_REQUIRE( pvd.getTypeInfo() ); 00340 BOOST_CHECK( pvd.getTypeInfo() != RTT::detail::DataSourceTypeInfo<RTT::detail::UnknownType>::getTypeInfo() ); 00341 00342 Property<PropertyBag> bag("Result","Rd"); 00343 // Decompose to property bag and check refs: 00344 BOOST_CHECK( propertyDecomposition( &pvd, bag.value() ) ); 00345 00346 Property<double> pvalue = bag.value().getItem(3); 00347 BOOST_REQUIRE( pvalue.ready() ); 00348 pvalue.set( 42 ); 00349 00350 BOOST_CHECK( pvd.rvalue()[3] == 42 ); 00351 00352 deletePropertyBag( bag.value() ); 00353 } 00354 00355 00356 BOOST_AUTO_TEST_CASE( testInit ) 00357 { 00358 // See if this compiles fine: 00359 // detects collisions with other constructors... 00360 Property<unsigned int> pui("PUI","", 0 ); 00361 Property<int> pi("PI","", 0 ); 00362 Property<bool> pb("PB","", false ); 00363 00364 // Test null assignment 00365 PropertyBase* pbase = 0; 00366 Property<int> p2 = pbase; 00367 BOOST_CHECK( !p2.ready() ); 00368 Property<int> p3; 00369 BOOST_CHECK( !p3.ready() ); 00370 00371 p3 = pbase; 00372 BOOST_CHECK( !p3.ready() ); 00373 00374 p2 = p3; 00375 BOOST_CHECK( !p2.ready() ); 00376 00377 p2 = pi; 00378 BOOST_CHECK( p2.ready() ); 00379 00380 BOOST_CHECK(true); 00381 } 00382 00383 00384 BOOST_AUTO_TEST_CASE( testUpdate ) 00385 { 00386 PropertyBag source; 00387 PropertyBag target; 00388 00389 Property<PropertyBag> b1("b1",""); 00390 Property<PropertyBag> b2("b2",""); 00391 Property<int> p1("p1","",-1); 00392 00393 Property<PropertyBag> b1c("b1",""); 00394 Property<PropertyBag> b2c("b2",""); 00395 Property<int> p1c("p1","",0); 00396 00397 // setup source tree 00398 source.addProperty( b1 ); 00399 b1.value().addProperty( b2 ); 00400 b2.value().addProperty( p1 ); 00401 00402 // update case: 00403 // setup target tree 00404 target.addProperty( b1c ); 00405 b1c.value().addProperty( b2c ); 00406 b2c.value().addProperty( p1c ); 00407 00408 BOOST_CHECK( p1.get() != p1c.get() ); 00409 00410 BOOST_CHECK( updateProperty(target, source, "b1/b2/p1", "/") ); 00411 00412 BOOST_CHECK( p1.get() == -1 ); 00413 BOOST_CHECK( p1c.get() == -1 ); 00414 00415 // creation case: 00416 target.removeProperty(&b1); 00417 BOOST_CHECK( updateProperty(target, source, "b1/b2/p1", "/") ); 00418 00419 Property<PropertyBag>* bag = target.getPropertyType<PropertyBag>("b1"); 00420 BOOST_CHECK( bag ); 00421 BOOST_CHECK( bag->getName() == "b1" ); 00422 bag = bag->get().getPropertyType<PropertyBag>("b2"); 00423 BOOST_CHECK( bag ); 00424 BOOST_CHECK( bag->getName() == "b2" ); 00425 00426 Property<int>* res = bag->get().getPropertyType<int>("p1"); 00427 BOOST_CHECK( res ); 00428 BOOST_CHECK( res->getName() == "p1" ); 00429 BOOST_CHECK( res->get() == -1 ); 00430 00431 } 00432 00433 BOOST_AUTO_TEST_SUITE_END()