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

org.evosuite.symbolic.vm.SymbolicEnvironment 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.symbolic.vm;

import org.evosuite.dse.MainConfig;

import java.lang.reflect.Array;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Deque;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.Set;

import org.evosuite.symbolic.expr.ref.ReferenceExpression;
import org.evosuite.symbolic.instrument.ConcolicInstrumentingClassLoader;
import org.evosuite.testcase.execution.EvosuiteError;
import org.objectweb.asm.Type;

/**
 * 
 * @author galeotti
 * 
 */
public final class SymbolicEnvironment {

	/**
	 * Storage for symbolic information in the memory heap
	 */
	public final SymbolicHeap heap = new SymbolicHeap();

	/**
	 * Stack of function/method/constructor invocation frames
	 */
	private final Deque stackFrame = new LinkedList();

	/**
	 * Classes whose static fields have been set to the default zero value or a
	 * dummy value.
	 */
	private final Set> preparedClasses = new HashSet>();

	private final ConcolicInstrumentingClassLoader classLoader;

	public SymbolicEnvironment(ConcolicInstrumentingClassLoader classLoader) {
		this.classLoader = classLoader;
	}

	public Frame topFrame() {
		return stackFrame.peek();
	}

	public void pushFrame(Frame frame) {
		stackFrame.push(frame);
	}

	public Frame callerFrame() {
		Frame top = stackFrame.pop();
		Frame res = stackFrame.peek();
		stackFrame.push(top);
		return res;
	}

	public Frame popFrame() {
		return stackFrame.pop();
	}

	public Class ensurePrepared(String className) {
		Type ownerType = Type.getType(className);
		if (ownerType.getSort() == Type.ARRAY) {
			Type elemType = ownerType.getElementType();
			if (isValueType(elemType))
				return primitiveClassType(elemType);
			else {
				// ensurePrepared component class
				className = elemType.getClassName();
				Class claz = classLoader.getClassForName(className);
				ensurePrepared(claz);
				
				// returns claz[] instead of claz
				Class arrayClaz = Array.newInstance(claz, 0).getClass();
				return arrayClaz;
			}
		} else {
			Class claz = classLoader.getClassForName(className);
			ensurePrepared(claz);
			return claz;
		}
	}

	private Class primitiveClassType(Type t) {
		if (t.equals(Type.BOOLEAN_TYPE))
			return boolean[].class;
		if (t.equals(Type.CHAR_TYPE))
			return char[].class;
		if (t.equals(Type.SHORT_TYPE))
			return short[].class;
		if (t.equals(Type.BYTE_TYPE))
			return byte[].class;
		if (t.equals(Type.INT_TYPE))
			return int[].class;
		if (t.equals(Type.LONG_TYPE))
			return long[].class;
		if (t.equals(Type.FLOAT_TYPE))
			return float[].class;
		if (t.equals(Type.DOUBLE_TYPE))
			return double[].class;

		throw new EvosuiteError(t.toString()
				+ " is not a primitive value class!");

	}

	private boolean isValueType(Type t) {
		return t.equals(Type.BOOLEAN_TYPE) || t.equals(Type.CHAR_TYPE)
				|| t.equals(Type.SHORT_TYPE) || t.equals(Type.BYTE_TYPE)
				|| t.equals(Type.INT_TYPE) || t.equals(Type.LONG_TYPE)
				|| t.equals(Type.FLOAT_TYPE) || t.equals(Type.DOUBLE_TYPE);
	}

	public void ensurePrepared(Class claz) {
		if (preparedClasses.contains(claz))
			return; // done, we have prepared this class earlier

		Class superClass = claz.getSuperclass();
		if (superClass != null)
			ensurePrepared(superClass); // prepare super class first

		String className = claz.getCanonicalName();
		if (className == null) {
			// no canonical name
		}
		/*
		 * Field[] fields = claz.getDeclaredFields();
		 * 
		 * final boolean isIgnored = MainConfig.get().isIgnored(className);
		 * 
		 * for (Field field : fields) {
		 * 
		 * final int fieldModifiers = field.getModifiers(); if (isIgnored &&
		 * Modifier.isPrivate(fieldModifiers)) continue; // skip private field
		 * of ignored class.
		 * 
		 * }
		 */
		preparedClasses.add(claz);

	}

	/**
	 * Prepare stack of function invocation frames.
	 * 
	 * Clear function invocation stack, push a frame that pretends to call the
	 * method under test. We push variables for our method onto the
	 * pseudo-callers stack, so our method can pop them from there.
	 */
	public void prepareStack(Method mainMethod) {
		stackFrame.clear();
		// bottom of the stack trace
		this.pushFrame(new FakeBottomFrame());

		// frame for argument purposes
		final FakeMainCallerFrame fakeMainCallerFrame = new FakeMainCallerFrame(
				mainMethod, MainConfig.get().MAX_LOCALS_DEFAULT); // fake caller
																	// of method
																	// under
																	// test

		if (mainMethod != null) {
			boolean isInstrumented = isInstrumented(mainMethod);
			fakeMainCallerFrame.invokeInstrumentedCode(isInstrumented);
			String[] emptyStringArray = new String[] {};
			ReferenceExpression emptyStringRef = heap.getReference(emptyStringArray);
			fakeMainCallerFrame.operandStack.pushRef(emptyStringRef);
		}
		this.pushFrame(fakeMainCallerFrame);
	}

	/**
	 * @return method is instrumented. It is neither native nor declared by an
	 *         ignored JDK class, etc.
	 */
	private static boolean isInstrumented(Method method) {
		if (Modifier.isNative(method.getModifiers()))
			return false;

		String declClass = method.getDeclaringClass().getCanonicalName();
		return !MainConfig.get().isIgnored(declClass);
	}

	public boolean isEmpty() {
		return stackFrame.isEmpty();
	}

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy