test(tests): added test suite

The test suite is extensive. Note that LLMs were used to aid in the development of the test suite. All LLM generated code was manually reviewed.
This commit is contained in:
2026-11-09 13:53:17 -05:00
parent 74e55a6859
commit cb20faeb3d
202 changed files with 35505 additions and 953 deletions

View File

@@ -0,0 +1,71 @@
#include <array>
#include <format>
#include <iterator>
#include <string>
#include <catch2/catch_test_macros.hpp>
#include <catch2/matchers/catch_matchers_string.hpp>
#include "serif/utils/laneemden/solution.hpp"
namespace {
namespace laneemden = serif::utils::laneemden;
constexpr laneemden::Sample sample{.xi = 2.0, .theta = 0.5, .derivative = -0.25};
/** @brief Use distinct profile and surface values so selection forwarding is observable. */
[[nodiscard]] laneemden::Solution example_solution() {
return {
.n = 1.0,
.samples = {{.xi = 0.0, .theta = 1.0, .derivative = 0.0}, sample},
.surface = laneemden::Sample{.xi = 3.0, .theta = 0.0, .derivative = -0.5}
};
}
}
TEST_CASE("Lane Emden sample formatting selects complete or individual values", "[laneemden][formatting]") {
CHECK(std::format("{}", sample) == "(ξ=2, θ=0.5, dθ/dξ=-0.25)");
CHECK(std::format("{:}", sample) == std::format("{}", sample));
CHECK(std::format("{:all}", sample) == std::format("{}", sample));
CHECK(std::format("{:xi}", sample) == "2");
CHECK(std::format("{:theta}", sample) == "0.5");
CHECK(std::format("{:derivative}", sample) == "-0.25");
CHECK(std::format("{1:theta} / {0:xi}", sample, sample) == "0.5 / 2");
CHECK(std::format("{{{:xi}}}", sample) == "{2}");
}
TEST_CASE("Lane Emden solution formatting forwards selection to its profile and surface", "[laneemden][formatting]") {
const auto solution = example_solution();
CHECK(std::format("{}", solution) == "Solution(n=1, samples=[(ξ=0, θ=1, dθ/dξ=0), (ξ=2, θ=0.5, dθ/dξ=-0.25)], surface=(ξ=3, θ=0, dθ/dξ=-0.5))");
CHECK(std::format("{:}", solution) == std::format("{}", solution));
CHECK(std::format("{:all}", solution) == std::format("{}", solution));
CHECK(std::format("{:xi}", solution) == "Solution(n=1, samples=[0, 2], surface=3)");
CHECK(std::format("{:theta}", solution) == "Solution(n=1, samples=[1, 0.5], surface=0)");
CHECK(std::format("{:derivative}", solution) == "Solution(n=1, samples=[0, -0.25], surface=-0.5)");
const laneemden::Solution empty{.n = 5.0, .samples = {}, .surface = {}};
CHECK(std::format("{}", empty) == "Solution(n=5, samples=[], surface=none)");
CHECK(std::format("{:theta}", empty) == "Solution(n=5, samples=[], surface=none)");
}
TEST_CASE("Lane Emden formatters preserve surrounding output and independent selectors", "[laneemden][formatting]") {
const auto solution = example_solution();
const std::string expected = "prefix Solution(n=1, samples=[1, 0.5], surface=0) | 2 | Solution(n=1, samples=[0, -0.25], surface=-0.5) suffix";
std::string appended = "prefix ";
std::format_to(std::back_inserter(appended), "{:theta} | {:xi} | {:derivative} suffix", solution, sample, solution);
CHECK(appended == expected);
std::array<char, 512> buffer{};
const auto end = std::format_to(buffer.data(), "prefix {:theta} | {:xi} | {:derivative} suffix", solution, sample, solution);
CHECK(std::string(buffer.data(), end) == expected);
}
TEST_CASE("Lane Emden formatters reject unsupported selectors through the central error helper", "[laneemden][formatting]") {
const auto solution = example_solution();
for (const std::string specifier : {"radius", "xi,theta", "theta ", ".2f", "theta:.2f"}) {
CAPTURE(specifier);
const std::string format = "{:" + specifier + "}";
CHECK_THROWS_AS(std::vformat(format, std::make_format_args(sample)), std::format_error);
CHECK_THROWS_AS(std::vformat(format, std::make_format_args(solution)), std::format_error);
CHECK_THROWS_WITH(std::vformat(format, std::make_format_args(sample)), Catch::Matchers::ContainsSubstring("Unknown Lane–Emden sample selector"));
}
CHECK_THROWS_AS(std::vformat("{:xi", std::make_format_args(sample)), std::format_error);
CHECK_THROWS_AS(std::vformat("{:theta", std::make_format_args(solution)), std::format_error);
}