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

org.evosuite.testcase.execution.ExecutionTraceImpl 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.testcase.execution;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Deque;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import org.evosuite.Properties;
import org.evosuite.TestGenerationContext;
import org.evosuite.Properties.Criterion;
import org.evosuite.coverage.branch.Branch;
import org.evosuite.coverage.branch.BranchPool;
import org.evosuite.coverage.dataflow.DefUse;
import org.evosuite.coverage.dataflow.DefUsePool;
import org.evosuite.coverage.dataflow.Definition;
import org.evosuite.coverage.dataflow.Use;
import org.evosuite.setup.CallContext;
import org.evosuite.statistics.RuntimeVariable;
import org.evosuite.utils.ArrayUtil;
import org.objectweb.asm.Opcodes;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Keep a trace of the program execution
 * 
 * @author Gordon Fraser
 */
public class ExecutionTraceImpl implements ExecutionTrace, Cloneable {

	@Deprecated
	public static class BranchEval {
		private final int branchId;
		private CallContext context = null;
		private final double falseDistance;
		private final double trueDistance;

		public BranchEval(int branchId, double trueDistance, double falseDistance) {
			this.branchId = branchId;
			this.trueDistance = trueDistance;
			this.falseDistance = falseDistance;
		}

		public BranchEval(int branchId, double trueDistance, double falseDistance, CallContext context) {
			this.branchId = branchId;
			this.trueDistance = trueDistance;
			this.falseDistance = falseDistance;
			this.context = context;
		}

		public int getBranchId() {
			return branchId;
		}

		public CallContext getContext() {
			return context;
		}

		public double getFalseDistance() {
			return falseDistance;
		}

		public double getTrueDistance() {
			return trueDistance;
		}

		@Override
		public String toString() {
			return "BranchEval [branchId=" + branchId + ", trueDistance=" + trueDistance + ", falseDistance="
					+ falseDistance + "]";
		}
	}

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

	/** Constant traceCalls=false */
	public static boolean traceCalls = false;

	public static boolean disableContext = false;

	/** Constant traceCoverage=true */
	public static boolean traceCoverage = true;

	private static void checkSaneCall(MethodCall call) {
		if (!((call.trueDistanceTrace.size() == call.falseDistanceTrace.size())
				&& (call.falseDistanceTrace.size() == call.defuseCounterTrace.size())
				&& (call.defuseCounterTrace.size() == call.branchTrace.size()))) {
			throw new IllegalStateException("insane MethodCall: traces should all be of equal size. " + call.explain());
		}

	}

	public static void enableContext() {
		// enableTraceCalls();
		disableContext = false;
	}

	public static void disableContext() {
		disableTraceCalls();
		disableContext = true;
	}

