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.
72 lines
3.9 KiB
C++
72 lines
3.9 KiB
C++
#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);
|
||
}
|