Skip to content

Commit 4dfed05

Browse files
committed
Add golden-corpus test for the expression parser
Define each expression's fully-bracketed AST rendering and assert it byte-for-byte, to lock parser behaviour. Defines also invalid_expressions, for which parser refusal is asserted. Also adds test for expressions with attached tokens for keyword/operand glue cases. Re ECFLOW-2112
1 parent 491e18d commit 4dfed05

6 files changed

Lines changed: 9713 additions & 0 deletions

File tree

libs/node/CMakeLists.txt

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,32 @@ target_clangformat(u_parser
118118
CONDITION ENABLE_TESTS
119119
)
120120

121+
122+
set(test_srcs
123+
# Sources
124+
test/expressions/TestExpressionsGoldenCorpus.cpp
125+
test/expressions/TestExpressions_main.cpp # test entry point
126+
)
127+
ecbuild_add_test(
128+
TARGET
129+
u_expressions
130+
LABELS
131+
unit nightly fast
132+
SOURCES
133+
${test_srcs}
134+
LIBS
135+
ecflow_all
136+
test_scaffold
137+
nlohmann::json
138+
Boost::boost # Boost header-only libraries must be available (namely unit_test_framework)
139+
TEST_DEPENDS
140+
u_node
141+
)
142+
target_clangformat(u_expressions
143+
CONDITION ENABLE_TESTS
144+
)
145+
146+
121147
if (ENABLE_ALL_TESTS)
122148
set(test_srcs
123149
test/TestSingleExprParse.cpp

libs/node/test/TestExprParser.cpp

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -940,6 +940,57 @@ BOOST_AUTO_TEST_CASE(test_parser_bad_expressions) {
940940
}
941941
}
942942

943+
BOOST_AUTO_TEST_CASE(test_parser_with_attached_tokens) {
944+
ECF_NAME_THIS_TEST();
945+
946+
// ECFLOW-2112:
947+
// A word operator (and/or/eq/ne/ge/gt/le/lt) must be a token in its own right, i.e. surrounded by
948+
// whitespace/brackets. When it is "attached"/glued to an adjacent operand it forms a single identifier
949+
// (e.g. 'completeand', '515and', 'andb') which silently changes the meaning of the expression.
950+
// These expressions must be rejected by the parser.
951+
952+
using namespace std::string_literals;
953+
std::vector expressions = {
954+
// ---- The exact malformed expressions observed in operational checkpoints (ECFLOW-2112) ----
955+
":TIME ge 515and :ECF_DATE gt :YMD"s,
956+
":TIME ge 1115and :ECF_DATE gt :YMD"s,
957+
"input eq completeand ( ( ../lag:YMD + 5) ge ../prep:YMD)"s,
958+
959+
// ---- 'and' attached to the preceding operand ----
960+
"a == completeand b == complete"s, // node state glued to 'and'
961+
"a eq completeand b eq complete"s, // word operators + state glued to 'and'
962+
"1 == 1and 2 == 2"s, // integer glued to 'and'
963+
"a:value == 10and b:value == 20"s, // integer glued to 'and'
964+
965+
// ---- 'and' attached to the following operand ----
966+
"a == complete andb == complete"s, // 'and' glued to node
967+
"a == complete and2 == 2"s, // 'and' glued to integer
968+
969+
// ---- 'or' attached to an operand ----
970+
"a == completeor b == complete"s, // node state glued to 'or'
971+
"a == complete orb == complete"s, // 'or' glued to node
972+
"1 == 1or 2 == 2"s, // integer glued to 'or'
973+
974+
// ---- word comparison operators glued to an operand ----
975+
"aeq complete"s, // 'eq' glued to left operand
976+
"a eqcomplete"s, // 'eq' glued to right operand
977+
":TIME ge515 and :ECF_DATE gt :YMD"s, // 'ge' glued to integer
978+
"a ne completeand b == complete"s, // 'ne'/state glued to 'and'
979+
980+
// ---- symbolic '==' interacting with a glued word operator ----
981+
"a == completeand"s, // trailing glued 'and' after equality
982+
"a == b == completeor c == complete"s // 'or' glued to state after chained '=='
983+
};
984+
985+
for (const auto& expression : expressions) {
986+
987+
ExprParser theExprParser(expression);
988+
std::string error;
989+
auto actual = theExprParser.doParse(error);
990+
BOOST_CHECK_MESSAGE(!actual, expression << " expected to fail (ECFLOW-2112 attached tokens)");
991+
}
992+
}
993+
943994
BOOST_AUTO_TEST_SUITE_END()
944995

945996
BOOST_AUTO_TEST_SUITE_END()

0 commit comments

Comments
 (0)