| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You 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.apache.commons.numbers.core; |
| |
| import java.io.ByteArrayInputStream; |
| import java.io.ByteArrayOutputStream; |
| import java.io.IOException; |
| import java.io.ObjectInputStream; |
| import java.io.ObjectOutputStream; |
| |
| import org.junit.jupiter.api.Assertions; |
| |
| /** |
| * Test utilities. |
| * TODO: Cleanup (remove unused and obsolete methods). |
| */ |
| public final class TestUtils { |
| /** |
| * Collection of static methods used in math unit tests. |
| */ |
| private TestUtils() { |
| super(); |
| } |
| |
| /** |
| * Serializes an object to a bytes array and then recovers the object from the bytes array. |
| * Returns the deserialized object. |
| * |
| * @param o object to serialize and recover |
| * @return the recovered, deserialized object |
| */ |
| public static Object serializeAndRecover(Object o) { |
| try { |
| // serialize the Object |
| ByteArrayOutputStream bos = new ByteArrayOutputStream(); |
| ObjectOutputStream so = new ObjectOutputStream(bos); |
| so.writeObject(o); |
| |
| // deserialize the Object |
| ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray()); |
| ObjectInputStream si = new ObjectInputStream(bis); |
| return si.readObject(); |
| } catch (IOException ioe) { |
| return null; |
| } catch (ClassNotFoundException cnfe) { |
| return null; |
| } |
| } |
| |
| /** |
| * Verifies that serialization preserves equals and hashCode. |
| * Serializes the object, then recovers it and checks equals and hash code. |
| * |
| * @param object the object to serialize and recover |
| */ |
| public static void checkSerializedEquality(Object object) { |
| Object object2 = serializeAndRecover(object); |
| Assertions.assertEquals(object, object2, "Equals check"); |
| Assertions.assertEquals(object.hashCode(), object2.hashCode(), "HashCode check"); |
| } |
| |
| /** |
| * Verifies that the relative error in actual vs. expected is less than or |
| * equal to relativeError. If expected is infinite or NaN, actual must be |
| * the same (NaN or infinity of the same sign). |
| * |
| * @param expected expected value |
| * @param actual observed value |
| * @param relativeError maximum allowable relative error |
| */ |
| public static void assertRelativelyEquals(double expected, double actual, |
| double relativeError) { |
| assertRelativelyEquals(null, expected, actual, relativeError); |
| } |
| |
| /** |
| * Verifies that the relative error in actual vs. expected is less than or |
| * equal to relativeError. If expected is infinite or NaN, actual must be |
| * the same (NaN or infinity of the same sign). |
| * |
| * @param msg message to return with failure |
| * @param expected expected value |
| * @param actual observed value |
| * @param relativeError maximum allowable relative error |
| */ |
| public static void assertRelativelyEquals(String msg, double expected, |
| double actual, double relativeError) { |
| if (Double.isNaN(expected)) { |
| Assertions.assertTrue(Double.isNaN(actual), msg); |
| } else if (Double.isNaN(actual)) { |
| Assertions.assertTrue(Double.isNaN(expected), msg); |
| } else if (Double.isInfinite(actual) || Double.isInfinite(expected)) { |
| Assertions.assertEquals(expected, actual, relativeError); |
| } else if (expected == 0.0) { |
| Assertions.assertEquals(expected, actual, relativeError, msg); |
| } else { |
| double absError = Math.abs(expected) * relativeError; |
| Assertions.assertEquals(expected, actual, absError, msg); |
| } |
| } |
| |
| /** |
| * Fails iff values does not contain a number within epsilon of x. |
| * |
| * @param msg message to return with failure |
| * @param values double array to search |
| * @param x value sought |
| * @param epsilon tolerance |
| */ |
| public static void assertContains(String msg, double[] values, |
| double x, double epsilon) { |
| for (double value : values) { |
| if (Precision.equals(value, x, epsilon)) { |
| return; |
| } |
| } |
| Assertions.fail(msg + " Unable to find " + x); |
| } |
| |
| /** |
| * Fails iff values does not contain a number within epsilon of x. |
| * |
| * @param values double array to search |
| * @param x value sought |
| * @param epsilon tolerance |
| */ |
| public static void assertContains(double[] values, double x, |
| double epsilon) { |
| assertContains(null, values, x, epsilon); |
| } |
| |
| /** |
| * Updates observed counts of values in quartiles. |
| * counts[0] <-> 1st quartile ... counts[3] <-> top quartile |
| */ |
| public static void updateCounts(double value, long[] counts, double[] quartiles) { |
| if (value < quartiles[0]) { |
| counts[0]++; |
| } else if (value > quartiles[2]) { |
| counts[3]++; |
| } else if (value > quartiles[1]) { |
| counts[2]++; |
| } else { |
| counts[1]++; |
| } |
| } |
| |
| /** |
| * Eliminates points with zero mass from densityPoints and densityValues parallel |
| * arrays. Returns the number of positive mass points and collapses the arrays so |
| * that the first <returned value> elements of the input arrays represent the positive |
| * mass points. |
| */ |
| public static int eliminateZeroMassPoints(int[] densityPoints, double[] densityValues) { |
| int positiveMassCount = 0; |
| for (int i = 0; i < densityValues.length; i++) { |
| if (densityValues[i] > 0) { |
| positiveMassCount++; |
| } |
| } |
| if (positiveMassCount < densityValues.length) { |
| int[] newPoints = new int[positiveMassCount]; |
| double[] newValues = new double[positiveMassCount]; |
| int j = 0; |
| for (int i = 0; i < densityValues.length; i++) { |
| if (densityValues[i] > 0) { |
| newPoints[j] = densityPoints[i]; |
| newValues[j] = densityValues[i]; |
| j++; |
| } |
| } |
| System.arraycopy(newPoints, 0, densityPoints, 0, positiveMassCount); |
| System.arraycopy(newValues, 0, densityValues, 0, positiveMassCount); |
| } |
| return positiveMassCount; |
| } |
| } |
| |
| |