/**
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.openejb.junit.context;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import org.junit.Test;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Hashtable;
public class UtilTest {
/*
* No setter method
*/
private String noSetter;
/**
* 0 parameter setter
*/
private String noParamSetter;
public void setNoParamSetter() {
}
/**
* Setter with multiple parameter
*/
private String multiParamSetter;
public void setMultiParamSetter(final String s1, final String s2) {
}
/**
* Setter isn't void
*/
private String notVoidSetter;
public String setNotVoidSetter(final String s) {
return null;
}
/**
* Setter has a primitive argument, but is supplied a null argument
*/
private int primitiveParamSetter;
public void setPrimitiveParamSetter(final int i) {
}
/**
* Setter has a different type of parameter
*/
private String wrongInstanceSetter;
public void setWrongInstanceSetter(final Integer i) {
}
/**
* A static setter with an instance field, which can't be a valid setter.
*/
private String staticSetterInstanceField;
private static void setStaticSetterInstanceField(final String s) {
}
private static abstract class AbstractClass {
private String abstractSetter;
abstract void setAbstractSetter(String s);
}
/*
* Setter is private, so it should be setAccessible
*/
private String privateSetter;
private void setPrivateSetter(final String s) {
}
/*
* Static setter and field
*/
private static String staticSetterStaticField;
public static void setStaticSetterStaticField(final String s) {
}
/**
* Instance setter for a static field
*/
private static String instanceSetterStaticField;
public void setInstanceSetterStaticField(final String s) {
}
/**
* Instance field
*/
private String instanceField;
public void setInstanceField(final String s) {
}
/**
* Primitive instance field and setter
*/
private int primitiveInstanceField;
public void setPrimitiveInstanceField(final int i) {
}
/*
* Two name matching setters, of which only one should be found
*/
private String twoSetter;
public void setTwoSetter(final String s, final String s1) {
}
public void setTwoSetter(final String s) {
}
/**
* 2 matching setters, should pick the most specific, ie. String
*/
private String twoAccessibleSetter;
public void setTwoAccessibleSetter(final String s) {
}
public void setTwoAccessibleSetter(final Object s) {
}
/**
* 2 matching setters, should pick the most specific, ie. IllegalArgumentException
*/
private IllegalArgumentException threeAccessibleNoExactMatchSetter;
public void setThreeAccessibleNoExactMatchSetter(final Object s) {
}
public void setThreeAccessibleNoExactMatchSetter(final Throwable s) {
}
public void setThreeAccessibleNoExactMatchSetter(final Exception s) {
}
/**
* Used to test failure of finding a setter, where a method with a name equal
* to the setter name exists. This would be cases where the method doesn't match
* a method
*/
private void findInvalidSetter(final String fieldName, final Object setValue) throws Exception {
// check the field exists
final Field field = getClass().getDeclaredField(fieldName);
// check a method with the correct name exists
final String setterName = "set" + Character.toUpperCase(fieldName.charAt(0)) + fieldName.substring(1);
boolean foundMethod = false;
for (final Method method : getClass().getDeclaredMethods()) {
if (setterName.equals(method.getName())) {
foundMethod = true;
break;
}
}
assertTrue("No Method exists with name: " + setterName, foundMethod);
// now check that the findSetter method returns null
final Method ret = Util.findSetter(getClass(), field, setValue);
assertNull("Invalid setter returned.", ret);
}
/**
* Used to test success of finding a setter, where a method with a name equal
* to the setter name exists and findSetter returns that method.
*
* @return found setter so further checks can be performed
*/
private Method findValidSetter(final String fieldName, final Object setValue) throws Exception {
// check the field exists
final Field field = getClass().getDeclaredField(fieldName);
// check a method with the correct name exists
final String setterName = "set" + Character.toUpperCase(fieldName.charAt(0)) + fieldName.substring(1);
Method foundMethod = null;
for (final Method method : getClass().getDeclaredMethods()) {
if (setterName.equals(method.getName())) {
foundMethod = method;
break;
}
}
assertNotNull("No Method exists with name: " + setterName, foundMethod);
// now check that the findSetter method returns the desired valid method
final Method ret = Util.findSetter(getClass(), field, setValue);
assertNotNull("Couldn't find setter.", ret);
assertEquals(foundMethod, ret);
return ret;
}
@Test
public void testFindSetterInvalidSetters() throws Exception {
findInvalidSetter("noParamSetter", "ValueString");
findInvalidSetter("multiParamSetter", "ValueString");
findInvalidSetter("notVoidSetter", "ValueString");
findInvalidSetter("primitiveParamSetter", null);
findInvalidSetter("wrongInstanceSetter", "ValueString");
findInvalidSetter("staticSetterInstanceField", "ValueString");
}
@Test
public void testFindSetterNoSetters() throws Exception {
final String fieldName = "noSetter";
final String setterName = "set" + Character.toUpperCase(fieldName.charAt(0)) + fieldName.substring(1);
final Field field = getClass().getDeclaredField(fieldName);
try {
getClass().getDeclaredMethod(setterName, String.class);
} catch (final NoSuchMethodException e) {
}
final Method method = Util.findSetter(getClass(), field, "ValueString");
assertNull("Setter found.", method);
}
@Test
public void testFindSetterAbstractSetter() throws Exception {
final String fieldName = "abstractSetter";
final String setterName = "set" + Character.toUpperCase(fieldName.charAt(0)) + fieldName.substring(1);
final Field field = AbstractClass.class.getDeclaredField(fieldName);
// will fail if the method doesn't exist
AbstractClass.class.getDeclaredMethod(setterName, String.class);
final Method method = Util.findSetter(AbstractClass.class, field, "ValueString");
assertNull("Abstract setter returned.", method);
}
@Test
public void testFindSetterValidSetters() throws Exception {
findValidSetter("staticSetterStaticField", "ValueString");
findValidSetter("instanceSetterStaticField", "ValueString");
findValidSetter("instanceField", "ValueString");
findValidSetter("primitiveInstanceField", 1);
final Method privateMethod = findValidSetter("privateSetter", "ValueString");
assertTrue(privateMethod.isAccessible());
}
@Test
public void testFindSetterDualValidSetters() throws Exception {
final String fieldName = "twoSetter";
// check the field exists
final Field field = getClass().getDeclaredField(fieldName);
// check a method with the correct name exists
final String setterName = "set" + Character.toUpperCase(fieldName.charAt(0)) + fieldName.substring(1);
getClass().getDeclaredMethod(setterName, String.class, String.class);
final Method setterMethod = getClass().getDeclaredMethod(setterName, String.class);
// now check that the findSetter method returns null
final Method ret = Util.findSetter(getClass(), field, "ValueString");
assertNotNull("Couldn't find setter.", ret);
assertEquals(setterMethod, ret);
}
@Test
public void testFindSetterBestMatchSetters() throws Exception {
final String fieldName = "twoAccessibleSetter";
// check the field exists
final Field field = getClass().getDeclaredField(fieldName);
// check a method with the correct name exists
final String setterName = "set" + Character.toUpperCase(fieldName.charAt(0)) + fieldName.substring(1);
getClass().getDeclaredMethod(setterName, Object.class);
final Method setterMethod = getClass().getDeclaredMethod(setterName, String.class);
// now check that the findSetter method returns null
final Method ret = Util.findSetter(getClass(), field, "ValueString");
assertNotNull("Couldn't find setter.", ret);
assertEquals(setterMethod, ret);
}
@Test
public void testFindSetterThreeAccessibleNoExactMatchSetter() throws Exception {
final String fieldName = "threeAccessibleNoExactMatchSetter";
// check the field exists
final Field field = getClass().getDeclaredField(fieldName);
// check a method with the correct name exists
final String setterName = "set" + Character.toUpperCase(fieldName.charAt(0)) + fieldName.substring(1);
getClass().getDeclaredMethod(setterName, Object.class);
getClass().getDeclaredMethod(setterName, Throwable.class);
final Method setterMethod = getClass().getDeclaredMethod(setterName, Exception.class);
// now check that the findSetter method returns null
final Method ret = Util.findSetter(getClass(), field, new NumberFormatException());
assertNotNull("Couldn't find setter.", ret);
assertEquals(setterMethod, ret);
}
@Test
public void testAddProperty() {
checkAddProperty("name=value", "name", "value");
checkAddProperty("name=", "name", "");
checkAddProperty("name", "name", "");
checkAddProperty(" name=value ", "name", "value");
checkAddProperty(" name = value ", "name", "value");
checkAddProperty("name = value", "name", "value");
checkAddProperty(" name= ", "name", "");
checkAddProperty(" name = ", "name", "");
checkAddProperty("name =", "name", "");
checkAddProperty("name", "name", "");
checkAddProperty(" name", "name", "");
checkAddProperty(" name ", "name", "");
failAddProperty("=", IllegalArgumentException.class);
failAddProperty("=value", IllegalArgumentException.class);
failAddProperty(null, IllegalArgumentException.class);
failAddProperty("", IllegalArgumentException.class);
}
/**
* Checks if the addProperty method works, adding a property with the specified
* key/value
*
* @param property
* @param key
* @param value
*/
private void checkAddProperty(final String property, final String key, final String value) {
final Hashtable<String, String> hashtable = new Hashtable<String, String>();
Util.addProperty(hashtable, property);
assertEquals(1, hashtable.size());
assertNotNull(hashtable.get(key));
assertEquals(value, hashtable.get(key));
}
/**
* Runs the addProperty and fails if it succeeds
*
* @param property
* @param exceptionType the type of failure that should occur
*/
private void failAddProperty(final String property, final Class<?> exceptionType) {
try {
final Hashtable<String, String> hashtable = new Hashtable<String, String>();
Util.addProperty(hashtable, property);
fail("Add property succeeded where it shouldn't have.");
} catch (final Exception e) {
assertEquals(exceptionType, e.getClass());
}
}
/**
* Test for isInstance()
*/
@Test
public void testIsInstance() {
// check non primitives first
checkIsInstance(true, Object.class, null);
checkIsInstance(true, Object.class, "String");
checkIsInstance(true, String.class, "String");
checkIsInstance(false, Integer.class, "String");
// null primitive
checkIsInstance(false, int.class, null);
// then primitives.
// We check each for a match, and then both a non-match against a primitive and object
checkIsInstancePrimitive(boolean.class, true);
checkIsInstancePrimitive(char.class, 'a');
checkIsInstancePrimitive(byte.class, (byte) 1);
checkIsInstancePrimitive(short.class, (short) 1);
checkIsInstancePrimitive(int.class, 1);
checkIsInstancePrimitive(long.class, 1L);
checkIsInstancePrimitive(float.class, 1.0f);
checkIsInstancePrimitive(double.class, 1.0);
}
/**
* Runs a check against isInstance for a primitive type. It does 3 checks
* <ol>
* <li>A valid instance
* <li>An invalid primitive instance
* <li>An invalid non-primitive instance
* <ol>
*
* @param type
* @param validInstance
*/
private void checkIsInstancePrimitive(final Class<?> type, final Object validInstance) {
// the invalidPrimitive is an integer in all cases, except against class int.class
// where we use a long
final Object invalidPrimitive;
if (type == int.class) {
invalidPrimitive = 1L;
} else {
invalidPrimitive = 1;
}
checkIsInstance(true, type, validInstance);
checkIsInstance(false, type, invalidPrimitive);
checkIsInstance(false, type, "Object");
}
/**
* Runs a check against isInstance, checking if it returns the expected value
*
* @param type
* @param instance
* @param expected Expected return value
*/
private void checkIsInstance(final boolean expected, final Class<?> type, final Object instance) {
assertEquals(expected, Util.isInstance(type, instance));
}
/**
* Tests the most specific method test
*/
@Test
public void testGetMostSpecificMethod() throws Exception {
final Method mObject = getClass().getDeclaredMethod("setThreeAccessibleNoExactMatchSetter", Object.class);
final Method mThrowable = getClass().getDeclaredMethod("setThreeAccessibleNoExactMatchSetter", Throwable.class);
final Method mException = getClass().getDeclaredMethod("setThreeAccessibleNoExactMatchSetter", Exception.class);
assertEquals(mThrowable, Util.getMostSpecificMethod(mObject, mThrowable));
assertEquals(mException, Util.getMostSpecificMethod(mException, mThrowable));
assertEquals(mException, Util.getMostSpecificMethod(mException, mObject));
}
}