Skip to content

Commit 36ec34c

Browse files
committed
refactoring minimizer
1 parent 3c72e47 commit 36ec34c

3 files changed

Lines changed: 82 additions & 47 deletions

File tree

core/src/main/kotlin/org/evomaster/core/search/service/Minimizer.kt

Lines changed: 17 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,9 @@ import org.evomaster.core.problem.rest.data.RestIndividual
1111
import org.evomaster.core.search.EvaluatedIndividual
1212
import org.evomaster.core.search.GroupsOfChildren
1313
import org.evomaster.core.search.Individual
14+
import org.evomaster.core.search.service.time.ExecutionPhaseController
1415
import org.evomaster.core.search.service.time.SearchStatusUpdater
16+
import org.evomaster.core.search.service.time.TimeBoxedPhase
1517
import org.evomaster.core.sql.SqlAction
1618
import org.slf4j.Logger
1719
import org.slf4j.LoggerFactory
@@ -21,7 +23,7 @@ import org.slf4j.LoggerFactory
2123
*
2224
* WARN: currently minimization loses all history info from EvaluatedIndividual, eg impact of genes
2325
*/
24-
class Minimizer<T: Individual> {
26+
class Minimizer<T: Individual> : TimeBoxedPhase {
2527

2628
companion object{
2729
private val log : Logger = LoggerFactory.getLogger(Minimizer::class.java)
@@ -38,45 +40,31 @@ class Minimizer<T: Individual> {
3840

3941
@Inject
4042
private lateinit var idMapper: IdMapper
41-
4243

43-
private var startTimer : Long = -1
44+
@Inject
45+
private lateinit var epc: ExecutionPhaseController
4446

4547

46-
fun doStartTheTimer(){
47-
startTimer = System.currentTimeMillis()
48-
}
48+
override fun applyPhase() {
49+
minimizeMainActionsPerCoveredTargetInArchive()
50+
pruneNonNeededDatabaseActions()
51+
simplifyActions()
4952

50-
fun passedTimeInSecond() : Int {
51-
if(startTimer < 0){
52-
throw IllegalStateException("Timer was not started")
53-
}
54-
return ((System.currentTimeMillis() - startTimer) / 1000).toInt()
53+
//TODO there could be more to do here
5554
}
5655

57-
private fun checkHasTimedout() : Boolean{
58-
if(startTimer < 0){
59-
throw IllegalStateException("Timer was not started")
60-
}
61-
if(config.minimizeTimeout < 0){
62-
return false
63-
}
64-
if(config.minimizeTimeout == 0){
65-
return true
66-
}
67-
val current = System.currentTimeMillis()
68-
val passed = (current - startTimer) / (1000 * 60.0)
69-
return passed > config.minimizeTimeout
56+
override fun hasPhaseTimedOut() : Boolean{
57+
return epc.hasPhaseTimedOut(ExecutionPhaseController.Phase.MINIMIZATION)
7058
}
7159

72-
fun pruneNonNeededDatabaseActions(){
60+
private fun pruneNonNeededDatabaseActions(){
7361
//TODO
7462
}
7563

7664
/**
7765
* eg, removed un-needed optional parameters
7866
*/
79-
fun simplifyActions(){
67+
private fun simplifyActions(){
8068
//TODO
8169
}
8270

@@ -88,9 +76,9 @@ class Minimizer<T: Individual> {
8876
*
8977
* "EvoSuite: On The Challenges of Test Case Generation in the Real World"
9078
*/
91-
fun minimizeMainActionsPerCoveredTargetInArchive() {
79+
private fun minimizeMainActionsPerCoveredTargetInArchive() {
9280

93-
if(checkHasTimedout()){
81+
if(hasPhaseTimedOut()){
9482
LoggingUtil.getInfoLogger().warn("Minimization phase has timed-out. You can use --minimizeTimeout to increase it.")
9583
return
9684
}
@@ -121,7 +109,7 @@ class Minimizer<T: Individual> {
121109

122110
current.forEach{
123111

124-
if(checkHasTimedout()){
112+
if(hasPhaseTimedOut()){
125113
LoggingUtil.getInfoLogger().warn("Minimization phase has timed-out. You can use --minimizeTimeout to increase it.")
126114
return
127115
}

core/src/main/kotlin/org/evomaster/core/search/service/SearchAlgorithm.kt

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -105,13 +105,7 @@ abstract class SearchAlgorithm<T> where T : Individual {
105105

106106
if(config.minimize){
107107
epc.markStartingMinimization()
108-
109-
minimizer.doStartTheTimer()
110-
minimizer.minimizeMainActionsPerCoveredTargetInArchive()
111-
minimizer.pruneNonNeededDatabaseActions()
112-
minimizer.simplifyActions()
113-
val seconds = minimizer.passedTimeInSecond()
114-
LoggingUtil.getInfoLogger().info("Minimization phase took $seconds seconds")
108+
minimizer.applyPhase()
115109
}
116110

117111
if(config.addPreDefinedTests) {

core/src/main/kotlin/org/evomaster/core/search/service/time/ExecutionPhaseController.kt

Lines changed: 64 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -8,18 +8,23 @@ import javax.inject.Inject
88
/**
99
* Service used to keep track of which phase of the fuzzing we are currently in,
1010
* and how long we have spent in them.
11+
*
12+
* The actual starting/stopping of these phases is done elsewhere (as it depends
13+
* on the problem type)
1114
*/
1215
class ExecutionPhaseController {
1316

14-
enum class Phase{
15-
NOT_STARTED,
16-
SEARCH,
17-
MINIMIZATION,
18-
SECURITY,
19-
ADDITIONAL_ORACLES,
20-
FLAKINESS,
21-
WRITE_OUTPUT,
22-
FINISHED
17+
enum class Phase(
18+
val timeBoxed: Boolean
19+
){
20+
NOT_STARTED(false),
21+
SEARCH(false),
22+
MINIMIZATION(true),
23+
SECURITY(true),
24+
ADDITIONAL_ORACLES(true),
25+
FLAKINESS(true),
26+
WRITE_OUTPUT(false),
27+
FINISHED(false)
2328
}
2429

2530
@Inject
@@ -31,10 +36,41 @@ class ExecutionPhaseController {
3136

3237
private val durationInSeconds : MutableMap<Phase, Long> = mutableMapOf()
3338

39+
private val hasTimedOut : MutableSet<Phase> = mutableSetOf()
40+
3441
fun getCurrentPhase() : Phase{
3542
return phase
3643
}
3744

45+
fun hasPhaseTimedOut(target: Phase) : Boolean {
46+
47+
if(!target.timeBoxed){
48+
throw IllegalArgumentException("Cannot query timeout for a non time-boxed phase: $target")
49+
}
50+
51+
if(target != phase){
52+
return hasTimedOut.contains(target)
53+
}
54+
55+
when(target){
56+
Phase.MINIMIZATION -> {
57+
if(config.minimizeTimeout < 0){
58+
return false
59+
}
60+
if(config.minimizeTimeout == 0){
61+
return true
62+
}
63+
//dealing with minutes
64+
val passed = elapsedSeconds() / 60.0
65+
return passed >= config.minimizeTimeout
66+
}
67+
else -> {
68+
//TODO other cases
69+
return false
70+
}
71+
}
72+
}
73+
3874
fun getPhaseDurationInSeconds(target: Phase) : Long {
3975
return durationInSeconds.getOrDefault(target, -1L)
4076
}
@@ -91,12 +127,27 @@ class ExecutionPhaseController {
91127
return phase != Phase.NOT_STARTED && phase != Phase.FINISHED
92128
}
93129

130+
private fun elapsedSeconds() : Long {
131+
132+
if(phase == Phase.NOT_STARTED){
133+
throw IllegalStateException("Fuzzing session has not started yet")
134+
}
135+
136+
val elapsed = System.currentTimeMillis() - lastPhaseStartMs
137+
val seconds = elapsed / 1000
138+
139+
return seconds
140+
}
141+
94142
private fun startPhase(newPhase: Phase){
95143

144+
if(newPhase == Phase.NOT_STARTED){
145+
throw IllegalStateException("Cannot start a 'not-started' phase")
146+
}
147+
96148
if(phase != Phase.NOT_STARTED){
97149
//starting a new phase will end the current one
98-
val elapsed = System.currentTimeMillis() - lastPhaseStartMs
99-
val seconds = elapsed / 1000
150+
val seconds = elapsedSeconds()
100151
durationInSeconds[phase] = seconds
101152

102153
if(!config.avoidNonDeterministicLogs) {
@@ -105,6 +156,8 @@ class ExecutionPhaseController {
105156
}
106157
}
107158

159+
LoggingUtil.getInfoLogger().info("Starting phase $newPhase")
160+
108161
phase = newPhase
109162
lastPhaseStartMs = System.currentTimeMillis()
110163
}

0 commit comments

Comments
 (0)