diff --git a/CMakeLists.txt b/CMakeLists.txt index fe680ec..56c52d0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -13,5 +13,6 @@ if(BUILD_TESTING) tests/tests.cc) add_test(NAME validator COMMAND partridge_tests validator) add_test(NAME construction COMMAND partridge_tests construction) + add_test(NAME rendering COMMAND partridge_tests rendering) add_test(NAME solver-small COMMAND partridge_tests solver-small) endif() diff --git a/TESTING.md b/TESTING.md index 7a1ccef..997bd28 100644 --- a/TESTING.md +++ b/TESTING.md @@ -12,7 +12,8 @@ ctest --test-dir build --output-on-failure The tests independently check board dimensions, square multiplicities, bounds, overlap, and complete coverage. They cover small unsatisfiable solver inputs, a known order-8 solution, invalid placement diagnostics, and construction of an -order-9 solution from the order-8 fixture. +order-9 solution from the order-8 fixture. The rendering test also formats the +known order-8 solution and checks the resulting grid dimensions and coverage. ## Debug and sanitizers diff --git a/tests/tests.cc b/tests/tests.cc index e683d3b..e022ecc 100644 --- a/tests/tests.cc +++ b/tests/tests.cc @@ -138,6 +138,16 @@ namespace { }; } + auto renderable_result(std::uint64_t side, + std::vector const &placements) -> Results { + std::vector squares; + squares.reserve(placements.size()); + for (auto const &placement: placements) { + squares.emplace_back(placement.x + placement.y * side, placement.side); + } + return Results(side, std::move(squares)); + } + auto construct_next_odd(std::uint64_t even_order, std::vector placements) -> std::vector { @@ -221,6 +231,29 @@ namespace { "even-to-odd construction was rejected:\n" + validation.text()); } + auto test_rendering() -> int { + auto const result = renderable_result(36, known_order_8()); + std::ostringstream rendered; + auto *const original_buffer = std::cout.rdbuf(rendered.rdbuf()); + result.output(); + std::cout.rdbuf(original_buffer); + + int failures = 0; + std::istringstream lines(rendered.str()); + std::string line; + std::uint64_t line_count = 0; + while (std::getline(lines, line)) { + ++line_count; + failures += expect(line.size() == result.length(), + "rendered row has incorrect width"); + failures += expect(line.find('.') == std::string::npos, + "valid solution left an unrendered cell"); + } + failures += expect(line_count == result.length(), + "rendered output has incorrect height"); + return failures; + } + auto test_small_solver() -> int { int failures = 0; for (auto const order: std::array{2, 3}) { @@ -262,6 +295,9 @@ int main(int argc, char **argv) { if (test == "construction") { return test_construction(); } + if (test == "rendering") { + return test_rendering(); + } if (test == "solver-small") { return test_small_solver(); }