Skip to content

Commit 5e32d58

Browse files
authored
Merge pull request #1246 from WebFuzzing/issue-#1154
starting addressing #1154
2 parents e643509 + 04b94d9 commit 5e32d58

File tree

32 files changed

+773
-24
lines changed

32 files changed

+773
-24
lines changed

client-java/controller-api/src/main/java/org/evomaster/client/java/controller/api/ControllerConstants.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,4 +31,6 @@ public class ControllerConstants {
3131
public static final String MONGO_INSERTION = "/mongoInsertion";
3232

3333
public static final String POST_SEARCH_ACTION = "/postSearchAction";
34+
35+
public static final String DERIVE_PARAMS = "/deriveParams";
3436
}

client-java/controller-api/src/main/java/org/evomaster/client/java/controller/api/dto/problem/RestProblemDto.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package org.evomaster.client.java.controller.api.dto.problem;
22

3+
import org.evomaster.client.java.controller.api.dto.problem.param.RestDerivedParamDto;
4+
35
import java.util.List;
46

57
/**
@@ -25,4 +27,7 @@ public class RestProblemDto extends ProblemInfoDto{
2527
* should not be set
2628
*/
2729
public String openApiSchema;
30+
31+
32+
public List<RestDerivedParamDto> derivedParams;
2833
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
package org.evomaster.client.java.controller.api.dto.problem.param;
2+
3+
public class DeriveParamResponseDto {
4+
5+
public String paramName;
6+
7+
public String paramValue;
8+
9+
public Integer actionIndex;
10+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
package org.evomaster.client.java.controller.api.dto.problem.param;
2+
3+
public class DerivedParamChangeReqDto {
4+
5+
public String paramName;
6+
7+
public String jsonData;
8+
9+
public String entryPoint;
10+
11+
public Integer actionIndex;
12+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
package org.evomaster.client.java.controller.api.dto.problem.param;
2+
3+
import java.util.Set;
4+
5+
public class RestDerivedParamDto {
6+
7+
/**
8+
* The name of the parameter
9+
*/
10+
public String paramName;
11+
12+
/**
13+
* The context in which this parameter is used, eg, whether it is a body payload or a query parameter.
14+
* This information is needed, as EM will need to determine which other values to use to derive this param.
15+
*/
16+
public String context;
17+
18+
/**
19+
* In case the parameter is used differently in different endpoints, specify for which endpoints this
20+
* derivation applies. If left null, it will apply to all endpoints where this param is present.
21+
*/
22+
public Set<String> endpointPaths;
23+
24+
/**
25+
* Optional positive integer specifying in which order the updates are done.
26+
* Left empty is equivalent to set it to 0.
27+
*
28+
* If all updates are independent (or there is only 1), then there is no point in specifying this value.
29+
* However, if the derivation of A depends on first deriving B, then A should get an higher order than B,
30+
* eg 1 vs 0.
31+
* In this case, first B is computed based on current state, and then, A is computed with current state
32+
* updated with derived B.
33+
*/
34+
public Integer order;
35+
}

client-java/controller/src/main/java/org/evomaster/client/java/controller/internal/EMController.java

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@
88
import org.evomaster.client.java.controller.api.dto.database.operations.MongoDatabaseCommandDto;
99
import org.evomaster.client.java.controller.api.dto.database.operations.MongoInsertionResultsDto;
1010
import org.evomaster.client.java.controller.api.dto.problem.*;
11+
import org.evomaster.client.java.controller.api.dto.problem.param.DeriveParamResponseDto;
12+
import org.evomaster.client.java.controller.api.dto.problem.param.DerivedParamChangeReqDto;
13+
import org.evomaster.client.java.controller.api.dto.problem.param.RestDerivedParamDto;
1114
import org.evomaster.client.java.controller.api.dto.problem.rpc.ScheduleTaskInvocationsDto;
1215
import org.evomaster.client.java.controller.api.dto.problem.rpc.ScheduleTaskInvocationsResult;
1316
import org.evomaster.client.java.controller.mongo.MongoScriptRunner;
@@ -206,6 +209,14 @@ public Response getSutInfo(@Context HttpServletRequest httpServletRequest) {
206209
dto.restProblem.endpointsToSkip = rp.getEndpointsToSkip();
207210
dto.restProblem.openApiSchema = rp.getOpenApiSchema();
208211
dto.restProblem.servicesToNotMock = servicesToNotMock;
212+
dto.restProblem.derivedParams = rp.getDerivedParams().stream()
213+
.map(p -> new RestDerivedParamDto(){{
214+
paramName = p.paramName;
215+
context = p.context.toString();
216+
endpointPaths = p.endpointPaths;
217+
order = p.order;
218+
}})
219+
.collect(Collectors.toList());
209220

210221
} else if (info instanceof GraphQlProblem) {
211222
GraphQlProblem p = (GraphQlProblem) info;
@@ -640,6 +651,42 @@ public Response scheduleTasksCommand(
640651
return Response.status(200).entity(WrappedResponseDto.withData(responseDto)).build();
641652
}
642653

654+
655+
@Path(ControllerConstants.DERIVE_PARAMS)
656+
@Consumes(MediaType.APPLICATION_JSON)
657+
@POST
658+
public Response deriveParams(List<DerivedParamChangeReqDto> dtos){
659+
660+
List<DeriveParamResponseDto> results = new ArrayList<>();
661+
List<String> errors = new ArrayList<>();
662+
663+
for(DerivedParamChangeReqDto dto : dtos){
664+
noKillSwitch(() -> {
665+
try {
666+
String value = sutController.deriveObjectParameterData(dto.paramName, dto.jsonData, dto.entryPoint);
667+
DeriveParamResponseDto response = new DeriveParamResponseDto();
668+
response.paramName = dto.paramName;
669+
response.paramValue = value;
670+
response.actionIndex = dto.actionIndex;
671+
results.add(response);
672+
} catch (Exception e) {
673+
String msg = "ERROR: failed to derived object parameter for '"
674+
+ dto.paramName +"': " + e.getMessage();
675+
SimpleLogger.error(msg, e);
676+
errors.add(msg);
677+
}
678+
});
679+
}
680+
681+
if(!errors.isEmpty()){
682+
String msg = "There were " + errors.size() + " errors.\n";
683+
msg += String.join("\n", errors);
684+
return Response.status(500).entity(WrappedResponseDto.withError(msg)).build();
685+
}
686+
687+
return Response.status(200).entity(WrappedResponseDto.withData(results)).build();
688+
}
689+
643690
@Path(ControllerConstants.NEW_ACTION)
644691
@Consumes(MediaType.APPLICATION_JSON)
645692
@PUT

client-java/controller/src/main/java/org/evomaster/client/java/controller/internal/SutController.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -241,6 +241,20 @@ public final void setControllerHost(String controllerHost) {
241241
this.controllerHost = controllerHost;
242242
}
243243

244+
245+
/**
246+
* Function used to derived params from the other values in the same object.
247+
* @param paramName the name of the parameter we need to derive
248+
* @param jsonObject JSON representation of full object evolved in EM. You might need just a subset to derive needed param
249+
* @param endpointPath the path of endpoint for this object, in case need to distinguish between same params in different endpoints
250+
* @return a string representation of derived value for paramName
251+
* @throws Exception
252+
*/
253+
public String deriveObjectParameterData(String paramName, String jsonObject, String endpointPath) throws Exception{
254+
throw new IllegalStateException("You must override deriveObjectParameterData method if you use derived param data");
255+
}
256+
257+
244258
@Override
245259
public InsertionResultsDto execInsertionsIntoDatabase(List<InsertionDto> insertions, InsertionResultsDto... previous) {
246260

client-java/controller/src/main/java/org/evomaster/client/java/controller/problem/RestProblem.java

Lines changed: 42 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package org.evomaster.client.java.controller.problem;
22

3+
import org.evomaster.client.java.controller.problem.param.RestDerivedParam;
4+
35
import java.util.ArrayList;
46
import java.util.Collections;
57
import java.util.List;
@@ -15,10 +17,19 @@ public class RestProblem extends ProblemInfo{
1517

1618
private final String openApiSchema;
1719

20+
private final List<RestDerivedParam> derivedParams;
21+
1822
public RestProblem(String openApiUrl, List<String> endpointsToSkip) {
1923
this(openApiUrl, endpointsToSkip, null);
2024
}
2125

26+
public RestProblem(
27+
String openApiUrl,
28+
List<String> endpointsToSkip,
29+
String openApiSchema
30+
){
31+
this(openApiUrl, endpointsToSkip, openApiSchema, null, null);
32+
}
2233

2334
/**
2435
*
@@ -31,13 +42,28 @@ public RestProblem(String openApiUrl, List<String> endpointsToSkip) {
3142
* @param openApiSchema the actual schema, as a string. Note, if this specified, then
3243
* openApiUrl must be null
3344
*/
34-
public RestProblem(String openApiUrl, List<String> endpointsToSkip, String openApiSchema) {
45+
public RestProblem(
46+
String openApiUrl,
47+
List<String> endpointsToSkip,
48+
String openApiSchema,
49+
List<ExternalService> servicesToNotMock,
50+
List<RestDerivedParam> derivedParams
51+
) {
3552
this.openApiUrl = openApiUrl;
3653
this.endpointsToSkip = endpointsToSkip == null
37-
? new ArrayList<>()
38-
: new ArrayList<>(endpointsToSkip);
54+
? Collections.emptyList()
55+
: Collections.unmodifiableList(new ArrayList<>(endpointsToSkip));
3956
this.openApiSchema = openApiSchema;
4057

58+
this.servicesToNotMock.clear();
59+
if(servicesToNotMock != null && !servicesToNotMock.isEmpty()) {
60+
this.servicesToNotMock.addAll(servicesToNotMock);
61+
}
62+
63+
this.derivedParams = derivedParams == null
64+
? Collections.emptyList()
65+
: Collections.unmodifiableList(new ArrayList<>(derivedParams));
66+
4167
boolean url = openApiUrl != null && !openApiUrl.isEmpty();
4268
boolean schema = openApiSchema != null && !openApiSchema.isEmpty();
4369

@@ -49,22 +75,29 @@ public RestProblem(String openApiUrl, List<String> endpointsToSkip, String openA
4975
}
5076
}
5177

78+
79+
@Override
80+
public RestProblem withServicesToNotMock(List<ExternalService> servicesToNotMock){
81+
return new RestProblem(openApiUrl, endpointsToSkip,openApiSchema,servicesToNotMock,derivedParams);
82+
}
83+
84+
public RestProblem withDerivedParams(List<RestDerivedParam> derivedParams){
85+
return new RestProblem(openApiUrl, endpointsToSkip,openApiSchema,servicesToNotMock,derivedParams);
86+
}
87+
5288
public String getOpenApiUrl() {
5389
return openApiUrl;
5490
}
5591

5692
public List<String> getEndpointsToSkip() {
57-
return Collections.unmodifiableList(endpointsToSkip);
93+
return endpointsToSkip;
5894
}
5995

6096
public String getOpenApiSchema() {
6197
return openApiSchema;
6298
}
6399

64-
@Override
65-
public RestProblem withServicesToNotMock(List<ExternalService> servicesToNotMock){
66-
RestProblem p = new RestProblem(this.openApiUrl, this.endpointsToSkip, this.openApiSchema);
67-
p.servicesToNotMock.addAll(servicesToNotMock);
68-
return p;
100+
public List<RestDerivedParam> getDerivedParams() {
101+
return derivedParams;
69102
}
70103
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
package org.evomaster.client.java.controller.problem.param;
2+
3+
public enum DerivedParamContext {
4+
5+
BODY_PAYLOAD
6+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
package org.evomaster.client.java.controller.problem.param;
2+
3+
import java.util.Objects;
4+
import java.util.Set;
5+
6+
public class RestDerivedParam {
7+
8+
/**
9+
* The name of the parameter
10+
*/
11+
public final String paramName;
12+
13+
/**
14+
* The context in which this parameter is used, eg, whether it is a body payload or a query parameter.
15+
* This information is needed, as EM will need to determine which other values to use to derive this param.
16+
*/
17+
public final DerivedParamContext context;
18+
19+
/**
20+
* In case the parameter is used differently in different endpoints, specify for which endpoints this
21+
* derivation applies. If left null, it will apply to all endpoints where this param is present.
22+
*/
23+
public final Set<String> endpointPaths;
24+
25+
/**
26+
* Positive integer specifying in which order the updates are done, starting from lowest value, incrementally.
27+
* If all updates are independent (or there is only 1), this value can be left to 0.
28+
* However, if the derivation of A depends on first deriving B, then A should get an higher order than B,
29+
* eg 1 vs 0.
30+
* In this case, first B is computed based on current state, and then, A is computed with current state
31+
* updated with derived B.
32+
*/
33+
public final Integer order;
34+
35+
public RestDerivedParam(
36+
String paramName,
37+
DerivedParamContext context,
38+
Set<String> endpointPaths,
39+
Integer order
40+
) {
41+
this.paramName = Objects.requireNonNull(paramName);
42+
this.context = Objects.requireNonNull(context);
43+
this.endpointPaths = endpointPaths;
44+
this.order = order;
45+
46+
if(this.order < 0){
47+
throw new IllegalArgumentException("order must be positive: " + order);
48+
}
49+
}
50+
}

core-it/src/test/kotlin/org/evomaster/core/problem/rest/SamplerVerifierTest.kt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ import com.netflix.governator.guice.LifecycleInjector
88
import org.evomaster.client.java.controller.api.dto.*
99
import org.evomaster.client.java.controller.api.dto.database.operations.*
1010
import org.evomaster.client.java.controller.api.dto.problem.RestProblemDto
11+
import org.evomaster.client.java.controller.api.dto.problem.param.DeriveParamResponseDto
12+
import org.evomaster.client.java.controller.api.dto.problem.param.DerivedParamChangeReqDto
1113
import org.evomaster.client.java.controller.api.dto.problem.rpc.ScheduleTaskInvocationsDto
1214
import org.evomaster.client.java.controller.api.dto.problem.rpc.ScheduleTaskInvocationsResult
1315
import org.evomaster.core.BaseModule
@@ -454,6 +456,10 @@ class SamplerVerifierTest {
454456
override fun close() {
455457
}
456458

459+
override fun deriveParams(deriveParams: List<DerivedParamChangeReqDto>): List<DeriveParamResponseDto> {
460+
return listOf()
461+
}
462+
457463
override fun invokeScheduleTasksAndGetResults(dtos: ScheduleTaskInvocationsDto): ScheduleTaskInvocationsResult? {
458464
return null
459465
}

core/src/main/kotlin/org/evomaster/core/EMConfig.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2004,7 +2004,7 @@ class EMConfig {
20042004
@Max(stringLengthHardLimit.toDouble())
20052005
@Cfg("The maximum length allowed for evolved strings. Without this limit, strings could in theory be" +
20062006
" billions of characters long")
2007-
var maxLengthForStrings = 200
2007+
var maxLengthForStrings = 1024
20082008

20092009

20102010
@Min(0.0)
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package org.evomaster.core.problem.enterprise.param
2+
3+
class DerivedParamChangeReq(
4+
5+
val paramName: String,
6+
7+
val jsonData: String,
8+
9+
val entryPoint: String,
10+
11+
val actionIndex: Int
12+
)
13+

0 commit comments

Comments
 (0)