Skip to content

Commit 3fca06a

Browse files
committed
Merge branch 'master' into vulnerability-analyser
2 parents 1394ace + d0edaa2 commit 3fca06a

13 files changed

Lines changed: 119 additions & 23 deletions

File tree

client-java/test-utils-java/src/main/java/org/evomaster/test/utils/EMTestUtils.java

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,15 +42,27 @@ public static String resolveLocation(String locationHeader, String expectedTempl
4242
} catch (Exception e){
4343
return locationHeader;
4444
}
45+
46+
/*
47+
Default behavior of split() is "peculiar", to say the least...
48+
/a
49+
would be "/" split into ["",a]
50+
the same as
51+
/a/
52+
!!!!!!!!
53+
to get trailing "", need to put a negative limit...
54+
*/
55+
int wtfJava = -1;
56+
4557
String locationPath = locationURI.getPath();
46-
String[] locationTokens = locationPath.split("/");
58+
String[] locationTokens = locationPath.split("/",wtfJava);
4759

4860

4961
//the template is not a valid URL, due to {}
5062
String normalizedTemplate = expectedTemplate.replace("{","").replace("}","");
5163
URI templateURI = URI.create(normalizedTemplate);
5264
String templatePath = templateURI.getPath();
53-
String[] templateTokens = templatePath.split("/");
65+
String[] templateTokens = templatePath.split("/",wtfJava);
5466

5567

5668
String targetPath = locationPath;

client-java/test-utils-java/src/test/java/org/evomaster/test/utils/EMTestUtilsTest.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,17 @@
88

