/** * Asserts, using reflection, that all methods with frameless arguments, such as * {@code Tuple3DReadOnly}, are overloaded with their frame type equivalent, i.e. * {@code Tuple2DBasics} is to be overloaded with {@code FrameTuple2D}. * * @param typeWithFrameMethods refers to the type to be tested. This asserts that * {@code typeWithFrameMethods} properly has all the methods necessary to properly * overload {@code typeWithFramelessMethods}. * @param typeWithFramelessMethods refers to the type declaring methods with frameless objects * that are to be overloaded. * @param assertAllCombinations when {@code false}, this asserts that for each method in * {@code typeWithFramelessMethods} there is one overloading method in * {@code typeWithFrameMethods} with all the arguments using the equivalent frame type. * When {@code true}, this asserts that for each method in * {@code typeWithFramelessArguments}, {@code typeWithFrameMethods} overloads it with * all the possible combinations of frame & frameless arguments, except for the * original frameless signature. */ public static void assertOverloadingWithFrameObjects(Class<?> typeWithFrameMethods, Class<?> typeWithFramelessMethods, boolean assertAllCombinations) { assertOverloadingWithFrameObjects(typeWithFrameMethods, typeWithFramelessMethods, assertAllCombinations, 1); }
/** * Asserts, using reflection, that the methods, that are public and static, in * {@code typeHoldingStaticMethodsToTest} are properly checking and/or setting reference frames * of their arguments. * <p> * This assertion expects methods to be declaring arguments as read-only to inform that they are * used as input only, and as mutable to inform that they are the output(s). * </p> * <p> * Note that this does not perform any assertion for methods with only 1 frame argument. * </p> * <p> * This expects methods to throw a {@link ReferenceFrameMismatchException} to indicate that the * operation cannot be performed because at least two arguments are expressed in a different * reference frame. * </p> * * @param typeDeclaringStaticMethodsToTest the type in which the methods are to be tested. * @throws Throwable if an unexpected throwable has been thrown by a method at invocation time. */ public static void assertStaticMethodsCheckReferenceFrame(Class<?> typeDeclaringStaticMethodsToTest) throws Throwable { assertStaticMethodsCheckReferenceFrame(typeDeclaringStaticMethodsToTest, m -> true); }
/** * Assuming the type {@code typeWithFrameMethodsToTest} declares the same static methods as * declared in {@code typeWithFramlessMethods} with the difference of dealing with reference * frame holders, this method asserts that the methods in {@code typeWithFrameMethodsToTest} does * not change the underlying algorithms. * <p> * For each method declared in {@code typeWithFrameMethodsToTest}, this methods searched for the * equivalent method in {@code typeWithFramelessMethods} and the methods from both classes are * invoked to compare the output. * </p> * * @param typeWithFrameMethodsToTest the type in which the methods are to be tested. * @param typeWithFramelessMethods the type declaring the methods against which the methods from * {@code typeWithFrameMethodsToTest} are to be compared. */ public static void assertStaticMethodsPreserveFunctionality(Class<?> typeWithFrameMethodsToTest, Class<?> typeWithFramelessMethods) { assertStaticMethodsPreserveFunctionality(typeWithFrameMethodsToTest, typeWithFramelessMethods, m -> true); }
private static Object instantiateParameterType(ReferenceFrame frame, Class<?> parameterType) { Object object = createFrameObject(parameterType, frame); if (object != null) return object; object = createFramelessObject(parameterType); if (object != null) return object; return newInstanceOf(parameterType); }
List<Method> framelessMethods = keepOnlyMethodsWithAtLeastNFramelessArguments(typeWithFramelessMethods.getMethods(), minNumberOfFramelessArguments); List<Class<?>[]> expectedMethodSignatures = createExpectedMethodSignaturesWithFrameArgument(framelessMethod, assertAllCombinations); assertMethodOverloadedWithSpecificSignature(typeWithFrameMethods, typeWithFramelessMethods, framelessMethod, expectedMethodSignature, typeWithFrameMethods);
List<Method> frameMethods = keepOnlyMethodsWithAtLeastNFrameArguments(typeWithFrameMethodsToTest.getMethods(), 0); if (isFrameType(frameMethodParameterTypes[i])) framelessMethodParameterTypes[i] = findCorrespondingFramelessType(frameMethodParameterTypes[i]); else framelessMethodParameterTypes[i] = frameMethodParameterTypes[i]; Object[] frameMethodParameters = instantiateParameterTypes(worldFrame, frameMethodParameterTypes); Object[] framelessMethodParameters = clone(frameMethodParameters); Throwable expectedException = null; Object framelessMethodReturnObject = null; framelessMethodReturnObject = invokeStaticMethod(framelessMethod, framelessMethodParameters); frameMethodReturnObject = invokeStaticMethod(frameMethod, frameMethodParameters); message += "The method: " + getMethodSimpleName(frameMethod); message += "\ndid not throw the same exception as the original method: " + getMethodSimpleName(framelessMethod); message += "\nExpected exception class: " + expectedException.getClass().getSimpleName(); message += "\nActual exception class: " + e.getClass().getSimpleName(); if (!epsilonEquals(framelessParameter, frameParameter, epsilon)) message += "\nInconsistent frame method: " + getMethodSimpleName(frameMethod); message += "\nOriginal frameless method: " + getMethodSimpleName(framelessMethod); message += "\nFrame arguments after call:\n" + Arrays.toString(frameMethodParameters); message += "\nFrameless arguments after call:\n" + toStringAsFramelessObjects(framelessMethodParameters); throw new AssertionError(message);
@Test public void testReferenceFrameChecks() throws Throwable { Random random = new Random(234); Predicate<Method> methodFilter = m -> !m.getName().contains("IncludingFrame") && !m.getName().contains("MatchingFrame") && !m.getName().contains("MatchingFrame") && !m.getName().equals("equals") && !m.getName().equals("epsilonEquals"); EuclidFrameAPITestTools.assertMethodsOfReferenceFrameHolderCheckReferenceFrame(frame -> createRandomFrameTuple(random, frame), methodFilter); }
@Test public void testConsistencyWithTuple2D() throws Exception { Random random = new Random(3422); FrameTypeBuilder<? extends ReferenceFrameHolder> frameTypeBuilder = (frame, polygon) -> createFrameConvexPolygon2D(frame, (ConvexPolygon2DReadOnly) polygon); GenericTypeBuilder framelessTypeBuilber = () -> createRandomFramelessConvexPolygon2D(random); Predicate<Method> methodFilter = m -> !m.getName().equals("hashCode") && Arrays.stream(m.getParameterTypes()).noneMatch(p -> Collection.class.isAssignableFrom(p)); EuclidFrameAPITestTools.assertFrameMethodsOfFrameHolderPreserveFunctionality(frameTypeBuilder, framelessTypeBuilber, methodFilter); }
System.arraycopy(arrayToClone, 0, clone[i], 0, arrayToClone.length); else if (isVertexSupplier(parameterType)) clone[i] = clone((Object[]) parametersToClone[i]); clone[i] = newInstanceOf(parameterType); Method setter = parameterType.getMethod("set", parameterType); setter.invoke(clone[i], parametersToClone[i]);
List<Method> frameMethods = keepOnlyMethodsWithAtLeastNFrameArguments(frameTypeToTest.getMethods(), 0); if (isFrameType(frameMethodParameterTypes[i])) framelessMethodParameterTypes[i] = findCorrespondingFramelessType(frameMethodParameterTypes[i]); else framelessMethodParameterTypes[i] = frameMethodParameterTypes[i]; Object[] frameMethodParameters = instantiateParameterTypes(worldFrame, frameMethodParameterTypes); Object[] framelessMethodParameters = clone(frameMethodParameters); Throwable expectedException = null; Object framelessMethodReturnObject = null; framelessMethodReturnObject = invokeMethod(framelessObject, framelessMethod, framelessMethodParameters); frameMethodReturnObject = invokeMethod(frameObject, frameMethod, frameMethodParameters); message += "The method: " + getMethodSimpleName(frameMethod); message += "\ndid not throw the same exception as the original method: " + getMethodSimpleName(framelessMethod); message += "\nExpected exception class: " + (expectedException == null ? "none" : expectedException.getClass().getSimpleName()); message += "\nActual exception class: " + e.getClass().getSimpleName(); if (!epsilonEquals(framelessParameter, frameParameter, epsilon)) message += "\nInconsistent frame method: " + getMethodSimpleName(frameMethod); message += "\nOriginal frameless method: " + getMethodSimpleName(framelessMethod); message += "\nFrame arguments after call:\n" + Arrays.toString(frameMethodParameters); message += "\nFrameless arguments after call:\n" + toStringAsFramelessObjects(framelessMethodParameters); throw new AssertionError(message);
@Test public void testReferenceFrameChecks() throws Throwable { Random random = new Random(234); Predicate<Method> methodFilter = m -> !m.getName().contains("IncludingFrame") && !m.getName().contains("MatchingFrame") && !m.getName().equals("equals") && !m.getName().equals("epsilonEquals"); EuclidFrameAPITestTools.assertMethodsOfReferenceFrameHolderCheckReferenceFrame(frame -> createRandomFrameConvexPolygon2D(random, frame), methodFilter); }
@Test public void testConsistencyWithLineSegment2D() { Random random = new Random(234235L); EuclidFrameAPITestTools.FrameTypeBuilder<? extends ReferenceFrameHolder> frameTypeBuilder = (frame, quaternion) -> createFrameLineSegment(frame, (LineSegment3DReadOnly) quaternion); EuclidFrameAPITestTools.GenericTypeBuilder framelessTypeBuilder = () -> EuclidGeometryRandomTools.nextLineSegment3D(random); Predicate<Method> methodFilter = m -> !m.getName().equals("hashCode") && !m.getName().equals("epsilonEquals"); EuclidFrameAPITestTools.assertFrameMethodsOfFrameHolderPreserveFunctionality(frameTypeBuilder, framelessTypeBuilder, methodFilter); }
/** * Asserts, using reflection, that all methods with frameless arguments, such as * {@code Tuple3DReadOnly}, are overloaded with their frame type equivalent, i.e. * {@code Tuple2DBasics} is to be overloaded with {@code FrameTuple2D}. * * @param typeWithFrameMethods refers to the type to be tested. This asserts that * {@code typeWithFrameMethods} properly has all the methods necessary to properly * overload {@code typeWithFramelessMethods}. * @param typeWithFramelessMethods refers to the type declaring methods with frameless objects * that are to be overloaded. * @param assertAllCombinations when {@code false}, this asserts that for each method in * {@code typeWithFramelessMethods} there is one overloading method in * {@code typeWithFrameMethods} with all the arguments using the equivalent frame type. * When {@code true}, this asserts that for each method in * {@code typeWithFramelessArguments}, {@code typeWithFrameMethods} overloads it with * all the possible combinations of frame & frameless arguments, except for the * original frameless signature. * @param minNumberOfFramelessArguments threshold used to filter out methods to assert in * {@code typeWithFramelessMethods}. */ public static void assertOverloadingWithFrameObjects(Class<?> typeWithFrameMethods, Class<?> typeWithFramelessMethods, boolean assertAllCombinations, int minNumberOfFramelessArguments) { assertOverloadingWithFrameObjects(typeWithFrameMethods, typeWithFramelessMethods, assertAllCombinations, minNumberOfFramelessArguments, m -> true); }
@Test public void testReferenceFrameChecks() throws Throwable { Random random = new Random(234); Predicate<Method> methodFilter = m -> !m.getName().equals("setIncludingFrame") && !m.getName().equals("equals") && !m.getName().equals("epsilonEquals") && !m.getName().equals("setMatchingFrame"); EuclidFrameAPITestTools.assertMethodsOfReferenceFrameHolderCheckReferenceFrame(frame -> createRandomFrameLineSegment(random, frame), methodFilter); } }
@Test public void testConsistencyWithLineSegment2D() { Random random = new Random(234235L); EuclidFrameAPITestTools.FrameTypeBuilder<? extends ReferenceFrameHolder> frameTypeBuilder = (frame, quaternion) -> createFrameLineSegment(frame, (LineSegment2DReadOnly) quaternion); EuclidFrameAPITestTools.GenericTypeBuilder framelessTypeBuilder = () -> EuclidGeometryRandomTools.nextLineSegment2D(random); Predicate<Method> methodFilter = m -> !m.getName().equals("hashCode") && !m.getName().equals("epsilonEquals"); EuclidFrameAPITestTools.assertFrameMethodsOfFrameHolderPreserveFunctionality(frameTypeBuilder, framelessTypeBuilder, methodFilter); }
@Test public void testConservedFunctionality() throws Exception { EuclidFrameAPITestTools.assertStaticMethodsPreserveFunctionality(EuclidFrameTools.class, EuclidGeometryTools.class); }
@Test public void testReferenceFrameChecked() throws Throwable { EuclidFrameAPITestTools.assertStaticMethodsCheckReferenceFrame(EuclidFrameTools.class); }
@Test public void testOverloading() throws Exception { EuclidFrameAPITestTools.assertOverloadingWithFrameObjects(FrameOrientation3DReadOnly.class, Orientation3DReadOnly.class, true); EuclidFrameAPITestTools.assertOverloadingWithFrameObjects(FrameOrientation3DBasics.class, Orientation3DBasics.class, true); EuclidFrameAPITestTools.assertOverloadingWithFrameObjects(FrameYawPitchRollReadOnly.class, YawPitchRollReadOnly.class, true); Map<String, Class<?>[]> framelessMethodsToIgnore = new HashMap<>(); framelessMethodsToIgnore.put("set", new Class<?>[] {YawPitchRoll.class}); framelessMethodsToIgnore.put("epsilonEquals", new Class<?>[] {YawPitchRoll.class, Double.TYPE}); framelessMethodsToIgnore.put("geometricallyEquals", new Class<?>[] {YawPitchRoll.class, Double.TYPE}); EuclidFrameAPITestTools.assertOverloadingWithFrameObjects(FrameYawPitchRoll.class, YawPitchRoll.class, true, 1, framelessMethodsToIgnore); }
@Test public void testReferenceFrameChecks() throws Throwable { Random random = new Random(234); Predicate<Method> methodFilter = m -> !m.getName().contains("IncludingFrame") && !m.getName().equals("equals") && !m.getName().equals("epsilonEquals") && !m.getName().equals("setMatchingFrame"); EuclidFrameAPITestTools.assertMethodsOfReferenceFrameHolderCheckReferenceFrame(frame -> createRandomFramePose(random, frame), methodFilter); }
@Test public void testConsistencyWithLine2D() { Random random = new Random(234235L); EuclidFrameAPITestTools.FrameTypeBuilder<? extends ReferenceFrameHolder> frameTypeBuilder = (frame, line) -> createFrameLine(frame, (Line2DReadOnly) line); EuclidFrameAPITestTools.GenericTypeBuilder framelessTypeBuilder = () -> EuclidGeometryRandomTools.nextLine2D(random); Predicate<Method> methodFilter = m -> !m.getName().equals("hashCode") && !m.getName().equals("epsilonEquals"); EuclidFrameAPITestTools.assertFrameMethodsOfFrameHolderPreserveFunctionality(frameTypeBuilder, framelessTypeBuilder, methodFilter); }