Skip to content

Commit 7ea66bc

Browse files
Merge branch 'master' into feature/cql-heuristics-calculator
2 parents 7671a3e + 1d31fad commit 7ea66bc

122 files changed

Lines changed: 5615 additions & 1938 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,10 @@
1313
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
1414
hs_err_pid*
1515

16+
# IntelliJ ANTLR plugin recognizer default locations:
17+
core/gen/
18+
core/src/main/antlr4/org/evomaster/core/parser/gen
19+
1620
**/*.DS_Store
1721
/.idea/
1822
.idea/

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,8 @@ Note, since version 4.0.0, now _EvoMaster_ by default also creates an interactiv
138138

139139
* _Schema_: REST APIs must provide a schema in [OpenAPI format](https://www.openapis.org/). We support versions _2.0_, _3.0_ and _3.1_. Unfortunately, support for version _3.2_ is currently on hold due to [swagger-parser](https://github.com/swagger-api/swagger-parser/issues/2248).
140140

141+
* _OAI Overlay_: for REST APIs, we natively support [Overlay](https://github.com/OAI/Overlay-Specification) transformations. This is needed for testers that want to add test data via "examples" entries without modifying the OpenAPI scheme directly, [see documentation](./docs/overlay.md).
142+
141143
* _Output_: the tool generates _JUnit_ (version 4 or 5) tests, written in either _Java_ or _Kotlin_, as well as test suites in _Python_ and _JavaScript_. For a complete list, see the documentation for the CLI parameter [--outputFormat](docs/options.md).
142144
Some examples are: PYTHON_UNITTEST, KOTLIN_JUNIT_5, JAVA_JUNIT_4 and JS_JEST.
143145
Note that the generated tests rely on third-party libraries (e.g., to make HTTP calls).

client-java/controller/src/main/java/org/evomaster/client/java/controller/mongo/MongoHeuristicsCalculator.java

Lines changed: 42 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ public class MongoHeuristicsCalculator {
2020
private final TaintHandler taintHandler;
2121

2222
public MongoHeuristicsCalculator() {
23-
this(null);
23+
this(null);
2424
}
2525

2626
public MongoHeuristicsCalculator(TaintHandler taintHandler) {
@@ -35,63 +35,65 @@ public MongoHeuristicsCalculator(TaintHandler taintHandler) {
3535
* @return a branch distance, where 0 means that the document would make the QUERY resolve as true
3636
*/
3737
public double computeExpression(Object query, Object doc) {
38+
3839
QueryOperation operation = getOperation(query);
39-
return calculateDistance(operation, doc);
40+
return computeHeuristic(operation, doc);
4041
}
4142

4243
private QueryOperation getOperation(Object query) {
4344
return new QueryParser().parse(query);
4445
}
4546

