|
Teuchos Package Browser (Single Doxygen Collection)
Version of the Day
|
00001 // @HEADER 00002 // *********************************************************************** 00003 // 00004 // Teuchos: Common Tools Package 00005 // Copyright (2004) Sandia Corporation 00006 // 00007 // Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive 00008 // license for use of this work by or on behalf of the U.S. Government. 00009 // 00010 // Redistribution and use in source and binary forms, with or without 00011 // modification, are permitted provided that the following conditions are 00012 // met: 00013 // 00014 // 1. Redistributions of source code must retain the above copyright 00015 // notice, this list of conditions and the following disclaimer. 00016 // 00017 // 2. Redistributions in binary form must reproduce the above copyright 00018 // notice, this list of conditions and the following disclaimer in the 00019 // documentation and/or other materials provided with the distribution. 00020 // 00021 // 3. Neither the name of the Corporation nor the names of the 00022 // contributors may be used to endorse or promote products derived from 00023 // this software without specific prior written permission. 00024 // 00025 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY 00026 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00027 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 00028 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE 00029 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 00030 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 00031 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 00032 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 00033 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 00034 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 00035 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00036 // 00037 // Questions? Contact Michael A. Heroux (maherou@sandia.gov) 00038 // 00039 // *********************************************************************** 00040 // @HEADER 00041 00042 #include "Teuchos_ObjectBuilder.hpp" 00043 #include "Teuchos_ParameterList.hpp" 00044 #include "Teuchos_ParameterListAcceptorHelpers.hpp" 00045 00046 #include "Teuchos_UnitTestHarness.hpp" 00047 00048 namespace Teuchos { 00049 00050 const std::string ObjectType_name = "Foo Type"; 00051 00052 class Foo : virtual public ParameterListAcceptor { 00053 public: 00054 Foo() {} 00055 virtual ~Foo() {} 00056 virtual std::string getString() const =0; 00057 virtual void setDefaults() =0; 00058 void setParameterList(const RCP<ParameterList> & paramList) { 00059 if (!is_null(paramList)) { 00060 paramList->validateParameters(*this->getValidParameters()); 00061 paramList_ = paramList; 00062 } 00063 setDefaults(); 00064 } 00065 RCP<ParameterList> getNonconstParameterList() { 00066 return paramList_; 00067 } 00068 RCP<ParameterList> unsetParameterList() { 00069 RCP<ParameterList> pl = paramList_; 00070 paramList_ = null; 00071 return pl; 00072 } 00073 RCP<const ParameterList> getParameterList() const { 00074 return paramList_; 00075 } 00076 private: 00077 RCP<ParameterList> paramList_; 00078 }; 00079 class FooA : virtual public Foo { 00080 public: 00081 FooA() { 00082 setDefaults(); 00083 } 00084 virtual ~FooA() {} 00085 std::string getString() const { 00086 return foo_; 00087 } 00088 void setDefaults() { 00089 RCP<ParameterList> pl = this->getNonconstParameterList(); 00090 if (is_null(pl)) { 00091 foo_ = "A"; 00092 } else { 00093 foo_ = pl->get("String",foo_); 00094 } 00095 } 00096 RCP<const ParameterList> getValidParameters() const { 00097 static RCP<ParameterList> validPL; 00098 if (is_null(validPL)) { 00099 RCP<ParameterList> pl = parameterList(); 00100 pl->set( "String", foo_ ); 00101 validPL = pl; 00102 } 00103 return validPL; 00104 } 00105 private: 00106 std::string foo_; 00107 }; 00108 class FooB : virtual public Foo { 00109 public: 00110 FooB() { 00111 setDefaults(); 00112 } 00113 virtual ~FooB() {} 00114 std::string getString() const { 00115 return foo_; 00116 } 00117 void setDefaults() { 00118 RCP<ParameterList> pl = this->getNonconstParameterList(); 00119 if (is_null(pl)) { 00120 foo_ = "B"; 00121 } else { 00122 foo_ = pl->get("String",foo_); 00123 } 00124 } 00125 RCP<const ParameterList> getValidParameters() const { 00126 static RCP<ParameterList> validPL; 00127 if (is_null(validPL)) { 00128 RCP<ParameterList> pl = parameterList(); 00129 pl->set( "String", foo_ ); 00130 validPL = pl; 00131 } 00132 return validPL; 00133 } 00134 private: 00135 std::string foo_; 00136 }; 00137 class FooC : virtual public Foo { 00138 public: 00139 FooC() { 00140 setDefaults(); 00141 } 00142 virtual ~FooC() {} 00143 std::string getString() const { 00144 return foo_; 00145 } 00146 void setDefaults() { 00147 RCP<ParameterList> pl = this->getNonconstParameterList(); 00148 if (is_null(pl)) { 00149 foo_ = "C"; 00150 } else { 00151 foo_ = pl->get("String",foo_); 00152 } 00153 } 00154 RCP<const ParameterList> getValidParameters() const { 00155 static RCP<ParameterList> validPL; 00156 if (is_null(validPL)) { 00157 RCP<ParameterList> pl = parameterList(); 00158 pl->set( "String", foo_ ); 00159 validPL = pl; 00160 } 00161 return validPL; 00162 } 00163 private: 00164 std::string foo_; 00165 }; 00166 00167 // The following happens at construction: 00168 // 1. initializeDefaults_ is called 00169 // a) object_name_ = "Object" 00170 // b) objectType_name_ = "Object Type" 00171 // c) defaultObject_ = "None" 00172 // d) validObjectNames_ just has "None" 00173 TEUCHOS_UNIT_TEST( Teuchos_ObjectBuilder, constructor) { 00174 RCP<ObjectBuilder<Foo> > ob = objectBuilder<Foo>(); 00175 TEST_EQUALITY_CONST( ob->getObjectName(), "None" ); 00176 TEST_EQUALITY_CONST( ob->create(), null ); 00177 RCP<const ParameterList> pl; 00178 TEST_NOTHROW( pl = ob->getValidParameters() ); 00179 TEST_EQUALITY_CONST( pl->get<std::string>("Object Type"), "None" ); 00180 TEST_NOTHROW( ob = null ); 00181 } 00182 00183 // Tests setObjectName and setObectTypeName 00184 // Note: it should throw an exception if the string is "" 00185 TEUCHOS_UNIT_TEST( Teuchos_ObjectBuilder, setNames) { 00186 { 00187 const RCP<ObjectBuilder<Foo> > ob = objectBuilder<Foo>(); 00188 TEST_THROW( ob->setObjectName(""), std::logic_error ); 00189 TEST_THROW( ob->setObjectTypeName(""), std::logic_error ); 00190 } 00191 { 00192 RCP<ObjectBuilder<Foo> > ob; 00193 TEST_THROW( ob = objectBuilder<Foo>("","Foo Type"), std::logic_error ); 00194 TEST_THROW( ob = objectBuilder<Foo>("Foo",""), std::logic_error ); 00195 TEST_THROW( ob = objectBuilder<Foo>("",""), std::logic_error ); 00196 } 00197 { 00198 const RCP<ObjectBuilder<Foo> > ob = objectBuilder<Foo>(); 00199 ob->setObjectName("Foo"); 00200 ob->setObjectTypeName("Foo Type"); 00201 const RCP<const ParameterList> validpl = ob->getValidParameters(); 00202 // Now we check that the parameterlist is correct 00203 TEST_EQUALITY_CONST( validpl->get<std::string>("Foo Type"), "None" ); 00204 const ParameterEntry pe = validpl->getEntry("Foo Type"); 00205 TEST_EQUALITY_CONST( pe.docString(), 00206 "Determines the type of Foo object that will be built.\nThe parameters for each Foo Type are specified in this sublist" 00207 ); 00208 } 00209 { 00210 const RCP<ObjectBuilder<Foo> > ob = objectBuilder<Foo>("Foo","Foo Type"); 00211 const RCP<const ParameterList> validpl = ob->getValidParameters(); 00212 // Now we check that the parameterlist is correct 00213 TEST_EQUALITY_CONST( validpl->get<std::string>("Foo Type"), "None" ); 00214 const ParameterEntry pe = validpl->getEntry("Foo Type"); 00215 TEST_EQUALITY_CONST( pe.docString(), 00216 "Determines the type of Foo object that will be built.\nThe parameters for each Foo Type are specified in this sublist" 00217 ); 00218 } 00219 } 00220 00221 // setObjectFactory does four things: 00222 // 1. adds a new object name 00223 // 1a. if object name is "" it throws an exception 00224 // 2. adds a new object factory 00225 // 3. sets defaultObject_ 00226 // 4. deletes the validParamList_ 00227 // 00228 // Notes about how to sense the changes: 00229 // 1. The new object name is appended to the list of valid names and shows up in the valid parameter list 00230 // 2. The new object factory is appended to the list of factories and is only accessible through create 00231 // 3. The default Object is accessible through both getObjectName and the valid parameter list. 00232 // 4. The validParameterList is deleted and this can only be sensed through calling getValidParameters 00233 TEUCHOS_UNIT_TEST( Teuchos_ObjectBuilder, setObjectFactory) { 00234 const RCP<ObjectBuilder<Foo> > ob = objectBuilder<Foo>("Foo","Foo Type"); 00235 TEST_EQUALITY_CONST( ob->getObjectName(), "None" ); 00236 ob->setObjectFactory(abstractFactoryStd<Foo,FooA>(),"Foo A"); 00237 TEST_EQUALITY_CONST( ob->getObjectName(), "Foo A" ); // 3. 00238 RCP<const ParameterList> pl = ob->getValidParameters(); 00239 TEST_EQUALITY_CONST( pl->get<std::string>("Foo Type"), "Foo A" ); // 1. 00240 TEST_EQUALITY_CONST( pl->sublist("Foo A").get<std::string>("String"), "A" ); // 1. 00241 const RCP<Foo> foo = ob->create(); 00242 const RCP<FooA> fooA = rcp_dynamic_cast<FooA>(foo,false); 00243 TEST_EQUALITY_CONST( is_null(fooA), false ); // 2. 00244 ob->setObjectFactory(abstractFactoryStd<Foo,FooB>(),"Foo B"); 00245 pl = ob->getValidParameters(); 00246 TEST_EQUALITY_CONST( pl->get<std::string>("Foo Type"), "Foo B" ); // 4. 00247 TEST_THROW( ob->setObjectFactory(abstractFactoryStd<Foo,FooC>(),""), std::logic_error ); // 1a. 00248 } 00249 00250 // We shouldn't be able to set two factories with the same name. 00251 TEUCHOS_UNIT_TEST( Teuchos_ObjectBuilder, setObjectFactory_bad ) { 00252 { 00253 const RCP<ObjectBuilder<Foo> > ob = objectBuilder<Foo>("Foo","Foo Type"); 00254 ob->setObjectFactory(abstractFactoryStd<Foo,FooA>(),"Foo A"); 00255 // ObjectBuilder will let you add the object, but will not throw until getValidParameters is called 00256 #ifdef TEUCHOS_DEBUG 00257 TEST_THROW( ob->setObjectFactory(abstractFactoryStd<Foo,FooA>(),"Foo A"), std::logic_error ); 00258 #else // TEUCHOS_DEBUG 00259 TEST_NOTHROW( ob->setObjectFactory(abstractFactoryStd<Foo,FooA>(),"Foo A") ); 00260 TEST_THROW( ob->getValidParameters(), std::logic_error ); 00261 #endif // TEUCHOS_DEBUG 00262 } 00263 { 00264 const RCP<ObjectBuilder<Foo> > ob = objectBuilder<Foo>("Foo","Foo Type"); 00265 ob->setObjectFactory(abstractFactoryStd<Foo,FooA>(),"Foo A"); 00266 TEST_NOTHROW( ob->setObjectFactory(abstractFactoryStd<Foo,FooA>(),"New Foo A") ); 00267 TEST_NOTHROW( ob->getValidParameters() ); 00268 } 00269 } 00270 00271 // getObjectName returns the default in the parameter list (if given), or the 00272 // default in the valid parameter list (if no parameter list is given) 00273 // 1. no parameter list is given, uses default in valid parameter list. 00274 // 2. parameter list is given, and uses its default 00275 TEUCHOS_UNIT_TEST( Teuchos_ObjectBuilder, getObjectName) { 00276 const RCP<ObjectBuilder<Foo> > ob = objectBuilder<Foo>("Foo", "Foo Type"); 00277 ob->setObjectFactory(abstractFactoryStd<Foo,FooA>(),"Foo A"); 00278 ob->setObjectFactory(abstractFactoryStd<Foo,FooB>(),"Foo B"); 00279 const RCP<ParameterList> pl = parameterList(); 00280 pl->setParameters(*ob->getValidParameters()); // copy parameters 00281 pl->set("Foo Type", "Foo A"); // change default 00282 // 1. 00283 TEST_EQUALITY_CONST( ob->getObjectName(), "Foo B" ); 00284 // 2. 00285 ob->setParameterList(pl); 00286 TEST_EQUALITY_CONST( ob->getObjectName(), "Foo A" ); 00287 } 00288 00289 // create has many cases 00290 // 1. It should return a null RCP if no factories are set 00291 // 2. It should return a null RCP if "Object Type" is set to "None" in the provided parameterList 00292 // 3. It should return the correct object consistent with the "Object Type" setting in the parameterList if no string is passed 00293 // 3a. It should return the correct object consistent with the "Object Type" 00294 // setting in the valid parameterList if no string is passed and no 00295 // parameterList is provided. 00296 // 4. It should return the correct object consistent with the input string regardless of the parameterLists 00297 // 4a. It should throw an exception if an invalid input string is provided 00298 // 5. If no parameter list is provided, then it will use the valid parameter list to set parameters on the object 00299 // 5a. If a parameter list is provided, then it will use that parameter list to set parameters on the object 00300 // 6. It will throw an exception with a nice message if the factory creates a null RCP 00301 // Under what conditions could this happen? 00302 // 7. [03/05/09 tscoffe: found bug] create() uses objectValidator_, so 00303 // getValidParameters must be valid at the beginning to avoid a null 00304 // dereference of the objectValidator_ pointer in the case that we ask for an 00305 // object by name and the validParamList_ has not been set up yet. 00306 TEUCHOS_UNIT_TEST( Teuchos_ObjectBuilder, create) { 00307 const RCP<ObjectBuilder<Foo> > ob = objectBuilder<Foo>("Foo", "Foo Type"); 00308 TEST_EQUALITY_CONST( ob->create("None"), null ); // 7. 00309 TEST_EQUALITY_CONST( ob->create(), null ); // 1. 00310 ob->setObjectFactory(abstractFactoryStd<Foo,FooA>(),"Foo A"); 00311 ob->setObjectFactory(abstractFactoryStd<Foo,FooB>(),"Foo B"); 00312 ob->setObjectFactory(abstractFactoryStd<Foo,FooC>(),"Foo C"); 00313 out << "op.getValidParamters():\n"; 00314 printValidParameters(*ob, out); 00315 const RCP<ParameterList> pl = parameterList(); 00316 pl->setParameters(*ob->getValidParameters()); 00317 pl->set("Foo Type","None"); 00318 ob->setParameterList(pl); 00319 TEST_EQUALITY_CONST( ob->create(), null ); // 2. 00320 pl->set("Foo Type", "Foo B"); 00321 pl->sublist("Foo B").set("String","BB"); 00322 pl->sublist("Foo C").set("String","CC"); 00323 { 00324 const RCP<Foo> foo = ob->create(); 00325 const RCP<FooB> fooB = rcp_dynamic_cast<FooB>(foo,false); 00326 TEST_EQUALITY_CONST( is_null(fooB), false ); // 3. 00327 TEST_EQUALITY_CONST( foo->getString(), "BB" ); // 5a. 00328 } 00329 ob->unsetParameterList(); 00330 { 00331 const RCP<Foo> foo = ob->create(); 00332 const RCP<FooC> fooC = rcp_dynamic_cast<FooC>(foo,false); 00333 TEST_EQUALITY_CONST( is_null(fooC), false ); // 3a. 00334 TEST_EQUALITY_CONST( foo->getString(), "C" ); // 5. 00335 } 00336 { 00337 const RCP<Foo> foo = ob->create("Foo A"); 00338 const RCP<FooA> fooA = rcp_dynamic_cast<FooA>(foo,false); 00339 TEST_EQUALITY_CONST( is_null(fooA), false ); // 4. 00340 } 00341 ob->setParameterList(pl); 00342 { 00343 const RCP<Foo> foo = ob->create("Foo A"); 00344 const RCP<FooA> fooA = rcp_dynamic_cast<FooA>(foo,false); 00345 TEST_EQUALITY_CONST( is_null(fooA), false ); // 4. 00346 } 00347 { 00348 RCP<Foo> foo; 00349 TEST_THROW( foo = ob->create("Foo D"), std::logic_error ); // 4a. 00350 } 00351 // 6. ??? 00352 } 00353 00354 // There are many places that the parameter list is validated to ensure that we 00355 // catch invalid parameter lists before we use them. This is particularly 00356 // important because we're storing a pointer to the parameter list and the user 00357 // can change it without ObjectBuilder knowing about it. 00358 // The parameter list is validated in four places: 00359 // 1. setParameterList 00360 // 2. unsetParameterList (only in debug mode) 00361 // 3. create (only in debug mode) 00362 // 4. destructor (only in debug mode) 00363 TEUCHOS_UNIT_TEST( Teuchos_ObjectBuilder, setParameterList) { 00364 RCP<ObjectBuilder<Foo> > ob = objectBuilder<Foo>(); 00365 ob->setObjectFactory(abstractFactoryStd<Foo,FooA>(),"Foo A"); 00366 RCP<ParameterList> pl = null; 00367 TEST_NOTHROW( ob->setParameterList(pl) ); 00368 pl = parameterList(); 00369 TEST_NOTHROW( ob->setParameterList(pl) ); 00370 pl->set("Hello","World"); 00371 TEST_THROW( ob->setParameterList(pl), std::logic_error ); // 1. 00372 #ifdef TEUCHOS_DEBUG 00373 TEST_THROW( ob->unsetParameterList(), std::logic_error ); // 2. 00374 TEST_THROW( ob->create(), std::logic_error ); // 3. 00375 TEST_THROW( ob = null, std::logic_error ); // 4. 00376 #else // TEUCHOS_DEBUG 00377 TEST_NOTHROW( ob->unsetParameterList() ); 00378 RCP<Foo> foo; 00379 TEST_NOTHROW( foo = ob->create() ); 00380 const RCP<FooA> fooA = rcp_dynamic_cast<FooA>(foo,false); 00381 TEST_EQUALITY_CONST( is_null(fooA), false ); 00382 TEST_NOTHROW( ob = null ); 00383 #endif // TEUCHOS_DEBUG 00384 } 00385 00386 // Here we test 00387 // 1. That it returns a null RCP before we give it a parameter list. 00388 // 2. That we can set up a valid parameter list, give it to the ObjectBuilder, and get it back out. 00389 TEUCHOS_UNIT_TEST( Teuchos_ObjectBuilder, getParameterList) { 00390 const RCP<ObjectBuilder<Foo> > ob = objectBuilder<Foo>(); 00391 ob->setObjectFactory(abstractFactoryStd<Foo,FooA>(),"Foo A"); 00392 const RCP<const ParameterList> pl = ob->getParameterList(); 00393 TEST_EQUALITY_CONST( is_null(pl), true ); // 1. 00394 const RCP<ParameterList> nonconstPL = parameterList(); 00395 nonconstPL->set("Object Type","None"); 00396 TEST_NOTHROW( ob->setParameterList(nonconstPL) ); 00397 { 00398 const RCP<const ParameterList> newPL = ob->getParameterList(); 00399 TEST_EQUALITY_CONST( nonconstPL.get(), newPL.get() ); // 2. 00400 } 00401 } 00402 00403 // Same as getParameterList 00404 TEUCHOS_UNIT_TEST( Teuchos_ObjectBuilder, getNonconstParameterList) { 00405 const RCP<ObjectBuilder<Foo> > ob = objectBuilder<Foo>(); 00406 ob->setObjectFactory(abstractFactoryStd<Foo,FooA>(),"Foo A"); 00407 RCP<ParameterList> pl = ob->getNonconstParameterList(); 00408 TEST_EQUALITY_CONST( is_null(pl), true ); 00409 pl = parameterList(); 00410 pl->set("Object Type","None"); 00411 TEST_NOTHROW( ob->setParameterList(pl) ); 00412 { 00413 RCP<ParameterList> newPL = null; 00414 newPL = ob->getNonconstParameterList(); 00415 TEST_EQUALITY_CONST( pl.get(), newPL.get() ); 00416 } 00417 } 00418 00419 // Here we're checking: 00420 // 1. That we can set a parameter list on it and it uses it and then we can 00421 // unset it and it goes back to using the valid parameter list. 00422 // 1a. We get back the same parameter list we set 00423 // 2. In debug mode, the parameter list is validated when unsetParameterList 00424 // is called. 00425 TEUCHOS_UNIT_TEST( Teuchos_ObjectBuilder, unsetParameterList) { 00426 RCP<ObjectBuilder<Foo> > ob = objectBuilder<Foo>(); 00427 ob->setObjectFactory(abstractFactoryStd<Foo,FooA>(),"Foo A"); 00428 const RCP<ParameterList> pl = parameterList(); 00429 pl->set("Object Type","None"); 00430 ob->setParameterList(pl); 00431 RCP<Foo> foo = ob->create(); 00432 TEST_EQUALITY_CONST( is_null(foo), true ); 00433 RCP<ParameterList> newPL = ob->unsetParameterList(); 00434 TEST_EQUALITY_CONST( pl.get(), newPL.get() ); // 1a. 00435 foo = ob->create(); 00436 const RCP<FooA> fooA = rcp_dynamic_cast<FooA>(foo,false); 00437 TEST_EQUALITY_CONST( is_null(fooA), false ); // 1. 00438 ob->setParameterList(pl); 00439 pl->set("Hello","World"); 00440 newPL = null; 00441 #ifdef TEUCHOS_DEBUG 00442 TEST_THROW( newPL = ob->unsetParameterList(), std::logic_error ); // 2. 00443 TEST_EQUALITY_CONST( is_null(newPL), true ); 00444 TEST_THROW( ob = null, std::logic_error ); 00445 #else // TEUCHOS_DEBUG 00446 TEST_NOTHROW( newPL = ob->unsetParameterList() ); 00447 TEST_EQUALITY_CONST( pl.get(), newPL.get() ); // 1a. 00448 TEST_NOTHROW( ob = null ); 00449 #endif // TEUCHOS_DEBUG 00450 } 00451 00452 // This function does several things. 00453 // 1. It creates the validParameterList whenever it is deleted [already tested in setObjectFactory] 00454 // 2. It creates the objectValidator 00455 // 3. It adds a docstring to the "Object Type" parameter in the parameter list [already tested in setNames] 00456 // 4. It fills the parameter list out with the valid parameteres for each object it can create 00457 TEUCHOS_UNIT_TEST( Teuchos_ObjectBuilder, getValidParameters) { 00458 { 00459 const RCP<ObjectBuilder<Foo> > ob = objectBuilder<Foo>(); 00460 ob->setObjectFactory(abstractFactoryStd<Foo,FooA>(),"Foo A"); 00461 const RCP<ParameterList> pl = parameterList(); 00462 pl->set("Object Type","Foo B"); 00463 TEST_THROW( ob->setParameterList(pl), std::logic_error ); // 2. 00464 } 00465 { 00466 const RCP<ObjectBuilder<Foo> > ob = objectBuilder<Foo>(); 00467 ob->setObjectFactory(abstractFactoryStd<Foo,FooA>(),"Foo A"); 00468 ob->setObjectFactory(abstractFactoryStd<Foo,FooA>(),"Foo B"); 00469 ob->setObjectFactory(abstractFactoryStd<Foo,FooA>(),"Foo C"); 00470 const RCP<ParameterList> validPL = parameterList(); 00471 validPL->set("Object Type","Foo C"); 00472 validPL->sublist("Foo A").set("String","A"); 00473 validPL->sublist("Foo B").set("String","B"); 00474 validPL->sublist("Foo C").set("String","C"); 00475 Array<std::string> validObjectNames; 00476 validObjectNames.push_back("None"); 00477 validObjectNames.push_back("Foo A"); 00478 validObjectNames.push_back("Foo B"); 00479 validObjectNames.push_back("Foo C"); 00480 const RCP<const StringToIntegralParameterEntryValidator<int> > 00481 objectValidator = rcp( 00482 new StringToIntegralParameterEntryValidator<int>( 00483 validObjectNames,"Object Type" 00484 ) 00485 ); 00486 validPL->set( 00487 "Object Type","Foo C" 00488 ,(std::string("Determines the type of Object object that will be built.\n") 00489 + "The parameters for each Object Type are specified in this sublist" 00490 ).c_str() 00491 ,objectValidator 00492 ); 00493 const RCP<const ParameterList> pl = ob->getValidParameters(); 00494 TEST_NOTHROW( pl->validateParameters(*validPL) ); // 4. 00495 validPL->set("Object Type","Foo A"); 00496 TEST_NOTHROW( pl->validateParameters(*validPL) ); // 4. 00497 validPL->set("Object Type","Foo B"); 00498 TEST_NOTHROW( pl->validateParameters(*validPL) ); // 4. 00499 validPL->set("Object Type","None"); 00500 TEST_NOTHROW( pl->validateParameters(*validPL) ); // 4. 00501 } 00502 } 00503 00504 // Now we verify that the parameter lists are coming out with Used parameters in the correct state 00505 // 1. Pass in empty parameter list and create an object. We should get a 00506 // sublist and used parameters on the sublist for the object we created, but no 00507 // other sublists. 00508 // 2. Pass in a full parameter list and create an object. We should get 00509 // used parameters for only the sublist of the object we created. 00510 TEUCHOS_UNIT_TEST( Teuchos_ObjectBuilder, usedParameters) { 00511 const RCP<ObjectBuilder<Foo> > ob = objectBuilder<Foo>("Foo","Foo Type"); 00512 ob->setObjectFactory(abstractFactoryStd<Foo,FooA>(),"Foo A"); 00513 ob->setObjectFactory(abstractFactoryStd<Foo,FooB>(),"Foo B"); 00514 ob->setObjectFactory(abstractFactoryStd<Foo,FooC>(),"Foo C"); 00515 { 00516 const RCP<ParameterList> pl = parameterList(); 00517 ob->setParameterList(pl); 00518 const RCP<Foo> foo = ob->create("Foo A"); 00519 TEST_EQUALITY_CONST( foo->getString(), "A" ); 00520 TEST_EQUALITY_CONST( pl->isSublist("Foo A"), true ); // 1. 00521 TEST_EQUALITY_CONST( pl->sublist("Foo A").isParameter("String"), true ); // 1. 00522 const ParameterEntry& pe = pl->sublist("Foo A").getEntry("String"); 00523 TEST_EQUALITY_CONST( pe.isUsed(), true ); // 1. 00524 TEST_EQUALITY_CONST( pe.isDefault(), true ); // 1. 00525 // verify the other sublists are missing 00526 TEST_EQUALITY_CONST( pl->isSublist("Foo B"), false ); // 1. 00527 TEST_EQUALITY_CONST( pl->isSublist("Foo C"), false ); // 1. 00528 ob->unsetParameterList(); 00529 } 00530 { 00531 RCP<ParameterList> pl = parameterList(); 00532 pl->setParameters(*ob->getValidParameters()); 00533 pl->sublist("Foo A").set("String","AA"); 00534 ob->setParameterList(pl); 00535 pl = null; 00536 const RCP<Foo> foo = ob->create("Foo A"); 00537 TEST_EQUALITY_CONST( foo->getString(), "AA" ); 00538 const RCP<const ParameterList> outPL = ob->getParameterList(); 00539 TEST_EQUALITY_CONST( outPL->isSublist("Foo A"), true ); 00540 TEST_EQUALITY_CONST( outPL->sublist("Foo A").isParameter("String"), true ); 00541 const ParameterEntry& pe = outPL->sublist("Foo A").getEntry("String"); 00542 TEST_EQUALITY_CONST( pe.isUsed(), true ); // 2. 00543 TEST_EQUALITY_CONST( pe.isDefault(), false ); // 2. 00544 // verify the other sublists are unused 00545 TEST_EQUALITY_CONST( outPL->sublist("Foo B").getEntry("String").isUsed(), false ); // 2. 00546 TEST_EQUALITY_CONST( outPL->sublist("Foo C").getEntry("String").isUsed(), false ); // 2. 00547 ob->unsetParameterList(); 00548 } 00549 } 00550 00551 TEUCHOS_UNIT_TEST( Teuchos_ObjectBuilder, setDefaultObject_withOneUsePL ) { 00552 const RCP<ObjectBuilder<Foo> > ob = objectBuilder<Foo>("Foo","Foo Type"); 00553 ob->setObjectFactory(abstractFactoryStd<Foo,FooA>(),"Foo A"); 00554 ob->setObjectFactory(abstractFactoryStd<Foo,FooB>(),"Foo B"); 00555 ob->setObjectFactory(abstractFactoryStd<Foo,FooC>(),"Foo C"); 00556 { 00557 const RCP<ParameterList> pl = parameterList(); 00558 ob->setParameterList(pl); 00559 const RCP<Foo> foo = ob->create(); 00560 RCP<FooC> fooC = Teuchos::rcp_dynamic_cast<FooC>(foo,false); 00561 TEST_ASSERT( !is_null(fooC) ); 00562 } 00563 { 00564 const RCP<ParameterList> pl = parameterList(); 00565 ob->setParameterList(pl); 00566 ob->setDefaultObject("Foo A"); 00567 const RCP<Foo> foo = ob->create(); 00568 RCP<FooA> fooA = Teuchos::rcp_dynamic_cast<FooA>(foo,false); 00569 TEST_ASSERT( !is_null(fooA) ); 00570 } 00571 { 00572 const RCP<ParameterList> pl = parameterList(); 00573 ob->setParameterList(pl); 00574 ob->setDefaultObject("None"); 00575 const RCP<Foo> foo = ob->create(); 00576 TEST_ASSERT( is_null(foo) ); 00577 } 00578 { 00579 #ifdef TEUCHOS_DEBUG 00580 TEST_THROW(ob->setDefaultObject("Foo D"), std::logic_error); 00581 #else 00582 ob->setDefaultObject("Foo D"); 00583 TEST_THROW(ob->getValidParameters(), std::logic_error); 00584 #endif // TEUCHOS_DEBUG 00585 } 00586 } 00587 TEUCHOS_UNIT_TEST( Teuchos_ObjectBuilder, setDefaultObject_withMultipleUsePL ) { 00588 const RCP<ObjectBuilder<Foo> > ob = objectBuilder<Foo>("Foo","Foo Type"); 00589 ob->setObjectFactory(abstractFactoryStd<Foo,FooA>(),"Foo A"); 00590 ob->setObjectFactory(abstractFactoryStd<Foo,FooB>(),"Foo B"); 00591 ob->setObjectFactory(abstractFactoryStd<Foo,FooC>(),"Foo C"); 00592 const RCP<ParameterList> pl = parameterList(); 00593 ob->setParameterList(pl); 00594 { 00595 const RCP<Foo> foo = ob->create(); 00596 RCP<FooC> fooC = Teuchos::rcp_dynamic_cast<FooC>(foo,false); 00597 TEST_ASSERT( !is_null(fooC) ); 00598 // Note: At this point, pl contains "Foo Type = Foo C" 00599 // And this pl was set on the ObjectBuilder, so defaultObject does no good. 00600 } 00601 { 00602 ob->setDefaultObject("Foo A"); 00603 const RCP<Foo> foo = ob->create(); 00604 RCP<FooA> fooA = Teuchos::rcp_dynamic_cast<FooA>(foo,false); 00605 TEST_ASSERT( is_null(fooA) ); 00606 } 00607 { 00608 ob->setDefaultObject("None"); 00609 const RCP<Foo> foo = ob->create(); 00610 TEST_ASSERT( !is_null(foo) ); 00611 } 00612 } 00613 00614 TEUCHOS_UNIT_TEST( Teuchos_ObjectBuilder, setDefaultObject_withoutPL ) { 00615 const RCP<ObjectBuilder<Foo> > ob = objectBuilder<Foo>("Foo","Foo Type"); 00616 ob->setObjectFactory(abstractFactoryStd<Foo,FooA>(),"Foo A"); 00617 ob->setObjectFactory(abstractFactoryStd<Foo,FooB>(),"Foo B"); 00618 ob->setObjectFactory(abstractFactoryStd<Foo,FooC>(),"Foo C"); 00619 { 00620 const RCP<Foo> foo = ob->create(); 00621 RCP<FooC> fooC = Teuchos::rcp_dynamic_cast<FooC>(foo,false); 00622 TEST_ASSERT( !is_null(fooC) ); 00623 } 00624 { 00625 ob->setDefaultObject("Foo A"); 00626 const RCP<Foo> foo = ob->create(); 00627 RCP<FooA> fooA = Teuchos::rcp_dynamic_cast<FooA>(foo,false); 00628 TEST_ASSERT( !is_null(fooA) ); 00629 } 00630 { 00631 ob->setDefaultObject("None"); 00632 const RCP<Foo> foo = ob->create(); 00633 TEST_ASSERT( is_null(foo) ); 00634 } 00635 } 00636 00637 } // namespace Teuchos 00638 00639 00640
1.7.6.1