diff --git a/README.md b/README.md
index f4ff6e0..69b9488 100644
--- a/README.md
+++ b/README.md
@@ -2,3 +2,5 @@
* universal compare tool
* compares any to any and shows the diff
* no reflection
+* compiles to bytecode version jdk11
+* but also handles records, if you run jdk16+
diff --git a/pom.xml b/pom.xml
index d556ec2..08b47df 100644
--- a/pom.xml
+++ b/pom.xml
@@ -29,10 +29,7 @@
maven-compiler-plugin
3.11.0
- 20
- 20
- 20
- --enable-preview
+ 11
diff --git a/src/main/java/nl/sander/apples/AppleFactory.java b/src/main/java/nl/sander/apples/AppleFactory.java
index ef656a4..f4b8a7a 100644
--- a/src/main/java/nl/sander/apples/AppleFactory.java
+++ b/src/main/java/nl/sander/apples/AppleFactory.java
@@ -5,12 +5,11 @@ import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.tree.*;
import java.lang.reflect.Modifier;
-import java.util.LinkedList;
import java.util.UUID;
import static org.objectweb.asm.Opcodes.*;
- class AppleFactory extends ClassVisitor {
+class AppleFactory extends ClassVisitor {
public static final String SUPER = javaName(BaseApple.class.getName());
@@ -39,7 +38,7 @@ import static org.objectweb.asm.Opcodes.*;
this.classToMap = name;
classNode.name = "Apple" + UUID.randomUUID();
classNode.superName = SUPER;
- classNode.version = V20;
+ classNode.version = V1_8;
classNode.access = ACC_PUBLIC;
MethodNode constructor = new MethodNode(ACC_PUBLIC, INIT, ZERO_ARGS_VOID, null, null);
constructor.instructions.add(new VarInsnNode(ALOAD, 0));
@@ -50,30 +49,32 @@ import static org.objectweb.asm.Opcodes.*;
compareMethod = new MethodNode(ACC_PUBLIC,
"compare", "(Ljava/lang/Object;Ljava/lang/Object;)Lnl/sander/apples/Result;", null, null);
classNode.methods.add(compareMethod);
- add(new VarInsnNode(ALOAD,0));
+ add(new VarInsnNode(ALOAD, 0));
}
public MethodVisitor visitMethod(int access, String methodname,
String desc, String signature, String[] exceptions) {
if (!hasArgs(desc) && access == Modifier.PUBLIC && isRecord ||
(methodname.startsWith("get") || (methodname.startsWith("is")) && desc.equals("()Z"))) {
- int startIndex;
- if (isRecord) {
- startIndex = 0;
- } else {
- if (methodname.startsWith("is")) {
- startIndex = 2;
- } else {
- startIndex = 3;
- }
- }
-
- visitGetter(correctName(methodname, startIndex), getReturnType(desc));
+ visitGetter(methodname, asProperty(methodname, isRecord), getReturnType(desc));
}
return null;
}
- private void visitGetter(String getterMethodName, String returnType) {
+ private String asProperty(String getter, boolean isRecord) {
+ if (isRecord){
+ return getter;
+ } else {
+ if (getter.startsWith("get")){
+ return getter.substring(3,4).toLowerCase()+getter.substring(4);
+ } else {
+ return getter.substring(2,3).toLowerCase()+getter.substring(3);
+ }
+ }
+ }
+
+ private void visitGetter(String getterMethodName, String propertyName, String returnType) {
+ add(new LdcInsnNode(propertyName));
add(new VarInsnNode(ALOAD, 1));
add(new TypeInsnNode(CHECKCAST, javaName(classToMap)));
add(new MethodInsnNode(INVOKEVIRTUAL, classToMap, getterMethodName, "()" + returnType));
@@ -82,13 +83,20 @@ import static org.objectweb.asm.Opcodes.*;
add(new TypeInsnNode(CHECKCAST, javaName(classToMap)));
add(new MethodInsnNode(INVOKEVIRTUAL, classToMap, getterMethodName, "()" + returnType));
- add(new MethodInsnNode(INVOKESTATIC, "nl/sander/apples/Apples", "compare", "(Ljava/lang/Object;Ljava/lang/Object;)Lnl/sander/apples/Result;"));
+ add(new MethodInsnNode(INVOKESTATIC, "nl/sander/apples/Apples", "compare", "("
+ + getSignature(returnType)
+ + ")Lnl/sander/apples/Result;"));
add(new VarInsnNode(ASTORE, 3 + (localVarIndex++)));
}
- private String correctName(String getterMethodName, int startIndex) {
- String tmp = getterMethodName.substring(startIndex);
- return tmp.substring(0, 1).toLowerCase() + tmp.substring(1);
+ private String getSignature(String returnType) {
+ String type;
+ if (returnType.startsWith("L")) {
+ type = "Ljava/lang/Object;";
+ } else {
+ type = returnType;
+ }
+ return "Ljava/lang/String;"+type + type;
}
@Override
diff --git a/src/main/java/nl/sander/apples/Apples.java b/src/main/java/nl/sander/apples/Apples.java
index 279c847..05e08e7 100644
--- a/src/main/java/nl/sander/apples/Apples.java
+++ b/src/main/java/nl/sander/apples/Apples.java
@@ -3,21 +3,28 @@ package nl.sander.apples;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassWriter;
-import java.io.FileOutputStream;
-import java.util.Map;
+import java.util.*;
+import java.util.concurrent.atomic.LongAdder;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+@SuppressWarnings({"unchecked", "rawtypes"})
public class Apples {
private final static Map CHAR_ESCAPES = Map.of('\t', "\\t", '\b', "\\b", '\n', "\\n", '\r', "\\r", '\f', "\\f", '\\', "\\\\");
private static final ByteClassLoader generatedClassesLoader = new ByteClassLoader();
public static Result compare(Object left, Object right) {
+ return compare("", left, right);
+ }
+
+ public static Result compare(String property, Object left, Object right) {
if (left == null) {
- return Result.from(right == null, "null != " + asString(right));
+ return Result.from(property, right == null, "null != " + asString(right));
}
if (right == null) {
- return Result.unequal(asString(left) + " != null");
+ return Result.unequal(property, asString(left) + " != null");
}
if (left == right) {
@@ -25,24 +32,42 @@ public class Apples {
}
if (left.getClass() != right.getClass()) {
- return Result.unequal(asString(left) + " != " + asString(right));
+ return Result.unequal(property, asString(left) + " != " + asString(right));
}
if (left instanceof String) {
- return Result.from(left.equals(right), () -> asString(left) + " != " + asString(right));
+ return Result.from(property, left.equals(right), () -> asString(left) + " != " + asString(right));
+ }
+
+ if (left instanceof Number) {
+ return Result.from(property, left.equals(right), () -> left + " != " + right);
+ }
+
+ if (left instanceof Collection) {
+ return compareCollections(property, (Collection>) left, (Collection>) right);
+ }
+
+ if (left instanceof Map) {
+ return compareMaps(property, (Map, ?>) left, (Map, ?>) right);
+ }
+
+ if (left instanceof Comparable>) {
+ int comparison = ((Comparable) left).compareTo(right);
+ if (comparison == 0) {
+ return new Result(true, List.of());
+ } else {
+ return Result.from(property, false, left + " != " + right);
+ }
}
try {
ClassReader cr = new ClassReader(left.getClass().getName());
AppleFactory appleFactory = new AppleFactory();
cr.accept(appleFactory, ClassReader.SKIP_FRAMES);
- ClassWriter classWriter = new ClassWriter(ClassWriter.COMPUTE_FRAMES );
+ ClassWriter classWriter = new ClassWriter(ClassWriter.COMPUTE_FRAMES);
appleFactory.classNode.accept(classWriter);
byte[] byteArray = classWriter.toByteArray();
- try (FileOutputStream f = new FileOutputStream("B.class")) {
- f.write(byteArray);
- }
generatedClassesLoader.addClass(appleFactory.classNode.name, byteArray);
BaseApple apple = (BaseApple) generatedClassesLoader.loadClass(appleFactory.classNode.name).getConstructor().newInstance();
return apple.compare(left, right);
@@ -51,79 +76,210 @@ public class Apples {
}
}
- public static Result compare(long left, long right) {
- return Result.from(left == right, left + " != " + right);
+ private static Result compareCollections(String property, Collection> left, Collection> right) {
+ List diffs =
+ zipAndEnumerate(left, right)
+ .map(t -> new Tuple4(t.e1, left, right, Apples.compare(property, t.e2, t.e3)))
+ .filter(t -> !t.e4.areEqual())
+ .map(t -> property + "[" + t.e1 + "]:" + t.e2 + " != " + t.e3)
+ .collect(Collectors.toList());
+ return new Result(!diffs.isEmpty(), diffs);
}
+ private static Result compareMaps(String property, Map, ?> left, Map, ?> right) {
+ List diffs = new ArrayList<>();
+ for (Map.Entry, ?> leftEntry : left.entrySet()) {
+ Object leftValue = leftEntry.getValue();
+ Object rightValue = right.get(leftEntry.getKey());
+ Result result = Apples.compare(property + "[" + leftEntry.getKey() + "]", leftValue, rightValue);
+ if (!result.areEqual()) {
+ diffs.addAll(result.getDiffs());
+ }
+ }
+ return new Result(diffs.isEmpty(), diffs);
+ }
+
+ private static Stream> zipAndEnumerate(Collection> left, Collection> right) {
+ Iterator> rightIt = right.iterator();
+ LongAdder adder = new LongAdder();
+ return left.stream()
+ .filter(__ -> rightIt.hasNext())
+ .map(o -> {
+ Tuple3 next = new Tuple3<>(adder.intValue(), o, rightIt.next());
+ adder.increment();
+ return next;
+ });
+ }
+
+ public static Result compare(long left, long right) {
+ return compare("", left, right);
+ }
+
+ public static Result compare(String property, long left, long right) {
+ return Result.from(property, left == right, left + " != " + right);
+ }
+
+ public static Result compare(int left, int right) {
+ return compare("", left, right);
+ }
+
+ public static Result compare(String property, int left, int right) {
+ return Result.from(property, left == right, left + " != " + right);
+ }
+
+ public static Result compare(short left, short right) {
+ return compare("", left, right);
+ }
+
+ public static Result compare(String property, short left, short right) {
+ return Result.from(property, left == right, left + " != " + right);
+ }
+
+ public static Result compare(byte left, byte right) {
+ return compare("", left, right);
+ }
+
+ public static Result compare(String property, byte left, byte right) {
+ return Result.from(property, left == right, left + " != " + right);
+ }
+
+ public static Result compare(float left, float right) {
+ return compare("", left, right);
+ }
+
+ public static Result compare(String property, float left, float right) {
+ return Result.from(property, left == right, left + " != " + right);
+ }
public static Result compare(Object left, long right) {
+ return compare("", left, right);
+ }
+
+ public static Result compare(String property, Object left, long right) {
if (left == null) {
- return Result.unequal("null != " + right);
+ return Result.unequal(property, "null != " + right);
+ }
+
+ if (left instanceof Long) {
+ return Result.from(property, (Long) left == right, asString(left) + " != " + right);
+ } else if (left instanceof Integer) {
+ return Result.from(property, (Integer) left == right, asString(left) + " != " + right);
+ } else if (left instanceof Short) {
+ return Result.from(property, (Short) left == right, asString(left) + " != " + right);
+ } else if (left instanceof Byte) {
+ return Result.from(property, (Byte) left == right, asString(left) + " != " + right);
+ } else {
+ return Result.unequal(property, asString(left) + " != " + right);
}
- return switch (left) {
- case Long l -> Result.from(l == right, asString(left) + " != " + right);
- case Integer i -> Result.from(i == right, asString(left) + " != " + right);
- case Short s -> Result.from(s == right, asString(left) + " != " + right);
- case Byte b -> Result.from(b == right, asString(left) + " != " + right);
- default -> Result.unequal(asString(left) + " != " + right);
- };
}
public static Result compare(char left, char right) {
- return Result.from(left == right, asString(left) + " != " + asString(right));
+ return compare("", left, right);
+ }
+
+ public static Result compare(String property, char left, char right) {
+ return Result.from(property, left == right, asString(left) + " != " + asString(right));
}
public static Result compare(Object left, char right) {
- return Result.from(left instanceof Character && (Character) left == right, asString(left) + " != " + asString(right));
+ return compare("", left, right);
+ }
+
+ public static Result compare(String property, Object left, char right) {
+ return Result.from(property, left instanceof Character && (Character) left == right, asString(left) + " != " + asString(right));
}
public static Result compare(long left, Object right) {
+ return compare("", left, right);
+ }
+
+ public static Result compare(String property, long left, Object right) {
if (right == null) {
- return Result.unequal(left + " != null");
+ return Result.unequal(property, left + " != null");
+ }
+ if (right instanceof Long) {
+ return Result.from(property, (Long) right == left, left + " != " + asString(right));
+ } else if (right instanceof Integer) {
+ return Result.from(property, (Integer) right == left, left + " != " + asString(right));
+ } else if (right instanceof Short) {
+ return Result.from(property, (Short) right == left, left + " != " + asString(right));
+ } else if (right instanceof Byte) {
+ return Result.from(property, (Byte) right == left, left + " != " + asString(right));
+ } else {
+ return Result.unequal(property, left + " != " + asString(right));
}
- return switch (right) {
- case Long l -> Result.from(l == left, left + " != " + asString(right));
- case Integer i -> Result.from(i == left, left + " != " + asString(right));
- case Short s -> Result.from(s == left, left + " != " + asString(right));
- case Byte b -> Result.from(b == left, left + " != " + asString(right));
- default -> Result.unequal(left + " != " + asString(right));
- };
}
public static Result compare(char left, Object right) {
- return Result.from(right instanceof Character && left == (Character) right, asString(left) + " != " + asString(right));
+ return compare("", left, right);
+ }
+
+ public static Result compare(String property, char left, Object right) {
+ return Result.from(property, right instanceof Character && left == (Character) right, asString(left) + " != " + asString(right));
}
public static Result compare(boolean left, boolean right) {
- return Result.from(left == right, left + " != " + right);
+ return compare("", left, right);
+ }
+
+ public static Result compare(String property, boolean left, boolean right) {
+ return Result.from(property, left == right, left + " != " + right);
}
public static Result compare(Object left, boolean right) {
- return Result.from(left instanceof Boolean && (Boolean) left == right, asString(left) + " != " + right);
+ return compare("", left, right);
+ }
+
+ public static Result compare(String property, Object left, boolean right) {
+ return Result.from(property, left instanceof Boolean && (Boolean) left == right, asString(left) + " != " + right);
}
public static Result compare(boolean left, Object right) {
- return Result.from(right instanceof Boolean && left == (Boolean) right, left + " != " + asString(right));
+ return compare("", left, right);
+ }
+
+ public static Result compare(String property, boolean left, Object right) {
+ return Result.from(property, right instanceof Boolean && left == (Boolean) right, left + " != " + asString(right));
}
public static Result compare(double left, double right) {
- return Result.from(left == right, left + " != " + right);
+ return compare("", left, right);
+ }
+
+ public static Result compare(String property, double left, double right) {
+ return Result.from(property, left == right, left + " != " + right);
}
public static Result compare(double left, double right, int precision) {
- return Result.from((int) (left * Math.pow(10, precision)) == (int) (right * Math.pow(10, precision)), left + " != " + right + ", using precision" + precision);
+ return compare("", left, right, precision);
+ }
+
+ public static Result compare(String property, double left, double right, int precision) {
+ return Result.from(property, (int) (left * Math.pow(10, precision)) == (int) (right * Math.pow(10, precision)), left + " != " + right + ", using precision" + precision);
}
public static Result compare(Object left, double right) {
- return Result.from(left instanceof Double && (Double) left == right, asString(left) + " != " + right);
+ return compare("", left, right);
+ }
+
+ public static Result compare(String property, Object left, double right) {
+ return Result.from(property, left instanceof Double && (Double) left == right, asString(left) + " != " + right);
}
public static Result compare(double left, Object right) {
- return Result.from(right instanceof Double && left == (Double) right, left + " != " + asString(right));
+ return compare("", left, right);
+ }
+
+ public static Result compare(String property, double left, Object right) {
+ return Result.from(property, right instanceof Double && left == (Double) right, left + " != " + asString(right));
}
public static Result compare(float left, Object right) {
- return Result.from(right instanceof Float && left == (Float) right, left + " != " + asString(right));
+ return compare("", left, right);
+ }
+
+ public static Result compare(String property, float left, Object right) {
+ return Result.from(property, right instanceof Float && left == (Float) right, left + " != " + asString(right));
}
private static String asString(char value) {
@@ -150,4 +306,30 @@ public class Apples {
return value.getClass().getName() + ": " + value;
}
}
+
+ static class Tuple3 {
+ final E1 e1;
+ final E2 e2;
+ final E3 e3;
+
+ Tuple3(E1 e1, E2 e2, E3 e3) {
+ this.e1 = e1;
+ this.e2 = e2;
+ this.e3 = e3;
+ }
+ }
+
+ static class Tuple4 {
+ final E1 e1;
+ final E2 e2;
+ final E3 e3;
+ final E4 e4;
+
+ Tuple4(E1 e1, E2 e2, E3 e3, E4 e4) {
+ this.e1 = e1;
+ this.e2 = e2;
+ this.e3 = e3;
+ this.e4 = e4;
+ }
+ }
}
diff --git a/src/main/java/nl/sander/apples/BaseApple.java b/src/main/java/nl/sander/apples/BaseApple.java
index f9ac0ed..2144aa5 100644
--- a/src/main/java/nl/sander/apples/BaseApple.java
+++ b/src/main/java/nl/sander/apples/BaseApple.java
@@ -1,6 +1,6 @@
package nl.sander.apples;
-abstract class BaseApple {
+public abstract class BaseApple {
public abstract Result compare(T left, T right);
}
diff --git a/src/main/java/nl/sander/apples/Result.java b/src/main/java/nl/sander/apples/Result.java
index 4d9346b..21e70b9 100644
--- a/src/main/java/nl/sander/apples/Result.java
+++ b/src/main/java/nl/sander/apples/Result.java
@@ -2,38 +2,89 @@ package nl.sander.apples;
import java.util.Arrays;
import java.util.List;
+import java.util.Objects;
import java.util.function.Supplier;
import java.util.stream.Collectors;
-public record Result(boolean areEqual, List diffs) {
+@SuppressWarnings("unused") // used by generated code
+public class Result {
+ private final boolean areEqual;
+ private final List diffs;
+
+ public Result(boolean areEqual, List diffs) {
+ this.areEqual = areEqual;
+ this.diffs = diffs;
+ }
+
public static Result SAME = new Result(true, List.of());
- public static Result from(boolean areEqual, String message) {
+ public static Result from(String property, boolean areEqual, String message) {
if (!areEqual) {
- return new Result(areEqual, List.of(message));
+ if (property.length() > 0) {
+ return new Result(areEqual, List.of("for " + property + ": " + message));
+ } else {
+ return new Result(areEqual, List.of(message));
+ }
} else {
return SAME;
}
}
- public static Result from(boolean areEqual, Supplier messageSupplier) {
+ public static Result from(String property, boolean areEqual, Supplier messageSupplier) {
if (!areEqual) {
- return new Result(areEqual, List.of(messageSupplier.get()));
+ if (property.length() > 0) {
+ return new Result(areEqual, List.of("for " + property + ": " + messageSupplier.get()));
+ } else {
+ return new Result(areEqual, List.of(messageSupplier.get()));
+ }
} else {
return SAME;
}
}
public static Result unequal(String message) {
- return from(false, message);
+ return from("", false, message);
+ }
+
+ public static Result unequal(String property, String message) {
+ return from(property, false, message);
+ }
+
+ public List getDiffs() {
+ return diffs;
+ }
+
+ public boolean areEqual() {
+ return areEqual;
}
public static Result merge(Result... result) {
boolean areEqual = Arrays.stream(result).allMatch(r -> r.areEqual);
List diffs = Arrays.stream(result)
- .map(Result::diffs)
+ .map(Result::getDiffs)
.flatMap(List::stream)
.collect(Collectors.toList());
return new Result(areEqual, diffs);
}
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ Result result = (Result) o;
+ return areEqual == result.areEqual && Objects.equals(diffs, result.diffs);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(areEqual, diffs);
+ }
+
+ @Override
+ public String toString() {
+ return "Result{" +
+ "areEqual=" + areEqual +
+ ", diffs=" + diffs +
+ '}';
+ }
}
diff --git a/src/test/java/nl/sander/apples/BeansTest.java b/src/test/java/nl/sander/apples/BeansTest.java
new file mode 100644
index 0000000..c6ed7d1
--- /dev/null
+++ b/src/test/java/nl/sander/apples/BeansTest.java
@@ -0,0 +1,25 @@
+package nl.sander.apples;
+
+import org.junit.jupiter.api.Test;
+
+import java.util.List;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+
+class BeansTest {
+
+ @Test
+ void testRecords() {
+ Result comparison = Apples.compare(new PlumBean("small", "red", true, 1, 1.0F, Storage.HIGH, (byte) 1, List.of(new Shop("tesco"))),
+ new PlumBean("large", "green", true, 1, 1.0F, Storage.LOW, (byte) 1, List.of(new Shop("asda"))));
+
+ assertFalse(comparison.areEqual());
+ assertFalse(comparison.getDiffs().isEmpty());
+ assertEquals(4, comparison.getDiffs().size());
+ assertEquals("for core: \"small\" != \"large\"", comparison.getDiffs().get(0));
+ assertEquals("for peel: \"red\" != \"green\"", comparison.getDiffs().get(1));
+ assertEquals("for storage: HIGH != LOW", comparison.getDiffs().get(2));
+ assertEquals("shops[0]:[Shop{name='tesco'}] != [Shop{name='asda'}]", comparison.getDiffs().get(3));
+ }
+}
diff --git a/src/test/java/nl/sander/apples/ObjectsTest.java b/src/test/java/nl/sander/apples/ObjectsTest.java
index 08d09a5..5229d4b 100644
--- a/src/test/java/nl/sander/apples/ObjectsTest.java
+++ b/src/test/java/nl/sander/apples/ObjectsTest.java
@@ -2,6 +2,9 @@ package nl.sander.apples;
import org.junit.jupiter.api.Test;
+import java.math.BigDecimal;
+import java.util.Map;
+
import static org.junit.jupiter.api.Assertions.*;
class ObjectsTest {
@@ -22,7 +25,34 @@ class ObjectsTest {
}
@Test
- void differentClass(){
+ void differentClass() {
assertEquals(Result.unequal("\"1\" != java.lang.Integer: 1"), Apples.compare("1", Integer.valueOf(1)));
}
+
+ @Test
+ void sameKeysAndValues() {
+ assertTrue(Apples.compare("map", Map.of("a", 1, "b", 2), Map.of("b", 2, "a", 1)).areEqual());
+ }
+
+ @Test
+ void differentKeysAndValues() {
+ Result result = Apples.compare("map", Map.of("a", 2, "b", 1), Map.of("b", 2, "a", 1));
+ assertFalse(result.areEqual());
+ assertTrue(result.getDiffs().contains("for map[b]: 1 != 2"));
+ assertTrue(result.getDiffs().contains("for map[a]: 2 != 1"));
+ }
+
+ @Test
+ void bigDecimals() {
+ Result result = Apples.compare(BigDecimal.valueOf(0), BigDecimal.valueOf(1));
+ assertFalse(result.areEqual());
+ assertEquals("0 != 1", result.getDiffs().get(0));
+ }
+
+ @Test
+ void enums() {
+ Result result = Apples.compare(Storage.HIGH, Storage.LOW);
+ assertFalse(result.areEqual());
+ assertEquals("HIGH != LOW", result.getDiffs().get(0));
+ }
}
diff --git a/src/test/java/nl/sander/apples/Plum.java b/src/test/java/nl/sander/apples/Plum.java
deleted file mode 100644
index 5d633e0..0000000
--- a/src/test/java/nl/sander/apples/Plum.java
+++ /dev/null
@@ -1,4 +0,0 @@
-package nl.sander.apples;
-
-public record Plum(String core, String peel, boolean juicy, int number, float price, Storage storage) {
-}
diff --git a/src/test/java/nl/sander/apples/PlumApple.java b/src/test/java/nl/sander/apples/PlumApple.java
deleted file mode 100644
index 9521e6a..0000000
--- a/src/test/java/nl/sander/apples/PlumApple.java
+++ /dev/null
@@ -1,14 +0,0 @@
-package nl.sander.apples;
-
-public class PlumApple extends BaseApple {
- public Result compare(Plum left, Plum right) {
- Result core = Apples.compare(left.core(), right.core());
- Result peel = Apples.compare(left.peel(), right.peel());
- Result juicy = Apples.compare(left.juicy(), right.juicy());
- Result price = Apples.compare(left.price(), right.price());
- Result number = Apples.compare(left.number(), right.number());
- Result storage = Apples.compare(left.storage(), right.storage());
-
- return Result.merge(core, peel, juicy, price, number, storage);
- }
-}
diff --git a/src/test/java/nl/sander/apples/PlumBean.java b/src/test/java/nl/sander/apples/PlumBean.java
new file mode 100644
index 0000000..d5e2c73
--- /dev/null
+++ b/src/test/java/nl/sander/apples/PlumBean.java
@@ -0,0 +1,58 @@
+package nl.sander.apples;
+
+import java.util.List;
+
+public class PlumBean {
+ private final String core;
+ private final String peel;
+ private final boolean juicy;
+ private final int number;
+ private final float price;
+ private final Storage storage;
+ private final byte cores;
+
+ private final List shops;
+
+ public PlumBean(String core, String peel, boolean juicy, int number, float price, Storage storage, byte cores, List shops) {
+ this.core = core;
+ this.peel = peel;
+ this.juicy = juicy;
+ this.number = number;
+ this.price = price;
+ this.storage = storage;
+ this.cores = cores;
+ this.shops = shops;
+ }
+
+ public String getCore() {
+ return core;
+ }
+
+ public String getPeel() {
+ return peel;
+ }
+
+ public boolean isJuicy() {
+ return juicy;
+ }
+
+ public int getNumber() {
+ return number;
+ }
+
+ public float getPrice() {
+ return price;
+ }
+
+ public Storage getStorage() {
+ return storage;
+ }
+
+ public byte getCores() {
+ return cores;
+ }
+
+ public List getShops() {
+ return shops;
+ }
+}
diff --git a/src/test/java/nl/sander/apples/PlumRecord.java b/src/test/java/nl/sander/apples/PlumRecord.java
new file mode 100644
index 0000000..cd3c9d6
--- /dev/null
+++ b/src/test/java/nl/sander/apples/PlumRecord.java
@@ -0,0 +1,17 @@
+/*
+ * uncomment when in jdk16+
+ */
+
+//package nl.sander.apples;
+//
+//import java.util.List;
+//
+//public record PlumRecord(String core,
+// String peel,
+// boolean juicy,
+// int number,
+// float price,
+// Storage storage,
+// byte cores,
+// List shops) {
+//}
diff --git a/src/test/java/nl/sander/apples/RecordsTest.java b/src/test/java/nl/sander/apples/RecordsTest.java
index e9dcb41..b99bc7e 100644
--- a/src/test/java/nl/sander/apples/RecordsTest.java
+++ b/src/test/java/nl/sander/apples/RecordsTest.java
@@ -1,33 +1,33 @@
-package nl.sander.apples;
+/*
+ * uncomment when in jdk16+
+ */
-import org.junit.jupiter.api.Test;
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertFalse;
-
-class RecordsTest {
-
- @Test
- void testExample() {
- Result comparison = new PlumApple().compare(new Plum("small", "red",true, 1, 1.0F,Storage.HIGH),
- new Plum("large", "green",true, 1, 1.0F,Storage.HIGH));
-
- assertFalse(comparison.areEqual());
- assertFalse(comparison.diffs().isEmpty());
- assertEquals(2, comparison.diffs().size());
- assertEquals("\"small\" != \"large\"", comparison.diffs().get(0));
- assertEquals("\"red\" != \"green\"", comparison.diffs().get(1));
- }
-
- @Test
- void testRecords() {
- Result comparison = Apples.compare(new Plum("small", "red",true, 1, 1.0F,Storage.HIGH),
- new Plum("large", "green",true, 1, 1.0F,Storage.HIGH));
-
- assertFalse(comparison.areEqual());
- assertFalse(comparison.diffs().isEmpty());
- assertEquals(2, comparison.diffs().size());
- assertEquals("\"small\" != \"large\"", comparison.diffs().get(0));
- assertEquals("\"red\" != \"green\"", comparison.diffs().get(1));
- }
-}
+//package nl.sander.apples;
+//
+//import org.junit.jupiter.api.Test;
+//
+//import java.util.List;
+//
+//import static org.junit.jupiter.api.Assertions.assertEquals;
+//import static org.junit.jupiter.api.Assertions.assertFalse;
+//
+//class RecordsTest {
+//
+// @Test
+// void testRecords() {
+// Result comparison = Apples.compare(new PlumRecord("small", "red", true, 1, 1.0F, Storage.HIGH, (byte) 1, List.of(new Shop("tesco"))),
+// new PlumRecord("large", "green", true, 1, 1.0F, Storage.LOW, (byte) 1, List.of(new Shop("asda"))));
+//
+// assertFalse(comparison.areEqual());
+// assertFalse(comparison.getDiffs().isEmpty());
+// assertEquals(4, comparison.getDiffs().size());
+// assertEquals("for core: \"small\" != \"large\"", comparison.getDiffs().get(0));
+// assertEquals("for peel: \"red\" != \"green\"", comparison.getDiffs().get(1));
+// assertEquals("for storage: HIGH != LOW", comparison.getDiffs().get(2));
+// assertEquals("shops[0]:[Shop{name='tesco'}] != [Shop{name='asda'}]", comparison.getDiffs().get(3));
+// }
+//
+//
+//}
+//
diff --git a/src/test/java/nl/sander/apples/Shop.java b/src/test/java/nl/sander/apples/Shop.java
new file mode 100644
index 0000000..84dae2a
--- /dev/null
+++ b/src/test/java/nl/sander/apples/Shop.java
@@ -0,0 +1,20 @@
+package nl.sander.apples;
+
+public class Shop {
+ private final String name;
+
+ public Shop(String name) {
+ this.name = name;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ @Override
+ public String toString() {
+ return "Shop{" +
+ "name='" + name + '\'' +
+ '}';
+ }
+}