001 /*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements. See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License. You may obtain a copy of the License at
008 *
009 * http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017
018 package org.apache.commons.math;
019
020 import java.io.ByteArrayInputStream;
021 import java.io.ByteArrayOutputStream;
022 import java.io.IOException;
023 import java.io.ObjectInputStream;
024 import java.io.ObjectOutputStream;
025
026 import junit.framework.Assert;
027 import junit.framework.AssertionFailedError;
028
029 import org.apache.commons.math.complex.Complex;
030 import org.apache.commons.math.complex.ComplexFormat;
031 import org.apache.commons.math.linear.FieldMatrix;
032 import org.apache.commons.math.linear.RealMatrix;
033
034 /**
035 * @version $Revision: 776939 $ $Date: 2009-05-20 23:17:52 -0400 (Wed, 20 May 2009) $
036 */
037 public class TestUtils {
038 /**
039 * Collection of static methods used in math unit tests.
040 */
041 private TestUtils() {
042 super();
043 }
044
045 /**
046 * Verifies that expected and actual are within delta, or are both NaN or
047 * infinities of the same sign.
048 */
049 public static void assertEquals(double expected, double actual, double delta) {
050 assertEquals(null, expected, actual, delta);
051 }
052
053 /**
054 * Verifies that expected and actual are within delta, or are both NaN or
055 * infinities of the same sign.
056 */
057 public static void assertEquals(String msg, double expected, double actual, double delta) {
058 // check for NaN
059 if(Double.isNaN(expected)){
060 Assert.assertTrue("" + actual + " is not NaN.",
061 Double.isNaN(actual));
062 } else {
063 Assert.assertEquals(msg, expected, actual, delta);
064 }
065 }
066
067 /**
068 * Verifies that the two arguments are exactly the same, either
069 * both NaN or infinities of same sign, or identical floating point values.
070 */
071 public static void assertSame(double expected, double actual) {
072 assertEquals(expected, actual, 0);
073 }
074
075 /**
076 * Verifies that real and imaginary parts of the two complex arguments
077 * are exactly the same. Also ensures that NaN / infinite components match.
078 */
079 public static void assertSame(Complex expected, Complex actual) {
080 assertSame(expected.getReal(), actual.getReal());
081 assertSame(expected.getImaginary(), actual.getImaginary());
082 }
083
084 /**
085 * Verifies that real and imaginary parts of the two complex arguments
086 * differ by at most delta. Also ensures that NaN / infinite components match.
087 */
088 public static void assertEquals(Complex expected, Complex actual, double delta) {
089 assertEquals(expected.getReal(), actual.getReal(), delta);
090 assertEquals(expected.getImaginary(), actual.getImaginary(), delta);
091 }
092
093 /**
094 * Verifies that two double arrays have equal entries, up to tolerance
095 */
096 public static void assertEquals(double expected[], double observed[], double tolerance) {
097 assertEquals("Array comparison failure", expected, observed, tolerance);
098 }
099
100 /**
101 * Serializes an object to a bytes array and then recovers the object from the bytes array.
102 * Returns the deserialized object.
103 *
104 * @param o object to serialize and recover
105 * @return the recovered, deserialized object
106 */
107 public static Object serializeAndRecover(Object o) {
108 try {
109 // serialize the Object
110 ByteArrayOutputStream bos = new ByteArrayOutputStream();
111 ObjectOutputStream so = new ObjectOutputStream(bos);
112 so.writeObject(o);
113
114 // deserialize the Object
115 ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
116 ObjectInputStream si = new ObjectInputStream(bis);
117 return si.readObject();
118 } catch (IOException ioe) {
119 return null;
120 } catch (ClassNotFoundException cnfe) {
121 return null;
122 }
123 }
124
125 /**
126 * Verifies that serialization preserves equals and hashCode.
127 * Serializes the object, then recovers it and checks equals and hash code.
128 *
129 * @param object the object to serialize and recover
130 */
131 public static void checkSerializedEquality(Object object) {
132 Object object2 = serializeAndRecover(object);
133 Assert.assertEquals("Equals check", object, object2);
134 Assert.assertEquals("HashCode check", object.hashCode(), object2.hashCode());
135 }
136
137 /**
138 * Verifies that the relative error in actual vs. expected is less than or
139 * equal to relativeError. If expected is infinite or NaN, actual must be
140 * the same (NaN or infinity of the same sign).
141 *
142 * @param expected expected value
143 * @param actual observed value
144 * @param relativeError maximum allowable relative error
145 */
146 public static void assertRelativelyEquals(double expected, double actual,
147 double relativeError) {
148 assertRelativelyEquals(null, expected, actual, relativeError);
149 }
150
151 /**
152 * Verifies that the relative error in actual vs. expected is less than or
153 * equal to relativeError. If expected is infinite or NaN, actual must be
154 * the same (NaN or infinity of the same sign).
155 *
156 * @param msg message to return with failure
157 * @param expected expected value
158 * @param actual observed value
159 * @param relativeError maximum allowable relative error
160 */
161 public static void assertRelativelyEquals(String msg, double expected,
162 double actual, double relativeError) {
163 if (Double.isNaN(expected)) {
164 Assert.assertTrue(msg, Double.isNaN(actual));
165 } else if (Double.isNaN(actual)) {
166 Assert.assertTrue(msg, Double.isNaN(expected));
167 } else if (Double.isInfinite(actual) || Double.isInfinite(expected)) {
168 Assert.assertEquals(expected, actual, relativeError);
169 } else if (expected == 0.0) {
170 Assert.assertEquals(msg, actual, expected, relativeError);
171 } else {
172 double x = Math.abs((expected - actual) / expected);
173 Assert.assertEquals(msg, 0.0, x, relativeError);
174 }
175 }
176
177 /**
178 * Fails iff values does not contain a number within epsilon of z.
179 *
180 * @param msg message to return with failure
181 * @param values complex array to search
182 * @param z value sought
183 * @param epsilon tolerance
184 */
185 public static void assertContains(String msg, Complex[] values,
186 Complex z, double epsilon) {
187 int i = 0;
188 boolean found = false;
189 while (!found && i < values.length) {
190 try {
191 assertEquals(values[i], z, epsilon);
192 found = true;
193 } catch (AssertionFailedError er) {
194 // no match
195 }
196 i++;
197 }
198 if (!found) {
199 Assert.fail(msg +
200 " Unable to find " + ComplexFormat.formatComplex(z));
201 }
202 }
203
204 /**
205 * Fails iff values does not contain a number within epsilon of z.
206 *
207 * @param values complex array to search
208 * @param z value sought
209 * @param epsilon tolerance
210 */
211 public static void assertContains(Complex[] values,
212 Complex z, double epsilon) {
213 assertContains(null, values, z, epsilon);
214 }
215
216 /**
217 * Fails iff values does not contain a number within epsilon of x.
218 *
219 * @param msg message to return with failure
220 * @param values double array to search
221 * @param x value sought
222 * @param epsilon tolerance
223 */
224 public static void assertContains(String msg, double[] values,
225 double x, double epsilon) {
226 int i = 0;
227 boolean found = false;
228 while (!found && i < values.length) {
229 try {
230 assertEquals(values[i], x, epsilon);
231 found = true;
232 } catch (AssertionFailedError er) {
233 // no match
234 }
235 i++;
236 }
237 if (!found) {
238 Assert.fail(msg + " Unable to find" + x);
239 }
240 }
241
242 /**
243 * Fails iff values does not contain a number within epsilon of x.
244 *
245 * @param values double array to search
246 * @param x value sought
247 * @param epsilon tolerance
248 */
249 public static void assertContains(double[] values, double x,
250 double epsilon) {
251 assertContains(null, values, x, epsilon);
252 }
253
254 /** verifies that two matrices are close (1-norm) */
255 public static void assertEquals(String msg, RealMatrix expected, RealMatrix observed,
256 double tolerance) {
257
258 if (observed == null) {
259 Assert.fail(msg + "\nObserved is null");
260 }
261
262 if (expected.getColumnDimension() != observed.getColumnDimension() ||
263 expected.getRowDimension() != observed.getRowDimension()) {
264 StringBuffer messageBuffer = new StringBuffer(msg);
265 messageBuffer.append("\nObserved has incorrect dimensions.");
266 messageBuffer.append("\nobserved is " + observed.getRowDimension() +
267 " x " + observed.getColumnDimension());
268 messageBuffer.append("\nexpected " + expected.getRowDimension() +
269 " x " + expected.getColumnDimension());
270 Assert.fail(messageBuffer.toString());
271 }
272
273 RealMatrix delta = expected.subtract(observed);
274 if (delta.getNorm() >= tolerance) {
275 StringBuffer messageBuffer = new StringBuffer(msg);
276 messageBuffer.append("\nExpected: " + expected);
277 messageBuffer.append("\nObserved: " + observed);
278 messageBuffer.append("\nexpected - observed: " + delta);
279 Assert.fail(messageBuffer.toString());
280 }
281 }
282
283 /** verifies that two matrices are equal */
284 public static void assertEquals(FieldMatrix<? extends FieldElement<?>> expected,
285 FieldMatrix<? extends FieldElement<?>> observed) {
286
287 if (observed == null) {
288 Assert.fail("Observed is null");
289 }
290
291 if (expected.getColumnDimension() != observed.getColumnDimension() ||
292 expected.getRowDimension() != observed.getRowDimension()) {
293 StringBuffer messageBuffer = new StringBuffer();
294 messageBuffer.append("Observed has incorrect dimensions.");
295 messageBuffer.append("\nobserved is " + observed.getRowDimension() +
296 " x " + observed.getColumnDimension());
297 messageBuffer.append("\nexpected " + expected.getRowDimension() +
298 " x " + expected.getColumnDimension());
299 Assert.fail(messageBuffer.toString());
300 }
301
302 for (int i = 0; i < expected.getRowDimension(); ++i) {
303 for (int j = 0; j < expected.getColumnDimension(); ++j) {
304 FieldElement<?> eij = expected.getEntry(i, j);
305 FieldElement<?> oij = observed.getEntry(i, j);
306 Assert.assertEquals(eij, oij);
307 }
308 }
309 }
310
311 /** verifies that two arrays are close (sup norm) */
312 public static void assertEquals(String msg, double[] expected, double[] observed,
313 double tolerance) {
314 StringBuffer out = new StringBuffer(msg);
315 if (expected.length != observed.length) {
316 out.append("\n Arrays not same length. \n");
317 out.append("expected has length ");
318 out.append(expected.length);
319 out.append(" observed length = ");
320 out.append(observed.length);
321 Assert.fail(out.toString());
322 }
323 boolean failure = false;
324 for (int i=0; i < expected.length; i++) {
325 try {
326 assertEquals(expected[i], observed[i], tolerance);
327 } catch (AssertionFailedError ex) {
328 failure = true;
329 out.append("\n Elements at index ");
330 out.append(i);
331 out.append(" differ. ");
332 out.append(" expected = ");
333 out.append(expected[i]);
334 out.append(" observed = ");
335 out.append(observed[i]);
336 }
337 }
338 if (failure) {
339 Assert.fail(out.toString());
340 }
341 }
342
343 /** verifies that two arrays are equal */
344 public static <T extends FieldElement<T>> void assertEquals(T[] m, T[] n) {
345 if (m.length != n.length) {
346 Assert.fail("vectors not same length");
347 }
348 for (int i = 0; i < m.length; i++) {
349 Assert.assertEquals(m[i],n[i]);
350 }
351 }
352
353 }