Skip to content

Commit 9a97d53

Browse files
committed
Merge remote-tracking branch 'origin/master' into sql-multi-column-foreign-keys
2 parents aea69bb + 5874c1e commit 9a97d53

21 files changed

Lines changed: 247 additions & 108 deletions

File tree

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import org.evomaster.core.problem.rest.service.sampler.AbstractRestSampler
1212
import org.evomaster.core.problem.rest.service.RestSecurityBuilder
1313
import org.evomaster.core.search.EvaluatedIndividual
1414
import org.evomaster.core.search.service.Archive
15+
import org.evomaster.core.search.service.time.ExecutionPhaseController
1516
import org.evomaster.core.seeding.service.rest.PirToRest
1617
import org.evomaster.e2etests.utils.RestTestBase
1718
import org.junit.jupiter.api.BeforeEach
@@ -60,6 +61,8 @@ abstract class IntegrationTestRestBase : RestTestBase() {
6061

6162
fun getSecurityOracle() = injector.getInstance(RestSecurityOracle::class.java)
6263

64+
fun getExecutionPhaseController() = injector.getInstance(ExecutionPhaseController::class.java)
65+
6366
/**
6467
* Create and evaluate an individual
6568
*/

core-tests/integration-tests/core-it/src/test/kotlin/org/evomaster/core/problem/rest/securityrestoracle/SecurityForbiddenOperationTest.kt

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,12 @@ class SecurityForbiddenOperationTest : IntegrationTestRestBase() {
3737
SecurityForbiddenOperationApplication.reset()
3838
}
3939

40+
private fun makeSureCanRunSecurityPhase(){
41+
val epc = getExecutionPhaseController()
42+
epc.markStartingSearch()
43+
epc.markStartingSecurity()
44+
}
45+
4046
@Test
4147
fun testDeletePatch(){
4248

@@ -107,6 +113,7 @@ class SecurityForbiddenOperationTest : IntegrationTestRestBase() {
107113
val security = getSecurityRest()
108114
val config = getEMConfig()
109115

116+
110117
config.security = true
111118
config.schemaOracles = false
112119

@@ -129,6 +136,7 @@ class SecurityForbiddenOperationTest : IntegrationTestRestBase() {
129136
val added = archive.addIfNeeded(ind)
130137
assertTrue(added)
131138

139+
makeSureCanRunSecurityPhase()
132140
val solution = security.applySecurityPhase()
133141

134142
val target = solution.individuals.find { it.hasAnyPotentialFault() }!!
@@ -186,7 +194,7 @@ class SecurityForbiddenOperationTest : IntegrationTestRestBase() {
186194
val otherAdded = archive.addIfNeeded(other)
187195
assertTrue(otherAdded)
188196

189-
197+
makeSureCanRunSecurityPhase()
190198
val solution = security.applySecurityPhase()
191199

192200
val target = solution.individuals.find { it.hasAnyPotentialFault() }!!
@@ -233,6 +241,7 @@ class SecurityForbiddenOperationTest : IntegrationTestRestBase() {
233241
val added = archive.addIfNeeded(ind)
234242
assertTrue(added)
235243

244+
makeSureCanRunSecurityPhase()
236245
val solution = security.applySecurityPhase()
237246

238247
val target = solution.individuals.find { it.hasAnyPotentialFault() }!!

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

Lines changed: 43 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -253,23 +253,28 @@ class Main {
253253
val idMapper = injector.getInstance(IdMapper::class.java)
254254
val epc = injector.getInstance(ExecutionPhaseController::class.java)
255255

256-
var solution = run(injector, controllerInfo)
256+
run(injector, controllerInfo)
257257

258258
//save data regarding the search phase
259259
writeOverallProcessData(injector)
260260
writeDependencies(injector)
261-
writeImpacts(injector, solution)
261+
writeImpacts(injector)
262262
writeExecuteInfo(injector)
263-
264263
logTimeSearchInfo(injector, config)
265264

265+
266+
//-----------------------------------------------------------
266267
//apply new phases
268+
phaseMinimizer(injector, config, epc)
267269
// 403 are usually not found during search, but created on purpose during security phase by
268270
// mixing different users in the same test. as some http oracles might depend on 403s,
269271
// we make sure to run security phase first
270-
solution = phaseSecurity(injector, config, epc, solution)
271-
solution = phaseHttpOracle(injector, config, epc, solution)
272-
solution = phaseFlaky(injector, config, epc, solution)
272+
phaseSecurity(injector, config, epc)
273+
phaseHttpOracle(injector, config, epc)
274+
phaseFlaky(injector, config, epc)
275+
//-----------------------------------------------------------
276+
277+
val solution = extractSolution(injector)
273278

274279
epc.markStartingWriteOutput()
275280
val suites = writeTests(injector, solution, controllerInfo)
@@ -278,7 +283,6 @@ class Main {
278283
writeCoveredTargets(injector, solution)
279284
//NOTE: the WRITE_OUTPUT phase here would be not computed, as it is not finished yet...
280285
writeStatistics(injector, solution)
281-
//FIXME if other phases after search, might get skewed data on 100% snapshots...
282286

283287
resetExternalServiceHandler(injector)
284288
// Stop the WM before test execution
@@ -412,17 +416,35 @@ class Main {
412416
}
413417
}
414418

419+
private fun extractSolution(injector: Injector): Solution<*> {
420+
val archive = injector.getInstance(Archive::class.java)
421+
return archive.extractSolution()
422+
}
423+
424+
private fun phaseMinimizer(
425+
injector: Injector,
426+
config: EMConfig,
427+
epc: ExecutionPhaseController,
428+
){
429+
if(!config.minimize){
430+
return
431+
}
432+
epc.markStartingMinimization()
433+
434+
val minimizer = injector.getInstance(Key.get(object : TypeLiteral<Minimizer<*>>() {}))
435+
minimizer.applyPhase()
436+
}
437+
415438
private fun phaseFlaky(
416439
injector: Injector,
417440
config: EMConfig,
418441
epc: ExecutionPhaseController,
419-
solution: Solution<*>
420-
): Solution<*> {
442+
) {
421443
if (!config.handleFlakiness){
422-
return solution
444+
return
423445
}
424446

425-
return when (config.problemType) {
447+
when (config.problemType) {
426448
EMConfig.ProblemType.REST -> {
427449
LoggingUtil.getInfoLogger().info("Starting to apply flaky detection")
428450
epc.markStartingFlakiness()
@@ -432,31 +454,25 @@ class Main {
432454
} else -> {
433455
LoggingUtil.getInfoLogger()
434456
.warn("Flakiness detection phase currently not handled for problem type: ${config.problemType}")
435-
solution
436457
}
437458
}
438-
439-
440-
441459
}
442460

443461

444462
private fun phaseSecurity(
445463
injector: Injector,
446464
config: EMConfig,
447465
epc: ExecutionPhaseController,
448-
solution: Solution<*>
449-
): Solution<*> {
466+
) {
450467
if (!config.security) {
451-
return solution
468+
return
452469
}
453470
//apply security testing phase
454-
LoggingUtil.getInfoLogger().info("Starting to apply security testing")
455471
epc.markStartingSecurity()
456472

457473
//TODO might need to reset stc, and print some updated info again
458474

459-
return when (config.problemType) {
475+
when (config.problemType) {
460476
EMConfig.ProblemType.REST -> {
461477
val securityRest = injector.getInstance(RestSecurityBuilder::class.java)
462478
securityRest.applySecurityPhase()
@@ -465,26 +481,22 @@ class Main {
465481
else -> {
466482
LoggingUtil.getInfoLogger()
467483
.warn("Security phase currently not handled for problem type: ${config.problemType}")
468-
solution
469484
}
470485
}
471486
}
472487

473488
private fun phaseHttpOracle(
474489
injector: Injector,
475490
config: EMConfig,
476-
epc: ExecutionPhaseController,
477-
solution: Solution<*>
478-
): Solution<*> {
491+
epc: ExecutionPhaseController
492+
) {
479493

480-
return if (config.httpOracles && config.problemType == EMConfig.ProblemType.REST) {
481-
LoggingUtil.getInfoLogger().info("Starting to apply HTTP")
494+
if (config.httpOracles && config.problemType == EMConfig.ProblemType.REST) {
495+
LoggingUtil.getInfoLogger().info("Starting to apply HTTP oracle detection")
482496
epc.markStartingAdditionalOracles()
483497

484498
val httpSemanticsService = injector.getInstance(HttpSemanticsService::class.java)
485499
httpSemanticsService.applyHttpSemanticsPhase()
486-
} else {
487-
solution
488500
}
489501
}
490502

@@ -1056,14 +1068,16 @@ class Main {
10561068
* save derived impacts of genes of actions.
10571069
* info is designed for experiment analysis
10581070
*/
1059-
private fun writeImpacts(injector: Injector, solution: Solution<*>) {
1071+
private fun writeImpacts(injector: Injector) {
10601072

10611073
val config = injector.getInstance(EMConfig::class.java)
10621074

10631075
if (!config.exportImpacts) {
10641076
return
10651077
}
10661078

1079+
val solution = extractSolution(injector)
1080+
10671081
val am = injector.getInstance(ArchiveImpactSelector::class.java)
10681082
am.exportImpacts(solution)
10691083
}

core/src/main/kotlin/org/evomaster/core/problem/graphql/service/GraphQLBlackBoxModule.kt

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,11 +48,16 @@ class GraphQLBlackBoxModule(
4848
bind(object : TypeLiteral<Archive<*>>() {})
4949
.to(object : TypeLiteral<Archive<GraphQLIndividual>>() {})
5050

51+
bind(Archive::class.java)
52+
.to(object : TypeLiteral<Archive<GraphQLIndividual>>() {})
53+
5154
bind(object : TypeLiteral<Minimizer<GraphQLIndividual>>(){})
5255
.asEagerSingleton()
5356

5457
bind(object : TypeLiteral<Minimizer<*>>(){})
55-
.asEagerSingleton()
58+
.to(object : TypeLiteral<Minimizer<GraphQLIndividual>>() {})
59+
.asEagerSingleton()
60+
5661

5762
bind(object : TypeLiteral<FlakinessDetector<GraphQLIndividual>>(){})
5863
.asEagerSingleton()

core/src/main/kotlin/org/evomaster/core/problem/graphql/service/GraphQLModule.kt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,10 +51,14 @@ class GraphQLModule : EnterpriseModule() {
5151
bind(object : TypeLiteral<Archive<*>>() {})
5252
.to(object : TypeLiteral<Archive<GraphQLIndividual>>() {})
5353

54+
bind(Archive::class.java)
55+
.to(object : TypeLiteral<Archive<GraphQLIndividual>>() {})
56+
5457
bind(object : TypeLiteral<Minimizer<GraphQLIndividual>>(){})
5558
.asEagerSingleton()
5659

5760
bind(object : TypeLiteral<Minimizer<*>>(){})
61+
.to(object : TypeLiteral<Minimizer<GraphQLIndividual>>(){})
5862
.asEagerSingleton()
5963

6064
bind(object : TypeLiteral<FlakinessDetector<GraphQLIndividual>>(){})

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

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,14 +18,16 @@ import org.evomaster.core.search.Solution
1818
import org.evomaster.core.search.service.Archive
1919
import org.evomaster.core.search.service.IdMapper
2020
import org.evomaster.core.search.service.Randomness
21+
import org.evomaster.core.search.service.time.ExecutionPhaseController
22+
import org.evomaster.core.search.service.time.TimeBoxedPhase
2123
import org.slf4j.Logger
2224
import org.slf4j.LoggerFactory
2325
import javax.annotation.PostConstruct
2426

2527
/**
2628
* Service class used to verify HTTP semantics properties.
2729
*/
28-
class HttpSemanticsService {
30+
class HttpSemanticsService : TimeBoxedPhase{
2931

3032
companion object {
3133
private val log: Logger = LoggerFactory.getLogger(HttpSemanticsService::class.java)
@@ -52,6 +54,9 @@ class HttpSemanticsService {
5254
@Inject
5355
private lateinit var builder: RestIndividualBuilder
5456

57+
@Inject
58+
private lateinit var epc: ExecutionPhaseController
59+
5560
/**
5661
* All actions that can be defined from the OpenAPI schema
5762
*/
@@ -72,7 +77,13 @@ class HttpSemanticsService {
7277

7378
}
7479

80+
override fun applyPhase() {
81+
applyHttpSemanticsPhase()
82+
}
7583

84+
override fun hasPhaseTimedOut(): Boolean {
85+
return epc.hasPhaseTimedOut(ExecutionPhaseController.Phase.ADDITIONAL_ORACLES)
86+
}
7687

7788
fun applyHttpSemanticsPhase(): Solution<RestIndividual>{
7889

@@ -92,12 +103,15 @@ class HttpSemanticsService {
92103
// – JSON-Merge-Patch: partial update should not impact other fields. Can have GET, PATCH, and GET to verify it
93104

94105

106+
if(hasPhaseTimedOut()) return
95107
// – 2xx GET on K : follow by success 2xx DELETE, should then give 404 on GET k (adding up to 2 calls)
96108
deleteShouldDelete()
97109

110+
if(hasPhaseTimedOut()) return
98111
// – A repeated followup PUT with 201 on same endpoint should not return 201 (must enforce 200 or 204)
99112
putRepeatedCreated()
100113

114+
if(hasPhaseTimedOut()) return
101115
sideEffectsOfFailedModification()
102116
}
103117

@@ -114,6 +128,8 @@ class HttpSemanticsService {
114128

115129
putOperations.forEach { put ->
116130

131+
if(hasPhaseTimedOut()) return
132+
117133
val creates = RestIndividualSelectorUtils.findAndSlice(
118134
individualsInSolution,
119135
HttpVerb.PUT,
@@ -160,6 +176,8 @@ class HttpSemanticsService {
160176

161177
deleteOperations.forEach { del ->
162178

179+
if(hasPhaseTimedOut()) return
180+
163181
val successDelete = RestIndividualSelectorUtils.findAndSlice(
164182
individualsInSolution,
165183
HttpVerb.DELETE,
@@ -227,6 +245,8 @@ class HttpSemanticsService {
227245

228246
modifyOperations.forEach { modOp ->
229247

248+
if(hasPhaseTimedOut()) return
249+
230250
val getDef = actionDefinitions.find { it.verb == HttpVerb.GET && it.path == modOp.path }
231251
?: return@forEach
232252

0 commit comments

Comments
 (0)