206 std::string expression;
212 const std::vector<TestCase> cases = {
214 {
"@{abs(-5)}",
"5",
false, 0.001 },
215 {
"@{abs(3.14)}",
"3.14",
false, 0.001 },
216 {
"@{sqrt(16)}",
"4",
false, 0.001 },
217 {
"@{sqrt(2)}",
"1.414",
false, 0.01 },
218 {
"@{pow(2, 3)}",
"8",
false, 0.001 },
219 {
"@{pow(3, 2)}",
"9",
false, 0.001 },
222 {
"@{floor(3.7)}",
"3",
false, 0.001 },
223 {
"@{ceil(3.2)}",
"4",
false, 0.001 },
224 {
"@{round(3.7)}",
"4",
false, 0.001 },
225 {
"@{round(3.2)}",
"3",
false, 0.001 },
226 {
"@{round(3.14159, 2)}",
"3.14",
false, 0.001 },
229 {
"@{min(5, 3, 8, 1)}",
"1",
false, 0.001 },
230 {
"@{max(5, 3, 8, 1)}",
"8",
false, 0.001 },
231 {
"@{min(3.5, 3.1)}",
"3.1",
false, 0.001 },
234 {
"@{sum(1, 2, 3, 4)}",
"10",
false, 0.001 },
235 {
"@{avg(2, 4, 6)}",
"4",
false, 0.001 },
238 {
"@{sqrt(-1)}",
"Text @{sqrt(-1)} more text",
true, 0 },
241 for(
const auto& testCase : cases )
245 if( testCase.shouldError )
253 if( testCase.tolerance > 0 )
256 double actualValue = wxStrtod(
result,
nullptr );
257 double expectedValue = wxStrtod( testCase.expected,
nullptr );
258 BOOST_CHECK_CLOSE( actualValue, expectedValue, testCase.tolerance * 100 );
461 std::string expression;
463 std::string description;
466 const std::vector<TestCase> cases = {
468 {
"@{2 +}",
true,
"incomplete expression" },
469 {
"@{(2 + 3",
true,
"unmatched parenthesis" },
470 {
"@{2 + 3)}",
true,
"extra closing parenthesis" },
471 {
"@{}",
true,
"empty calculation" },
474 {
"@{unknownfunc(1, 2)}",
true,
"unknown function" },
477 {
"@{abs()}",
true,
"abs with no arguments" },
478 {
"@{abs(1, 2)}",
true,
"abs with too many arguments" },
479 {
"@{sqrt()}",
true,
"sqrt with no arguments" },
482 {
"@{1 / 0}",
true,
"division by zero" },
483 {
"@{sqrt(-1)}",
true,
"square root of negative" },
486 {
"Plain text",
false,
"plain text should not error" },
487 {
"@{2 + 2}",
false,
"simple calculation should work" },
490 for(
const auto& testCase : cases )
494 if( testCase.shouldError )
496 BOOST_CHECK_MESSAGE( evaluator.
HasErrors(),
497 "Expected error for: " + testCase.description );
501 BOOST_CHECK_MESSAGE( !evaluator.
HasErrors(),
502 "Unexpected error for: " + testCase.description );
517 std::string expression;
522 const std::vector<TestCase> cases = {
524 {
"@{2 * ${pi} * ${radius}}",
"31.42", 0.01 },
525 {
"@{${pi} * pow(${radius}, 2)}",
"78.54", 0.01 },
526 {
"@{sqrt(pow(3, 2) + pow(4, 2))}",
"5", 0.001 },
529 {
"@{max(abs(-5), sqrt(16), floor(3.7))}",
"5", 0.001 },
530 {
"@{round(avg(1.1, 2.2, 3.3), 1)}",
"2.2", 0.001 },
533 {
"Circle with radius @{${radius}} has area @{format(${pi} * pow(${radius}, 2), 1)}",
534 "Circle with radius 5 has area 78.5", 0 },
537 for(
const auto& testCase : cases )
540 std::string resultStr =
result.ToStdString();
543 if( testCase.tolerance > 0 )
546 std::regex numberRegex( R
"([\d.]+)" );
549 if( std::regex_search( resultStr, match, numberRegex ) )
551 double actualValue = std::stod( match[0].str() );
552 double expectedValue = std::stod( testCase.expected );
553 BOOST_CHECK_CLOSE( actualValue, expectedValue, testCase.tolerance * 100 );
571 std::string largeExpression =
"Result: ";
572 for(
int i = 0; i < 50; ++i )
574 largeExpression +=
"@{" + std::to_string(i) +
" * 2} ";
577 auto start = std::chrono::high_resolution_clock::now();
579 auto end = std::chrono::high_resolution_clock::now();
581 auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(
end - start );
584 BOOST_CHECK( !
result.empty() );
587 BOOST_CHECK_LT( duration.count(), 1000 );
wxString result
Test unit parsing edge cases and error handling.
BOOST_CHECK_EQUAL(result, "25.4")
BOOST_AUTO_TEST_CASE(BasicArithmetic)
Declare the test suite.