Skip to content

Commit

Permalink
2023: add unit tests for Grid
Browse files Browse the repository at this point in the history
  • Loading branch information
yut23 committed Jan 24, 2024
1 parent edc3060 commit 60f50b3
Show file tree
Hide file tree
Showing 2 changed files with 161 additions and 12 deletions.
124 changes: 121 additions & 3 deletions 2023/src/test00_ds.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,17 @@
* Description: Unit tests for data structures.
*****************************************************************************/

#include "unit_test/unit_test.hpp"
#include "data_structures.hpp" // IWYU pragma: associated
#include "unit_test/pretty_print.hpp" // for repr
#include "unit_test/unit_test.hpp" // for ManualTest, fix_exit_code
#include "util/util.hpp" // for demangle

#include "data_structures.hpp"
#include <array> // for array
#include <cstddef> // for size_t
#include <functional> // for greater
#include <string> // for string, to_string, string_literals
#include <iostream> // for cerr
#include <string> // for string
#include <typeinfo> // for type_info

namespace aoc::ds::test {

Expand Down Expand Up @@ -81,11 +86,124 @@ std::size_t test_pairing_heap_min() {
return test.done(), test.num_failed();
}

template <class T>
std::size_t test_grid() {
const std::string type_name = util::demangle(typeid(T).name());
unit_test::ManualTest test("aoc::ds::Grid<" + type_name + ">");
std::array<T, 50> arr;
{
int i = 0;
for (auto &x : arr) {
x = i++;
}
}
Grid<T> grid(5, 10, arr);
DO_TEST(grid.in_bounds(4, 9));
DO_TEST(!grid.in_bounds(5, 3));
DO_TEST(!grid.in_bounds(0, 10));
DO_TEST(!grid.in_bounds(-2, 4));
test(
[&grid]() {
using pretty_print::repr;
auto col_it = grid.begin();
for (int y = 0; y < grid.height; ++y, ++col_it) {
assert(col_it >= grid.begin());
assert(col_it == grid.begin() + y);
auto row_it = col_it->begin();
for (int x = 0; x < grid.width; ++x, ++row_it) {
if (grid.at(x, y) != *row_it) {
std::cerr
<< "mismatch at " << x << ", " << y << ": expected "
<< pretty_print::repr(grid.at(x, y), true)
<< ", got " << pretty_print::repr(*row_it, true)
<< "\n";
return false;
}
}
if (row_it != col_it->end()) {
std::cerr << "iterator for row " << y << " not at end\n";
return false;
}
}
if (col_it != grid.end()) {
std::cerr << "grid iterator not at end\n";
return false;
}
return true;
},
"input iterator");
test(
[&grid]() {
using pretty_print::repr;
auto col_it = grid.cbegin();
for (int y = 0; y < grid.height; ++y, ++col_it) {
assert(col_it >= grid.begin());
assert(col_it == grid.begin() + y);
assert(col_it >= grid.cbegin());
assert(col_it == grid.cbegin() + y);
auto row_it = col_it->begin();
for (int x = 0; x < grid.width; ++x, ++row_it) {
if (grid.at(x, y) != *row_it) {
std::cerr
<< "mismatch at " << x << ", " << y << ": expected "
<< pretty_print::repr(grid.at(x, y), true)
<< ", got " << pretty_print::repr(*row_it, true)
<< "\n";
return false;
}
}
if (row_it != col_it->end()) {
std::cerr << "iterator for row " << y << " not at end\n";
return false;
}
}
if (col_it != grid.cend()) {
std::cerr << "grid iterator not at end\n";
return false;
}
return true;
},
"input const_iterator");
test(
[&grid]() {
using pretty_print::repr;
auto col_it = grid.begin();
for (int y = 0; y < grid.height; ++y, ++col_it) {
assert(col_it >= grid.begin());
assert(col_it == grid.begin() + y);
auto row_it = col_it->begin();
for (int x = 0; x < grid.width; ++x, ++row_it) {
auto new_val = 1 - *row_it;
*row_it = new_val;
if (grid.at(x, y) != new_val) {
std::cerr << "writing failed at " << x << ", " << y
<< "\n";
return false;
}
}
if (row_it != col_it->end()) {
std::cerr << "iterator for row " << y << " not at end\n";
return false;
}
}
if (col_it != grid.end()) {
std::cerr << "grid iterator not at end\n";
return false;
}
return true;
},
"output iterator");

return test.done(), test.num_failed();
}

} // namespace aoc::ds::test

int main() {
std::size_t failed_count = 0;
failed_count += aoc::ds::test::test_pairing_heap_max();
failed_count += aoc::ds::test::test_pairing_heap_min();
failed_count += aoc::ds::test::test_grid<int>();
failed_count += aoc::ds::test::test_grid<bool>();
return unit_test::fix_exit_code(failed_count);
}
49 changes: 40 additions & 9 deletions 2023/src/unit_test/unit_test.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include <algorithm> // for transform, min
#include <cassert> // for assert
#include <compare> // for strong_ordering
#include <concepts> // for predicate
#include <cstddef> // for size_t
#include <cstdlib> // for abs
#include <filesystem> // for path
Expand Down Expand Up @@ -641,11 +642,23 @@ PureTest(const std::string &, std::function<R(Args...)>, int)
-> PureTest<R, Args...>;

struct ManualTest : public BaseTest {
using runner_type = TestRunner<bool>;

explicit ManualTest(const std::string &name) : BaseTest(name) {}

template <class T>
bool operator()(T &&passed, const std::string &note = "") {
return (*this)(bool(std::forward<T>(passed)), note);
if constexpr (std::predicate<T>) {
// passed is a function that takes no arguments and returns a
// boolean-testable result
++test_num;
TestRunner<bool> runner(passed, 0);
TestResult result = runner.run_on_args(true, note);
record_result(result);
return result.passed;
} else {
return (*this)(bool(std::forward<T>(passed)), note);
}
}
bool operator()(bool passed, const std::string &note = "") {
++test_num;
Expand All @@ -658,14 +671,32 @@ struct ManualTest : public BaseTest {

namespace {
[[maybe_unused]] void _lint_helper() {
unit_test::PureTest test(
"foobar",
+[](const std::vector<int> &vec1, const std::vector<int> &vec2)
-> std::strong_ordering { return vec1 <=> vec2; });
test({1, 2}, {1, 2}, std::strong_ordering::equal);
test({1, 2, 3}, {1, 2}, std::strong_ordering::greater);
test({2, 2, 3}, {1, 2}, std::strong_ordering::less, "note");
test.done();
{
unit_test::PureTest test(
"foobar",
+[](const std::vector<int> &vec1, const std::vector<int> &vec2)
-> std::strong_ordering { return vec1 <=> vec2; });
test({1, 2}, {1, 2}, std::strong_ordering::equal);
test({1, 1}, {1, 2}, std::strong_ordering::less);
test({2, 2}, {1, 2}, std::strong_ordering::greater);
test({1, 2, 3}, {1, 2}, std::strong_ordering::greater);
test({1, 1, 3}, {1, 2}, std::strong_ordering::less, "note");
test.done();
}
{
const auto count_chars =
+[](const std::string &s) -> std::unordered_map<char, int> {
std::unordered_map<char, int> counts;
for (char ch : s) {
++counts[ch];
}
return counts;
};
unit_test::PureTest test("count_chars", count_chars);
test("abc", {{'a', 1}, {'b', 1}, {'c', 1}});
test("banana", {{'a', 3}, {'b', 1}, {'n', 2}});
test.done();
}
}
} // namespace

Expand Down

0 comments on commit 60f50b3

Please sign in to comment.