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

io.rivulet.internal.Violation Maven / Gradle / Ivy

The newest version!
package io.rivulet.internal;

import io.rivulet.ViolationReportingUtils;
import io.rivulet.internal.rerun.Replacement;
import io.rivulet.internal.rerun.TestRerunConfiguration;

import java.io.Serializable;
import java.util.Collection;
import java.util.LinkedHashSet;

/* Stores information about a flow from at least one source method to a sink method. */
public class Violation implements Serializable {

    private static final long serialVersionUID = 7285031412986364823L;
    // The maximum number of tainted values that should be printed
    private static final int MAX_TAINTED_VALUES = 5;
    // Name of sink method from which the actual sink method invoked inherited its status as a sink
    private final String baseSink;
    // Name of the class of the actual sink method to which a tainted value flowed
    private final String actualSinkClass;
    // Set of tainted values that reached the sink
    private final LinkedHashSet taintedValues;
    // Uniquely identifies this violation
    private String uniqueID;
    // Name of the class of the test method during which this violation occurred
    private String testClass;
    // Name of the test method during which this violation occurred
    private String testMethod;

    /* Constructs a new violation with an empty set of tainted values. */
    public Violation(String baseSink, String actualSink) {
        this.baseSink = baseSink;
        this.actualSinkClass = actualSink.substring(0, actualSink.indexOf("."));
        this.taintedValues = new LinkedHashSet<>();
    }

    /* Constructs a new violation with a tainted value set containing the values in the specified collection. */
    private Violation(String baseSink, String actualSinkClass, Collection taintedValues) {
        this.baseSink = baseSink;
        this.actualSinkClass = actualSinkClass;
        this.taintedValues = new LinkedHashSet<>(taintedValues);
    }

    /* Adds the specified TaintedSinkValue to taintedValues. */
    public void addTaintedValue(TaintedSinkValue value) {
        taintedValues.add(value);
    }

    /* Adds information about the test being run to this violation. */
    public void setTestInfo(String uniqueID, String testClass, String testMethod) {
        this.uniqueID = uniqueID;
        this.testClass = testClass;
        this.testMethod = testMethod;
    }

    /* Getter for baseSink. */
    public String getBaseSink() {
        return baseSink;
    }

    /* Getter for actualSinkClass. */
    public String getActualSinkClass() {
        return actualSinkClass;
    }

    /* Getter for taintedValues. */
    public LinkedHashSet getTaintedValues() {
        return taintedValues;
    }

    /* Getter for uniqueID. */
    public String getUniqueID() {
        return uniqueID;
    }

    /* Getter for testClass. */
    public String getTestClass() {
        return testClass;
    }

    /* Getter for testMethod. */
    public String getTestMethod() {
        return testMethod;
    }

    /* Returns a text representation of this violation. */
    @Override
    public String toString() {
        StringBuilder builder = new StringBuilder("\tbaseSink: ").append(baseSink);
        builder.append("\n\tactualSinkClass: ").append(actualSinkClass);
        builder.append("\n\ttaintedValues: [\n");
        int i = 0;
        for(TaintedSinkValue val : taintedValues) {
            builder.append(val.toString(2)).append("\n");
            if(i++ >= MAX_TAINTED_VALUES) {
                break;
            }
        }
        int remaining = taintedValues.size() - MAX_TAINTED_VALUES;
        if(remaining > 0) {
            builder.append("\t\t+").append(remaining).append(" more\n");
        }
        return builder.append("\t]").toString();
    }

    /* Returns a nicely formatted string containing information about this violation. If critical is true the violation
     * is labeled as being critical. */
    public String toString(boolean critical, TestRerunConfiguration curConfig) {
        String violationStatus = ViolationReportingUtils.colorText(critical ? "CRITICAL VIOLATION" : "VIOLATION", ViolationReportingUtils.RivuletColor.VIOLATION);
        violationStatus = ViolationReportingUtils.boldText(violationStatus);
        String testName = ViolationReportingUtils.formatTestName(testClass, testMethod);
        if(critical && curConfig != null) {
            // Added replacement information
            StringBuilder builder = new StringBuilder(String.format("[%s] %s {\n%s\n", violationStatus, testName, toString()));
            builder.append("\treplacements: [\n");
            for(Replacement replacement : curConfig.getReplacementsCopy()) {
                builder.append(replacement.toString(2)).append("\n");
            }
            return builder.append("\t]\n}").toString();
        } else {
            return String.format("[%s] %s {\n%s\n}", violationStatus, testName, toString());
        }
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Violation violation = (Violation) o;
        if (!baseSink.equals(violation.baseSink)) return false;
        if (!actualSinkClass.equals(violation.actualSinkClass)) return false;
        return taintedValues.equals(violation.taintedValues);
    }

    @Override
    public int hashCode() {
        int result = baseSink.hashCode();
        result = 31 * result + actualSinkClass.hashCode();
        result = 31 * result + taintedValues.hashCode();
        return result;
    }

    /* Returns a semi-shallow copy of this Violation. */
    public Violation copy() {
        return copyWithTaintedValues(new LinkedHashSet<>(taintedValues));
    }

    /* Returns a copy of this Violation but with the specified set of taintedValues. */
    public Violation copyWithTaintedValues(Collection newTaintedValues) {
        Violation copy = new Violation(baseSink, actualSinkClass, newTaintedValues);
        copy.setTestInfo(uniqueID, testClass, testMethod);
        return copy;
    }

    /* Returns all of the labels on some tainted value in this instance's taint value set. */
    public LinkedHashSet getAllLabels() {
        LinkedHashSet labels = new LinkedHashSet<>();
        for(TaintedSinkValue taintedValue : taintedValues) {
            labels.addAll(taintedValue.getTaintSources());
        }
        return labels;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy