Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Weighted elements #77

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions com.gzoltar.cli.examples/run.sh
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,7 @@ java -cp $BUILD_DIR:$JUNIT_JAR:$HAMCREST_JAR:$GZOLTAR_CLI_JAR \
--family "sfl" \
--formula "ochiai" \
--metric "entropy" \
--weightedElements \
--formatter "txt" || die "Generation of fault-localization report has failed!"

[ -s "$SPECTRA_FILE" ] || die "$SPECTRA_FILE does not exist or it is empty!"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,9 @@ public class FaultLocalizationReport extends AbstractReport {
metaVar = "<formatter>", required = false)
private String formatter = ReportFormatter.TXT.name();

@Option(name = "--weightedElements", usage = "weighted elements algorithm to improve general score", metaVar = "<weightedElements>", required = false)
private Boolean weightedElements = false;

/**
* {@inheritDoc}
*/
Expand Down Expand Up @@ -98,6 +101,7 @@ protected void generateReport(final Locale locale) throws Exception {
this.agentConfigs.setInclDeprecatedMethods(this.inclDeprecatedMethods);
this.agentConfigs.setIncludes(this.includes);
this.agentConfigs.setExcludes(this.excludes);
this.agentConfigs.setWeightedElements(this.weightedElements);

final ConfigFaultLocalizationFamily configFlFamily = new ConfigFaultLocalizationFamily();

Expand Down
4 changes: 4 additions & 0 deletions com.gzoltar.core/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,10 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>8</source>
<target>8</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
Expand Down
24 changes: 24 additions & 0 deletions com.gzoltar.core/src/main/java/com/gzoltar/core/AgentConfigs.java
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,10 @@ public final class AgentConfigs {

public static final InstrumentationLevel DEFAULT_INSTRUMENTATION_LEVEL = InstrumentationLevel.FULL;

public static final String WEIGHTED_ELEMENTS_KEY = "weightedElements";

public static final boolean DEFAULT_WEIGHTED_ELEMENTS = false;

private final Map<String, String> configs;

private static final Collection<String> VALID_CONFIGS =
Expand Down Expand Up @@ -494,6 +498,26 @@ public void setInstrumentationLevel(final InstrumentationLevel instrumentationLe
this.setConfig(INSTRUMENTATION_LEVEL_KEY, instrumentationLevel.name());
}

/**
* Returns whether weighted elements algorithm should be executed.
*
* @return <code>true</code> if weighted elements algorithm should be executed
*/
public Boolean getWeightedElements() {
return this.getConfig(WEIGHTED_ELEMENTS_KEY, DEFAULT_WEIGHTED_ELEMENTS);
}

/**
* Sets whether weighted elements algorithm should be executed.
*
* @param weightedElements <code>true</code> if weighted elements algorithm should be executed
*/
public void setWeightedElements(final boolean weightedElements) {
this.setConfig(WEIGHTED_ELEMENTS_KEY, weightedElements);
}



/**
* Generate required JVM argument based on current configuration and supplied agent jar location.
*
Expand Down
19 changes: 19 additions & 0 deletions com.gzoltar.core/src/main/java/com/gzoltar/core/model/Node.java
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,10 @@ public class Node {

private Map<String, Double> suspiciousnessValues = null;

private Boolean containsMathOperator = false;

private Boolean haveFailedTest = false;

/**
*
* @param name
Expand Down Expand Up @@ -360,4 +364,19 @@ public boolean equals(Object obj) {
return builder.isEquals();
}

public Boolean getContainsMathOperator() {
return containsMathOperator;
}

public void setContainsMathOperator(Boolean containsMathOperator) {
this.containsMathOperator = containsMathOperator;
}

public Boolean getHaveFailedTest() {
return haveFailedTest;
}

public void setHaveFailedTest(Boolean haveFailedTest) {
this.haveFailedTest = haveFailedTest;
}
}
Original file line number Diff line number Diff line change
@@ -1,21 +1,22 @@
/**
* Copyright (C) 2020 GZoltar contributors.
*
*
* This file is part of GZoltar.
*
*
* GZoltar 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 of
* the License, or (at your option) any later version.
*
*
* GZoltar 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
* General Public License for more details.
*
*
* You should have received a copy of the GNU Lesser General Public License along with GZoltar. If
* not, see <https://www.gnu.org/licenses/>.
*/
package com.gzoltar.core.spectrum;

import com.gzoltar.core.util.FileUtils;
import org.apache.commons.lang3.tuple.ImmutablePair;
import com.gzoltar.core.AgentConfigs;
import com.gzoltar.core.instr.Outcome;
Expand All @@ -35,6 +36,11 @@
import com.gzoltar.core.util.ArrayUtils;
import javassist.Modifier;

import java.io.*;
import java.nio.file.Files;
import java.util.HashMap;
import java.util.List;

public class FilteredSpectrum {

private final GranularityLevel granularity;
Expand All @@ -43,14 +49,20 @@ public class FilteredSpectrum {

private final Filter methodFilter = new Filter();

private boolean WeightedElements = false;

HashMap<String, List<String>> classesContent = new HashMap<>();

/**
*
*
* @param source
*/
public FilteredSpectrum(AgentConfigs configs) {

this.granularity = configs.getGranularity();

this.WeightedElements = configs.getWeightedElements() != null;

// === Class level filters ===

// instrument some classes
Expand All @@ -73,18 +85,18 @@ public FilteredSpectrum(AgentConfigs configs) {

if (!configs.getInclDeprecatedMethods()) {
this.methodFilter
.add(new BlackList(new MethodAnnotationMatcher(Deprecated.class.getCanonicalName())));
.add(new BlackList(new MethodAnnotationMatcher(Deprecated.class.getCanonicalName())));
}
}

/**
* Returns a filtered {@link com.gzoltar.core.spectrum.ISpectrum} object according to user's
* preferences.
*
*
* @param source
* @return
*/
public ISpectrum filter(ISpectrum source) {
public ISpectrum filter(ISpectrum source) throws IOException {
if (source == null) {
return null;
}
Expand Down Expand Up @@ -115,8 +127,10 @@ public ISpectrum filter(ISpectrum source) {
}

if (this.granularity == GranularityLevel.LINE) {
Node node = WeightedElements ? verifyMathOperations(probe) : probe.getNode();
// register Line probe
newProbeGroup.registerProbe(probe.getNode(), probe.getCtBehavior());
newProbeGroup.registerProbe(node, probe.getCtBehavior());

} else if (this.granularity == GranularityLevel.CLASS) {
// register Class probe
newProbeGroup.registerProbe(probe.getNode(), probe.getCtBehavior());
Expand All @@ -127,8 +141,8 @@ public ISpectrum filter(ISpectrum source) {

Node node = probe.getNode();
String methodName =
node.getName().substring(node.getName().indexOf(NodeType.METHOD.getSymbol()) + 1,
node.getName().indexOf(NodeType.LINE.getSymbol()));
node.getName().substring(node.getName().indexOf(NodeType.METHOD.getSymbol()) + 1,
node.getName().indexOf(NodeType.LINE.getSymbol()));

granularityMethodFilter.add(new BlackList(new MethodNameMatcher(methodName)));
} else if (this.granularity == GranularityLevel.BASICBLOCK && probe.getNode().isStartBlock()) {
Expand All @@ -146,8 +160,8 @@ public ISpectrum filter(ISpectrum source) {

for (Transaction transaction : source.getTransactions()) {
Transaction newTransaction =
new Transaction(transaction.getName(), transaction.getTransactionOutcome(),
transaction.getRuntime(), transaction.getStackTrace());
new Transaction(transaction.getName(), transaction.getTransactionOutcome(),
transaction.getRuntime(), transaction.getStackTrace());

for (String hash : transaction.getProbeGroupsHash()) {
if (!filteredSpectrum.containsProbeGroupByHash(hash)) {
Expand Down Expand Up @@ -175,7 +189,7 @@ public ISpectrum filter(ISpectrum source) {

if (ArrayUtils.containsValue(newHitArray, true)) {
newTransaction.addActivity(hash,
new ImmutablePair<String, boolean[]>(newProbeGroup.getName(), newHitArray));
new ImmutablePair<String, boolean[]>(newProbeGroup.getName(), newHitArray));
}
}

Expand All @@ -196,12 +210,12 @@ public ISpectrum filter(ISpectrum source) {
switch (this.granularity) {
case CLASS:
newNodeName =
node.getName().substring(0, node.getName().indexOf(NodeType.METHOD.getSymbol()));
node.getName().substring(0, node.getName().indexOf(NodeType.METHOD.getSymbol()));
newNodeType = NodeType.CLASS;
break;
case METHOD:
newNodeName =
node.getName().substring(0, node.getName().indexOf(NodeType.LINE.getSymbol()));
node.getName().substring(0, node.getName().indexOf(NodeType.LINE.getSymbol()));
newNodeType = NodeType.METHOD;
break;
case BASICBLOCK:
Expand All @@ -221,4 +235,41 @@ public ISpectrum filter(ISpectrum source) {
return filteredSpectrum;
}

/**
* Only called when node in probe is a statement and weighted elements is activated
* @param probe
*/
private Node verifyMathOperations(Probe probe) throws IOException {
Node node = probe.getNode();
String className = probe.getCtBehavior().getDeclaringClass().getName();
if (!classesContent.containsKey(className)) {
// build file path
String classPath = className.replace('.', '/') + ".java";
String baseDir = System.getProperty("user.dir") + "/src";
String filePath = baseDir + "/" + classPath;
File file = new File(filePath);
InputStream inputStream = Files.newInputStream(file.toPath());
List<String> classContent = FileUtils.loadFileByLine(inputStream);

classesContent.put(className, classContent);
}
String[] words = classesContent.get(className).get(node.getLineNumber() - 1).split(" ");
for (String word : words) {
if (containsMathOperator(word)) {
node.setContainsMathOperator(true);
}
}
return node;
}

private static Boolean containsMathOperator(String word) {
char[] operators = {'+', '-', '*', '/', '%', '^'};

for (char operator : operators) {
if (word.indexOf(operator) != -1) {
return true;
}
}
return false;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@

public interface ISpectrum {

public void maxScore(String formula, double score);

public double getMaxScore(String formula);

// === ProbeGroups ===

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@

public class Spectrum implements ISpectrum {

private final Map<String, Double> maxScore;

/** <ProbeGroup hash, ProbeGroup> */
private final Map<String, ProbeGroup> probeGroups;

Expand All @@ -39,10 +41,21 @@ public class Spectrum implements ISpectrum {
* Constructs a new {@link com.gzoltar.core.spectrum.Spectrum}.
*/
public Spectrum() {
this.maxScore = new LinkedHashMap<String, Double>();
this.probeGroups = new LinkedHashMap<String, ProbeGroup>();
this.transactions = new ArrayList<Transaction>();
}

@Override
public void maxScore(String formula, double score) {
this.maxScore.put(formula, Math.max(this.maxScore.getOrDefault(formula, score), score));
}

@Override
public double getMaxScore(String formula) {
return this.maxScore.get(formula);
}

// === ProbeGroups ===

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,10 @@
package com.gzoltar.core.util;

import java.io.File;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

public final class FileUtils {

Expand All @@ -44,4 +46,21 @@ public static List<File> listFiles(final File dir, final String ext, final boole
return files;
}

/**
* Returns a list with all the lines in a given file.
*
* @param stream of the file to be read
* @return a {@link java.util.List} of all lines in the file
*/
public static List<String> loadFileByLine(InputStream stream) {
List<String> lines = new ArrayList<>();
try (Scanner scanner = new Scanner(stream)) {
while (scanner.hasNextLine()) {
String line = scanner.nextLine().trim();
lines.add(line);
}
}
return lines;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ public ISpectrum diagnose(final String buildLocation, final AgentConfigs agentCo
FilteredSpectrum filter = new FilteredSpectrum(agentConfigs);
ISpectrum filteredSpectrum = filter.filter(spectrum);

this.fl.diagnose(filteredSpectrum);
this.fl.diagnose(filteredSpectrum, agentConfigs.getWeightedElements());

return filteredSpectrum;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,5 +24,5 @@ public interface IFaultLocalization<F extends IFormula> {
*
* @param spectrum a {@link com.gzoltar.core.spectrum.ISpectrum} object
*/
public void diagnose(final ISpectrum spectrum);
public void diagnose(final ISpectrum spectrum, Boolean weightedElements);
}
Loading