Teuchos Package Browser (Single Doxygen Collection)  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
ParameterList_UnitTests.cpp
Go to the documentation of this file.
1 // @HEADER
2 // *****************************************************************************
3 // Teuchos: Common Tools Package
4 //
5 // Copyright 2004 NTESS and the Teuchos contributors.
6 // SPDX-License-Identifier: BSD-3-Clause
7 // *****************************************************************************
8 // @HEADER
9 
11 #include "Teuchos_getConst.hpp"
12 #include "Teuchos_as.hpp"
16 
17 
18 //
19 // Utilities
20 //
21 
22 
23 namespace {
24 
25 
26 class DummyValidator : public Teuchos::ParameterEntryValidator
27 {
28 public:
29 
30  const std::string getXMLTypeName() const { return ""; }
31  virtual void printDoc(std::string const& docString, std::ostream &out) const {}
32  virtual ValidStringsList validStringValues() const { return Teuchos::null; }
33  virtual void validate(
34  Teuchos::ParameterEntry const& entry,
35  std::string const& paramName,
36  std::string const& sublistName
37  ) const
38  {}
39 };
40 
41 
42 class SimpleModifier : public Teuchos::ParameterListModifier
43 {
44 public:
45 
46  SimpleModifier() : Teuchos::ParameterListModifier("Simple Modifier"){}
47 
48  void modify(Teuchos::ParameterList &pl, Teuchos::ParameterList &valid_pl) const
49  {
50  expandSublistsUsingBaseName("SubA", pl, valid_pl);
51  }
52 
53  void reconcile(Teuchos::ParameterList &pl) const
54  {
55  // If A and B are less than 0.0 then throw an error
56  TEUCHOS_TEST_FOR_EXCEPTION(pl.get<double>("A") < 0.0 && pl.get<double>("B") < 0.0,
57  std::logic_error, "Parameters A and B can't both be less than 0.0");
58  }
59 };
60 
61 
62 class SimpleSubModifier : public Teuchos::ParameterListModifier {
63 
64 public:
65 
66  SimpleSubModifier() : Teuchos::ParameterListModifier("Simple Sub Modifier"){}
67 
68  void modify(Teuchos::ParameterList &pl, Teuchos::ParameterList &valid_pl) const
69  {
70  expandSublistsUsingBaseName("SubB", pl, valid_pl);
71  }
72  void reconcile(Teuchos::ParameterList &pl) const
73  {
74  // If E and F are less than 10 then throw an error
75  const int max_CD = 10;
76  TEUCHOS_TEST_FOR_EXCEPTION(pl.get<int>("C") > max_CD && pl.get<int>("D") > max_CD,
77  std::logic_error, "Parameters C and D can't both be greater than 10")
78  }
79 };
80 
81 
82 class ReconciliationModifier1 : public Teuchos::ParameterListModifier
83 {
84 public:
85  ReconciliationModifier1() : Teuchos::ParameterListModifier("Reconciliation Modifier 1"){}
86  void reconcile(Teuchos::ParameterList &pl) const
87  {
88  // This reconciliation routine needs the ReconciliationModifier2's reconcile method
89  // to be run first to create the "e" parameter.
90  Teuchos::ParameterList &subA = pl.sublist("A");
91  pl.set("b", subA.get<int>("e"));
92  }
93 };
94 
95 
96 class ReconciliationModifier2 : public Teuchos::ParameterListModifier
97 {
98 public:
99  ReconciliationModifier2() : Teuchos::ParameterListModifier("Reconciliation Modifier 2"){}
100  void reconcile(Teuchos::ParameterList &pl) const
101  {
102  // Add a convenience parameter
103  pl.set("e", pl.get<int>("c") + pl.get<int>("d"));
104  }
105 };
106 
107 
108 } // namespace
109 
110 
111 namespace Teuchos {
112 
113 
114 //
115 // Test help utilities
116 //
117 
118 
120 {
121  ParameterList PL_Main("PL_Main");
122  const std::string Direction_Doc = "This sublist controls how direction is computed.";
123  ParameterList &PL_Direction = PL_Main.sublist("Direction", false, Direction_Doc);
124  ParameterList &PL_Newton = PL_Direction.sublist("Newton");
125  PL_Newton.sublist("Linear Solver");
126  PL_Main.sublist("Line Search");
127  return PL_Main;
128 }
129 
130 
131 
133 {
134 
135  ParameterList PL_Main_valid("PL_Main_valid");
136  PL_Main_valid.setParameters(createMainPL());
137 
138  // Create a validator for the "Nonlinear Solver" parameter
139  setStringToIntegralParameter<int>(
140  "Nonlinear Solver",
141  "Line Search Based",
142  "Selects the type of nonlinear solver to use",
143  tuple<std::string>("Line Search Based","Trust Region Based"),
144  &PL_Main_valid
145  );
146 
147  // Create a validator for the parameter "Line Search"->"Polynomial"->"Max Iters"
148  // that accepts an 'int', a 'double' or a 'std::string' value!
151  linesearchMaxItersValidator = rcp(
154  AcceptedTypes(false).allowInt(true).allowDouble(true).allowString(true)
155  )
156  );
157  PL_Main_valid.sublist("Line Search").sublist("Polynomial").set(
158  "Max Iters",3
159  ,"The maximum number of inner linear search iterations allowed."
160  ,linesearchMaxItersValidator
161  );
162 
163  // Create a validator for the parameter "Direction"->"Newton"->"Linear Solver"->"Tol"
164  // that accepts a 'double' or a 'std::string' value!
166  linSolveTolValidator = rcp(
169  AcceptedTypes(false).allowDouble(true).allowString(true)
170  )
171  );
172  PL_Main_valid.sublist("Direction",true).sublist("Newton",true)
173  .sublist("Linear Solver",true).set(
174  "Tol", double(1e-5)
175  ,"Select the linear solve tolerance"
176  ,linSolveTolValidator
177  );
178 
179  // Create a validator for the parameter "Elements"
180  // that accepts an 'int', a 'long long' or a 'std::string' value!
182  elementsValidator = rcp(
185  AcceptedTypes(false).allowInt(true).allowLongLong(true).allowString(true)
186  )
187  );
188  typedef long long LL;
189  PL_Main_valid.set(
190  "Elements", LL(72057594037927936ll) // 2^56
191  ,"Number of finite elements to generate"
192  ,elementsValidator
193  );
194 
195  return PL_Main_valid;
196 
197 }
198 
199 
200 //
201 // Unit tests
202 //
203 
204 
205 TEUCHOS_UNIT_TEST( ParameterList, construct_default )
206 {
207  ParameterList pl;
208  TEST_EQUALITY_CONST(pl.name(), "ANONYMOUS");
210 }
211 
212 
213 TEUCHOS_UNIT_TEST( ParameterList, construct_withName )
214 {
215  ParameterList pl("someName");
216  TEST_EQUALITY_CONST(pl.name(), "someName");
218 }
219 
220 
221 TEUCHOS_UNIT_TEST( ParameterList, createParameterList_empty )
222 {
223  RCP<ParameterList> pl = createParameterList();
224  TEST_ASSERT(nonnull(pl));
225  TEST_EQUALITY_CONST(pl->name(), "ANONYMOUS");
226 }
227 
228 
229 TEUCHOS_UNIT_TEST( ParameterList, createParameterList_withName )
230 {
231  RCP<ParameterList> pl = createParameterList("dummyName");
232  TEST_ASSERT(nonnull(pl));
233  TEST_EQUALITY_CONST(pl->name(), "dummyName");
234 }
235 
236 
238 {
239  ParameterList pl;
240 
241  out << "\n";
242  ECHO(pl.set("my int", 3));
243 
244  out << "\n";
245  ECHO(const ParameterEntry& my_int_c_param = getConst(pl).getEntry("my int"));
246  TEST_EQUALITY_CONST(my_int_c_param.isUsed(), false);
247  TEST_EQUALITY_CONST(my_int_c_param.isList(), false);
248  TEST_EQUALITY_CONST(my_int_c_param.isDefault(), false);
249  TEST_EQUALITY_CONST(my_int_c_param.docString(), "");
250  TEST_ASSERT(is_null(my_int_c_param.validator()));
251  TEST_EQUALITY_CONST(getValue<int>(my_int_c_param), 3);
252  ECHO(const bool param_isType_int1 = my_int_c_param.isType<int>());
253  TEST_EQUALITY_CONST(param_isType_int1, true);
254  ECHO(const bool param_isType_double1 = my_int_c_param.isType<double>());
255  TEST_EQUALITY_CONST(param_isType_double1, false);
256 
257  out << "\n";
258  ECHO(const ParameterEntry& my_int_param = pl.getEntry("my int"));
259  TEST_EQUALITY_CONST(my_int_param.isUsed(), true);
260 
261  out << "\n";
262  ECHO(const int my_int = pl.get<int>("my int"));
263  TEST_EQUALITY_CONST(my_int, 3);
264 
265 }
266 
267 
268 TEUCHOS_UNIT_TEST( ParameterList, setParametersWithModifier )
269 {
271  RCP<ParameterListModifier> modifier1 = rcp(new ParameterListModifier("Modifier 1"));
272  RCP<ParameterListModifier> modifier2 = rcp(new ParameterListModifier("Modifier 2"));
273  //pl1:
274  // A: 1.0
275  // SubA: # with `modifier1`
276  // B: 2
277  ParameterList pl1("pl");
278  pl1.set("A", 1.0);
279  pl1.sublist("SubA", modifier1).set("B", 2);
280  ParameterList pl2("pl");
281  pl2.setParameters(pl1);
282  // Show that all values and the modifier were copied from `pl1` to `pl2`
283  TEST_EQUALITY(*pl2.sublist("SubA").getModifier(), *modifier1);
284  TEST_EQUALITY(pl1, pl2);
285  pl1.sublist("SubA").setModifier(Teuchos::null);
286  TEST_ASSERT(is_null(pl1.sublist("SubA").getModifier()));
287  TEST_EQUALITY(*pl2.sublist("SubA").getModifier(), *modifier1);
288  // Now test that `setParametersNotAlreadySet` has the correct behavior
289  pl1.sublist("SubA").setModifier(modifier1);
290  pl1.sublist("SubB", modifier2).set("C", 3);
292  TEST_EQUALITY(*pl2.sublist("SubB").getModifier(), *modifier2);
293  TEST_EQUALITY(pl1, pl2);
294  // Test that sublists with their modifiers and parameters are correctly
295  // overwritten in `setParameters`
296  pl1 = ParameterList();
297  pl1.sublist("SubA", modifier1).set("A", 1);
298  pl2 = ParameterList();
299  pl2.sublist("SubA", modifier2).set("B", 2);
300  pl2.setParameters(pl1);
301  // pl2 should look just like pl1 except with the extra "B" parameter
302  ParameterList pl_expected = ParameterList();
303  pl_expected.sublist("SubA", modifier1).set("B", 2).set("A", 1);
304  TEST_EQUALITY(pl_expected, pl2);
305 }
306 
307 
308 TEUCHOS_UNIT_TEST( ParameterList, param_isParameter_isSublist_isType )
309 {
310  ParameterList pl;
311  ECHO(pl.set("my int", 3));
312  ECHO(const int my_int = pl.get<int>("my int"));
313  TEST_EQUALITY_CONST(my_int, 3);
314  TEST_EQUALITY_CONST(pl.isParameter("my int"), true);
315  TEST_EQUALITY_CONST(pl.isParameter("Does not Exist"), false);
316  TEST_EQUALITY_CONST(pl.isSublist("my int"), false);
317  TEST_EQUALITY_CONST(pl.isSublist("Does not exist"), false);
318  TEST_EQUALITY_CONST(pl.isType<int>("my int"), true);
319  TEST_EQUALITY_CONST(pl.isType<double>("my int"), false);
320  TEST_EQUALITY_CONST(pl.isType("my int", static_cast<int*>(0)), true);
321  TEST_EQUALITY_CONST(pl.isType("my int", static_cast<double*>(0)), false);
322 }
323 
324 
325 TEUCHOS_UNIT_TEST( ParameterList, sublist_isParameter_isSublist_isType )
326 {
327  ParameterList pl;
328  ECHO(pl.sublist("my sublist").set("my int", 3));
329  ECHO(const int my_int = getConst(pl).sublist("my sublist").get<int>("my int"));
330  TEST_EQUALITY_CONST(my_int, 3);
331  TEST_EQUALITY_CONST(pl.isParameter("my sublist"), true); // Should be false, but backward compatiable!
332  TEST_EQUALITY_CONST(pl.isParameter("Does not Exist"), false);
333  TEST_EQUALITY_CONST(pl.isSublist("my sublist"), true);
334  TEST_EQUALITY_CONST(pl.isType<ParameterList>("my sublist"), true);
335  TEST_EQUALITY_CONST(pl.isType<double>("my sublist"), false);
336  TEST_EQUALITY_CONST(pl.isType("my sublist", static_cast<ParameterList*>(0)), true);
337  TEST_EQUALITY_CONST(pl.isType("my sublist", static_cast<double*>(0)), false);
338 }
339 
340 
342 {
343  ParameterList pl;
344  ECHO(pl.set("my int", 3, "Some documentation"));
345  ECHO(const ParameterEntry& my_int_param = getConst(pl).getEntry("my int"));
346  TEST_EQUALITY_CONST(my_int_param.docString(), "Some documentation");
347  TEST_ASSERT(is_null(my_int_param.validator()));
348 }
349 
350 
351 TEUCHOS_UNIT_TEST( ParameterList, set_doc_validator )
352 {
353  ParameterList pl;
354  ECHO(pl.set("my int", 3, "Some documentation", rcp(new DummyValidator)));
355  ECHO(const ParameterEntry& my_int_param = getConst(pl).getEntry("my int"));
356  TEST_EQUALITY_CONST(my_int_param.docString(), "Some documentation");
357  TEST_NOTHROW(rcp_dynamic_cast<const DummyValidator>(my_int_param.validator(), true));
358 }
359 
360 
361 TEUCHOS_UNIT_TEST( ParameterList, set_invalid_int_first )
362 {
363  ParameterList pl;
365  validator(new Teuchos::EnhancedNumberValidator<int>(0, 1)));
366  TEST_THROW(pl.set("my int", -1, "", validator),
369 }
370 
371 
372 TEUCHOS_UNIT_TEST( ParameterList, set_invalid_int_second )
373 {
374  ParameterList pl;
376  validator(new Teuchos::EnhancedNumberValidator<int>(0, 1)));
377  TEST_NOTHROW(pl.set("my int", 1, "", validator));
379  TEST_EQUALITY_CONST(pl.get<int>("my int"), 1);
381  TEST_EQUALITY_CONST(pl.get<int>("my int"), 1);
382 }
383 
384 
386 {
387  ParameterList pl;
388  ECHO(pl.setEntry("my int", ParameterEntry(as<int>(3), true, true, "Some doc", rcp(new DummyValidator))));
389  ECHO(const ParameterEntry& my_int_param = getConst(pl).getEntry("my int"));
390  TEST_EQUALITY_CONST(my_int_param.docString(), "Some doc");
391  ECHO(const int my_int_1 = my_int_param.getValue<int>(0));
392  TEST_EQUALITY_CONST(my_int_1, 3);
393  TEST_EQUALITY_CONST(my_int_param.isUsed(), true);
394  TEST_EQUALITY_CONST(my_int_param.isList(), false); // The isList entry is ignored!
395  TEST_INEQUALITY_CONST(rcp_dynamic_cast<const DummyValidator>(my_int_param.validator(), true), null);
396 }
397 
398 
399 TEUCHOS_UNIT_TEST( ParameterList, set_int_twice_keep_validator )
400 {
401  ParameterList pl;
402  ECHO(pl.setEntry("my int", ParameterEntry(as<int>(3), true, true, "Some doc", rcp(new DummyValidator))));
403  {
404  ECHO(const ParameterEntry& my_int_param = getConst(pl).getEntry("my int"));
405  TEST_INEQUALITY_CONST(rcp_dynamic_cast<const DummyValidator>(my_int_param.validator(), true), null);
406  }
407  TEST_EQUALITY_CONST(pl.get<int>("my int"), 3);
408  ECHO(pl.set("my int", 4));
409  TEST_EQUALITY_CONST(pl.get<int>("my int"), 4);
410  {
411  ECHO(const ParameterEntry& my_int_param = getConst(pl).getEntry("my int"));
412  TEST_INEQUALITY_CONST(rcp_dynamic_cast<const DummyValidator>(my_int_param.validator(), true), null);
413  }
414 }
415 
416 
417 TEUCHOS_UNIT_TEST( ParameterList, set_get_char_str )
418 {
419  ParameterList pl;
420 
421  ECHO(char dummy_str_1[] = "dummy str 1");
422  ECHO(pl.set("dummy 1", dummy_str_1));
423  ECHO(const std::string dummy_1 = pl.get<std::string>("dummy 1"));
424  TEST_EQUALITY_CONST(dummy_1, "dummy str 1");
425 
426  ECHO(const char dummy_str_const_2[] = "dummy str 2");
427  ECHO(pl.set("dummy 2", dummy_str_const_2));
428  ECHO(const std::string dummy_2 = pl.get<std::string>("dummy 2"));
429  TEST_EQUALITY_CONST(dummy_2, "dummy str 2");
430 
431 }
432 
433 
435 {
436  ParameterList pl;
437 
438  ECHO(const std::string dummy_str = "dummy str");
439  ECHO(pl.set("my str", dummy_str));
440  ECHO(const std::string my_str = pl.get<std::string>("my str"));
441  TEST_EQUALITY_CONST(my_str, "dummy str");
442 
443 }
444 
445 TEUCHOS_UNIT_TEST( ParameterList, set_string_move_semantics)
446 {
447  ParameterList pl;
448 
449  ECHO(std::string my_str_1{"my text 1"});
450  ECHO(pl.set("my string 1", std::move(my_str_1)));
451 
452  // Check that the parameter value was moved by checking that my_str_1 is now empty.
453  TEST_ASSERT(my_str_1.empty());
454 
455  TEST_EQUALITY_CONST(pl.get<std::string>("my string 1"), "my text 1");
456 }
457 
458 TEUCHOS_UNIT_TEST( ParameterList, set_string_specified_template_argument)
459 {
460  // Check the templated set method and its overload when the template argument is specified.
461 
462  ParameterList pl;
463 
464  // The parameter value can be passed by rvalue reference.
465  // The main templated set method is called, and the parameter value is moved.
466  ECHO(std::string my_str_2{"my text 2"});
467  ECHO(pl.set<std::string>("my string 2", std::move(my_str_2)));
468  TEST_ASSERT(my_str_2.empty());
469  TEST_EQUALITY_CONST(pl.get<std::string>("my string 2"), "my text 2");
470 
471  // The parameter value cannot be passed by rvalue reference.
472  // The overload of the templated set method is called, and the parameter value is not moved.
473  ECHO(std::string my_str_3{"my text 3"});
474  ECHO(pl.set<std::string>("my string 3", my_str_3));
475  TEST_ASSERT( ! my_str_3.empty());
476  TEST_EQUALITY_CONST(pl.get<std::string>("my string 3"), "my text 3");
477 
478  ECHO(const std::string my_str_4{"my text 4"});
479  ECHO(pl.set<std::string>("my string 4", my_str_4));
480  TEST_ASSERT( ! my_str_4.empty());
481  TEST_EQUALITY_CONST(pl.get<std::string>("my string 4"), "my text 4");
482 
483  ECHO(pl.set<std::string>("my string 5", "my text 5"));
484  TEST_EQUALITY_CONST(pl.get<std::string>("my string 5"), "my text 5");
485 }
486 
488 {
489  operator const int&() const { return value; }
490 
491  int value;
492 };
493 
494 TEUCHOS_UNIT_TEST( ParameterList, set_int_user_defined_conversion_function)
495 {
496  // Check the templated set method and its overload when the template argument is specified
497  // and the parameter is set via a user defined conversion function.
498  ParameterList pl;
499 
500  ECHO(MyWrappedInt my_wrapped_int{42});
501  ECHO(pl.set<int>("my int", my_wrapped_int));
502  TEST_EQUALITY_CONST(pl.get<int>("my int"), my_wrapped_int.value);
503 }
504 
505 TEUCHOS_UNIT_TEST( ParameterList, get_nonexisting_param )
506 {
507  ParameterList pl;
508  TEST_THROW(pl.getEntry("Does not exist 1"), Exceptions::InvalidParameterName);
509  TEST_THROW(pl.get<int>("Does not exist 2"), Exceptions::InvalidParameterName);
510  TEST_THROW(getConst(pl).get<int>("Does not exist 3"), Exceptions::InvalidParameterName);
511  TEST_EQUALITY(pl.getPtr<int>("Does not exist 4"), static_cast<int*>(0));
512  TEST_EQUALITY(getConst(pl).getPtr<int>("Does not exist 5"), static_cast<const int*>(0));
513  ECHO(char raw_str[] = "dummy");
514  TEST_EQUALITY_CONST(pl.get("Does not exist 6", raw_str), "dummy");
515  ECHO(const char raw_c_str[] = "dummy");
516  TEST_EQUALITY_CONST(pl.get("Does not exist 7", raw_c_str), "dummy");
517  ECHO(const std::string str = "dummy");
518  TEST_EQUALITY_CONST(pl.get("Does not exist 8", str), "dummy");
519  TEST_THROW(pl.getEntry("Does not exist 9"), Exceptions::InvalidParameterName);
520  TEST_THROW(getConst(pl).getEntry("Does not exist 10"), Exceptions::InvalidParameterName);
521  TEST_EQUALITY(pl.getEntryPtr("Does not exist 11"), static_cast<ParameterEntry*>(0));
522  TEST_EQUALITY(getConst(pl).getEntryPtr("Does not exist 12"), static_cast<const ParameterEntry*>(0));
523  TEST_EQUALITY(pl.getEntryRCP("Does not exist 13"), RCP<ParameterEntry>());
524  TEST_EQUALITY(getConst(pl).getEntryRCP("Does not exist 14"), RCP<const ParameterEntry>());
525 }
526 
527 
528 TEUCHOS_UNIT_TEST( ParameterList, get_existing_incorrect_type )
529 {
530  ParameterList pl;
531  pl.set("my int", 4);
532  TEST_THROW(pl.get<double>("my int"), Exceptions::InvalidParameterType);
533  // ToDo: Assert the contents of the error message
534 }
535 
536 
538 {
539  ParameterList pl;
540  pl.set("my int", 4);
541  TEST_EQUALITY_CONST(pl.getPtr<int>("Does not Exist"), static_cast<int*>(0));
542  TEST_INEQUALITY_CONST(pl.getPtr<int>("my int"), static_cast<int*>(0));
543  TEST_EQUALITY_CONST(*pl.getPtr<int>("my int"), 4);
544  TEST_EQUALITY_CONST(pl.getPtr<double>("my int"), static_cast<double*>(0));
545  TEST_EQUALITY_CONST(getConst(pl).getPtr<int>("Does not Exist"), static_cast<const int*>(0));
546  TEST_INEQUALITY_CONST(getConst(pl).getPtr<int>("my int"), static_cast<int*>(0));
547  TEST_EQUALITY_CONST(*getConst(pl).getPtr<int>("my int"), 4);
548  TEST_EQUALITY_CONST(getConst(pl).getPtr<double>("my int"), static_cast<const double*>(0));
549 }
550 
551 
553 {
554  ParameterList pl;
555  pl.set("my int", 4);
556  TEST_EQUALITY_CONST(pl.getEntryRCP("Does not Exist"), null);
557  TEST_INEQUALITY_CONST(pl.getEntryRCP("my int"), null);
558  TEST_EQUALITY_CONST(pl.getEntryRCP("my int")->getValue<int>(0), 4);
559  TEST_EQUALITY_CONST(getConst(pl).getEntryRCP("Does not Exist"), null);
560  TEST_INEQUALITY_CONST(getConst(pl).getEntryRCP("my int"), null);
561  TEST_EQUALITY_CONST(getConst(pl).getEntryRCP("my int")->getValue<int>(0), 4);
562 }
563 
564 
565 // Test nonconstFind()
566 
567 // Test find()
568 
569 
570 TEUCHOS_UNIT_TEST( ParameterList, get_default_then_change )
571 {
572  ParameterList pl;
573  ECHO(int &my_int = pl.get("my int", 3));
574  TEST_EQUALITY_CONST(my_int, 3);
575  TEST_EQUALITY_CONST(pl.get<int>("my int"), 3);
576  ECHO(my_int = 5);
577  TEST_EQUALITY_CONST(pl.get<int>("my int"), 5);
578 }
579 
580 
582 {
583  ParameterList pl;
585  ECHO(pl.set("my int", 2));
587  TEST_EQUALITY_CONST(pl.get<int>("my int"), 2);
588  ECHO(const bool param_was_removed_1 = pl.remove("my int"));
589  TEST_EQUALITY_CONST(param_was_removed_1, true);
591  TEST_THROW(pl.get<int>("my int"), Exceptions::InvalidParameterName);
593  ECHO(const bool param_was_removed_2 = pl.remove("my int", false));
594  TEST_EQUALITY_CONST(param_was_removed_2, false);
595 }
596 
597 
598 TEUCHOS_UNIT_TEST( ParameterList, get_nonexisting_sublist_default )
599 {
600  ParameterList pl("Base");
601  ECHO(pl.sublist("my sublist"));
602  ECHO(const ParameterEntry &sublistParam = pl.getEntry("my sublist"));
603  TEST_EQUALITY_CONST(sublistParam.isUsed(), false);
604  TEST_EQUALITY_CONST(sublistParam.isList(), true);
605  TEST_EQUALITY_CONST(sublistParam.isDefault(), false);
606  TEST_EQUALITY_CONST(sublistParam.docString(), "");
607  TEST_EQUALITY_CONST(sublistParam.getValue<ParameterList>(0).name(), "Base->my sublist");
608 }
609 
610 
611 TEUCHOS_UNIT_TEST( ParameterList, get_nonexisting_sublist_docString )
612 {
613  ParameterList pl("Base");
614  ECHO(pl.sublist("my sublist", false, "My great sublist"));
615  ECHO(const ParameterEntry &sublistParam = pl.getEntry("my sublist"));
616  TEST_EQUALITY_CONST(sublistParam.isUsed(), false);
617  TEST_EQUALITY_CONST(sublistParam.isList(), true);
618  TEST_EQUALITY_CONST(sublistParam.isDefault(), false);
619  TEST_EQUALITY_CONST(sublistParam.docString(), "My great sublist");
620  TEST_EQUALITY_CONST(sublistParam.getValue<ParameterList>(0).name(), "Base->my sublist");
621 }
622 
623 
624 TEUCHOS_UNIT_TEST( ParameterList, get_nonexisting_sublist_mustAlreadyExist )
625 {
626  ParameterList pl("Base");
627  TEST_THROW(pl.sublist("my sublist", true), Exceptions::InvalidParameterName);
628  // ToDo: Examine the actual structure of the error message
629 }
630 
631 
632 TEUCHOS_UNIT_TEST( ParameterList, get_existing_sublist_nonsublist )
633 {
634  ParameterList pl("Base");
635  ECHO(pl.set("my sublist", 1)); // Not a sublist!
637  // ToDo: Examine the actual structure of the error message
638 }
639 
640 
641 TEUCHOS_UNIT_TEST( ParameterList, get_existing_sublist_nonconst )
642 {
643  ParameterList pl("Base");
644  ECHO(pl.sublist("my sublist").set("my int", 2));
645  ECHO(const int my_int = pl.sublist("my sublist").get<int>("my int"));
646  TEST_EQUALITY_CONST(my_int, 2);
647 }
648 
649 
650 TEUCHOS_UNIT_TEST( ParameterList, get_existing_sublist_const )
651 {
652  ParameterList pl("Base");
653  ECHO(pl.sublist("my sublist").set("my int", 2));
654  ECHO(const int my_int = getConst(pl).sublist("my sublist").get<int>("my int"));
655  TEST_EQUALITY_CONST(my_int, 2);
656 }
657 
658 
659 TEUCHOS_UNIT_TEST( ParameterList, get_nonexisting_sublist_const )
660 {
661  ParameterList pl("Base");
662  TEST_THROW(getConst(pl).sublist("my sublist"), Exceptions::InvalidParameterName);
663  // ToDo: Examine the actual structure of the error message
664 }
665 
666 
667 TEUCHOS_UNIT_TEST( ParameterList, get_existing_sublist_const_nonsublist )
668 {
669  ParameterList pl("Base");
670  ECHO(pl.set("my sublist", 1)); // Not a sublist!
671  TEST_THROW(getConst(pl).sublist("my sublist"), Exceptions::InvalidParameterType);
672  // ToDo: Examine the actual structure of the error message
673 }
674 
675 
677 {
678  ParameterList PL_Main("PL_Main");
679  const std::string Direction_Doc = "This sublist controls how direction is computed.";
680  ParameterList& PL_Direction = PL_Main.sublist("Direction", false, Direction_Doc);
681  ParameterList& PL_LineSearch = PL_Main.sublist("Line Search");
682  out << "PL_Main=\n" << PL_Main << "\n";
683  TEST_EQUALITY_CONST(PL_Main.name(), "PL_Main");
684  TEST_EQUALITY_CONST(PL_Main.isSublist("Direction"), true);
685  TEST_EQUALITY_CONST(PL_Main.isSublist("Line Search"), true);
686  ECHO(const ParameterList& PL_Direction_2 = getConst(PL_Main).sublist("Direction"));
687  TEST_EQUALITY(&PL_Direction, &PL_Direction_2);
688  ECHO(const ParameterList& PL_LineSearch_2 = getConst(PL_Main).sublist("Line Search"));
689  TEST_EQUALITY(&PL_LineSearch, &PL_LineSearch_2);
690  TEST_EQUALITY_CONST(getConst(PL_Main).sublist("Direction").name(), "PL_Main->Direction");
691  TEST_EQUALITY_CONST(PL_Direction.name(), "PL_Main->Direction");
692  TEST_EQUALITY_CONST(PL_LineSearch.name(), "PL_Main->Line Search");
693 }
694 
695 
696 TEUCHOS_UNIT_TEST( ParameterList, sublist_scenario_1 )
697 {
698  // This is the scenario in the orginal testing program
699  ParameterList PL_Main("PL_Main");
700  const std::string Direction_Doc = "This sublist controls how direction is computed.";
701  ParameterList &PL_Direction = PL_Main.sublist("Direction", false, Direction_Doc);
702  ParameterList &PL_Newton = PL_Direction.sublist("Newton");
703  ParameterList &PL_LinSol = PL_Newton.sublist("Linear Solver");
704  ParameterList &PL_LineSearch = PL_Main.sublist("Line Search");
705  out << "PL_Main=\n" << PL_Main << "\n";
706  TEST_EQUALITY_CONST(PL_Main.name(), "PL_Main");
707  TEST_EQUALITY_CONST(PL_Main.isSublist("Direction"), true);
708  ECHO(const ParameterList& PL_Direction_2 = getConst(PL_Main).sublist("Direction"));
709  TEST_EQUALITY(&PL_Direction, &PL_Direction_2);
710  TEST_EQUALITY_CONST(getConst(PL_Main).sublist("Direction").name(), "PL_Main->Direction");
711  TEST_EQUALITY_CONST(PL_Direction.name(), "PL_Main->Direction");
712  TEST_EQUALITY_CONST(PL_Direction.isSublist("Newton"), true);
713  TEST_EQUALITY_CONST(PL_Newton.isSublist("Linear Solver"), true);
714  TEST_EQUALITY_CONST(PL_Newton.name(), "PL_Main->Direction->Newton");
715  TEST_EQUALITY_CONST(PL_Newton.isSublist("Linear Solver"), true);
716  TEST_EQUALITY_CONST(PL_LinSol.name(), "PL_Main->Direction->Newton->Linear Solver");
717  TEST_EQUALITY_CONST(PL_Main.isSublist("Line Search"), true);
718  TEST_EQUALITY_CONST(PL_LineSearch.name(), "PL_Main->Line Search");
719 }
720 
721 
722 TEUCHOS_UNIT_TEST( ParameterList, copy_constructor )
723 {
724  ECHO(ParameterList pl1("A"));
725  ECHO(pl1.set("my int", 2));
726  ECHO(ParameterList pl2(pl1));
727  TEST_EQUALITY_CONST(pl2.name(), "A");
728  TEST_EQUALITY_CONST(pl2.get<int>("my int"), 2);
729 }
730 
731 
732 TEUCHOS_UNIT_TEST( ParameterList, assignment_operator )
733 {
734  ECHO(ParameterList pl1("A"));
735  ECHO(pl1.set("my int", 2));
736  ECHO(ParameterList pl2);
737  ECHO(const ParameterList &pl2_ref = pl2 = pl1);
738  TEST_EQUALITY_CONST(&pl2_ref, &pl2);
739  TEST_EQUALITY_CONST(pl2.name(), "A");
740  TEST_EQUALITY_CONST(pl2.get<int>("my int"), 2);
741 }
742 
743 
744 TEUCHOS_UNIT_TEST( ParameterList, iterator_params )
745 {
746  typedef ParameterList::ConstIterator ConstIter;
747  ParameterList pl;
748  pl.set("c", 1);
749  pl.set("a", 2);
750  pl.set("b", 3);
751  ConstIter pl_itr = pl.begin();
752  TEST_EQUALITY_CONST(pl_itr->first, "c");
753  TEST_EQUALITY_CONST(pl_itr->second.getValue<int>(0), 1);
754  ECHO(++pl_itr);
755  TEST_EQUALITY_CONST(pl_itr->first, "a");
756  TEST_EQUALITY_CONST(pl_itr->second.getValue<int>(0), 2);
757  ECHO(++pl_itr);
758  TEST_EQUALITY_CONST(pl_itr->first, "b");
759  TEST_EQUALITY_CONST(pl_itr->second.getValue<int>(0), 3);
760  ECHO(++pl_itr);
761  TEST_ITER_EQUALITY(pl_itr, pl.end());
762 }
763 
764 
765 TEUCHOS_UNIT_TEST( ParameterList, iterator_params_sublists )
766 {
767  typedef ParameterList::ConstIterator ConstIter;
768  ParameterList pl("base");
769  pl.set("c", 1);
770  pl.sublist("a");
771  pl.set("b", 3);
772  ConstIter pl_itr = pl.begin();
773  TEST_EQUALITY_CONST(pl_itr->first, "c");
774  TEST_EQUALITY_CONST(pl_itr->second.getValue<int>(0), 1);
775  ECHO(++pl_itr);
776  TEST_EQUALITY_CONST(pl_itr->first, "a");
777  TEST_EQUALITY_CONST(pl_itr->second.getValue<ParameterList>(0).name(), "base->a");
778  ECHO(++pl_itr);
779  TEST_EQUALITY_CONST(pl_itr->first, "b");
780  TEST_EQUALITY_CONST(pl_itr->second.getValue<int>(0), 3);
781  ECHO(++pl_itr);
782  TEST_ITER_EQUALITY(pl_itr, pl.end());
783 }
784 
785 // Test iterator access after removing params
786 
787 // Test iterator access after removing sublists
788 
789 
790 TEUCHOS_UNIT_TEST( ParameterList, operatorEqualityWithEmpty )
791 {
792  // An empty list should not be equal to a full list
795  TEST_ASSERT( A == B );
796  A.set("Hello","World");
797  TEST_ASSERT( A != B );
798  B.set("Hello","World");
799  TEST_ASSERT( A == B );
800 }
801 
802 
803 TEUCHOS_UNIT_TEST( ParameterList, operatorEqualityDifferentSublistNames )
804 {
805  // Sublists with different names should not be equal
808  A.sublist("Bob");
809  B.sublist("Tom");
810  TEST_ASSERT( A != B );
811 }
812 
813 
814 TEUCHOS_UNIT_TEST( ParameterList, operatorEqualityDifferentLengths )
815 {
818  A.set("A","a");
819  A.set("B","b");
820  A.set("C","c");
821  A.print(out);
822 
823  B.set("A","a");
824  B.set("B","b");
825  B.print(out);
826 
827  TEST_ASSERT( A != B );
828 
829  B.set("C","c");
830  TEST_ASSERT( A == B );
831 }
832 
833 
834 TEUCHOS_UNIT_TEST( ParameterList, haveSameValuesWithEmpty )
835 {
838  TEST_ASSERT( haveSameValues(A,B) );
839  A.set("a",1);
840  TEST_ASSERT( !haveSameValues(A,B) );
841  A.set("b",2);
842  B.set("a",1);
843  B.set("b",2);
844  TEST_ASSERT( haveSameValues(A,B) );
845 }
846 
847 
848 TEUCHOS_UNIT_TEST( ParameterList, haveSameValuesDifferentSublistNames )
849 {
852  A.sublist("Smith").set("People",4);
853  B.sublist("Jones").set("People",4);
854  TEST_ASSERT( !haveSameValues(A,B) ); // sublist names matter
855 }
856 
857 
858 TEUCHOS_UNIT_TEST( ParameterList, haveSameValuesSortedReversedOrder )
859 {
860  ParameterList A, B;
861  A.set("a",1);
862  A.set("b",2);
863  // Create second list with the same entries but different order
864  B.set("b",2);
865  B.set("a",1);
866  TEST_ASSERT( haveSameValuesSorted(A,B) );
867  B.set("c",3);
868  TEST_ASSERT( !haveSameValuesSorted(A,B) ); // check for length
869 }
870 
871 
872 TEUCHOS_UNIT_TEST( ParameterList, haveSameValuesSortedNested)
873 {
874  ParameterList A, B;
875  ParameterList &asublist = A.sublist("A");
876  asublist.set("a",1);
877  asublist.set("b",2);
878  ParameterList &bsublist = B.sublist("A");
879  bsublist.set("a",1);
880  bsublist.set("b",2);
881  TEST_ASSERT( haveSameValuesSorted(A,B) );
882  asublist.set("c",3);
883  bsublist.set("c",4);
884  TEST_ASSERT( !haveSameValuesSorted(A,B) );
885 }
886 
887 
888 TEUCHOS_UNIT_TEST( ParameterList, validateAgainstSelf )
889 {
890  ParameterList PL_Main = createMainPL();
891  ParameterList PL_Main_valid = createValidMainPL();
892  TEST_NOTHROW(PL_Main.validateParameters(PL_Main_valid));
893 }
894 
895 
896 TEUCHOS_UNIT_TEST( ParameterList, validateParametersAndSetDefaults_default )
897 {
898  // Test for proper behavior when the user doesn't set `Nonlinear Solver`
899  ParameterList PL_Main = createMainPL();
900  ParameterList PL_Main_valid = createValidMainPL();
901  ECHO(PL_Main.validateParametersAndSetDefaults(PL_Main_valid));
902  TEST_NOTHROW(
903  rcp_dynamic_cast<const StringToIntegralParameterEntryValidator<int> >(
904  PL_Main.getEntry("Nonlinear Solver").validator(), true ) );
905  // Make sure the parameter entry is set to default and unused after validation
906  const ParameterEntry &default_entry = PL_Main.getEntry("Nonlinear Solver");
907  TEST_EQUALITY(default_entry.isDefault(), true);
908  TEST_EQUALITY(default_entry.isUsed(), false);
909  // Make sure the value is stored as an integer after validation
910 #if defined(HAVE_TEUCHOS_MODIFY_DEFAULTS_DURING_VALIDATION)
911  TEST_NOTHROW(Teuchos::any_cast<int>(default_entry.getAny()));
912 #endif
913 }
914 
915 
916 TEUCHOS_UNIT_TEST( ParameterList, validateParametersAndSetDefaults_noDefault )
917 {
918  // Now make sure we have the correct behavior when not using a default value
919  ParameterList PL_Main = createMainPL();
920  PL_Main.set("Nonlinear Solver", "Trust Region Based");
921  ParameterList PL_Main_valid = createValidMainPL();
922  PL_Main.validateParametersAndSetDefaults(PL_Main_valid);
923  const ParameterEntry &entry = PL_Main.getEntry("Nonlinear Solver");
924  TEST_EQUALITY(entry.isDefault(), false);
925  TEST_EQUALITY(entry.isUsed(), false);
926 #if defined(HAVE_TEUCHOS_MODIFY_DEFAULTS_DURING_VALIDATION)
927  TEST_NOTHROW(Teuchos::any_cast<int>(entry.getAny()));
928 #endif
929 }
930 
931 
932 TEUCHOS_UNIT_TEST( ParameterList, getIntegralValue_int )
933 {
934  ParameterList PL_Main = createMainPL();
935  ParameterList PL_Main_valid = createValidMainPL();
936  ECHO(PL_Main.set("Nonlinear Solver", "Line Search Based"));
937  ECHO(PL_Main.validateParametersAndSetDefaults(PL_Main_valid));
938  ECHO(const int lineSearchValue = getIntegralValue<int>(PL_Main, "Nonlinear Solver"));
939  TEST_EQUALITY_CONST(lineSearchValue, 0);
940  ECHO(PL_Main.set("Nonlinear Solver", "Trust Region Based"));
941  ECHO(const int trustRegionValue = getIntegralValue<int>(PL_Main, "Nonlinear Solver"));
942  TEST_EQUALITY_CONST(trustRegionValue, 1);
943 }
944 
945 
946 TEUCHOS_UNIT_TEST( ParameterList, replaceScalarParameterWithArray ) {
947  ParameterList pl = ParameterList("Parameter List with Scalar Parameter");
948  const int a_val = 2, b_val = 3;
949  pl.set("A", a_val);
950  pl.set("B", b_val);
951  replaceParameterWithArray<int>("A", "A array", pl);
952  replaceParameterWithArray<int>("B", "B", pl);
953  ParameterList expected_pl = ParameterList("Parameter List with Array Parameter");
954  Array<int> a_array = tuple<int>(a_val), b_array = tuple<int>(b_val);
955  expected_pl.set("A array", a_array);
956  expected_pl.set("B", b_array);
957  TEST_ASSERT(haveSameValuesSorted(expected_pl, pl, true));
958  // Throw an error when trying to overwrite a parameter that already exists but
959  // doesn't have the same name.
960  pl.set("C", 1);
961  TEST_THROW(replaceParameterWithArray<int>("C", "B", pl), std::logic_error);
962  pl.print();
963 }
964 
965 
966 TEUCHOS_UNIT_TEST( ParameterList, simpleModifierModifyReconcile )
967 {
968  RCP<SimpleModifier> modifier = rcp(new SimpleModifier());
969  ParameterList valid_pl("My Valid Parameter List with a Modifier", modifier);
970  //valid_pl before modification
971  // A: 1.0
972  // B: 0.1
973  // SubA:
974  // C: 1
975  valid_pl.set("A", 1.0);
976  valid_pl.set("B", 0.1);
977  valid_pl.sublist("SubA").set("C", 1);
978  ParameterList pl("My Parameter List");
979  pl.set("A", 5.0);
980  pl.set("B", -0.1);
981  pl.sublist("SubA 1").set("C", 3);
982  pl.sublist("SubA 2").set("C", 4);
983  ParameterList expected_valid_pl(valid_pl);
984  expected_valid_pl.remove("SubA");
985  expected_valid_pl.sublist("SubA 1").set("C", 1);
986  expected_valid_pl.sublist("SubA 2").set("C", 1);
987  pl.modifyParameterList(valid_pl);
988  //valid_pl after modification
989  // A: 1.0
990  // B: 0.1
991  // SubA 1:
992  // C: 1
993  // SubA 2:
994  // C: 1
995  TEST_EQUALITY(valid_pl, expected_valid_pl);
996 // std::cout << haveSameValuesSorted(expected_valid_pl, valid_pl, true) << std::endl;
998  TEST_NOTHROW(pl.reconcileParameterList(valid_pl));
999  pl.set("A", -1.0);
1000  TEST_THROW(pl.reconcileParameterList(valid_pl), std::logic_error);
1001  // Test the copy constructor
1002  ParameterList copy_valid_pl(valid_pl);
1003  TEST_EQUALITY(valid_pl, copy_valid_pl);
1004 }
1005 
1006 
1007 TEUCHOS_UNIT_TEST( ParameterList, modify_CopiesModifiers ) {
1008  RCP<ParameterListModifier> mod_top = rcp<ParameterListModifier>(new ParameterListModifier("Modifier Top"));
1009  RCP<ParameterListModifier> mod_A = rcp<ParameterListModifier>(new ParameterListModifier("Modifier A"));
1010  RCP<ParameterListModifier> mod_B = rcp<ParameterListModifier>(new ParameterListModifier("Modifier B"));
1011  ParameterList input{"Plist"}, valid{"Plist", mod_top};
1012  input.sublist("A").sublist("B");
1013  valid.sublist("A", mod_A);
1014  valid.sublist("A").sublist("B", mod_B);
1015  input.modifyParameterList(valid);
1016  // This calls `haveSameModifiers` to make sure they are all copied to `input`
1017  TEST_EQUALITY(input, valid);
1018 }
1019 
1020 
1021 TEUCHOS_UNIT_TEST( ParameterList, nestedSublistExpansion ) {
1023  Teuchos::RCP<SimpleSubModifier> sub_modifier = Teuchos::rcp(new SimpleSubModifier());
1024  // The unmodified (template-like) validation parameter list
1025  ParameterList valid_pl("valid_pl", modifier);
1026  valid_pl.set("A", 1.0);
1027  valid_pl.set("B", 1.0);
1028  valid_pl.sublist("SubA").setModifier(sub_modifier);
1029  valid_pl.sublist("SubA").set("C", 3);
1030  valid_pl.sublist("SubA").set("D", 4);
1031  valid_pl.sublist("SubA").sublist("SubB").set("E", 10);
1032  valid_pl.sublist("SubA").sublist("SubB").set("F", 11);
1033  // The user's input parameter list
1034  ParameterList pl("pl");
1035  pl.set("A", 1.0);
1036  pl.set("B", 2.0);
1037  pl.sublist("SubA 1").set("C", 3);
1038  pl.sublist("SubA 1").set("D", 4);
1039  pl.sublist("SubA 1").sublist("SubB 1").set("E", 51);
1040  pl.sublist("SubA 1").sublist("SubB 1").set("F", 61);
1041  pl.sublist("SubA 1").sublist("SubB 2").set("E", 52);
1042  pl.sublist("SubA 1").sublist("SubB 2").set("F", 62);
1043  pl.sublist("SubA 2").set("C", 3);
1044  pl.sublist("SubA 2").set("D", 4);
1045  pl.sublist("SubA 2").sublist("SubB 3").set("E", 53);
1046  pl.sublist("SubA 2").sublist("SubB 3").set("F", 63);
1047  // The expanded valid parameter list after modification
1048  ParameterList expected_valid_pl("valid_pl_expanded");
1049  expected_valid_pl.set("A", 1.0);
1050  expected_valid_pl.set("B", 1.0);
1051  expected_valid_pl.sublist("SubA 1").set("C", 3);
1052  expected_valid_pl.sublist("SubA 1").set("D", 4);
1053  expected_valid_pl.sublist("SubA 1").sublist("SubB 1").set("E", 10);
1054  expected_valid_pl.sublist("SubA 1").sublist("SubB 1").set("F", 11);
1055  expected_valid_pl.sublist("SubA 1").sublist("SubB 2").set("E", 10);
1056  expected_valid_pl.sublist("SubA 1").sublist("SubB 2").set("F", 11);
1057  expected_valid_pl.sublist("SubA 2").set("C", 3);
1058  expected_valid_pl.sublist("SubA 2").set("D", 4);
1059  expected_valid_pl.sublist("SubA 2").sublist("SubB 3").set("E", 10);
1060  expected_valid_pl.sublist("SubA 2").sublist("SubB 3").set("F", 11);
1061  // Expand the validation parameter list based on the user's input parameter list
1062  pl.modifyParameterList(valid_pl);
1063  // Modified parameter lists aren't equal because they don't have the same modifiers
1064  TEST_ASSERT(valid_pl != expected_valid_pl);
1065  // Test that they are the same except for the modifiers
1066  TEST_ASSERT(haveSameValuesSorted(expected_valid_pl, valid_pl, true));
1067  // Check the equality of the modifiers
1068  expected_valid_pl.setModifier(modifier);
1069  expected_valid_pl.sublist("SubA 1", true).setModifier(sub_modifier);
1070  expected_valid_pl.sublist("SubA 2", true).setModifier(sub_modifier);
1071  TEST_ASSERT(haveSameModifiers(valid_pl, expected_valid_pl));
1072  // Now test the recursive reconciliation
1073  TEST_NOTHROW(pl.reconcileParameterList(valid_pl));
1074  pl.sublist("SubA 1").set("C", 11);
1075  pl.sublist("SubA 1").set("D", 11);
1076  TEST_THROW(pl.reconcileParameterList(valid_pl), std::logic_error);
1077 }
1078 
1079 
1080 TEUCHOS_UNIT_TEST( ParameterList, disableRecursion ) {
1082  Teuchos::RCP<SimpleSubModifier> sub_modifier = Teuchos::rcp(new SimpleSubModifier());
1083  // The unmodified (template-like) validation parameter list
1084  ParameterList valid_pl("valid_pl", modifier);
1085  valid_pl.set("A", 1.0);
1086  valid_pl.set("B", 1.0);
1087  valid_pl.sublist("SubA").setModifier(sub_modifier);
1088  valid_pl.sublist("SubA").set("C", 3.0);
1089  valid_pl.sublist("SubA").set("D", 4);
1090  valid_pl.sublist("SubA").sublist("SubB").set("E", 10);
1091  valid_pl.sublist("SubA").sublist("SubB").set("F", 11);
1092  // The user's input parameter list
1093  ParameterList pl("pl");
1094  pl.set("A", 1.0);
1095  pl.set("B", 2.0);
1096  pl.sublist("SubA 1").set("C", 3);
1097  pl.sublist("SubA 1").set("D", 4);
1098  pl.sublist("SubA 1").sublist("SubB").set("E", 53);
1099  pl.sublist("SubA 1").sublist("SubB").set("E", 63);
1100  // The expanded valid parameter list after modification
1101  ParameterList expected_valid_pl("valid_pl");
1102  expected_valid_pl.set("A", 1.0);
1103  expected_valid_pl.set("B", 1.0);
1104  expected_valid_pl.sublist("SubA 1").set("C", 3.0);
1105  expected_valid_pl.sublist("SubA 1").set("D", 4);
1106  expected_valid_pl.sublist("SubA 1").sublist("SubB").set("E", 10);
1107  expected_valid_pl.sublist("SubA 1").sublist("SubB").set("F", 11);
1108  // Make a copy of the user's input parameter list before it is validated
1109  ParameterList copy_pl(pl);
1110  // The float validator will cast integers in `pl` to floats
1111  RCP<AnyNumberParameterEntryValidator> float_validator = rcp(
1113  AnyNumberParameterEntryValidator::AcceptedTypes(false).allowInt(true).allowDouble(true)));
1114  valid_pl.sublist("SubA").getEntry("C").setValidator(float_validator);
1115  // Don't modify `SubA`
1116  valid_pl.sublist("SubA").disableRecursiveModification();
1117  pl.modifyParameterList(valid_pl);
1118  TEST_ASSERT(haveSameValuesSorted(expected_valid_pl, valid_pl, true));
1119  // Don't validate `SubA 1`
1120  valid_pl.sublist("SubA 1").disableRecursiveValidation();
1121  pl.validateParametersAndSetDefaults(valid_pl);
1122  // If we were to validate `SubA 1` then parameter C would turn into a float and the following test would fail
1123  TEST_ASSERT(haveSameValuesSorted(pl, copy_pl, true));
1124 }
1125 
1126 
1127 TEUCHOS_UNIT_TEST( ParameterList, recursiveValidation ) {
1128  ParameterList valid_pl("valid_pl");
1129  valid_pl.set("A", 1);
1130  valid_pl.sublist("SubA").set("B", 1);
1131  ParameterList pl("pl");
1132  pl.set("A", 1.0);
1133  pl.sublist("SubA").set("B", 2);
1134  ParameterList validated_pl("valid_pl");
1135  validated_pl.set("A", 1.0);
1136  validated_pl.sublist("SubA").set("B", 2.0);
1137  // The float validator will cast integers in `pl` to floats
1138  RCP<AnyNumberParameterEntryValidator> float_validator = rcp(
1140  AnyNumberParameterEntryValidator::AcceptedTypes(false).allowInt(true).allowDouble(true)));
1141  valid_pl.getEntry("A").setValidator(float_validator);
1142  valid_pl.sublist("SubA").getEntry("B").setValidator(float_validator);
1143  pl.validateParametersAndSetDefaults(valid_pl);
1144  // All of the integers in `pl` should be casted to floats in `validated_pl`
1145  TEST_ASSERT(haveSameValuesSorted(validated_pl, pl, true));
1146 }
1147 
1148 
1149 TEUCHOS_UNIT_TEST( ParameterList, recursiveReconciliation ) {
1150  Teuchos::RCP<ReconciliationModifier1> modifier1 = Teuchos::rcp(new ReconciliationModifier1());
1151  Teuchos::RCP<ReconciliationModifier2> modifier2 = Teuchos::rcp(new ReconciliationModifier2());
1152  ParameterList valid_pl("valid_pl");
1153  valid_pl.set("a", 1);
1154  valid_pl.setModifier(modifier1);
1155  valid_pl.sublist("A").setModifier(modifier2);
1156  valid_pl.sublist("A").set("c", 1);
1157  valid_pl.sublist("A").set("d", 1);
1158  ParameterList pl("pl");
1159  pl.set("a", 1);
1160  pl.sublist("A").set("c", 2);
1161  pl.sublist("A").set("d", 3);
1162  ParameterList reconciled_pl("reconciled_pl");
1163  reconciled_pl.set("a", 1);
1164  reconciled_pl.set("b", 5);
1165  reconciled_pl.sublist("A").set("c", 2);
1166  reconciled_pl.sublist("A").set("d", 3);
1167  reconciled_pl.sublist("A").set("e", 5);
1168  pl.reconcileParameterList(valid_pl);
1169  TEST_ASSERT(haveSameValuesSorted(reconciled_pl, pl, true));
1170 }
1171 
1172 
1173 TEUCHOS_UNIT_TEST( ParameterList, attachValidatorRecursively ) {
1174  ParameterList valid_pl("valid_pl");
1175  valid_pl.set("a", 0.);
1176  valid_pl.sublist("A").set("b", 0.);
1177  valid_pl.sublist("A").set("c", 0.);
1178  valid_pl.sublist("A").sublist("AA").set("d", 0.);
1179  ParameterList pl("pl");
1180  pl.set("a", 1);
1181  pl.sublist("A").set("b", 2);
1182  pl.sublist("A").set("c", 3);
1183  pl.sublist("A").sublist("AA").set("d", 4);
1184  ParameterList validated_pl("validated_pl");
1185  validated_pl.set("a", 1.);
1186  validated_pl.sublist("A").set("b", 2.);
1187  validated_pl.sublist("A").set("c", 3.);
1188  validated_pl.sublist("A").sublist("AA").set("d", 4.);
1189  // The float validator will cast integers in `pl` to floats
1190  RCP<AnyNumberParameterEntryValidator> float_validator = rcp(
1192  AnyNumberParameterEntryValidator::AcceptedTypes(false).allowInt(true).allowDouble(true)));
1193  valid_pl.recursivelySetValidator<double>(float_validator, 1);
1194  // This should fail since we only set the float validator on the top level of `valid_pl`
1195  TEST_THROW(pl.validateParametersAndSetDefaults(valid_pl), std::logic_error);
1196  // Now attach the validator to every double
1197  valid_pl.recursivelySetValidator<double>(float_validator);
1198  pl.validateParametersAndSetDefaults(valid_pl);
1199  TEST_ASSERT(haveSameValuesSorted(validated_pl, pl, true));
1200 }
1201 
1202 // TODO: test printing of modifiers
1203 // valid_pl.print(std::cout, ParameterList::PrintOptions().showDoc(true).indent(2).showTypes(true));
1204 
1206  ParameterList valid_pl("valid_pl");
1207  valid_pl.set("a", 0.);
1208 
1209  {
1210  ParameterList pl("pl");
1211  pl.set("a", 1.);
1212  pl.validateParametersAndSetDefaults(valid_pl);
1213  ParameterList::PrintOptions printOptions;
1214  printOptions.showDefault(false);
1215  std::ostringstream ss;
1216  pl.print(ss, printOptions);
1217  std::cout << ss.str();
1218  TEST_ASSERT(ss.str().size() > 0);
1219  }
1220 
1221  {
1222  ParameterList pl("pl");
1223  pl.validateParametersAndSetDefaults(valid_pl);
1224  ParameterList::PrintOptions printOptions;
1225  std::ostringstream ss;
1226  pl.print(ss, printOptions);
1227  std::cout << ss.str();
1228  TEST_ASSERT(ss.str().size() > 0);
1229 
1230  ss.str("");
1231  printOptions.showDefault(false);
1232  pl.print(ss, printOptions);
1233  std::cout << ss.str();
1234  TEST_ASSERT(ss.str().size() == 0);
1235  }
1236 }
1237 
1238 // define enum class Shape in anonymous namespace outside of unittest
1239 // "NonPrintableParameterEntries" to avoid polution of class type in string comparison
1240 namespace {
1241  enum class Shape : int { CIRCLE, SQUARE, TRIANGLE };
1242 }
1243 
1244 TEUCHOS_UNIT_TEST( ParameterList, NonPrintableParameterEntries){
1245  // test printing std::vector<int> from a parameter list
1246  {
1247  std::vector<int> testVec = {1};
1248  ParameterList paramList = ParameterList("std::vector test");
1249  paramList.set("My std::vector<int>", testVec);
1250 
1251  try {
1252  paramList.print(); // Should throw!
1253  TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error, "If you get here then the test failed!");
1254  }
1255  catch (const NonprintableTypeException &except) {
1256  std::string actualMessage = except.what();
1257  std::string expectedMessage = "Trying to print type std::vector<int, std::allocator<int> > "
1258  "which is not printable (i.e. does not have operator<<() defined)!";
1259  TEST_ASSERT(actualMessage.find(expectedMessage) != std::string::npos);
1260  }
1261  }
1262 
1263  // test printing enum class from a parameter list
1264  {
1265  ParameterList paramList = ParameterList("enum class test");
1266  paramList.set("My enum class", Shape::SQUARE);
1267 
1268  try {
1269  paramList.print(); // Should throw!
1270  TEUCHOS_TEST_FOR_EXCEPTION( true, std::logic_error, "If you get here then the test failed!" );
1271  }
1272  catch (const NonprintableTypeException &except) {
1273  std::string actualMessage = except.what();
1274  std::string expectedMessage =
1275  "Trying to print type Teuchos::(anonymous namespace)::Shape which is not printable "
1276  "(i.e. does not have operator<<() defined)!";
1277  TEST_ASSERT(actualMessage.find(expectedMessage) != std::string::npos);
1278  }
1279  }
1280 }
1281 
1282 
1283 
1284 
1285 } // namespace Teuchos
1286 
1287 
1288 
ParameterList createMainPL()
void print() const
Print function to use in debugging in a debugger.
const std::string & name() const
The name of this ParameterList.
C++ Standard Library compatable filtered iterator.
#define TEST_ASSERT(v1)
Assert the given statement is true.
ParameterList & setEntry(const std::string &name, U &&entry)
Set a parameter directly as a ParameterEntry.
ConstIterator end() const
An iterator pointing beyond the last entry.
#define TEST_INEQUALITY_CONST(v1, v2)
Assert the inequality of v1 and constant v2.
RCP< ParameterEntry > getEntryRCP(const std::string &name)
Retrieves the RCP for an entry with the name name if it exists.
ParameterList & disableRecursiveValidation()
#define TEST_NOTHROW(code)
Asserr that the statement &#39;code&#39; does not thrown any excpetions.
#define ECHO(statement)
Echo the given statement before it is executed.
void setValidator(RCP< const ParameterEntryValidator > const &validator)
Set the validator.
RCP< const ParameterEntryValidator > validator() const
Return the (optional) validator object.
T & get(const std::string &name, T def_value)
Return the parameter&#39;s value, or the default value if it is not there.
bool nonnull(const std::shared_ptr< T > &p)
Returns true if p.get()!=NULL.
This object is held as the &quot;value&quot; in the Teuchos::ParameterList std::map.
bool is_null(const std::shared_ptr< T > &p)
Returns true if p.get()==NULL.
virtual void printDoc(std::string const &docString, std::ostream &out) const =0
Print documentation for this parameter.
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
Macro for throwing an exception with breakpointing to ease debugging.
#define TEST_ITER_EQUALITY(iter1, iter2)
Assert that two iterators are equal.
Exception class for non-printable parameter types, such as enum class/std::vector and many more which...
#define TEST_EQUALITY(v1, v2)
Assert the equality of v1 and v2.
#define TEST_THROW(code, ExceptType)
Assert that the statement &#39;code&#39; throws the exception &#39;ExceptType&#39; (otherwise the test fails)...
virtual const std::string getXMLTypeName() const =0
Get a string that should be used as a value of the type attribute when serializing it to XML...
const T & getConst(T &t)
Return a constant reference to an object given a non-const reference.
Ordinal numParams() const
Get the number of stored parameters.
ParameterList & set(std::string const &name, T &&value, std::string const &docString="", RCP< const ParameterEntryValidator > const &validator=null)
Templated set method.
Abstract interface for an object that can modify both a parameter list and the parameter list being u...
void recursivelySetValidator(RCP< const ParameterEntryValidator > const &validator, int const depth=1000)
Recursively attach a validator to parameters of type T.
bool isDefault() const
Indicate whether this entry takes on the default value.
ParameterList createValidMainPL()
ParameterEntry * getEntryPtr(const std::string &name)
Retrieves the pointer for an entry with the name name if it exists.
PrintOptions & showDefault(bool _showDefault)
bool isParameter(const std::string &name) const
Whether the given parameter exists in this list.
TEUCHOS_UNIT_TEST(ConstNonconstObjectContainer, create)
bool remove(std::string const &name, bool throwIfNotExists=true)
Remove a parameter (does not depend on the type of the parameter).
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
Deprecated.
Templated Parameter List class.
virtual void modify(ParameterList &paramList, ParameterList &validParamList) const
Modify a parameter list and/or the valid parameter list being used to validate it and throw std::exce...
bool isSublist(const std::string &name) const
Whether the given sublist exists in this list.
Unit testing support.
#define TEST_EQUALITY_CONST(v1, v2)
Assert the equality of v1 and constant v2.
void validateParametersAndSetDefaults(ParameterList const &validParamList, int const depth=1000)
Validate the parameters in this list given valid selections in the input list and set defaults for th...
int expandSublistsUsingBaseName(const std::string &baseName, ParameterList &paramList, ParameterList &validParamList, const bool &allowBaseName=true) const
Create sublists in the valid parameter list using a base name and the corresponding sublists in the p...
Utility class for setting and passing in print options.
virtual ValidStringsList validStringValues() const =0
Return an array of strings of valid values if applicable.
ConstIterator begin() const
An iterator pointing to the first entry.
T * getPtr(const std::string &name)
Retrieves the pointer for parameter name of type T from a list. A null pointer is returned if this pa...
A list of parameters of arbitrary type.
void validateParameters(ParameterList const &validParamList, int const depth=1000, EValidateUsed const validateUsed=VALIDATE_USED_ENABLED, EValidateDefaults const validateDefaults=VALIDATE_DEFAULTS_ENABLED) const
Validate the parameters in this list given valid selections in the input list.
ParameterList & setParameters(const ParameterList &source)
Parameter List Modifier class.
void modifyParameterList(ParameterList &validParamList, int const depth=1000)
Modify the valid parameter list prior to validation.
Abstract interface for an object that can validate a ParameterEntry&#39;s value.
any & getAny(bool activeQry=true)
Direct access to the Teuchos::any data value underlying this object. The bool argument activeQry (def...
RCP< const ParameterListModifier > getModifier() const
Return the optional modifier object.
ParameterList & setParametersNotAlreadySet(const ParameterList &source)
Class uesd to validate a particular type of number.
virtual void reconcile(ParameterList &paramList) const
Reconcile a parameter list and/or the valid parameter list being used to validate it and throw std::e...
bool isType(const std::string &name) const
Whether the given parameter exists in this list and has type T.
ParameterList & sublist(const std::string &name, bool mustAlreadyExist=false, const std::string &docString="")
Creates an empty sublist and returns a reference to the sublist name. If the list already exists...
Smart reference counting pointer class for automatic garbage collection.
bool isUsed() const
Return whether or not the value has been used; i.e., whether or not the value has been retrieved via ...
Standard implementation of a ParameterEntryValidator that accepts numbers from a number of different ...
ParameterEntry & getEntry(const std::string &name)
Retrieves an entry with the name name.
ParameterList & disableRecursiveModification()
Definition of Teuchos::as, for conversions between types.
void reconcileParameterList(ParameterList &validParamList, const bool left_to_right=true)
Reconcile a parameter list after validation.
void setModifier(RCP< const ParameterListModifier > const &modifier)
virtual void validate(ParameterEntry const &entry, std::string const &paramName, std::string const &sublistName) const =0
Validate a parameter entry value and throw std::exception (with a great error message) if validation ...