From 5c25d02ac5313c035bfadba59c4fe10e8b70115e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Belellou?= Date: Thu, 21 Nov 2024 12:02:13 +0100 Subject: [PATCH] Added runtime class search when testing --- pom.xml | 6 +++ .../kevin/advent/generic/DaySolver.java | 4 ++ .../belellou/kevin/advent/year2015/Day1.java | 11 ++++ .../belellou/kevin/advent/year2015/Day2.java | 31 +++++++---- .../belellou/kevin/advent/year2015/Day3.java | 11 ++++ .../belellou/kevin/advent/year2015/Day4.java | 27 +++++++--- .../belellou/kevin/advent/DaySolverTest.java | 54 +++++++++++-------- 7 files changed, 103 insertions(+), 41 deletions(-) diff --git a/pom.xml b/pom.xml index 1141121..f722619 100644 --- a/pom.xml +++ b/pom.xml @@ -27,6 +27,7 @@ 1.17.1 3.17.0 + 6.2.0 3.26.3 5.11.3 @@ -58,6 +59,11 @@ commons-lang3 ${commons-lang3.version} + + org.springframework + spring-context + ${spring-context.version} + diff --git a/src/main/java/com/belellou/kevin/advent/generic/DaySolver.java b/src/main/java/com/belellou/kevin/advent/generic/DaySolver.java index aa813e5..63d7c46 100644 --- a/src/main/java/com/belellou/kevin/advent/generic/DaySolver.java +++ b/src/main/java/com/belellou/kevin/advent/generic/DaySolver.java @@ -4,5 +4,9 @@ public interface DaySolver { int solveFirstStar(); + int getFirstStarSolution(); + int solveSecondStar(); + + int getSecondStarSolution(); } diff --git a/src/main/java/com/belellou/kevin/advent/year2015/Day1.java b/src/main/java/com/belellou/kevin/advent/year2015/Day1.java index 70f2e71..b10b039 100644 --- a/src/main/java/com/belellou/kevin/advent/year2015/Day1.java +++ b/src/main/java/com/belellou/kevin/advent/year2015/Day1.java @@ -9,6 +9,7 @@ import com.belellou.kevin.advent.generic.Day; import com.belellou.kevin.advent.generic.Year; +@SuppressWarnings("unused") public class Day1 extends AbstractDaySolver { private static final int STARTING_FLOOR = 0; @@ -27,6 +28,11 @@ protected int doSolveFirstStar(BufferedReader reader) throws IOException { return STARTING_FLOOR + up - down; } + @Override + public int getFirstStarSolution() { + return 74; + } + @Override protected int doSolveSecondStar(BufferedReader reader) throws IOException { String line = reader.readLine(); @@ -48,4 +54,9 @@ protected int doSolveSecondStar(BufferedReader reader) throws IOException { } } } + + @Override + public int getSecondStarSolution() { + return 1_795; + } } diff --git a/src/main/java/com/belellou/kevin/advent/year2015/Day2.java b/src/main/java/com/belellou/kevin/advent/year2015/Day2.java index 81ac540..9edbd20 100644 --- a/src/main/java/com/belellou/kevin/advent/year2015/Day2.java +++ b/src/main/java/com/belellou/kevin/advent/year2015/Day2.java @@ -11,6 +11,7 @@ import com.belellou.kevin.advent.generic.Day; import com.belellou.kevin.advent.generic.Year; +@SuppressWarnings("unused") public class Day2 extends AbstractDaySolver { private static final Pattern PATTERN = Pattern.compile("^(\\d+)x(\\d+)x(\\d+)$"); @@ -19,11 +20,6 @@ public Day2() { super(Year.YEAR_2015, Day.DAY_2); } - @Override - protected int doSolveFirstStar(BufferedReader reader) { - return reader.lines().map(Day2::findAreaNeeded).reduce(Integer::sum).orElseThrow(); - } - private static int findAreaNeeded(String line) { Dimensions dimensions = getDimensions(line); @@ -34,11 +30,6 @@ private static int findAreaNeeded(String line) { return 2 * side1Area + 2 * side2Area + 2 * side3Area + NumberUtils.min(side1Area, side2Area, side3Area); } - @Override - protected int doSolveSecondStar(BufferedReader reader) { - return reader.lines().map(Day2::findLengthNeeded).reduce(Integer::sum).orElseThrow(); - } - private static int findLengthNeeded(String line) { Dimensions dimensions = getDimensions(line); @@ -60,6 +51,26 @@ private static Dimensions getDimensions(String line) { return new Dimensions(length, width, height); } + @Override + protected int doSolveFirstStar(BufferedReader reader) { + return reader.lines().map(Day2::findAreaNeeded).reduce(Integer::sum).orElseThrow(); + } + + @Override + public int getFirstStarSolution() { + return 1_588_178; + } + + @Override + protected int doSolveSecondStar(BufferedReader reader) { + return reader.lines().map(Day2::findLengthNeeded).reduce(Integer::sum).orElseThrow(); + } + + @Override + public int getSecondStarSolution() { + return 3_783_758; + } + private record Dimensions(int length, int width, int height) { Integer[] sorted() { diff --git a/src/main/java/com/belellou/kevin/advent/year2015/Day3.java b/src/main/java/com/belellou/kevin/advent/year2015/Day3.java index f566b14..598b3d4 100644 --- a/src/main/java/com/belellou/kevin/advent/year2015/Day3.java +++ b/src/main/java/com/belellou/kevin/advent/year2015/Day3.java @@ -9,6 +9,7 @@ import com.belellou.kevin.advent.generic.Day; import com.belellou.kevin.advent.generic.Year; +@SuppressWarnings("unused") public class Day3 extends AbstractDaySolver { public Day3() { @@ -47,6 +48,11 @@ protected int doSolveFirstStar(BufferedReader reader) throws IOException { return houses.size() + 1; } + @Override + public int getFirstStarSolution() { + return 2_081; + } + @Override protected int doSolveSecondStar(BufferedReader reader) throws IOException { String line = reader.readLine(); @@ -98,5 +104,10 @@ protected int doSolveSecondStar(BufferedReader reader) throws IOException { return houses.size(); } + @Override + public int getSecondStarSolution() { + return 2_341; + } + private record Position(int x, int y) {} } diff --git a/src/main/java/com/belellou/kevin/advent/year2015/Day4.java b/src/main/java/com/belellou/kevin/advent/year2015/Day4.java index d0b5566..76d7a7c 100644 --- a/src/main/java/com/belellou/kevin/advent/year2015/Day4.java +++ b/src/main/java/com/belellou/kevin/advent/year2015/Day4.java @@ -10,6 +10,7 @@ import com.belellou.kevin.advent.generic.Day; import com.belellou.kevin.advent.generic.Year; +@SuppressWarnings("unused") public class Day4 extends AbstractDaySolver { private static final String FIVE_ZEROES_PATTERN = "00000"; @@ -19,6 +20,16 @@ public Day4() { super(Year.YEAR_2015, Day.DAY_4); } + private static int findNumber(String line, String pattern) { + return IntStream.range(1, Integer.MAX_VALUE) + .takeWhile(value -> { + String s = DigestUtils.md5Hex(line + value); + return !s.startsWith(pattern); + }) + .reduce((left, right) -> right) + .orElseThrow() + 1; + } + @Override protected int doSolveFirstStar(BufferedReader reader) throws IOException { String line = reader.readLine(); @@ -26,6 +37,11 @@ protected int doSolveFirstStar(BufferedReader reader) throws IOException { return findNumber(line, FIVE_ZEROES_PATTERN); } + @Override + public int getFirstStarSolution() { + return 346_386; + } + @Override protected int doSolveSecondStar(BufferedReader reader) throws IOException { String line = reader.readLine(); @@ -33,13 +49,8 @@ protected int doSolveSecondStar(BufferedReader reader) throws IOException { return findNumber(line, SIX_ZEROES_PATTERN); } - private static int findNumber(String line, String pattern) { - return IntStream.range(1, Integer.MAX_VALUE) - .takeWhile(value -> { - String s = DigestUtils.md5Hex(line + value); - return !s.startsWith(pattern); - }) - .reduce((left, right) -> right) - .orElseThrow() + 1; + @Override + public int getSecondStarSolution() { + return 9_958_218; } } diff --git a/src/test/java/com/belellou/kevin/advent/DaySolverTest.java b/src/test/java/com/belellou/kevin/advent/DaySolverTest.java index 80f4fc2..7dadbc4 100644 --- a/src/test/java/com/belellou/kevin/advent/DaySolverTest.java +++ b/src/test/java/com/belellou/kevin/advent/DaySolverTest.java @@ -1,46 +1,54 @@ package com.belellou.kevin.advent; +import java.lang.reflect.InvocationTargetException; import java.util.List; +import java.util.Set; +import java.util.function.Consumer; import org.junit.jupiter.api.DynamicTest; import org.junit.jupiter.api.TestFactory; +import org.springframework.beans.factory.config.BeanDefinition; +import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider; +import org.springframework.core.type.filter.AssignableTypeFilter; import com.belellou.kevin.advent.generic.DaySolver; -import com.belellou.kevin.advent.year2015.Day1; -import com.belellou.kevin.advent.year2015.Day2; -import com.belellou.kevin.advent.year2015.Day3; -import com.belellou.kevin.advent.year2015.Day4; import static org.assertj.core.api.Assertions.assertThat; public class DaySolverTest { - private static final List TEST_CASES = List.of(new TestCase(new Day1(), 74, 1_795), - new TestCase(new Day2(), 1_588_178, 3_783_758), - new TestCase(new Day3(), 2_081, 2_341), - new TestCase(new Day4(), 346_386, 9_958_218)); - private static final String FIRST_SOLUTION = " - First solution"; private static final String SECOND_SOLUTION = " - Second solution"; - @TestFactory - List testDaySolvers() { - return TEST_CASES.stream() - .mapMulti((testCase, consumer) -> { - consumer.accept(dynamicTestOf(testCase, true)); - consumer.accept(dynamicTestOf(testCase, false)); - }).toList(); + private static void createDynamicTest(BeanDefinition component, Consumer consumer) { + try { + Class clazz = Class.forName(component.getBeanClassName()); + DaySolver daySolver = (DaySolver) clazz.getDeclaredConstructor().newInstance(); + + consumer.accept(dynamicTestOf(daySolver, true)); + consumer.accept(dynamicTestOf(daySolver, false)); + } catch (ClassNotFoundException | InvocationTargetException | InstantiationException | + IllegalAccessException | NoSuchMethodException e) { + throw new RuntimeException(e); + } } - private static DynamicTest dynamicTestOf(TestCase testCase, boolean firstSolution) { - return DynamicTest.dynamicTest(testCase.daySolver + (firstSolution ? FIRST_SOLUTION : SECOND_SOLUTION), + private static DynamicTest dynamicTestOf(DaySolver daySolver, boolean firstSolution) { + return DynamicTest.dynamicTest(daySolver + (firstSolution ? FIRST_SOLUTION : SECOND_SOLUTION), firstSolution - ? () -> assertThat(testCase.daySolver.solveFirstStar()) - .isEqualTo(testCase.firstSolution) - : () -> assertThat(testCase.daySolver.solveSecondStar()) - .isEqualTo(testCase.secondSolution) + ? () -> assertThat(daySolver.solveFirstStar()) + .isEqualTo(daySolver.getFirstStarSolution()) + : () -> assertThat(daySolver.solveSecondStar()) + .isEqualTo(daySolver.getSecondStarSolution()) ); } - protected record TestCase(DaySolver daySolver, int firstSolution, int secondSolution) {} + @TestFactory + List testDaySolvers() { + ClassPathScanningCandidateComponentProvider provider = new ClassPathScanningCandidateComponentProvider(false); + provider.addIncludeFilter(new AssignableTypeFilter(DaySolver.class)); + + Set components = provider.findCandidateComponents(getClass().getPackageName()); + return components.stream().mapMulti(DaySolverTest::createDynamicTest).toList(); + } }