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    }