Skip to content

Commit

Permalink
Merge branch 'master' into sql-multidb-v3
Browse files Browse the repository at this point in the history
# Conflicts:
#	client-java/sql/src/main/java/org/evomaster/client/java/sql/internal/SqlNameContext.java
  • Loading branch information
man-zhang committed Jan 2, 2025
2 parents 434bef4 + ca8203c commit 26da911
Show file tree
Hide file tree
Showing 54 changed files with 2,044 additions and 214 deletions.
31 changes: 17 additions & 14 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,23 @@ jobs:
path: core/target/evomaster.jar
retention-days: ${{env.retention-days}}
if-no-files-found: error
- name: Docker meta
id: meta
uses: docker/metadata-action@v5
with:
images: webfuzzing/evomaster
- name: Login to DockerHub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_PASSWORD }}
- name: Build and push Docker
uses: docker/build-push-action@v5
with:
context: .
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}

installer-for-windows:
needs: build-base
Expand Down Expand Up @@ -129,7 +146,6 @@ jobs:
runs-on: "ubuntu-latest"

steps:

- name: Download fat jar
uses: actions/download-artifact@v4
with:
Expand All @@ -146,19 +162,6 @@ jobs:
uses: actions/download-artifact@v4
with:
name: evomaster.msi


## Doesn't seem any longer maintained... plus usability issues
# - uses: "marvinpinto/action-automatic-releases@latest"
# with:
# repo_token: "${{ secrets.GITHUB_TOKEN }}"
# prerelease: false
# files: |
# evomaster.jar
# ${{env.installer-windows}}
# ${{env.installer-osx}}
# ${{env.installer-debian}}

- name: Release
uses: softprops/action-gh-release@v1
with:
Expand Down
46 changes: 46 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
FROM amazoncorretto:21-alpine-jdk

COPY core/target/evomaster.jar .

ENTRYPOINT [ \
"java", \
"-Xmx4G", \
"-jar", "evomaster.jar", \
"--runningInDocker", "true" \
]


###################
###### NOTES ######
###################
# Build
# docker build -t webfuzzing/evomaster .
#
# Run
# docker run webfuzzing/evomaster <options>
#
# Publish (latest, otherwise tag with :TAG)
# docker login
# docker push webfuzzing/evomaster
#
# Example remote BB
# docker run -v "/$(pwd)/generated_tests":/generated_tests webfuzzing/evomaster --blackBox true --bbSwaggerUrl https://api.apis.guru/v2/openapi.yaml --outputFormat JAVA_JUNIT_4 --maxTime 10s --ratePerMinute 60
#
# Example local BB
# docker run -v "/$(pwd)/generated_tests":/generated_tests webfuzzing/evomaster --blackBox true --bbSwaggerUrl http://host.docker.internal:8080/v3/api-docs --maxTime 5s
#
# Example WB (NOT IMPLEMENTED YET)
# docker run -v "/$(pwd)/generated_tests":/generated_tests webfuzzing/evomaster --dockerLocalhost true
#
# Setting for existing em.yaml
# -v "/$(pwd)/em.yaml":/em.yaml
#
# Debugging
# docker run -it --entrypoint sh webfuzzing/evomaster
#
#
#
#
#
#
#
11 changes: 11 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,17 @@ __Known limitations__:
-->


### Use in Industry

Several enterprises use _EvoMaster_ to fuzz their Web APIs.
We do few academia-industry collaborations ([see more info here](docs/contribute.md)), where we help test engineers to apply _EvoMaster_ on their systems, as long as we can then report on such experience.
Example of Fortune 500 companies using _EvoMaster_ are:

