Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix/tests #7

Merged
merged 5 commits into from
Dec 27, 2023
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
64 changes: 52 additions & 12 deletions src/graderPrivate/java/h06/H3_MazeSolverRecursiveTest.java
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
package h06;

import com.fasterxml.jackson.databind.node.ArrayNode;
import h06.mock.TestWorld;
import h06.problems.MazeSolver;
import h06.problems.MazeSolverIterative;
import h06.problems.MazeSolverRecursive;
import h06.world.DirectionVector;
import h06.world.World;
Expand Down Expand Up @@ -63,11 +63,6 @@
@SkipAfterFirstFailedTest(TestConstants.SKIP_AFTER_FIRST_FAILED_TEST)
public class H3_MazeSolverRecursiveTest {

/**
* The {@link MazeSolver} to test.
*/
private final MazeSolver solver = new MazeSolverIterative();

/**
* The {@link TypeLink} to {@link MazeSolverRecursive} used for context information.
*
Expand All @@ -94,6 +89,11 @@ private MethodLink getMethod(String name) {
@DisplayName("H3.1 | nextStep(World, Point, DirectionVector)")
public class NextStepTest {

/**
* The {@link MazeSolver} to test.
*/
private final MazeSolver solver = new MazeSolverRecursive();

/**
* Tests whether {@link MazeSolverRecursive#nextStep(World, Point, DirectionVector)} computes the next step
* correctly.
Expand All @@ -105,7 +105,7 @@ public class NextStepTest {
*/
private void assertNextStep(WorldProperties properties, Point p, DirectionVector d, DirectionVector expected) {
MethodLink method = getMethod("nextStep");
World world = properties.createWorld();
World world = properties.createWorld(TestWorld::new);
DirectionVector actual = solver.nextStep(world, p, d);
Context context = contextBuilder().subject(method)
.add(buildWorldContext(properties))
Expand Down Expand Up @@ -267,6 +267,11 @@ public void testRequirements() {
@DisplayName("H3.2 | numberOfSteps(World, Point, Point, Direction)")
public class NumberOfStepsTest {

/**
* The {@link MazeSolver} to test.
*/
private final MazeSolver solver = new TestNextStepWorld();

/**
* Returns the method for context information.
*
Expand Down Expand Up @@ -346,7 +351,7 @@ public void testNextStep() {
*/
private void assertNumberOfSteps(WorldProperties properties, Point s, Point e, DirectionVector d, int expected) {
MethodLink method = getMethod();
World world = properties.createWorld();
World world = properties.createWorld(TestWorld::new);
int actual = solver.numberOfSteps(world, s, e, d);
Context context = contextBuilder().subject(method)
.add(buildWorldContext(properties))
Expand Down Expand Up @@ -460,6 +465,11 @@ public void testRequirements() {
@DisplayName("H3.3 | solve(World, Point, Point, Direction)")
public class SolveTest {

/**
* The {@link MazeSolver} to test.
*/
private final MazeSolver solver = new TestSolverWorld();

/**
* Returns the method for context information.
*
Expand Down Expand Up @@ -527,7 +537,7 @@ public void testCorrectArraySize(
expected[i] = new Point(node.get(i).get("x").asInt(), node.get(i).get("y").asInt());
}
MethodLink method = getMethod();
World world = properties.createWorld();
World world = properties.createWorld(TestWorld::new);
Point[] actual = solver.solve(world, s, e, d);
Context context = contextBuilder().subject(method)
.add(buildWorldContext(properties))
Expand Down Expand Up @@ -573,7 +583,7 @@ public void testContainsStart(
expected[i] = new Point(node.get(i).get("x").asInt(), node.get(i).get("y").asInt());
}
MethodLink method = getMethod();
World world = properties.createWorld();
World world = properties.createWorld(TestWorld::new);
Point[] actual = solver.solve(world, s, e, d);

Context context = contextBuilder().subject(method)
Expand Down Expand Up @@ -620,7 +630,7 @@ public void testContainsEnd(
expected[i] = new Point(node.get(i).get("x").asInt(), node.get(i).get("y").asInt());
}
MethodLink method = getMethod();
World world = properties.createWorld();
World world = properties.createWorld(TestWorld::new);
Point[] actual = solver.solve(world, s, e, d);

Context context = contextBuilder().subject(method)
Expand Down Expand Up @@ -668,7 +678,7 @@ public void testContainsAll(
}

MethodLink method = getMethod();
World world = properties.createWorld();
World world = properties.createWorld(TestWorld::new);
Point[] actual = solver.solve(world, s, e, d);

for (int i = 1; i < expected.length - 1; i++) {
Expand Down Expand Up @@ -698,4 +708,34 @@ public void testRequirements() {
assertRecursive(method.getCtElement(), "MazeSolverRecursive#solve(World, Point, Point, Direction))", context);
}
}

/**
* Used to make testing of implementation independent of next step.
*/
@SkipCheck
private static class TestNextStepWorld extends MazeSolverRecursive {

@Override
public DirectionVector nextStep(World world, Point p, DirectionVector d) {
return !world.isBlocked(p, TutorUtils.rotate270(d))
? TutorUtils.rotate270(d) :
nextStep(world, p, TutorUtils.rotate90(d));
}
}

/**
* Used to make testing of implementation independent of the next step and number of steps.
*/
@SkipCheck
private static class TestSolverWorld extends TestNextStepWorld {

@Override
public int numberOfSteps(World world, Point s, Point e, DirectionVector d) {
if (s.equals(e)) {
return 1;
}
DirectionVector next = nextStep(world, s, d);
return 1 + numberOfSteps(world, next.getMovement(s), e, next);
}
}
}
71 changes: 61 additions & 10 deletions src/graderPrivate/java/h06/H4_MazeSolverIterativeTest.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package h06;

import com.fasterxml.jackson.databind.node.ArrayNode;
import h06.mock.TestWorld;
import h06.problems.MazeSolver;
import h06.problems.MazeSolverIterative;
import h06.problems.MazeSolverRecursive;
Expand Down Expand Up @@ -53,11 +54,6 @@
@SkipAfterFirstFailedTest(TestConstants.SKIP_AFTER_FIRST_FAILED_TEST)
public class H4_MazeSolverIterativeTest {

/**
* The {@link MazeSolver} to test.
*/
private final MazeSolver solver = new MazeSolverIterative();

/**
* The {@link TypeLink} to {@link MazeSolverRecursive} used for context information.
*
Expand All @@ -84,6 +80,11 @@ private MethodLink getMethod(String name) {
@DisplayName("H4.1 | nextStep(World, Point, DirectionVector)")
public class NextStepTest {

/**
* The {@link MazeSolver} to test.
*/
private final MazeSolver solver = new MazeSolverIterative();

/**
* Tests whether {@link MazeSolverRecursive#nextStep(World, Point, DirectionVector)} computes the next step
* correctly.
Expand All @@ -95,7 +96,7 @@ public class NextStepTest {
*/
private void assertNextStep(WorldProperties properties, Point p, DirectionVector d, DirectionVector expected) {
MethodLink method = getMethod("nextStep");
World world = properties.createWorld();
World world = properties.createWorld(TestWorld::new);
DirectionVector actual = solver.nextStep(world, p, d);
Context context = contextBuilder().subject(method)
.add(buildWorldContext(properties))
Expand Down Expand Up @@ -221,6 +222,11 @@ public void testRequirements() {
@DisplayName("H4.2 | numberOfSteps(World, Point, Point, Direction)")
public class NumberOfStepsTest {

/**
* The {@link MazeSolver} to test.
*/
private final MazeSolver solver = new TestNextStepWorld();

/**
* Returns the method for context information.
*
Expand Down Expand Up @@ -272,7 +278,7 @@ private void assertNumberOfSteps(
int expected
) {
MethodLink method = getMethod();
World world = properties.createWorld();
World world = properties.createWorld(TestWorld::new);
int actual = solver.numberOfSteps(world, s, e, d);
Context context = contextBuilder().subject(method)
.add(buildWorldContext(properties))
Expand Down Expand Up @@ -385,6 +391,11 @@ public void testRequirements() {
@DisplayName("H4.3 | solve(World, Point, Point, Direction)")
public class SolveTest {

/**
* The {@link MazeSolver} to test.
*/
private final MazeSolver solver = new TestSolverWorld();

/**
* Returns the method for context information.
*
Expand Down Expand Up @@ -452,7 +463,7 @@ public void testCorrectArraySize(
expected[i] = new Point(node.get(i).get("x").asInt(), node.get(i).get("y").asInt());
}
MethodLink method = getMethod();
World world = properties.createWorld();
World world = properties.createWorld(TestWorld::new);
Point[] actual = solver.solve(world, s, e, d);
Context context = contextBuilder().subject(method)
.add(buildWorldContext(properties))
Expand Down Expand Up @@ -498,7 +509,7 @@ public void testContainsStartEnd(
expected[i] = new Point(node.get(i).get("x").asInt(), node.get(i).get("y").asInt());
}
MethodLink method = getMethod();
World world = properties.createWorld();
World world = properties.createWorld(TestWorld::new);
Point[] actual = solver.solve(world, s, e, d);

Context.Builder<?> context = contextBuilder().subject(method)
Expand Down Expand Up @@ -551,7 +562,7 @@ public void testContainsAll(
}

MethodLink method = getMethod();
World world = properties.createWorld();
World world = properties.createWorld(TestWorld::new);
Point[] actual = solver.solve(world, s, e, d);

for (int i = 1; i < expected.length - 1; i++) {
Expand Down Expand Up @@ -580,4 +591,44 @@ public void testRequirements() {
assertIterative(method.getCtElement(), "MazeSolverIterative#solve(World, Point, Point, Direction)", context);
}
}

/**
* Used to make testing of implementation independent of next step.
*/
@SkipCheck
private static class TestNextStepWorld extends MazeSolverIterative {

@Override
public DirectionVector nextStep(World world, Point p, DirectionVector d) {
DirectionVector next = TutorUtils.rotate270(d);
for (int i = 0; i < DirectionVector.values().length; i++) {
if (!world.isBlocked(p, next)) {
return next;
}
next = TutorUtils.rotate90(next);
}
return d;
}
}

/**
* Used to make testing of implementation independent of the next step and number of steps.
*/
@SkipCheck
private static class TestSolverWorld extends TestNextStepWorld {

@Override
public int numberOfSteps(World world, Point s, Point e, DirectionVector d) {
int steps = 0;
Point next = s;
DirectionVector nextDir = d;
while (!next.equals(e)) {
nextDir = nextStep(world, next, nextDir);
next = nextDir.getMovement(next);
steps++;
}
steps++;
return steps;
}
}
}
16 changes: 16 additions & 0 deletions src/graderPrivate/java/h06/SkipCheck.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package h06;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
* Mark class which should not be checked for rubrics.
*
* @author Nhan Huynh
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface SkipCheck {
}
35 changes: 34 additions & 1 deletion src/graderPrivate/java/h06/TutorUtils.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package h06;

import h06.world.DirectionVector;
import org.junit.jupiter.api.DisplayName;
import org.sourcegrade.jagr.api.rubric.Criterion;
import org.sourcegrade.jagr.api.rubric.Grader;
Expand Down Expand Up @@ -164,7 +165,9 @@ private static Criterion singleCriterion(Class<?> source) {
* @return the criterion for a nested test class
*/
public static Criterion criterionNested(Class<?> source) {
Class<?>[] classes = source.getDeclaredClasses();
Class<?>[] classes = Arrays.stream(source.getDeclaredClasses())
.filter(clazz -> !clazz.isAnnotationPresent(SkipCheck.class))
.toArray(Class[]::new);
Criterion[] mainCriteria = new Criterion[classes.length];
for (int i = 0; i < classes.length; i++) {
Class<?> clazz = classes[i];
Expand All @@ -187,6 +190,7 @@ public static Criterion criterionNested(Class<?> source) {
}
mainCriteria[i] = Criterion.builder()
.shortDescription(clazz.getAnnotation(DisplayName.class).value())
.minPoints(0)
.addChildCriteria(criteria.toArray(Criterion[]::new))
.build();
}
Expand Down Expand Up @@ -272,4 +276,33 @@ private static boolean isRecursive(
return false;
}

/**
* Returns the direction vector counterclockwise to given direction vector (90 degrees to the left).
*
* @param d the direction vector to rotate
* @return the direction vector counterclockwise to the given direction vector
*/
public static DirectionVector rotate270(DirectionVector d) {
return switch (d) {
case UP -> DirectionVector.LEFT;
case RIGHT -> DirectionVector.UP;
case DOWN -> DirectionVector.RIGHT;
case LEFT -> DirectionVector.DOWN;
};
}

/**
* Returns the direction vector clockwise to given direction vector (90 degrees to the right).
*
* @param d the direction vector to rotate
* @return the direction vector clockwise to the given direction vector
*/
public static DirectionVector rotate90(DirectionVector d) {
return switch (d) {
case UP -> DirectionVector.RIGHT;
case RIGHT -> DirectionVector.DOWN;
case DOWN -> DirectionVector.LEFT;
case LEFT -> DirectionVector.UP;
};
}
}
13 changes: 12 additions & 1 deletion src/graderPrivate/java/h06/WorldProperties.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import h06.world.World;

import java.awt.Point;
import java.util.function.BiFunction;


/**
Expand Down Expand Up @@ -42,7 +43,17 @@ public class WorldProperties {
* @return the world with the given properties
*/
public World createWorld() {
World world = new World(width, height);
return createWorld(World::new);
}

/**
* Constructs a world with the given properties.
*
* @param mapper a function used to create dynamic world instance
* @return the world with the given properties
*/
public World createWorld(BiFunction<Integer, Integer, World> mapper) {
World world = mapper.apply(width, height);
for (Point p : horizontal) {
world.placeWall(p.x, p.y, true);
}
Expand Down
Loading
Loading