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 );
467 std::string expression;
469 std::string description;
472 const std::vector<TestCase> cases = {
474 {
"@{2 +}",
true,
"incomplete expression" },
475 {
"@{(2 + 3",
true,
"unmatched parenthesis" },
476 {
"@{2 + 3)}",
true,
"extra closing parenthesis" },
477 {
"@{}",
true,
"empty calculation" },
480 {
"@{unknownfunc(1, 2)}",
true,
"unknown function" },
483 {
"@{abs()}",
true,
"abs with no arguments" },
484 {
"@{abs(1, 2)}",
true,
"abs with too many arguments" },
485 {
"@{sqrt()}",
true,
"sqrt with no arguments" },
488 {
"@{1 / 0}",
true,
"division by zero" },
489 {
"@{sqrt(-1)}",
true,
"square root of negative" },
492 {
"Plain text",
false,
"plain text should not error" },
493 {
"@{2 + 2}",
false,
"simple calculation should work" },
496 for(
const auto& testCase : cases )
500 if( testCase.shouldError )
502 BOOST_CHECK_MESSAGE( evaluator.
HasErrors(),
503 "Expected error for: " + testCase.description );
507 BOOST_CHECK_MESSAGE( !evaluator.
HasErrors(),
508 "Unexpected error for: " + testCase.description );
523 std::string expression;
528 const std::vector<TestCase> cases = {
530 {
"@{2 * ${pi} * ${radius}}",
"31.42", 0.01 },
531 {
"@{${pi} * pow(${radius}, 2)}",
"78.54", 0.01 },
532 {
"@{sqrt(pow(3, 2) + pow(4, 2))}",
"5", 0.001 },
535 {
"@{max(abs(-5), sqrt(16), floor(3.7))}",
"5", 0.001 },
536 {
"@{round(avg(1.1, 2.2, 3.3), 1)}",
"2.2", 0.001 },
539 {
"Circle with radius @{${radius}} has area @{format(${pi} * pow(${radius}, 2), 1)}",
540 "Circle with radius 5 has area 78.5", 0 },
543 for(
const auto& testCase : cases )
546 std::string resultStr =
result.ToStdString();
549 if( testCase.tolerance > 0 )
552 std::regex numberRegex( R
"([\d.]+)" );
555 if( std::regex_search( resultStr, match, numberRegex ) )
557 double actualValue = std::stod( match[0].str() );
558 double expectedValue = std::stod( testCase.expected );
559 BOOST_CHECK_CLOSE( actualValue, expectedValue, testCase.tolerance * 100 );
577 std::string largeExpression =
"Result: ";
578 for(
int i = 0; i < 50; ++i )
580 largeExpression +=
"@{" + std::to_string(i) +
" * 2} ";
583 auto start = std::chrono::high_resolution_clock::now();
585 auto end = std::chrono::high_resolution_clock::now();
587 auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(
end - start );
590 BOOST_CHECK( !
result.empty() );
593 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.