Verified Commit cbc10023 authored by Daniel Mangold's avatar Daniel Mangold
Browse files

Made tree generation completely random

parents 72801db9 670286f4
......@@ -3,7 +3,7 @@ import org.jagrkt.submitter.submit
plugins {
java
application
id("org.jagrkt.submitter").version("0.2.0")
id("org.jagrkt.submitter").version("0.3.1")
}
submit {
......@@ -11,6 +11,8 @@ submit {
studentId = null // TU-ID z.B. "ab12cdef"
firstName = null
lastName = null
// Optionally require tests for prepareSubmission task. Default is true
requireTests = true
}
// !! Achtung !!
......
......@@ -51,6 +51,7 @@ public class MyParenthesesTreeIteratorTest {
public void testNext(String treeString) throws ReflectiveOperationException {
requireTest(MyTreeTest.class.getDeclaredMethod("testIterator"));
treeString = treeString.substring(0, treeString.indexOf('\n') + 1);
Iterator<Character> iterator = MyTreeTest.getIterator(treeString);
StringBuilder builder = new StringBuilder();
......@@ -74,6 +75,7 @@ public class MyParenthesesTreeIteratorTest {
requireTest(MyTreeTest.class.getDeclaredMethod("testIterator"));
requireTest(MyParenthesesTreeIteratorTest.class.getDeclaredMethod("testNext", String.class), "()\n");
treeString = treeString.substring(0, treeString.indexOf('\n') + 1);
Iterator<Character> iterator = MyTreeTest.getIterator(treeString);
for (int i = 0; i < treeString.length() - 1; i++, iterator.next())
......
package h05;
import h05.Utils.TestType;
import h05.provider.RandomTreeProvider;
import h05.provider.TreeProvider;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
......@@ -19,9 +17,10 @@ import java.util.Iterator;
import java.util.Stack;
import static h05.Assertions.*;
import static h05.Config.BUILD_VARIANT;
import static h05.Config.*;
import static h05.Utils.*;
import static h05.Utils.TestType.Type.CLASS;
import static h05.provider.RandomTreeProvider.treeToString;
import static java.lang.reflect.Modifier.*;
@SuppressWarnings("ConstantConditions")
......@@ -32,8 +31,9 @@ public class MyTreeTest {
public static Constructor<?> constructor;
public static Field root, nextNodeID;
public static Method buildRecursively, buildIteratively, iterator, isIsomorphic;
private static final String CLASS_NAME = "h05.MyTree";
private static boolean printedWarning = false;
@BeforeAll
public static void checkClass() {
......@@ -128,73 +128,90 @@ public class MyTreeTest {
}
@ParameterizedTest
@ArgumentsSource(TreeProvider.class)
public void testConstructor(String treeString, Boolean shouldThrowException) throws ReflectiveOperationException, IOException {
boolean buildRecursively = BUILD_VARIANT == null ? RANDOM.nextBoolean() : BUILD_VARIANT;
@ArgumentsSource(RandomTreeProvider.class)
void testConstructorWithValid(String treeString) throws ReflectiveOperationException, IOException {
boolean recursive = BUILD_VARIANT == null ? RANDOM.nextBoolean() : BUILD_VARIANT;
StringReader reader = new StringReader(treeString);
int endOfTree = treeString.indexOf('\n');
if (shouldThrowException) {
assertThrows(BadStringOperationException.class, () -> {
try {
constructor.newInstance(reader, buildRecursively);
} catch (ReflectiveOperationException e) {
throw e.getCause();
}
}, "Constructor did not throw BadStringOperationException, called with second parameter = " + buildRecursively);
} else {
Object instance = constructor.newInstance(reader, buildRecursively);
int i = 0;
while (i < treeString.length() && (treeString.charAt(i) == '(' || treeString.charAt(i) == ')'))
i++;
assertEquals(treeString.substring(0, i), TreeProvider.treeToString(root.get(instance), true),
"Trees do not match, called constructor with second parameter = " + buildRecursively);
for (i = treeString.length() - i - 1; i > 0; i--)
assertEquals(treeString.charAt(treeString.length() - i), (char) reader.read(),
"Reader did not return correct character");
assertEquals(-1, reader.read(), "Reader should not have any characters left");
}
assertEquals(treeString.substring(0, endOfTree), treeToString(root.get(getNewInstance(reader, recursive)), true),
"Trees do not match, called constructor with second parameter = " + recursive);
assertRestOfReaderMatches(treeString.substring(endOfTree + 1), reader);
}
@ParameterizedTest
@ArgumentsSource(RandomTreeProvider.class)
void testConstructorWithInvalid(String treeString) {
boolean recursive = BUILD_VARIANT == null ? RANDOM.nextBoolean() : BUILD_VARIANT;
assertThrows(BadStringOperationException.class, () -> {
try {
String invalidTreeString = treeString.replaceFirst(
"\n", RANDOM.nextBoolean() ? "" : RANDOM.nextBoolean() ? "(\n" : ")\n");
getNewInstance(invalidTreeString, recursive);
} catch (ReflectiveOperationException e) {
throw e.getCause();
}
}, "Constructor did not throw BadStringOperationException, called with second parameter = " + recursive);
}
private void assertRestOfReaderMatches(String rest, StringReader reader) throws IOException {
for (int i = 0; i < rest.length(); i++)
assertEquals(rest.charAt(i), reader.read(), "Reader did not return correct character");
assertEquals(-1, reader.read(), "Reader should not have any characters left");
}
@Test
public void testIterator() throws ReflectiveOperationException {
requireTest(MyParenthesesTreeIteratorTest.class);
Object instance = constructor.newInstance(new StringReader("\n"), BUILD_VARIANT == null ? RANDOM.nextBoolean() : BUILD_VARIANT);
assertEquals(MyParenthesesTreeIteratorTest.myParenthesesTreeIteratorClass, iterator.invoke(instance).getClass(),
assertEquals(MyParenthesesTreeIteratorTest.myParenthesesTreeIteratorClass, iterator.invoke(getNewInstance("\n")).getClass(),
"Returned object does not have type MyParenthesesTreeIterator");
}
@SuppressWarnings("unchecked")
public static Iterator<Character> getIterator(String treeString) throws ReflectiveOperationException {
return (Iterator<Character>) iterator.invoke(constructor.newInstance(new StringReader(treeString),
BUILD_VARIANT == null ? RANDOM.nextBoolean() : BUILD_VARIANT));
return (Iterator<Character>) iterator.invoke(getNewInstance(treeString));
}
@ParameterizedTest
@ArgumentsSource(RandomTreeProvider.class)
public void testIsIsomorphic(String treeString) throws ReflectiveOperationException {
Object instance1 = constructor.newInstance(new StringReader(treeString),
BUILD_VARIANT == null ? RANDOM.nextBoolean() : BUILD_VARIANT),
instance2 = constructor.newInstance(new StringReader(treeString),
BUILD_VARIANT == null ? RANDOM.nextBoolean() : BUILD_VARIANT);
Object instance1 = getNewInstance(treeString),
instance2 = getNewInstance(treeString);
assertTrue((Boolean) isIsomorphic.invoke(instance1, instance2), "Trees are isomorphic");
assertTrue((Boolean) isIsomorphic.invoke(instance2, instance1), "Trees are isomorphic");
assertTrue((Boolean) isIsomorphic.invoke(instance1, instance1), "Trees are isomorphic");
assertTrue((Boolean) isIsomorphic.invoke(instance2, instance2), "Trees are isomorphic");
String nonIsomorphicTreeString = "(((((())))))\n";
Object nonIsomorphicInstance = constructor.newInstance(new StringReader(nonIsomorphicTreeString),
BUILD_VARIANT == null ? RANDOM.nextBoolean() : BUILD_VARIANT);
String nonIsomorphicTreeString = "(".repeat(MAX_TREE_DEPTH + 1) + ")".repeat(MAX_TREE_DEPTH + 1) + "\n";
Object nonIsomorphicInstance = getNewInstance(nonIsomorphicTreeString);
assertFalse((Boolean) isIsomorphic.invoke(instance1, nonIsomorphicInstance), "Trees are not isomorphic");
assertFalse((Boolean) isIsomorphic.invoke(nonIsomorphicInstance, instance1), "Trees are not isomorphic");
assertFalse((Boolean) isIsomorphic.invoke(instance2, nonIsomorphicInstance), "Trees are not isomorphic");
assertFalse((Boolean) isIsomorphic.invoke(nonIsomorphicInstance, instance2), "Trees are not isomorphic");
}
private static Object getNewInstance(String treeString) throws ReflectiveOperationException {
return getNewInstance(treeString, BUILD_VARIANT == null ? RANDOM.nextBoolean() : BUILD_VARIANT);
}
private static Object getNewInstance(String treeString, boolean recursive) throws ReflectiveOperationException {
return getNewInstance(new StringReader(treeString), recursive);
}
private static Object getNewInstance(Reader reader, boolean recursive) throws ReflectiveOperationException {
if (BUILD_VARIANT != null && !printedWarning) {
System.out.println("BUILD_VARIANT is " + BUILD_VARIANT + ". Will only test " +
(BUILD_VARIANT ? "buildRecursively" : "buildIteratively"));
printedWarning = true;
}
return constructor.newInstance(reader, recursive);
}
}
package h05.provider;
import h05.ListItemTest;
import h05.MyTreeNodeTest;
import h05.Utils;
import org.junit.jupiter.api.extension.ExtensionContext;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.ArgumentsProvider;
import java.util.StringJoiner;
import java.util.stream.Stream;
import static h05.Config.*;
......@@ -13,12 +16,18 @@ public class RandomTreeProvider implements ArgumentsProvider {
@Override
public Stream<? extends Arguments> provideArguments(ExtensionContext context) {
return Stream.generate(() -> Arguments.of(randomTreeString(MAX_TREE_DEPTH) + '\n'))
return Stream.generate(RandomTreeProvider::randomTreeArguments)
.limit(NUMBER_OF_TEST_RUNS.getOrDefault(
context.getRequiredTestMethod().getDeclaringClass().getName() + "#" + context.getDisplayName(),
5));
}
private static Arguments randomTreeArguments() {
String treeString = randomTreeString(MAX_TREE_DEPTH);
return Arguments.of(treeString + '\n' + (char) ('A' + Utils.RANDOM.nextInt(26)));
}
private static String randomTreeString(int maxTreeDepth) {
double x = Utils.RANDOM.nextDouble();
......@@ -29,4 +38,13 @@ public class RandomTreeProvider implements ArgumentsProvider {
return randomTreeString(maxTreeDepth - 1) + randomTreeString(maxTreeDepth - 1);
}
public static String treeToString(Object root, boolean isRoot) throws ReflectiveOperationException {
StringJoiner joiner = new StringJoiner("");
for (Object p = MyTreeNodeTest.successors.get(root); p != null; p = ListItemTest.next.get(p))
joiner.add(treeToString(ListItemTest.key.get(p), false));
return isRoot ? joiner.toString() : "(" + joiner + ")";
}
}
package h05.provider;
import h05.ListItemTest;
import h05.MyTreeNodeTest;
import org.junit.jupiter.api.extension.ExtensionContext;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.ArgumentsProvider;
import java.util.StringJoiner;
import java.util.stream.Stream;
public class TreeProvider implements ArgumentsProvider {
@Override
public Stream<? extends Arguments> provideArguments(ExtensionContext context) {
return Stream.of(
Arguments.of("()()\n", false),
Arguments.of("(())(()())\n", false),
Arguments.of("\n", false),
Arguments.of("()\n()", false),
Arguments.of("()\nabc", false),
Arguments.of("", true),
Arguments.of("abc\n", true),
Arguments.of("(()))\n", true),
Arguments.of(")()()\n", true),
Arguments.of("(((()()))\n", true)
);
}
public static String treeToString(Object root, boolean isRoot) throws ReflectiveOperationException {
StringJoiner joiner = new StringJoiner("");
for (Object p = MyTreeNodeTest.successors.get(root); p != null; p = ListItemTest.next.get(p))
joiner.add(treeToString(ListItemTest.key.get(p), false));
return isRoot ? joiner.toString() : "(" + joiner + ")";
}
}
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