Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 12 additions & 9 deletions src/coreComponents/codingUtilities/RTTypes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ rtTypes::RegexMapType rtTypes::createBasicTypesRegexMap()
// string_view const ru = "[\\d]+";// unused

string_view const intDesc = "Input value must be a signed int (eg. -123, 455, +789, etc.)";
string_view const intRegex = "[+-]?[\\d]+";
string_view const intRegex = "\\s*[+-]?[\\d]+\\s*";

// Explanation of parts:
// [+-]?[\\d]* matches an optional +/- at the beginning, any numbers preceding the decimal
Expand All @@ -160,28 +160,31 @@ rtTypes::RegexMapType rtTypes::createBasicTypesRegexMap()
// ([eE][-+]?[\\d]+|\\s*) matches an optional scientific notation number
// Note: the xsd regex implementation does not allow an empty branch, so use allow whitespace at the end
string_view const realDesc = "Input value must be a real number (eg. 1, .25, +2.3, -.4, 5.6e7, -8E-9, etc.)";
string_view const realRegex = "[+-]?[\\d]*([\\d]\\.?|\\.[\\d])[\\d]*([eE][-+]?[\\d]+|\\s*)";
string_view const realRegex = "\\s*[+-]?[\\d]*([\\d]\\.?|\\.[\\d])[\\d]*([eE][-+]?[\\d]+|\\s*)";

string_view const R1Desc = "Input value must be a R1Tensor, an array of 3 real numbers surrounded by braces and separated by commas (eg. \"{ 1, .25, +2.3}\", \"{ -.4, 5.6e7, -8E-9\", etc.) .";
string const R1Regex = "\\s*\\{\\s*(" + string( realRegex ) + "\\s*,\\s*){2}" + string( realRegex ) + "\\s*\\}\\s*";
string_view const R2Desc = "Input value must be a R2SymTensor, an array of 6 real numbers surrounded by braces and separated by commas (eg. \"{ 1, .25, +2.3, -.4, 5.6e7, -8E-9\", etc.) .";
string const R2Regex = "\\s*\\{\\s*(" + string( realRegex ) + "\\s*,\\s*){5}" + string( realRegex ) + "\\s*\\}\\s*";

string_view const strDesc = "Input value must be a string that cannot be empty, contain any whitespaces nor the characters , { }";
string_view const strRegex = "[^,\\{\\}\\s]+\\s*";
string_view const strRegex = "\\s*[^,\\{\\}\\s]+\\s*";
string_view const strEDesc = "Input value must be a string that cannot contain any whitespaces nor the characters , { }";
string_view const strERegex = "[^,\\{\\}\\s]*\\s*";
string_view const strERegex = "\\s*[^,\\{\\}\\s]*\\s*";

string_view const pathDesc = "Input value must be a string that cannot be empty, contain any whitespaces nor the characters * ? < > | : \" ";
string_view const pathRegex = "[^*?<>\\|:\";,\\s]+\\s*";
string_view const pathRegex = "\\s*[^*?<>\\|:\";,\\s]+\\s*";
string_view const pathEDesc = "Input value must be a string that cannot contain any whitespaces nor the characters * ? < > | : \" ";
string_view const pathERegex = "[^*?<>\\|:\";,\\s]*\\s*";
string_view const pathERegex = "\\s*[^*?<>\\|:\";,\\s]*\\s*";

string_view const groupNameDesc = "Input value must be a string that cannot be empty and contains only upper/lower letters, digits, and the characters . - _";
string_view const groupNameRegex = "[a-zA-Z0-9.\\-_]+";
string_view const groupNameRegex = "\\s*[a-zA-Z0-9.\\-_]+\\s*";
// to reference groups, we need to support the / for paths, and * [ ] for fnmatch patterns.
string_view const groupNameRefDesc = "Input value must be a string that can contain only upper/lower letters, digits, and the characters . - _ / * [ ]";
string_view const groupNameRefRegex = "[a-zA-Z0-9.\\-_/*\\[\\]]*";
string_view const groupNameRefRegex = "\\s*[a-zA-Z0-9.\\-_/*\\[\\]]*\\s*";
// to reference an array of groups, we need to support the / for paths, and * [ ] for fnmatch patterns.
string_view const groupNameRefArrayDesc = "Input value must be a list of strings that can contain only upper/lower letters, digits, and the characters . - _ / * [ ]";
string_view const groupNameRefArrayRegex = "\\s*\\{([a-zA-Z0-9.\\-_/*\\[\\], ]+)*\\}\\s*";


