Teuchos Package Browser (Single Doxygen Collection) Version of the Day
ObjectBuilder_UnitTests.cpp
Go to the documentation of this file.
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 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines