/* * $Id$ * This file is a part of the Arakhne Foundation Classes, http://www.arakhne.org/afc * * Copyright (c) 2000-2012 Stephane GALLAND. * Copyright (c) 2005-10, Multiagent Team, Laboratoire Systemes et Transports, * Universite de Technologie de Belfort-Montbeliard. * Copyright (c) 2013-2016 The original authors, and other authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.arakhne.afc.testtools; import static org.junit.Assert.fail; import java.awt.geom.Point2D; import java.lang.reflect.Array; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.math.BigDecimal; import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Date; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Objects; import java.util.Random; import org.junit.Assert; import org.junit.ComparisonFailure; /** Abstract class that is providing a base for unit tests. * * @author $Author: sgalland$ * @version $FullVersion$ * @mavengroupid $GroupId$ * @mavenartifactid $ArtifactId$ */ @SuppressWarnings("checkstyle:methodcount") public abstract class AbstractTestCase extends EnableAssertion { /** Precision of the floating point number epsilon-tests. */ public static final int DEFAULT_DECIMAL_COUNT = 8; /** Precision of the floating point number epsilon-tests. */ public static final double EPSILON = 10 * 1.110223024E-16; private int decimalPrecision = DEFAULT_DECIMAL_COUNT; /** Random number sequence. */ private final Random random = new Random(); /** Replies the random number generator. * * @return the random number generator. */ public Random getRandom() { return this.random; } /** Set the epsilon used be testing floating-point values. * * @param precision is the count of decimal digits to support */ public void setDecimalPrecision(int precision) { this.decimalPrecision = Math.max(0, precision); } /** Set the epsilon used be testing floating-point values to * its default value. */ public void setDefaultDecimalPrecision() { this.decimalPrecision = DEFAULT_DECIMAL_COUNT; } /** Replies if two values are equals at espilon. * * @param v1 the first value. * @param v2 the second value. * @param isNaNEqual indicates if the NaN value is equals to itself. * @return <code>true</code> or <code>false</code> */ public boolean isEpsilonEquals(double v1, double v2, boolean isNaNEqual) { if (v1 == v2) { return true; } final boolean nanA = Double.isNaN(v1); final boolean nanB = Double.isNaN(v2); if (nanA || nanB) { if (isNaNEqual) { return nanA == nanB; } return false; } if (!Double.isInfinite(v1) && !Double.isInfinite(v1) && !Double.isNaN(v1) && !Double.isNaN(v2)) { return isEpsilonEquals(new BigDecimal(v1), new BigDecimal(v2), this.decimalPrecision / 2); } return false; } /** Replies if two values are equals at espilon. * * @param v1 the first value. * @param v2 the second value. * @return <code>true</code> or <code>false</code> */ public boolean isEpsilonEquals(double v1, double v2) { return isEpsilonEquals(v1, v2, true); } /** Replies if two values are equals at espilon. * * @param v1 the first value. * @param v2 the second value. * @return <code>true</code> or <code>false</code> */ public boolean isEpsilonEquals(BigDecimal v1, BigDecimal v2) { return isEpsilonEquals(v1, v2, this.decimalPrecision); } /** Replies if two values are equals at espilon. * * @param v1 the first value. * @param v2 the second value. * @param precision is the number of decimal digits to test. * @return <code>true</code> or <code>false</code> */ public static boolean isEpsilonEquals(BigDecimal v1, BigDecimal v2, int precision) { final BigDecimal ma = v1.movePointRight(precision); final BigDecimal mb = v2.movePointRight(precision); BigDecimal aa = ma.setScale(0, BigDecimal.ROUND_HALF_UP); BigDecimal bb = mb.setScale(0, BigDecimal.ROUND_HALF_UP); if (aa.compareTo(bb) == 0) { return true; } aa = ma.setScale(0, BigDecimal.ROUND_DOWN); bb = mb.setScale(0, BigDecimal.ROUND_DOWN); return aa.compareTo(bb) == 0; } /** * Replies if two arrays have the same values at epsilon. * * @param v1 the first value. * @param v2 the second value. * @return <code>true</code> if the two arrays are equal, otherwise * <code>false</code>. */ public boolean isEpsilonEquals(double[] v1, double[] v2) { if (v1 == v2) { return true; } if (v1 == null || v2 == null) { return false; } if (v1.length != v2.length) { return false; } assert v1 != null && v2 != null; for (int i = 0; i < v1.length; ++i) { if (!isEpsilonEquals(v1[i], v2[i])) { return false; } } return true; } /** Test if the actual value is not equal to the expected value with * a distance of epsilon. * * @param expected the expected value. * @param actual the actual value. */ public static void assertNotEquals(int expected, int actual) { assertNotEquals(null, expected, actual); } /** Test if the actual value is not equal to the expected value with * a distance of epsilon. * * @param message the error message. * @param expected the expected value. * @param actual the actual value. */ public static void assertNotEquals(String message, int expected, int actual) { if (expected == actual) { fail(formatFailMessage(message, "same value, expecting not equal to:", expected, actual)); //$NON-NLS-1$ } } /** Test if the actual value is not equal to the expected value with * a distance of epsilon. * * @param expected the expected value. * @param actual the actual value. */ public static void assertNotEquals(Object expected, Object actual) { assertNotEquals(null, expected, actual); } /** Test if the actual value is not equal to the expected value with * a distance of epsilon. * * @param message the error message. * @param expected the expected value. * @param actual the actual value. */ public static void assertNotEquals(String message, Object expected, Object actual) { if (!Objects.equals(expected, actual)) { throw new junit.framework.ComparisonFailure(message, Objects.toString(expected), Objects.toString(actual)); } } /** Test if the given value is not a number. * * @param value the value to test. */ public static void assertNaN(double value) { if (!Double.isNaN(value)) { fail(formatFailMessage(null, "Expecting NaN", value)); //$NON-NLS-1$ } } /** Test if the given value is not a number. * * @param value the value to test. */ public static void assertNaN(float value) { if (!Float.isNaN(value)) { fail(formatFailMessage(null, "Expecting NaN", value)); //$NON-NLS-1$ } } /** Test if the given value is equal to zero. * * @param value the value to test. */ public static void assertZero(byte value) { if (value != 0) { fail(formatFailMessage(null, "Expecting zero", value)); //$NON-NLS-1$ } } /** Test if the given value is equal to zero. * * @param value the value to test. */ public static void assertZero(short value) { if (value != 0) { fail(formatFailMessage(null, "Expecting zero", value)); //$NON-NLS-1$ } } /** Test if the given value is equal to zero. * * @param value the value to test. */ public static void assertZero(int value) { if (value != 0) { fail(formatFailMessage(null, "Expecting zero", value)); //$NON-NLS-1$ } } /** Test if the given value is equal to zero. * * @param value the value to test. */ public static void assertZero(long value) { if (value != 0) { fail(formatFailMessage(null, "Expecting zero", value)); //$NON-NLS-1$ } } /** Test if the given value is equal to zero. * * @param value the value to test. */ public static void assertZero(float value) { if (value != 0f) { fail(formatFailMessage(null, "Expecting zero", value)); //$NON-NLS-1$ } } /** Test if the given value is equal to zero. * * @param value the value to test. */ public static void assertZero(double value) { assertZero(null, value); } /** Test if the given value is equal to zero. * * @param message the error message. * @param value the value to test. */ public static void assertZero(String message, double value) { if (value != 0.) { fail(formatFailMessage(message, "Expecting zero", value)); //$NON-NLS-1$ } } /** Test if the given value is near to zero. * * @param value the value to test. */ public void assertEpsilonZero(double value) { assertEpsilonZero(null, value); } /** Test if the given value is near to zero. * * @param message the error message. * @param value the value to test. */ public void assertEpsilonZero(String message, double value) { if (!isEpsilonEquals(value, 0.)) { fail(formatFailMessage(message, "Expecting zero", value)); //$NON-NLS-1$ } } /** Assert two iterable objects have the same elements. * * @param <T> the type of the elements in the iterable objects. * @param expected the expected value. * @param actual the actual value. */ public static <T> void assertCollectionEquals(Iterable<? extends T> expected, Iterable<? extends T> actual) { final Iterator<? extends T> it1 = expected.iterator(); final Iterator<? extends T> it2 = actual.iterator(); while (it1.hasNext()) { if (!it2.hasNext()) { throw new ComparisonFailure( formatFailMessage(null, "Element is missed", expected, actual), //$NON-NLS-1$ toString(expected), toString(actual)); } final T expect = it1.next(); final T act = it2.next(); if (!Objects.equals(expect, act)) { throw new ComparisonFailure(formatFailMessage(null, "Not same element", expected, actual), //$NON-NLS-1$ toString(expected), toString(actual)); } } if (it2.hasNext()) { throw new ComparisonFailure(formatFailMessage(null, "Too many elements", expected, actual), //$NON-NLS-1$ toString(expected), toString(actual)); } } private static String toString(Iterable<?> it) { final StringBuilder b = new StringBuilder(); for (final Object o : it) { b.append(o); b.append(",\n"); //$NON-NLS-1$ } return b.toString(); } @SuppressWarnings({"checkstyle:returncount", "checkstyle:npathcomplexity"}) private static String arrayToString(Object obj) { if (obj == null) { return null; } if (obj instanceof boolean[]) { return Arrays.toString((boolean[]) obj); } if (obj instanceof byte[]) { return Arrays.toString((byte[]) obj); } if (obj instanceof char[]) { return Arrays.toString((char[]) obj); } if (obj instanceof short[]) { return Arrays.toString((short[]) obj); } if (obj instanceof int[]) { return Arrays.toString((int[]) obj); } if (obj instanceof long[]) { return Arrays.toString((long[]) obj); } if (obj instanceof float[]) { return Arrays.toString((float[]) obj); } if (obj instanceof double[]) { return Arrays.toString((double[]) obj); } if (obj instanceof Object[]) { return Arrays.toString((Object[]) obj); } return obj.toString(); } /** Replies if the given elements is in the array. * * <p>This function is based on {@link Object#equals(java.lang.Object)}. */ private static <T> boolean arrayContainsAll(T[] elts, T[] array) { boolean found; for (final T elt : elts) { found = false; for (final T t : array) { if ((t == elt) || ((t != null) && (t.equals(elt)))) { found = true; break; } } if (!found) { return false; } } return true; } /** * Format a failure message for invalid value. * * @param message is the message to reply. * @param expected is the expected object. * @param actual is the actual value of the object. * @return the message */ protected static String formatFailMessage(String message, Object expected, Object actual) { final StringBuilder formatted = new StringBuilder(); if (message != null) { formatted.append(message); formatted.append(' '); } formatted.append("expected: <"); //$NON-NLS-1$ formatted.append(arrayToString(expected)); formatted.append("> but was: <"); //$NON-NLS-1$ formatted.append(arrayToString(actual)); formatted.append(">"); //$NON-NLS-1$ return formatted.toString(); } /** * Format a failure message. * * @param message the first part of the message (optional). * @param msg the second part of the message. * @return the message */ protected static String formatFailMessage(String message, String msg) { final StringBuilder formatted = new StringBuilder(); if (message != null) { formatted.append(message); formatted.append(' '); } formatted.append(msg); return formatted.toString(); } /** * Format a failure message for invalid value. * * @param message is the first part of the message (optional). * @param msg is the second part of the message (mandatory). * @param expected is the expected object. * @param actual is the actual value of the object. * @return the message */ protected static String formatFailMessage(String message, String msg, Object expected, Object actual) { final StringBuilder formatted = new StringBuilder(); if (message != null) { formatted.append(message); formatted.append(' '); } formatted.append(msg); formatted.append("; expected: <"); //$NON-NLS-1$ formatted.append(arrayToString(expected)); formatted.append("> but was: <"); //$NON-NLS-1$ formatted.append(arrayToString(actual)); formatted.append(">"); //$NON-NLS-1$ return formatted.toString(); } /** * Format a failure message for invalid value. * * @param message is the first part of the message (optional). * @param msg is the second part of the message (mandatory). * @param actual is the actual value of the object. * @return the message */ protected static String formatFailMessage(String message, String msg, Object actual) { final StringBuilder formatted = new StringBuilder(); if (message != null) { formatted.append(message); formatted.append(' '); } formatted.append(msg); formatted.append(" but was: <"); //$NON-NLS-1$ formatted.append(arrayToString(actual)); formatted.append(">"); //$NON-NLS-1$ return formatted.toString(); } /** Asserts that the actual object is equal to one of the expected objects. If not * an AssertionFailedError is thrown with the given message. * * @param message is the error message to put inside the assertion. * @param expectedObjects are the set of expected values during the unit test. * @param actual is the actual value of the object in the unit test. */ public static void assertContains(String message, Object[] expectedObjects, Object actual) { if ((expectedObjects != null) && (expectedObjects.length > 0)) { for (final Object object : expectedObjects) { if ((object == null) && (actual == null)) { return; } if ((object != null) && (object.equals(actual))) { return; } } } fail(formatFailMessage(message, expectedObjects, actual)); } /** Asserts that the actual object is equal to one of the expected objects. If not * an AssertionFailedError is thrown. * * @param expectedObjects are the set of expected values during the unit test. * @param actual is the actual value of the object in the unit test. */ public static void assertContains(Object[] expectedObjects, Object actual) { assertContains(null, expectedObjects, actual); } /** Asserts that the actual object is equal to one of the expected objects. If not * an AssertionFailedError is thrown. * This assertion function tests the types of its parameters to call the best * {@code assertEquals} function. * * @param expected is the expected value during the unit test. * @param actual is the actual value of the object during the unit test. * @see Assert#assertEquals(Object, Object) * @see #assertContains(Object[], Object) */ public static void assertEqualsGeneric(Object expected, Object actual) { assertEqualsGeneric(null, expected, actual); } /** Asserts that the actual object is equal to one of the expected objects. If not * an AssertionFailedError is thrown. * This assertion function tests the types of its parameters to call the best * {@code assertEquals} function. * * @param message is the error message to put inside the assertion. * @param expected is the expected value during the unit test. * @param actual is the actual value of the object during the unit test. * @see Assert#assertEquals(Object, Object) * @see #assertContains(Object[], Object) */ public static void assertEqualsGeneric(String message, Object expected, Object actual) { if ((expected != null) && (actual != null) && (expected.getClass().isArray())) { if (actual.getClass().isArray()) { assertContains(message, (Object[]) expected, (Object[]) actual); } else { assertContains(message, (Object[]) expected, actual); } } else { Assert.assertEquals(message, expected, actual); } } /** Asserts that the actual similar is equal to one of the expected objects. If not * an AssertionFailedError is thrown. * * @param <T> is the type of the values * @param expectedObjects are the expected values during the unit test. * @param actual are the actual values of the objects during the unit test. */ public static <T> void assertSimilars(T[] expectedObjects, T[] actual) { assertSimilars(null, expectedObjects, actual); } /** Asserts that the actual similar is equal to one of the expected objects. If not * an AssertionFailedError is thrown. * * @param <T> is the type of the values * @param message is the error message to put inside the assertion. * @param expectedObjects are the expected values during the unit test. * @param actual are the actual values of the objects during the unit test. */ public static <T> void assertSimilars(String message, T[] expectedObjects, T[] actual) { if (expectedObjects == actual) { return; } if ((arrayContainsAll(expectedObjects, actual)) && (arrayContainsAll(actual, expectedObjects))) { return; } fail(formatFailMessage(message, expectedObjects, actual)); } /** Asserts that the actual similar is equal to one of the expected objects. If not * an AssertionFailedError is thrown. * * @param <T> is the type of the values * @param expectedObjects are the expected values during the unit test. * @param actual are the actual values of the objects during the unit test. */ public static <T> void assertSimilars(Collection<T> expectedObjects, Collection<T> actual) { assertSimilars(null, expectedObjects, actual); } /** Asserts that the actual similar is equal to one of the expected objects. If not * an AssertionFailedError is thrown. * * @param <T> is the type of the values * @param message is the error message to put inside the assertion. * @param expectedObjects are the expected values during the unit test. * @param actual are the actual values of the objects during the unit test. */ public static <T> void assertSimilars(String message, Collection<T> expectedObjects, Collection<T> actual) { if (expectedObjects == actual) { return; } if (similars(expectedObjects, actual)) { return; } fail(formatFailMessage(message, expectedObjects, actual)); } /** Asserts that the actual object is equal to one of the expected objects. If not * an AssertionFailedError is thrown. * * @param <T> is the type of the values * @param <X> is the element's type of the values if they are arrays. * @param message is the error message to put inside the assertion. * @param expected is the expected value during the unit test. * @param actual are the actual value of the object during the unit test. */ @SuppressWarnings("unchecked") public static <T, X> void assertSimilars(String message, T expected, T actual) { if (expected == actual) { return; } if (expected instanceof Collection) { assertSimilars(message, (Collection<?>) expected, (Collection<?>) actual); } else if (expected instanceof Point2D) { assertSimilars(message, (Point2D) expected, (Point2D) actual); } else if (expected instanceof Date) { assertSimilars(message, (Date) expected, (Date) actual); } else if (expected.getClass().isArray()) { assertSimilars(message, (X[]) expected, (X[]) actual); } else { Assert.assertEquals(message, expected, actual); } } private static <T> boolean similars(Collection<T> c1, Collection<T> c2) { final List<T> a = new ArrayList<>(); a.addAll(c2); for (final T elt : c1) { if (!a.remove(elt)) { return false; } } return a.isEmpty(); } /** Asserts that the actual object is equal to one of the expected objects. If not * an AssertionFailedError is thrown. * * @param <T> is the type of the values. * @param <X> is the element's type of the values if they are arrays. * @param message is the error message to put inside the assertion. * @param expected is the expected value. * @param actual is the current value. */ public static <T, X> void assertNotSimilars(String message, T expected, T actual) { if (expected != actual) { try { assertSimilars(message, expected, actual); } catch (Throwable exception) { // ok return; } } fail(formatFailMessage(message, expected, actual)); } /** Replies if the two objects are similars. * * @param <T> is the type of the values * @param <X> is the element's type of the values if they are arrays. * @param obj1 the first object. * @param obj2 the second object. * @return <code>true</code> if the objects are similar, otherwise <code>false</code> */ public static <T, X> boolean isSimilarObjects(T obj1, T obj2) { if (obj1 == obj2) { return true; } try { assertSimilars(null, obj1, obj2); return true; } catch (Throwable exception) { return false; } } /** Asserts that the actual similar is equal to one of the expected objects. If not * an AssertionFailedError is thrown. * * @param <K> is the type of the map keys. * @param <V> is the type of the map values. * @param expectedObjects is the expected map. * @param actual is the current map. */ public static <K, V> void assertDeepSimilars(Map<K, V> expectedObjects, Map<K, V> actual) { assertDeepSimilars(null, expectedObjects, actual); } /** Asserts that the actual similar is equal to one of the expected objects. If not * an AssertionFailedError is thrown. * * @param <K> is the type of the map keys. * @param <V> is the type of the map values. * @param message is the error message to put inside the assertion. * @param expectedObjects is the expected map. * @param actual is the current map. */ public static <K, V> void assertDeepSimilars(String message, Map<K, V> expectedObjects, Map<K, V> actual) { if (expectedObjects == actual) { return; } if (similars(expectedObjects.keySet(), actual.keySet())) { for (final Entry<K, V> entry : expectedObjects.entrySet()) { final V v1 = entry.getValue(); final V v2 = actual.get(entry.getKey()); assertSimilars(message, v1, v2); } // all values are correct return; } fail(formatFailMessage(message, expectedObjects, actual)); } /** Asserts that the actual similar is equal to one of the expected objects. If not * an AssertionFailedError is thrown. * * @param <K> is the type of the map keys. * @param <V> is the type of the map values. * @param expectedObjects is the expected map. * @param actual is the current map. */ public static <K, V> void assertNotDeepSimilars(Map<K, V> expectedObjects, Map<K, V> actual) { assertNotDeepSimilars(null, expectedObjects, actual); } /** Asserts that the actual similar is equal to one of the expected objects. If not * an AssertionFailedError is thrown. * * @param <K> is the type of the map keys. * @param <V> is the type of the map values. * @param message is the error message to put inside the assertion. * @param expectedObjects is the expected map. * @param actual is the current map. */ public static <K, V> void assertNotDeepSimilars(String message, Map<K, V> expectedObjects, Map<K, V> actual) { if (expectedObjects != actual) { if (!similars(expectedObjects.keySet(), actual.keySet())) { return; } for (final Entry<K, V> entry : expectedObjects.entrySet()) { final V v1 = entry.getValue(); final V v2 = actual.get(entry.getKey()); if (!isSimilarObjects(v1, v2)) { return; } } } fail(formatFailMessage(message, expectedObjects, actual)); } /** Asserts that the specified value is stricly negative. * * @param number the value. */ public static void assertStrictlyNegative(Number number) { assertStrictlyNegative(null, number); } /** Asserts that the specified value is stricly negative. * * @param message is the error message to put inside the assertion. * @param number the value. */ public static void assertStrictlyNegative(String message, Number number) { if (number.doubleValue() < 0.) { return; } fail(formatFailMessage(message, "expected negative value", number)); //$NON-NLS-1$ } /** Asserts that the specified value is stricly positive. * * @param number the value. */ public static void assertStrictlyPositive(Number number) { assertStrictlyPositive(null, number); } /** Asserts that the specified value is stricly positive. * * @param message is the error message to put inside the assertion. * @param number the value. */ public static void assertStrictlyPositive(String message, Number number) { if (number.doubleValue() > 0.) { return; } fail(formatFailMessage(message, "expected positive value", number)); //$NON-NLS-1$ } /** Asserts that the specified value is negative. * * @param number the value. */ public static void assertNegative(Number number) { assertNegative(null, number); } /** Asserts that the specified value is negative. * * @param message is the error message to put inside the assertion. * @param number the value. */ public static void assertNegative(String message, Number number) { if (number.doubleValue() <= 0.) { return; } fail(formatFailMessage(message, "expected negative value", number)); //$NON-NLS-1$ } /** Asserts that the specified value is positive. * * @param number the value. */ public static void assertPositive(Number number) { assertPositive(null, number); } /** Asserts that the specified value is positive. * * @param message is the error message to put inside the assertion. * @param number the value. */ public static void assertPositive(String message, Number number) { if (number.doubleValue() >= 0.) { return; } fail(formatFailMessage(message, "expected positive value", number)); //$NON-NLS-1$ } /** * Replies an array which is containing values randomly selected from the parameter. * Duplicate values are allowed. * * @param <T> is the type of the values. * @param availableValues is the collection of available values. * @return the selected values (possible duplicated) */ @SuppressWarnings("unchecked") public <T> T[] extractRandomValues(T[] availableValues) { final int count = getRandom().nextInt(500); final List<T> tab = new ArrayList<>(count); for (int i = 0; i < count; ++i) { tab.add(availableValues[getRandom().nextInt(availableValues.length)]); } final Class<?> clazz = availableValues.getClass().getComponentType(); final T[] array = (T[]) Array.newInstance(clazz, tab.size()); tab.toArray(array); tab.clear(); return array; } /** Replies a randomized string. * * @return a random string. */ public String randomString() { return randomString(-1); } /** Replies a randomized string with a max length. * * @param maxSize is the max length of the string. * @return a random string with a max length. */ @SuppressWarnings("checkstyle:magicnumber") public String randomString(int maxSize) { final StringBuilder b = new StringBuilder(); final int count = getRandom().nextInt(maxSize <= 0 ? 255 : maxSize - 1) + 1; for (int i = 0; i < count; ++i) { final char c = (char) ('A' + getRandom().nextInt(26)); b.append(c); } return b.toString(); } /** Random a value from an enumeration. * * @param <E> is the type of the enumeration * @param type is the type of the enumeration * @return a value from the specified enumeration. */ public <E extends Enum<E>> E randomEnum(Class<E> type) { final E[] constants = type.getEnumConstants(); return constants[getRandom().nextInt(constants.length)]; } /** Assert the the specified method thrown an exception. * * @param self is the calling object * @param method is the name of the method to invoke * @param types is the parameter types of the method * @param parameters is the parameter values to pass at invocation. */ public static void assertException(Object self, String method, Class<?>[] types, Object[] parameters) { assertException((String) null, self, method, types, parameters); } /** Assert the the specified method thrown an exception. * * @param message is the error message to put in the assertion. * @param self is the calling object * @param method is the name of the method to invoke * @param types is the parameter types of the method * @param parameters is the parameter values to pass at invocation. */ public static void assertException(String message, Object self, String method, Class<?>[] types, Object[] parameters) { try { final Class<?> clazz = self.getClass(); final Method methodFunc = clazz.getMethod(method, types); methodFunc.invoke(self, parameters); fail(formatFailMessage(message, "An exception was attempted but never thrown.")); //$NON-NLS-1$ } catch (Exception exception) { // Expected behavior } } /** Assert the the specified method thrown an exception. * * @param self is the calling object * @param method is the name of the method to invoke */ public static void assertException(Object self, String method) { assertException((String) null, self, method, new Class<?>[0], new Object[0]); } /** Assert the the specified method thrown an exception. * * @param message is the error message to put in the assertion. * @param self is the calling object * @param method is the name of the method to invoke */ public static void assertException(String message, Object self, String method) { assertException(message, self, method, new Class<?>[0], new Object[0]); } /** Test if the given method entity throws the specified exception on the given entity. * * @param expectedException the expected exception. * @param object the object that is supposed to generate the exception. * @param methodName the method that is supposed to generate the exception. * @param values are the values to pass to the methods. */ protected static void assertException(Class<? extends Throwable> expectedException, Object object, String methodName, Object... values) { assertException(null, expectedException, object, methodName, values); } /** Test if the given method entity throws the specified exception on the given entity. * * @param message the error message. * @param expectedException the expected exception. * @param object the object that is supposed to generate the exception. * @param methodName the method that is supposed to generate the exception. * @param values are the values to pass to the methods. */ protected static void assertException(String message, Class<? extends Throwable> expectedException, Object object, String methodName, Object... values) { final Class<?>[] types = new Class<?>[values.length]; for (int idx = 0; idx < types.length; ++idx) { types[idx] = values[idx].getClass(); } assertException(message, expectedException, object, methodName, types, values); } /** Test if the given method entity throws the specified exception on the given entity. * * @param expectedException the expected exception. * @param object the object that is supposed to generate the exception. * @param methodName the method that is supposed to generate the exception. * @param types are the types of the method parameters. * @param values are the values to pass to the methods. */ protected static void assertException(Class<? extends Throwable> expectedException, Object object, String methodName, Class<?>[] types, Object... values) { assertException(null, expectedException, object, methodName, types, values); } /** Test if the given method entity throws the specified exception on the given entity. * * @param message the error message. * @param expectedException the expected exception. * @param object the object that is supposed to generate the exception. * @param methodName the method that is supposed to generate the exception. * @param types are the types of the method parameters. * @param values are the values to pass to the methods. */ protected static void assertException(String message, Class<? extends Throwable> expectedException, Object object, String methodName, Class<?>[] types, Object... values) { assert object != null; Class<?> objType; Object obj = object; if (obj instanceof Class<?>) { objType = (Class<?>) obj; obj = null; } else { objType = obj.getClass(); } while (Enum.class.isAssignableFrom(objType) && !objType.isEnum()) { objType = objType.getSuperclass(); } Method method = null; Throwable t = null; try { method = objType.getMethod(methodName, types); if (method == null) { fail(formatFailMessage(message, "unable to find the method " + methodName)); //$NON-NLS-1$ return; } } catch (Exception exception) { fail(formatFailMessage(message, "unable to find the method " + methodName)); //$NON-NLS-1$ return; } try { method.invoke(obj, values); } catch (InvocationTargetException e) { if (expectedException.equals(e.getCause().getClass())) { return; } t = e.getCause(); } catch (Throwable e) { if (expectedException.equals(e.getClass())) { return; } t = e; } if (t != null) { fail(formatFailMessage(message, "the method " + methodName //$NON-NLS-1$ + " does not thrown the expected exception of type " + expectedException //$NON-NLS-1$ + ". An exception of type " + t.getClass().getName() + " is thrown insteed.")); //$NON-NLS-1$ //$NON-NLS-2$ } else { fail(formatFailMessage(message, "the method " + methodName //$NON-NLS-1$ + " does not thrown the expected exception of type " + expectedException //$NON-NLS-1$ + ". No exception was thrown insteed.")); //$NON-NLS-1$ } } /** Test if the actual value is equal to the expected value with * a distance of epsilon. * * @param expected the expected value. * @param actual the actual value. */ public void assertEpsilonEquals(double expected, double actual) { assertEpsilonEquals(null, expected, actual); } /** Test if the actual value is equal to the expected value with * a distance of epsilon. * * @param message the error message. * @param expected the expected value. * @param actual the actual value. */ public void assertEpsilonEquals(String message, double expected, double actual) { if (isEpsilonEquals(expected, actual)) { return; } throw new ComparisonFailure( formatFailMessage(message, "not same double value.", expected, actual), //$NON-NLS-1$ Double.toString(expected), Double.toString(actual)); } /** Test if the two collections contain the same elements without * taking into account the order of the elements in the collections. * * @param <T> the type of the elements in the collections. * @param expected the expected collection. * @param actual the actual collection. */ public static <T> void assertEpsilonEquals(Collection<? extends T> expected, Collection<? extends T> actual) { assertEpsilonEquals(null, expected, actual); } /** Test if the two collections contain the same elements without * taking into account the order of the elements in the collections. * * @param <T> the type of the elements in the collections. * @param message the error message. * @param expected the expected collection. * @param actual the actual collection. */ public static <T> void assertEpsilonEquals(String message, Collection<? extends T> expected, Collection<? extends T> actual) { final List<T> l = new ArrayList<>(actual); for (final T e : expected) { if (!l.remove(e)) { throw new ComparisonFailure( formatFailMessage(message, "not similar collections", expected, actual), //$NON-NLS-1$ expected.toString(), actual.toString()); } } if (!l.isEmpty()) { throw new ComparisonFailure( formatFailMessage(message, "not similar collections, not expected elements", expected, actual), //$NON-NLS-1$ expected.toString(), actual.toString()); } } /** Test if the two collections contain the same elements without * taking into account the order of the elements in the collections. * * @param <T> the type of the elements in the collections. * @param expected the expected collection. * @param actual the actual collection. */ public static <T> void assertEpsilonEquals(T[] expected, T[] actual) { assertEpsilonEquals(null, expected, actual); } /** Test if the two collections contain the same elements without * taking into account the order of the elements in the collections. * * @param <T> the type of the elements in the collections. * @param message the error message. * @param expected the expected collection. * @param actual the actual collection. */ public static <T> void assertEpsilonEquals(String message, T[] expected, T[] actual) { final List<T> l = new ArrayList<>(Arrays.asList(actual)); for (final T e : expected) { if (!l.remove(e)) { throw new ComparisonFailure( formatFailMessage(message, "not similar collections", expected, actual), //$NON-NLS-1$ Arrays.toString(expected), Arrays.toString(actual)); } } if (!l.isEmpty()) { throw new ComparisonFailure( formatFailMessage(message, "not similar collections, not expected elements", expected, actual), //$NON-NLS-1$ Arrays.toString(expected), Arrays.toString(actual)); } } /** Test if the two date are equals with an epsilon. * * @param expected the expected date. * @param actual the actual date. */ protected static void assertEpsilonEquals(Date expected, Date actual) { if (expected == actual) { return; } if (expected == null) { throw new ComparisonFailure(formatFailMessage("not same", expected, actual), //$NON-NLS-1$ null, actual.toString()); } if (actual == null) { throw new ComparisonFailure(formatFailMessage("not same", expected, actual), //$NON-NLS-1$ null, expected.toString()); } assert expected != null && actual != null; final DateFormat fmt = new SimpleDateFormat("yyyy-MM-dd"); //$NON-NLS-1$ final String expectedStr = fmt.format(expected); final String actualStr = fmt.format(expected); if (expectedStr.equals(actualStr)) { return; } throw new ComparisonFailure(formatFailMessage(null, expected, actual), expected.toString(), actual.toString()); } /** Test if the actual value is not equal to the expected value with * a distance of epsilon. * * @param expected the expected value. * @param actual the actual value. */ public void assertNotEpsilonEquals(double expected, double actual) { assertNotEpsilonEquals(null, expected, actual); } /** Test if the actual value is not equal to the expected value with * a distance of epsilon. * * @param message the error message. * @param expected the expected value. * @param actual the actual value. */ public void assertNotEpsilonEquals(String message, double expected, double actual) { if (!isEpsilonEquals(expected, actual, false)) { return; } throw new ComparisonFailure( formatFailMessage(message, "same double value.", expected, actual), //$NON-NLS-1$ Double.toString(expected), Double.toString(actual)); } /** Test if the two collections do no contain the same elements without * taking into account the order of the elements in the collections. * * @param <T> the type of the elements in the collections. * @param expected the expected collection. * @param actual the actual collection. */ public static <T> void assertNotEpsilonEquals(T[] expected, T[] actual) { assertNotEpsilonEquals(null, expected, actual); } /** Test if the two collections do no contain the same elements without * taking into account the order of the elements in the collections. * * @param <T> the type of the elements in the collections. * @param message the error message. * @param expected the expected collection. * @param actual the actual collection. */ public static <T> void assertNotEpsilonEquals(String message, T[] expected, T[] actual) { final List<T> l = new ArrayList<>(Arrays.asList(actual)); for (final T e : expected) { if (!l.remove(e)) { return; } } if (l.isEmpty()) { throw new ComparisonFailure( formatFailMessage(message, "having similar collections is not expected", expected, actual), //$NON-NLS-1$ Arrays.toString(expected), Arrays.toString(actual)); } } }