/* This file is part of JSMAA. (c) Tommi Tervonen, 2009 JSMAA is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. JSMAA 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 for more details. You should have received a copy of the GNU General Public License along with JSMAA. If not, see <http://www.gnu.org/licenses/>. */ package org.drugis.common; import static org.easymock.EasyMock.createMock; import static org.easymock.EasyMock.expectLastCall; import static org.easymock.EasyMock.not; import static org.easymock.EasyMock.replay; import static org.easymock.EasyMock.reportMatcher; import static org.easymock.EasyMock.verify; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Collection; import java.util.EventObject; import java.util.HashSet; import java.util.List; import java.util.Set; import javax.swing.event.TableModelEvent; import javax.swing.event.TableModelListener; import com.jgoodies.binding.beans.Observable; import com.jgoodies.binding.value.ValueModel; public class JUnitUtil { public static void testSetter(Observable source, String propertyName, Object oldValue, Object newValue) { PropertyChangeListener mock = mockListener(source, propertyName, oldValue, newValue); source.addPropertyChangeListener(mock); Object desc = null; try { getSetterMethod(source, propertyName, newValue).invoke(source, newValue); desc = getGetterMethod(source, propertyName).invoke(source); } catch (Exception e) { fail(e.toString()); } assertEquals(newValue, desc); verify(mock); } public static PropertyChangeListener mockListener(Object source, String propertyName, Object oldValue, Object newValue) { PropertyChangeListener mock = createMock(PropertyChangeListener.class); PropertyChangeEvent event = new PropertyChangeEvent( source, propertyName, oldValue, newValue); mock.propertyChange(eqPropertyChangeEvent(event)); mock.propertyChange(not(eqPropertyChangeEvent(event))); expectLastCall().anyTimes(); replay(mock); return mock; } public static PropertyChangeListener mockAnyTimesListener(Object source, String propertyName, Object oldValue, Object newValue) { PropertyChangeListener mock = createMock(PropertyChangeListener.class); PropertyChangeEvent event = new PropertyChangeEvent( source, propertyName, oldValue, newValue); mock.propertyChange(eqPropertyChangeEvent(event)); expectLastCall().anyTimes(); mock.propertyChange(not(eqPropertyChangeEvent(event))); expectLastCall().anyTimes(); replay(mock); return mock; } public static PropertyChangeListener mockMultipleCallListener(Object source, String propertyName, Object oldValue, Object newValue) { PropertyChangeListener mock = createMock(PropertyChangeListener.class); PropertyChangeEvent event = new PropertyChangeEvent( source, propertyName, oldValue, newValue); mock.propertyChange(eqPropertyChangeEvent(event)); expectLastCall().atLeastOnce(); mock.propertyChange(not(eqPropertyChangeEvent(event))); expectLastCall().anyTimes(); replay(mock); return mock; } public static PropertyChangeListener mockStrictListener(Object source, String propertyName, Object oldValue, Object newValue) { PropertyChangeListener mock = createMock(PropertyChangeListener.class); PropertyChangeEvent event = new PropertyChangeEvent( source, propertyName, oldValue, newValue); mock.propertyChange(eqPropertyChangeEvent(event)); replay(mock); return mock; } public static TableModelListener mockTableModelListener(TableModelEvent expected) { TableModelListener mock = createMock(TableModelListener.class); mock.tableChanged((TableModelEvent)eqEventObject(expected)); replay(mock); return mock; } private static Method getGetterMethod(Observable source, String propertyName) throws NoSuchMethodException { return source.getClass().getMethod(deriveGetter(propertyName)); } private static Method getSetterMethod(Observable source, String propertyName, Object newValue) throws NoSuchMethodException { Method[] methods = source.getClass().getMethods(); for (Method m : methods) { if (m.getName().equals(deriveSetter(propertyName))) { return m; } } throw new NoSuchMethodException("Cannot find method " + deriveSetter(propertyName) + " of class " + source.getClass().getCanonicalName()); } private static Method get1ParamMethod(Observable source, String methodName, Object methodParam) throws NoSuchMethodException { // TODO: we should check that the method has 1 param and that the param is correct type Method[] methods = source.getClass().getMethods(); for (Method m : methods) { if (m.getName().equals(methodName)) { return m; } } throw new NoSuchMethodException("no method " + methodName); } private static String deriveGetter(String propertyName) { return "get" + capitalize(propertyName); } private static String deriveSetter(String propertyName) { return "set" + capitalize(propertyName); } private static String capitalize(String propertyName) { return propertyName.substring(0, 1).toUpperCase() + propertyName.substring(1); } public static PropertyChangeEvent eqPropertyChangeEvent(PropertyChangeEvent in) { reportMatcher(new PropertyChangeEventMatcher(in, false)); return null; } public static PropertyChangeEvent eqPropertyChangeEventIgnoreValues(PropertyChangeEvent in) { reportMatcher(new PropertyChangeEventMatcher(in, true)); return null; } public static EventObject eqEventObject(EventObject in) { reportMatcher(new EventObjectMatcher(in)); return null; } @SuppressWarnings("unchecked") public static <T> void testAdder(Observable source, String propertyName, String methodName, T toAdd) { List<T> list1 = new ArrayList<T>(); List<T> list2 = new ArrayList<T>(); list2.add(toAdd); PropertyChangeListener mock = mockListener(source, propertyName, list1, list2); source.addPropertyChangeListener(mock); Object actual = null; try { get1ParamMethod(source, methodName, toAdd).invoke(source, toAdd); actual = getGetterMethod(source, propertyName).invoke(source); } catch (Exception e) { fail(e.toString()); } assertTrue(((List<T>) actual).contains(toAdd)); assertTrue(1 == ((List<T>) actual).size()); verify(mock); } @SuppressWarnings("unchecked") public static <T> void testAdderSet(Observable source, String propertyName, String methodName, T toAdd) { Set<T> list1 = new HashSet<T>(); Set<T> list2 = new HashSet<T>(); list2.add(toAdd); PropertyChangeListener mock = mockListener(source, propertyName, list1, list2); source.addPropertyChangeListener(mock); Object actual = null; try { get1ParamMethod(source, methodName, toAdd).invoke(source, toAdd); actual = getGetterMethod(source, propertyName).invoke(source); } catch (Exception e) { fail(e.toString()); } assertTrue(((Set<T>) actual).contains(toAdd)); assertTrue(1 == ((Set<T>) actual).size()); verify(mock); } @SuppressWarnings("unchecked") public static <T> void testDeleter(Observable source, String propertyName, String deleteMethodName, T toDelete) throws Exception { List<T> list1 = new ArrayList<T>(); List<T> list2 = new ArrayList<T>(); list1.add(toDelete); // set the parameter getSetterMethod(source, propertyName, list1).invoke(source, list1); PropertyChangeListener mock = mockListener(source, propertyName, list1, list2); source.addPropertyChangeListener(mock); get1ParamMethod(source, deleteMethodName, toDelete).invoke(source, toDelete); Object actual = getGetterMethod(source, propertyName).invoke(source); assertTrue(0 == ((List<T>) actual).size()); verify(mock); } @SuppressWarnings("unchecked") public static <T> void testDeleterSet(Observable source, String propertyName, String deleteMethodName, T toDelete) throws Exception { Set<T> list1 = new HashSet<T>(); Set<T> list2 = new HashSet<T>(); list1.add(toDelete); // set the parameter getSetterMethod(source, propertyName, list1).invoke(source, list1); PropertyChangeListener mock = mockListener(source, propertyName, list1, list2); source.addPropertyChangeListener(mock); get1ParamMethod(source, deleteMethodName, toDelete).invoke(source, toDelete); Object actual = getGetterMethod(source, propertyName).invoke(source); assertTrue(0 == ((Set<T>) actual).size()); verify(mock); } public static void assertNotEquals(Object expected, Object actual) { if (expected == null) { assertTrue(actual != null); } else { assertFalse(expected.equals(actual)); } } @SuppressWarnings("unchecked") public static <B> B serializeObject(B b) throws Exception { ByteArrayOutputStream bos = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(bos); oos.writeObject(b); ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray()); ObjectInputStream ois = new ObjectInputStream(bis); return (B) ois.readObject(); } public static void testSetter(ValueModel vm, Object oldValue, Object newValue) { PropertyChangeListener mock = mockListener(vm, "value", oldValue, newValue); vm.addValueChangeListener(mock); vm.setValue(newValue); assertEquals(newValue, vm.getValue()); verify(mock); } public static void assertAllAndOnly(Collection<?> expected, Collection<?> actual) { if (!expected.containsAll(actual)) { throw new AssertionError("AllAndOnly: expected does not contain the actual.\n" + "expected = " + expected + " actual = " + actual); } if (!actual.containsAll(expected)) { throw new AssertionError("AllAndOnly: actual does not contain the expected.\n" + "expected = " + expected + " actual = " + actual); } } }