/**
* Copyright (c) 2016, All Contributors (see CONTRIBUTORS file)
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package com.eventsourcing.layout;
import lombok.Getter;
import lombok.Setter;
import lombok.SneakyThrows;
import lombok.Value;
import org.testng.annotations.Test;
import java.lang.reflect.Parameter;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Optional;
import static org.testng.Assert.*;
public class LayoutTest {
public static class NoConstructor {
private NoConstructor() {}
}
@Test(expectedExceptions = IllegalArgumentException.class) @SneakyThrows
public void noConstructor() {
Layout.forClass(NoConstructor.class);
}
public static class ConflictingConstructors {
public ConflictingConstructors(String a, String b) {
}
public ConflictingConstructors(Integer a, String b) {
}
}
@Test(expectedExceptions = IllegalArgumentException.class) @SneakyThrows
public void conflictingConstructors() {
Layout.forClass(ConflictingConstructors.class);
}
public static class ExplicitConstructor {
@Getter private Integer a;
@Getter private String b;
public ExplicitConstructor(String a, String b) {
}
@LayoutConstructor
public ExplicitConstructor(Integer a, String b) {
}
}
@Test @SneakyThrows
public void explicitConstructor() {
Layout<ExplicitConstructor> layout = Layout.forClass(ExplicitConstructor.class);
Parameter[] parameters = layout.getConstructor().getParameters();
assertEquals(parameters[0].getName(), "a");
assertEquals(parameters[0].getType(), Integer.class);
assertEquals(parameters[1].getName(), "b");
assertEquals(parameters[1].getType(), String.class);
}
public static class WidestConstructor {
@Getter private final Integer a;
@Getter private final String b;
@Getter private final Integer c;
public WidestConstructor(Integer a, String b) {
this(a, b, null);
}
public WidestConstructor(Integer a, String b, Integer c) {
this.a = a;
this.b = b;
this.c = c;
}
}
@Test @SneakyThrows
public void widestConstructor() {
Layout<WidestConstructor> layout = Layout.forClass(WidestConstructor.class);
assertEquals(layout.getConstructor().getParameters().length, 3);
}
public static class MissingPropertyGetter {
public MissingPropertyGetter(String a) {
}
}
@Test(expectedExceptions = IllegalArgumentException.class) @SneakyThrows
public void missingPropertyGetter() {
Layout.forClass(MissingPropertyGetter.class);
}
public static class MismatchedPropertyType {
@Getter private Integer a;
public MismatchedPropertyType(String a) {
}
}
@Test(expectedExceptions = IllegalArgumentException.class) @SneakyThrows
public void mismatchedPropertyType() {
Layout.forClass(MismatchedPropertyType.class);
}
public static class RenamedProperty {
@Getter private String abc;
public RenamedProperty(@PropertyName("abc") String a) {
}
}
@Test @SneakyThrows
public void renamedProperty() {
Layout<RenamedProperty> layout = Layout.forClass(RenamedProperty.class);
List<Property<RenamedProperty>> properties = layout.getProperties();
assertEquals(properties.size(), 1);
assertEquals(properties.get(0).getName(), "abc");
}
public static class Properties {
@Getter private final String a;
@Getter private final int b;
@Getter private final boolean c;
public Properties(boolean c, String a, int b) {
this.a = a;
this.b = b;
this.c = c;
}
}
@Test @SneakyThrows
public void properties() {
Layout<Properties> layout = Layout.forClass(Properties.class);
List<Property<Properties>> properties = layout.getProperties();
assertEquals(properties.size(), 3);
// Lexicographically sorted:
assertEquals(properties.get(0).getName(), "a");
assertEquals(properties.get(1).getName(), "b");
assertEquals(properties.get(2).getName(), "c");
// Constructor properties retain the order:
List<Property<Properties>> constructorProperties = layout.getConstructorProperties();
assertEquals(constructorProperties.size(), 3);
assertEquals(constructorProperties.get(0).getName(), "c");
assertEquals(constructorProperties.get(1).getName(), "a");
assertEquals(constructorProperties.get(2).getName(), "b");
}
@Test @SneakyThrows
public void getters() {
Layout<Properties> layout = Layout.forClass(Properties.class);
List<Property<Properties>> properties = layout.getProperties();
Properties test = new Properties(true, "hello", 1);
assertEquals(properties.get(0).get(test), "hello");
assertEquals((int)properties.get(1).get(test), 1);
assertEquals((boolean)properties.get(2).get(test), true);
}
@LayoutName("DigestTest")
@Value
private static class DigestTest1 {
private String x;
}
@Value
private static class DigestTest1Name {
private String x;
}
@LayoutName("DigestTest")
@Value
private static class DigestTest1SameName {
private String x;
}
@LayoutName("DigestTest")
@Value
private static class DigestTest1PropName {
private String y;
}
@LayoutName("DigestTest")
@Value
private static class DigestTest1Type {
private int x;
}
@Test
@SneakyThrows
public void hashDifferentClassName() {
Layout<DigestTest1> layout1 = Layout.forClass(DigestTest1.class);
Layout<DigestTest1Name> layout1Name = Layout.forClass(DigestTest1Name.class);
Layout<DigestTest1SameName> layout1SameName = Layout.forClass(DigestTest1SameName.class);
assertNotEquals(layout1, layout1Name);
assertFalse(Arrays.equals(layout1.getHash(), layout1Name.getHash()));
assertEquals(layout1, layout1SameName);
assertTrue(Arrays.equals(layout1.getHash(), layout1SameName.getHash()));
}
@Test
@SneakyThrows
public void hashSameContent() {
Layout<DigestTest1> layout1 = Layout.forClass(DigestTest1.class);
Layout<DigestTest1SameName> layout1SameName = Layout.forClass(DigestTest1SameName.class);
assertEquals(layout1, layout1SameName);
assertEquals(layout1.getHash(), layout1SameName.getHash());
}
@Test
@SneakyThrows
public void hashDifferentPropName() {
Layout<DigestTest1> layout1 = Layout.forClass(DigestTest1.class);
Layout<DigestTest1PropName> layout1Name = Layout.forClass(DigestTest1PropName.class);
assertNotEquals(layout1, layout1Name);
assertNotEquals(layout1.getHash(), layout1Name.getHash());
}
@Test
@SneakyThrows
public void hashDifferentType() {
Layout<DigestTest1> layout1 = Layout.forClass(DigestTest1.class);
Layout<DigestTest1Type> layout1Name = Layout.forClass(DigestTest1Type.class);
assertNotEquals(layout1, layout1Name);
assertNotEquals(layout1.getHash(), layout1Name.getHash());
}
@LayoutName("boxing")
@Value
private static class DigestTest1Unboxed {
private short a;
private int b;
private long c;
private float d;
private double e;
private boolean f;
private byte g;
}
@LayoutName("boxing")
@Value
private static class DigestTest1Boxed {
private Short a;
private Integer b;
private Long c;
private Float d;
private Double e;
private Boolean f;
private Byte g;
}
@Test
@SneakyThrows
public void hashBoxed() {
Layout<DigestTest1Unboxed> layout1 = Layout.forClass(DigestTest1Unboxed.class);
Layout<DigestTest1Boxed> layout1Name = Layout.forClass(DigestTest1Boxed.class);
assertEquals(layout1, layout1Name);
assertEquals(layout1.getHash(), layout1Name.getHash());
}
@LayoutName("ListParametrizedTest")
@Value
private static class ListParametrizedTest1 {
private List<Integer> x;
}
@LayoutName("ListParametrizedTest")
@Value
private static class ListParametrizedTest2 {
private List<String> x;
}
@Test
@SneakyThrows
public void respectsParametrizedList() {
Layout<ListParametrizedTest1> layout1 = Layout.forClass(ListParametrizedTest1.class);
Layout<ListParametrizedTest2> layout2 = Layout.forClass(ListParametrizedTest2.class);
assertNotEquals(layout1, layout2, "Should be different");
assertFalse(Arrays.equals(layout1.getHash(), layout2.getHash()));
}
@LayoutName("OptionalParametrizedTest")
@Value
private static class OptionalParametrizedTest1 {
private Optional<Integer> y;
}
@LayoutName("OptionalParametrizedTest")
@Value
private static class OptionalParametrizedTest2 {
private Optional<String> y;
}
@Test
@SneakyThrows
public void respectsParametrizedOptional() {
Layout<OptionalParametrizedTest1> layout1 = Layout.forClass(OptionalParametrizedTest1.class);
Layout<OptionalParametrizedTest2> layout2 = Layout.forClass(OptionalParametrizedTest2.class);
assertNotEquals(layout1, layout2, "Should be different");
assertFalse(Arrays.equals(layout1.getHash(), layout2.getHash()));
}
@Test
@SneakyThrows
public void layoutLayout() {
Layout<Layout> layout = Layout.forClass(Layout.class);
assertEquals(layout.getName(), "rfc.eventsourcing.com/spec:7/LDL/#Layout");
assertEquals(layout.getProperties().size(), 2);
assertTrue(layout.getProperties().stream().anyMatch(p -> p.getName().contentEquals("name")));
assertTrue(layout.getProperties().stream().anyMatch(p -> p.getName().contentEquals("properties")));
}
@Value
public static class Initializer {
private final String a;
private boolean b;
}
@Test
@SneakyThrows
public void defaultConstructor() {
Layout<Initializer> layout = Layout.forClass(Initializer.class);
Initializer instance = layout.instantiate();
assertEquals(instance.getA(), "");
assertFalse(instance.isB());
}
@Test
@SneakyThrows
public void partialConstructor() {
Layout<Initializer> layout = Layout.forClass(Initializer.class);
HashMap<Property<Initializer>, Object> properties = new HashMap<>();
properties.put(layout.getProperty("a"), "hello");
Initializer instance = layout.instantiate(properties);
assertEquals(instance.getA(), "hello");
assertFalse(instance.isB());
}
@Test
@SneakyThrows
public void nullValueInConstructorArgs() {
Layout<Initializer> layout = Layout.forClass(Initializer.class);
HashMap<Property<Initializer>, Object> properties = new HashMap<>();
properties.put(layout.getProperty("a"), null);
Initializer instance = layout.instantiate(properties);
assertEquals(instance.getA(), "");
}
public static class Base0Class {
@Getter @Setter
private String a;
@Getter @Setter
private boolean b;
public Base0Class() {
}
public Base0Class(String a, boolean b) {
this.a = a;
this.b = b;
}
}
public static class BaseClass extends Base0Class {
@Getter @Setter
private String a;
@Getter @Setter
private boolean b;
public BaseClass() {
}
public BaseClass(String a, boolean b) {
this.a = a;
this.b = b;
}
}
@Value
public static class Inheritance extends BaseClass {
private String c;
}
@Test
@SneakyThrows
public void inheritance() {
Layout<Inheritance> layout = Layout.forClass(Inheritance.class);
assertEquals(layout.getProperties().size(), 3);
Property<Inheritance> a = layout.getProperty("a");
Property<Inheritance> b = layout.getProperty("b");
assertNotNull(a);
assertNotNull(b);
HashMap<Property<Inheritance>, Object> properties = new HashMap<>();
properties.put(layout.getProperty("a"), "hello");
properties.put(layout.getProperty("b"), true);
properties.put(layout.getProperty("c"), "C");
Inheritance instance = layout.instantiate(properties);
assertEquals(instance.getA(), "hello");
assertTrue(instance.isB());
assertEquals(instance.getC(), "C");
}
}