99
public class EMTestUtilsTest {
1010

11+
@Test
12+
public void testEmptyPath(){
13+
14+
String template = "http://localhost:12345/a/42";
15+
String location = "/a/";
16+
17+
String res = EMTestUtils.resolveLocation(location, template);
18+
assertEquals("http://localhost:12345/a/", res);
19+
}
20+
21+
1122
@Test
1223
public void testResolveLocation_direct() {
1324

core-it/src/main/kotlin/bar/examples/it/spring/cleanupcreate/CleanUpDeleteApplication.kt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ open class CleanUpDeleteApplication {
1818
SpringApplication.run(CleanUpDeleteApplication::class.java, *args)
1919
}
2020

21-
private val data = mutableMapOf<Int, String>()
21+
private val data = mutableMapOf<String, String>()
2222

2323
fun reset(){
2424
data.clear()
@@ -30,15 +30,15 @@ open class CleanUpDeleteApplication {
3030

3131
@PutMapping(path = ["/{id}"])
3232
open fun put(
33-
@PathVariable("id") id: Int
33+
@PathVariable("id") id: String
3434
): ResponseEntity<Any> {
3535

3636
data[id] = "Data for $id"
3737
return ResponseEntity.status(200).build()
3838
}
3939

4040
@DeleteMapping(path = ["/{id}"])
41-
open fun delete(@PathVariable("id") id: Int): ResponseEntity<String> {
41+
open fun delete(@PathVariable("id") id: String): ResponseEntity<String> {
4242

4343
if(!data.containsKey(id)){
4444
return ResponseEntity.status(404).build()

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

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import org.evomaster.core.problem.rest.data.RestCallResult
1212
import org.junit.jupiter.api.Assertions.*
1313
import org.junit.jupiter.api.BeforeAll
1414
import org.junit.jupiter.api.BeforeEach
15+
import org.junit.jupiter.api.Disabled
1516
import org.junit.jupiter.api.Test
1617

1718
class CleanUpDeleteTest: IntegrationTestRestBase() {
@@ -53,4 +54,33 @@ class CleanUpDeleteTest: IntegrationTestRestBase() {
5354
assertEquals(0, CleanUpDeleteApplication.numberExistingData())
5455

5556
}
57+
58+
@Disabled("Tricky. In the end, we made not possible to send empty path elements. " +
59+
"See discussion in action builder.")
60+
@Test
61+
fun testEmpty(){
62+
63+
assertEquals(0, CleanUpDeleteApplication.numberExistingData())
64+
65+
val pirTest = getPirToRest()
66+
67+
val fail = pirTest.fromVerbPath("put", "/api/resources")
68+
assertNull(fail)
69+
70+
val put = pirTest.fromVerbPath("put", "/api/resources/")!!
71+
val delete = pirTest.fromVerbPath("delete", "/api/resources/")!! //explicit delete
72+
val x = createIndividual(listOf(put,delete), SampleType.RANDOM)
73+
val resPut = x.evaluatedMainActions()[0].result as RestCallResult
74+
val resDel = x.evaluatedMainActions()[1].result as RestCallResult
75+
assertEquals(200, resPut.getStatusCode())
76+
assertEquals(204, resDel.getStatusCode())
77+
78+
assertEquals(0, CleanUpDeleteApplication.numberExistingData())
79+
80+
val y = createIndividual(listOf(put), SampleType.RANDOM)
81+
val resPutY = y.evaluatedMainActions()[0].result as RestCallResult
82+
assertEquals(200, resPutY.getStatusCode())
83+
84+
assertEquals(0, CleanUpDeleteApplication.numberExistingData())
85+
}
5686
}

core/src/main/kotlin/org/evomaster/core/output/service/RestTestCaseWriter.kt

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -455,12 +455,13 @@ class RestTestCaseWriter : HttpWsTestCaseWriter {
455455
"\"${call.path.resolveOnlyPath(call.parameters)}\""
456456
}
457457

458-
//TODO JS
459458
//TODO code here should use same algorithm as in res.getResourceId()
460459
//TODO this is quite limited, would need proper refactoring
461460
val extract = when {
462461
format.isPython() -> "str($resVarName.json()['${res.getResourceIdName()}'])"
463-
else -> "$resVarName.extract().body().path$extraTypeInfo(\"${res.getResourceIdName()}\").toString()"
462+
format.isJavaScript() -> "$resVarName.body.${res.getResourceIdName()}"
463+
format.isJavaOrKotlin() -> "$resVarName.extract().body().path$extraTypeInfo(\"${res.getResourceIdName()}\").toString()"
464+
else -> throw IllegalStateException("Unhandled format: $format")
464465
}
465466

466467
lines.add("${locationVar(call.creationLocationId())} = $baseUri + \"/\" + $extract")

core/src/main/kotlin/org/evomaster/core/output/service/TestCaseWriter.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,7 @@ abstract class TestCaseWriter {
129129
// handleFieldDeclarations.
130130
handleTestInitialization(lines, baseUrlOfSut, ind, insertionVars, test.name)
131131
handleActionCalls(lines, baseUrlOfSut, ind, insertionVars, testCaseName = test.name, testSuitePath)
132+
handleCleanUpActions(lines, baseUrlOfSut, ind, insertionVars, test.name,testSuitePath)
132133
}
133134

134135

core/src/main/kotlin/org/evomaster/core/problem/rest/builder/RestActionBuilderV3.kt

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1640,7 +1640,7 @@ object RestActionBuilderV3 {
16401640
}
16411641

16421642
/**
1643-
* Buils a StringGene that represents a char value.
1643+
* Build a StringGene that represents a char value.
16441644
* Char values are modelled as string of fixed size 1.
16451645
*/
16461646
private fun buildStringGeneForChar(
@@ -1663,7 +1663,14 @@ object RestActionBuilderV3 {
16631663
isInPath: Boolean
16641664
): StringGene {
16651665

1666+
/*
1667+
This is bit tricky, as would prevent empty inputs, which are not necessarily invalid.
1668+
In OpenAPI, path variables are always require.
1669+
Sending an empty /users/ for a /users/{id} might or might not work, and could lead to a 405...
1670+
maybe we skip it, and treat it for a robustness testing
1671+
*/
16661672
val defaultMin = if(isInPath) 1 else 0
1673+
//val defaultMin = 0
16671674

16681675
return StringGene(
16691676
name,

core/src/main/kotlin/org/evomaster/core/problem/rest/data/RestPath.kt

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -462,7 +462,7 @@ class RestPath(path: String) {
462462
}
463463

464464
fun getElements(): List<Map<String, Boolean>> {
465-
return elements.map { it.tokens.map { t -> Pair(t.name, t.isParameter) }.toMap() }
465+
return elements.map { it.tokens.associate { t -> Pair(t.name, t.isParameter) } }
466466
}
467467

468468
/**
@@ -477,9 +477,7 @@ class RestPath(path: String) {
477477
* /foo/bar/{id}
478478
*/
479479
fun matches(resolvedPath: String): Boolean {
480-
if (resolvedPath.matches(Regex(getRegexToMatch())))
481-
return true
482-
return false
480+
return resolvedPath.matches(Regex(getRegexToMatch()))
483481
}
484482

485483
/**

core/src/main/kotlin/org/evomaster/core/problem/rest/service/fitness/BlackBoxRestFitness.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -129,8 +129,6 @@ class BlackBoxRestFitness : RestFitness() {
129129
}
130130
individual.addCleanUpAction(delete)
131131

132-
//FIXME chainState seems broken as based on static path, so can have only one. Need refactoring
133-
134132
//make sure location is saved in the chain
135133
handleSaveLocation(create.action,create.result as RestCallResult,chainState)
136134
}
@@ -141,6 +139,8 @@ class BlackBoxRestFitness : RestFitness() {
141139

142140
for(delete in cleanup){
143141
handleRestCall(delete as RestCallAction, all, actionResults, chainState, cookies, tokens, fv)
142+
val res = actionResults.first { it.sourceLocalId == delete.getLocalId() } as RestCallResult
143+
assert(StatusGroup.G_2xx.isInGroup(res.getStatusCode())){"Wrong status: ${res.getStatusCode()}"}
144144
}
145145
}
146146

core/src/test/kotlin/org/evomaster/core/problem/rest/RestPathTest.kt

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -302,6 +302,18 @@ internal class RestPathTest{
302302
assertEquals("/x%20+%20y?a=k+%2B+w", uri)
303303
}
304304

305+
@Test
306+
fun testMatchEmptyElement(){
307+
308+
assertFalse(RestPath("/x/").matches("/x"))
309+
assertFalse(RestPath("/x").matches("/x/"))
310+
311+
assertTrue(RestPath("/x").matches("/x"))
312+
assertTrue(RestPath("/x/").matches("/x/"))
313+
314+
assertTrue(RestPath("/x/{id}").matches("/x/"))
315+
}
316+
305317
@Test
306318
fun testMatchResolvedPath(){
307319
val path = RestPath("/x/{y}/z")

0 commit comments

Comments
 (0)