/** * Copyright (C) 2010-2017 Gordon Fraser, Andrea Arcuri and EvoSuite * contributors * * This file is part of EvoSuite. * * EvoSuite is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published * by the Free Software Foundation, either version 3.0 of the License, or * (at your option) any later version. * * EvoSuite 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 * Lesser Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with EvoSuite. If not, see <http://www.gnu.org/licenses/>. */ package org.evosuite.assertion; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Locale; import java.util.Map; import org.apache.commons.lang3.ClassUtils; import org.evosuite.Properties; import org.evosuite.runtime.mock.MockList; import org.evosuite.setup.TestUsageChecker; import org.evosuite.utils.JdkPureMethodsList; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class InspectorManager { private static InspectorManager instance = null; private static Logger logger = LoggerFactory .getLogger(InspectorManager.class); private final Map<Class<?>, List<Inspector>> inspectors = new HashMap<Class<?>, List<Inspector>>(); private final Map<String, List<String>> blackList = new HashMap<String, List<String>>(); private InspectorManager() { // TODO: Need to replace this with proper analysis // readInspectors(); initializeBlackList(); } private void initializeBlackList() { // These methods will include absolute path names and should not be in assertions blackList.put( "java.io.File", Arrays.asList(new String[] { "getPath", "getAbsolutePath", "getCanonicalPath" })); blackList.put("java.io.DataOutputStream", Arrays.asList(new String[] { "size"})); // These methods will contain locale specific strings blackList.put("java.util.Date", Arrays.asList(new String[] { "getLocaleString" })); // These methods will include data differing in every run blackList.put( "java.lang.Thread", Arrays.asList(new String[] { "activeCount", "getId", "getName", "getPriority", "toString", "getState", "isAlive" })); blackList.put( "java.lang.ThreadGroup", Arrays.asList(new String[] { "activeCount", "activeGroupCount", "getMaxPriority", "isDaemon", "isDestroyed", "toString" })); blackList.put("java.util.EventObject", Arrays.asList(new String[] { "toString" })); blackList.put(Locale.class.getCanonicalName(), Arrays.asList(new String[] { "getDisplay" })); blackList.put("java.util.Hashtable", Arrays.asList(new String[] { "toString" })); blackList.put("java.util.HashSet", Arrays.asList(new String[] { "toString" })); blackList.put("java.util.HashMap", Arrays.asList(new String[] { "toString" })); blackList.put("java.util.AbstractMap", Arrays.asList(new String[] { "toString" })); blackList.put("java.util.AbstractCollection", Arrays.asList(new String[] { "toString" })); blackList.put("java.util.logging.Logger", Arrays.asList(new String[] { "getUseParentHandlers" })); // AWT identifiers are different with every run blackList.put("java.awt.Panel", Arrays.asList(new String[] { "toString" })); blackList.put("java.awt.event.ActionEvent", Arrays.asList(new String[] { "toString" })); // TODO: Figure out how to make AWT/Swing component status deterministic between headless/non-headless blackList.put("java.awt.Component", Arrays.asList(new String[] { "toString", "isVisible", "isForegroundSet", "isBackgroundSet", "isFontSet", "isCursorSet", "isDisplayable", "isEnabled", "isFocusable", "isFocusOwner", "isFocusTraversable", "isLightweight", "isMaximumSizeSet", "isMinimumSizeSet", "isPreferredSizeSet", "isShowing", "isValid", "isVisible"})); blackList.put("java.awt.Container", Arrays.asList(new String[] { "countComponents", "getComponentCount", "isForegroundSet", "isBackgroundSet", "isFontSet" })); blackList.put("java.awt.event.MouseWheelEvent", Arrays.asList(new String[] { "toString" })); blackList.put("javax.swing.DefaultListSelectionModel", Arrays.asList(new String[] { "toString" })); blackList.put("javax.swing.JPopupMenu", Arrays.asList(new String[] { "isFontSet", "getComponentCount", "isForegroundSet", "isBackgroundSet", "isFontSet" })); blackList.put("javax.swing.JInternalFrame", Arrays.asList(new String[] {"getComponentCount", "countComponents", "isForegroundSet", "isBackgroundSet", "isFontSet"})); blackList.put("javax.swing.text.StyleContext", Arrays.asList(new String[] { "toString" })); blackList.put("java.rmi.server.ObjID", Arrays.asList(new String[] { "toString" })); blackList.put("java.awt.event.InvocationEvent", Arrays.asList(new String[] { "getWhen"})); blackList.put("java.lang.StringBuffer", Arrays.asList(new String[] { "capacity"})); } /** * <p> * Getter for the field <code>instance</code>. * </p> * * @return a {@link org.evosuite.assertion.InspectorManager} object. */ public static InspectorManager getInstance() { if (instance == null) { instance = new InspectorManager(); } return instance; } public static void resetSingleton() { instance=null; } private boolean isInspectorMethod(Method method) { if (!Modifier.isPublic(method.getModifiers())) return false; if (!method.getReturnType().isPrimitive() && !method.getReturnType().equals(String.class) && !method.getReturnType().isEnum() && !ClassUtils.isPrimitiveWrapper(method.getReturnType())) { return false; } if (method.getReturnType().equals(void.class)) return false; if (method.getParameterTypes().length != 0) return false; if (method.getName().equals("hashCode")) return false; if (method.getDeclaringClass().equals(Object.class)) return false; if (method.getDeclaringClass().equals(Enum.class)) return false; if (method.isSynthetic()) return false; if (method.isBridge()) return false; if (method.getName().equals("pop")) return false; if (isBlackListed(method)) return false; if (isImpureJDKMethod(method)) return false; if(isAWTToString(method)) return false; if (Properties.PURE_INSPECTORS) { if (!CheapPurityAnalyzer.getInstance().isPure(method)) { return false; } } return true; } private boolean isImpureJDKMethod(Method method) { String className = method.getDeclaringClass().getCanonicalName(); if (!className.startsWith("java.")) return false; return !JdkPureMethodsList.instance.isPureJDKMethod(method); } private boolean isAWTToString(Method method) { String className = method.getDeclaringClass().getCanonicalName(); if(className.startsWith("javax.") || className.startsWith("java.awt.")) { if(method.getName().equals("toString")) return true; } return false; } private boolean isBlackListed(Method method) { String className = method.getDeclaringClass().getCanonicalName(); if(MockList.isAMockClass(className)) { className = method.getDeclaringClass().getSuperclass().getCanonicalName(); } if (!blackList.containsKey(className)) return false; String methodName = method.getName(); return blackList.get(className).contains(methodName); } private void determineInspectors(Class<?> clazz) { if (!TestUsageChecker.canUse(clazz)) { inspectors.put(clazz, Collections.emptyList()); } if (!TestUsageChecker.canUse(clazz)) return; List<Inspector> inspectorList = new ArrayList<Inspector>(); for (Method method : clazz.getMethods()) { if (isInspectorMethod(method)) { // FIXXME logger.debug("Inspector for class " + clazz.getSimpleName() + ": " + method.getName() + " defined in " + method.getDeclaringClass().getCanonicalName()); inspectorList.add(new Inspector(clazz, method)); } else { logger.debug("Not an inspector: "+method.getName()); } } inspectors.put(clazz, inspectorList); } /** * <p> * Getter for the field <code>inspectors</code>. * </p> * * @param clazz * a {@link java.lang.Class} object. * @return a {@link java.util.List} object. */ public List<Inspector> getInspectors(Class<?> clazz) { if (!inspectors.containsKey(clazz)) { determineInspectors(clazz); } return inspectors.get(clazz); } /** * <p> * removeInspector * </p> * * @param clazz * a {@link java.lang.Class} object. * @param inspector * a {@link org.evosuite.assertion.Inspector} object. */ public void removeInspector(Class<?> clazz, Inspector inspector) { if (inspectors.containsKey(clazz)) { inspectors.get(clazz).remove(inspector); } } }