From af6bb8f808c95a29d5e9917e89615d3b9083fb9d Mon Sep 17 00:00:00 2001 From: zentox Date: Tue, 2 Jan 2024 20:33:03 +0100 Subject: [PATCH 1/4] Improve tests --- .../java/h06/H1_DirectionVectorTest.java | 27 +++++++++---------- .../java/h06/H3_MazeSolverRecursiveTest.java | 26 ++++++++++-------- .../java/h06/H4_MazeSolverIterativeTest.java | 20 +++++++++----- 3 files changed, 41 insertions(+), 32 deletions(-) diff --git a/src/graderPrivate/java/h06/H1_DirectionVectorTest.java b/src/graderPrivate/java/h06/H1_DirectionVectorTest.java index 3d88b0f..05d3255 100644 --- a/src/graderPrivate/java/h06/H1_DirectionVectorTest.java +++ b/src/graderPrivate/java/h06/H1_DirectionVectorTest.java @@ -16,9 +16,12 @@ import org.tudalgo.algoutils.tutor.general.reflections.BasicMethodLink; import org.tudalgo.algoutils.tutor.general.reflections.MethodLink; import org.tudalgo.algoutils.tutor.general.reflections.TypeLink; +import spoon.reflect.code.CtAssignment; import spoon.reflect.code.CtConditional; +import spoon.reflect.code.CtExpression; import spoon.reflect.code.CtIf; import spoon.reflect.code.CtReturn; +import spoon.reflect.code.CtVariableRead; import spoon.reflect.declaration.CtElement; import java.util.List; @@ -89,22 +92,18 @@ public void testRotate270( @DisplayName("02 | Verbindliche Anforderungen") @Test public void testRequirements() { - TypeLink type = getTypeLink(Package.WORLD, DirectionVector.class); BasicMethodLink method = ((BasicMethodLink) getMethodLink(Package.WORLD, DirectionVector.class, "rotate270")); Context context = contextBuilder().subject(method).build(); - - List> returns = method.getCtElement().filterChildren(it -> it instanceof CtReturn) - .list(); - boolean found = false; - for (CtReturn ret : returns) { - if (ret.getReturnedExpression() instanceof CtConditional expression) { - found = true; - break; - } - } - assertTrue(found, context, - result -> "DirectionVector#rotate270() should contain exactly one conditional statement, but found %s" - .formatted(returns.stream().map(CtReturn::getReturnedExpression).toList())); + CtExpression expression = method.getCtElement().filterChildren(it -> it instanceof CtReturn) + .>list().get(0).getReturnedExpression(); + boolean condRet = expression instanceof CtConditional; + boolean condAndVarRead = expression instanceof CtVariableRead + && !method.getCtElement().filterChildren(it -> it instanceof CtConditional).list().isEmpty(); + boolean condAndAssign = expression instanceof CtAssignment assignment + && assignment.getAssignment() instanceof CtConditional; + assertTrue(condRet || condAndVarRead || condAndAssign, context, + result -> "DirectionVector#rotate270() should contain exactly one conditional statement, but found none" + ); } } diff --git a/src/graderPrivate/java/h06/H3_MazeSolverRecursiveTest.java b/src/graderPrivate/java/h06/H3_MazeSolverRecursiveTest.java index 3ff0b59..86e9d11 100644 --- a/src/graderPrivate/java/h06/H3_MazeSolverRecursiveTest.java +++ b/src/graderPrivate/java/h06/H3_MazeSolverRecursiveTest.java @@ -23,12 +23,14 @@ import org.tudalgo.algoutils.tutor.general.reflections.MethodLink; import org.tudalgo.algoutils.tutor.general.reflections.TypeLink; import spoon.reflect.code.CtAbstractInvocation; +import spoon.reflect.code.CtAssignment; import spoon.reflect.code.CtBinaryOperator; import spoon.reflect.code.CtConditional; import spoon.reflect.code.CtExpression; import spoon.reflect.code.CtInvocation; import spoon.reflect.code.CtLiteral; import spoon.reflect.code.CtReturn; +import spoon.reflect.code.CtVariableRead; import spoon.reflect.reference.CtExecutableReference; import java.awt.Point; @@ -221,20 +223,22 @@ public void testLeftRightComplex( @DisplayName("13 | Verbindliche Anforderungen") @Test public void testRequirements() { - TypeLink type = getTypeLink(Package.WORLD, DirectionVector.class); - BasicMethodLink method = ((BasicMethodLink) getMethod("nextStep")); + BasicMethodLink method = ((BasicMethodLink) getMethod("nextStep")); Context context = contextBuilder().subject(method).build(); - + int conds = method.getCtElement().filterChildren(it -> it instanceof CtConditional).list().size(); + assertEquals(1, conds, context, + result -> "MazeSolverRecursive#nextStep(World, Point, DirectionVector) should contain exactly one " + + "conditional statement, but found %s".formatted(conds)); List> returns = method.getCtElement().filterChildren(it -> it instanceof CtReturn) .list(); - boolean found = false; - for (CtReturn ret : returns) { - if (ret.getReturnedExpression() instanceof CtConditional expression) { - found = true; - break; - } - } - assertTrue(found, context, + CtExpression expression = method.getCtElement().filterChildren(it -> it instanceof CtReturn) + .>list().get(0).getReturnedExpression(); + boolean condRet = expression instanceof CtConditional; + boolean condAndVarRead = expression instanceof CtVariableRead + && !method.getCtElement().filterChildren(it -> it instanceof CtConditional).list().isEmpty(); + boolean condAndAssign = expression instanceof CtAssignment assignment + && assignment.getAssignment() instanceof CtConditional; + assertTrue(condRet || condAndVarRead || condAndAssign, context, result -> "MazeSolverRecursive#nextStep(World, Point, DirectionVector) should contain exactly one " + "conditional statement, but found %s" .formatted(returns.stream().map(CtReturn::getReturnedExpression).toList())); diff --git a/src/graderPrivate/java/h06/H4_MazeSolverIterativeTest.java b/src/graderPrivate/java/h06/H4_MazeSolverIterativeTest.java index 37a64b8..d65bf92 100644 --- a/src/graderPrivate/java/h06/H4_MazeSolverIterativeTest.java +++ b/src/graderPrivate/java/h06/H4_MazeSolverIterativeTest.java @@ -24,13 +24,15 @@ import org.tudalgo.algoutils.tutor.general.reflections.TypeLink; import spoon.reflect.code.CtAbstractInvocation; import spoon.reflect.code.CtInvocation; -import spoon.reflect.code.CtLocalVariable; +import spoon.reflect.declaration.CtField; +import spoon.reflect.declaration.CtVariable; import spoon.reflect.reference.CtExecutableReference; import java.awt.Point; import java.util.Arrays; import java.util.List; import java.util.concurrent.TimeUnit; +import java.util.stream.Stream; import static h06.TutorUtils.assertIterative; import static h06.TutorUtils.buildWorldContext; @@ -245,19 +247,23 @@ private BasicMethodLink getMethod() { @Test public void testCounterVariable() { BasicMethodLink method = getMethod(); - List> variables = method.getCtElement() - .filterChildren(it -> it instanceof CtLocalVariable) - .list(); - List> found = variables.stream() + List> variables = Stream.concat( + method.getCtElement().getParent().filterChildren(it -> it instanceof CtField) + .>list() + .stream(), + method.getCtElement().filterChildren(it -> it instanceof CtVariable) + .>list() + .stream() + ) .filter(it -> it.getType().getActualClass().equals(int.class)) .toList(); Context context = contextBuilder().subject(method) .add("Local variables", variables) .build(); assertFalse( - found.isEmpty(), context, + variables.isEmpty(), context, result -> "numberOfSteps(World, Point, Point, Direction) should at least contain one local variable " - + "for computing the total number of steps, found %s".formatted(found.size())); + + "for computing the total number of steps, found %s".formatted(variables)); } /** From 461d28e8495867c8dc8647cf63ed2ead3e29054e Mon Sep 17 00:00:00 2001 From: zentox Date: Wed, 3 Jan 2024 13:30:13 +0100 Subject: [PATCH 2/4] Remove junit timeouts --- src/graderPrivate/java/h06/H1_DirectionVectorTest.java | 5 ----- src/graderPrivate/java/h06/H2_WorldTest.java | 5 ----- src/graderPrivate/java/h06/H3_MazeSolverRecursiveTest.java | 5 ----- src/graderPrivate/java/h06/H4_MazeSolverIterativeTest.java | 5 ----- 4 files changed, 20 deletions(-) diff --git a/src/graderPrivate/java/h06/H1_DirectionVectorTest.java b/src/graderPrivate/java/h06/H1_DirectionVectorTest.java index 05d3255..e9d897d 100644 --- a/src/graderPrivate/java/h06/H1_DirectionVectorTest.java +++ b/src/graderPrivate/java/h06/H1_DirectionVectorTest.java @@ -42,11 +42,6 @@ @DisplayName("H1 | DirectionVector") @TestMethodOrder(MethodOrderer.DisplayName.class) @TestForSubmission -@Timeout( - value = TestConstants.TEST_TIMEOUT_IN_SECONDS, - unit = TimeUnit.SECONDS, - threadMode = Timeout.ThreadMode.SEPARATE_THREAD -) @SkipAfterFirstFailedTest(TestConstants.SKIP_AFTER_FIRST_FAILED_TEST) public class H1_DirectionVectorTest { diff --git a/src/graderPrivate/java/h06/H2_WorldTest.java b/src/graderPrivate/java/h06/H2_WorldTest.java index e2b5648..1f6a1c8 100644 --- a/src/graderPrivate/java/h06/H2_WorldTest.java +++ b/src/graderPrivate/java/h06/H2_WorldTest.java @@ -32,11 +32,6 @@ @DisplayName("H2 | World") @TestMethodOrder(MethodOrderer.DisplayName.class) @TestForSubmission -@Timeout( - value = TestConstants.TEST_TIMEOUT_IN_SECONDS, - unit = TimeUnit.SECONDS, - threadMode = Timeout.ThreadMode.SEPARATE_THREAD -) @SkipAfterFirstFailedTest(TestConstants.SKIP_AFTER_FIRST_FAILED_TEST) public class H2_WorldTest { diff --git a/src/graderPrivate/java/h06/H3_MazeSolverRecursiveTest.java b/src/graderPrivate/java/h06/H3_MazeSolverRecursiveTest.java index 86e9d11..e7152dc 100644 --- a/src/graderPrivate/java/h06/H3_MazeSolverRecursiveTest.java +++ b/src/graderPrivate/java/h06/H3_MazeSolverRecursiveTest.java @@ -57,11 +57,6 @@ @DisplayName("H3 | MazeSolverRecursive") @TestForSubmission @TestMethodOrder(MethodOrderer.DisplayName.class) -@Timeout( - value = TestConstants.TEST_TIMEOUT_IN_SECONDS, - unit = TimeUnit.SECONDS, - threadMode = Timeout.ThreadMode.SEPARATE_THREAD -) @SkipAfterFirstFailedTest(TestConstants.SKIP_AFTER_FIRST_FAILED_TEST) public class H3_MazeSolverRecursiveTest { diff --git a/src/graderPrivate/java/h06/H4_MazeSolverIterativeTest.java b/src/graderPrivate/java/h06/H4_MazeSolverIterativeTest.java index d65bf92..697c6d1 100644 --- a/src/graderPrivate/java/h06/H4_MazeSolverIterativeTest.java +++ b/src/graderPrivate/java/h06/H4_MazeSolverIterativeTest.java @@ -48,11 +48,6 @@ @DisplayName("H4 | MazeSolverIterative") @TestMethodOrder(MethodOrderer.DisplayName.class) @TestForSubmission -@Timeout( - value = TestConstants.TEST_TIMEOUT_IN_SECONDS, - unit = TimeUnit.SECONDS, - threadMode = Timeout.ThreadMode.SEPARATE_THREAD -) @SkipAfterFirstFailedTest(TestConstants.SKIP_AFTER_FIRST_FAILED_TEST) public class H4_MazeSolverIterativeTest { From dbaeabcddecf7027c9bfcc4b0a2cae1bb618d0cc Mon Sep 17 00:00:00 2001 From: zentox Date: Sun, 7 Jan 2024 22:25:55 +0100 Subject: [PATCH 3/4] Fix wrong requirements tests for criterion 25 --- build.gradle.kts | 6 ++++++ gradle/libs.versions.toml | 2 +- src/graderPrivate/java/h06/H3_MazeSolverRecursiveTest.java | 2 +- src/graderPrivate/java/h06/TutorUtils.java | 2 +- 4 files changed, 9 insertions(+), 3 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index b2582ab..7f646ed 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -7,6 +7,12 @@ plugins { version = file("version").readLines().first() +configurations.all { + resolutionStrategy { + force("org.junit-pioneer:junit-pioneer:1.7.1") + } +} + jagr { assignmentId.set("h06") submissions { diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index dfabc90..23befaf 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -10,7 +10,7 @@ annotations = "org.jetbrains:annotations:23.0.0" algoutils-student = { module = "org.tudalgo:algoutils-student", version.ref = "algoutils" } algoutils-tutor = { module = "org.tudalgo:algoutils-tutor", version.ref = "algoutils" } junit-core = { module = "org.junit.jupiter:junit-jupiter", version = "5.9.1" } -junit-pioneer = { module = "org.junit-pioneer:junit-pioneer", version = "1.7.1" } +junit-pioneer = { module = "org.junit-pioneer:junit-pioneer", version = "2.2.0" } fopbot = { module = "org.tudalgo:fopbot", version = "0.7.0" } [bundles] diff --git a/src/graderPrivate/java/h06/H3_MazeSolverRecursiveTest.java b/src/graderPrivate/java/h06/H3_MazeSolverRecursiveTest.java index e7152dc..ef8ff40 100644 --- a/src/graderPrivate/java/h06/H3_MazeSolverRecursiveTest.java +++ b/src/graderPrivate/java/h06/H3_MazeSolverRecursiveTest.java @@ -701,7 +701,7 @@ public void testContainsAll( @DisplayName("24 | Verbindliche Anforderungen") @Test public void testRequirements() { - BasicMethodLink method = ((BasicMethodLink) H3_MazeSolverRecursiveTest.this.getMethod("numberOfSteps")); + BasicMethodLink method = ((BasicMethodLink) H3_MazeSolverRecursiveTest.this.getMethod("solve")); Context context = contextBuilder().subject(method) .build(); assertRecursive(method.getCtElement(), "MazeSolverRecursive#solve(World, Point, Point, Direction))", context); diff --git a/src/graderPrivate/java/h06/TutorUtils.java b/src/graderPrivate/java/h06/TutorUtils.java index f1848f4..01a1cab 100644 --- a/src/graderPrivate/java/h06/TutorUtils.java +++ b/src/graderPrivate/java/h06/TutorUtils.java @@ -273,7 +273,7 @@ private static boolean isRecursive( } return isRecursive(method, newCalls, visited); } - return false; + return true; } /** From 2a0597b81dd9cecc6ba3d2e31f69333985232231 Mon Sep 17 00:00:00 2001 From: zentox Date: Sun, 7 Jan 2024 22:31:27 +0100 Subject: [PATCH 4/4] Change lambda param names --- src/graderPrivate/java/h06/TutorUtils.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/graderPrivate/java/h06/TutorUtils.java b/src/graderPrivate/java/h06/TutorUtils.java index 01a1cab..2fadec0 100644 --- a/src/graderPrivate/java/h06/TutorUtils.java +++ b/src/graderPrivate/java/h06/TutorUtils.java @@ -257,7 +257,7 @@ private static boolean isRecursive( List> calls, Set> visited ) { - if (calls.stream().anyMatch(it -> it.getSimpleName().equals(method.getSimpleName()))) { + if (calls.stream().anyMatch(m -> m.getSimpleName().equals(method.getSimpleName()))) { return true; } for (CtExecutableReference call : calls) { @@ -265,10 +265,10 @@ private static boolean isRecursive( .list() .stream() .map(it -> it instanceof CtInvocation ? ((CtInvocation) it).getExecutable() : null) - .filter(it -> !visited.contains(it)) + .filter(m -> !visited.contains(m)) .peek(visited::add) .toList(); - if (newCalls.stream().anyMatch(it -> !it.filterChildren(it2 -> it2 instanceof CtLoop).list().isEmpty())) { + if (newCalls.stream().anyMatch(m -> !m.filterChildren(statement -> statement instanceof CtLoop).list().isEmpty())) { return false; } return isRecursive(method, newCalls, visited);