new name, new functionality
This commit is contained in:
parent
8a8dc9d9de
commit
4d4ebe9c7f
36 changed files with 904 additions and 533 deletions
11
README.md
11
README.md
|
|
@ -1,8 +1,15 @@
|
||||||
# Apples
|
# reflective
|
||||||
|
Utility classes that use ASM for generating metaclasses as if it were standard java reflection, but without the performance overhead.
|
||||||
|
|
||||||
|
|
||||||
|
__nl.sander.reflective.compare.Compare__
|
||||||
* universal (deep) compare tool
|
* universal (deep) compare tool
|
||||||
* compares [apple] to [orange] recursively and shows the diff
|
* compares [apple] to [orange] recursively and shows the diff
|
||||||
* no reflection
|
* no reflection
|
||||||
* compiles to bytecode version jdk11
|
* compiles to bytecode version jdk11
|
||||||
* but also handles records, if you run jdk16+
|
* but also handles records, if you run jdk16+
|
||||||
|
* Can optionally do 'structural comparison' (as opposed to _nominal_ like in the respective types of polymorphism). Let's say you have class Apple with property _color_ and a class Orange, also with property _color_. `Compare` provides `any` method with which you can compare the values disregarding the type that contains them.
|
||||||
|
|
||||||
|
__nl.sander.reflective.tomap.ToMap__
|
||||||
|
* turn any bean/record in a Map<String, Object>
|
||||||
|
|
||||||
* I have one more wish for this and that is 'structural comparison'. Let's say you have class Apple with property _color_ and a class Orange, also with property _color_. Right now `Apples` does the sensible thing, and that is saying: "classes don't match". But what what if you could compare these apples and oranges? Should be possible.
|
|
||||||
6
pom.xml
6
pom.xml
|
|
@ -3,10 +3,10 @@
|
||||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<groupId>nl.sander</groupId>
|
<groupId>nl.sander</groupId>
|
||||||
<artifactId>Apples</artifactId>
|
<artifactId>reflective</artifactId>
|
||||||
<version>0.0.1-SNAPSHOT</version>
|
<version>0.0.1-SNAPSHOT</version>
|
||||||
<name>Comparator</name>
|
<name>reflective</name>
|
||||||
<description>Comparator</description>
|
<description>Reflective utils that don't use java.lang.reflect</description>
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<dependency>
|
<dependency>
|
||||||
|
|
|
||||||
|
|
@ -1,6 +0,0 @@
|
||||||
package nl.sander.apples;
|
|
||||||
|
|
||||||
public abstract class BaseApple {
|
|
||||||
|
|
||||||
public abstract Result compare(Object apple, Object orange);
|
|
||||||
}
|
|
||||||
|
|
@ -0,0 +1,6 @@
|
||||||
|
package nl.sander.reflective.compare;
|
||||||
|
|
||||||
|
public abstract class AbstractComparator {
|
||||||
|
|
||||||
|
public abstract Result compare(Object apple, Object orange);
|
||||||
|
}
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
package nl.sander.apples;
|
package nl.sander.reflective.compare;
|
||||||
|
|
||||||
|
import nl.sander.reflective.java.Java;
|
||||||
import org.objectweb.asm.ClassVisitor;
|
import org.objectweb.asm.ClassVisitor;
|
||||||
import org.objectweb.asm.MethodVisitor;
|
import org.objectweb.asm.MethodVisitor;
|
||||||
import org.objectweb.asm.tree.*;
|
import org.objectweb.asm.tree.*;
|
||||||
|
|
@ -9,16 +10,14 @@ import java.util.UUID;
|
||||||
|
|
||||||
import static org.objectweb.asm.Opcodes.*;
|
import static org.objectweb.asm.Opcodes.*;
|
||||||
|
|
||||||
class AppleFactory extends ClassVisitor {
|
class ComparatorFactory extends ClassVisitor {
|
||||||
|
|
||||||
public static final String SUPER = javaName(BaseApple.class.getName());
|
public static final String SUPER = Java.internalName(AbstractComparator.class);
|
||||||
|
|
||||||
public static final String INIT = "<init>";
|
|
||||||
public static final String ZERO_ARGS_VOID = "()V";
|
|
||||||
|
|
||||||
private boolean isRecord = false;
|
private boolean isRecord = false;
|
||||||
|
|
||||||
public AppleFactory() {
|
public ComparatorFactory() {
|
||||||
super(ASM9);
|
super(ASM9);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -40,52 +39,41 @@ class AppleFactory extends ClassVisitor {
|
||||||
classNode.superName = SUPER;
|
classNode.superName = SUPER;
|
||||||
classNode.version = V11;
|
classNode.version = V11;
|
||||||
classNode.access = ACC_PUBLIC;
|
classNode.access = ACC_PUBLIC;
|
||||||
MethodNode constructor = new MethodNode(ACC_PUBLIC, INIT, ZERO_ARGS_VOID, null, null);
|
MethodNode constructor = new MethodNode(ACC_PUBLIC, Java.INIT, Java.ZERO_ARGS_VOID, null, null);
|
||||||
constructor.instructions.add(new VarInsnNode(ALOAD, 0));
|
constructor.instructions.add(new VarInsnNode(ALOAD, 0));
|
||||||
constructor.instructions.add(new MethodInsnNode(INVOKESPECIAL, SUPER, INIT, ZERO_ARGS_VOID));
|
constructor.instructions.add(new MethodInsnNode(INVOKESPECIAL, SUPER, Java.INIT, Java.ZERO_ARGS_VOID));
|
||||||
constructor.instructions.add(new InsnNode(RETURN));
|
constructor.instructions.add(new InsnNode(RETURN));
|
||||||
classNode.methods.add(constructor);
|
classNode.methods.add(constructor);
|
||||||
|
|
||||||
compareMethod = new MethodNode(ACC_PUBLIC,
|
compareMethod = new MethodNode(ACC_PUBLIC,
|
||||||
"compare", "(Ljava/lang/Object;Ljava/lang/Object;)Lnl/sander/apples/Result;", null, null);
|
"compare", "(Ljava/lang/Object;Ljava/lang/Object;)L" + Java.internalName(Result.class) + ";", null, null);
|
||||||
classNode.methods.add(compareMethod);
|
classNode.methods.add(compareMethod);
|
||||||
add(new VarInsnNode(ALOAD, 0));
|
add(new VarInsnNode(ALOAD, 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public MethodVisitor visitMethod(int access, String methodname,
|
public MethodVisitor visitMethod(int access, String methodname,
|
||||||
String desc, String signature, String[] exceptions) {
|
String desc, String signature, String[] exceptions) {
|
||||||
if (!hasArgs(desc) && access == Modifier.PUBLIC && isRecord ||
|
if (!Java.hasArgs(desc) && access == Modifier.PUBLIC && isRecord ||
|
||||||
(methodname.startsWith("get") || (methodname.startsWith("is")) && desc.equals("()Z"))) {
|
(methodname.startsWith("get") || (methodname.startsWith("is")) && desc.equals("()Z"))) {
|
||||||
visitGetter(methodname, asProperty(methodname, isRecord), getReturnType(desc));
|
visitGetter(methodname, Java.asProperty(methodname, isRecord), Java.getReturnType(desc));
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
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) {
|
private void visitGetter(String getterMethodName, String propertyName, String returnType) {
|
||||||
add(new LdcInsnNode(propertyName));
|
add(new LdcInsnNode(propertyName));
|
||||||
add(new VarInsnNode(ALOAD, 1));
|
add(new VarInsnNode(ALOAD, 1));
|
||||||
add(new TypeInsnNode(CHECKCAST, javaName(classToMap)));
|
add(new TypeInsnNode(CHECKCAST, Java.internalName(classToMap)));
|
||||||
add(new MethodInsnNode(INVOKEVIRTUAL, classToMap, getterMethodName, "()" + returnType));
|
add(new MethodInsnNode(INVOKEVIRTUAL, classToMap, getterMethodName, "()" + returnType));
|
||||||
|
|
||||||
add(new VarInsnNode(ALOAD, 2));
|
add(new VarInsnNode(ALOAD, 2));
|
||||||
add(new TypeInsnNode(CHECKCAST, javaName(classToMap)));
|
add(new TypeInsnNode(CHECKCAST, Java.internalName(classToMap)));
|
||||||
add(new MethodInsnNode(INVOKEVIRTUAL, classToMap, getterMethodName, "()" + returnType));
|
add(new MethodInsnNode(INVOKEVIRTUAL, classToMap, getterMethodName, "()" + returnType));
|
||||||
|
|
||||||
add(new MethodInsnNode(INVOKESTATIC, "nl/sander/apples/Apples", "compare", "("
|
add(new MethodInsnNode(INVOKESTATIC, Java.internalName(Compare.class), "compare", "("
|
||||||
+ getSignature(returnType)
|
+ getSignature(returnType)
|
||||||
+ ")Lnl/sander/apples/Result;"));
|
+ ")L" + Java.internalName(Result.class) + ";"));
|
||||||
add(new VarInsnNode(ASTORE, 3 + (localVarIndex++)));
|
add(new VarInsnNode(ASTORE, 3 + (localVarIndex++)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -96,7 +84,7 @@ class AppleFactory extends ClassVisitor {
|
||||||
} else {
|
} else {
|
||||||
type = returnType;
|
type = returnType;
|
||||||
}
|
}
|
||||||
return "Ljava/lang/String;"+type + type;
|
return "Ljava/lang/String;" + type + type;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -106,7 +94,7 @@ class AppleFactory extends ClassVisitor {
|
||||||
} else {
|
} else {
|
||||||
add(new LdcInsnNode(localVarIndex));
|
add(new LdcInsnNode(localVarIndex));
|
||||||
}
|
}
|
||||||
add(new TypeInsnNode(ANEWARRAY, "nl/sander/apples/Result"));
|
add(new TypeInsnNode(ANEWARRAY, Java.internalName(Result.class)));
|
||||||
|
|
||||||
for (int i = 0; i < localVarIndex; i++) {
|
for (int i = 0; i < localVarIndex; i++) {
|
||||||
add(new InsnNode(DUP));
|
add(new InsnNode(DUP));
|
||||||
|
|
@ -119,7 +107,7 @@ class AppleFactory extends ClassVisitor {
|
||||||
add(new InsnNode(AASTORE));
|
add(new InsnNode(AASTORE));
|
||||||
}
|
}
|
||||||
|
|
||||||
add(new MethodInsnNode(INVOKESTATIC, "nl/sander/apples/Result", "merge", "([Lnl/sander/apples/Result;)Lnl/sander/apples/Result;"));
|
add(new MethodInsnNode(INVOKESTATIC, Java.internalName(Result.class), "merge", "([L" + Java.internalName(Result.class) + ";)L" + Java.internalName(Result.class) + ";"));
|
||||||
add(new InsnNode(ARETURN));
|
add(new InsnNode(ARETURN));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -127,16 +115,5 @@ class AppleFactory extends ClassVisitor {
|
||||||
compareMethod.instructions.add(ins);
|
compareMethod.instructions.add(ins);
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getReturnType(String desc) {
|
|
||||||
return desc.substring(2);
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean hasArgs(String desc) {
|
|
||||||
return desc.charAt(1) != ')';
|
|
||||||
}
|
|
||||||
|
|
||||||
private static String javaName(String className) {
|
|
||||||
return className.replaceAll("\\.", "/");
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -1,97 +1,167 @@
|
||||||
package nl.sander.apples;
|
package nl.sander.reflective.compare;
|
||||||
|
|
||||||
|
import nl.sander.reflective.java.ByteClassLoader;
|
||||||
|
import nl.sander.reflective.java.Java;
|
||||||
|
import nl.sander.reflective.tomap.ToMap;
|
||||||
import org.objectweb.asm.ClassReader;
|
import org.objectweb.asm.ClassReader;
|
||||||
import org.objectweb.asm.ClassWriter;
|
import org.objectweb.asm.ClassWriter;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
import java.util.concurrent.ConcurrentMap;
|
||||||
import java.util.concurrent.atomic.LongAdder;
|
import java.util.concurrent.atomic.LongAdder;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||||
public class Apples {
|
/**
|
||||||
|
* Deep (recursive) comparison of two objects
|
||||||
|
* - floating point comparison with optional precision
|
||||||
|
* - objects of same type or differing types, allowing comparison of types that have the same data or subsets
|
||||||
|
*
|
||||||
|
* In case of maps or differing object types, every item in apple is expected in orange, so apple can be subset of orange.
|
||||||
|
*/
|
||||||
|
public class Compare {
|
||||||
private final static Map<Character, String> CHAR_ESCAPES = Map.of('\t', "\\t", '\b', "\\b", '\n', "\\n", '\r', "\\r", '\f', "\\f", '\\', "\\\\");
|
private final static Map<Character, String> CHAR_ESCAPES = Map.of('\t', "\\t", '\b', "\\b", '\n', "\\n", '\r', "\\r", '\f', "\\f", '\\', "\\\\");
|
||||||
|
|
||||||
private static final ByteClassLoader generatedClassesLoader = new ByteClassLoader();
|
private final static ConcurrentMap<Class<?>, AbstractComparator> cache = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compares two objects. They are assumed to be of the same type, otherwise that is the difference
|
||||||
|
*
|
||||||
|
* @param apple first object for comparison
|
||||||
|
* @param orange second object for comparison
|
||||||
|
* @return A Result object with the outcome and some details
|
||||||
|
*
|
||||||
|
* throws nothing but Result can wrap an exception instead of an actual comparison (rust style exception handling)
|
||||||
|
*/
|
||||||
public static Result compare(Object apple, Object orange) {
|
public static Result compare(Object apple, Object orange) {
|
||||||
return compare("", apple, orange);
|
return compare("", apple, orange, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Result compare(String property, Object apple, Object orange) {
|
/**
|
||||||
if (apple == null) {
|
* Compare two objects. They are not assumed to be of the same type.
|
||||||
return Result.from(property, orange == null, "null != " + asString(orange));
|
*
|
||||||
}
|
* @param apple first object for comparison
|
||||||
|
* @param orange second object for comparison
|
||||||
|
* @return A Result object with the outcome and some details
|
||||||
|
* throws nothing but Result can wrap an exception instead of an actual comparison (rust style exception handling)
|
||||||
|
*/
|
||||||
|
public static Result any(Object apple, Object orange) {
|
||||||
|
return compare("", apple, orange, true);
|
||||||
|
}
|
||||||
|
|
||||||
if (orange == null) {
|
/**
|
||||||
return Result.unequal(property, asString(apple) + " != null");
|
* Version of same compare method where you can specify a common property for the two objects to compare.
|
||||||
}
|
* This is primarily useful for doing bean/record property comparison.
|
||||||
|
*
|
||||||
|
* @param property common property (key) for apple and orange
|
||||||
|
* @param apple first object for comparison
|
||||||
|
* @param orange second object for comparison
|
||||||
|
* @return A Result object with the outcome and some details
|
||||||
|
* throws nothing but Result can wrap an exception instead of an actual comparison (rust style exception handling)
|
||||||
|
*/
|
||||||
|
public static Result compare(String property, Object apple, Object orange) {
|
||||||
|
return compare(property, apple, orange, false);
|
||||||
|
}
|
||||||
|
|
||||||
if (apple == orange) {
|
|
||||||
return Result.SAME;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (apple.getClass() != orange.getClass()) {
|
static Result compare(String property, Object apple, Object orange, boolean allowDifferingTypes) {
|
||||||
return Result.unequal(property, asString(apple) + " != " + asString(orange));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (apple instanceof String) {
|
|
||||||
return Result.from(property, apple.equals(orange), () -> asString(apple) + " != " + asString(orange));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (apple instanceof Number) {
|
|
||||||
return Result.from(property, apple.equals(orange), () -> apple + " != " + orange);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (apple instanceof Collection) {
|
|
||||||
return compareCollections(property, (Collection<?>) apple, (Collection<?>) orange);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (apple instanceof Map) {
|
|
||||||
return compareMaps(property, (Map<?, ?>) apple, (Map<?, ?>) orange);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (apple instanceof Comparable<?>) {
|
|
||||||
int comparison = ((Comparable) apple).compareTo(orange);
|
|
||||||
if (comparison == 0) {
|
|
||||||
return new Result(true, List.of());
|
|
||||||
} else {
|
|
||||||
return Result.from(property, false, apple + " != " + orange);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
try {
|
try {
|
||||||
ClassReader cr = new ClassReader(apple.getClass().getName());
|
if (apple == null) {
|
||||||
AppleFactory appleFactory = new AppleFactory();
|
return Result.from(property, orange == null, "null != " + asString(orange));
|
||||||
cr.accept(appleFactory, ClassReader.SKIP_FRAMES);
|
}
|
||||||
|
|
||||||
|
if (orange == null) {
|
||||||
|
return Result.unequal(property, asString(apple) + " != null");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (apple == orange) {
|
||||||
|
return Result.SAME;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (apple.getClass() != orange.getClass()) {
|
||||||
|
if (allowDifferingTypes) {
|
||||||
|
// convert objects to maps and compare their keys/values
|
||||||
|
return compareMaps(property, ToMap.map(apple), (Map<?, ?>) ToMap.map(orange), allowDifferingTypes);
|
||||||
|
} else {
|
||||||
|
return Result.unequal(property, asString(apple) + " != " + asString(orange));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (apple instanceof String) {
|
||||||
|
return Result.from(property, apple.equals(orange), () -> asString(apple) + " != " + asString(orange));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (apple instanceof Number) {
|
||||||
|
return Result.from(property, apple.equals(orange), () -> apple + " != " + orange);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (apple instanceof Collection) {
|
||||||
|
return compareCollections(property, (Collection<?>) apple, (Collection<?>) orange, allowDifferingTypes);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (apple instanceof Map) {
|
||||||
|
return compareMaps(property, (Map<?, ?>) apple, (Map<?, ?>) orange, allowDifferingTypes);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (apple instanceof Comparable<?>) {
|
||||||
|
int comparison = ((Comparable) apple).compareTo(orange);
|
||||||
|
if (comparison == 0) {
|
||||||
|
return new Result(true, List.of());
|
||||||
|
} else {
|
||||||
|
return Result.from(property, false, apple + " != " + orange);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return cache.computeIfAbsent(apple.getClass(), k -> createComparator(apple))
|
||||||
|
.compare(apple, orange);
|
||||||
|
} catch (Exception e) {
|
||||||
|
return Result.error(e.getCause());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static AbstractComparator createComparator(Object apple) {
|
||||||
|
try {
|
||||||
|
ClassReader cr = Java.getClassReader(apple);
|
||||||
|
|
||||||
|
ComparatorFactory comparatorFactory = new ComparatorFactory();
|
||||||
|
cr.accept(comparatorFactory, ClassReader.SKIP_FRAMES);
|
||||||
ClassWriter classWriter = new ClassWriter(ClassWriter.COMPUTE_FRAMES);
|
ClassWriter classWriter = new ClassWriter(ClassWriter.COMPUTE_FRAMES);
|
||||||
|
|
||||||
appleFactory.classNode.accept(classWriter);
|
comparatorFactory.classNode.accept(classWriter);
|
||||||
byte[] byteArray = classWriter.toByteArray();
|
byte[] byteArray = classWriter.toByteArray();
|
||||||
|
|
||||||
generatedClassesLoader.addClass(appleFactory.classNode.name, byteArray);
|
ByteClassLoader.INSTANCE.addClass(comparatorFactory.classNode.name, byteArray);
|
||||||
BaseApple baseApple = (BaseApple) generatedClassesLoader.loadClass(appleFactory.classNode.name).getConstructor().newInstance();
|
return (AbstractComparator) ByteClassLoader.INSTANCE.loadClass(comparatorFactory.classNode.name).getConstructor().newInstance();
|
||||||
return baseApple.compare(apple, orange);
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Result compareCollections(String property, Collection<?> apple, Collection<?> orange) {
|
private static Result compareCollections(String property, Collection<?> apple, Collection<?> orange, boolean allowDifferingTypes) {
|
||||||
List<String> diffs =
|
List<String> diffs =
|
||||||
zipAndEnumerate(apple, orange)
|
zipAndEnumerate(apple, orange)
|
||||||
.map(t -> new Tuple4<Integer, Object, Object, Result>(t.e1, apple, orange, Apples.compare(property, t.e2, t.e3)))
|
.map(t -> {
|
||||||
|
try {
|
||||||
|
return new Tuple4<Integer, Object, Object, Result>(t.e1, apple, orange, Compare.compare(property, t.e2, t.e3, allowDifferingTypes));
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException(e);//meh
|
||||||
|
}
|
||||||
|
})
|
||||||
.filter(t -> !t.e4.areEqual())
|
.filter(t -> !t.e4.areEqual())
|
||||||
.map(t -> property + "[" + t.e1 + "]:" + t.e2 + " != " + t.e3)
|
.map(t -> property + "[" + t.e1 + "]:" + t.e2 + " != " + t.e3)
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
return new Result(!diffs.isEmpty(), diffs);
|
return new Result(!diffs.isEmpty(), diffs);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Result compareMaps(String property, Map<?, ?> apple, Map<?, ?> orange) {
|
private static Result compareMaps(String property, Map<?, ?> apple, Map<?, ?> orange, boolean allowDifferingTypes) throws Exception {
|
||||||
List<String> diffs = new ArrayList<>();
|
List<String> diffs = new ArrayList<>();
|
||||||
for (Map.Entry<?, ?> appleEntry : apple.entrySet()) {
|
for (Map.Entry<?, ?> appleEntry : apple.entrySet()) {
|
||||||
Object appleValue = appleEntry.getValue();
|
Object appleValue = appleEntry.getValue();
|
||||||
Object orangeValue = orange.get(appleEntry.getKey());
|
Object orangeValue = orange.get(appleEntry.getKey());
|
||||||
Result result = Apples.compare(property + "[" + appleEntry.getKey() + "]", appleValue, orangeValue);
|
Result result = Compare.compare(property + "[" + appleEntry.getKey() + "]", appleValue, orangeValue, allowDifferingTypes);
|
||||||
if (!result.areEqual()) {
|
if (!result.areEqual()) {
|
||||||
diffs.addAll(result.getDiffs());
|
diffs.addAll(result.getDiffs());
|
||||||
}
|
}
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
package nl.sander.apples;
|
package nl.sander.reflective.compare;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
@ -6,18 +6,30 @@ import java.util.Objects;
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
@SuppressWarnings("unused") // used by generated code
|
|
||||||
public class Result {
|
public class Result {
|
||||||
private final boolean areEqual;
|
private final boolean areEqual;
|
||||||
private final List<String> diffs;
|
private final List<String> diffs;
|
||||||
|
|
||||||
|
private final Throwable e;
|
||||||
|
|
||||||
public Result(boolean areEqual, List<String> diffs) {
|
public Result(boolean areEqual, List<String> diffs) {
|
||||||
this.areEqual = areEqual;
|
this.areEqual = areEqual;
|
||||||
this.diffs = diffs;
|
this.diffs = diffs;
|
||||||
|
this.e = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Result SAME = new Result(true, List.of());
|
public static Result SAME = new Result(true, List.of());
|
||||||
|
|
||||||
|
public Result(Throwable e) {
|
||||||
|
this.areEqual = false;//meh
|
||||||
|
this.diffs = null;
|
||||||
|
this.e = e;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Result error(Throwable e) {
|
||||||
|
return new Result(e);
|
||||||
|
}
|
||||||
|
|
||||||
public static Result from(String property, boolean areEqual, String message) {
|
public static Result from(String property, boolean areEqual, String message) {
|
||||||
if (!areEqual) {
|
if (!areEqual) {
|
||||||
if (property.length() > 0) {
|
if (property.length() > 0) {
|
||||||
|
|
@ -1,11 +1,17 @@
|
||||||
package nl.sander.apples;
|
package nl.sander.reflective.java;
|
||||||
|
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.concurrent.ConcurrentMap;
|
import java.util.concurrent.ConcurrentMap;
|
||||||
|
|
||||||
class ByteClassLoader extends ClassLoader {
|
/*
|
||||||
|
* common util not for external use
|
||||||
|
*
|
||||||
|
* Loads the class into the jvm, after the user has generated some bytecode
|
||||||
|
*/
|
||||||
|
public class ByteClassLoader extends ClassLoader {
|
||||||
|
|
||||||
private final ConcurrentMap<String, Class<?>> classes = new ConcurrentHashMap<>();
|
private final ConcurrentMap<String, Class<?>> classes = new ConcurrentHashMap<>();
|
||||||
|
public final static ByteClassLoader INSTANCE = new ByteClassLoader();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Class<?> findClass(String name) throws ClassNotFoundException {
|
protected Class<?> findClass(String name) throws ClassNotFoundException {
|
||||||
51
src/main/java/nl/sander/reflective/java/Java.java
Normal file
51
src/main/java/nl/sander/reflective/java/Java.java
Normal file
|
|
@ -0,0 +1,51 @@
|
||||||
|
package nl.sander.reflective.java;
|
||||||
|
|
||||||
|
import org.objectweb.asm.ClassReader;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* common utils not for external use
|
||||||
|
*/
|
||||||
|
public class Java {
|
||||||
|
|
||||||
|
public static final String INIT = "<init>";
|
||||||
|
public static final String ZERO_ARGS_VOID = "()V";
|
||||||
|
public static final String OBJECT = "Ljava/lang/Object;";
|
||||||
|
|
||||||
|
public static String internalName(String className) {
|
||||||
|
return className.replaceAll("\\.", "/");
|
||||||
|
}
|
||||||
|
public static String internalName(Class<?> type) {
|
||||||
|
return internalName(type.getName());
|
||||||
|
}
|
||||||
|
public static boolean hasArgs(String desc) {
|
||||||
|
return desc.charAt(1) != ')';
|
||||||
|
}
|
||||||
|
|
||||||
|
public static 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getReturnType(String desc) {
|
||||||
|
return desc.substring(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ClassReader getClassReader(Object value) throws ClassNotFoundException {
|
||||||
|
ClassReader cr = null;
|
||||||
|
try {
|
||||||
|
cr = new ClassReader(value.getClass().getName());
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new ClassNotFoundException(value.getClass().getName());
|
||||||
|
}
|
||||||
|
return cr;
|
||||||
|
}
|
||||||
|
}
|
||||||
37
src/main/java/nl/sander/reflective/tomap/AbstractToMap.java
Normal file
37
src/main/java/nl/sander/reflective/tomap/AbstractToMap.java
Normal file
|
|
@ -0,0 +1,37 @@
|
||||||
|
package nl.sander.reflective.tomap;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public abstract class AbstractToMap {
|
||||||
|
|
||||||
|
public abstract Map<String, Object> toMap(Object object);
|
||||||
|
|
||||||
|
protected void add(HashMap<String, Object> m, String key, byte b) {
|
||||||
|
m.put(key, b);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void add(HashMap<String, Object> m, String key, short s) {
|
||||||
|
m.put(key, s);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void add(HashMap<String, Object> m, String key, int i) {
|
||||||
|
m.put(key, i);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void add(HashMap<String, Object> m, String key, boolean b) {
|
||||||
|
m.put(key, b);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void add(HashMap<String, Object> m, String key, float f) {
|
||||||
|
m.put(key, f);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void add(HashMap<String, Object> m, String key, double b) {
|
||||||
|
m.put(key, b);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void add(HashMap<String, Object> m, String key, Object o) {
|
||||||
|
m.put(key, o);
|
||||||
|
}
|
||||||
|
}
|
||||||
50
src/main/java/nl/sander/reflective/tomap/ToMap.java
Normal file
50
src/main/java/nl/sander/reflective/tomap/ToMap.java
Normal file
|
|
@ -0,0 +1,50 @@
|
||||||
|
package nl.sander.reflective.tomap;
|
||||||
|
|
||||||
|
|
||||||
|
import nl.sander.reflective.java.ByteClassLoader;
|
||||||
|
import nl.sander.reflective.java.Java;
|
||||||
|
import org.objectweb.asm.ClassReader;
|
||||||
|
import org.objectweb.asm.ClassWriter;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
import java.util.concurrent.ConcurrentMap;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Turns any class (beans with getters/setters and records) into a HashMap.
|
||||||
|
*/
|
||||||
|
public class ToMap {
|
||||||
|
private static final ConcurrentMap<Class<?>, AbstractToMap> cache = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param value some bean or record (so use wisely if the class is not of that pattern)
|
||||||
|
* @return Map<String, Object>
|
||||||
|
* @throws Exception if the class that you want to mappify somehow can't be read from the classpath
|
||||||
|
*/
|
||||||
|
public static Map<String, Object> map(Object value) throws Exception {
|
||||||
|
try {
|
||||||
|
return cache.computeIfAbsent(value.getClass(), k ->
|
||||||
|
createNew(value)).toMap(value);
|
||||||
|
} catch (RuntimeException e) {
|
||||||
|
throw new Exception(e.getCause());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static AbstractToMap createNew(Object value) {
|
||||||
|
try{
|
||||||
|
ClassReader cr = Java.getClassReader(value);
|
||||||
|
ToMapFactory factory = new ToMapFactory();
|
||||||
|
cr.accept(factory, ClassReader.SKIP_FRAMES);
|
||||||
|
ClassWriter classWriter = new ClassWriter(ClassWriter.COMPUTE_FRAMES);
|
||||||
|
|
||||||
|
factory.classNode.accept(classWriter);
|
||||||
|
byte[] byteArray = classWriter.toByteArray();
|
||||||
|
|
||||||
|
ByteClassLoader.INSTANCE.addClass(factory.classNode.name, byteArray);
|
||||||
|
return (AbstractToMap) ByteClassLoader.INSTANCE.loadClass(factory.classNode.name).getConstructor().newInstance();}
|
||||||
|
catch (Exception e){
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
89
src/main/java/nl/sander/reflective/tomap/ToMapFactory.java
Normal file
89
src/main/java/nl/sander/reflective/tomap/ToMapFactory.java
Normal file
|
|
@ -0,0 +1,89 @@
|
||||||
|
package nl.sander.reflective.tomap;
|
||||||
|
|
||||||
|
import nl.sander.reflective.java.Java;
|
||||||
|
import org.objectweb.asm.ClassVisitor;
|
||||||
|
import org.objectweb.asm.MethodVisitor;
|
||||||
|
import org.objectweb.asm.tree.*;
|
||||||
|
|
||||||
|
import java.lang.reflect.Modifier;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
import static org.objectweb.asm.Opcodes.*;
|
||||||
|
|
||||||
|
class ToMapFactory extends ClassVisitor {
|
||||||
|
public static final String SUPER_NAME = Java.internalName(AbstractToMap.class.getName());
|
||||||
|
private boolean isRecord = false;
|
||||||
|
final ClassNode classNode = new ClassNode();
|
||||||
|
|
||||||
|
private String classToMap;
|
||||||
|
|
||||||
|
private MethodNode mappifyMethod;
|
||||||
|
|
||||||
|
|
||||||
|
public ToMapFactory() {
|
||||||
|
super(ASM9);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {
|
||||||
|
if (superName.equals("java/lang/Record")) {
|
||||||
|
isRecord = true;
|
||||||
|
}
|
||||||
|
this.classToMap = name;
|
||||||
|
classNode.name = "ToMap" + UUID.randomUUID();
|
||||||
|
classNode.superName = SUPER_NAME;
|
||||||
|
classNode.version = V11;
|
||||||
|
classNode.access = ACC_PUBLIC;
|
||||||
|
MethodNode constructor = new MethodNode(ACC_PUBLIC, Java.INIT, Java.ZERO_ARGS_VOID, null, null);
|
||||||
|
constructor.instructions.add(new VarInsnNode(ALOAD, 0));
|
||||||
|
constructor.instructions.add(new MethodInsnNode(INVOKESPECIAL, SUPER_NAME, Java.INIT, Java.ZERO_ARGS_VOID));
|
||||||
|
constructor.instructions.add(new InsnNode(RETURN));
|
||||||
|
classNode.methods.add(constructor);
|
||||||
|
|
||||||
|
mappifyMethod = new MethodNode(ACC_PUBLIC,
|
||||||
|
"toMap", "(Ljava/lang/Object;)Ljava/util/Map;", null, null);
|
||||||
|
classNode.methods.add(mappifyMethod);
|
||||||
|
add(new TypeInsnNode(NEW, "java/util/HashMap"));
|
||||||
|
add(new InsnNode(DUP));
|
||||||
|
add(new MethodInsnNode(INVOKESPECIAL, "java/util/HashMap", Java.INIT, Java.ZERO_ARGS_VOID));
|
||||||
|
add(new VarInsnNode(ASTORE, 2));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public MethodVisitor visitMethod(int access, String methodname,
|
||||||
|
String desc, String signature, String[] exceptions) {
|
||||||
|
if (!Java.hasArgs(desc) && access == Modifier.PUBLIC && isRecord ||
|
||||||
|
(methodname.startsWith("get") || (methodname.startsWith("is")) && desc.equals("()Z"))) {
|
||||||
|
visitGetter(methodname, Java.asProperty(methodname, isRecord), Java.getReturnType(desc));
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void visitGetter(String getterMethodName, String propertyName, String returnType) {
|
||||||
|
add(new VarInsnNode(ALOAD, 0));
|
||||||
|
add(new VarInsnNode(ALOAD, 2));
|
||||||
|
add(new LdcInsnNode(propertyName));
|
||||||
|
add(new VarInsnNode(ALOAD, 1));
|
||||||
|
add(new TypeInsnNode(CHECKCAST, Java.internalName(classToMap)));
|
||||||
|
add(new MethodInsnNode(INVOKEVIRTUAL, classToMap, getterMethodName, "()" + returnType));
|
||||||
|
add(new MethodInsnNode(INVOKEVIRTUAL, classNode.name, "add", "(Ljava/util/HashMap;Ljava/lang/String;"+translate(returnType)+")V"));
|
||||||
|
}
|
||||||
|
|
||||||
|
private String translate(String typeDesc){
|
||||||
|
if (typeDesc.startsWith("L")){
|
||||||
|
return Java.OBJECT;
|
||||||
|
} else {
|
||||||
|
return typeDesc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visitEnd() {
|
||||||
|
add(new VarInsnNode(ALOAD, 2));
|
||||||
|
add(new InsnNode(ARETURN));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void add(AbstractInsnNode ins) {
|
||||||
|
mappifyMethod.instructions.add(ins);
|
||||||
|
}
|
||||||
|
}
|
||||||
15
src/test/java/ExampleMappifier.java
Normal file
15
src/test/java/ExampleMappifier.java
Normal file
|
|
@ -0,0 +1,15 @@
|
||||||
|
import nl.sander.reflective.tomap.AbstractToMap;
|
||||||
|
import nl.sander.reflective.compare.PlumBean;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public class ExampleMappifier extends AbstractToMap {
|
||||||
|
|
||||||
|
public Map<String, Object> toMap(Object o) {
|
||||||
|
HashMap<String, Object> m = new HashMap<>();
|
||||||
|
add(m, "core", ((PlumBean) o).getCore());
|
||||||
|
add(m, "number", ((PlumBean) o).getNumber());
|
||||||
|
return m;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,63 +0,0 @@
|
||||||
package nl.sander.apples;
|
|
||||||
|
|
||||||
import org.junit.jupiter.api.Test;
|
|
||||||
|
|
||||||
import static org.junit.jupiter.api.Assertions.*;
|
|
||||||
|
|
||||||
class BytesTest {
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void nilEqualsNil() {
|
|
||||||
assertEquals(Result.SAME, Apples.compare((byte) 0, (byte) 0));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void nilNotEqualsSome() {
|
|
||||||
assertEquals(Result.unequal("0 != 1"), Apples.compare((byte) 0, (byte) 1));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void OneNotEqualsNil() {
|
|
||||||
assertEquals(Result.unequal("1 != 0"), Apples.compare((byte) 1, (byte) 0));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void nilByteNotEqualsOne() {
|
|
||||||
assertEquals(Result.unequal("java.lang.Byte: 0 != 1"), Apples.compare(Byte.valueOf((byte) 0), (byte) 1));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void nilNotEqualsOneByte() {
|
|
||||||
assertEquals(Result.unequal("0 != java.lang.Byte: 1"), Apples.compare((byte) 0, Byte.valueOf((byte) 1)));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void nullNotEqualsNilByte() {
|
|
||||||
assertEquals(Result.unequal("null != java.lang.Byte: 0"), Apples.compare(null, Byte.valueOf((byte) 0)));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void nullNotEqualsNil() {
|
|
||||||
assertEquals(Result.unequal("null != 0"), Apples.compare(null, (byte) 0));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void nilByteNotEqualsNull() {
|
|
||||||
assertEquals(Result.unequal("java.lang.Byte: 0 != null"), Apples.compare(Byte.valueOf((byte) 0), null));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void nilNotEqualsNull() {
|
|
||||||
assertEquals(Result.unequal("0 != null"), Apples.compare((byte) 0, null));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void byteNotEqualsString() {
|
|
||||||
assertEquals(Result.unequal("0 != \"true\""), Apples.compare((byte) 0, "true"));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void StringNotEqualsByte() {
|
|
||||||
assertEquals(Result.unequal("\"false\" != 0"), Apples.compare("false", (byte) 0));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,63 +0,0 @@
|
||||||
package nl.sander.apples;
|
|
||||||
|
|
||||||
import org.junit.jupiter.api.Test;
|
|
||||||
|
|
||||||
import static org.junit.jupiter.api.Assertions.*;
|
|
||||||
|
|
||||||
class CharsTest {
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void nilEqualsNil() {
|
|
||||||
assertTrue(Apples.compare((char) 0, (char) 0).areEqual());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void nilNotEqualsSome() {
|
|
||||||
assertEquals(Result.unequal("'A' != 'B'"),Apples.compare('A', 'B'));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void SomeNotEqualsNil() {
|
|
||||||
assertEquals(Result.unequal("'\\u0001' != '\\u0000'"),Apples.compare((char) 1, (char) 0));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void charEqualsCharacter() {
|
|
||||||
assertTrue(Apples.compare(Character.valueOf('X'), 'X').areEqual());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void nilNotEqualsOneCharacter() {
|
|
||||||
assertEquals(Result.unequal("'\\u0000' != '\\u0001'"),Apples.compare((char) 0, Character.valueOf((char) 1)));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void nullNotEqualsNilCharacter() {
|
|
||||||
assertEquals(Result.unequal("null != '\\u0000'"),Apples.compare(null, Character.valueOf((char) 0)));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void nullNotEqualsChar() {
|
|
||||||
assertEquals(Result.unequal("null != '\\u0000'"),Apples.compare(null, (char) 0));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void nilCharacterNotEqualsNull() {
|
|
||||||
assertEquals(Result.unequal("'\\u0000' != null"),Apples.compare(Character.valueOf((char) 0), null));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void charNotEqualsNull() {
|
|
||||||
assertEquals(Result.unequal("'\\u0000' != null"),Apples.compare((char) 0, null));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void charNotEqualsString() {
|
|
||||||
assertEquals(Result.unequal("'\\u0000' != \"true\""),Apples.compare((char)0, "true"));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void StringNotEqualsChar() {
|
|
||||||
assertEquals(Result.unequal("\"false\" != '\\u0000'"),Apples.compare("false", (char)0));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,89 +0,0 @@
|
||||||
package nl.sander.apples;
|
|
||||||
|
|
||||||
import org.junit.jupiter.api.Test;
|
|
||||||
|
|
||||||
import static org.junit.jupiter.api.Assertions.*;
|
|
||||||
|
|
||||||
@SuppressWarnings("ConstantValue")
|
|
||||||
class FloatsTest {
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void floatImprecisionLeft() {
|
|
||||||
assertTrue(Apples.compare(2 / 3F, 0.66F, 2).areEqual(), (2 / 3F) + " != " + 0.66F);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void floatImprecisionRight() {
|
|
||||||
assertTrue(Apples.compare(0.66F, 2 / 3F, 2).areEqual(), (2 / 3F) + " != " + 0.66F);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void nilFEqualsNilF() {
|
|
||||||
assertTrue(Apples.compare(0F, 0F).areEqual());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void nilFEqualsNilFloat() {
|
|
||||||
assertTrue(Apples.compare(0F, Float.valueOf(0)).areEqual());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void nilFEqualsNilL() {
|
|
||||||
assertTrue(Apples.compare(0F, 0L).areEqual());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void nilEqualsNilF() {
|
|
||||||
assertTrue(Apples.compare(0L, 0F).areEqual());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void nullNotEqualsSome() {
|
|
||||||
assertEquals(Result.unequal("0.0 != 1.0"), Apples.compare(0F, 1F));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void SomeNotEqualsNull() {
|
|
||||||
assertEquals(Result.unequal("1.0 != 0.0"), Apples.compare(1F, 0F));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void nilByteNotEqualsOne() {
|
|
||||||
assertEquals(Result.unequal("java.lang.Float: 0.0 != 1.0"), Apples.compare(Float.valueOf(0), 1F));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void nilNotEqualsOneByte() {
|
|
||||||
assertEquals(Result.unequal("0.0 != java.lang.Float: 1.0"), Apples.compare(0F, Float.valueOf(1)));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void nullNotEqualsNilFloat() {
|
|
||||||
assertEquals(Result.unequal("null != java.lang.Float: 0.0"), Apples.compare(null, Float.valueOf(0)));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void nullNotEqualsNil() {
|
|
||||||
assertEquals(Result.unequal("null != 0.0"), Apples.compare(null, 0F));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void nilFloatNotEqualsNull() {
|
|
||||||
assertEquals(Result.unequal("java.lang.Float: 0.0 != null"), Apples.compare(Float.valueOf(0), null));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void nilNotEqualsNull() {
|
|
||||||
assertEquals(Result.unequal("0.0 != null"), Apples.compare(0F, null));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void floatNotEqualsString() {
|
|
||||||
assertEquals(Result.unequal("0.0 != \"true\""), Apples.compare(0F, "true"));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void StringNotEqualsFloat() {
|
|
||||||
assertEquals(Result.unequal("\"false\" != 0.0"), Apples.compare("false", 0F));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,68 +0,0 @@
|
||||||
package nl.sander.apples;
|
|
||||||
|
|
||||||
import org.junit.jupiter.api.Test;
|
|
||||||
|
|
||||||
import static org.junit.jupiter.api.Assertions.*;
|
|
||||||
|
|
||||||
class LongsTest {
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void nullEqualsNull() {
|
|
||||||
assertEquals(Result.SAME, Apples.compare(0, 0));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void nullNotEqualsSome() {
|
|
||||||
assertEquals(Result.unequal("0 != 1"), Apples.compare(0, 1));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void SomeNotEqualsNull() {
|
|
||||||
assertEquals(Result.unequal("1 != 0"), Apples.compare(1, 0));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void nilLongNotEqualsOne() {
|
|
||||||
assertEquals(Result.unequal("java.lang.Long: 0 != 1"), Apples.compare(Long.valueOf(0), 1));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void nilNotEqualsOneLong() {
|
|
||||||
assertEquals(Result.unequal("0 != java.lang.Long: 1"), Apples.compare(0, Long.valueOf(1)));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void nilEqualsNilLong() {
|
|
||||||
assertTrue(Apples.compare(0, Long.valueOf(0)).areEqual());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void nullNotEqualsNilLong() {
|
|
||||||
assertEquals(Result.unequal("null != java.lang.Long: 0"), Apples.compare(null, Long.valueOf(0)));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void nullNotEqualsNil() {
|
|
||||||
assertEquals(Result.unequal("null != 0"), Apples.compare(null, 0));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void nilLongNotEqualsNull() {
|
|
||||||
assertEquals(Result.unequal("java.lang.Long: 0 != null"), Apples.compare(Long.valueOf(0), null));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void nilNotEqualsNull() {
|
|
||||||
assertEquals(Result.unequal("0 != null"), Apples.compare(0, null));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void longNotEqualsString() {
|
|
||||||
assertEquals(Result.unequal("0 != \"0\""), Apples.compare(0, "0"));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void StringNotEqualsLong() {
|
|
||||||
assertEquals(Result.unequal("\"false\" != 0"), Apples.compare("false", 0));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,73 +0,0 @@
|
||||||
package nl.sander.apples;
|
|
||||||
|
|
||||||
import org.junit.jupiter.api.Test;
|
|
||||||
|
|
||||||
import static org.junit.jupiter.api.Assertions.*;
|
|
||||||
|
|
||||||
class ShortsTest {
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void nullEqualsNull() {
|
|
||||||
assertTrue(Apples.compare((short) 0, (short) 0).areEqual());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void nullEqualsNullShort() {
|
|
||||||
assertTrue(Apples.compare((short) 0, Short.valueOf((short) 0)).areEqual());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void nullShortEqualsNull() {
|
|
||||||
assertTrue(Apples.compare(Short.valueOf((short) 0), (short) 0).areEqual());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void nullNotEqualsSome() {
|
|
||||||
assertEquals(Result.unequal("0 != 1"), Apples.compare((short) 0, (short) 1));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void SomeNotEqualsNull() {
|
|
||||||
assertEquals(Result.unequal("1 != 0"), Apples.compare((short) 1, (short) 0));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void nilshortNotEqualsOne() {
|
|
||||||
assertEquals(Result.unequal("java.lang.Short: 0 != 1"), Apples.compare(Short.valueOf((short) 0), (short) 1));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void nilNotEqualsOneshort() {
|
|
||||||
assertEquals(Result.unequal("0 != java.lang.Short: 1"), Apples.compare((short) 0, Short.valueOf((short) 1)));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void nullNotEqualsNilshort() {
|
|
||||||
assertEquals(Result.unequal("null != java.lang.Short: 0"), Apples.compare(null, Short.valueOf((short) 0)));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void nullNotEqualsNil() {
|
|
||||||
assertEquals(Result.unequal("null != 0"), Apples.compare(null, (short) 0));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void nilshortNotEqualsNull() {
|
|
||||||
assertEquals(Result.unequal("java.lang.Short: 0 != null"), Apples.compare(Short.valueOf((short) 0), null));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void nilNotEqualsNull() {
|
|
||||||
assertEquals(Result.unequal("0 != null"), Apples.compare((short) 0, null));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void shortNotEqualsString() {
|
|
||||||
assertEquals(Result.unequal("0 != \"true\""), Apples.compare((short) 0, "true"));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void StringNotEqualsshort() {
|
|
||||||
assertEquals(Result.unequal("\"false\" != 0"), Apples.compare("false", (short) 0));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
package nl.sander.apples;
|
package nl.sander.reflective.compare;
|
||||||
|
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
|
@ -11,7 +11,7 @@ public class BeansTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testBeans() {
|
void testBeans() {
|
||||||
Result comparison = Apples.compare(new PlumBean("small", "red", true, 1, 1.0F, Storage.HIGH, (byte) 1, List.of(new Shop("tesco"))),
|
Result comparison = Compare.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"))));
|
new PlumBean("large", "green", true, 1, 1.0F, Storage.LOW, (byte) 1, List.of(new Shop("asda"))));
|
||||||
|
|
||||||
assertFalse(comparison.areEqual());
|
assertFalse(comparison.areEqual());
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
package nl.sander.apples;
|
package nl.sander.reflective.compare;
|
||||||
|
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
|
@ -8,103 +8,103 @@ class BooleansTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void falseEqualsFalse() {
|
void falseEqualsFalse() {
|
||||||
assertTrue(Apples.compare(false, false).areEqual());
|
assertTrue(Compare.compare(false, false).areEqual());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void falseEqualsBooleanFalse() {
|
void falseEqualsBooleanFalse() {
|
||||||
assertTrue(Apples.compare(false, Boolean.FALSE).areEqual());
|
assertTrue(Compare.compare(false, Boolean.FALSE).areEqual());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void trueEqualsBooleanTrue() {
|
void trueEqualsBooleanTrue() {
|
||||||
assertTrue(Apples.compare(true, Boolean.TRUE).areEqual());
|
assertTrue(Compare.compare(true, Boolean.TRUE).areEqual());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void trueEqualsTrue() {
|
void trueEqualsTrue() {
|
||||||
assertTrue(Apples.compare(true, true).areEqual());
|
assertTrue(Compare.compare(true, true).areEqual());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void falseNotEqualsTrue() {
|
void falseNotEqualsTrue() {
|
||||||
assertEquals(Result.unequal("false != true"), Apples.compare(false, true));
|
assertEquals(Result.unequal("false != true"), Compare.compare(false, true));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void trueNotEqualsFalse() {
|
void trueNotEqualsFalse() {
|
||||||
assertEquals(Result.unequal("true != false"), Apples.compare(true, false));
|
assertEquals(Result.unequal("true != false"), Compare.compare(true, false));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void falseNotEqualsTrueBoolean() {
|
void falseNotEqualsTrueBoolean() {
|
||||||
assertEquals(Result.unequal("false != java.lang.Boolean: true"), Apples.compare(false, Boolean.valueOf(true)));
|
assertEquals(Result.unequal("false != java.lang.Boolean: true"), Compare.compare(false, Boolean.valueOf(true)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void trueNotEqualsFalseBoolean() {
|
void trueNotEqualsFalseBoolean() {
|
||||||
assertEquals(Result.unequal("true != java.lang.Boolean: false"), Apples.compare(true, Boolean.valueOf(false)));
|
assertEquals(Result.unequal("true != java.lang.Boolean: false"), Compare.compare(true, Boolean.valueOf(false)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void falseBooleanNotEqualsTrue() {
|
void falseBooleanNotEqualsTrue() {
|
||||||
assertEquals(Result.unequal("java.lang.Boolean: false != true"), Apples.compare(Boolean.valueOf(false), true));
|
assertEquals(Result.unequal("java.lang.Boolean: false != true"), Compare.compare(Boolean.valueOf(false), true));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void trueBooleanNotEqualsFalse() {
|
void trueBooleanNotEqualsFalse() {
|
||||||
assertEquals(Result.unequal("java.lang.Boolean: true != false"), Apples.compare(Boolean.valueOf(true), false));
|
assertEquals(Result.unequal("java.lang.Boolean: true != false"), Compare.compare(Boolean.valueOf(true), false));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void nullNotEqualsTrue() {
|
void nullNotEqualsTrue() {
|
||||||
assertEquals(Result.unequal("null != true"), Apples.compare(null, true));
|
assertEquals(Result.unequal("null != true"), Compare.compare(null, true));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void nullNotEqualsFalse() {
|
void nullNotEqualsFalse() {
|
||||||
assertEquals(Result.unequal("null != false"), Apples.compare(null, false));
|
assertEquals(Result.unequal("null != false"), Compare.compare(null, false));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void trueNotEqualsNull() {
|
void trueNotEqualsNull() {
|
||||||
assertEquals(Result.unequal("true != null"), Apples.compare(true, null));
|
assertEquals(Result.unequal("true != null"), Compare.compare(true, null));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void falseNotEqualsNull() {
|
void falseNotEqualsNull() {
|
||||||
assertEquals(Result.unequal("false != null"), Apples.compare(false, null));
|
assertEquals(Result.unequal("false != null"), Compare.compare(false, null));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void trueNotEqualsString() {
|
void trueNotEqualsString() {
|
||||||
assertEquals(Result.unequal("true != \"true\""), Apples.compare(true, "true"));
|
assertEquals(Result.unequal("true != \"true\""), Compare.compare(true, "true"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void StringNotEqualsFalse() {
|
void StringNotEqualsFalse() {
|
||||||
assertEquals(Result.unequal("\"false\" != false"), Apples.compare("false", false));
|
assertEquals(Result.unequal("\"false\" != false"), Compare.compare("false", false));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void nullNotEqualsTrueBoolean() {
|
void nullNotEqualsTrueBoolean() {
|
||||||
assertEquals(Result.unequal("null != java.lang.Boolean: true"), Apples.compare(null, Boolean.TRUE));
|
assertEquals(Result.unequal("null != java.lang.Boolean: true"), Compare.compare(null, Boolean.TRUE));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void nullNotEqualsFalseBoolean() {
|
void nullNotEqualsFalseBoolean() {
|
||||||
assertEquals(Result.unequal("null != java.lang.Boolean: false"), Apples.compare(null, Boolean.FALSE));
|
assertEquals(Result.unequal("null != java.lang.Boolean: false"), Compare.compare(null, Boolean.FALSE));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void trueBooleanNotEqualsNull() {
|
void trueBooleanNotEqualsNull() {
|
||||||
assertEquals(Result.unequal("java.lang.Boolean: true != null"), Apples.compare(Boolean.TRUE, null));
|
assertEquals(Result.unequal("java.lang.Boolean: true != null"), Compare.compare(Boolean.TRUE, null));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void falseBooleanNotEqualsNull() {
|
void falseBooleanNotEqualsNull() {
|
||||||
assertEquals(Result.unequal("java.lang.Boolean: false != null"), Apples.compare(Boolean.FALSE, null));
|
assertEquals(Result.unequal("java.lang.Boolean: false != null"), Compare.compare(Boolean.FALSE, null));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
63
src/test/java/nl/sander/reflective/compare/BytesTest.java
Normal file
63
src/test/java/nl/sander/reflective/compare/BytesTest.java
Normal file
|
|
@ -0,0 +1,63 @@
|
||||||
|
package nl.sander.reflective.compare;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
|
|
||||||
|
class BytesTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void nilEqualsNil() {
|
||||||
|
assertEquals(Result.SAME, Compare.compare((byte) 0, (byte) 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void nilNotEqualsSome() {
|
||||||
|
assertEquals(Result.unequal("0 != 1"), Compare.compare((byte) 0, (byte) 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void OneNotEqualsNil() {
|
||||||
|
assertEquals(Result.unequal("1 != 0"), Compare.compare((byte) 1, (byte) 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void nilByteNotEqualsOne() {
|
||||||
|
assertEquals(Result.unequal("java.lang.Byte: 0 != 1"), Compare.compare(Byte.valueOf((byte) 0), (byte) 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void nilNotEqualsOneByte() {
|
||||||
|
assertEquals(Result.unequal("0 != java.lang.Byte: 1"), Compare.compare((byte) 0, Byte.valueOf((byte) 1)));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void nullNotEqualsNilByte() {
|
||||||
|
assertEquals(Result.unequal("null != java.lang.Byte: 0"), Compare.compare(null, Byte.valueOf((byte) 0)));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void nullNotEqualsNil() {
|
||||||
|
assertEquals(Result.unequal("null != 0"), Compare.compare(null, (byte) 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void nilByteNotEqualsNull() {
|
||||||
|
assertEquals(Result.unequal("java.lang.Byte: 0 != null"), Compare.compare(Byte.valueOf((byte) 0), null));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void nilNotEqualsNull() {
|
||||||
|
assertEquals(Result.unequal("0 != null"), Compare.compare((byte) 0, null));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void byteNotEqualsString() {
|
||||||
|
assertEquals(Result.unequal("0 != \"true\""), Compare.compare((byte) 0, "true"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void StringNotEqualsByte() {
|
||||||
|
assertEquals(Result.unequal("\"false\" != 0"), Compare.compare("false", (byte) 0));
|
||||||
|
}
|
||||||
|
}
|
||||||
63
src/test/java/nl/sander/reflective/compare/CharsTest.java
Normal file
63
src/test/java/nl/sander/reflective/compare/CharsTest.java
Normal file
|
|
@ -0,0 +1,63 @@
|
||||||
|
package nl.sander.reflective.compare;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
|
|
||||||
|
class CharsTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void nilEqualsNil() {
|
||||||
|
assertTrue(Compare.compare((char) 0, (char) 0).areEqual());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void nilNotEqualsSome() {
|
||||||
|
assertEquals(Result.unequal("'A' != 'B'"), Compare.compare('A', 'B'));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void SomeNotEqualsNil() {
|
||||||
|
assertEquals(Result.unequal("'\\u0001' != '\\u0000'"), Compare.compare((char) 1, (char) 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void charEqualsCharacter() {
|
||||||
|
assertTrue(Compare.compare(Character.valueOf('X'), 'X').areEqual());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void nilNotEqualsOneCharacter() {
|
||||||
|
assertEquals(Result.unequal("'\\u0000' != '\\u0001'"), Compare.compare((char) 0, Character.valueOf((char) 1)));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void nullNotEqualsNilCharacter() {
|
||||||
|
assertEquals(Result.unequal("null != '\\u0000'"), Compare.compare(null, Character.valueOf((char) 0)));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void nullNotEqualsChar() {
|
||||||
|
assertEquals(Result.unequal("null != '\\u0000'"), Compare.compare(null, (char) 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void nilCharacterNotEqualsNull() {
|
||||||
|
assertEquals(Result.unequal("'\\u0000' != null"), Compare.compare(Character.valueOf((char) 0), null));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void charNotEqualsNull() {
|
||||||
|
assertEquals(Result.unequal("'\\u0000' != null"), Compare.compare((char) 0, null));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void charNotEqualsString() {
|
||||||
|
assertEquals(Result.unequal("'\\u0000' != \"true\""), Compare.compare((char) 0, "true"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void StringNotEqualsChar() {
|
||||||
|
assertEquals(Result.unequal("\"false\" != '\\u0000'"), Compare.compare("false", (char) 0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,28 @@
|
||||||
|
package nl.sander.reflective.compare;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||||
|
|
||||||
|
public class DifferentTypesTest {
|
||||||
|
@Test
|
||||||
|
void testAppleAndOrange() {
|
||||||
|
assertTrue(Compare.any(new Apple("orange"), new Orange("orange")).areEqual());
|
||||||
|
}
|
||||||
|
|
||||||
|
class Apple {
|
||||||
|
final String color;
|
||||||
|
|
||||||
|
Apple(String color) {
|
||||||
|
this.color = color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Orange {
|
||||||
|
final String color;
|
||||||
|
|
||||||
|
Orange(String color) {
|
||||||
|
this.color = color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
package nl.sander.apples;
|
package nl.sander.reflective.compare;
|
||||||
|
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
|
@ -8,77 +8,77 @@ class DoublesTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void floatImprecisionLeft() {
|
void floatImprecisionLeft() {
|
||||||
assertTrue(Apples.compare(2 / 3.0, 0.66, 2).areEqual(), (2 / 3) + " != " + 0.66);
|
assertTrue(Compare.compare(2 / 3.0, 0.66, 2).areEqual(), (2 / 3) + " != " + 0.66);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void floatImprecisionRight() {
|
void floatImprecisionRight() {
|
||||||
assertTrue(Apples.compare(0.66, 2 / 3D, 2).areEqual(), (2 / 3D) + " != " + 0.66);
|
assertTrue(Compare.compare(0.66, 2 / 3D, 2).areEqual(), (2 / 3D) + " != " + 0.66);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void nilFEqualsNilF() {
|
void nilFEqualsNilF() {
|
||||||
assertTrue(Apples.compare(0.0, .0).areEqual());
|
assertTrue(Compare.compare(0.0, .0).areEqual());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void nilFEqualsNilL() {
|
void nilFEqualsNilL() {
|
||||||
assertTrue(Apples.compare(0.0, 0L).areEqual());
|
assertTrue(Compare.compare(0.0, 0L).areEqual());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void nilEqualsNilF() {
|
void nilEqualsNilF() {
|
||||||
assertTrue(Apples.compare(0L, 0.0).areEqual());
|
assertTrue(Compare.compare(0L, 0.0).areEqual());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void nullNotEqualsSome() {
|
void nullNotEqualsSome() {
|
||||||
assertEquals(Result.unequal("0.0 != 1.0"), Apples.compare(0.0, 1.0F));
|
assertEquals(Result.unequal("0.0 != 1.0"), Compare.compare(0.0, 1.0F));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void SomeNotEqualsNull() {
|
void SomeNotEqualsNull() {
|
||||||
assertEquals(Result.unequal("1.0 != 0.0"), Apples.compare(1.0, .0));
|
assertEquals(Result.unequal("1.0 != 0.0"), Compare.compare(1.0, .0));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void nilDoubleNotEqualsOne() {
|
void nilDoubleNotEqualsOne() {
|
||||||
assertEquals(Result.unequal("java.lang.Double: 0.0 != 1.0"), Apples.compare(Double.valueOf(0), 1F));
|
assertEquals(Result.unequal("java.lang.Double: 0.0 != 1.0"), Compare.compare(Double.valueOf(0), 1F));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void nilNotEqualsOneDouble() {
|
void nilNotEqualsOneDouble() {
|
||||||
assertEquals(Result.unequal("0.0 != java.lang.Double: 1.0"), Apples.compare(0F, Double.valueOf(1)));
|
assertEquals(Result.unequal("0.0 != java.lang.Double: 1.0"), Compare.compare(0F, Double.valueOf(1)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void nullNotEqualsNilDouble() {
|
void nullNotEqualsNilDouble() {
|
||||||
assertEquals(Result.unequal("null != java.lang.Double: 0.0"), Apples.compare(null, Double.valueOf(0)));
|
assertEquals(Result.unequal("null != java.lang.Double: 0.0"), Compare.compare(null, Double.valueOf(0)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void nullNotEqualsNil() {
|
void nullNotEqualsNil() {
|
||||||
assertEquals(Result.unequal("null != 0.0"), Apples.compare(null, .0));
|
assertEquals(Result.unequal("null != 0.0"), Compare.compare(null, .0));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void nilDoubleNotEqualsNull() {
|
void nilDoubleNotEqualsNull() {
|
||||||
assertEquals(Result.unequal("java.lang.Double: 0.0 != null"), Apples.compare(Double.valueOf(0), null));
|
assertEquals(Result.unequal("java.lang.Double: 0.0 != null"), Compare.compare(Double.valueOf(0), null));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void nilNotEqualsNull() {
|
void nilNotEqualsNull() {
|
||||||
assertEquals(Result.unequal("0.0 != null"), Apples.compare(.0, null));
|
assertEquals(Result.unequal("0.0 != null"), Compare.compare(.0, null));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void doubleNotEqualsString() {
|
void doubleNotEqualsString() {
|
||||||
assertEquals(Result.unequal("0.0 != \"0\""), Apples.compare(.0, "0"));
|
assertEquals(Result.unequal("0.0 != \"0\""), Compare.compare(.0, "0"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void StringNotEqualsDouble() {
|
void StringNotEqualsDouble() {
|
||||||
assertEquals(Result.unequal("\"0\" != 0.0"), Apples.compare("0", .0));
|
assertEquals(Result.unequal("\"0\" != 0.0"), Compare.compare("0", .0));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
88
src/test/java/nl/sander/reflective/compare/FloatsTest.java
Normal file
88
src/test/java/nl/sander/reflective/compare/FloatsTest.java
Normal file
|
|
@ -0,0 +1,88 @@
|
||||||
|
package nl.sander.reflective.compare;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
|
|
||||||
|
class FloatsTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void floatImprecisionLeft() {
|
||||||
|
assertTrue(Compare.compare(2 / 3F, 0.66F, 2).areEqual(), (2 / 3F) + " != " + 0.66F);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void floatImprecisionRight() {
|
||||||
|
assertTrue(Compare.compare(0.66F, 2 / 3F, 2).areEqual(), (2 / 3F) + " != " + 0.66F);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void nilFEqualsNilF() {
|
||||||
|
assertTrue(Compare.compare(0F, 0F).areEqual());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void nilFEqualsNilFloat() {
|
||||||
|
assertTrue(Compare.compare(0F, Float.valueOf(0)).areEqual());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void nilFEqualsNilL() {
|
||||||
|
assertTrue(Compare.compare(0F, 0L).areEqual());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void nilEqualsNilF() {
|
||||||
|
assertTrue(Compare.compare(0L, 0F).areEqual());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void nullNotEqualsSome() {
|
||||||
|
assertEquals(Result.unequal("0.0 != 1.0"), Compare.compare(0F, 1F));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void SomeNotEqualsNull() {
|
||||||
|
assertEquals(Result.unequal("1.0 != 0.0"), Compare.compare(1F, 0F));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void nilByteNotEqualsOne() {
|
||||||
|
assertEquals(Result.unequal("java.lang.Float: 0.0 != 1.0"), Compare.compare(Float.valueOf(0), 1F));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void nilNotEqualsOneByte() {
|
||||||
|
assertEquals(Result.unequal("0.0 != java.lang.Float: 1.0"), Compare.compare(0F, Float.valueOf(1)));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void nullNotEqualsNilFloat() {
|
||||||
|
assertEquals(Result.unequal("null != java.lang.Float: 0.0"), Compare.compare(null, Float.valueOf(0)));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void nullNotEqualsNil() {
|
||||||
|
assertEquals(Result.unequal("null != 0.0"), Compare.compare(null, 0F));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void nilFloatNotEqualsNull() {
|
||||||
|
assertEquals(Result.unequal("java.lang.Float: 0.0 != null"), Compare.compare(Float.valueOf(0), null));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void nilNotEqualsNull() {
|
||||||
|
assertEquals(Result.unequal("0.0 != null"), Compare.compare(0F, null));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void floatNotEqualsString() {
|
||||||
|
assertEquals(Result.unequal("0.0 != \"true\""), Compare.compare(0F, "true"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void StringNotEqualsFloat() {
|
||||||
|
assertEquals(Result.unequal("\"false\" != 0.0"), Compare.compare("false", 0F));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
package nl.sander.apples;
|
package nl.sander.reflective.compare;
|
||||||
|
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
|
@ -8,66 +8,66 @@ class IntsTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void nilEqualsNil() {
|
void nilEqualsNil() {
|
||||||
assertEquals(Result.SAME, Apples.compare(0, 0));
|
assertEquals(Result.SAME, Compare.compare(0, 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void nilEqualsNilInteger() {
|
void nilEqualsNilInteger() {
|
||||||
assertEquals(Result.SAME, Apples.compare(0, Integer.valueOf(0)));
|
assertEquals(Result.SAME, Compare.compare(0, Integer.valueOf(0)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void nilIntegerEqualsNil() {
|
void nilIntegerEqualsNil() {
|
||||||
assertEquals(Result.SAME, Apples.compare(Integer.valueOf(0), 0));
|
assertEquals(Result.SAME, Compare.compare(Integer.valueOf(0), 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void nullNotEqualsSome() {
|
void nullNotEqualsSome() {
|
||||||
assertEquals(Result.unequal("0 != 1"), Apples.compare(0, 1));
|
assertEquals(Result.unequal("0 != 1"), Compare.compare(0, 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void SomeNotEqualsNull() {
|
void SomeNotEqualsNull() {
|
||||||
assertEquals(Result.unequal("1 != 0"), Apples.compare(1, 0));
|
assertEquals(Result.unequal("1 != 0"), Compare.compare(1, 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void nilByteNotEqualsOne() {
|
void nilByteNotEqualsOne() {
|
||||||
assertEquals(Result.unequal("java.lang.Integer: 0 != 1"), Apples.compare(Integer.valueOf(0), 1));
|
assertEquals(Result.unequal("java.lang.Integer: 0 != 1"), Compare.compare(Integer.valueOf(0), 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void nilNotEqualsOneByte() {
|
void nilNotEqualsOneByte() {
|
||||||
assertEquals(Result.unequal("0 != java.lang.Integer: 1"), Apples.compare(0, Integer.valueOf(1)));
|
assertEquals(Result.unequal("0 != java.lang.Integer: 1"), Compare.compare(0, Integer.valueOf(1)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void nullNotEqualsNilByte() {
|
void nullNotEqualsNilByte() {
|
||||||
assertEquals(Result.unequal("null != java.lang.Integer: 0"), Apples.compare(null, Integer.valueOf(0)));
|
assertEquals(Result.unequal("null != java.lang.Integer: 0"), Compare.compare(null, Integer.valueOf(0)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void nullNotEqualsNil() {
|
void nullNotEqualsNil() {
|
||||||
assertEquals(Result.unequal("null != 0"), Apples.compare(null, 0));
|
assertEquals(Result.unequal("null != 0"), Compare.compare(null, 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void nilByteNotEqualsNull() {
|
void nilByteNotEqualsNull() {
|
||||||
assertEquals(Result.unequal("java.lang.Integer: 0 != null"), Apples.compare(Integer.valueOf(0), null));
|
assertEquals(Result.unequal("java.lang.Integer: 0 != null"), Compare.compare(Integer.valueOf(0), null));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void nilNotEqualsNull() {
|
void nilNotEqualsNull() {
|
||||||
assertEquals(Result.unequal("0 != null"), Apples.compare(0, null));
|
assertEquals(Result.unequal("0 != null"), Compare.compare(0, null));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void intNotEqualsString() {
|
void intNotEqualsString() {
|
||||||
assertEquals(Result.unequal("0 != \"true\""), Apples.compare(0, "true"));
|
assertEquals(Result.unequal("0 != \"true\""), Compare.compare(0, "true"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void StringNotEqualsInt() {
|
void StringNotEqualsInt() {
|
||||||
assertEquals(Result.unequal("\"0\" != 0"), Apples.compare("0", 0));
|
assertEquals(Result.unequal("\"0\" != 0"), Compare.compare("0", 0));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
68
src/test/java/nl/sander/reflective/compare/LongsTest.java
Normal file
68
src/test/java/nl/sander/reflective/compare/LongsTest.java
Normal file
|
|
@ -0,0 +1,68 @@
|
||||||
|
package nl.sander.reflective.compare;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
|
|
||||||
|
class LongsTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void nullEqualsNull() {
|
||||||
|
assertEquals(Result.SAME, Compare.compare(0, 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void nullNotEqualsSome() {
|
||||||
|
assertEquals(Result.unequal("0 != 1"), Compare.compare(0, 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void SomeNotEqualsNull() {
|
||||||
|
assertEquals(Result.unequal("1 != 0"), Compare.compare(1, 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void nilLongNotEqualsOne() {
|
||||||
|
assertEquals(Result.unequal("java.lang.Long: 0 != 1"), Compare.compare(Long.valueOf(0), 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void nilNotEqualsOneLong() {
|
||||||
|
assertEquals(Result.unequal("0 != java.lang.Long: 1"), Compare.compare(0, Long.valueOf(1)));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void nilEqualsNilLong() {
|
||||||
|
assertTrue(Compare.compare(0, Long.valueOf(0)).areEqual());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void nullNotEqualsNilLong() {
|
||||||
|
assertEquals(Result.unequal("null != java.lang.Long: 0"), Compare.compare(null, Long.valueOf(0)));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void nullNotEqualsNil() {
|
||||||
|
assertEquals(Result.unequal("null != 0"), Compare.compare(null, 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void nilLongNotEqualsNull() {
|
||||||
|
assertEquals(Result.unequal("java.lang.Long: 0 != null"), Compare.compare(Long.valueOf(0), null));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void nilNotEqualsNull() {
|
||||||
|
assertEquals(Result.unequal("0 != null"), Compare.compare(0, null));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void longNotEqualsString() {
|
||||||
|
assertEquals(Result.unequal("0 != \"0\""), Compare.compare(0, "0"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void StringNotEqualsLong() {
|
||||||
|
assertEquals(Result.unequal("\"false\" != 0"), Compare.compare("false", 0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
package nl.sander.apples;
|
package nl.sander.reflective.compare;
|
||||||
|
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
|
@ -11,32 +11,32 @@ class ObjectsTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void nullEqualsNull() {
|
void nullEqualsNull() {
|
||||||
assertTrue(Apples.compare(null, null).areEqual());
|
assertTrue(Compare.compare(null, null).areEqual());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void nullNotEqualsSome() {
|
void nullNotEqualsSome() {
|
||||||
assertEquals(Result.unequal("null != \"some\""), Apples.compare(null, "some"));
|
assertEquals(Result.unequal("null != \"some\""), Compare.compare(null, "some"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void SomeNotEqualsNull() {
|
void SomeNotEqualsNull() {
|
||||||
assertEquals(Result.unequal("\"some\" != null"), Apples.compare("some", null));
|
assertEquals(Result.unequal("\"some\" != null"), Compare.compare("some", null));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void differentClass() {
|
void differentClass() {
|
||||||
assertEquals(Result.unequal("\"1\" != java.lang.Integer: 1"), Apples.compare("1", Integer.valueOf(1)));
|
assertEquals(Result.unequal("\"1\" != java.lang.Integer: 1"), Compare.compare("1", Integer.valueOf(1)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void sameKeysAndValues() {
|
void sameKeysAndValues() {
|
||||||
assertTrue(Apples.compare("map", Map.of("a", 1, "b", 2), Map.of("b", 2, "a", 1)).areEqual());
|
assertTrue(Compare.compare("map", Map.of("a", 1, "b", 2), Map.of("b", 2, "a", 1)).areEqual());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void differentKeysAndValues() {
|
void differentKeysAndValues() {
|
||||||
Result result = Apples.compare("map", Map.of("a", 2, "b", 1), Map.of("b", 2, "a", 1));
|
Result result = Compare.compare("map", Map.of("a", 2, "b", 1), Map.of("b", 2, "a", 1));
|
||||||
assertFalse(result.areEqual());
|
assertFalse(result.areEqual());
|
||||||
assertTrue(result.getDiffs().contains("for map[b]: 1 != 2"));
|
assertTrue(result.getDiffs().contains("for map[b]: 1 != 2"));
|
||||||
assertTrue(result.getDiffs().contains("for map[a]: 2 != 1"));
|
assertTrue(result.getDiffs().contains("for map[a]: 2 != 1"));
|
||||||
|
|
@ -44,14 +44,14 @@ class ObjectsTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void bigDecimals() {
|
void bigDecimals() {
|
||||||
Result result = Apples.compare(BigDecimal.valueOf(0), BigDecimal.valueOf(1));
|
Result result = Compare.compare(BigDecimal.valueOf(0), BigDecimal.valueOf(1));
|
||||||
assertFalse(result.areEqual());
|
assertFalse(result.areEqual());
|
||||||
assertEquals("0 != 1", result.getDiffs().get(0));
|
assertEquals("0 != 1", result.getDiffs().get(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void enums() {
|
void enums() {
|
||||||
Result result = Apples.compare(Storage.HIGH, Storage.LOW);
|
Result result = Compare.compare(Storage.HIGH, Storage.LOW);
|
||||||
assertFalse(result.areEqual());
|
assertFalse(result.areEqual());
|
||||||
assertEquals("HIGH != LOW", result.getDiffs().get(0));
|
assertEquals("HIGH != LOW", result.getDiffs().get(0));
|
||||||
}
|
}
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
package nl.sander.apples;
|
package nl.sander.reflective.compare;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
package nl.sander.apples;
|
package nl.sander.reflective.compare;
|
||||||
|
|
||||||
public class Shop {
|
public class Shop {
|
||||||
private final String name;
|
private final String name;
|
||||||
73
src/test/java/nl/sander/reflective/compare/ShortsTest.java
Normal file
73
src/test/java/nl/sander/reflective/compare/ShortsTest.java
Normal file
|
|
@ -0,0 +1,73 @@
|
||||||
|
package nl.sander.reflective.compare;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
|
|
||||||
|
class ShortsTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void nullEqualsNull() {
|
||||||
|
assertTrue(Compare.compare((short) 0, (short) 0).areEqual());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void nullEqualsNullShort() {
|
||||||
|
assertTrue(Compare.compare((short) 0, Short.valueOf((short) 0)).areEqual());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void nullShortEqualsNull() {
|
||||||
|
assertTrue(Compare.compare(Short.valueOf((short) 0), (short) 0).areEqual());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void nullNotEqualsSome() {
|
||||||
|
assertEquals(Result.unequal("0 != 1"), Compare.compare((short) 0, (short) 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void SomeNotEqualsNull() {
|
||||||
|
assertEquals(Result.unequal("1 != 0"), Compare.compare((short) 1, (short) 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void nilshortNotEqualsOne() {
|
||||||
|
assertEquals(Result.unequal("java.lang.Short: 0 != 1"), Compare.compare(Short.valueOf((short) 0), (short) 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void nilNotEqualsOneshort() {
|
||||||
|
assertEquals(Result.unequal("0 != java.lang.Short: 1"), Compare.compare((short) 0, Short.valueOf((short) 1)));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void nullNotEqualsNilshort() {
|
||||||
|
assertEquals(Result.unequal("null != java.lang.Short: 0"), Compare.compare(null, Short.valueOf((short) 0)));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void nullNotEqualsNil() {
|
||||||
|
assertEquals(Result.unequal("null != 0"), Compare.compare(null, (short) 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void nilshortNotEqualsNull() {
|
||||||
|
assertEquals(Result.unequal("java.lang.Short: 0 != null"), Compare.compare(Short.valueOf((short) 0), null));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void nilNotEqualsNull() {
|
||||||
|
assertEquals(Result.unequal("0 != null"), Compare.compare((short) 0, null));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void shortNotEqualsString() {
|
||||||
|
assertEquals(Result.unequal("0 != \"true\""), Compare.compare((short) 0, "true"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void StringNotEqualsshort() {
|
||||||
|
assertEquals(Result.unequal("\"false\" != 0"), Compare.compare("false", (short) 0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
package nl.sander.apples;
|
package nl.sander.reflective.compare;
|
||||||
|
|
||||||
public enum Storage {
|
public enum Storage {
|
||||||
HIGH,
|
HIGH,
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
package nl.sander.apples;
|
package nl.sander.reflective.compare;
|
||||||
|
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
|
@ -7,7 +7,7 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||||
class StringTest {
|
class StringTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void test() {
|
void test() {
|
||||||
assertTrue(Apples.compare("left", "left").areEqual());
|
assertTrue(Compare.compare("left", "left").areEqual());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
30
src/test/java/nl/sander/reflective/tomap/ToMapTest.java
Normal file
30
src/test/java/nl/sander/reflective/tomap/ToMapTest.java
Normal file
|
|
@ -0,0 +1,30 @@
|
||||||
|
package nl.sander.reflective.tomap;
|
||||||
|
|
||||||
|
import nl.sander.reflective.compare.PlumBean;
|
||||||
|
import nl.sander.reflective.compare.Shop;
|
||||||
|
import nl.sander.reflective.compare.Storage;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
|
|
||||||
|
class ToMapTest {
|
||||||
|
@Test
|
||||||
|
void testBeans() throws Exception {
|
||||||
|
Map<String,Object> map = ToMap.map(new PlumBean("small", "red", true, 1, 1.0F, Storage.HIGH, (byte) 1, List.of(new Shop("tesco"))));
|
||||||
|
assertEquals("small", map.get("core"));
|
||||||
|
assertEquals("red", map.get("peel"));
|
||||||
|
assertEquals(true, map.get("juicy"));
|
||||||
|
assertEquals(1, map.get("number"));
|
||||||
|
assertEquals(1.0F, map.get("price"));
|
||||||
|
assertEquals(Storage.HIGH, map.get("storage"));
|
||||||
|
assertEquals((byte)1, map.get("cores"));
|
||||||
|
Object shops = map.get("shops");
|
||||||
|
assertTrue(shops instanceof List);
|
||||||
|
List<Shop> shopsList = (List<Shop>) shops;
|
||||||
|
assertEquals(1, shopsList.size());
|
||||||
|
assertEquals("tesco", shopsList.get(0).getName());
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Add table
Reference in a new issue