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 + '\'' + + '}'; + } +}