Skip to content
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package org.cryptimeleon.math.serialization.standalone;

public class MathStandaloneReprTest extends StandaloneReprTest {
public MathStandaloneReprTest() {
super("org.cryptimeleon.math");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,18 @@
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestInstance;
import org.junit.jupiter.api.extension.ExtensionContext;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.ArgumentsProvider;
import org.junit.jupiter.params.provider.ArgumentsSource;
import org.junit.jupiter.params.provider.MethodSource;
import org.reflections.Reflections;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Modifier;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Objects;
import java.util.Set;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

Expand All @@ -27,13 +26,23 @@
* Tests that {@link StandaloneRepresentable} classes fulfill their contract.<br>
* This class mostly just gathers the classes that need testing and delegates to {@link StandaloneReprSubTest},
* whose task is essentially to instantiate classes so that they can be tested.
*
* To use this test for your own package, extend this class and and set up a no-argument constructor like this: <br>
* {@code public YourOwnStandaloneReprTest() { super("com.mypackageprefix"); }}
*/
public class StandaloneReprTest {
@TestInstance(TestInstance.Lifecycle.PER_CLASS) //required for the @MethodSource non-static method to work.
public abstract class StandaloneReprTest {
protected static HashSet<Class<? extends StandaloneRepresentable>> testedClasses = new HashSet<>();
private static final Reflections reflection = new Reflections("org.cryptimeleon.math");
private final String packageName;
private final Reflections reflection;

public StandaloneReprTest(String packageName) {
this.packageName = packageName;
this.reflection = new Reflections(packageName);
}

@ParameterizedTest(name = "''{0}''")
@ArgumentsSource(SubtestArgumentProvider.class)
@MethodSource("provideStandaloneReprSubTests")
public void testStandaloneRepresentables(StandaloneReprSubTest subtest) {
testedClasses.addAll(subtest.runTests());
}
Expand All @@ -43,25 +52,22 @@ public void testStandaloneRepresentablesWithParameterlessConstructors() {
testedClasses.addAll(new TestForParameterlessConstructorClasses().runTests());
}

public static class SubtestArgumentProvider implements ArgumentsProvider {
@Override
public Stream<? extends Arguments> provideArguments(ExtensionContext context) {
return reflection.getSubTypesOf(StandaloneReprSubTest.class).stream()
.filter(clazz -> !clazz.equals(TestForParameterlessConstructorClasses.class))
.map(clazz -> {
try {
return clazz.getDeclaredConstructor().newInstance();
} catch (InstantiationException | IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
e.printStackTrace();
return null;
}
})
.filter(Objects::nonNull)
.map(Arguments::of);
}
protected Stream<? extends Arguments> provideStandaloneReprSubTests() {
return reflection.getSubTypesOf(StandaloneReprSubTest.class).stream()
.filter(clazz -> !clazz.equals(TestForParameterlessConstructorClasses.class))
.map(clazz -> {
try {
return clazz.getDeclaredConstructor().newInstance();
} catch (InstantiationException | IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
e.printStackTrace();
return null;
}
})
.filter(Objects::nonNull)
.map(Arguments::of);
}

private static class TestForParameterlessConstructorClasses extends StandaloneReprSubTest {
protected class TestForParameterlessConstructorClasses extends StandaloneReprSubTest {
public void testClassesWithTrivialConstructor() {
reflection.getSubTypesOf(StandaloneRepresentable.class).stream()
.filter(clazz -> Arrays.stream(clazz.getConstructors()).anyMatch(constr -> constr.getParameterCount() == 0))
Expand All @@ -77,12 +83,12 @@ public void testClassesWithTrivialConstructor() {

@AfterAll
@DisplayName("Checking that every StandaloneRepresentable has been tested.")
static void checkForUntestedClasses() {
public void checkForUntestedClasses() {
Set<Class<? extends StandaloneRepresentable>> classesToTest = reflection.getSubTypesOf(StandaloneRepresentable.class);
classesToTest.removeAll(testedClasses);

//Remove interfaces and such
classesToTest.removeIf(c -> c.isInterface() || Modifier.isAbstract(c.getModifiers()) || !c.getPackage().toString().startsWith("package org.cryptimeleon.math"));
classesToTest.removeIf(c -> c.isInterface() || Modifier.isAbstract(c.getModifiers()) || !c.getPackage().toString().startsWith("package "+packageName));

for (Class<? extends StandaloneRepresentable> notTestedClass : classesToTest) {
System.err.println(notTestedClass.getName() + " implements StandaloneRepresentable was not tested by StandaloneTest. You need to define a StandaloneSubTest for it.");
Expand Down