1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    * 
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   * 
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  
18  package org.apache.commons.math;
19  
20  import java.io.ByteArrayInputStream;
21  import java.io.ByteArrayOutputStream;
22  import java.io.IOException;
23  import java.io.ObjectInputStream;
24  import java.io.ObjectOutputStream;
25  
26  import junit.framework.Assert;
27  import junit.framework.AssertionFailedError;
28  
29  import org.apache.commons.math.complex.Complex;
30  import org.apache.commons.math.complex.ComplexFormat;
31  
32  /**
33   * @version $Revision: 611492 $ $Date: 2008-01-12 14:52:16 -0700 (Sat, 12 Jan 2008) $
34   */
35  public class TestUtils {
36      /**
37       * Collection of static methods used in math unit tests.
38       */
39      private TestUtils() {
40          super();
41      }
42  
43      /**
44       * Verifies that expected and actual are within delta, or are both NaN or
45       * infinities of the same sign.
46       */
47      public static void assertEquals(double expected, double actual, double delta) {
48          assertEquals(null, expected, actual, delta);
49      }
50  
51      /**
52       * Verifies that expected and actual are within delta, or are both NaN or
53       * infinities of the same sign.
54       */
55      public static void assertEquals(String msg, double expected, double actual, double delta) {
56          // check for NaN
57          if(Double.isNaN(expected)){
58              Assert.assertTrue("" + actual + " is not NaN.",
59                  Double.isNaN(actual));
60          } else {
61              Assert.assertEquals(msg, expected, actual, delta);
62          }
63      }
64      
65      /**
66       * Verifies that the two arguments are exactly the same, either
67       * both NaN or infinities of same sign, or identical floating point values.
68       */
69      public static void assertSame(double expected, double actual) {
70       assertEquals(expected, actual, 0);
71      }
72      
73      /**
74       * Verifies that real and imaginary parts of the two complex arguments
75       * are exactly the same.  Also ensures that NaN / infinite components match.
76       */
77      public static void assertSame(Complex expected, Complex actual) {
78          assertSame(expected.getReal(), actual.getReal());
79          assertSame(expected.getImaginary(), actual.getImaginary());
80      }
81      
82      /**
83       * Verifies that real and imaginary parts of the two complex arguments
84       * differ by at most delta.  Also ensures that NaN / infinite components match.
85       */
86      public static void assertEquals(Complex expected, Complex actual, double delta) {
87          assertEquals(expected.getReal(), actual.getReal(), delta);
88          assertEquals(expected.getImaginary(), actual.getImaginary(), delta);
89      }
90      
91      /**
92       * Verifies that two double arrays have equal entries, up to tolerance
93       */
94      public static void assertEquals(double a[], double b[], double tolerance) {
95          Assert.assertEquals(a.length, b.length);
96          for (int i = 0; i < a.length; i++) {
97              Assert.assertEquals(a[i], b[i], tolerance);
98          }
99      }
100     
101     /**
102      * Serializes an object to a bytes array and then recovers the object from the bytes array.
103      * Returns the deserialized object.
104      * 
105      * @param o  object to serialize and recover
106      * @return  the recovered, deserialized object
107      */
108     public static Object serializeAndRecover(Object o) {
109         try {
110             // serialize the Object
111             ByteArrayOutputStream bos = new ByteArrayOutputStream();
112             ObjectOutputStream so = new ObjectOutputStream(bos);
113             so.writeObject(o);
114 
115             // deserialize the Object
116             ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
117             ObjectInputStream si = new ObjectInputStream(bis);
118             return si.readObject();
119         } catch (IOException ioe) {
120             return null;
121         } catch (ClassNotFoundException cnfe) {
122             return null;
123         }
124     }
125     
126     /**
127      * Verifies that serialization preserves equals and hashCode.
128      * Serializes the object, then recovers it and checks equals and hash code.
129      * 
130      * @param object  the object to serialize and recover
131      */
132     public static void checkSerializedEquality(Object object) {
133         Object object2 = serializeAndRecover(object);
134         Assert.assertEquals("Equals check", object, object2);
135         Assert.assertEquals("HashCode check", object.hashCode(), object2.hashCode());
136     }
137 
138     /**
139      * Verifies that the relative error in actual vs. expected is less than or
140      * equal to relativeError.  If expected is infinite or NaN, actual must be
141      * the same (NaN or infinity of the same sign).
142      * 
143      * @param expected expected value
144      * @param actual  observed value
145      * @param relativeError  maximum allowable relative error
146      */
147     public static void assertRelativelyEquals(double expected, double actual,
148             double relativeError) {
149         assertRelativelyEquals(null, expected, actual, relativeError);
150     }
151     
152     /**
153      * Verifies that the relative error in actual vs. expected is less than or
154      * equal to relativeError.  If expected is infinite or NaN, actual must be
155      * the same (NaN or infinity of the same sign).
156      * 
157      * @param msg  message to return with failure
158      * @param expected expected value
159      * @param actual  observed value
160      * @param relativeError  maximum allowable relative error
161      */
162     public static void assertRelativelyEquals(String msg, double expected,
163             double actual, double relativeError) {
164         if (Double.isNaN(expected)) {
165             Assert.assertTrue(msg, Double.isNaN(actual));
166         } else if (Double.isNaN(actual)) {
167             Assert.assertTrue(msg, Double.isNaN(expected));
168         } else if (Double.isInfinite(actual) || Double.isInfinite(expected)) {
169             Assert.assertEquals(expected, actual, relativeError);
170         } else if (expected == 0.0) {
171             Assert.assertEquals(msg, actual, expected, relativeError);
172         } else {
173             double x = Math.abs((expected - actual) / expected);
174             Assert.assertEquals(msg, 0.0, x, relativeError);
175         }
176     }
177     
178     /**
179      * Fails iff values does not contain a number within epsilon of z.
180      * 
181      * @param msg  message to return with failure
182      * @param values complex array to search
183      * @param z  value sought
184      * @param epsilon  tolerance
185      */
186     public static void assertContains(String msg, Complex[] values,
187             Complex z, double epsilon) {
188         int i = 0;
189         boolean found = false;
190         while (!found && i < values.length) {
191             try {
192                 assertEquals(values[i], z, epsilon);
193                 found = true; 
194             } catch (AssertionFailedError er) {
195                 // no match
196             }
197             i++;
198         }
199         if (!found) {
200             Assert.fail(msg + 
201                 " Unable to find " + ComplexFormat.formatComplex(z));
202         }
203     }
204     
205     /**
206      * Fails iff values does not contain a number within epsilon of z.
207      * 
208      * @param values complex array to search
209      * @param z  value sought
210      * @param epsilon  tolerance
211      */
212     public static void assertContains(Complex[] values,
213             Complex z, double epsilon) {
214         assertContains(null, values, z, epsilon);      
215     }
216     
217     /**
218      * Fails iff values does not contain a number within epsilon of x.
219      * 
220      * @param msg  message to return with failure
221      * @param values double array to search
222      * @param x value sought
223      * @param epsilon  tolerance
224      */
225     public static void assertContains(String msg, double[] values,
226             double x, double epsilon) {
227         int i = 0;
228         boolean found = false;
229         while (!found && i < values.length) {
230             try {
231                 assertEquals(values[i], x, epsilon);
232                 found = true; 
233             } catch (AssertionFailedError er) {
234                 // no match
235             }
236             i++;
237         }
238         if (!found) {
239             Assert.fail(msg + " Unable to find" + x);
240         }
241     }
242     
243     /**
244      * Fails iff values does not contain a number within epsilon of x.
245      * 
246      * @param values double array to search
247      * @param x value sought
248      * @param epsilon  tolerance
249      */
250     public static void assertContains(double[] values, double x,
251             double epsilon) {
252        assertContains(null, values, x, epsilon);
253     }
254     
255 }