Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 23 additions & 8 deletions .github/workflows/gen_matrix.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,12 @@ def find_include_paths(line: str) -> Generator[Path, None, None]:
yield curr_path
break

elif path.name == "Makefile":

def find_include_paths(line: str) -> Generator[Path, None, None]:
if line.strip().startswith("include "):
yield path.parent / line.strip().removeprefix("include ")

else:
return frozenset()

Expand All @@ -72,31 +78,40 @@ def get_transitive_dependencies(path: Path, *include_dirs: Path) -> frozenset[Pa
@dataclass(order=True, frozen=True, kw_only=True)
class Target:
base_dir: Path
day: int
day: int | None
prefix: str
extra: str

@property
def _day_str(self) -> str:
if self.day is None:
return ""
return f"{self.day:02d}"

@property
def suffix(self) -> str:
return f"{self.day:02d}{self.extra}"
return f"{self._day_str}{self.extra}"

def __str__(self) -> str:
return f"{self.prefix}{self.day:02d}{self.extra}"
return f"{self.prefix}{self._day_str}{self.extra}"

@classmethod
def from_file(cls, base_dir: Path, source_file: Path) -> Target:
m = re.match(
r"(?P<prefix>day|test)(?P<day>\d+)(?P<extra>.*)$", source_file.stem
r"(?P<prefix>day|test)(?P<day>\d+)?(?P<extra>.*)$", source_file.stem
)
assert m is not None, source_file
return cls(
base_dir=base_dir, day=int(m["day"]), prefix=m["prefix"], extra=m["extra"]
)
if m["day"] is None:
assert m["prefix"] == "test", "only unit tests may omit a day number"
day = None
else:
day = int(m["day"])
return cls(base_dir=base_dir, day=day, prefix=m["prefix"], extra=m["extra"])

def get_deps(self, mode: str) -> frozenset[Path]:
deps = set()
src = self.base_dir / "src"
aoc_lib = self.base_dir.parent / "aoc_lib"
aoc_lib = self.base_dir.parent / "aoc_lib/src"
deps.add(src / f"{self}.cpp")
for included_file in get_transitive_dependencies(
src / f"{self}.cpp", src, aoc_lib
Expand Down
138 changes: 107 additions & 31 deletions .github/workflows/test_gen_matrix.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,20 @@
from gen_matrix import ROOT, WORKFLOWS_DIR, Matrix, get_dependencies
from pathlib import Path

from gen_matrix import (
ROOT,
WORKFLOWS_DIR,
Matrix,
get_dependencies,
get_transitive_dependencies,
)

ACTIONS_DIR = ROOT / ".github/actions"


def test_get_dependencies_cpp():
base_dir = ROOT / "2023"
src = base_dir / "src"
aoc_lib = base_dir.parent / "aoc_lib"
aoc_lib = base_dir.parent / "aoc_lib/src"
include_dirs = (src, aoc_lib)
assert get_dependencies(src / "day01.cpp", *include_dirs) == {aoc_lib / "lib.hpp"}
assert get_dependencies(src / "day05.cpp", *include_dirs) == {
Expand All @@ -19,6 +27,39 @@ def test_get_dependencies_cpp():
aoc_lib / "unit_test/unit_test.hpp",
}

assert get_dependencies(ROOT / "2022/src/day16.cpp", *include_dirs) == {
ROOT / "2022/src/lib.h"
}


def test_get_transitive_dependencies():
base_dir = ROOT / "2023"
src = base_dir / "src"
aoc_lib = base_dir.parent / "aoc_lib/src"
include_dirs = (src, aoc_lib)
assert get_transitive_dependencies(src / "day22.cpp", *include_dirs) == frozenset(
{
src / "day22.hpp",
aoc_lib / "lib.hpp",
aoc_lib / "util/hash.hpp",
aoc_lib / "util/concepts.hpp",
aoc_lib / "graph_traversal.hpp",
}
)

assert get_transitive_dependencies(aoc_lib / "test_ds.cpp", aoc_lib) == frozenset(
{
aoc_lib / "ds/grid.hpp",
aoc_lib / "ds/pairing_heap.hpp",
aoc_lib / "unit_test/pretty_print.hpp",
aoc_lib / "unit_test/unit_test.hpp",
aoc_lib / "util/util.hpp",
aoc_lib / "lib.hpp",
aoc_lib / "util/hash.hpp",
aoc_lib / "util/concepts.hpp",
}
)


def test_get_dependencies_workflows():
assert get_dependencies(WORKFLOWS_DIR / "unit-tests.yml") == {
Expand All @@ -41,60 +82,95 @@ def test_get_dependencies_workflows():
}


def matrix_helper(*changed_files: str) -> dict[str, set[str]]:
result = {}
for mode in ("build", "answer", "unit"):
matrix = Matrix(mode)
for f in changed_files:
matrix.process_changed_file(ROOT / f)
result[mode] = {
"{directory}/{name}".format(**target.to_dict()) for target in matrix.targets
}
return result
class MatrixHelper:
def __init__(self) -> None:
self.matrices = {mode: Matrix(mode) for mode in ("build", "answer", "unit")}

def get_targets(self, *changed_files: str | Path) -> dict[str, set[str]]:
result = {}
for mode in ("build", "answer", "unit"):
matrix = self.matrices[mode]
for f in changed_files:
matrix.process_changed_file(ROOT / f)
result[mode] = {
"{directory}/{name}".format(**target.to_dict())
for target in matrix.targets
}
matrix.targets.clear()
return result


def test_matrix():
# pylint: disable=use-dict-literal
everything = matrix_helper("2022/Makefile", "tools/cpp/Makefile")
helper = MatrixHelper()
everything = helper.get_targets(*ROOT.glob("*/Makefile"), "tools/cpp/Makefile")

# C++ source files
assert matrix_helper("2023/src/day05.cpp") == dict(
assert helper.get_targets("2023/src/day05.cpp") == dict(
build={"2023/day05"}, answer={"2023/day05"}, unit=set()
)
assert matrix_helper("2023/src/day05.hpp") == dict(
build={"2023/day05", "2023/test05"}, answer={"2023/day05"}, unit={"2023/test05"}
assert helper.get_targets("2023/src/day05.hpp") == dict(
build={"2023/day05", "2023/test05"},
answer={"2023/day05"},
unit={"2023/test05"},
)
assert matrix_helper("2023/src/test05.cpp") == dict(
assert helper.get_targets("2023/src/test05.cpp") == dict(
build={"2023/test05"}, answer=set(), unit={"2023/test05"}
)

# 2022 doesn't use aoc_lib/src/lib.hpp
matrix = Matrix("build")
matrix.process_changed_file(ROOT / "aoc_lib/src/lib.hpp")
assert all(target.base_dir != ROOT / "2022" for target in matrix.targets)

# unit tests for aoc_lib
assert helper.get_targets("aoc_lib/src/test_graph.cpp") == dict(
build={"aoc_lib/test_graph"},
answer=set(),
unit={"aoc_lib/test_graph"},
)
assert "aoc_lib/test_lib" in helper.get_targets("aoc_lib/src/lib.hpp")["unit"]
assert (
"aoc_lib/test_graph"
in helper.get_targets("aoc_lib/src/graph_traversal.hpp")["unit"]
)
assert "aoc_lib/test_ds" in helper.get_targets("aoc_lib/src/ds/grid.hpp")["unit"]
assert (
"aoc_lib/test_ds"
in helper.get_targets("aoc_lib/src/ds/pairing_heap.hpp")["unit"]
)
assert (
"aoc_lib/test_unit_test"
in helper.get_targets("aoc_lib/src/unit_test/unit_test.hpp")["unit"]
)

# answer tests
assert matrix_helper("2023/answer_tests/day01/example2.txt") == dict(
assert helper.get_targets("2023/answer_tests/day01/example2.txt") == dict(
build=set(), answer={"2023/day01"}, unit=set()
)

# workflow files
assert matrix_helper(".github/workflows/gen_matrix.py") == everything
assert matrix_helper(".github/workflows/generate-matrix.yml") == everything
assert matrix_helper(".github/workflows/docker-build.yml") == everything
assert helper.get_targets(".github/workflows/gen_matrix.py") == everything
assert helper.get_targets(".github/workflows/generate-matrix.yml") == everything
assert helper.get_targets(".github/workflows/docker-build.yml") == everything

assert matrix_helper(".github/workflows/test-build.yml") == dict(
assert helper.get_targets(".github/workflows/test-build.yml") == dict(
build=everything["build"], answer=set(), unit=set()
)
assert matrix_helper(".github/workflows/answer-tests.yml") == dict(
assert helper.get_targets(".github/workflows/answer-tests.yml") == dict(
build=set(), answer=everything["answer"], unit=set()
)
assert matrix_helper(".github/workflows/unit-tests.yml") == dict(
assert helper.get_targets(".github/workflows/unit-tests.yml") == dict(
build=set(), answer=set(), unit=everything["unit"]
)

# workflow action helpers
assert matrix_helper(".github/actions/build-action/action.yml") == matrix_helper(
".github/workflows/test-build.yml"
)
assert matrix_helper(
assert helper.get_targets(
".github/actions/build-action/action.yml"
) == helper.get_targets(".github/workflows/test-build.yml")
assert helper.get_targets(
".github/actions/answer-test-action/action.yml"
) == matrix_helper(".github/workflows/answer-tests.yml")
assert matrix_helper(
) == helper.get_targets(".github/workflows/answer-tests.yml")
assert helper.get_targets(
".github/actions/unit-test-action/action.yml"
) == matrix_helper(".github/workflows/unit-tests.yml")
) == helper.get_targets(".github/workflows/unit-tests.yml")
2 changes: 1 addition & 1 deletion .lvimrc
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
" add the aoc_lib dir to 'path', so gf works as expected
let &path = lh#path#munge(&path, lh#path#fix(g:localvimrc_script_dir . '/aoc_lib'))
let &path = lh#path#munge(&path, lh#path#fix(g:localvimrc_script_dir . '/aoc_lib/src'))

if &filetype ==# 'cpp'
let b:surround_{char2nr('D')} = "if constexpr (aoc::DEBUG) {\n\r\n}"
Expand Down
13 changes: 13 additions & 0 deletions aoc_lib/.autoenv.zsh
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
local wrapper_cmd=${0:h}/make_wrapper.sh
if [[ $autoenv_event == 'enter' ]]; then
alias iwyu=${0:h}/iwyu
alias make="$wrapper_cmd -f ${(q)0:h}/Makefile"
compdef "$wrapper_cmd"=make
export AOC_YEAR=aoc_lib
else
unalias iwyu make
# remove completion definition
unset "_comps[$wrapper_cmd]"
unset "_services[$wrapper_cmd]"
unset AOC_YEAR
fi
3 changes: 3 additions & 0 deletions aoc_lib/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# set default target
test:
include ../tools/cpp/Makefile
1 change: 1 addition & 0 deletions aoc_lib/iwyu
1 change: 1 addition & 0 deletions aoc_lib/make_wrapper.sh
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
2 changes: 1 addition & 1 deletion 2023/src/test00_ds.cpp → aoc_lib/src/test_ds.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/******************************************************************************
* File: test00_ds.cpp
* File: test_ds.cpp
*
* Author: Eric T. Johnson (yut23)
* Created: 2024-01-01
Expand Down
2 changes: 1 addition & 1 deletion 2023/src/test00_graph.cpp → aoc_lib/src/test_graph.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/******************************************************************************
* File: test00_graph.cpp
* File: test_graph.cpp
*
* Author: Eric T. Johnson (yut23)
* Created: 2024-01-15
Expand Down
2 changes: 1 addition & 1 deletion 2023/src/test00.cpp → aoc_lib/src/test_lib.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/******************************************************************************
* File: test00.cpp
* File: test_lib.cpp
*
* Author: Eric T. Johnson (yut23)
* Created: 2023-12-19
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/******************************************************************************
* File: test00_unit_test.cpp
* File: test_unit_test.cpp
*
* Author: Eric T. Johnson (yut23)
* Created: 2024-01-23
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
2 changes: 1 addition & 1 deletion tools/cpp/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ ifeq ($(USE_LIBCXX),TRUE)
endif

# These are searched left-to-right
INCLUDES = -Isrc -I../aoc_lib
INCLUDES = -Isrc -I../aoc_lib/src

LOCAL_CXXFLAGS = -Wall -Wextra -O3 -g -std=c++20 $(INCLUDES) $(STDLIB_CXXFLAGS)
DEBUG_CXXFLAGS = $(LOCAL_CXXFLAGS) -O0 -DDEBUG_MODE
Expand Down
Loading