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
1 change: 1 addition & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ dependencies {
)
testImplementation(
'org.junit.jupiter:junit-jupiter-api:5.1.0',
'org.junit.jupiter:junit-jupiter-params:5.1.0'
)
testRuntimeOnly(
'org.junit.jupiter:junit-jupiter-engine:5.1.0',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ public class ProductGroup implements Group {
@Represented
protected Group[] groups;

public ProductGroup(Group[] groups) {
public ProductGroup(Group... groups) {
this.groups = groups;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -266,7 +266,7 @@ protected void init(int groupBitSize) {
BarretoNaehrigGroup1ElementImpl P1;
BarretoNaehrigGroup2ElementImpl P2;

BigInteger u = BigInteger.ONE.shiftLeft(groupBitSize / 4 + 1);
u = BigInteger.ONE.shiftLeft(groupBitSize / 4 + 1);

/*
* assure that u=1 mod 2 and u=1 mod 3. u=1 mod 2 assures that p(u) = 3 mod 4 and hence -1 is QNR in F_p u=1 mod
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ public class ProductRing implements Ring {
@Represented
protected Ring[] rings;

public ProductRing(Ring[] rings) {
public ProductRing(Ring... rings) {
this.rings = rings;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,20 +1,14 @@
package org.cryptimeleon.math.serialization.standalone.params;
package org.cryptimeleon.math.serialization.annotations;

import org.cryptimeleon.math.serialization.Representation;
import org.cryptimeleon.math.serialization.StandaloneRepresentable;
import org.cryptimeleon.math.serialization.annotations.ReprUtil;
import org.cryptimeleon.math.serialization.standalone.StandaloneTestParams;

import java.util.*;

/**
* Verify that all serialization Annotations support (de-)serialization of null values
*/
public class NullTestParams {
public static StandaloneTestParams get() {
return new StandaloneTestParams(NullTestClass.class, new NullTestClass());
}

public static class NullTestClass implements StandaloneRepresentable {

private StandaloneRepresentable nullTestObject;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
package org.cryptimeleon.math.serialization.annotations;


import org.cryptimeleon.math.structures.rings.Ring;
import org.cryptimeleon.math.structures.rings.RingElement;
import org.cryptimeleon.math.serialization.Representation;
import org.cryptimeleon.math.serialization.StandaloneRepresentable;
import org.cryptimeleon.math.serialization.standalone.StandaloneTestParams;
import org.cryptimeleon.math.structures.rings.Ring;
import org.cryptimeleon.math.structures.rings.RingElement;
import org.cryptimeleon.math.structures.rings.zn.Zn;
import org.cryptimeleon.math.structures.rings.zn.Zp;
import org.junit.Test;
Expand All @@ -27,6 +26,10 @@ public static class Foo implements StandaloneRepresentable {
@Represented
Zp zp;

public Foo() {
this(new Zp(BigInteger.valueOf(17)));
}

public Foo(Zp zp) {
this.zp = zp;
}
Expand Down Expand Up @@ -60,10 +63,6 @@ public boolean equals(Object o) {
public int hashCode() {
return Objects.hash(zp);
}

public static StandaloneTestParams getStandaloneTestParams() {
return new StandaloneTestParams(new Foo(new Zp(BigInteger.valueOf(2))));
}
}

@Test
Expand Down
Original file line number Diff line number Diff line change
@@ -1,21 +1,14 @@
package org.cryptimeleon.math.serialization.standalone.params;
package org.cryptimeleon.math.serialization.annotations;

import org.cryptimeleon.math.serialization.Representation;
import org.cryptimeleon.math.serialization.StandaloneRepresentable;
import org.cryptimeleon.math.serialization.annotations.ReprUtil;
import org.cryptimeleon.math.serialization.annotations.Represented;
import org.cryptimeleon.math.serialization.standalone.StandaloneTestParams;

import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

public class RepresentedEnumParams {

public static StandaloneTestParams get() {
return new StandaloneTestParams(RepresentedEnum.class, new RepresentedEnum());
}

public enum RepresentableEnum {
ENUM_VALUE1, ENUM_VALUE2, ENUM_VALUE3
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
package org.cryptimeleon.math.serialization.standalone;

import org.cryptimeleon.math.serialization.Representation;
import org.cryptimeleon.math.serialization.StandaloneRepresentable;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.HashSet;
import java.util.Set;

import static org.junit.jupiter.api.Assertions.*;

/**
* Base class for testing {@link StandaloneRepresentable}s. <br>
*
* Implementing classes should write methods that instantiate a {@linkplain StandaloneRepresentable}
* and then call {@link #test(StandaloneRepresentable)} for it.
* All public (non-static) methods the implementing class declares are automatically executed at test time.
* When in doubt, check out some examples (e.g., {@link org.cryptimeleon.math.serialization.standalone.params.StructureStandaloneReprTest}).
*/
public abstract class StandaloneReprSubTest {
private HashSet<Class<? extends StandaloneRepresentable>> testedClasses;

protected final void test(StandaloneRepresentable object) {
Class<? extends StandaloneRepresentable> clazz = object.getClass();
testedClasses.add(clazz);

//Test for constructor with single Representation parameter
try {
Constructor<? extends StandaloneRepresentable> constructor = clazz.getConstructor(Representation.class);
assertNotNull(constructor, "Constructor is null");
} catch (NoSuchMethodException | SecurityException e) {
// no constructor given or constructor not visible
fail(clazz.getName() + " has no public constructor with a single Representation parameter");
}

// Test for override of equals
try {
Method equals = clazz.getMethod("equals", Object.class);
assertNotEquals(equals.getDeclaringClass(), Object.class);
} catch (NoSuchMethodException | SecurityException e) {
fail(clazz.getName() + " does not override equals(Object)");
}

// Test for override of hashCode
try {
Method hashCode = clazz.getMethod("hashCode");
assertNotEquals(hashCode.getDeclaringClass(), Object.class);
} catch (NoSuchMethodException | SecurityException e) {
fail(clazz.getName() + " does not override hashCode()");
}

//Test serialization/deserialization
try {
Constructor<? extends StandaloneRepresentable> constructor = clazz.getConstructor(Representation.class);
assertNotNull(constructor);
Representation repr = (Representation) clazz.getMethod("getRepresentation").invoke(object);
assertEquals(object, constructor.newInstance(repr));
} catch (IllegalAccessException | InvocationTargetException | InstantiationException | NoSuchMethodException e) {
e.printStackTrace();
fail("An exception occured while serializing/deserializing "+clazz.getName());
}
}

public final Set<Class<? extends StandaloneRepresentable>> runTests() {
//Clear list
testedClasses = new HashSet<>();

//Call every non-private method on this object
Method[] declaredMethods = getClass().getDeclaredMethods();
for (Method method : declaredMethods) {
try {
if (method.getParameterCount() == 0 && !Modifier.isStatic(method.getModifiers()) && !Modifier.isPrivate(method.getModifiers())) {
method.invoke(this);
}
} catch (IllegalAccessException e) {
fail(e);
} catch (InvocationTargetException e) {
e.printStackTrace();
fail("Exception thrown during execution of "+getClass().getName()+"::"+method.getName(), e);
}
}

return testedClasses;
}

@Override
public String toString() {
return this.getClass().getSimpleName();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
package org.cryptimeleon.math.serialization.standalone;

import org.cryptimeleon.math.serialization.StandaloneRepresentable;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
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.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.stream.Collectors;
import java.util.stream.Stream;

import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.api.Assertions.fail;

/**
* 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.
*/
public class StandaloneReprTest {
protected static HashSet<Class<? extends StandaloneRepresentable>> testedClasses = new HashSet<>();
private static final Reflections reflection = new Reflections("org.cryptimeleon.math");

@ParameterizedTest(name = "''{0}''")
@ArgumentsSource(SubtestArgumentProvider.class)
public void testStandaloneRepresentables(StandaloneReprSubTest subtest) {
testedClasses.addAll(subtest.runTests());
}

@Test
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);
}
}

private static class TestForParameterlessConstructorClasses extends StandaloneReprSubTest {
public void testClassesWithTrivialConstructor() {
reflection.getSubTypesOf(StandaloneRepresentable.class).stream()
.filter(clazz -> Arrays.stream(clazz.getConstructors()).anyMatch(constr -> constr.getParameterCount() == 0))
.forEach(clazz -> {
try {
test(clazz.getConstructor().newInstance());
} catch (InstantiationException | IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
fail(e);
}
});
}
}

@AfterAll
@DisplayName("Checking that every StandaloneRepresentable has been tested.")
static 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"));

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.");
}

assertTrue(classesToTest.isEmpty(), "Missing (or failed) StandaloneRepresentation tests for "+classesToTest.stream().map(Class::getSimpleName).sorted().collect(Collectors.joining(", ")));
}
}
Loading