-
Notifications
You must be signed in to change notification settings - Fork 86
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
25 changed files
with
631 additions
and
145 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
42 changes: 42 additions & 0 deletions
42
.../main/java/org/evomaster/client/java/controller/mongo/operations/NearSphereOperation.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
package org.evomaster.client.java.controller.mongo.operations; | ||
|
||
/** | ||
* Represent $nearSphere operation. | ||
* Specifies a point for which a geospatial query returns the documents from nearest to farthest. | ||
*/ | ||
public class NearSphereOperation extends QueryOperation { | ||
private final String fieldName; | ||
private final Double longitude; | ||
private final Double latitude; | ||
private final Double maxDistance; | ||
private final Double minDistance; | ||
|
||
|
||
public NearSphereOperation(String fieldName, Double longitude, Double latitude, Double maxDistance, Double minDistance) { | ||
this.fieldName = fieldName; | ||
this.longitude = longitude; | ||
this.latitude = latitude; | ||
this.maxDistance = maxDistance; | ||
this.minDistance = minDistance; | ||
} | ||
|
||
public String getFieldName() { | ||
return fieldName; | ||
} | ||
|
||
public Double getLongitude() { | ||
return longitude; | ||
} | ||
|
||
public Double getLatitude() { | ||
return latitude; | ||
} | ||
|
||
public Double getMaxDistance() { | ||
return maxDistance; | ||
} | ||
|
||
public Double getMinDistance() { | ||
return minDistance; | ||
} | ||
} |
96 changes: 96 additions & 0 deletions
96
...rc/main/java/org/evomaster/client/java/controller/mongo/selectors/NearSphereSelector.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,96 @@ | ||
package org.evomaster.client.java.controller.mongo.selectors; | ||
|
||
import org.evomaster.client.java.controller.mongo.operations.NearSphereOperation; | ||
import org.evomaster.client.java.controller.mongo.operations.QueryOperation; | ||
|
||
import java.util.List; | ||
import java.util.Set; | ||
|
||
import static org.evomaster.client.java.controller.mongo.utils.BsonHelper.*; | ||
|
||
/** | ||
* { field: { $nearSphere: [ x, y ], $maxDistance: value, $minDistance: value } } | ||
* or | ||
* { field: { $nearSphere: {$geometry: {type: "Point", coordinates: [ longitude, latitude ]}, $maxDistance: value, $minDistance: value}} | ||
*/ | ||
public class NearSphereSelector extends QuerySelector { | ||
|
||
public static final int EARTH_RADIUS_IN_METERS = 6371000; | ||
|
||
@Override | ||
public QueryOperation getOperation(Object query) { | ||
String fieldName = extractFieldName(query); | ||
Object innerDoc = getValue(query, fieldName); | ||
|
||
if (!isDocument(innerDoc) || !hasTheExpectedOperator(query)) return null; | ||
|
||
Object point = getValue(innerDoc, operator()); | ||
Object geometry = getValue(point, "$geometry"); | ||
boolean legacyCoordinates = geometry == null; | ||
|
||
return parseValue(fieldName, innerDoc, legacyCoordinates); | ||
} | ||
|
||
protected String extractOperator(Object query) { | ||
String fieldName = extractFieldName(query); | ||
Set<String> keys = documentKeys(getValue(query, fieldName)); | ||
return keys.stream().findFirst().orElse(null); | ||
} | ||
|
||
@Override | ||
protected String operator() { | ||
return "$nearSphere"; | ||
} | ||
|
||
public QueryOperation parseValue(String fieldName, Object innerDoc, boolean legacyCoordinates) { | ||
Object longitude; | ||
Object latitude; | ||
Object maxDistance = null; | ||
Object minDistance = null; | ||
|
||
Object point = getValue(innerDoc, operator()); | ||
|
||
if (legacyCoordinates) { | ||
Object maxDistanceInRadians = getValue(innerDoc, "$maxDistance"); | ||
Object minDistanceInRadians = getValue(innerDoc, "$minDistance"); | ||
|
||
if (maxDistanceInRadians instanceof Double) { | ||
maxDistance = radiansToMeters((double) maxDistanceInRadians); | ||
} | ||
|
||
if (minDistanceInRadians instanceof Double) { | ||
minDistance = radiansToMeters((double) minDistanceInRadians); | ||
} | ||
|
||
longitude = getValue(point, "x"); | ||
latitude = getValue(point, "y"); | ||
} else { | ||
Object geometry = getValue(point, "$geometry"); | ||
Object coordinates = getValue(geometry, "coordinates"); | ||
|
||
if (coordinates instanceof List<?> && ((List<?>) coordinates).size() == 2) { | ||
longitude = ((List<?>) coordinates).get(0); | ||
latitude = ((List<?>) coordinates).get(1); | ||
} else { | ||
return null; | ||
} | ||
|
||
maxDistance = getValue(point, "$maxDistance"); | ||
minDistance = getValue(point, "$minDistance"); | ||
} | ||
|
||
if (longitude instanceof Double && latitude instanceof Double && (maxDistance == null || maxDistance instanceof Double) && (minDistance == null || minDistance instanceof Double)) { | ||
return new NearSphereOperation(fieldName, (Double) longitude, (Double) latitude, (Double) maxDistance, (Double) minDistance); | ||
} | ||
return null; | ||
} | ||
|
||
private static double radiansToMeters(double radians) { | ||
return EARTH_RADIUS_IN_METERS * radians; | ||
} | ||
|
||
private String extractFieldName(Object query) { | ||
Set<String> keys = documentKeys(query); | ||
return keys.stream().findFirst().orElse(null); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
54 changes: 54 additions & 0 deletions
54
...entation/coverage/methodreplacement/thirdpartyclasses/CursorPreparerClassReplacement.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
package org.evomaster.client.java.instrumentation.coverage.methodreplacement.thirdpartyclasses; | ||
|
||
import org.evomaster.client.java.instrumentation.coverage.methodreplacement.Replacement; | ||
import org.evomaster.client.java.instrumentation.coverage.methodreplacement.ThirdPartyCast; | ||
import org.evomaster.client.java.instrumentation.coverage.methodreplacement.UsageFilter; | ||
import org.evomaster.client.java.instrumentation.shared.ReplacementCategory; | ||
import org.evomaster.client.java.instrumentation.shared.ReplacementType; | ||
|
||
import java.lang.reflect.Field; | ||
import java.util.function.Function; | ||
|
||
/** | ||
* This replacement should ideally be unnecessary due to the existence of MongoOperationClassReplacement. | ||
* However, there appears to be an issue as operations related to IDs are not being captured by this replacement, | ||
* and the root cause for this behavior is not immediately apparent. | ||
* Until this issue is resolved, this workaround should address the problem. | ||
*/ | ||
public class CursorPreparerClassReplacement extends MongoOperationClassReplacement { | ||
private static final CursorPreparerClassReplacement singleton = new CursorPreparerClassReplacement(); | ||
|
||
@Override | ||
protected String getNameOfThirdPartyTargetClass() { | ||
return "org.springframework.data.mongodb.core.CursorPreparer"; | ||
} | ||
|
||
@Replacement(replacingStatic = false, type = ReplacementType.TRACKER, id = "initiateFind", usageFilter = UsageFilter.ANY, category = ReplacementCategory.MONGO, castTo = "com.mongodb.client.FindIterable") | ||
public static Object initiateFind(Object preparer, @ThirdPartyCast(actualType = "com.mongodb.client.MongoCollection") Object mongoCollection, Function<Object, Object> find) { | ||
return handleFind(mongoCollection, find); | ||
} | ||
|
||
private static Object handleFind(Object mongoCollection, Function<Object, Object> find) { | ||
long startTime = System.currentTimeMillis(); | ||
|
||
Object argument = getField(find, "arg$1"); | ||
Object query = getField(argument, "query"); | ||
Object result = find.apply(mongoCollection); | ||
|
||
long endTime = System.currentTimeMillis(); | ||
|
||
handleMongo(mongoCollection, query, true, endTime - startTime); | ||
|
||
return result; | ||
} | ||
|
||
private static Object getField(Object object, String fieldName) { | ||
try { | ||
Field field = object.getClass().getDeclaredField(fieldName); | ||
field.setAccessible(true); | ||
return field.get(object); | ||
} catch (NoSuchFieldException | IllegalAccessException e) { | ||
throw new RuntimeException(e); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.