All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.evosuite.runtime.classhandling.ClassStateSupport Maven / Gradle / Ivy

There is a newer version: 1.0.6
Show newest version
/**
 * 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 .
 */
package org.evosuite.runtime.classhandling;

import java.lang.instrument.UnmodifiableClassException;
import java.util.ArrayList;
import java.util.List;

import org.evosuite.runtime.LoopCounter;
import org.evosuite.runtime.RuntimeSettings;
import org.evosuite.runtime.agent.InstrumentingAgent;
import org.evosuite.runtime.instrumentation.InstrumentedClass;
import org.evosuite.runtime.sandbox.Sandbox;
import org.evosuite.runtime.util.AtMostOnceLogger;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;



/**
 * Class used to handle the static state of classes, their intialization and
 * re-instrumentation 
 * @author arcuri
 *
 */
public class ClassStateSupport {

	private static final Logger logger = LoggerFactory.getLogger(ClassStateSupport.class);

    /**
     * Load all the classes with given name with the provided input classloader.
     * Those classes are all supposed to be instrumented.
	 *
	 * 

* This method will usually be called in a @BeforeClass initialization *

* * @param classLoader * @param classNames */ public static boolean initializeClasses(ClassLoader classLoader, String... classNames) { boolean problem = false; List> classes = loadClasses(classLoader, classNames); if(classes.size() != classNames.length) { problem = true; } if(RuntimeSettings.isUsingAnyMocking()) { for (Class clazz : classes) { if(clazz.isInterface()) { /* FIXME: once we ll start to support Java 8, in which interfaces can have code, we ll need to instrument them as well */ continue; } if (!InstrumentedClass.class.isAssignableFrom(clazz)) { String msg = "Class " + clazz.getName() + " was not instrumented by EvoSuite. " + "This could happen if you are running JUnit tests in a way that is not handled by EvoSuite, in " + "which some classes are loaded be reflection before the tests are run. Consult the EvoSuite documentation " + "for possible workarounds for this issue."; logger.error(msg); problem = true; //throw new IllegalStateException(msg); // throwing an exception might be a bit too extreme } } } return problem; //retransformIfNeeded(classes); // cannot do it, as retransformation does not really work :( } /** * Reset the static state of all the given classes. * *

* This method will be usually called after a test is executed, ie in a @After *

* * @param classNames */ public static void resetClasses(String... classNames) { for (int i=0; i< classNames.length;i++) { String classNameToReset = classNames[i]; ClassResetter.getInstance().reset(classNameToReset); } } private static List> loadClasses(ClassLoader classLoader, String... classNames) { List> classes = new ArrayList<>(); InstrumentingAgent.activate(); boolean safe = Sandbox.isSafeToExecuteSUTCode(); //assert !Sandbox.isSecurityManagerInitialized() || Sandbox.isOnAndExecutingSUTCode(); for (int i=0; i< classNames.length;i++) { org.evosuite.runtime.Runtime.getInstance().resetRuntime(); String classNameToLoad = classNames[i]; Sandbox.goingToExecuteSUTCode(); boolean wasLoopCheckOn = LoopCounter.getInstance().isActivated(); try { if(!safe){ Sandbox.goingToExecuteUnsafeCodeOnSameThread(); } LoopCounter.getInstance().setActive(false); Class aClass = Class.forName(classNameToLoad, true, classLoader); classes.add(aClass); } catch (Exception | Error ex) { AtMostOnceLogger.error(logger,"Could not initialize " + classNameToLoad + ": " + ex.getMessage()); } finally { if(!safe){ Sandbox.doneWithExecutingUnsafeCodeOnSameThread(); } Sandbox.doneWithExecutingSUTCode(); LoopCounter.getInstance().setActive(wasLoopCheckOn); } } InstrumentingAgent.deactivate(); return classes; } // deprecated --------------------------------- /** * If any of the loaded class was not instrumented yet, then re-instrument them. * Note: re-instrumentation is more limited, as cannot change class signature */ @Deprecated public static void retransformIfNeeded(ClassLoader classLoader, String... classNames) { List> classes = new ArrayList<>(); for(String name : classNames) { try { classes.add(classLoader.loadClass(name)); } catch (ClassNotFoundException e) { java.lang.System.err.println("Could not load: "+name); } } retransformIfNeeded(classes); } /** * If any of the loaded class was not instrumented yet, then re-instrument them. * Note: re-instrumentation is more limited, as cannot change class signature * @param classes */ @Deprecated public static void retransformIfNeeded(List> classes) { if(classes==null || classes.isEmpty()){ return; } List> classToReInstrument = new ArrayList<>(); /* InstrumentingAgent.activate(); for(Class cl : classes){ try{ InstrumentingAgent.getInstumentation().retransformClasses(cl); } catch(UnsupportedOperationException e){ / * * this happens if class was already loaded by JUnit (eg the abstract class problem) * and re-instrumentation do change the signature * / classToReInstument.add(cl); } catch(Exception | Error e){ //this shouldn't really happen java.lang.System.err.println("Could not instrument "+cl.getName()+". Exception "+e.toString()); } } */ for(Class cl : classes) { if(!InstrumentingAgent.getTransformer().isClassAlreadyTransformed(cl.getName())) { classToReInstrument.add(cl); } } if(classToReInstrument.isEmpty()) { return; } InstrumentingAgent.setRetransformingMode(true); try { if(!classToReInstrument.isEmpty()) { InstrumentingAgent.getInstrumentation().retransformClasses(classToReInstrument.toArray(new Class[0])); } } catch (UnmodifiableClassException e) { //this shouldn't really happen, as already checked in previous loop java.lang.System.err.println("Could not re-instrument classes"); } catch(UnsupportedOperationException e) { //if this happens, then it is a bug in EvoSuite :( logger.error("EvoSuite wrong re-instrumentation: "+e.getMessage()); } finally { InstrumentingAgent.setRetransformingMode(false); } InstrumentingAgent.deactivate(); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy