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 }