blob: bfdb434b2a0662a0615d0c3b088e8ad6ff3cb569 [file] [log] [blame]
/*
* 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;
}
}