Skip to content

Commit

Permalink
Added runtime class search when testing
Browse files Browse the repository at this point in the history
  • Loading branch information
kevin-belellou committed Nov 21, 2024
1 parent cb03545 commit 5c25d02
Show file tree
Hide file tree
Showing 7 changed files with 103 additions and 41 deletions.
6 changes: 6 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
<!-- Dependency versions -->
<commons-codec.version>1.17.1</commons-codec.version>
<commons-lang3.version>3.17.0</commons-lang3.version>
<spring-context.version>6.2.0</spring-context.version>
<assertj.version>3.26.3</assertj.version>
<junit.version>5.11.3</junit.version>

Expand Down Expand Up @@ -58,6 +59,11 @@
<artifactId>commons-lang3</artifactId>
<version>${commons-lang3.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring-context.version}</version>
</dependency>

<!-- Test scope -->
<dependency>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,9 @@ public interface DaySolver {

int solveFirstStar();

int getFirstStarSolution();

int solveSecondStar();

int getSecondStarSolution();
}
11 changes: 11 additions & 0 deletions src/main/java/com/belellou/kevin/advent/year2015/Day1.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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();
Expand All @@ -48,4 +54,9 @@ protected int doSolveSecondStar(BufferedReader reader) throws IOException {
}
}
}

@Override
public int getSecondStarSolution() {
return 1_795;
}
}
31 changes: 21 additions & 10 deletions src/main/java/com/belellou/kevin/advent/year2015/Day2.java
Original file line number Diff line number Diff line change
Expand Up @@ -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+)$");
Expand All @@ -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);

Expand All @@ -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);

Expand All @@ -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() {
Expand Down
11 changes: 11 additions & 0 deletions src/main/java/com/belellou/kevin/advent/year2015/Day3.java
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand Down Expand Up @@ -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();
Expand Down Expand Up @@ -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) {}
}
27 changes: 19 additions & 8 deletions src/main/java/com/belellou/kevin/advent/year2015/Day4.java
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand All @@ -19,27 +20,37 @@ 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();

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();

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;
}
}
54 changes: 31 additions & 23 deletions src/test/java/com/belellou/kevin/advent/DaySolverTest.java
Original file line number Diff line number Diff line change
@@ -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<TestCase> 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<DynamicTest> testDaySolvers() {
return TEST_CASES.stream()
.<DynamicTest>mapMulti((testCase, consumer) -> {
consumer.accept(dynamicTestOf(testCase, true));
consumer.accept(dynamicTestOf(testCase, false));
}).toList();
private static void createDynamicTest(BeanDefinition component, Consumer<DynamicTest> 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<DynamicTest> testDaySolvers() {
ClassPathScanningCandidateComponentProvider provider = new ClassPathScanningCandidateComponentProvider(false);
provider.addIncludeFilter(new AssignableTypeFilter(DaySolver.class));

Set<BeanDefinition> components = provider.findCandidateComponents(getClass().getPackageName());
return components.stream().mapMulti(DaySolverTest::createDynamicTest).toList();
}
}

0 comments on commit 5c25d02

Please sign in to comment.