/*
* Copyright 2007-2009 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
package org.visage.runtime;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Collection;
import java.util.HashSet;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.visage.runtime.sequence.Sequence;
import org.visage.runtime.sequence.Sequences;
import junit.framework.Assert;
import junit.framework.TestCase;
/**
* VisageTestCase
*
* @author Brian Goetz
*/
public abstract class VisageTestCase extends TestCase {
private static final double EPSILON = 0.0001;
private final Pattern methodWithQualifiers = Pattern.compile("(.*)\\((.*)\\)");
/**
* Helper method for asserting that a sequence contains a specific set of values;
* test equality of toString(), by iterating the elements, and by toArray
*/
protected <T> void assertEquals(Sequence<? extends T> sequence, T... values) {
final int length = sequence.size();
assertEquals(length, values.length);
int index = 0;
for (T t : sequence) {
assertEquals(t, values[index++]);
}
StringBuffer sb = new StringBuffer();
sb.append("[");
for (int i = 0; i < values.length; i++) {
if (i != 0)
sb.append(",");
sb.append(" ");
sb.append(values[i]);
}
sb.append(" ]");
assertEquals(sb.toString(), sequence.toString());
T[] array = Util.<T>newObjectArray(length);
sequence.toArray(0, length, array, 0);
assertEquals(array.length, values.length);
for (int i = 0; i < array.length; i++)
assertEquals(array[i], values[i]);
}
protected void assertEquals(Sequence<? extends Double> sequence, Double... values) {
assertEquals(sequence.size(), values.length);
int index = 0;
for (Double t : sequence) {
Double value = values[index++];
assertTrue(value + " !~ " + t, Math.abs(t - value) < EPSILON);
}
}
protected void assertArrayEquals(Double[] expected, Double ... values) {
assertEquals(expected.length, values.length);
int index = 0;
for (Double t : expected) {
Double value = values[index++];
assertTrue(value + " !~ " + t, Math.abs(t - value) < EPSILON);
}
}
protected void assertEquals(Sequence<? extends Float> sequence, Float... values) {
assertEquals(sequence.size(), values.length);
int index = 0;
for (Float f : sequence) {
Float value = values[index++];
assertTrue(value + " !~ " + f, Math.abs(f - value) < EPSILON);
}
}
protected void assertArrayEquals(Float[] expected, Float ... values) {
assertEquals(expected.length, values.length);
int index = 0;
for (Float f : expected) {
Float value = values[index++];
assertTrue(value + " !~ " + f, Math.abs(f - value) < EPSILON);
}
}
protected <T> void assertEquals(Sequence<? extends T> sequence, T value) {
if (value == null)
assertEquals(0, sequence.size());
else {
assertEquals(1, sequence.size());
assertEquals(sequence.get(0), value);
}
}
protected <T> void assertEquals(Sequence<? extends T> sequence, Sequence<? extends T> values) {
assertEquals((Object) sequence, (Object) values);
}
protected<T> void assertEquals(Collection<T> collection, T... values) {
Collection<T> newCollection = new HashSet<T>();
for (T val : values)
newCollection.add(val);
assertEquals(collection, newCollection);
}
protected void assertEquals(int[] array, int... values) {
assertEquals(array.length, values.length);
for (int i=0; i<array.length; i++)
assertEquals(array[i], values[i]);
}
protected void assertEquals(double[] array, double... values) {
assertEquals(array.length, values.length);
for (int i=0; i<array.length; i++)
assertEquals(array[i], values[i]);
}
protected void assertEquals(long[] array, long... values) {
assertEquals(array.length, values.length);
for (int i=0; i<array.length; i++)
assertEquals(array[i], values[i]);
}
protected void assertEquals(boolean[] array, boolean... values) {
assertEquals(array.length, values.length);
for (int i=0; i<array.length; i++)
assertEquals(array[i], values[i]);
}
protected interface VoidCallable {
public void call() throws Exception;
}
protected static void assertThrows(Class<? extends Exception> exceptionClass, VoidCallable closure) {
try {
closure.call();
fail("Expected exception " + exceptionClass.getCanonicalName());
}
catch (Exception e) {
if (!exceptionClass.isInstance(e))
throw new RuntimeException("Expecting exception " + exceptionClass.getCanonicalName() + "; found exception " + e.getClass().getCanonicalName(), e);
}
}
/**
* Assert that invoking the named method reflectively on the specified target with the specified arguments throws UOE.
* Because we try and guess the the signature from the arguments, and Class.getMethod() is picky, the methodName string
* can also take the form name(xxx), where each x is a one-character code for the formal type of the corresponding parameter, derived
* from the classfile format: B=byte, C=char, D=double, F=float, I=int, J=long, L=Object, S=short, Z=boolean, T=Object,
* or a sequence of the form Lpackage.classname;
* (for convenience, T is used for type parameters that erase to Object)
*/
protected void assertException(Class<? extends Throwable> clazz, Object target, String methodName, Object... arguments) {
Class[] classes = new Class[arguments.length];
for (int i=0; i<arguments.length; i++)
classes[i] = arguments[i].getClass();
Matcher matcher = methodWithQualifiers.matcher(methodName);
if (matcher.matches()) {
methodName = matcher.group(1);
String types = matcher.group(2);
for (int charIndex=0, paramIndex=0; charIndex<types.length(); charIndex++, paramIndex++) {
char ch = types.charAt(charIndex);
switch (ch) {
case 'B' : classes[paramIndex] = Byte.TYPE; break;
case 'C' : classes[paramIndex] = Character.TYPE; break;
case 'D' : classes[paramIndex] = Double.TYPE; break;
case 'F' : classes[paramIndex] = Float.TYPE; break;
case 'I' : classes[paramIndex] = Integer.TYPE; break;
case 'J' : classes[paramIndex] = Long.TYPE; break;
case 'L' : {
String rest = types.substring(charIndex+1);
int pos = rest.indexOf(';');
charIndex = pos;
String className = rest.substring(0, pos);
try {
classes[paramIndex] = Class.forName(className);
} catch (ClassNotFoundException e) {
fail("No such class " + className);
}
break;
}
case 'T' : classes[paramIndex] = Object.class; break;
case 'S' : classes[paramIndex] = Short.TYPE; break;
case 'Z' : classes[paramIndex] = Boolean.TYPE; break;
default: break;
}
}
}
Method m = null;
try {
m = target.getClass().getMethod(methodName, classes);
} catch (NoSuchMethodException e) {
fail("No such method " + methodName);
}
try {
m.invoke(target, arguments);
fail("Expected exception " + clazz.getName());
}
catch (InvocationTargetException e) {
// Can't do the test reflectively because of class loader issues :(
if (!e.getCause().getClass().getName().equals(clazz.getName()))
fail("Expected exception " + clazz.getName() + ", got " + e.getCause().toString());
}
catch (Exception e) {
fail("Unexpected exception in invoke: " + e.toString());
}
}
protected void assertUOE(Object target, String methodName, Object... arguments) {
assertException(UnsupportedOperationException.class, target, methodName, arguments);
}
}