Skip to content

Commit fb1c9e2

Browse files
committed
fixed issue in which wrongly repeating cleanup DELETE on same equivalent PUTs
1 parent b8e7d4b commit fb1c9e2

3 files changed

Lines changed: 142 additions & 10 deletions

File tree

core-tests/integration-tests/core-it/src/test/kotlin/org/evomaster/core/problem/rest/cleanupuuid/CleanUpUUIDTest.kt

Lines changed: 107 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -152,9 +152,111 @@ class CleanUpUUIDTest: IntegrationTestRestBase() {
152152
assertEquals(0, CleanUpUUIDApplication.numberExistingData())
153153
}
154154

155-
//TODO multi distinct POST
156-
//TODO mixed POST PUT
157-
//TODO mixed multi POST PUT repeated
155+
@Test
156+
fun testMultiPostDelete() {
157+
158+
assertEquals(0, CleanUpUUIDApplication.numberExistingData())
159+
160+
val pirTest = getPirToRest()
161+
162+
val post0 = pirTest.fromVerbPath("post", "/api/resources")!!
163+
val post1 = pirTest.fromVerbPath("post", "/api/resources")!!
164+
val post2 = pirTest.fromVerbPath("post", "/api/resources")!!
165+
166+
val x = createIndividual(listOf(post0,post1,post2), SampleType.RANDOM)
167+
val resDel0 = x.evaluatedMainActions()[0].result as RestCallResult
168+
assertEquals(201, resDel0.getStatusCode())
169+
assertEquals(1, getReturnedSize(resDel0))
170+
val resDel1 = x.evaluatedMainActions()[1].result as RestCallResult
171+
assertEquals(201, resDel1.getStatusCode())
172+
assertEquals(2, getReturnedSize(resDel1))
173+
val resDel2 = x.evaluatedMainActions()[2].result as RestCallResult
174+
assertEquals(201, resDel2.getStatusCode())
175+
assertEquals(3, getReturnedSize(resDel2))
176+
177+
178+
assertEquals(3, x.evaluatedMainActions().size)
179+
assertEquals(3, x.individual.seeMainExecutableActions().size)
180+
assertEquals(3, x.individual.seeCleanUpActions().size)
181+
182+
//delete should had been automatically added
183+
assertEquals(0, CleanUpUUIDApplication.numberExistingData())
184+
}
185+
186+
@Test
187+
fun testPostPutDelete() {
188+
189+
assertEquals(0, CleanUpUUIDApplication.numberExistingData())
190+
191+
val pirTest = getPirToRest()
192+
193+
val id = UUID.randomUUID().toString()
194+
val put = pirTest.fromVerbPath("put", "/api/resources/$id")!!
195+
val post = pirTest.fromVerbPath("post", "/api/resources")!!
196+
197+
val x = createIndividual(listOf(put,post), SampleType.RANDOM)
198+
val resDel = x.evaluatedMainActions()[0].result as RestCallResult
199+
assertEquals(201, resDel.getStatusCode())
200+
assertEquals(1, getReturnedSize(resDel))
201+
val resDel1 = x.evaluatedMainActions()[1].result as RestCallResult
202+
assertEquals(201, resDel1.getStatusCode())
203+
assertEquals(2, getReturnedSize(resDel1))
204+
205+
206+
assertEquals(2, x.evaluatedMainActions().size)
207+
assertEquals(2, x.individual.seeMainExecutableActions().size)
208+
assertEquals(2, x.individual.seeCleanUpActions().size)
209+
210+
//delete should had been automatically added
211+
assertEquals(0, CleanUpUUIDApplication.numberExistingData())
212+
}
213+
214+
215+
@Test
216+
fun testMultipleRepeatedPostPutDelete() {
217+
218+
assertEquals(0, CleanUpUUIDApplication.numberExistingData())
219+
220+
val pirTest = getPirToRest()
221+
222+
val id0 = UUID.randomUUID().toString()
223+
val put0 = pirTest.fromVerbPath("put", "/api/resources/$id0")!!
224+
val id1 = UUID.randomUUID().toString()
225+
val put1 = pirTest.fromVerbPath("put", "/api/resources/$id1")!!
226+
//this is using same id as first call, so replace, does not create new resource
227+
val put2 = pirTest.fromVerbPath("put", "/api/resources/$id0")!!
228+
229+
val post0 = pirTest.fromVerbPath("post", "/api/resources")!!
230+
val post1 = pirTest.fromVerbPath("post", "/api/resources")!!
231+
232+
233+
val x = createIndividual(listOf(post0,put0,put1,put2,post1), SampleType.RANDOM)
234+
235+
val resDel0 = x.evaluatedMainActions()[0].result as RestCallResult
236+
assertEquals(201, resDel0.getStatusCode())
237+
assertEquals(1, getReturnedSize(resDel0))
238+
val resDel1 = x.evaluatedMainActions()[1].result as RestCallResult
239+
assertEquals(201, resDel1.getStatusCode())
240+
assertEquals(2, getReturnedSize(resDel1))
241+
val resDel2 = x.evaluatedMainActions()[2].result as RestCallResult
242+
assertEquals(201, resDel2.getStatusCode())
243+
assertEquals(3, getReturnedSize(resDel2))
244+
val resDel3 = x.evaluatedMainActions()[3].result as RestCallResult
245+
assertEquals(200, resDel3.getStatusCode())
246+
assertEquals(3, getReturnedSize(resDel3))
247+
val resDel4 = x.evaluatedMainActions()[4].result as RestCallResult
248+
assertEquals(201, resDel4.getStatusCode())
249+
assertEquals(4, getReturnedSize(resDel4))
250+
251+
252+
assertEquals(5, x.evaluatedMainActions().size)
253+
assertEquals(5, x.individual.seeMainExecutableActions().size)
254+
assertEquals(4, x.individual.seeCleanUpActions().size)
255+
256+
//delete should had been automatically added
257+
assertEquals(0, CleanUpUUIDApplication.numberExistingData())
258+
}
259+
260+
158261
//TODO merge (various combinations)
159-
//TODO mutation remove POST/PUT (should remove delete)
160-
}
262+
}

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

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import org.evomaster.core.search.action.ActionResult
1515
import org.evomaster.core.search.EvaluatedIndividual
1616
import org.evomaster.core.search.FitnessValue
1717
import org.evomaster.core.search.StructuralElement
18+
import org.evomaster.core.utils.CollectionUtils
1819
import org.slf4j.Logger
1920
import org.slf4j.LoggerFactory
2021
import javax.inject.Inject
@@ -98,17 +99,26 @@ class BlackBoxRestFitness : RestFitness() {
9899
individual.removeAllCleanUp()
99100
assert(individual.size() == size) // no side effects on main actions
100101

101-
val toHandle = RestIndividualSelectorUtils.findActionsInIndividual(
102+
val createWithPost = RestIndividualSelectorUtils.findActionsInIndividual(
102103
individual,
103104
actionResults,
104105
verb = HttpVerb.POST,
105106
statusGroup = StatusGroup.G_2xx
106-
).plus(RestIndividualSelectorUtils.findActionsInIndividual(
107+
)
108+
109+
val createWithPut = RestIndividualSelectorUtils.findActionsInIndividual(
107110
individual,
108111
actionResults,
109112
verb = HttpVerb.PUT,
110113
statusGroup = StatusGroup.G_2xx
111-
))
114+
)
115+
116+
val toHandle = createWithPost.plus(
117+
CollectionUtils.deDuplicate(createWithPut){x,y ->
118+
//if more than 1 PUT resolve to same location, just need to handle it once
119+
CreateResourceUtils.doesResolveToSamePath(x.action as RestCallAction, y.action as RestCallAction)
120+
}
121+
)
112122

113123
if(toHandle.isEmpty()){
114124
return
@@ -161,4 +171,4 @@ class BlackBoxRestFitness : RestFitness() {
161171
*/
162172
return null
163173
}
164-
}
174+
}

core/src/main/kotlin/org/evomaster/core/utils/CollectionUtils.kt

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package org.evomaster.core.utils
22

3+
import java.util.function.BiFunction
4+
35
object CollectionUtils {
46

57

@@ -16,4 +18,22 @@ object CollectionUtils {
1618
// return list.associateBy({ it },{ list.count { e -> it == e } })
1719
.filter { it.value > 1 }
1820
}
19-
}
21+
22+
/**
23+
* Return a sublist on the input [list], where only "distinct" elements are returned.
24+
* This is based on the provided [equivalentLambda], which should return whether 2 elements
25+
* are equivalent.
26+
*/
27+
fun <T> deDuplicate(list: List<T>, equivalentLambda: BiFunction<T,T, Boolean>) : List<T>{
28+
29+
val result = mutableListOf<T>()
30+
for(x in list){
31+
if(result.any { equivalentLambda.apply(it, x) }){
32+
continue
33+
}
34+
result.add(x)
35+
}
36+
37+
return result
38+
}
39+
}

0 commit comments

Comments
 (0)