46-
private double calculateDistance(QueryOperation operation, Object doc) {
47-
if (operation instanceof EqualsOperation<?>)
47+
private double computeHeuristic(QueryOperation operation, Object doc) {
48+
if (operation instanceof EqualsOperation<?>) {
4849
return calculateDistanceForEquals((EqualsOperation<?>) operation, doc);
49-
if (operation instanceof NotEqualsOperation<?>)
50+
} else if (operation instanceof NotEqualsOperation<?>) {
5051
return calculateDistanceForNotEquals((NotEqualsOperation<?>) operation, doc);
51-
if (operation instanceof GreaterThanOperation<?>)
52+
} else if (operation instanceof GreaterThanOperation<?>) {
5253
return calculateDistanceForGreaterThan((GreaterThanOperation<?>) operation, doc);
53-
if (operation instanceof GreaterThanEqualsOperation<?>)
54+
} else if (operation instanceof GreaterThanEqualsOperation<?>) {
5455
return calculateDistanceForGreaterEqualsThan((GreaterThanEqualsOperation<?>) operation, doc);
55-
if (operation instanceof LessThanOperation<?>)
56+
} else if (operation instanceof LessThanOperation<?>) {
5657
return calculateDistanceForLessThan((LessThanOperation<?>) operation, doc);
57-
if (operation instanceof LessThanEqualsOperation<?>)
58+
} else if (operation instanceof LessThanEqualsOperation<?>) {
5859
return calculateDistanceForLessEqualsThan((LessThanEqualsOperation<?>) operation, doc);
59-
if (operation instanceof AndOperation)
60+
} else if (operation instanceof AndOperation) {
6061
return calculateDistanceForAnd((AndOperation) operation, doc);
61-
if (operation instanceof OrOperation)
62+
} else if (operation instanceof OrOperation) {
6263
return calculateDistanceForOr((OrOperation) operation, doc);
63-
if (operation instanceof NorOperation)
64+
} else if (operation instanceof NorOperation) {
6465
return calculateDistanceForNor((NorOperation) operation, doc);
65-
if (operation instanceof InOperation<?>)
66+
} else if (operation instanceof InOperation<?>) {
6667
return calculateDistanceForIn((InOperation<?>) operation, doc);
67-
if (operation instanceof NotInOperation<?>)
68+
} else if (operation instanceof NotInOperation<?>) {
6869
return calculateDistanceForNotIn((NotInOperation<?>) operation, doc);
69-
if (operation instanceof AllOperation<?>)
70+
} else if (operation instanceof AllOperation<?>) {
7071
return calculateDistanceForAll((AllOperation<?>) operation, doc);
71-
if (operation instanceof InvertedAllOperation<?>)
72+
} else if (operation instanceof InvertedAllOperation<?>) {
7273
return calculateDistanceForInvertedAll((InvertedAllOperation<?>) operation, doc);
73-
if (operation instanceof SizeOperation)
74+
} else if (operation instanceof SizeOperation) {
7475
return calculateDistanceForSize((SizeOperation) operation, doc);
75-
if (operation instanceof InvertedSizeOperation)
76+
} else if (operation instanceof InvertedSizeOperation) {
7677
return calculateDistanceForInvertedSize((InvertedSizeOperation) operation, doc);
77-
if (operation instanceof ElemMatchOperation)
78+
} else if (operation instanceof ElemMatchOperation) {
7879
return calculateDistanceForElemMatch((ElemMatchOperation) operation, doc);
79-
if (operation instanceof ExistsOperation)
80+
} else if (operation instanceof ExistsOperation) {
8081
return calculateDistanceForExists((ExistsOperation) operation, doc);
81-
if (operation instanceof ModOperation)
82+
} else if (operation instanceof ModOperation) {
8283
return calculateDistanceForMod((ModOperation) operation, doc);
83-
if (operation instanceof InvertedModOperation)
84+
} else if (operation instanceof InvertedModOperation) {
8485
return calculateDistanceForInvertedMod((InvertedModOperation) operation, doc);
85-
if (operation instanceof NotOperation)
86+
} else if (operation instanceof NotOperation) {
8687
return calculateDistanceForNot((NotOperation) operation, doc);
87-
if (operation instanceof TypeOperation)
88+
} else if (operation instanceof TypeOperation) {
8889
return calculateDistanceForType((TypeOperation) operation, doc);
89-
if (operation instanceof InvertedTypeOperation)
90+
} else if (operation instanceof InvertedTypeOperation) {
9091
return calculateDistanceForInvertedType((InvertedTypeOperation) operation, doc);
91-
if (operation instanceof NearSphereOperation)
92+
} else if (operation instanceof NearSphereOperation) {
9293
return calculateDistanceForNearSphere((NearSphereOperation) operation, doc);
93-
94-
return Double.MAX_VALUE;
94+
} else {
95+
return Double.MAX_VALUE;
96+
}
9597
}
9698

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

135137
private double calculateDistanceForOr(OrOperation operation, Object doc) {
136138
return operation.getConditions().stream()
137-
.mapToDouble(condition -> calculateDistance(condition, doc))
139+
.mapToDouble(condition -> computeHeuristic(condition, doc))
138140
.min()
139141
.getAsDouble();
140142
}
@@ -143,7 +145,7 @@ private double calculateDistanceForAnd(AndOperation operation, Object doc) {
143145
return operation.getConditions()
144146
.stream()
145147
.mapToDouble(condition ->
146-
TruthnessUtils.normalizeValue(calculateDistance(condition, doc)))
148+
TruthnessUtils.normalizeValue(computeHeuristic(condition, doc)))
147149
.sum();
148150
}
149151