// Build master list of regexes
Expand Down Expand Up @@ -220,7 +223,7 @@ rtTypes::RegexMapType rtTypes::createBasicTypesRegexMap()
{ string( CustomTypes::plotLevel ), Regex( intRegex, intDesc ) },
{ string( CustomTypes::groupName ), Regex( groupNameRegex, groupNameDesc ) },
{ string( CustomTypes::groupNameRef ), Regex( groupNameRefRegex, groupNameRefDesc ) },
{ string( CustomTypes::groupNameRefArray ), constructArrayRegex( groupNameRefRegex, groupNameRefDesc, 1 ) }
{ string( CustomTypes::groupNameRefArray ), Regex( groupNameRefArrayRegex, groupNameRefArrayDesc ) }
};
return regexMap;
}
Expand Down
109 changes: 102 additions & 7 deletions src/coreComponents/dataRepository/unitTests/testXmlWrapper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -243,6 +243,9 @@ INSTANTIATE_TEST_SUITE_P(
real64AttributeTests,
real64AttributeTestFixture,
::testing::Values( std::make_tuple( "1", 1, false ),
std::make_tuple( "1 ", 1, false ),
std::make_tuple( " 1", 1, false ),
std::make_tuple( " 1 ", 1, false ),
std::make_tuple( "-23", -23, false ),
std::make_tuple( "4.5", 4.5, false ),
std::make_tuple( "4.", 4.0, false ),
Expand All @@ -260,7 +263,6 @@ INSTANTIATE_TEST_SUITE_P(
std::make_tuple( "1.234gamma", 0, true ),
std::make_tuple( "1.2.3", 0, true ),
std::make_tuple( "1e2.3 ", 0, true ),
std::make_tuple( "1 ", 0, true ),
std::make_tuple( "1e", 0, true ),
std::make_tuple( "1e-", 0, true ),
std::make_tuple( "1e+", 0, true )));
Expand All @@ -284,6 +286,9 @@ INSTANTIATE_TEST_SUITE_P(
real32AttributeTests,
real32AttributeTestFixture,
::testing::Values( std::make_tuple( "1", 1, false ),
std::make_tuple( "1 ", 1, false ),
std::make_tuple( " 1", 1, false ),
std::make_tuple( " 1 ", 1, false ),
std::make_tuple( "-23", -23, false ),
std::make_tuple( "4.5", 4.5, false ),
std::make_tuple( "4.", 4.0, false ),
Expand All @@ -301,7 +306,6 @@ INSTANTIATE_TEST_SUITE_P(
std::make_tuple( "1.234gamma", 0, true ),
std::make_tuple( "1.2.3", 0, true ),
std::make_tuple( "1e2.3 ", 0, true ),
std::make_tuple( "1 ", 0, true ),
std::make_tuple( "1e", 0, true ),
Comment on lines 308 to 309
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why removing that case instead of adding one to test your new feature? (space before)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since the regex has been updated this case no longer works

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since your last commit, it is not prohibed nor accepted.
Take clear decision on "1 " and " 1".

std::make_tuple( "1e-", 0, true ),
std::make_tuple( "1e+", 0, true )));
Expand All @@ -319,13 +323,15 @@ INSTANTIATE_TEST_SUITE_P(
integerAttributeTests,
integerAttributeTestFixture,
::testing::Values( std::make_tuple( "1", 1, false ),
std::make_tuple( "1 ", 1, false ),
std::make_tuple( " 1", 1, false ),
std::make_tuple( " 1 ", 1, false ),
std::make_tuple( "-23", -23, false ),
std::make_tuple( "4.5", 0, true ),
std::make_tuple( "4.", 0, true ),
std::make_tuple( "alpha", 0, true ),
std::make_tuple( "1beta234", 0, true ),
std::make_tuple( "1234gamma", 0, true ),
std::make_tuple( "1 ", 0, true ),
std::make_tuple( "1 2", 0, true )));


Expand Down Expand Up @@ -374,12 +380,16 @@ TEST( testXmlWrapper, testGroupNamesFormats )
GroupNameTest( groupNameRegex, "testname01" ),
GroupNameTest( groupNameRegex, "test_name" ),
GroupNameTest( groupNameRegex, "test-name" ),
GroupNameTest( groupNameRegex, "test.name" ),
GroupNameTest( groupNameRegex, " testname " ),
GroupNameTest( groupNameRegex, " \t testname \n " ),
};
for( GroupNameTest const & input : workingInputs )
{
EXPECT_NO_THROW( xmlWrapper::stringToInputVariable( groupName, input.m_valueToTest, input.m_regex ) );
EXPECT_STREQ( input.m_valueToTest.c_str(), groupName.c_str() );
std::string groupNameComp;
std::istringstream ss( input.m_valueToTest );
ss >> groupNameComp >> std::ws;
EXPECT_STREQ( groupNameComp.c_str(), groupName.c_str() );
Comment on lines +389 to +392
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please revert

}
}
{
Expand All @@ -391,8 +401,6 @@ TEST( testXmlWrapper, testGroupNamesFormats )
//white spaces
GroupNameTest( groupNameRegex, "test name" ),
GroupNameTest( groupNameRegex, "test\tname" ),
GroupNameTest( groupNameRegex, "testname " ),
GroupNameTest( groupNameRegex, " testname" ),
//fordbiden characters
GroupNameTest( groupNameRegex, "test/name" ),
GroupNameTest( groupNameRegex, "test:name" ),
Expand All @@ -407,6 +415,93 @@ TEST( testXmlWrapper, testGroupNamesFormats )
}
}
}
TEST( testXmlWrapper, testGroupNamesArrayFormats )
{
struct GroupNameTest
{
Regex const & m_regex;
string m_valueToTest;
GroupNameTest( Regex const & regex, string_view valueToTest ):
m_regex( regex ), m_valueToTest( valueToTest ) {}
};

Regex const & groupNameRefArrayRegex = rtTypes::getTypeRegex< string >( rtTypes::CustomTypes::groupNameRefArray );
string groupName;

{
stdVector< GroupNameTest > workingInputs = {
GroupNameTest( groupNameRefArrayRegex, "{}" ),
GroupNameTest( groupNameRefArrayRegex, " {} " ),
GroupNameTest( groupNameRefArrayRegex, " \t {} \n " ),
GroupNameTest( groupNameRefArrayRegex, "{groupName}" ),
GroupNameTest( groupNameRefArrayRegex, "{123name}" ),
GroupNameTest( groupNameRefArrayRegex, "{name123}" ),
GroupNameTest( groupNameRefArrayRegex, "{a-Z0-9./*[]-_,}" ),
GroupNameTest( groupNameRefArrayRegex, "{name.with-special_chars}" ),
GroupNameTest( groupNameRefArrayRegex, "{path/to/resource*}" ),
GroupNameTest( groupNameRefArrayRegex, "{[arrayElement]}" ),
Comment on lines +441 to +442
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you add these ones in non-array groupName test please?

GroupNameTest( groupNameRefArrayRegex, "{name1,name2,name3}" ),
};
for( GroupNameTest const & input : workingInputs )
{
EXPECT_NO_THROW( xmlWrapper::stringToInputVariable( groupName, input.m_valueToTest, input.m_regex ) );
std::string groupNameComp;
std::istringstream ss( input.m_valueToTest );
ss >> groupNameComp >> std::ws;
EXPECT_STREQ( groupNameComp.c_str(), groupName.c_str() );
}
}
{
stdVector< GroupNameTest > erroneousInputs = {
GroupNameTest( groupNameRefArrayRegex, "" ),
GroupNameTest( groupNameRefArrayRegex, " " ),
GroupNameTest( groupNameRefArrayRegex, " \t " ),
GroupNameTest( groupNameRefArrayRegex, "{\t}" ),
GroupNameTest( groupNameRefArrayRegex, "{test:name}" ),
GroupNameTest( groupNameRefArrayRegex, "{test;name}" ),
GroupNameTest( groupNameRefArrayRegex, "{test\\name}" ),
GroupNameTest( groupNameRefArrayRegex, "{test|name}" ),
GroupNameTest( groupNameRefArrayRegex, "{test^name}" ),
GroupNameTest( groupNameRefArrayRegex, "{test$name}" ),
GroupNameTest( groupNameRefArrayRegex, "{test&name}" ),
GroupNameTest( groupNameRefArrayRegex, "{test#name}" ),
GroupNameTest( groupNameRefArrayRegex, "{test!name}" ),
GroupNameTest( groupNameRefArrayRegex, "{test%name}" ),
GroupNameTest( groupNameRefArrayRegex, "{test@name}" ),
GroupNameTest( groupNameRefArrayRegex, "{test(name}" ),
GroupNameTest( groupNameRefArrayRegex, "{test)name}" ),
GroupNameTest( groupNameRefArrayRegex, "{test=name}" ),
GroupNameTest( groupNameRefArrayRegex, "{test+name}" ),
GroupNameTest( groupNameRefArrayRegex, "{test<name}" ),
GroupNameTest( groupNameRefArrayRegex, "{test>name}" ),
GroupNameTest( groupNameRefArrayRegex, "{test\tname}" ),
GroupNameTest( groupNameRefArrayRegex, "{test\nname}" ),
GroupNameTest( groupNameRefArrayRegex, "{test\rname}" ),
GroupNameTest( groupNameRefArrayRegex, "groupName" ),
GroupNameTest( groupNameRefArrayRegex, "{groupName" ),
GroupNameTest( groupNameRefArrayRegex, "groupName}" ),
GroupNameTest( groupNameRefArrayRegex, "{groupName}} " ),
GroupNameTest( groupNameRefArrayRegex, "{}groupName" ),
GroupNameTest( groupNameRefArrayRegex, "groupName{}" ),
GroupNameTest( groupNameRefArrayRegex, "{hello, \t\n\r ,world}" ),
GroupNameTest( groupNameRefArrayRegex, "test{groupName}" ),
GroupNameTest( groupNameRefArrayRegex, "{groupName}test" ),
GroupNameTest( groupNameRefArrayRegex, "{groupName} test" ),
GroupNameTest( groupNameRefArrayRegex, "{element with space, another}" ),
GroupNameTest( groupNameRefArrayRegex, "{element, element with space, 123.456, a-b}" ),
GroupNameTest( groupNameRefArrayRegex, "{ space at ends } " ),
GroupNameTest( groupNameRefArrayRegex, "{valuewith,,commas }" ),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add one with all alowed whitespaces kind in-between the commas ({hello, \t\n\r ,world})

GroupNameTest( groupNameRefArrayRegex, "{ value with , commas }" ),
GroupNameTest( groupNameRefArrayRegex, "{{groupname}}" ),
};
for( GroupNameTest const & input : erroneousInputs )
{
EXPECT_THROW( xmlWrapper::stringToInputVariable( groupName, input.m_valueToTest, input.m_regex ),
InputError ) << "Parsing input '"<< input.m_valueToTest
<< "' with regex '" << input.m_regex.m_regexStr << "' didn't throw an InputError as expected.";
}
}
}


int main( int argc, char * argv[] )
Expand Down
4 changes: 2 additions & 2 deletions src/coreComponents/dataRepository/xmlWrapper.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -351,8 +351,8 @@ std::enable_if_t< traits::CanStreamInto< std::istringstream, T > >
stringToInputVariable( T & target, string const & value, Regex const & regex )
{
validateString( value, regex );

std::istringstream ss( value );
string_view stringTrimed = stringutilities::trimSpaces( value );
std::istringstream ss( (string( stringTrimed )) );
ss >> target;
GEOS_THROW_IF( ss.fail() || !ss.eof(),
"Error detected while parsing string \"" << value <<
Expand Down
Loading
Loading