Commit d845bb4b authored by Adam Blank's avatar Adam Blank
Browse files

Merge branch 'fixes' into 'master'

Fixes

See merge request !1
1 merge request!1Fixes
Pipeline #76080 failed with stage
in 0 seconds
Showing with 852 additions and 744 deletions
+852 -744
File added
<component name="libraryTable">
<library name="org.javassist:javassist:3.29.2-GA" type="repository">
<properties maven-id="org.javassist:javassist:3.29.2-GA" />
<CLASSES>
<root url="jar://$MAVEN_REPOSITORY$/org/javassist/javassist/3.29.2-GA/javassist-3.29.2-GA.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES />
</library>
</component>
\ No newline at end of file
......@@ -9,7 +9,7 @@
<component name="PreferredVcsStorage">
<preferredVcsName>ApexVCS</preferredVcsName>
</component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_17" default="true" project-jdk-name="17" project-jdk-type="JavaSDK">
<component name="ProjectRootManager" version="2" languageLevel="JDK_15" default="true" project-jdk-name="19" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/out" />
</component>
</project>
</project>
\ No newline at end of file
......@@ -4,6 +4,7 @@
<option name="MAIN_CLASS_NAME" value="" />
<option name="METHOD_NAME" value="" />
<option name="TEST_OBJECT" value="tags" />
<option name="VM_PARAMETERS" value="-noverify -ea -javaagent:.idea/libraries/instrumentation.jar" />
<option name="PARAMETERS" value="" />
<option name="TEST_SEARCH_SCOPE">
<value defaultName="wholeProject" />
......@@ -13,4 +14,4 @@
<option name="Make" enabled="true" />
</method>
</configuration>
</component>
\ No newline at end of file
</component>
......@@ -4,6 +4,7 @@
<option name="MAIN_CLASS_NAME" value="" />
<option name="METHOD_NAME" value="" />
<option name="TEST_OBJECT" value="tags" />
<option name="VM_PARAMETERS" value="-noverify -ea -javaagent:.idea/libraries/instrumentation.jar" />
<option name="PARAMETERS" value="" />
<option name="TEST_SEARCH_SCOPE">
<value defaultName="wholeProject" />
......@@ -13,4 +14,4 @@
<option name="Make" enabled="true" />
</method>
</configuration>
</component>
\ No newline at end of file
</component>
......@@ -4,6 +4,7 @@
<option name="MAIN_CLASS_NAME" value="" />
<option name="METHOD_NAME" value="" />
<option name="TEST_OBJECT" value="tags" />
<option name="VM_PARAMETERS" value="-noverify -ea -javaagent:.idea/libraries/instrumentation.jar" />
<option name="PARAMETERS" value="" />
<option name="TEST_SEARCH_SCOPE">
<value defaultName="wholeProject" />
......
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ChangeListManager">
<list default="true" id="59dc1d65-5f60-42d1-aafd-1f41614da1fe" name="Changes" comment="">
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/edu/caltech/cs2/datastructures/ArrayDeque.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/edu/caltech/cs2/datastructures/ArrayDeque.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/edu/caltech/cs2/datastructures/LinkedDeque.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/edu/caltech/cs2/datastructures/LinkedDeque.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/tests/edu/caltech/cs2/helpers/Inspection.java" beforeDir="false" afterPath="$PROJECT_DIR$/tests/edu/caltech/cs2/helpers/Inspection.java" afterDir="false" />
</list>
<option name="SHOW_DIALOG" value="false" />
<option name="HIGHLIGHT_CONFLICTS" value="true" />
<option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
<option name="LAST_RESOLUTION" value="IGNORE" />
</component>
<component name="Git.Settings">
<option name="RECENT_GIT_ROOT_PATH" value="$PROJECT_DIR$" />
</component>
<component name="MarkdownSettingsMigration">
<option name="stateVersion" value="1" />
</component>
<component name="ProjectLevelVcsManager" settingsEditedManually="true" />
<component name="RunManager" selected="JUnit.C Tests">
<list>
<item itemvalue="JUnit.C Tests" />
<item itemvalue="JUnit.B Tests" />
<item itemvalue="JUnit.A Tests" />
</list>
</component>
<component name="TaskManager">
<servers />
</component>
</project>
\ No newline at end of file
......@@ -15,5 +15,6 @@
<orderEntry type="library" name="org.junit.jupiter:junit-jupiter:5.6.0-M1" level="project" />
<orderEntry type="library" name="org.hamcrest:hamcrest:2.2" level="project" />
<orderEntry type="library" name="org.hamcrest:hamcrest-core:2.2" level="project" />
<orderEntry type="library" name="org.javassist:javassist:3.29.2-GA" level="project" />
</component>
</module>
\ No newline at end of file
......@@ -6,6 +6,10 @@ import java.util.Iterator;
public class CircularArrayFixedSizeQueue<E> implements IFixedSizeQueue<E> {
public CircularArrayFixedSizeQueue(int capacity) {
}
@Override
public boolean isFull() {
return false;
......@@ -36,6 +40,16 @@ public class CircularArrayFixedSizeQueue<E> implements IFixedSizeQueue<E> {
return 0;
}
@Override
public void add(E e) {
}
@Override
public void clear() {
}
@Override
public Iterator<E> iterator() {
return null;
......
......@@ -4,7 +4,7 @@ package edu.caltech.cs2.interfaces;
* This interface represents a queue - a data structure that can add elements at one end and remove them from the other.
* @param <E> Element type
*/
public interface IQueue<E> extends Iterable<E> {
public interface IQueue<E> extends Iterable<E>, ICollection<E> {
/**
* Adds an element to the back of the queue.
* @param e Element to add
......
package edu.caltech.cs2.datastructures;
import edu.caltech.cs2.helpers.Inspection;
import edu.caltech.cs2.helpers.Reflection;
import edu.caltech.cs2.helpers.RuntimeInstrumentation;
import edu.caltech.cs2.interfaces.IFixedSizeQueueTests;
import edu.caltech.cs2.interfaces.IFixedSizeQueue;
import edu.caltech.cs2.interfaces.IQueue;
import edu.caltech.cs2.helpers.*;
import edu.caltech.cs2.interfaces.*;
import org.junit.jupiter.api.*;
import org.junit.jupiter.api.extension.ExtendWith;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.CsvSource;
import org.junit.jupiter.params.provider.ValueSource;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.util.*;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.stream.Stream;
import static edu.caltech.cs2.project03.Project03TestOrdering.*;
import static java.util.concurrent.TimeUnit.SECONDS;
......@@ -22,174 +21,153 @@ import static org.junit.jupiter.api.Assertions.*;
@Tag("B")
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
public class CircularArrayFixedSizeQueueTests implements IFixedSizeQueueTests {
@ExtendWith(TestExtension.class)
public class CircularArrayFixedSizeQueueTests {
private static String FIXED_QUEUE_SOURCE = "src/edu/caltech/cs2/datastructures/CircularArrayFixedSizeQueue.java";
private Constructor circFixedSizeQueueConstructor = Reflection.getConstructor(CircularArrayFixedSizeQueue.class,
int.class);
private int DEFAULT_CAPACITY = 10;
public IQueue<Object> newQueue() {
return Reflection.newInstance(circFixedSizeQueueConstructor, DEFAULT_CAPACITY);
}
public IQueue<Object> newQueue(int capacity) {
return Reflection.newInstance(circFixedSizeQueueConstructor, capacity);
}
public IFixedSizeQueue<Object> newFixedSizeQueue(int capacity) {
return Reflection.newInstance(circFixedSizeQueueConstructor, capacity);
}
// FIXED QUEUE-SPECIFIC TESTS ----------------------------------------
@Order(classSpecificTestLevel)
@DisplayName("Does not use or import disallowed classes")
@Test
public void testForInvalidClasses() {
List<String> regexps = List.of("java\\.util\\.(?!Iterator)", "java\\.lang\\.reflect", "java\\.io");
Inspection.assertNoImportsOf(FIXED_QUEUE_SOURCE, regexps);
Inspection.assertNoUsageOf(FIXED_QUEUE_SOURCE, regexps);
}
@DisplayName("Style")
@Nested
class StyleTests implements IStyleTests {
public int getMaxFields() {
return 4;
}
@Order(classSpecificTestLevel)
@DisplayName("There are no static fields")
@Test
public void testConstantFields() {
Reflection.assertFieldsEqualTo(CircularArrayFixedSizeQueue.class, "static", 0);
}
public List<String> getPublicInterface() {
return List.of("enqueue", "dequeue", "peek", "iterator", "size", "isFull", "capacity", "toString", "add", "clear");
}
@Order(classSpecificTestLevel)
@DisplayName("The overall number of fields is small")
@Test
public void testSmallNumberOfFields() {
Reflection.assertFieldsLessThan(CircularArrayFixedSizeQueue.class, "private", 4);
}
@Override
public String getSource() {
return FIXED_QUEUE_SOURCE;
}
@Order(classSpecificTestLevel)
@DisplayName("There are no public fields")
@Test
public void testNoPublicFields() {
Reflection.assertNoPublicFields(CircularArrayFixedSizeQueue.class);
@Override
public Class<?> getClazz() {
return CircularArrayFixedSizeQueue.class;
}
}
@Order(classSpecificTestLevel)
@DisplayName("There are no protected fields")
@Test
public void testNoProtectedFields() {
Reflection.assertNoProtectedFields(CircularArrayFixedSizeQueue.class);
}
@Nested
@DisplayName("Runtime Complexity")
class RuntimeTests {
@Order(complexityTestLevel)
@DisplayName("enqueue() and dequeue() take constant time")
@Timeout(value = 10, unit = SECONDS)
@Test()
public void testQueueOperationComplexity() {
Function<Integer, IFixedSizeQueue<Integer>> provide = (Integer numElements) -> {
Constructor c = Reflection.getConstructor(CircularArrayFixedSizeQueue.class, int.class);
IFixedSizeQueue<Integer> q = Reflection.newInstance(c, numElements * 2);
for (int i = 0; i < numElements; i++) {
q.enqueue(i);
}
return q;
};
Consumer<IFixedSizeQueue<Integer>> enqueue = (IFixedSizeQueue<Integer> q) -> q.enqueue(0);
Consumer<IFixedSizeQueue<Integer>> dequeue = (IFixedSizeQueue<Integer> q) -> q.dequeue();
RuntimeInstrumentation.assertAtMost("enqueue", RuntimeInstrumentation.ComplexityType.CONSTANT, provide, enqueue, 8);
RuntimeInstrumentation.assertAtMost("dequeue", RuntimeInstrumentation.ComplexityType.CONSTANT, provide, dequeue, 8);
}
@Order(classSpecificTestLevel)
@DisplayName("All fields in CircularArrayFixedSizeQueue have modifiers")
@Test
public void testFieldModifiers() {
Reflection.assertFieldModifiers(CircularArrayFixedSizeQueue.class);
@Order(complexityTestLevel)
@DisplayName("peek() takes constant time")
@Timeout(value = 10, unit = SECONDS)
@Test()
public void testPeekComplexity() {
Function<Integer, IFixedSizeQueue<Integer>> provide = (Integer numElements) -> {
Constructor c = Reflection.getConstructor(CircularArrayFixedSizeQueue.class, int.class);
IFixedSizeQueue<Integer> q = Reflection.newInstance(c, numElements * 2);
for (int i = 0; i < numElements; i++) {
q.enqueue(i);
}
return q;
};
Consumer<IFixedSizeQueue<Integer>> peek = (IFixedSizeQueue<Integer> q) -> q.peek();
RuntimeInstrumentation.assertAtMost("peek", RuntimeInstrumentation.ComplexityType.CONSTANT, provide, peek, 8);
}
}
@Order(classSpecificTestLevel)
@DisplayName("The public interface is correct")
@Test
public void testPublicInterface() {
Reflection.assertPublicInterface(CircularArrayFixedSizeQueue.class,
List.of("enqueue", "dequeue", "peek", "iterator", "size", "isFull", "capacity", "toString"));
}
@Nested
@DisplayName("IFixedSizeQueue Functionality")
class QueueTests implements IFixedSizeQueueTests {
@Order(classSpecificTestLevel)
@DisplayName("Uses this(...) notation in all but one constructor")
@Test
public void testForThisConstructors() {
Inspection.assertConstructorHygiene(FIXED_QUEUE_SOURCE);
}
public IFixedSizeQueue<Object> newQueue() {
return Reflection.newInstance(circFixedSizeQueueConstructor);
}
// TOSTRING TESTS ---------------------------------------------------
public IFixedSizeQueue<Object> newQueue(int size) {
return Reflection.newInstance(circFixedSizeQueueConstructor, size);
}
@Order(toStringTestLevel)
@DisplayName("toString is correctly overridden")
@Test
public void testToStringOverride() {
Reflection.assertMethodCorrectlyOverridden(ArrayDeque.class, "toString");
@Override
public IFixedSizeQueue<Object> newFixedSizeQueue(int capacity) {
return CircularArrayFixedSizeQueueTests.this.newFixedSizeQueue(capacity);
}
}
@Order(toStringTestLevel)
@DisplayName("toString() matches java.util.ArrayDeque")
@ParameterizedTest(name = "Test toString() on [{arguments}]")
@ValueSource(strings = { "0, 1, 2, 3", "5, 4, 3, 2, 1", "8, 3, 5, 7, 4, 3, 12, 12, 1" })
public void testToString(String inputs) {
java.util.ArrayDeque<String> reference = new java.util.ArrayDeque<String>();
Constructor c = Reflection.getConstructor(CircularArrayFixedSizeQueue.class, int.class);
IFixedSizeQueue<String> me = Reflection.newInstance(c, inputs.length());
for (String value : inputs.trim().split(", ")) {
assertEquals(reference.toString(), me.toString(), "toString outputs should be the same");
reference.addLast(value);
me.enqueue(value);
@Nested
@DisplayName("ICollection Functionality")
class CollectionTests implements ICollectionTests {
@Override
public ICollection<Object> newCollection() {
return Reflection.newInstance(circFixedSizeQueueConstructor, 100000);
}
}
// TIME COMPLEXITY TESTS ------------------------------------------------
@Order(complexityTestLevel)
@DisplayName("enqueue() and dequeue() take constant time")
@Timeout(value = 10, unit = SECONDS)
@Test()
public void testQueueOperationComplexity() {
Function<Integer, IFixedSizeQueue<Integer>> provide = (Integer numElements) -> {
Constructor c = Reflection.getConstructor(CircularArrayFixedSizeQueue.class, int.class);
IFixedSizeQueue<Integer> q = Reflection.newInstance(c, numElements * 2);
for (int i = 0; i < numElements; i++) {
q.enqueue(i);
}
return q;
};
Consumer<IFixedSizeQueue<Integer>> enqueue = (IFixedSizeQueue<Integer> q) -> q.enqueue(0);
Consumer<IFixedSizeQueue<Integer>> dequeue = (IFixedSizeQueue<Integer> q) -> q.dequeue();
RuntimeInstrumentation.assertAtMost("enqueue", RuntimeInstrumentation.ComplexityType.CONSTANT, provide, enqueue, 8);
RuntimeInstrumentation.assertAtMost("dequeue", RuntimeInstrumentation.ComplexityType.CONSTANT, provide, dequeue, 8);
}
@DisplayName("Implementation Tests")
@Nested
class ImplementationTests {
@Order(fixedSizeQueueLevel)
@DisplayName("Test iterator matches reference for wraparound values")
@TestHint("This test is likely failing because you don't have correct wrap-around behavior.\n Remember that everything should advance; so, it's possible that your start wraps around.")
@ParameterizedTest(name = "Test iterator and wraparound behavior with {1} random values with seed = {0} and fixed array size = {2}")
@CsvSource({"69, 200, 20", "21, 300, 200"})
public void testWrapAround(int seed, int numVals, int queueSize) {
Random r = new Random(seed);
IFixedSizeQueue<Object> me = newFixedSizeQueue(queueSize);
Queue<Object> reference = new java.util.ArrayDeque<>();
assertEquals(queueSize, me.capacity(), "capacity does not match expected value");
for (int i = 0; i < queueSize; i++) {
int num = r.nextInt();
assertFalse(me.isFull(), "queue should not be full");
assertTrue(me.enqueue(num), "enqueue should be successful");
reference.add(num);
@Order(complexityTestLevel)
@DisplayName("peek() takes constant time")
@Timeout(value = 10, unit = SECONDS)
@Test()
public void testPeekComplexity() {
Function<Integer, IFixedSizeQueue<Integer>> provide = (Integer numElements) -> {
Constructor c = Reflection.getConstructor(CircularArrayFixedSizeQueue.class, int.class);
IFixedSizeQueue<Integer> q = Reflection.newInstance(c, numElements * 2);
for (int i = 0; i < numElements; i++) {
q.enqueue(i);
}
return q;
};
Consumer<IFixedSizeQueue<Integer>> peek = (IFixedSizeQueue<Integer> q) -> q.peek();
RuntimeInstrumentation.assertAtMost("peek", RuntimeInstrumentation.ComplexityType.CONSTANT, provide, peek, 8);
}
@Order(fixedSizeQueueLevel)
@DisplayName("Test iterator matches reference for wraparound values")
@ParameterizedTest(name = "Test iterator and wraparound behavior with {1} random values with seed = {0} and fixed array size = {2}")
@CsvSource({ "69, 200, 20", "21, 300, 200" })
public void testWrapAround(int seed, int numVals, int queueSize) {
Random r = new Random(seed);
IFixedSizeQueue<Object> me = newFixedSizeQueue(queueSize);
Queue<Object> reference = new java.util.ArrayDeque<>();
assertEquals(queueSize, me.capacity(), "capacity does not match expected value");
for (int i = 0; i < queueSize; i++) {
int num = r.nextInt();
assertFalse(me.isFull(), "queue should not be full");
assertTrue(me.enqueue(num), "enqueue should be successful");
reference.add(num);
for (int i = 0; i < numVals; i++) {
me.enqueue(me.dequeue());
reference.add(reference.remove());
assertEquals(reference.peek(), me.peek(), "return values of peek()s are not equal");
assertEquals(reference.size(), me.size(), "size()s are not equal");
assertEquals(queueSize, me.capacity(), "capacity of a fixed size queue should not change");
assertIterableEquals(reference, me, "Reference and implemented queues are not equal");
}
}
for (int i = 0; i < numVals; i++) {
me.enqueue(me.dequeue());
reference.add(reference.remove());
assertEquals(reference.peek(), me.peek(), "return values of peek()s are not equal");
assertEquals(reference.size(), me.size(), "size()s are not equal");
assertEquals(queueSize, me.capacity(), "capacity of a fixed size queue should not change");
assertIterableEquals(reference, me, "Reference and implemented queues are not equal");
@Order(toStringTestLevel)
@DisplayName("toString() matches java.util.ArrayDeque")
@DependsOn({"fields", "constructors", "toString", "enqueue"})
@ParameterizedTest(name = "Test toString() on [{arguments}]")
@ValueSource(strings = {
"0, 1, 2, 3", "5, 4, 3, 2, 1", "8, 3, 5, 7, 4, 3, 12, 12, 1"
})
public void testToString(String inputs) {
java.util.ArrayDeque<String> reference = new java.util.ArrayDeque<String>();
edu.caltech.cs2.interfaces.IFixedSizeQueue<Object> me = new CircularArrayFixedSizeQueue<>(10);
for (String value : inputs.trim().split(", ")) {
assertEquals(reference.toString(), me.toString(), "toString outputs should be the same");
reference.addLast(value);
me.enqueue(value);
}
}
}
}
package edu.caltech.cs2.helpers;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface DependsOn {
String[] value();
}
package edu.caltech.cs2.helpers;
public class NewNode {
public static int NUM_CALLS = 0;
}
package edu.caltech.cs2.helpers;
public class NewObjectArray {
public static int NUM_CALLS = 0;
}
package edu.caltech.cs2.helpers;
public class RuntimeCounter {
public static int NUM_CALLS = 0;
public static void inc() {
NUM_CALLS++;
}
}
......@@ -9,8 +9,8 @@ import java.util.function.Consumer;
import java.util.function.Function;
public class RuntimeInstrumentation {
private static final int SKIP = 5;
private static final int ITERATIONS = 100;
private static final int SKIP = 3;
private static final int ITERATIONS = 1;
public enum ComplexityType {
CONSTANT(0, "constant"),
......@@ -37,10 +37,11 @@ public class RuntimeInstrumentation {
}
public static <DS> long timeFunction(DS ds, Consumer<DS> function) {
long startTime = System.nanoTime();
RuntimeCounter.NUM_CALLS = 0;
//long startTime = System.nanoTime();
function.accept(ds);
long endTime = System.nanoTime();
return endTime - startTime;
//long endTime = System.nanoTime();
return RuntimeCounter.NUM_CALLS;//endTime - startTime;
}
public static <DS> ComplexityType getEmpiricalComplexity(Function<Integer, DS> provideDSOfSize, Consumer<DS> functionToTest, int numberOfDoubles) {
......@@ -50,9 +51,6 @@ public class RuntimeInstrumentation {
long totalTime = 0;
for (int i = 0; i < ITERATIONS; i++) {
DS ds = provideDSOfSize.apply(currentSize);
// Bring ds into cache! Make sure we're only clocking
// the function, and not JVM operations on the heap / cache
timeFunction(ds, functionToTest);
totalTime += timeFunction(ds, functionToTest);
}
times.add(Math.round((double)totalTime / ITERATIONS));
......@@ -62,6 +60,10 @@ public class RuntimeInstrumentation {
times.remove(0);
}
if (times.stream().allMatch(((x) -> x == 0))) {
fail("Infrastructure is broken or method is unimplemented! See course staff!");
}
if (isApproximately(ComplexityType.CONSTANT, times)) {
return ComplexityType.CONSTANT;
}
......@@ -152,13 +154,13 @@ public class RuntimeInstrumentation {
// Tune depending on strictness - 0.95 accounts for variations
// *Should* actually be like 0.99, but sometimes weird heap operations
// happen and make certain runs take longer
return rSq >= 0.92;
return rSq >= 0.98;
}
public static <DS> void assertAtMost(String whatIsBeingTested, ComplexityType expected, Function<Integer, DS> provideDSOfSize, Consumer<DS> functionToTest, int numberOfDoubles) {
ComplexityType calculated = getEmpiricalComplexity(provideDSOfSize, functionToTest, numberOfDoubles);
if (calculated.isSlowerThan(expected)) {
fail(whatIsBeingTested + " is expected to be " + expected + " time or better. The actual calculated time is " + calculated + ".\nThis test is non-deterministic which means it might not always be correct. If you run it multiple times and it usually passes, that's probably fine.");
fail(whatIsBeingTested + " is expected to be " + expected + " time or better. The actual calculated time is " + calculated + ".");//"\nThis test is non-deterministic which means it might not always be correct. If you run it multiple times and it usually passes, that's probably fine.");
}
}
}
package edu.caltech.cs2.helpers;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface TestDescription {
String value();
}
package edu.caltech.cs2.helpers;
import org.junit.jupiter.api.extension.ExtensionContext;
import org.junit.jupiter.api.extension.LifecycleMethodExecutionExceptionHandler;
import org.junit.jupiter.api.extension.TestExecutionExceptionHandler;
import java.util.Arrays;
public class TestExtension implements TestExecutionExceptionHandler {
public static final String TEXT_RED = "\u001B[31m";
public static final String TEXT_BLACK = "\u001B[30m";
public static final String TEXT_GREEN = "\u001B[32m";
public static final String TEXT_BLUE = "\u001B[34m";
public static final String TEXT_RESET = "\u001B[0m";
public static final String TEXT_PURPLE = "\u001B[35m";
public static final String TEXT_CYAN = "\u001B[36m";
public static final String TEXT_YELLOW = "\u001B[33m";
public static final String TEXT_WHITE = "\u001B[37m";
@Override
public void handleTestExecutionException(ExtensionContext context, Throwable throwable)
throws Throwable {
DependsOn d = context.getTestMethod().get().getAnnotation(DependsOn.class);
System.out.print(TEXT_YELLOW);
System.out.println(context.getDisplayName());
System.out.println("=".repeat(context.getDisplayName().length()));
TestDescription t2 = context.getTestMethod().get().getAnnotation(TestDescription.class);
if (t2 != null) {
System.out.println(t2.value());
}
System.out.print(TEXT_PURPLE);
if (d != null) {
System.out.println("Hint: This test depends on the following being implemented correctly:\n - " + String.join("\n - ", d.value()));
}
TestHint t = context.getTestMethod().get().getAnnotation(TestHint.class);
if (t != null) {
System.out.println("Hint: " + t.value());
}
System.out.print(TEXT_RESET);
throw throwable;
}
}
\ No newline at end of file
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment