/** * 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.coverage.lcsaj; import java.util.ArrayList; import java.util.List; import org.evosuite.Properties; import org.evosuite.TestGenerationContext; import org.evosuite.Properties.Strategy; import org.evosuite.coverage.branch.Branch; import org.evosuite.coverage.branch.BranchPool; import org.evosuite.graphs.cfg.BytecodeInstruction; import org.objectweb.asm.tree.AbstractInsnNode; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class LCSAJ implements Comparable<LCSAJ> { private static Logger logger = LoggerFactory.getLogger(LCSAJ.class); // All branches passed in the LCSAJ private final List<Branch> branches = new ArrayList<Branch>(); // Information needed and maintained in the LCSAJ instrumentation and detection algorithm private AbstractInsnNode lastAccessedNode; private int id = -1; // Class and method where the LCSAJ occurs private final String className; private final String methodName; private int positionReached = 0; /** * <p> * Constructor for LCSAJ. * </p> * * @param className * a {@link java.lang.String} object. * @param methodName * a {@link java.lang.String} object. * @param start * a {@link org.evosuite.graphs.cfg.BytecodeInstruction} object. */ public LCSAJ(String className, String methodName, BytecodeInstruction start) { this.className = className; this.methodName = methodName; this.lastAccessedNode = start.getASMNode(); if (!BranchPool.getInstance(TestGenerationContext.getInstance().getClassLoaderForSUT()).isKnownAsBranch(start)) { if (methodName.startsWith("<init>") && start.getInstructionId() <= 1) { } if (Properties.STRATEGY != Strategy.EVOSUITE) { start.forceBranch(); BranchPool.getInstance(TestGenerationContext.getInstance().getClassLoaderForSUT()).registerAsBranch(start); logger.info("Registering new branch for start node"); } } Branch branch = BranchPool.getInstance(TestGenerationContext.getInstance().getClassLoaderForSUT()).getBranchForInstruction(start); branches.add(branch); } //Copy constructor /** * <p> * Constructor for LCSAJ. * </p> * * @param l * a {@link org.evosuite.coverage.lcsaj.LCSAJ} object. */ public LCSAJ(LCSAJ l) { this.className = l.getClassName(); this.methodName = l.getMethodName(); this.branches.addAll(l.branches); this.lastAccessedNode = l.getLastNodeAccessed(); } /** * <p> * getID * </p> * * @return a int. */ public int getID() { return this.id; } /** * Set an (not necessarily unique) new ID for a LCSAJ. While adding a LCSAJ * into the Pool the number is set to its occurrence during the detection of * all LCSAJ in a method * * @param id * a int. */ public void setID(int id) { this.id = id; } /** * <p> * getBranchInstructions * </p> * * @return a {@link java.util.List} object. */ public List<Branch> getBranchInstructions() { return branches; } /** * <p> * getBranch * </p> * * @param position * a int. * @return a {@link org.evosuite.coverage.branch.Branch} object. */ public Branch getBranch(int position) { return branches.get(position); } /** * <p> * getBranchID * </p> * * @param position * a int. * @return a int. */ public int getBranchID(int position) { return branches.get(position).getActualBranchId(); } /** * <p> * getStartBranch * </p> * * @return a {@link org.evosuite.coverage.branch.Branch} object. */ public Branch getStartBranch() { return branches.get(0); } /** * <p> * getLastBranch * </p> * * @return a {@link org.evosuite.coverage.branch.Branch} object. */ public Branch getLastBranch() { return branches.get(branches.size() - 1); } /** * <p> * getLastNodeAccessed * </p> * * @return a {@link org.objectweb.asm.tree.AbstractInsnNode} object. */ public AbstractInsnNode getLastNodeAccessed() { return lastAccessedNode; } /** * <p> * Getter for the field <code>className</code>. * </p> * * @return a {@link java.lang.String} object. */ public String getClassName() { return this.className; } /** * <p> * Getter for the field <code>methodName</code>. * </p> * * @return a {@link java.lang.String} object. */ public String getMethodName() { return this.methodName; } /** * <p> * lookupInstruction * </p> * * @param id * a int. * @param instruction * a {@link org.evosuite.graphs.cfg.BytecodeInstruction} object. */ public void lookupInstruction(int id, BytecodeInstruction instruction) { lastAccessedNode = instruction.getASMNode(); if (instruction.isBranch()) { Branch branch = BranchPool.getInstance(TestGenerationContext.getInstance().getClassLoaderForSUT()).getBranchForInstruction(instruction); branches.add(branch); } else if (instruction.isReturn() || instruction.isThrow() || instruction.isGoto()) { if (Properties.STRATEGY != Strategy.EVOSUITE && !BranchPool.getInstance(TestGenerationContext.getInstance().getClassLoaderForSUT()).isKnownAsBranch(instruction)) { instruction.forceBranch(); BranchPool.getInstance(TestGenerationContext.getInstance().getClassLoaderForSUT()).registerAsBranch(instruction); logger.info("Registering new branch"); } Branch branch = BranchPool.getInstance(TestGenerationContext.getInstance().getClassLoaderForSUT()).getBranchForInstruction(instruction); branches.add(branch); } } /** * <p> * length * </p> * * @return a int. */ public int length() { return branches.size(); } /** {@inheritDoc} */ @Override public String toString() { String output = "LCSAJ no.: " + this.id; output += " in " + this.className + "/" + this.methodName + ". Branches passed: "; for (Branch b : branches) output += " -> " + b.getActualBranchId(); //output += "\n"; // for (Branch b : branches) // output += " -> " + b.getASMNodeString() + "\n"; return output; } /** * <p> * Setter for the field <code>positionReached</code>. * </p> * * @param position * a int. */ public void setPositionReached(int position) { this.positionReached = position; } /** * <p> * getdPositionReached * </p> * * @return a int. */ public int getdPositionReached() { return this.positionReached; } /* (non-Javadoc) * @see java.lang.Comparable#compareTo(java.lang.Object) */ @Override public int compareTo(LCSAJ o) { for (int i = 0; i < Math.min(branches.size(), o.length()); i++) { if (branches.get(i).compareTo(o.getBranch(i)) != 0) return branches.get(i).compareTo(o.getBranch(i)); } return length() - o.length(); } }