/** * 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.setup; import org.apache.commons.lang3.StringUtils; import org.evosuite.PackageInfo; import org.evosuite.TestGenerationContext; import org.evosuite.runtime.Reflection; import org.evosuite.runtime.mock.MockList; import org.evosuite.runtime.util.ReflectionUtils; import org.junit.Test; import org.junit.runners.Suite; import org.objectweb.asm.Type; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.util.*; /** * Set of pure static methods */ public class TestClusterUtils { protected static final Logger logger = LoggerFactory.getLogger(TestClusterUtils.class); /* Only final constants and caches should instantiated in this class */ private static final List<String> classExceptions = Collections.unmodifiableList(Arrays.asList(new String[] { "com.apple.", "apple.", "sun.", "com.sun.", "com.oracle.", "sun.awt." })); private final static Map<Class<?>, Set<Field>> accessibleFieldCache = new LinkedHashMap<>(); private final static Map<Class<?>, Set<Method>> methodCache = new LinkedHashMap<>(); /** * Determine if this class contains JUnit tests * @deprecated use {@code org.evosuite.junit.CoverageAnalysis.isTest(Class<?> cls)} * * @param className * @return */ @Deprecated public static boolean isTest(String className) { // TODO-JRO Identifying tests should be done differently: // If the class either contains methods // annotated with @Test (> JUnit 4.0) // or contains Test or Suite in it's inheritance structure try { Class<?> clazz = TestGenerationContext.getInstance().getClassLoaderForSUT().loadClass(className); Class<?> superClazz = clazz.getSuperclass(); while (!superClazz.equals(Object.class)) { if (superClazz.equals(Suite.class)) return true; if (superClazz.equals(Test.class)) return true; superClazz = clazz.getSuperclass(); } for (Method method : clazz.getMethods()) { if (method.isAnnotationPresent(Test.class)) { return true; } } } catch (ClassNotFoundException e) { logger.info("Could not load class: ", className); } return false; } public static boolean isAnonymousClass(String className) { int pos = className.lastIndexOf('$'); if(pos < 0) return false; char firstLetter = className.charAt(pos + 1); if(firstLetter >= '0' && firstLetter <= '9') return true; return false; } public static void makeAccessible(Field field) { if (!Modifier.isPublic(field.getModifiers()) || !Modifier.isPublic(field.getDeclaringClass().getModifiers())) { field.setAccessible(true); } } public static void makeAccessible(Method method) { if (!Modifier.isPublic(method.getModifiers()) || !Modifier.isPublic(method.getDeclaringClass().getModifiers())) { method.setAccessible(true); } } public static void makeAccessible(Constructor<?> constructor) { if (!Modifier.isPublic(constructor.getModifiers()) || !Modifier.isPublic(constructor.getDeclaringClass().getModifiers())) { constructor.setAccessible(true); } } public static boolean isEvoSuiteClass(Class<?> c) { return c.getName().startsWith(PackageInfo.getEvoSuitePackage()); //|| c.getName().equals("java.lang.String"); // This is now handled in addDependencyClass } /** * Calculate package distance between two classnames * * @param className1 * @param className2 * @return */ public static int getPackageDistance(String className1, String className2) { String[] package1 = StringUtils.split(className1, '.'); String[] package2 = StringUtils.split(className2, '.'); int distance = 0; int same = 1; int num = 0; while (num < package1.length && num < package2.length && package1[num].equals(package2[num])) { same++; num++; } if (package1.length > same) distance += package1.length - same; if (package2.length > same) distance += package2.length - same; return distance; } /** * Check if we can use the given class directly in a JUnit test * * @param className * a {@link String} object. * @return a boolean. */ public static boolean checkIfCanUse(String className) { if (MockList.shouldBeMocked(className)) { return false; } for (String s : classExceptions) { if (className.startsWith(s)) { return false; } } return true; } /** * Get the set of constructors defined in this class and its superclasses * * @param clazz * @return */ public static Set<Constructor<?>> getConstructors(Class<?> clazz) { Map<String, Constructor<?>> helper = new TreeMap<>(); Set<Constructor<?>> constructors = new LinkedHashSet<>(); for (Constructor<?> c : Reflection.getDeclaredConstructors(clazz)) { helper.put(org.objectweb.asm.Type.getConstructorDescriptor(c), c); } for (Constructor<?> c : helper.values()) { constructors.add(c); } return constructors; } /** * Get the set of fields defined in this class and its superclasses * * @param clazz * @return */ public static Set<Field> getFields(Class<?> clazz) { // TODO: Helper not necessary here! Map<String, Field> helper = new TreeMap<>(); Set<Field> fields = new LinkedHashSet<>(); if (clazz.getSuperclass() != null) { for (Field f : getFields(clazz.getSuperclass())) { helper.put(f.toGenericString(), f); } } for (Class<?> in : Reflection.getInterfaces(clazz)) { for (Field f : getFields(in)) { helper.put(f.toGenericString(), f); } } for (Field f : Reflection.getDeclaredFields(clazz)) { helper.put(f.toGenericString(), f); } fields.addAll(helper.values()); return fields; } public static boolean hasStaticGenerator(Class<?> clazz) { for(Method m : ReflectionUtils.getMethods(clazz)) { if(Modifier.isStatic(m.getModifiers())) { if(clazz.isAssignableFrom(m.getReturnType())) { return true; } } } return false; } /** * Get the set of fields defined in this class and its superclasses * * @param clazz * @return */ public static Set<Field> getAccessibleFields(Class<?> clazz) { if(accessibleFieldCache.containsKey(clazz)) { return accessibleFieldCache.get(clazz); } Set<Field> fields = new LinkedHashSet<>(); for (Field f : Reflection.getFields(clazz)) { if (TestUsageChecker.canUse(f) && !Modifier.isFinal(f.getModifiers())) { fields.add(f); } } accessibleFieldCache.put(clazz, fields); return fields; } /** * Get the set of methods defined in this class and its superclasses * * @param clazz * @return */ public static Set<Method> getMethods(Class<?> clazz) { // As this is expensive, doing some caching here // Note that with the change of a class loader the cached values could // be thrown away if(methodCache.containsKey(clazz)) { return methodCache.get(clazz); } Map<String, Method> helper = new TreeMap<String, Method>(); if (clazz.getSuperclass() != null) { for (Method m : getMethods(clazz.getSuperclass())) { helper.put(m.getName() + org.objectweb.asm.Type.getMethodDescriptor(m), m); } } for (Class<?> in : Reflection.getInterfaces(clazz)) { for (Method m : getMethods(in)) { helper.put(m.getName() + org.objectweb.asm.Type.getMethodDescriptor(m), m); } } for (Method m : Reflection.getDeclaredMethods(clazz)) { helper.put(m.getName() + org.objectweb.asm.Type.getMethodDescriptor(m), m); } Set<Method> methods = new LinkedHashSet<>(); methods.addAll(helper.values()); methodCache.put(clazz, methods); return methods; } public static Method getMethod(Class<?> clazz, String methodName, String desc) { for (Method method : Reflection.getMethods(clazz)) { if (method.getName().equals(methodName) && Type.getMethodDescriptor(method).equals(desc)) return method; } return null; } public static Class<?> getClass(String className) { try { Class<?> clazz = Class.forName(className, true, TestGenerationContext.getInstance().getClassLoaderForSUT()); return clazz; } catch (ClassNotFoundException e) { return null; } catch (NoClassDefFoundError e) { // an ExceptionInInitializationError might have happened during class initialization. return null; } } }