* [Meituan](https://www.meituan.com): see [TOSEM'23](docs/publications/2023_tosem_rpc.pdf), [ASE'24](docs/publications/2024_ase.pdf).

* [Volkswagen](https://www.volkswagen.com): see [AUSE'24](docs/publications/2024_ause_vw.pdf), [ICST'25](docs/publications/2025_icst.pdf).


### Videos

![](docs/img/video-player-flaticon.png)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package org.evomaster.client.java.distance.heuristics;

import java.util.Arrays;

public class TruthnessUtils {

/**
Expand All @@ -13,7 +15,7 @@ public static double normalizeValue(double v) {
throw new IllegalArgumentException("Negative value: " + v);
}

if(Double.isInfinite(v) || v == Double.MAX_VALUE){
if (Double.isInfinite(v) || v == Double.MAX_VALUE) {
return 1d;
}

Expand All @@ -26,7 +28,6 @@ public static double normalizeValue(double v) {
}



public static Truthness getEqualityTruthness(int a, int b) {
double distance = DistanceHelper.getDistanceToEquality(a, b);
double normalizedDistance = normalizeValue(distance);
Expand All @@ -45,6 +46,15 @@ public static Truthness getEqualityTruthness(long a, long b) {
);
}


public static Truthness getLessThanTruthness(double a, double b) {
double distance = DistanceHelper.getDistanceToEquality(a, b);
return new Truthness(
a < b ? 1d : 1d / (1.1d + distance),
a >= b ? 1d : 1d / (1.1d + distance)
);
}

public static Truthness getLessThanTruthness(long a, long b) {
double distance = DistanceHelper.getDistanceToEquality(a, b);
return new Truthness(
Expand Down Expand Up @@ -79,4 +89,58 @@ public static Truthness getTruthnessToEmpty(int len) {
}
return t;
}

public static Truthness buildAndAggregationTruthness(Truthness... truthnesses) {
double averageOfTrue = averageOfTrue(truthnesses);
double falseOrAverageFalse = falseOrAverageFalse(truthnesses);
return new Truthness(averageOfTrue, falseOrAverageFalse);
}

private static double averageOfTrue(Truthness... truthnesses) {
checkValidTruthnesses(truthnesses);
double[] getOfTrueValues = Arrays.stream(truthnesses).mapToDouble(Truthness::getOfTrue)
.toArray();
return average(getOfTrueValues);
}

private static void checkValidTruthnesses(Truthness[] truthnesses) {
if (truthnesses == null || truthnesses.length == 0 || Arrays.stream(truthnesses).anyMatch(e -> e == null)) {
throw new IllegalArgumentException("null or empty Truthness instance");
}
}

private static double average(double... values) {
if (values == null || values.length == 0) {
throw new IllegalArgumentException("null or empty values");
}
double total = 0.0;
for (double v : values) {
total += v;
}
return total / values.length;
}

private static double averageOfFalse(Truthness... truthnesses) {
checkValidTruthnesses(truthnesses);
double[] getOfFalseValues = Arrays.stream(truthnesses).mapToDouble(Truthness::getOfFalse)
.toArray();
return average(getOfFalseValues);
}

private static double falseOrAverageFalse(Truthness... truthnesses) {
checkValidTruthnesses(truthnesses);
if (Arrays.stream(truthnesses).anyMatch(t -> t.isFalse())) {
return 1.0d;
} else {
return averageOfFalse(truthnesses);
}
}

public static Truthness buildScaledTruthness(double base, double ofTrueToScale) {
final double scaledOfTrue = DistanceHelper.scaleHeuristicWithBase(ofTrueToScale, base);
final double ofFalse = 1.0d;
return new Truthness(scaledOfTrue, ofFalse);
}


}
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ public QueryResult(List<VariableDescriptor> variableDescriptorList) {
variableDescriptors.addAll(variableDescriptorList);
}



/**
* WARNING: Constructor only needed for testing
*
Expand Down Expand Up @@ -180,4 +182,17 @@ public QueryResultDto toDto(){

return dto;
}

/**
* Retrieves the table name of this queryResult.
*
* @return the table name of the first {@code VariableDescriptor} in the {@code variableDescriptors} list.
* @throws IllegalStateException if the {@code variableDescriptors} list is empty.
*/
public String getTableName() {
if (variableDescriptors.isEmpty()) {
throw new IllegalStateException("No variable descriptors found");
}
return variableDescriptors.get(0).getTableName();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
package org.evomaster.client.java.sql;

import java.util.Map;
import java.util.TreeMap;

/**
* Represents a collection of query results mapped to table names,
* with support for both named and virtual tables.
*
* This class allows case-sensitive or case-insensitive handling of table names
* and provides mechanisms to add, retrieve, and manage query results.
*
*/
public class QueryResultSet {

/**
* A map storing query results associated with table names.
* The keys are table names, and the values are {@link QueryResult} objects.
*/
private final Map<String, QueryResult> queryResults;

/**
* Indicates whether table name comparisons are case-sensitive.
*/
private final boolean isCaseSensitive;

/**
* Stores the query result for a virtual table, if any.
*/
private QueryResult queryResultForVirtualTable;

public QueryResultSet() {
this(true);
}

/**
* Creates a new {@code QueryResultSet}.
*
* @param isCaseSensitive whether table name comparisons should be case-sensitive
*/
public QueryResultSet(boolean isCaseSensitive) {
queryResults = new TreeMap<>(isCaseSensitive ? null : String.CASE_INSENSITIVE_ORDER);
this.isCaseSensitive = isCaseSensitive;
}

/**
* Returns whether table name comparisons are case-sensitive.
*
* @return {@code true} if comparisons are case-sensitive, {@code false} otherwise
*/
public boolean isCaseSensitive() {
return isCaseSensitive;
}

/**
* Adds a query result to the result set.
* <p>
* If the query result corresponds to a named table, it is stored in the map.
* If it corresponds to a virtual table, it is stored separately.
* Throws an exception if a duplicate table (named or virtual) is added.
* </p>
*
* @param queryResult the query result to add
* @throws IllegalArgumentException if the table name already exists in the set
*/
public void addQueryResult(QueryResult queryResult) {
String tableName = queryResult.seeVariableDescriptors()
.stream()
.findFirst()
.map(VariableDescriptor::getTableName)
.orElse(null);

if (tableName == null) {
handleVirtualTable(queryResult);
} else {
handleNamedTable(tableName, queryResult);
}
}

private void handleNamedTable(String tableName, QueryResult queryResult) {
if (queryResults.containsKey(tableName)) {
throw new IllegalArgumentException("Duplicate table in QueryResultSet: " + tableName);
}
queryResults.put(tableName, queryResult);
}

private void handleVirtualTable(QueryResult queryResult) {
if (queryResultForVirtualTable != null) {
throw new IllegalArgumentException("Duplicate values for virtual table");
}
queryResultForVirtualTable = queryResult;
}

/**
* Retrieves the query result associated with a named table.
*
* @param tableName the name of the table
* @return the query result for the table, or {@code null} if no result exists
*/
public QueryResult getQueryResultForNamedTable(String tableName) {
return queryResults.get(tableName);
}

/**
* Retrieves the query result for a virtual table.
*
* @return the query result for the virtual table, or {@code null} if none exists
*/
public QueryResult getQueryResultForVirtualTable() {
return queryResultForVirtualTable;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@ public VariableDescriptor(String columnName) {
}

public VariableDescriptor(String columnName, String alias, String tableName) {
this.columnName = columnName.trim().toLowerCase();
this.columnName = (columnName==null || columnName.trim().isEmpty() ?
null : columnName.trim().toLowerCase());
this.alias = (alias == null || alias.trim().isEmpty() ?
this.columnName :
alias.trim().toLowerCase());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,20 +51,26 @@ public static SqlDistanceWithMetrics computeDistance(
QueryResult... data
) {

/**
* This is not an ideal solution, but it will remain this way until config.heuristicsForSQLAdvanced remains
* experimental and it does not replace the "Plain" SqlHeuristicsCalculator
*/
if (advancedHeuristics) {
return SqlHeuristicsCalculator.computeDistance(sqlCommand,schema,taintHandler,data);
}

if (data.length == 0 || Arrays.stream(data).allMatch(QueryResult::isEmpty)){
//if no data, we have no info whatsoever
return new SqlDistanceWithMetrics(Double.MAX_VALUE,0, false);
}

Statement stmt = SqlParserUtils.parseSqlCommand(sqlCommand);

Expression where = getWhere(stmt);
if (where == null) {
//no constraint and at least one data point
return new SqlDistanceWithMetrics(0.0,0, false);
}


SqlNameContext context = new SqlNameContext(stmt);
if (schema != null) {
context.setSchema(schema);
Expand Down
Loading

0 comments on commit 26da911

Please sign in to comment.