	/**
	 * 

* disableTraceCalls *

*/ public static void disableTraceCalls() { traceCalls = false; } /** *

* enableTraceCalls *

*/ public static void enableTraceCalls() { traceCalls = true; } public static boolean isTraceCallsEnabled() { return traceCalls; } /** *

* enableTraceCoverage *

*/ public static void enableTraceCoverage() { traceCoverage = true; } /** * Removes from the given ExecutionTrace all finished_calls with an index in * removableCalls */ private static void removeFinishCalls(ExecutionTraceImpl trace, ArrayList removableCalls) { Collections.sort(removableCalls); for (int i = removableCalls.size() - 1; i >= 0; i--) { int toRemove = removableCalls.get(i); MethodCall removed = trace.finishedCalls.remove(toRemove); if (removed == null) { throw new IllegalStateException("trace.finished_calls not allowed to contain null"); } } } /** * Removes from the given MethodCall all trace information with an index in * removableIndices */ private static void removeFromFinishCall(MethodCall call, ArrayList removableIndices) { checkSaneCall(call); Collections.sort(removableIndices); for (int i = removableIndices.size() - 1; i >= 0; i--) { int removableIndex = removableIndices.get(i); Integer removedBranch = call.branchTrace.remove(removableIndex); Double removedTrue = call.trueDistanceTrace.remove(removableIndex); Double removedFalse = call.falseDistanceTrace.remove(removableIndex); Integer removedCounter = call.defuseCounterTrace.remove(removableIndex); if ((removedCounter == null) || (removedBranch == null) || (removedTrue == null) || (removedFalse == null)) { throw new IllegalStateException("trace.finished_calls-traces not allowed to contain null"); } } } private List branchesTrace = new ArrayList(); // Coverage information public Map>> coverage = Collections .synchronizedMap(new HashMap>>()); public Map coveredFalse = Collections.synchronizedMap(new HashMap()); public Map coveredMethods = Collections.synchronizedMap(new HashMap()); public Map coveredBranchlessMethods = Collections.synchronizedMap(new HashMap()); public Map coveredPredicates = Collections.synchronizedMap(new HashMap()); public Map coveredTrue = Collections.synchronizedMap(new HashMap()); public Map coveredDefs = Collections.synchronizedMap(new HashMap()); public Map> coveredTrueContext = Collections .synchronizedMap(new HashMap>()); public Map> coveredFalseContext = Collections .synchronizedMap(new HashMap>()); public Map> coveredPredicateContext = Collections .synchronizedMap(new HashMap>()); public Map> coveredMethodContext = Collections .synchronizedMap(new HashMap>()); // number of seen Definitions and uses for indexing purposes private int duCounter = 0; // The last explicitly thrown exception is kept here private Throwable explicitException = null; public Map falseDistances = Collections.synchronizedMap(new HashMap()); private final Map falseDistancesSum = Collections.synchronizedMap(new HashMap()); // finished_calls; public List finishedCalls = Collections.synchronizedList(new ArrayList()); public Map knownCallerObjects = Collections.synchronizedMap(new HashMap()); // to differentiate between different MethodCalls private int methodId = 0; public Map mutantDistances = Collections.synchronizedMap(new HashMap()); // for defuse-coverage it is important to keep track of all the objects that // called the ExecutionTracer private int objectCounter = 0; // for each Variable-Name these maps hold the data for which objectID // at which time (duCounter) which Definition or Use was passed public Map>> passedDefinitions = Collections .synchronizedMap(new HashMap>>()); public Map>> passedUses = Collections .synchronizedMap(new HashMap>>()); public Map>> passedDefinitionObject = Collections .synchronizedMap(new HashMap>>()); public Map>> passedUseObject = Collections .synchronizedMap(new HashMap>>()); private int proxyCount = 1; // Data information public Map>> returnData = Collections .synchronizedMap(new HashMap>>()); // active calls LinkedList stack = new LinkedList<>(); public Set touchedMutants = Collections.synchronizedSet(new HashSet()); public Map trueDistances = Collections.synchronizedMap(new HashMap()); private final Map trueDistancesSum = Collections.synchronizedMap(new HashMap()); public static Set gradientBranches = Collections.synchronizedSet(new HashSet()); public static Set gradientBranchesCoveredTrue = Collections.synchronizedSet(new HashSet()); public static Set gradientBranchesCoveredFalse = Collections.synchronizedSet(new HashSet()); public static Map> bytecodeInstructionReached = Collections .synchronizedMap(new HashMap>()); public static Map> bytecodeInstructionCoveredTrue = Collections .synchronizedMap(new HashMap>()); public static Map> bytecodeInstructionCoveredFalse = Collections .synchronizedMap(new HashMap>()); /** *

* Constructor for ExecutionTraceImpl. *

*/ public ExecutionTraceImpl() { stack.add(new MethodCall("", "", 0, 0, 0)); // Main method } /** *

* addProxy *

*/ public void addProxy() { proxyCount++; } /** *

* removeProxy *

*/ public void removeProxy() { proxyCount--; } /** * {@inheritDoc} * * Add branch to currently active method call */ @Override public void branchPassed(int branch, int bytecode_id, double true_distance, double false_distance) { assert (true_distance >= 0.0); assert (false_distance >= 0.0); updateTopStackMethodCall(branch, bytecode_id, true_distance, false_distance); // TODO: property should really be called TRACK_GRADIENT_BRANCHES! if (Properties.TRACK_BOOLEAN_BRANCHES) { if ((true_distance != 0 && true_distance != 1) || (false_distance != 0 && false_distance != 1)) gradientBranches.add(branch); } if (traceCoverage) { if (!coveredPredicates.containsKey(branch)) coveredPredicates.put(branch, 1); else coveredPredicates.put(branch, coveredPredicates.get(branch) + 1); if (true_distance == 0.0) { if (!coveredTrue.containsKey(branch)) coveredTrue.put(branch, 1); else coveredTrue.put(branch, coveredTrue.get(branch) + 1); } if (false_distance == 0.0) { if (!coveredFalse.containsKey(branch)) coveredFalse.put(branch, 1); else coveredFalse.put(branch, coveredFalse.get(branch) + 1); } } if (Properties.TRACK_COVERED_GRADIENT_BRANCHES) { if (gradientBranches.contains(branch)) { if ((coveredTrue.containsKey(branch))) gradientBranchesCoveredTrue.add(branch); if ((coveredFalse.containsKey(branch))) gradientBranchesCoveredFalse.add(branch); } } if (Properties.BRANCH_COMPARISON_TYPES) { int opcode = BranchPool.getInstance(TestGenerationContext.getInstance().getClassLoaderForSUT()) .getBranch(branch).getInstruction().getASMNode().getOpcode(); int previousOpcode = -2; if (BranchPool.getInstance(TestGenerationContext.getInstance().getClassLoaderForSUT()).getBranch(branch) .getInstruction().getASMNode().getPrevious() != null) previousOpcode = BranchPool.getInstance(TestGenerationContext.getInstance().getClassLoaderForSUT()) .getBranch(branch).getInstruction().getASMNode().getPrevious().getOpcode(); boolean cTrue = coveredTrue.containsKey(branch); boolean cFalse = coveredFalse.containsKey(branch); switch (previousOpcode) { case Opcodes.LCMP: trackBranchOpcode(bytecodeInstructionReached, RuntimeVariable.Reached_lcmp, branch); if (cTrue) trackBranchOpcode(bytecodeInstructionCoveredTrue, RuntimeVariable.Covered_lcmp, branch); if (cFalse) trackBranchOpcode(bytecodeInstructionCoveredFalse, RuntimeVariable.Covered_lcmp, branch); break; case Opcodes.FCMPL: trackBranchOpcode(bytecodeInstructionReached, RuntimeVariable.Reached_fcmpl, branch); if (cTrue) trackBranchOpcode(bytecodeInstructionCoveredTrue, RuntimeVariable.Covered_fcmpl, branch); if (cFalse) trackBranchOpcode(bytecodeInstructionCoveredFalse, RuntimeVariable.Covered_fcmpl, branch); break; case Opcodes.FCMPG: trackBranchOpcode(bytecodeInstructionReached, RuntimeVariable.Reached_fcmpg, branch); if (cTrue) trackBranchOpcode(bytecodeInstructionCoveredTrue, RuntimeVariable.Covered_fcmpg, branch); if (cFalse) trackBranchOpcode(bytecodeInstructionCoveredFalse, RuntimeVariable.Covered_fcmpg, branch); break; case Opcodes.DCMPL: trackBranchOpcode(bytecodeInstructionReached, RuntimeVariable.Reached_dcmpl, branch); if (cTrue) trackBranchOpcode(bytecodeInstructionCoveredTrue, RuntimeVariable.Covered_dcmpl, branch); if (cFalse) trackBranchOpcode(bytecodeInstructionCoveredFalse, RuntimeVariable.Covered_dcmpl, branch); break; case Opcodes.DCMPG: trackBranchOpcode(bytecodeInstructionReached, RuntimeVariable.Reached_dcmpg, branch); if (cTrue) trackBranchOpcode(bytecodeInstructionCoveredTrue, RuntimeVariable.Covered_dcmpg, branch); if (cFalse) trackBranchOpcode(bytecodeInstructionCoveredFalse, RuntimeVariable.Covered_dcmpg, branch); break; } switch (opcode) { // copmpare int with zero case Opcodes.IFEQ: case Opcodes.IFNE: case Opcodes.IFLT: case Opcodes.IFGE: case Opcodes.IFGT: case Opcodes.IFLE: trackBranchOpcode(bytecodeInstructionReached, RuntimeVariable.Reached_IntZero, branch); if (cTrue) trackBranchOpcode(bytecodeInstructionCoveredTrue, RuntimeVariable.Covered_IntZero, branch); if (cFalse) trackBranchOpcode(bytecodeInstructionCoveredFalse, RuntimeVariable.Covered_IntZero, branch); break; // copmpare int with int case Opcodes.IF_ICMPEQ: case Opcodes.IF_ICMPNE: case Opcodes.IF_ICMPLT: case Opcodes.IF_ICMPGE: case Opcodes.IF_ICMPGT: case Opcodes.IF_ICMPLE: trackBranchOpcode(bytecodeInstructionReached, RuntimeVariable.Reached_IntInt, branch); if (cTrue) trackBranchOpcode(bytecodeInstructionCoveredTrue, RuntimeVariable.Covered_IntInt, branch); if (cFalse) trackBranchOpcode(bytecodeInstructionCoveredFalse, RuntimeVariable.Covered_IntInt, branch); break; // copmpare reference with reference case Opcodes.IF_ACMPEQ: case Opcodes.IF_ACMPNE: trackBranchOpcode(bytecodeInstructionReached, RuntimeVariable.Reached_RefRef, branch); if (cTrue) trackBranchOpcode(bytecodeInstructionCoveredTrue, RuntimeVariable.Covered_RefRef, branch); if (cFalse) trackBranchOpcode(bytecodeInstructionCoveredFalse, RuntimeVariable.Covered_RefRef, branch); break; // compare reference with null case Opcodes.IFNULL: case Opcodes.IFNONNULL: trackBranchOpcode(bytecodeInstructionReached, RuntimeVariable.Reached_RefNull, branch); if (cTrue) trackBranchOpcode(bytecodeInstructionCoveredTrue, RuntimeVariable.Covered_RefNull, branch); if (cFalse) trackBranchOpcode(bytecodeInstructionCoveredFalse, RuntimeVariable.Covered_RefNull, branch); break; } } if (!trueDistances.containsKey(branch)) trueDistances.put(branch, true_distance); else trueDistances.put(branch, Math.min(trueDistances.get(branch), true_distance)); if (!falseDistances.containsKey(branch)) falseDistances.put(branch, false_distance); else falseDistances.put(branch, Math.min(falseDistances.get(branch), false_distance)); if (!trueDistancesSum.containsKey(branch)) trueDistancesSum.put(branch, true_distance); else trueDistancesSum.put(branch, trueDistancesSum.get(branch) + true_distance); if (!falseDistancesSum.containsKey(branch)) falseDistancesSum.put(branch, false_distance); else falseDistancesSum.put(branch, falseDistancesSum.get(branch) + false_distance); if (!disableContext && (Properties.INSTRUMENT_CONTEXT || Properties.INSTRUMENT_METHOD_CALLS || ArrayUtil.contains(Properties.CRITERION, Criterion.IBRANCH) || ArrayUtil.contains(Properties.CRITERION, Criterion.CBRANCH))) { updateBranchContextMaps(branch, true_distance, false_distance); } // This requires a lot of memory and should not really be used if (Properties.BRANCH_EVAL) { branchesTrace.add(new BranchEval(branch, true_distance, false_distance)); } } /** * Track reach/coverage of branch based on it's underlying opcode during * execution * * @param trackedMap * relevant map for the variable type (one of the three static * maps) * @param v * branch type (based on opcode) * @param branch_id * of the tracked branch */ private void trackBranchOpcode(Map> trackedMap, RuntimeVariable v, int branch_id) { if (!trackedMap.containsKey(v)) trackedMap.put(v, new HashSet<>()); Set branchSet = trackedMap.get(v); branchSet.add(branch_id); trackedMap.put(v, branchSet); } /** * @param branch * @param true_distance * @param false_distance */ private void updateBranchContextMaps(int branch, double true_distance, double false_distance) { if (!coveredPredicateContext.containsKey(branch)) { coveredPredicateContext.put(branch, new HashMap<>()); coveredTrueContext.put(branch, new HashMap<>()); coveredFalseContext.put(branch, new HashMap<>()); } CallContext context = new CallContext(Thread.currentThread().getStackTrace()); if (!coveredPredicateContext.get(branch).containsKey(context)) { coveredPredicateContext.get(branch).put(context, 1); coveredTrueContext.get(branch).put(context, true_distance); coveredFalseContext.get(branch).put(context, false_distance); } else { coveredPredicateContext.get(branch).put(context, coveredPredicateContext.get(branch).get(context) + 1); coveredTrueContext.get(branch).put(context, Math.min(coveredTrueContext.get(branch).get(context), true_distance)); coveredFalseContext.get(branch).put(context, Math.min(coveredFalseContext.get(branch).get(context), false_distance)); } } /** * {@inheritDoc} * * Reset to 0 */ @Override public void clear() { finishedCalls = new ArrayList(); stack = new LinkedList(); // stack.clear(); // finished_calls.clear(); stack.add(new MethodCall("", "", 0, 0, 0)); // Main method coverage = new HashMap>>(); returnData = new HashMap>>(); methodId = 0; duCounter = 0; objectCounter = 0; knownCallerObjects = new HashMap(); trueDistances = new HashMap(); falseDistances = new HashMap(); mutantDistances = new HashMap(); touchedMutants = new HashSet(); coveredMethods = new HashMap(); coveredBranchlessMethods = new HashMap(); coveredPredicates = new HashMap(); coveredTrue = new HashMap(); coveredFalse = new HashMap(); coveredDefs = new HashMap(); passedDefinitions = new HashMap>>(); passedUses = new HashMap>>(); passedDefinitionObject = new HashMap>>(); passedUseObject = new HashMap>>(); branchesTrace = new ArrayList(); coveredTrueContext = new HashMap>(); coveredFalseContext = new HashMap>(); coveredPredicateContext = new HashMap>(); } /** * {@inheritDoc} * * Create a deep copy */ @Override public ExecutionTraceImpl clone() { ExecutionTraceImpl copy = new ExecutionTraceImpl(); for (MethodCall call : finishedCalls) { copy.finishedCalls.add(call.clone()); } // copy.finished_calls.addAll(finished_calls); copy.coverage = new HashMap>>(); if (coverage != null) { copy.coverage.putAll(coverage); } copy.returnData = new HashMap>>(); copy.returnData.putAll(returnData); /* * if(stack != null && !stack.isEmpty() && stack.peek().method_name != * null && stack.peek().method_name.equals("")) { logger.info( * "Copying main method"); copy.finished_calls.add(stack.peek()); } */ copy.trueDistances.putAll(trueDistances); copy.falseDistances.putAll(falseDistances); copy.coveredMethods.putAll(coveredMethods); copy.coveredBranchlessMethods.putAll(coveredBranchlessMethods); copy.coveredPredicates.putAll(coveredPredicates); copy.coveredTrue.putAll(coveredTrue); copy.coveredFalse.putAll(coveredFalse); copy.coveredDefs.putAll(coveredDefs); copy.touchedMutants.addAll(touchedMutants); copy.mutantDistances.putAll(mutantDistances); copy.passedDefinitions.putAll(passedDefinitions); copy.passedUses.putAll(passedUses); copy.passedDefinitionObject.putAll(passedDefinitionObject); copy.passedUseObject.putAll(passedUseObject); copy.branchesTrace.addAll(branchesTrace); copy.coveredTrueContext.putAll(coveredTrueContext); copy.coveredFalseContext.putAll(coveredFalseContext); copy.coveredPredicateContext.putAll(coveredPredicateContext); copy.methodId = methodId; copy.duCounter = duCounter; copy.objectCounter = objectCounter; copy.knownCallerObjects.putAll(knownCallerObjects); copy.proxyCount = 1; return copy; } /** * {@inheritDoc} * * Adds Definition-Use-Coverage trace information for the given definition. * * Registers the given caller-Object Traces the occurrence of the given * definition in the passedDefs-field Sets the given definition as the * currently active one for the definitionVariable in the * activeDefinitions-field Adds fake trace information to the currently * active MethodCall in this.stack */ @Override public void definitionPassed(Object object, Object caller, int defID) { if (!traceCalls) { return; } Definition def = DefUsePool.getDefinitionByDefId(defID); if (def == null) { throw new IllegalStateException("expect DefUsePool to known defIDs that are passed by instrumented code"); } if (!coveredDefs.containsKey(defID)) { coveredDefs.put(defID, 0); } else { coveredDefs.put(defID, coveredDefs.get(defID) + 1); } String varName = def.getVariableName(); int objectID = registerObject(caller); // if this is a static variable, treat objectID as zero for consistency // in the representation of static data if (objectID != 0 && def.isStaticDefUse()) objectID = 0; if (passedDefinitions.get(varName) == null) { passedDefinitions.put(varName, new HashMap>()); passedDefinitionObject.put(varName, new HashMap>()); } HashMap defs = passedDefinitions.get(varName).get(objectID); HashMap defsObject = passedDefinitionObject.get(varName).get(objectID); if (defs == null) { defs = new HashMap(); defsObject = new HashMap(); } defs.put(duCounter, defID); defsObject.put(duCounter, object); passedDefinitions.get(varName).put(objectID, defs); passedDefinitionObject.get(varName).put(objectID, defsObject); // logger.trace(duCounter+": set active definition for var // "+def.getDUVariableName()+" on object "+objectID+" to Def "+defID); duCounter++; } /** * {@inheritDoc} * * Add a new method call to stack */ @Override public void enteredMethod(String className, String methodName, Object caller) { if (traceCoverage) { String id = className + "." + methodName; if (!coveredMethods.containsKey(id)) { coveredMethods.put(id, 1); } else { coveredMethods.put(id, coveredMethods.get(id) + 1); } if (BranchPool.getInstance(TestGenerationContext.getInstance().getClassLoaderForSUT()) .isBranchlessMethod(className, id)) { if (!coveredBranchlessMethods.containsKey(id)) { coveredBranchlessMethods.put(id, 1); } else { coveredBranchlessMethods.put(id, coveredBranchlessMethods.get(id) + 1); } } } if (!className.isEmpty() && !methodName.isEmpty()) { if (traceCalls) { int callingObjectID = registerObject(caller); MethodCall call = new MethodCall(className, methodName, methodId, callingObjectID, stack.size()); methodId++; // TODO: Skip this? if (ArrayUtil.contains(Properties.CRITERION, Criterion.DEFUSE) || ArrayUtil.contains(Properties.CRITERION, Criterion.ALLDEFS)) { call.branchTrace.add(-1); call.trueDistanceTrace.add(1.0); call.falseDistanceTrace.add(0.0); call.defuseCounterTrace.add(duCounter); // TODO line_trace ? } stack.push(call); } if (!disableContext && (Properties.INSTRUMENT_CONTEXT || ArrayUtil.contains(Properties.CRITERION, Criterion.IBRANCH) || ArrayUtil.contains(Properties.CRITERION, Criterion.CBRANCH))) { updateMethodContextMaps(className, methodName, caller); } } } /** * @param className * @param methodName * @param caller */ private void updateMethodContextMaps(String className, String methodName, Object caller) { String id = className + "." + methodName; if (!coveredMethodContext.containsKey(id)) { coveredMethodContext.put(id, new HashMap<>()); } CallContext context = new CallContext(new Throwable().getStackTrace()); //CallContext context = new CallContext(stack); if (!coveredMethodContext.get(id).containsKey(context)) { coveredMethodContext.get(id).put(context, 1); } else { coveredMethodContext.get(id).put(context, coveredMethodContext.get(id).get(context) + 1); } } /** {@inheritDoc} */ @Override public boolean equals(Object obj) { if (this == obj) { return true; } if (obj == null) { return false; } if (getClass() != obj.getClass()) { return false; } ExecutionTraceImpl other = (ExecutionTraceImpl) obj; if (coverage == null) { if (other.coverage != null) { return false; } } else if (!coverage.equals(other.coverage)) { return false; } if (finishedCalls == null) { if (other.finishedCalls != null) { return false; } } else if (!finishedCalls.equals(other.finishedCalls)) { return false; } if (returnData == null) { if (other.returnData != null) { return false; } } else if (!returnData.equals(other.returnData)) { return false; } if (stack == null) { if (other.stack != null) { return false; } } else if (!stack.equals(other.stack)) { return false; } return true; } /** * {@inheritDoc} * * Pop last method call from stack */ @Override public void exitMethod(String classname, String methodname) { if (!classname.isEmpty() && !methodname.isEmpty()) { if(traceCalls) { if (!stack.isEmpty() && !(stack.peek().methodName.equals(methodname))) { // Handle cases where unexpected calls are on the stack if (stack.peek().methodName.isEmpty() && !stack.peek().branchTrace.isEmpty()) { finishedCalls.add(stack.pop()); } else { // Usually, this happens if we use mutation testing and // the mutation causes an unexpected exception or // timeout stack.pop(); } } else { finishedCalls.add(stack.pop()); } } } } /** {@inheritDoc} */ @Override public synchronized void finishCalls() { logger.debug("At the end, we have " + stack.size() + " calls left on stack"); while (!stack.isEmpty()) { finishedCalls.add(stack.pop()); } } /** {@inheritDoc} */ @Override public List getBranchesTrace() { return branchesTrace; } /* * (non-Javadoc) * * @see org.evosuite.testcase.ExecutionTrace#getCoverageData() */ /** {@inheritDoc} */ @Override public Map>> getCoverageData() { return coverage; } /* * (non-Javadoc) * * @see org.evosuite.testcase.ExecutionTrace#getCoveredFalseBranches() */ /** {@inheritDoc} */ @Override public Set getCoveredFalseBranches() { Set covered = new HashSet(); for (Entry entry : falseDistances.entrySet()) { if (entry.getValue() == 0.0) covered.add(entry.getKey()); } return covered; } /* * (non-Javadoc) * * @see org.evosuite.testcase.ExecutionTrace#getCoveredLines() */ /** {@inheritDoc} */ @Override public Set getCoveredLines(String className) { Set coveredLines = new HashSet(); for (Entry>> entry : coverage.entrySet()) { if ((entry.getKey().equals(className)) || // is it a internal class of 'className' ? (entry.getKey().startsWith(className + "$"))) { for (Map methodentry : entry.getValue().values()) { coveredLines.addAll(methodentry.keySet()); } } } return coveredLines; } @Override public Set getCoveredLines() { return this.getCoveredLines(Properties.TARGET_CLASS); } @Override public Set getAllCoveredLines() { Set coveredLines = new HashSet(); for (Entry>> entry : coverage.entrySet()) { for (Map methodentry : entry.getValue().values()) { coveredLines.addAll(methodentry.keySet()); } } return coveredLines; } /* * (non-Javadoc) * * @see org.evosuite.testcase.ExecutionTrace#getCoveredMethods() */ /** {@inheritDoc} */ @Override public Set getCoveredMethods() { return coveredMethods.keySet(); } @Override public Set getCoveredBranchlessMethods() { return coveredBranchlessMethods.keySet(); } /* * (non-Javadoc) * * @see org.evosuite.testcase.ExecutionTrace#getCoveredPredicates() */ /** {@inheritDoc} */ @Override public Set getCoveredPredicates() { return coveredPredicates.keySet(); } /* * (non-Javadoc) * * @see org.evosuite.testcase.ExecutionTrace#getCoveredTrueBranches() */ /** {@inheritDoc} */ @Override public Set getCoveredTrueBranches() { Set covered = new HashSet(); for (Entry entry : trueDistances.entrySet()) { if (entry.getValue() == 0.0) covered.add(entry.getKey()); } return covered; } /* * (non-Javadoc) * * @see org.evosuite.testcase.ExecutionTrace#getCoveredDefinitions() */ @Override public Set getCoveredDefinitions() { return coveredDefs.keySet(); } /* * (non-Javadoc) * * @see org.evosuite.testcase.ExecutionTrace#getDefinitionExecutionCount() */ @Override public Map getDefinitionExecutionCount() { return coveredDefs; } /* * (non-Javadoc) * * @see org.evosuite.testcase.ExecutionTrace#getDefinitionData() */ /** {@inheritDoc} */ @Override public Map>> getDefinitionData() { return passedDefinitions; } public Map>> getDefinitionDataObjects() { return passedDefinitionObject; } /** {@inheritDoc} */ @Override public Throwable getExplicitException() { return explicitException; } /* * (non-Javadoc) * * @see org.evosuite.testcase.ExecutionTrace#getFalseDistance(int) */ /** {@inheritDoc} */ @Override public double getFalseDistance(int branchId) { return falseDistances.get(branchId); } /* * (non-Javadoc) * * @see org.evosuite.testcase.ExecutionTrace#getFalseDistances() */ /** {@inheritDoc} */ @Override public Map getFalseDistances() { return falseDistances; } /* * (non-Javadoc) * * @see org.evosuite.testcase.ExecutionTrace#getMethodCalls() */ /** {@inheritDoc} */ @Override public List getMethodCalls() { return finishedCalls; } /* * (non-Javadoc) * * @see org.evosuite.testcase.ExecutionTrace#getMethodExecutionCount() */ /** {@inheritDoc} */ @Override public Map getMethodExecutionCount() { return coveredMethods; } /* * (non-Javadoc) * * @see org.evosuite.testcase.ExecutionTrace#getMutationDistance(int) */ /** {@inheritDoc} */ @Override public double getMutationDistance(int mutationId) { return mutantDistances.get(mutationId); } /* * (non-Javadoc) * * @see org.evosuite.testcase.ExecutionTrace#getMutationDistances() */ /** {@inheritDoc} */ @Override public Map getMutationDistances() { return mutantDistances; } /* * (non-Javadoc) * * @see org.evosuite.testcase.ExecutionTrace#getPassedDefinitions(java.lang. * String) */ /** {@inheritDoc} */ @Override public Map> getPassedDefinitions(String variableName) { return passedDefinitions.get(variableName); } /* * (non-Javadoc) * * @see org.evosuite.testcase.ExecutionTrace#getPassedUses(java.lang.String) */ /** {@inheritDoc} */ @Override public Map> getPassedUses(String variableName) { return passedUses.get(variableName); } /* * (non-Javadoc) * * @see org.evosuite.testcase.ExecutionTrace#getPredicateExecutionCount() */ /** {@inheritDoc} */ @Override public Map getPredicateExecutionCount() { return coveredPredicates; } /** *

* Getter for the field proxyCount. *

* * @return a int. */ public int getProxyCount() { return proxyCount; } /* * (non-Javadoc) * * @see org.evosuite.testcase.ExecutionTrace#getReturnData() */ /** {@inheritDoc} */ @Override public Map>> getReturnData() { return returnData; } /* * (non-Javadoc) * * @see org.evosuite.testcase.ExecutionTrace#getTouchedMutants() */ /** {@inheritDoc} */ @Override public Set getTouchedMutants() { return touchedMutants; } @Override public Set getInfectedMutants() { Set infectedMutants = new LinkedHashSet(); for (Entry entry : mutantDistances.entrySet()) { if (entry.getValue() == 0.0) { infectedMutants.add(entry.getKey()); } } return infectedMutants; } /** * {@inheritDoc} * * Returns a copy of this trace where all MethodCall-information traced from * objects other then the one identified by the given objectID is removed * from the finished_calls-field * * WARNING: this will not affect this.true_distances and other fields of * ExecutionTrace this only affects the finished_calls field (which should * suffice for BranchCoverageFitness-calculation) */ @Override public ExecutionTrace getTraceForObject(int objectId) { ExecutionTraceImpl r = clone(); ArrayList removableCalls = new ArrayList(); for (int i = 0; i < r.finishedCalls.size(); i++) { MethodCall call = r.finishedCalls.get(i); if ((call.callingObjectID != objectId) && (call.callingObjectID != 0)) { removableCalls.add(i); } } removeFinishCalls(r, removableCalls); return new ExecutionTraceProxy(r); } /** * {@inheritDoc} * * Returns a copy of this trace where all MethodCall-information associated * with duCounters outside the range of the given duCounter-Start and -End * is removed from the finished_calls-traces * * finished_calls without any point in the trace at which the given * duCounter range is hit are removed completely * * Also traces for methods other then the one that holds the given targetDU * are removed as well as trace information that would pass the branch of * the given targetDU If wantToCoverTargetDU is false instead those * targetDUBranch information is removed that would pass the alternative * branch of targetDU * * The latter is because this method only gets called when the given * targetDU was not active in the given duCounter-range if and only if * wantToCoverTargetDU is set, and since useFitness calculation is on branch * level and the branch of the targetDU can be passed before the targetDU is * passed this can lead to a flawed branchFitness. * * * WARNING: this will not affect this.true_distances and other fields of * ExecutionTrace this only affects the finished_calls field (which should * suffice for BranchCoverageFitness-calculation) */ @Override public ExecutionTrace getTraceInDUCounterRange(DefUse targetDU, boolean wantToCoverTargetDU, int duCounterStart, int duCounterEnd) { if (duCounterStart > duCounterEnd) { throw new IllegalArgumentException("start has to be lesser or equal end"); /* * // DONE: bug // this still has a major flaw: s. * MeanTestClass.mean(): // right now its like we map branches to * activeDefenitions // but especially in the root branch of a * method // activeDefenitions change during execution time // FIX: * in order to avoid these false positives remove all information // * for a certain branch if some information for that branch is * supposed to be removed // subTodo since branchPassed() only gets * called when a branch is passed initially // fake calls to * branchPassed() have to be made whenever a DU is passed // s. * definitionPassed(), usePassed() and * addFakeActiveMethodCallInformation() * * // DONE: new bug // turns out thats an over-approximation that * makes it // impossible to cover some potentially coverable goals * * // completely new: // if your definition gets overwritten in a * trace // the resulting fitness should be the fitness of not * taking the branch with the overwriting definition // DONE: in * order to do that don't remove older trace information for an * overwritten branch // but rather set the true and false distance * of that previous branch information to the distance of not taking * the overwriting branch // done differently: s. * DefUseCoverageTestFitness.getFitness() */ } ExecutionTraceImpl r = clone(); Branch targetDUBranch = targetDU.getControlDependentBranch(); ArrayList removableCalls = new ArrayList(); for (int callPos = 0; callPos < r.finishedCalls.size(); callPos++) { MethodCall call = r.finishedCalls.get(callPos); // check if call is for the method of targetDU if (!call.methodName.equals(targetDU.getMethodName())) { removableCalls.add(callPos); continue; } ArrayList removableIndices = new ArrayList(); for (int i = 0; i < call.defuseCounterTrace.size(); i++) { int currentDUCounter = call.defuseCounterTrace.get(i); int currentBranchBytecode = call.branchTrace.get(i); if (currentDUCounter < duCounterStart || currentDUCounter > duCounterEnd) removableIndices.add(i); else if (currentBranchBytecode == targetDUBranch.getInstruction().getInstructionId()) { // only remove this point in the trace if it would cover // targetDU boolean targetExpressionValue = targetDU.getControlDependentBranchExpressionValue(); if (targetExpressionValue) { if (call.trueDistanceTrace.get(i) == 0.0) removableIndices.add(i); } else { if (call.falseDistanceTrace.get(i) == 0.0) removableIndices.add(i); } } } removeFromFinishCall(call, removableIndices); if (call.defuseCounterTrace.size() == 0) removableCalls.add(callPos); } removeFinishCalls(r, removableCalls); return new ExecutionTraceProxy(r); } /* * (non-Javadoc) * * @see org.evosuite.testcase.ExecutionTrace#getTrueDistance(int) */ /** {@inheritDoc} */ @Override public double getTrueDistance(int branchId) { return trueDistances.get(branchId); } /* * (non-Javadoc) * * @see org.evosuite.testcase.ExecutionTrace#getTrueDistances() */ /** {@inheritDoc} */ @Override public Map getTrueDistances() { return trueDistances; } /* * (non-Javadoc) * * @see org.evosuite.testcase.ExecutionTrace#getUseData() */ /** {@inheritDoc} */ @Override public Map>> getUseData() { return passedUses; } public Map>> getUseDataObjects() { return passedUseObject; } /* * (non-Javadoc) * * @see org.evosuite.testcase.ExecutionTrace#wasCoveredFalse(int) */ /** {@inheritDoc} */ @Override public boolean hasFalseDistance(int predicateId) { return falseDistances.containsKey(predicateId); } /** {@inheritDoc} */ @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((coverage == null) ? 0 : coverage.hashCode()); result = prime * result + ((finishedCalls == null) ? 0 : finishedCalls.hashCode()); result = prime * result + ((returnData == null) ? 0 : returnData.hashCode()); result = prime * result + ((stack == null) ? 0 : stack.hashCode()); return result; } /* * (non-Javadoc) * * @see org.evosuite.testcase.ExecutionTrace#wasCoveredTrue(int) */ /** {@inheritDoc} */ @Override public boolean hasTrueDistance(int predicateId) { return trueDistances.containsKey(predicateId); } /* * (non-Javadoc) * * @see org.evosuite.testcase.ExecutionTrace#lazyClone() */ /** {@inheritDoc} */ @Override public ExecutionTrace lazyClone() { // TODO Auto-generated method stub return null; } private boolean stackHasMethod(String methodName) { for (MethodCall call : stack) { if (call.methodName.equals(methodName)) return true; } return false; } /** * {@inheritDoc} * * Add line to currently active method call */ @Override public void linePassed(String className, String methodName, int line) { if (traceCalls) { if (stack.isEmpty()) { logger.info("Method stack is empty: " + className + "." + methodName + " - l" + line); // TODO // switch // back // logger.debug to // logger.warn } else { boolean empty = false; if (!stack.peek().methodName.equals(methodName)) { if (stack.peek().methodName.equals("")) return; if (stackHasMethod(methodName)) { do { logger.debug("Popping method " + stack.peek().methodName + " because we were looking for " + methodName); finishedCalls.add(stack.pop()); } while (!stack.isEmpty() && !stack.peek().methodName.equals(methodName) && !stack.peek().methodName.equals("")); } else { logger.warn("Popping method " + stack.peek().methodName + " because we were looking for " + methodName); logger.warn("Current stack: " + stack); finishedCalls.add(stack.pop()); } if (stack.isEmpty()) { logger.warn("Method stack is empty: " + className + "." + methodName + " - l" + line); // TODO // switch // back empty = true; } } if (!empty) stack.peek().lineTrace.add(line); } } if (traceCoverage) { if (!coverage.containsKey(className)) { coverage.put(className, new HashMap>()); } if (!coverage.get(className).containsKey(methodName)) { coverage.get(className).put(methodName, new HashMap()); } if (!coverage.get(className).get(methodName).containsKey(line)) { coverage.get(className).get(methodName).put(line, 1); } else { coverage.get(className).get(methodName).put(line, coverage.get(className).get(methodName).get(line) + 1); } } } /** {@inheritDoc} */ @Override public void mutationPassed(int mutationId, double distance) { touchedMutants.add(mutationId); if (!mutantDistances.containsKey(mutationId)) { mutantDistances.put(mutationId, distance); } else { mutantDistances.put(mutationId, Math.min(distance, mutantDistances.get(mutationId))); } } /** * Returns the objecectId for the given object. * * The ExecutionTracer keeps track of all objects it gets called from in * order to distinguish them later in the fitness calculation for the * defuse-Coverage-Criterion. */ private int registerObject(Object caller) { if (caller == null) { return 0; } for (Integer objectId : knownCallerObjects.keySet()) { if (knownCallerObjects.get(objectId) == caller) { return objectId; } } // object unknown so far objectCounter++; knownCallerObjects.put(objectCounter, caller); return objectCounter; } /** {@inheritDoc} */ @Override public void returnValue(String className, String methodName, int value) { if (!returnData.containsKey(className)) { returnData.put(className, new HashMap>()); } if (!returnData.get(className).containsKey(methodName)) { returnData.get(className).put(methodName, new HashMap()); } if (!returnData.get(className).get(methodName).containsKey(value)) { // logger.info("Got return value "+value); returnData.get(className).get(methodName).put(value, 1); } else { // logger.info("Got return value again "+value); returnData.get(className).get(methodName).put(value, returnData.get(className).get(methodName).get(value) + 1); } } /** {@inheritDoc} */ @Override public void setExplicitException(Throwable explicitException) { this.explicitException = explicitException; } /** * {@inheritDoc} * * Returns a String containing the information in passedDefs and passedUses * * Used for Definition-Use-Coverage-debugging */ @Override public String toDefUseTraceInformation() { StringBuffer r = new StringBuffer(); for (String var : passedDefinitions.keySet()) { r.append(" for variable: " + var + ": "); for (Integer objectId : passedDefinitions.get(var).keySet()) { if (passedDefinitions.get(var).keySet().size() > 1) { r.append("\n\ton object " + objectId + ": "); } r.append(toDefUseTraceInformation(var, objectId)); } r.append("\n "); } return r.toString(); } /** * {@inheritDoc} * * Returns a String containing the information in passedDefs and passedUses * filtered for a specific variable * * Used for Definition-Use-Coverage-debugging */ @Override public String toDefUseTraceInformation(String targetVar) { StringBuffer r = new StringBuffer(); for (Integer objectId : passedDefinitions.get(targetVar).keySet()) { if (passedDefinitions.get(targetVar).keySet().size() > 1) { r.append("\n\ton object " + objectId + ": "); } r.append(toDefUseTraceInformation(targetVar, objectId)); } r.append("\n "); return r.toString(); } /** * {@inheritDoc} * * Returns a String containing the information in passedDefs and passedUses * for the given variable * * Used for Definition-Use-Coverage-debugging */ @Override public String toDefUseTraceInformation(String var, int objectId) { if (passedDefinitions.get(var) == null) { return ""; } if ((objectId == -1) && (passedDefinitions.get(var).keySet().size() == 1)) { objectId = (Integer) passedDefinitions.get(var).keySet().toArray()[0]; } if (passedDefinitions.get(var).get(objectId) == null) { return ""; } // gather all DUs String[] duTrace = new String[this.duCounter]; for (int i = 0; i < this.duCounter; i++) { duTrace[i] = ""; } for (Integer duPos : passedDefinitions.get(var).get(objectId).keySet()) { duTrace[duPos] = "(" + duPos + ":Def " + passedDefinitions.get(var).get(objectId).get(duPos) + ")"; } if ((passedUses.get(var) != null) && (passedUses.get(var).get(objectId) != null)) { for (Integer duPos : passedUses.get(var).get(objectId).keySet()) { duTrace[duPos] = "(" + duPos + ":Use " + passedUses.get(var).get(objectId).get(duPos) + ")"; } } // build up the String StringBuffer r = new StringBuffer(); for (String s : duTrace) { r.append(s); if (s.length() > 0) { r.append(", "); } } // remove last ", " String traceString = r.toString(); if (traceString.length() > 2) { return traceString.substring(0, traceString.length() - 2); } return traceString; } /** {@inheritDoc} */ @Override public String toString() { StringBuffer ret = new StringBuffer(); for (MethodCall m : finishedCalls) { ret.append(m); } ret.append("\nCovered methods: "); for (Entry entry : coveredMethods.entrySet()) { ret.append(entry.getKey() + ": " + entry.getValue() + ", "); } ret.append("\nCovered predicates: "); for (Entry entry : coveredPredicates.entrySet()) { ret.append(entry.getKey() + ": " + entry.getValue() + ", "); } ret.append("\nTrue distances: "); for (Entry entry : trueDistances.entrySet()) { ret.append(entry.getKey() + ": " + entry.getValue() + ", "); } ret.append("\nFalse distances: "); for (Entry entry : falseDistances.entrySet()) { ret.append(entry.getKey() + ": " + entry.getValue() + ", "); } return ret.toString(); } /** * Adds trace information to the active MethodCall in this.stack */ private void updateTopStackMethodCall(int branch, int bytecode_id, double true_distance, double false_distance) { if (traceCalls) { if (stack.isEmpty()) { return; } stack.peek().branchTrace.add(branch); // was: bytecode_id stack.peek().trueDistanceTrace.add(true_distance); stack.peek().falseDistanceTrace.add(false_distance); assert ((true_distance == 0.0) || (false_distance == 0.0)); // TODO line_trace ? if (ArrayUtil.contains(Properties.CRITERION, Criterion.DEFUSE) || ArrayUtil.contains(Properties.CRITERION, Criterion.ALLDEFS)) { stack.peek().defuseCounterTrace.add(duCounter); } } } /** * {@inheritDoc} * * Adds Definition-Use-Coverage trace information for the given use. * * Registers the given caller-Object Traces the occurrence of the given use * in the passedUses-field */ @Override public void usePassed(Object object, Object caller, int useID) { if (!traceCalls) // TODO ??? return; Use use = DefUsePool.getUseByUseId(useID); int objectID = registerObject(caller); // if this is a static variable, treat objectID as zero for consistency // in the representation of static data if (objectID != 0) { if (use == null) throw new IllegalStateException( "expect DefUsePool to known defIDs that are passed by instrumented code"); if (use.isStaticDefUse()) objectID = 0; } String varName = use.getVariableName(); if (passedUses.get(varName) == null) { passedUses.put(varName, new HashMap>()); passedUseObject.put(varName, new HashMap>()); } HashMap uses = passedUses.get(varName).get(objectID); HashMap usesObject = passedUseObject.get(varName).get(objectID); if (uses == null) { uses = new HashMap(); usesObject = new HashMap(); } uses.put(duCounter, useID); usesObject.put(duCounter, object); passedUses.get(varName).put(objectID, uses); passedUseObject.get(varName).put(objectID, usesObject); duCounter++; } /* * (non-Javadoc) * * @see org.evosuite.testcase.ExecutionTrace#wasMutationTouched(int) */ /** {@inheritDoc} */ @Override public boolean wasMutationTouched(int mutationId) { return touchedMutants.contains(mutationId); } /** {@inheritDoc} */ @Override public Map getFalseDistancesSum() { return falseDistancesSum; } /** {@inheritDoc} */ @Override public Map getTrueDistancesSum() { return trueDistancesSum; } /** {@inheritDoc} */ @Override public Map>> getPassedUses() { return passedUses; } /* * (non-Javadoc) * * @see org.evosuite.testcase.ExecutionTrace#getPassedDefIDs() */ // Map>> @Override public Set getPassedDefIDs() { Set defs = new HashSet(); for (HashMap> classDefs : passedDefinitions.values()) { for (HashMap currentDefs : classDefs.values()) { defs.addAll(currentDefs.values()); } } return defs; } /* * (non-Javadoc) * * @see org.evosuite.testcase.ExecutionTrace#getPassedUseIDs() */ @Override public Set getPassedUseIDs() { Set uses = new HashSet(); for (HashMap> classUses : passedUses.values()) { for (HashMap currentUses : classUses.values()) { uses.addAll(currentUses.values()); } } return uses; } /* * (non-Javadoc) * * @see org.evosuite.testcase.ExecutionTrace#getTrueDistancesContext() */ @Override public Map> getTrueDistancesContext() { return coveredTrueContext; } /* * (non-Javadoc) * * @see org.evosuite.testcase.ExecutionTrace#getFalseDistancesContext() */ @Override public Map> getFalseDistancesContext() { return coveredFalseContext; } /* * (non-Javadoc) * * @see * org.evosuite.testcase.ExecutionTrace#getPredicateContextExecutionCount() */ @Override public Map> getPredicateContextExecutionCount() { return coveredPredicateContext; } /* * (non-Javadoc) * * @see org.evosuite.testcase.ExecutionTrace#getMethodContextCount() */ @Override public Map> getMethodContextCount() { return coveredMethodContext; } /** * This set keeps those classes that have a static write (i.e. PUTSTATIC) * during test execution. */ private final HashSet classesWithStaticWrites = new HashSet(); @Override public void putStaticPassed(String classNameWithDots, String fieldName) { classesWithStaticWrites.add(classNameWithDots); } /** * This set keeps those classes that have a static read (i.e. GETSTATIC) * during test execution. */ private final HashSet classesWithStaticReads = new HashSet(); @Override public void getStaticPassed(String classNameWithDots, String fieldName) { classesWithStaticReads.add(classNameWithDots); } @Override public Set getClassesWithStaticWrites() { return classesWithStaticWrites; } /** * This field keeps the names of those classes that were initialized (ie * was completed during this test execution). The list has no * repetitions. */ private final List initializedClasses = new LinkedList(); /** * Adds the class to the list of those classes that were initialized during * this test execution. The class is not added if it was already contained * in the list. */ @Override public void classInitialized(String classNameWithDots) { if (!initializedClasses.contains(classNameWithDots)) { initializedClasses.add(classNameWithDots); } } @Override public Set getClassesWithStaticReads() { return classesWithStaticReads; } @Override public List getInitializedClasses() { return this.initializedClasses; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy