org.evosuite.setup.ConcreteClassAnalyzer Maven / Gradle / Ivy
The newest version!
/**
* Copyright (C) 2010-2018 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 .
*/
package org.evosuite.setup;
import org.evosuite.Properties;
import org.evosuite.TestGenerationContext;
import org.evosuite.runtime.mock.MockList;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.lang.reflect.Modifier;
import java.util.*;
public class ConcreteClassAnalyzer {
private static Logger logger = LoggerFactory.getLogger(ConcreteClassAnalyzer.class);
private static ConcreteClassAnalyzer instance;
private ConcreteClassAnalyzer() {
}
public static ConcreteClassAnalyzer getInstance() {
if(instance == null)
instance = new ConcreteClassAnalyzer();
return instance;
}
private Map, Set>> cache = new LinkedHashMap<>();
public void clear() {
cache.clear();
}
public Set> getConcreteClasses(Class> clazz,
InheritanceTree inheritanceTree) {
if(cache.containsKey(clazz))
return cache.get(clazz);
Set> classes = getConcreteClassesImpl(clazz, inheritanceTree);
cache.put(clazz, classes);
return classes;
}
private Set> getConcreteClassesImpl(Class> clazz,
InheritanceTree inheritanceTree) {
// Some special cases
if (clazz.equals(java.util.Map.class))
return getConcreteClassesMap();
else if (clazz.equals(java.util.List.class))
return getConcreteClassesList();
else if (clazz.equals(Set.class))
return getConcreteClassesSet();
else if (clazz.equals(java.util.Collection.class))
return getConcreteClassesList();
else if (clazz.equals(java.util.Iterator.class))
// We don't want to explicitly create iterators
// This would only pull in java.util.Scanner, the only
// concrete subclass
return new LinkedHashSet>();
else if (clazz.equals(java.util.ListIterator.class))
// We don't want to explicitly create iterators
return new LinkedHashSet>();
else if (clazz.equals(java.io.Serializable.class))
return new LinkedHashSet>();
else if (clazz.equals(Comparable.class))
return getConcreteClassesComparable();
else if (clazz.equals(java.util.Comparator.class))
return new LinkedHashSet>();
else if (clazz.equals(java.io.Reader.class))
return getConcreteClassesReader();
else if (clazz.equals(java.io.Writer.class))
return getConcreteClassesWriter();
Set> actualClasses = new LinkedHashSet>();
if (Modifier.isAbstract(clazz.getModifiers())
|| Modifier.isInterface(clazz.getModifiers()) || clazz.equals(Enum.class)) {
// We have to use getName here and not getCanonicalName
// because getCanonicalname uses . rather than $ for inner classes
// but the InheritanceTree uses $
String className = clazz.getName();
if(MockList.isAMockClass(className))
className = clazz.getSuperclass().getName();
Set subClasses = inheritanceTree.getSubclasses(className);
logger.debug("Subclasses of " + clazz.getName() + ": " + subClasses);
Map classDistance = new HashMap();
int maxDistance = -1;
String name = clazz.getName();
if (clazz.equals(Enum.class)) {
name = Properties.TARGET_CLASS;
}
for (String subClass : subClasses) {
int distance = TestClusterUtils.getPackageDistance(subClass, name);
classDistance.put(subClass, distance);
maxDistance = Math.max(distance, maxDistance);
}
int distance = 0;
while (actualClasses.isEmpty() && distance <= maxDistance) {
logger.debug(" Current distance: " + distance);
for (String subClass : subClasses) {
if (TestClusterUtils.isAnonymousClass(subClass)) {
continue;
}
if (classDistance.get(subClass) == distance) {
try {
TestGenerationContext.getInstance().goingToExecuteSUTCode();
Class> subClazz = Class.forName(subClass,
false,
TestGenerationContext.getInstance().getClassLoaderForSUT());
if (!TestUsageChecker.canUse(subClazz))
continue;
if (subClazz.isInterface())
continue;
if (Modifier.isAbstract(subClazz.getModifiers())) {
if(!TestClusterUtils.hasStaticGenerator(subClazz))
continue;
}
Class> mock = MockList.getMockClass(subClazz.getCanonicalName());
if (mock != null) {
/*
* If we are mocking this class, then such class should not be used
* in the generated JUnit test cases, but rather its mock.
*/
logger.debug("Adding mock " + mock + " instead of "
+ clazz);
subClazz = mock;
} else {
if (!TestClusterUtils.checkIfCanUse(subClazz.getCanonicalName())) {
continue;
}
}
actualClasses.add(subClazz);
} catch (ClassNotFoundException | IncompatibleClassChangeError | NoClassDefFoundError e) {
logger.error("Problem for " + Properties.TARGET_CLASS
+ ". Class not found: " + subClass, e);
logger.error("Removing class from inheritance tree");
inheritanceTree.removeClass(subClass);
} finally {
TestGenerationContext.getInstance().doneWithExecutingSUTCode();
}
}
}
distance++;
}
if(TestClusterUtils.hasStaticGenerator(clazz)) {
actualClasses.add(clazz);
}
if (actualClasses.isEmpty()) {
logger.info("Don't know how to instantiate abstract class {}", clazz.getName());
}
} else {
actualClasses.add(clazz);
}
logger.debug("Subclasses of " + clazz.getName() + ": " + actualClasses);
return actualClasses;
}
private Set> getConcreteClassesMap() {
Set> mapClasses = new LinkedHashSet<>();
Class> mapClazz;
try {
mapClazz = Class.forName("java.util.HashMap",
false,
TestGenerationContext.getInstance().getClassLoaderForSUT());
mapClasses.add(mapClazz);
} catch (ClassNotFoundException e) {
logger.error(e.getMessage());
}
return mapClasses;
}
private Set> getConcreteClassesList() {
Set> mapClasses = new LinkedHashSet>();
Class> mapClazz;
try {
mapClazz = Class.forName("java.util.LinkedList",
false,
TestGenerationContext.getInstance().getClassLoaderForSUT());
mapClasses.add(mapClazz);
} catch (ClassNotFoundException e) {
logger.error(e.getMessage());
}
return mapClasses;
}
private Set> getConcreteClassesSet() {
Set> mapClasses = new LinkedHashSet>();
Class> setClazz;
try {
setClazz = Class.forName("java.util.LinkedHashSet",
false,
TestGenerationContext.getInstance().getClassLoaderForSUT());
mapClasses.add(setClazz);
} catch (ClassNotFoundException e) {
logger.error(e.getMessage());
}
return mapClasses;
}
private Set> getConcreteClassesReader() {
Set> mapClasses = new LinkedHashSet>();
Class> setClazz;
try {
setClazz = Class.forName("java.io.StringReader",
false,
TestGenerationContext.getInstance().getClassLoaderForSUT());
mapClasses.add(setClazz);
} catch (ClassNotFoundException e) {
logger.error(e.getMessage());
}
return mapClasses;
}
private Set> getConcreteClassesWriter() {
Set> mapClasses = new LinkedHashSet>();
Class> setClazz;
try {
setClazz = Class.forName("java.io.StringWriter",
false,
TestGenerationContext.getInstance().getClassLoaderForSUT());
mapClasses.add(setClazz);
} catch (ClassNotFoundException e) {
logger.error(e.getMessage());
}
return mapClasses;
}
private Set> getConcreteClassesComparable() {
Set> comparableClasses = new LinkedHashSet>();
Class> comparableClazz;
try {
comparableClazz = Class.forName("java.lang.Integer",
false,
TestGenerationContext.getInstance().getClassLoaderForSUT());
comparableClasses.add(comparableClazz);
} catch (ClassNotFoundException e) {
logger.error(e.getMessage());
}
return comparableClasses;
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy