add basic types and fix cmake

This commit is contained in:
2026-04-19 15:35:21 +02:00
parent ebf6cea353
commit 41fd2a83ee
30 changed files with 1562 additions and 5 deletions

75
src/test/FormulaTest.cpp Normal file
View File

@@ -0,0 +1,75 @@
#include "catch.hpp"
#include <stdexcept>
#include "Formula.h"
TEST_CASE("Formula compiles a constant expression", "[formula]")
{
const Formula f = Formula::compile("42");
REQUIRE(f.isValid());
REQUIRE(f.evaluate(0.0) == Approx(42.0));
REQUIRE(f.evaluate(100.0) == Approx(42.0));
}
TEST_CASE("Formula evaluates a linear expression in x", "[formula]")
{
// Matches world.toml [waves].threat_rate_formula default.
const Formula f = Formula::compile("1*x - 30");
REQUIRE(f.evaluate(0.0) == Approx(-30.0));
REQUIRE(f.evaluate(30.0) == Approx(0.0));
REQUIRE(f.evaluate(60.0) == Approx(30.0));
}
TEST_CASE("Formula evaluates a polynomial in x", "[formula]")
{
const Formula f = Formula::compile("2 + 3*x*x");
REQUIRE(f.evaluate(0.0) == Approx(2.0));
REQUIRE(f.evaluate(2.0) == Approx(14.0));
REQUIRE(f.evaluate(4.0) == Approx(50.0));
}
TEST_CASE("Formula retains its source string", "[formula]")
{
const std::string source = "10 + x / 5";
const Formula f = Formula::compile(source);
REQUIRE(f.source() == source);
}
TEST_CASE("Formula throws on malformed source", "[formula]")
{
REQUIRE_THROWS_AS(Formula::compile("1 * + x"), std::runtime_error);
REQUIRE_THROWS_AS(Formula::compile(""), std::runtime_error);
REQUIRE_THROWS_AS(Formula::compile("unknown_var"), std::runtime_error);
}
TEST_CASE("Formula survives move construction", "[formula]")
{
// tinyexpr bakes the bound variable's address into the compiled tree.
// Formula keeps x on the heap so that address stays valid across moves.
Formula original = Formula::compile("x * 2");
Formula moved(std::move(original));
REQUIRE(moved.evaluate(21.0) == Approx(42.0));
}
TEST_CASE("Formula survives move assignment", "[formula]")
{
Formula a = Formula::compile("x + 1");
Formula b = Formula::compile("x + 100");
b = std::move(a);
REQUIRE(b.evaluate(5.0) == Approx(6.0));
}
TEST_CASE("Default-constructed Formula is invalid and throws on evaluate", "[formula]")
{
const Formula f;
REQUIRE_FALSE(f.isValid());
REQUIRE_THROWS_AS(f.evaluate(0.0), std::runtime_error);
}