Revision 9e18ee9bf4a37f2d961642ad24c3c348b9efdebe authored by Gary Hu on 07 March 2024, 02:45:29 UTC, committed by Gary Hu on 07 March 2024, 02:45:29 UTC
1 parent a23d263
InputParametersTest.C
//* This file is part of the MOOSE framework
//* https://www.mooseframework.org
//*
//* All rights reserved, see COPYRIGHT for full restrictions
//* https://github.com/idaholab/moose/blob/master/COPYRIGHT
//*
//* Licensed under LGPL 2.1, please see LICENSE for details
//* https://www.gnu.org/licenses/lgpl-2.1.html
// MOOSE includes
#include "InputParameters.h"
#include "MooseEnum.h"
#include "MultiMooseEnum.h"
#include "Conversion.h"
#include "gtest/gtest.h"
TEST(InputParameters, checkControlParamPrivateError)
{
try
{
InputParameters params = emptyInputParameters();
params.addPrivateParam<Real>("private", 1);
params.declareControllable("private");
params.checkParams("");
FAIL() << "checkParams failed to catch private control param";
}
catch (const std::exception & e)
{
std::string msg(e.what());
ASSERT_TRUE(msg.find("private parameter '' marked controllable") != std::string::npos)
<< "failed with unexpected error: " << msg;
}
}
// This tests for the bug https://github.com/idaholab/moose/issues/8586.
// It makes sure that range-checked input file parameters comparison functions
// do absolute floating point comparisons instead of using a default epsilon.
TEST(InputParameters, checkRangeCheckedParam)
{
try
{
InputParameters params = emptyInputParameters();
params.addRangeCheckedParam<Real>("p", 1.000000000000001, "p = 1", "Some doc");
params.checkParams("");
FAIL() << "range checked input param failed to catch 1.000000000000001 != 1";
}
catch (const std::exception & e)
{
std::string msg(e.what());
ASSERT_TRUE(msg.find("Range check failed for param") != std::string::npos)
<< "range check failed with unexpected error: " << msg;
}
}
TEST(InputParameters, checkControlParamTypeError)
{
try
{
InputParameters params = emptyInputParameters();
params.addParam<PostprocessorName>("pp_name", "make_it_valid", "Some doc");
params.declareControllable("pp_name");
params.checkParams("");
FAIL() << "checkParams failed to catch invalid control param type";
}
catch (const std::exception & e)
{
std::string msg(e.what());
ASSERT_TRUE(msg.find("non-controllable type") != std::string::npos)
<< "failed with unexpected error:" << msg;
}
}
TEST(InputParameters, checkControlParamValidError)
{
try
{
InputParameters params = emptyInputParameters();
params.declareControllable("not_valid");
params.checkParams("");
FAIL() << "checkParams failed to catch non existing control param";
}
catch (const std::exception & e)
{
std::string msg(e.what());
ASSERT_TRUE(msg.find("cannot be marked as controllable") != std::string::npos)
<< "failed with unexpected error: " << msg;
}
}
TEST(InputParameters, checkSuppressedError)
{
try
{
InputParameters params = emptyInputParameters();
params.suppressParameter<int>("nonexistent");
FAIL() << "failed to error on supression of nonexisting parameter";
}
catch (const std::exception & e)
{
std::string msg(e.what());
ASSERT_TRUE(msg.find("Unable to suppress nonexistent parameter") != std::string::npos)
<< "failed with unexpected error: " << msg;
}
}
TEST(InputParameters, checkSuppressingControllableParam)
{
InputParameters params = emptyInputParameters();
params.addParam<bool>("b", "Controllable boolean");
params.declareControllable("b");
// Instead of building another identical copy of `param`, we directly suppress the parameter. In a
// normal situation, suppressing would happen in a child class, but it makes no difference here
params.suppressParameter<bool>("b");
// After calling suppressParameter, the controllable parameter should no longer be controllable
ASSERT_TRUE(params.isControllable("b") == false);
}
TEST(InputParameters, checkSetDocString)
{
InputParameters params = emptyInputParameters();
params.addParam<Real>("little_guy", "What about that little guy?");
params.setDocString("little_guy", "That little guy, I wouldn't worry about that little_guy.");
ASSERT_TRUE(params.getDocString("little_guy")
.find("That little guy, I wouldn't worry about that little_guy.") !=
std::string::npos)
<< "retrieved doc string has unexpected value '" << params.getDocString("little_guy") << "'";
}
TEST(InputParameters, checkSetDocStringError)
{
try
{
InputParameters params = emptyInputParameters();
params.setDocString("little_guy", "That little guy, I wouldn't worry about that little_guy.");
FAIL() << "failed to error on attempt to set non-existing parameter";
}
catch (const std::exception & e)
{
std::string msg(e.what());
ASSERT_TRUE(msg.find("Unable to set the documentation string (using setDocString)") !=
std::string::npos)
<< "failed with unexpected error: " << msg;
}
}
void
testBadParamName(const std::string & name)
{
try
{
InputParameters params = emptyInputParameters();
params.addParam<bool>(name, "Doc");
FAIL() << "failed to error on attempt to set invalid parameter name";
}
catch (const std::exception & e)
{
std::string msg(e.what());
EXPECT_TRUE(msg.find("Invalid parameter name") != std::string::npos)
<< "failed with unexpected error: " << msg;
}
}
/// Just make sure we don't allow invalid parameter names
TEST(InputParameters, checkParamName)
{
testBadParamName("p 0");
testBadParamName("p-0");
testBadParamName("p!0");
}
TEST(InputParameters, applyParameter)
{
InputParameters p1 = emptyInputParameters();
p1.addParam<MultiMooseEnum>("enum", MultiMooseEnum("foo=0 bar=1", "foo"), "testing");
EXPECT_TRUE(p1.get<MultiMooseEnum>("enum").contains("foo"));
InputParameters p2 = emptyInputParameters();
p2.addParam<MultiMooseEnum>("enum", MultiMooseEnum("foo=42 bar=43", "foo"), "testing");
EXPECT_TRUE(p2.get<MultiMooseEnum>("enum").contains("foo"));
p2.set<MultiMooseEnum>("enum") = "bar";
p1.applyParameter(p2, "enum");
EXPECT_TRUE(p1.get<MultiMooseEnum>("enum").contains("bar"));
}
TEST(InputParameters, applyParametersVector)
{
MooseEnum types("foo bar");
InputParameters p1 = emptyInputParameters();
p1.addRequiredParam<std::vector<MooseEnum>>("enum", std::vector<MooseEnum>(1, types), "testing");
InputParameters p2 = emptyInputParameters();
p2.addRequiredParam<std::vector<MooseEnum>>("enum", std::vector<MooseEnum>(1, types), "testing");
MooseEnum set("foo bar", "bar");
p2.set<std::vector<MooseEnum>>("enum") = std::vector<MooseEnum>(1, set);
EXPECT_FALSE(p1.isParamValid("enum"));
EXPECT_TRUE(p2.isParamValid("enum"));
p1.applyParameters(p2);
EXPECT_TRUE(p1.get<std::vector<MooseEnum>>("enum")[0] == "bar");
}
TEST(InputParameters, applyParameters)
{
// First enum
InputParameters p1 = emptyInputParameters();
p1.addParam<MultiMooseEnum>("enum", MultiMooseEnum("foo=0 bar=1", "foo"), "testing");
EXPECT_TRUE(p1.get<MultiMooseEnum>("enum").contains("foo"));
EXPECT_FALSE(p1.get<MultiMooseEnum>("enum").contains("bar"));
// Second enum
InputParameters p2 = emptyInputParameters();
p2.addParam<MultiMooseEnum>("enum", MultiMooseEnum("foo=42 bar=43", "foo"), "testing");
EXPECT_TRUE(p2.get<MultiMooseEnum>("enum").contains("foo"));
EXPECT_FALSE(p2.get<MultiMooseEnum>("enum").contains("bar"));
// Change second and apply to first
p2.set<MultiMooseEnum>("enum") = "bar";
p1.applyParameters(p2);
EXPECT_TRUE(p1.get<MultiMooseEnum>("enum").contains("bar"));
EXPECT_FALSE(p1.get<MultiMooseEnum>("enum").contains("foo"));
// Change back first (in "quiet_mode") then reapply second, first should change again
p1.set<MultiMooseEnum>("enum", true) = "foo";
EXPECT_FALSE(p1.get<MultiMooseEnum>("enum").contains("bar"));
EXPECT_TRUE(p1.get<MultiMooseEnum>("enum").contains("foo"));
p1.applyParameters(p2);
EXPECT_TRUE(p1.get<MultiMooseEnum>("enum").contains("bar"));
EXPECT_FALSE(p1.get<MultiMooseEnum>("enum").contains("foo"));
// Change back first then reapply second, first should not change
p1.set<MultiMooseEnum>("enum") = "foo";
EXPECT_FALSE(p1.get<MultiMooseEnum>("enum").contains("bar"));
EXPECT_TRUE(p1.get<MultiMooseEnum>("enum").contains("foo"));
p1.applyParameters(p2);
EXPECT_FALSE(p1.get<MultiMooseEnum>("enum").contains("bar"));
EXPECT_TRUE(p1.get<MultiMooseEnum>("enum").contains("foo"));
}
TEST(InputParameters, applyParametersPrivateOverride)
{
InputParameters p1 = emptyInputParameters();
p1.addPrivateParam<bool>("_flag", true);
EXPECT_TRUE(p1.get<bool>("_flag"));
InputParameters p2 = emptyInputParameters();
p2.addPrivateParam<bool>("_flag", false);
EXPECT_FALSE(p2.get<bool>("_flag"));
p1.applySpecificParameters(p2, {"_flag"}, true);
EXPECT_FALSE(p1.get<bool>("_flag"));
}
TEST(InputParameters, makeParamRequired)
{
InputParameters params = emptyInputParameters();
params.addParam<Real>("good_param", "documentation");
params.addParam<Real>("wrong_param_type", "documentation");
// Require existing parameter with the appropriate type
EXPECT_FALSE(params.isParamRequired("good_param"));
params.makeParamRequired<Real>("good_param");
EXPECT_TRUE(params.isParamRequired("good_param"));
// Require existing parameter with the wrong type
try
{
params.makeParamRequired<PostprocessorName>("wrong_param_type");
FAIL() << "failed to error on attempt to change a parameter type when making it required";
}
catch (const std::exception & e)
{
std::string msg(e.what());
EXPECT_TRUE(msg.find("Unable to require nonexistent parameter: wrong_param_type") !=
std::string::npos)
<< "failed with unexpected error: " << msg;
}
// Require non-existing parameter
try
{
params.makeParamRequired<PostprocessorName>("wrong_param_name");
FAIL() << "failed to error on attempt to require a non-existent parameter";
}
catch (const std::exception & e)
{
std::string msg(e.what());
EXPECT_TRUE(msg.find("Unable to require nonexistent parameter: wrong_param_name") !=
std::string::npos)
<< "failed with unexpected error: " << msg;
}
}
TEST(InputParameters, setPPandVofPP)
{
// programmatically set default value of PPName parameter
InputParameters p1 = emptyInputParameters();
p1.addParam<std::vector<PostprocessorName>>("pp_name", "testing");
p1.set<std::vector<PostprocessorName>>("pp_name") = {"first", "second", "third"};
// check if we have a vector of pps
EXPECT_TRUE(p1.isType<std::vector<PostprocessorName>>("pp_name"))
<< "Failed to detect vector of PPs";
// check what happens if default value is requested
/*
try
{
p1.hasDefaultPostprocessorValue("pp_name", 2);
FAIL() << "failed to error on supression of nonexisting parameter";
}
catch (const std::exception & e)
{
std::string msg(e.what());
ASSERT_TRUE(msg.find("Attempting to access _have_default_postprocessor_val") !=
std::string::npos)
<< "failed with unexpected error: " << msg;
}
*/
// EXPECT_EQ(p1.getDefaultPostprocessorValue("pp_name"), 1);
}
TEST(InputParameters, getPairs)
{
std::vector<std::string> num_words{"zero", "one", "two", "three"};
InputParameters p = emptyInputParameters();
p.addParam<std::vector<std::string>>("first", num_words, "");
p.addParam<std::vector<int>>("second", std::vector<int>{0, 1, 2, 3}, "");
auto pairs = p.get<std::string, int>("first", "second");
for (int i = 0; i < 4; ++i)
{
EXPECT_EQ(pairs[i].first, num_words[i]);
EXPECT_EQ(pairs[i].second, i);
}
}
TEST(InputParameters, getMultiMooseEnumPairs)
{
std::vector<std::string> v1{"zero", "one", "two", "three"};
auto s1 = Moose::stringify(v1, " ");
std::vector<std::string> v2{"null", "eins", "zwei", "drei"};
auto s2 = Moose::stringify(v2, " ");
InputParameters p = emptyInputParameters();
p.addParam<MultiMooseEnum>("first", MultiMooseEnum(s1, s1), "");
p.addParam<MultiMooseEnum>("second", MultiMooseEnum(s2, s2), "");
auto pairs = p.get<MooseEnumItem, MooseEnumItem>("first", "second");
for (int i = 0; i < 4; ++i)
{
EXPECT_EQ(pairs[i].first, v1[i]);
EXPECT_EQ(pairs[i].second, v2[i]);
}
}
TEST(InputParameters, getPairLength)
{
std::vector<std::string> num_words{"zero", "one", "two"};
InputParameters p = emptyInputParameters();
p.addParam<std::vector<std::string>>("first", num_words, "");
p.addParam<std::vector<int>>("second", std::vector<int>{0, 1, 2, 3}, "");
try
{
auto pairs = p.get<std::string, int>("first", "second");
FAIL() << "Missing expected exception.";
}
catch (const std::exception & e)
{
std::string msg(e.what());
ASSERT_TRUE(
msg.find(
"Vector parameters first:(size: 3) and second:(size: 4) are of different lengths") !=
std::string::npos)
<< "Failed with unexpected error message: " << msg;
}
}
TEST(InputParameters, getControllablePairs)
{
std::vector<std::string> num_words{"zero", "one", "two", "three"};
InputParameters p = emptyInputParameters();
p.addParam<std::vector<std::string>>("first", num_words, "");
p.addParam<std::vector<int>>("second", std::vector<int>{0, 1, 2, 3}, "");
p.declareControllable("first");
try
{
auto pairs = p.get<std::string, int>("first", "second");
FAIL() << "Missing expected exception.";
}
catch (const std::exception & e)
{
std::string msg(e.what());
ASSERT_TRUE(
msg.find(
"first: and/or second: are controllable parameters and cannot be "
"retireved using the MooseObject::getParam/InputParameters::get methods for pairs") !=
std::string::npos)
<< "Failed with unexpected error message: " << msg;
}
}
TEST(InputParameters, getParamList)
{
std::vector<std::string> num_words{"zero", "one", "two", "three"};
InputParameters p = emptyInputParameters();
p.addParam<std::vector<std::string>>("first", num_words, "");
p.addParam<std::vector<int>>("second", std::vector<int>{0, 1, 2, 3}, "");
std::set<std::string> param_list({"first", "second"});
EXPECT_EQ(p.getParametersList(), param_list);
}
TEST(InputParameters, transferParameters)
{
// Add parameters of various types to p1
InputParameters p1 = emptyInputParameters();
p1.addRequiredParam<Real>("r1", "Required 1");
p1.addRequiredRangeCheckedParam<Real>("r2", "r2 > 0", "Required 2");
p1.addRequiredCoupledVar("r3", "Required 3");
MooseEnum options("option1 option2");
MultiMooseEnum several_options("option1 option2");
p1.addRequiredParam<MooseEnum>("r4", options, "Required 4");
p1.addRequiredParam<MultiMooseEnum>("r5", several_options, "Required 5");
p1.addParam<Real>("o1", 3, "Optional 1");
p1.addRangeCheckedParam<Real>("o2", "o2 > 0", "Optional 2");
p1.addCoupledVar("o3", "Optional 3");
p1.addParam<MooseEnum>("o4", options, "Optional 4");
p1.addParam<MultiMooseEnum>("o5", several_options, "Optional 5");
p1.addParam<Real>("od1", "Optional with default 1");
p1.addRangeCheckedParam<Real>("od2", "od2 > 0", "Optional with default 2");
p1.addCoupledVar("od3a", 1., "Optional with default 3a");
p1.addCoupledVar("od3b", {1., 2.}, "Optional with default 3b");
// Params with modified attributes
p1.declareControllable("r1");
p1.addPrivateParam<Real>("private", 2);
// Transfer them all to p2
InputParameters p2 = emptyInputParameters();
p2.transferParam<Real>(p1, "r1");
p2.transferParam<Real>(p1, "r2");
p2.transferParam<std::vector<VariableName>>(p1, "r3");
p2.transferParam<MooseEnum>(p1, "r4");
p2.transferParam<MultiMooseEnum>(p1, "r5");
p2.transferParam<Real>(p1, "o1");
p2.transferParam<Real>(p1, "o2");
p2.transferParam<std::vector<VariableName>>(p1, "o3");
p2.transferParam<MooseEnum>(p1, "o4");
p2.transferParam<MultiMooseEnum>(p1, "o5");
p2.transferParam<Real>(p1, "od1");
p2.transferParam<Real>(p1, "od2");
p2.transferParam<std::vector<VariableName>>(p1, "od3a");
p2.transferParam<std::vector<VariableName>>(p1, "od3b");
p2.transferParam<Real>(p1, "private");
// Check that all the parameters match
// Same parameters
EXPECT_EQ(p1.have_parameter<Real>("r1"), p2.have_parameter<Real>("r1"));
EXPECT_EQ(p1.have_parameter<Real>("r2"), p2.have_parameter<Real>("r2"));
EXPECT_EQ(p1.hasCoupledValue("r3"), p2.hasCoupledValue("r3"));
EXPECT_EQ(p1.have_parameter<MooseEnum>("r4"), p2.have_parameter<MooseEnum>("r4"));
EXPECT_EQ(p1.have_parameter<MultiMooseEnum>("r5"), p2.have_parameter<MultiMooseEnum>("r5"));
EXPECT_EQ(p1.have_parameter<Real>("o1"), p2.have_parameter<Real>("o1"));
EXPECT_EQ(p1.have_parameter<Real>("o2"), p2.have_parameter<Real>("o2"));
EXPECT_EQ(p1.hasCoupledValue("o3"), p2.hasCoupledValue("o3"));
EXPECT_EQ(p1.have_parameter<MooseEnum>("o4"), p2.have_parameter<MooseEnum>("o4"));
EXPECT_EQ(p1.have_parameter<MultiMooseEnum>("o5"), p2.have_parameter<MultiMooseEnum>("o5"));
EXPECT_EQ(p1.have_parameter<Real>("od1"), p2.have_parameter<Real>("od1"));
EXPECT_EQ(p1.have_parameter<Real>("od2"), p2.have_parameter<Real>("od2"));
EXPECT_EQ(p1.hasDefaultCoupledValue("od3a"), p2.hasDefaultCoupledValue("od3a"));
EXPECT_EQ(p1.hasDefaultCoupledValue("od3b"), p2.hasDefaultCoupledValue("od3b"));
// Same required status
EXPECT_EQ(p1.isParamRequired("r1"), p2.isParamRequired("r1"));
EXPECT_EQ(p1.isParamRequired("r2"), p2.isParamRequired("r2"));
EXPECT_EQ(p1.isParamRequired("r3"), p2.isParamRequired("r3"));
EXPECT_EQ(p1.isParamRequired("r4"), p2.isParamRequired("r4"));
EXPECT_EQ(p1.isParamRequired("r5"), p2.isParamRequired("r5"));
EXPECT_EQ(p1.isParamRequired("o1"), p2.isParamRequired("o1"));
EXPECT_EQ(p1.isParamRequired("o2"), p2.isParamRequired("o2"));
EXPECT_EQ(p1.isParamRequired("o3"), p2.isParamRequired("o3"));
EXPECT_EQ(p1.isParamRequired("o4"), p2.isParamRequired("o4"));
EXPECT_EQ(p1.isParamRequired("o5"), p2.isParamRequired("o5"));
EXPECT_EQ(p1.isParamRequired("od1"), p2.isParamRequired("od1"));
EXPECT_EQ(p1.isParamRequired("od2"), p2.isParamRequired("od2"));
EXPECT_EQ(p1.isParamRequired("od3a"), p2.isParamRequired("od3a"));
EXPECT_EQ(p1.isParamRequired("od3b"), p2.isParamRequired("od3b"));
// Same private status
EXPECT_EQ(p1.isPrivate("r1"), p2.isPrivate("r1"));
EXPECT_EQ(p1.isPrivate("private"), p2.isPrivate("private"));
// Same controllable status
EXPECT_EQ(p1.isControllable("r1"), p2.isControllable("r1"));
EXPECT_EQ(p1.isControllable("r2"), p2.isControllable("r2"));
// Same defaults
EXPECT_EQ(p1.get<Real>("od1"), p2.get<Real>("od1"));
EXPECT_EQ(p1.get<Real>("od2"), p2.get<Real>("od2"));
EXPECT_EQ(p1.defaultCoupledValue("od3a"), p2.defaultCoupledValue("od3a"));
// EXPECT_EQ(p1.defaultCoupledValue("od3b", 1), p2.defaultCoupledValue("od3b", 1));
// Same docstrings
EXPECT_EQ(p1.getDocString("r1"), p2.getDocString("r1"));
EXPECT_EQ(p1.getDocString("r2"), p2.getDocString("r2"));
EXPECT_EQ(p1.getDocString("r3"), p2.getDocString("r3"));
EXPECT_EQ(p1.getDocString("r4"), p2.getDocString("r4"));
EXPECT_EQ(p1.getDocString("r5"), p2.getDocString("r5"));
EXPECT_EQ(p1.getDocString("o1"), p2.getDocString("o1"));
EXPECT_EQ(p1.getDocString("o2"), p2.getDocString("o2"));
EXPECT_EQ(p1.getDocString("o3"), p2.getDocString("o3"));
EXPECT_EQ(p1.getDocString("o4"), p2.getDocString("o4"));
EXPECT_EQ(p1.getDocString("o5"), p2.getDocString("o5"));
EXPECT_EQ(p1.getDocString("od1"), p2.getDocString("od1"));
EXPECT_EQ(p1.getDocString("od2"), p2.getDocString("od2"));
EXPECT_EQ(p1.getDocString("od3a"), p2.getDocString("od3a"));
EXPECT_EQ(p1.getDocString("od3b"), p2.getDocString("od3b"));
}
TEST(InputParameters, noDefaultValueError)
{
InputParameters params = emptyInputParameters();
params.addParam<Real>("dummy_real", "a dummy real");
params.addParam<std::vector<Real>>("dummy_vector", "a dummy vector");
// Throw an error message when no default value is provided
try
{
params.getParamHelper<Real>("dummy_real", params, static_cast<Real *>(0));
FAIL() << "failed to get the parameter because the default value is missing";
}
catch (const std::exception & e)
{
std::string msg(e.what());
ASSERT_TRUE(msg.find("The parameter \"dummy_real\" is being retrieved before being set.") !=
std::string::npos)
<< "Failed with unexpected error message: " << msg;
}
try
{
params.getParamHelper<std::vector<Real>>(
"dummy_vector", params, static_cast<std::vector<Real> *>(0));
FAIL() << "failed to get the parameter because the default value is missing";
}
catch (const std::exception & e)
{
std::string msg(e.what());
ASSERT_TRUE(msg.find("The parameter \"dummy_vector\" is being retrieved before being set.") !=
std::string::npos)
<< "Failed with unexpected error message: " << msg;
}
}
![swh spinner](/static/img/swh-spinner.gif)
Computing file changes ...