@@ -233,7 +235,7 @@ private double calculateDistanceForElemMatch(ElemMatchOperation operation, Objec
233235
.mapToDouble(elem -> {
234236
Object newDoc = newDocument(doc);
235237
appendToDocument(newDoc, operation.getFieldName(), elem);
236-
return calculateDistance(operation.getCondition(), newDoc);
238+
return computeHeuristic(operation.getCondition(), newDoc);
237239
})
238240
.min()
239241
.getAsDouble();
@@ -289,14 +291,14 @@ private double calculateDistanceForNot(NotOperation operation, Object doc) {
289291
QueryOperation condition = operation.getCondition();
290292
QueryOperation invertedOperation = invertOperation(condition);
291293

292-
return calculateDistance(invertedOperation, doc);
294+
return computeHeuristic(invertedOperation, doc);
293295
}
294296

295297
private double calculateDistanceForNor(NorOperation operation, Object doc) {
296298
return operation.getConditions()
297299
.stream()
298300
.mapToDouble(condition ->
299-
TruthnessUtils.normalizeValue(calculateDistance(invertOperation(condition), doc)))
301+
TruthnessUtils.normalizeValue(computeHeuristic(invertOperation(condition), doc)))
300302
.sum();
301303
}
302304

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

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

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

468-
if(taintHandler!=null){
469-
taintHandler.handleTaintForStringEquals((String)val1,(String)val2, false);
470+
if (taintHandler != null) {
471+
taintHandler.handleTaintForStringEquals((String) val1, (String) val2, false);
470472
}
471473

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

479481
if (val1 instanceof String && isObjectId(val2)) {
480-
if(taintHandler!=null){
481-
taintHandler.handleTaintForStringEquals((String)val1,val2.toString(),false);
482+
if (taintHandler != null) {
483+
taintHandler.handleTaintForStringEquals((String) val1, val2.toString(), false);
482484
}
483485
return (double) DistanceHelper.getLeftAlignmentDistance((String) val1, val2.toString());
484486
}
485487

486488
if (val2 instanceof String && isObjectId(val1)) {
487-
if(taintHandler!=null){
488-
taintHandler.handleTaintForStringEquals(val1.toString(),val2.toString(),false);
489+
if (taintHandler != null) {
490+
taintHandler.handleTaintForStringEquals(val1.toString(), val2.toString(), false);
489491
}
490492
return (double) DistanceHelper.getLeftAlignmentDistance(val1.toString(), (String) val2);
491493
}

client-java/controller/src/main/java/org/evomaster/client/java/controller/mongo/QueryParser.java

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import java.util.Arrays;
77
import java.util.List;
88
import java.util.Objects;
9+
import java.util.stream.Collectors;
910

1011
/**
1112
* Determines to which operation a query correspond.
@@ -35,11 +36,16 @@ public class QueryParser {
3536
new ImplicitSelector()
3637
);
3738

38-
public QueryOperation parse(Object query) {
39-
return selectors.stream()
40-
.map(selector -> selector.getOperation(query))
39+
public QueryOperation parse(Object bsonDocument) {
40+
List<QueryOperation> results = selectors.stream()
41+
.map(selector -> selector.getOperation(bsonDocument))
4142
.filter(Objects::nonNull)
42-
.findFirst()
43-
.orElse(null);
43+
.collect(Collectors.toList());
44+
45+
if (results.size() != 1) {
46+
return null;
47+
}
48+
49+
return results.get(0);
4450
}
45-
}
51+
}

client-java/controller/src/main/java/org/evomaster/client/java/controller/mongo/selectors/AllSelector.java

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,21 +3,35 @@
33
import org.evomaster.client.java.controller.mongo.operations.*;
44

55
import java.util.List;
6+
import java.util.Objects;
67

78
/**
9+
* Represents a selector for the MongoDB `$all` operator.
810
* { field: { $all: [ value1 , value2 ... ] } }
11+
*
12+
* <p>
13+
* This operator matches arrays that contain all elements specified in the query.
14+
* The selector checks if the query value is a list and, if so, creates an
15+
* {@link AllOperation} object corresponding to the field and the list of values.
916
*/
1017
public class AllSelector extends SingleConditionQuerySelector {
18+
19+
public static final String ALL_OPERATOR = "$all";
20+
1121
@Override
1222
protected QueryOperation parseValue(String fieldName, Object value) {
23+
Objects.requireNonNull(fieldName);
24+
Objects.requireNonNull(value);
25+
1326
if (value instanceof List<?>) {
1427
return new AllOperation<>(fieldName, (List<?>) value);
28+
} else {
29+
return null;
1530
}
16-
return null;
1731
}
1832

1933
@Override
2034
protected String operator() {
21-
return "$all";
35+
return ALL_OPERATOR;
2236
}
23-
}
37+
}

client-java/controller/src/main/java/org/evomaster/client/java/controller/mongo/selectors/AndSelector.java

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,21 +5,24 @@
55

66
import java.util.ArrayList;
77
import java.util.List;
8+
import java.util.Objects;
89

910
/**
11+
* Represents a selector for the MongoDB `$and` operator.
1012
* { $and: [ { expression1 }, { expression2 } , ... , { expressionN } ] }
1113
*/
1214
public class AndSelector extends MultiConditionQuerySelector {
1315

16+
public static final String AND_OPERATOR = "$and";
17+
1418
@Override
15-
protected QueryOperation parseConditions(List<?> value) {
16-
ArrayList<QueryOperation> conditions = new ArrayList<>();
17-
value.forEach(condition -> conditions.add(new QueryParser().parse(condition)));
18-
return conditions.isEmpty()? null : new AndOperation(conditions);
19+
protected QueryOperation composeConditions(List<QueryOperation> conditions) {
20+
Objects.requireNonNull(conditions);
21+
return conditions.isEmpty() ? null : new AndOperation(conditions);
1922
}
2023

2124
@Override
2225
protected String operator() {
23-
return "$and";
26+
return AND_OPERATOR;
2427
}
25-
}
28+
}

client-java/controller/src/main/java/org/evomaster/client/java/controller/mongo/selectors/ElemMatchSelector.java

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,22 +3,31 @@
33
import org.evomaster.client.java.controller.mongo.operations.*;
44
import org.evomaster.client.java.controller.mongo.QueryParser;
55

6-
import static org.evomaster.client.java.controller.mongo.utils.BsonHelper.isDocument;
6+
import java.util.Objects;
7+
8+
import static org.evomaster.client.java.controller.mongo.utils.BsonHelper.isBsonDocument;
79
/**
810
* { field: { $elemMatch: { query1, query2, ... } } }
911
*/
1012
public class ElemMatchSelector extends SingleConditionQuerySelector {
13+
14+
public static final String ELEM_MATCH_OPERATOR = "$elemMatch";
15+
1116
@Override
1217
protected QueryOperation parseValue(String fieldName, Object value) {
13-
if (isDocument(value)) {
18+
Objects.requireNonNull(fieldName);
19+
Objects.requireNonNull(value);
20+
21+
if (isBsonDocument(value)) {
1422
QueryOperation condition = new QueryParser().parse(value);
1523
return new ElemMatchOperation(fieldName, condition);
24+
} else {
25+
return null;
1626
}
17-
return null;
1827
}
1928

2029
@Override
2130
protected String operator() {
22-
return "$elemMatch";
31+
return ELEM_MATCH_OPERATOR;
2332
}
24-
}
33+
}

client-java/controller/src/main/java/org/evomaster/client/java/controller/mongo/selectors/EqualsSelector.java

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,30 @@
33
import org.evomaster.client.java.controller.mongo.operations.EqualsOperation;
44
import org.evomaster.client.java.controller.mongo.operations.QueryOperation;
55

6+
import java.util.Objects;
7+
68
/**
79
* { field: { $eq: value } }
810
*/
911
public class EqualsSelector extends SingleConditionQuerySelector {
1012

13+
public static final String EQUALS_OPERATOR = "$eq";
14+
15+
/**
16+
* Parses the provided field name and value into a QueryOperation representing an equality condition.
17+
*
18+
* @param fieldName the name of the field involved in the condition; must not be null
19+
* @param value the value to match against the field; null is a valid value
20+
* @return an instance of EqualsOperation representing the equality condition for the given field and value
21+
*/
1122
@Override
1223
protected QueryOperation parseValue(String fieldName, Object value) {
24+
Objects.requireNonNull(fieldName);
1325
return new EqualsOperation<>(fieldName, value);
1426
}
1527

1628
@Override
1729
protected String operator() {
18-
return "$eq";
30+
return EQUALS_OPERATOR;
1931
}
20-
}
32+
}

0 commit comments

Comments
 (0)