Skip to content
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
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ public class MongoHeuristicsCalculator {
private final TaintHandler taintHandler;

public MongoHeuristicsCalculator() {
this(null);
this(null);
}

public MongoHeuristicsCalculator(TaintHandler taintHandler) {
Expand All @@ -35,63 +35,65 @@ public MongoHeuristicsCalculator(TaintHandler taintHandler) {
* @return a branch distance, where 0 means that the document would make the QUERY resolve as true
*/
public double computeExpression(Object query, Object doc) {

QueryOperation operation = getOperation(query);
return calculateDistance(operation, doc);
return computeHeuristic(operation, doc);
}

private QueryOperation getOperation(Object query) {
return new QueryParser().parse(query);
}

private double calculateDistance(QueryOperation operation, Object doc) {
if (operation instanceof EqualsOperation<?>)
private double computeHeuristic(QueryOperation operation, Object doc) {
if (operation instanceof EqualsOperation<?>) {
return calculateDistanceForEquals((EqualsOperation<?>) operation, doc);
if (operation instanceof NotEqualsOperation<?>)
} else if (operation instanceof NotEqualsOperation<?>) {
return calculateDistanceForNotEquals((NotEqualsOperation<?>) operation, doc);
if (operation instanceof GreaterThanOperation<?>)
} else if (operation instanceof GreaterThanOperation<?>) {
return calculateDistanceForGreaterThan((GreaterThanOperation<?>) operation, doc);
if (operation instanceof GreaterThanEqualsOperation<?>)
} else if (operation instanceof GreaterThanEqualsOperation<?>) {
return calculateDistanceForGreaterEqualsThan((GreaterThanEqualsOperation<?>) operation, doc);
if (operation instanceof LessThanOperation<?>)
} else if (operation instanceof LessThanOperation<?>) {
return calculateDistanceForLessThan((LessThanOperation<?>) operation, doc);
if (operation instanceof LessThanEqualsOperation<?>)
} else if (operation instanceof LessThanEqualsOperation<?>) {
return calculateDistanceForLessEqualsThan((LessThanEqualsOperation<?>) operation, doc);
if (operation instanceof AndOperation)
} else if (operation instanceof AndOperation) {
return calculateDistanceForAnd((AndOperation) operation, doc);
if (operation instanceof OrOperation)
} else if (operation instanceof OrOperation) {
return calculateDistanceForOr((OrOperation) operation, doc);
if (operation instanceof NorOperation)
} else if (operation instanceof NorOperation) {
return calculateDistanceForNor((NorOperation) operation, doc);
if (operation instanceof InOperation<?>)
} else if (operation instanceof InOperation<?>) {
return calculateDistanceForIn((InOperation<?>) operation, doc);
if (operation instanceof NotInOperation<?>)
} else if (operation instanceof NotInOperation<?>) {
return calculateDistanceForNotIn((NotInOperation<?>) operation, doc);
if (operation instanceof AllOperation<?>)
} else if (operation instanceof AllOperation<?>) {
return calculateDistanceForAll((AllOperation<?>) operation, doc);
if (operation instanceof InvertedAllOperation<?>)
} else if (operation instanceof InvertedAllOperation<?>) {
return calculateDistanceForInvertedAll((InvertedAllOperation<?>) operation, doc);
if (operation instanceof SizeOperation)
} else if (operation instanceof SizeOperation) {
return calculateDistanceForSize((SizeOperation) operation, doc);
if (operation instanceof InvertedSizeOperation)
} else if (operation instanceof InvertedSizeOperation) {
return calculateDistanceForInvertedSize((InvertedSizeOperation) operation, doc);
if (operation instanceof ElemMatchOperation)
} else if (operation instanceof ElemMatchOperation) {
return calculateDistanceForElemMatch((ElemMatchOperation) operation, doc);
if (operation instanceof ExistsOperation)
} else if (operation instanceof ExistsOperation) {
return calculateDistanceForExists((ExistsOperation) operation, doc);
if (operation instanceof ModOperation)
} else if (operation instanceof ModOperation) {
return calculateDistanceForMod((ModOperation) operation, doc);
if (operation instanceof InvertedModOperation)
} else if (operation instanceof InvertedModOperation) {
return calculateDistanceForInvertedMod((InvertedModOperation) operation, doc);
if (operation instanceof NotOperation)
} else if (operation instanceof NotOperation) {
return calculateDistanceForNot((NotOperation) operation, doc);
if (operation instanceof TypeOperation)
} else if (operation instanceof TypeOperation) {
return calculateDistanceForType((TypeOperation) operation, doc);
if (operation instanceof InvertedTypeOperation)
} else if (operation instanceof InvertedTypeOperation) {
return calculateDistanceForInvertedType((InvertedTypeOperation) operation, doc);
if (operation instanceof NearSphereOperation)
} else if (operation instanceof NearSphereOperation) {
return calculateDistanceForNearSphere((NearSphereOperation) operation, doc);

return Double.MAX_VALUE;
} else {
return Double.MAX_VALUE;
}
}

private double calculateDistanceForEquals(EqualsOperation<?> operation, Object doc) {
Expand Down Expand Up @@ -134,7 +136,7 @@ private double calculateDistanceForComparisonOperation(ComparisonOperation<?> op

private double calculateDistanceForOr(OrOperation operation, Object doc) {
return operation.getConditions().stream()
.mapToDouble(condition -> calculateDistance(condition, doc))
.mapToDouble(condition -> computeHeuristic(condition, doc))
.min()
.getAsDouble();
}
Expand All @@ -143,7 +145,7 @@ private double calculateDistanceForAnd(AndOperation operation, Object doc) {
return operation.getConditions()
.stream()
.mapToDouble(condition ->
TruthnessUtils.normalizeValue(calculateDistance(condition, doc)))
TruthnessUtils.normalizeValue(computeHeuristic(condition, doc)))
.sum();
}

Expand Down Expand Up @@ -233,7 +235,7 @@ private double calculateDistanceForElemMatch(ElemMatchOperation operation, Objec
.mapToDouble(elem -> {
Object newDoc = newDocument(doc);
appendToDocument(newDoc, operation.getFieldName(), elem);
return calculateDistance(operation.getCondition(), newDoc);
return computeHeuristic(operation.getCondition(), newDoc);
})
.min()
.getAsDouble();
Expand Down Expand Up @@ -289,14 +291,14 @@ private double calculateDistanceForNot(NotOperation operation, Object doc) {
QueryOperation condition = operation.getCondition();
QueryOperation invertedOperation = invertOperation(condition);

return calculateDistance(invertedOperation, doc);
return computeHeuristic(invertedOperation, doc);
}

private double calculateDistanceForNor(NorOperation operation, Object doc) {
return operation.getConditions()
.stream()
.mapToDouble(condition ->
TruthnessUtils.normalizeValue(calculateDistance(invertOperation(condition), doc)))
TruthnessUtils.normalizeValue(computeHeuristic(invertOperation(condition), doc)))
.sum();
}

Expand Down Expand Up @@ -332,7 +334,7 @@ private double calculateDistanceForNearSphere(NearSphereOperation operation, Obj
type key is case-sensitive.
(https://datatracker.ietf.org/doc/html/rfc7946#section-1.4) for more details.
*/
if (isDocument(actualPoint) && getValue(actualPoint, "type").equals("Point") && getValue(actualPoint, "coordinates") instanceof List<?>) {
if (isBsonDocument(actualPoint) && getValue(actualPoint, "type").equals("Point") && getValue(actualPoint, "coordinates") instanceof List<?>) {

List<?> coordinates = (List<?>) getValue(actualPoint, "coordinates");
x2 = Math.toRadians((Double) coordinates.get(0));
Expand Down Expand Up @@ -465,8 +467,8 @@ private double compareValues(Object val1, Object val2) {

if (val1 instanceof String && val2 instanceof String) {

if(taintHandler!=null){
taintHandler.handleTaintForStringEquals((String)val1,(String)val2, false);
if (taintHandler != null) {
taintHandler.handleTaintForStringEquals((String) val1, (String) val2, false);
}

return (double) DistanceHelper.getLeftAlignmentDistance((String) val1, (String) val2);
Expand All @@ -477,15 +479,15 @@ private double compareValues(Object val1, Object val2) {
}

if (val1 instanceof String && isObjectId(val2)) {
if(taintHandler!=null){
taintHandler.handleTaintForStringEquals((String)val1,val2.toString(),false);
if (taintHandler != null) {
taintHandler.handleTaintForStringEquals((String) val1, val2.toString(), false);
}
return (double) DistanceHelper.getLeftAlignmentDistance((String) val1, val2.toString());
}

if (val2 instanceof String && isObjectId(val1)) {
if(taintHandler!=null){
taintHandler.handleTaintForStringEquals(val1.toString(),val2.toString(),false);
if (taintHandler != null) {
taintHandler.handleTaintForStringEquals(val1.toString(), val2.toString(), false);
}
return (double) DistanceHelper.getLeftAlignmentDistance(val1.toString(), (String) val2);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
* Determines to which operation a query correspond.
Expand Down Expand Up @@ -35,11 +36,16 @@ public class QueryParser {
new ImplicitSelector()
);

public QueryOperation parse(Object query) {
return selectors.stream()
.map(selector -> selector.getOperation(query))
public QueryOperation parse(Object bsonDocument) {
List<QueryOperation> results = selectors.stream()
.map(selector -> selector.getOperation(bsonDocument))
.filter(Objects::nonNull)
.findFirst()
.orElse(null);
.collect(Collectors.toList());

if (results.size() != 1) {
return null;
}

return results.get(0);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,35 @@
import org.evomaster.client.java.controller.mongo.operations.*;

import java.util.List;
import java.util.Objects;

/**
* Represents a selector for the MongoDB `$all` operator.
* { field: { $all: [ value1 , value2 ... ] } }
*
* <p>
* This operator matches arrays that contain all elements specified in the query.
* The selector checks if the query value is a list and, if so, creates an
* {@link AllOperation} object corresponding to the field and the list of values.
*/
public class AllSelector extends SingleConditionQuerySelector {

public static final String ALL_OPERATOR = "$all";

@Override
protected QueryOperation parseValue(String fieldName, Object value) {
Objects.requireNonNull(fieldName);
Objects.requireNonNull(value);

if (value instanceof List<?>) {
return new AllOperation<>(fieldName, (List<?>) value);
} else {
return null;
}
return null;
}

@Override
protected String operator() {
return "$all";
return ALL_OPERATOR;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,21 +5,24 @@

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

/**
* Represents a selector for the MongoDB `$and` operator.
* { $and: [ { expression1 }, { expression2 } , ... , { expressionN } ] }
*/
public class AndSelector extends MultiConditionQuerySelector {

public static final String AND_OPERATOR = "$and";

@Override
protected QueryOperation parseConditions(List<?> value) {
ArrayList<QueryOperation> conditions = new ArrayList<>();
value.forEach(condition -> conditions.add(new QueryParser().parse(condition)));
return conditions.isEmpty()? null : new AndOperation(conditions);
protected QueryOperation composeConditions(List<QueryOperation> conditions) {
Objects.requireNonNull(conditions);
return conditions.isEmpty() ? null : new AndOperation(conditions);
}

@Override
protected String operator() {
return "$and";
return AND_OPERATOR;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,31 @@
import org.evomaster.client.java.controller.mongo.operations.*;
import org.evomaster.client.java.controller.mongo.QueryParser;

import static org.evomaster.client.java.controller.mongo.utils.BsonHelper.isDocument;
import java.util.Objects;

import static org.evomaster.client.java.controller.mongo.utils.BsonHelper.isBsonDocument;
/**
* { field: { $elemMatch: { query1, query2, ... } } }
*/
public class ElemMatchSelector extends SingleConditionQuerySelector {

public static final String ELEM_MATCH_OPERATOR = "$elemMatch";

@Override
protected QueryOperation parseValue(String fieldName, Object value) {
if (isDocument(value)) {
Objects.requireNonNull(fieldName);
Objects.requireNonNull(value);

if (isBsonDocument(value)) {
QueryOperation condition = new QueryParser().parse(value);
return new ElemMatchOperation(fieldName, condition);
} else {
return null;
}
return null;
}

@Override
protected String operator() {
return "$elemMatch";
return ELEM_MATCH_OPERATOR;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,30 @@
import org.evomaster.client.java.controller.mongo.operations.EqualsOperation;
import org.evomaster.client.java.controller.mongo.operations.QueryOperation;

import java.util.Objects;

/**
* { field: { $eq: value } }
*/
public class EqualsSelector extends SingleConditionQuerySelector {

public static final String EQUALS_OPERATOR = "$eq";

/**
* Parses the provided field name and value into a QueryOperation representing an equality condition.
*
* @param fieldName the name of the field involved in the condition; must not be null
* @param value the value to match against the field; null is a valid value
* @return an instance of EqualsOperation representing the equality condition for the given field and value
*/
@Override
protected QueryOperation parseValue(String fieldName, Object value) {
Objects.requireNonNull(fieldName);
return new EqualsOperation<>(fieldName, value);
}

@Override
protected String operator() {
return "$eq";
return EQUALS_OPERATOR;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,28 @@

import org.evomaster.client.java.controller.mongo.operations.*;

import java.util.Objects;

/**
* { field: { $exists: boolean } }
*/
public class ExistsSelector extends SingleConditionQuerySelector {

public static final String EXISTS_OPERATOR = "$exists";

@Override
protected QueryOperation parseValue(String fieldName, Object value) {
if (value instanceof Boolean) return new ExistsOperation(fieldName, (Boolean) value);
return null;
Objects.requireNonNull(fieldName);

if (value!=null && value instanceof Boolean) {
return new ExistsOperation(fieldName, (Boolean) value);
} else {
return null;
}
}

@Override
protected String operator() {
return "$exists";
return EXISTS_OPERATOR;
}
}
}
Loading
Loading