Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
57 commits
Select commit Hold shift + click to select a range
34c6e31
add option for enabling flakiness detection
man-zhang Jan 13, 2026
1a2365b
add option for enabling flakiness detection
man-zhang Jan 13, 2026
c82b7b6
add FlakinessDetector Singleton
man-zhang Jan 13, 2026
16bb348
identify flakiness for Http actions
man-zhang Jan 13, 2026
e44d7da
add unit test for set flakiness
man-zhang Jan 13, 2026
9a94fb7
fix a bug
man-zhang Jan 13, 2026
7f074fd
support comment out flaky assertions for Junit
man-zhang Jan 13, 2026
968248e
add test
man-zhang Jan 13, 2026
15cf9e7
update test
man-zhang Jan 13, 2026
4ee3399
add doc
man-zhang Jan 13, 2026
2b393bd
add extra test for list
man-zhang Jan 13, 2026
06a9508
minor
man-zhang Jan 13, 2026
85e5cb3
handle for response in plain text
man-zhang Jan 13, 2026
059bd87
add e2e test
man-zhang Jan 13, 2026
604f5f1
fix the test
man-zhang Jan 13, 2026
00b5e27
fix a bug
man-zhang Jan 14, 2026
23af2a9
rename detectFlakiness to handleFlakiness
man-zhang Jan 20, 2026
b8a9348
fix a bug
man-zhang Jan 20, 2026
4139bd0
fix a bug with line sep
man-zhang Jan 20, 2026
f278e92
change gson to jackson
man-zhang Jan 22, 2026
6231480
add doc
man-zhang Jan 22, 2026
6437385
Merge branch 'flaky-detect' of https://github.com/WebFuzzing/EvoMaste…
man-zhang Jan 22, 2026
cee07da
minor update
man-zhang Jan 22, 2026
b77801d
fix the test and modify the assertions
man-zhang Jan 26, 2026
b3093e4
Merge branch 'master' into flaky-detect
man-zhang Jan 26, 2026
334a2df
add running example
man-zhang Jan 29, 2026
6101dba
add flakyPhase
man-zhang Jan 29, 2026
ab1b531
add derive
man-zhang Jan 29, 2026
b4bf238
put back setFlakiness in HttpWsCallResult.kt
man-zhang Jan 29, 2026
4fa39b9
Merge branch 'master' into flaky-detect
man-zhang Feb 5, 2026
79ccad7
resolve conflicts in options.md
man-zhang Feb 5, 2026
09b71c2
clarify
man-zhang Feb 5, 2026
637bba7
handle status
man-zhang Feb 5, 2026
c3ed0eb
support flakiness assertion for python
man-zhang Feb 5, 2026
cb4ac9f
fix the bugs in module
man-zhang Feb 5, 2026
0b5fd2e
support python output
man-zhang Feb 5, 2026
1e62529
add unint test
man-zhang Feb 5, 2026
585e9d0
use setOption
man-zhang Feb 5, 2026
2e160a1
add bb e2e test
man-zhang Feb 5, 2026
d48a7b5
support JS
man-zhang Feb 5, 2026
a53fd11
update config
man-zhang Feb 5, 2026
4d9fa6f
add bb e2e tests
man-zhang Feb 5, 2026
892314b
Merge branch 'master' into flaky-detect
man-zhang Feb 5, 2026
569fe7e
add unit test and more doc for flakinessInferenceUtil
man-zhang Feb 5, 2026
c0bc11e
Merge branch 'flaky-detect' of https://github.com/WebFuzzing/EvoMaste…
man-zhang Feb 5, 2026
047c2cd
fix a bug
man-zhang Feb 6, 2026
5f24b0e
increase the change to be flaky in example
man-zhang Feb 6, 2026
1a6674c
change the seed
man-zhang Feb 6, 2026
02f35b9
fix tests
man-zhang Feb 10, 2026
14aae4e
add new util method
man-zhang Feb 10, 2026
b6fd977
clean code
man-zhang Feb 10, 2026
d078dbf
update EMConfig
man-zhang Feb 10, 2026
6181716
use ExecutionPhaseController
man-zhang Feb 10, 2026
f239f3b
remove TODO
man-zhang Feb 11, 2026
4193835
fix the test
man-zhang Feb 11, 2026
4717043
Merge branch 'master' into flaky-detect
man-zhang Feb 11, 2026
3ca8611
resolve the conflicts
man-zhang Feb 11, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -610,6 +610,26 @@ protected void assertTextInTests(String outputFolder, String className, Predicat

}

/**
* assert min count of a certain text in the generated tests
* @param outputFolder the folder where the test is
* @param className the complete test name
* @param condition is the content to check
* @param minCount is the minimal count of the certain text existing in the generated tests
*/
protected void assertCountTextInTests(String outputFolder, String className, Predicate<String> condition, int minCount) {
String path = outputFolderPath(outputFolder)+ "/"+String.join("/", className.split("\\."))+".kt";
Path test = Paths.get(path);
try {
boolean ok = Files.lines(test).filter(condition).count() >= minCount;
String msg = "Cannot find "+minCount+" lines with requested condition in "+className+" in "+outputFolder;
assertTrue(ok, msg);
}catch (IOException e){
throw new IllegalStateException("Fail to get the test "+className+" in "+outputFolder+" with error "+ e.getMessage());
}

}

/**
* This function is used to retrieve the item with the identifier "key" in the Solution "sol"
* from Statistics. Returns the value of the element if the element exists, otherwise returns null.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.foo.rest.examples.bb.flakinessdetect

import org.springframework.boot.SpringApplication
import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration

@SpringBootApplication(exclude = [SecurityAutoConfiguration::class])
open class FlakinessDetectApplication {
companion object {
@JvmStatic
fun main(args: Array<String>) {
SpringApplication.run(FlakinessDetectApplication::class.java, *args)
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
package com.foo.rest.examples.bb.flakinessdetect

import org.evomaster.e2etests.utils.CoveredTargets
import org.h2.util.MathUtils.randomInt
import org.springframework.http.ResponseEntity
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.PathVariable
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RequestParam
import org.springframework.web.bind.annotation.RestController
import java.time.LocalDateTime
import java.time.format.DateTimeFormatter
import kotlin.math.max
import kotlin.math.min

@RestController
@RequestMapping(path = ["/api/flakinessdetect"])
class FlakinessDetectRest {

companion object{
val formatter = DateTimeFormatter.ofPattern("HH:mm:ss.SSS yyyy-MM-dd EEEE 'Week' ww")
}

@GetMapping(path = ["/stringfirst/{n}"])
open fun getFirst( @PathVariable("n") n: Int) : ResponseEntity<String> {
CoveredTargets.cover("First")
return ResponseEntity.ok(getPartialDate(n))
}

@GetMapping(path = ["/next/{n}"])
open fun getNext( @PathVariable("n") n: Int) : ResponseEntity<FlakinessDetectData> {
CoveredTargets.cover("Next")
return ResponseEntity.ok(FlakinessDetectData(getPartialDate(n), randomInt(n)))
}

@GetMapping(path = ["/multiplelines/{num}"])
open fun getMultipleLines( @PathVariable("num") num: Int) : ResponseEntity<FlakinessDetectData> {

val num = min(20, max(2, randomInt(num)))

val msg = (1..num).joinToString(System.lineSeparator()) { "LINE $it" }
CoveredTargets.cover("MultipleLines")
return ResponseEntity.ok(FlakinessDetectData(msg, num))
}

@GetMapping("/price/estimate")
fun estimatePrice(@RequestParam base: Int): Map<String, Int> {
val randomJitter = randomInt(1000)

val total = base + randomJitter

CoveredTargets.cover("estimate")
return mapOf(
"base" to base,
"jitter" to randomJitter,
"total" to total
)
}

@GetMapping("/calculate/timeago")
fun getTimeAgo(
@RequestParam(defaultValue = "0") day: Long,
@RequestParam(defaultValue = "0") hour: Long,
@RequestParam(defaultValue = "0") min: Long,
@RequestParam(defaultValue = "0") sec: Long
): ResponseEntity<TimeAgoData> {

CoveredTargets.cover("TimeAgo")
val msg = listOf(day to "day", hour to "hour", min to "minute", sec to "second")
.filter { it.first > 0 }
.joinToString(", ") { (v, u) -> "$v $u${if (v > 1) "s" else ""}" }.takeIf { it.isNotEmpty() }
?.let { "$it ago" }
?: "just now"

val pastDate = LocalDateTime.now()
.minusDays(day).minusHours(hour).minusMinutes(min).minusSeconds(sec)

return ResponseEntity.ok(TimeAgoData(msg, pastDate.toString()))
}

private fun getPartialDate(n: Int) : String {
val now = LocalDateTime.now().format(formatter)
val size = max(12, min(now.toString().length, n))

return now.substring(0, size)
}
}

data class FlakinessDetectData(
val first : String, val next : Int)

data class TimeAgoData(
val message: String,
val calculatedPastTime: String
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.foo.rest.examples.bb.flakinessdetect

import com.foo.rest.examples.bb.SpringController



class FlakinessDetectController : SpringController(FlakinessDetectApplication::class.java)
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package org.evomaster.e2etests.spring.rest.bb.flakinessdetect


import com.foo.rest.examples.bb.flakinessdetect.FlakinessDetectController
import org.evomaster.core.output.OutputFormat
import org.evomaster.e2etests.spring.rest.bb.SpringTestBase
import org.junit.jupiter.api.Assertions.assertTrue
import org.junit.jupiter.api.BeforeAll
import org.junit.jupiter.params.ParameterizedTest
import org.junit.jupiter.params.provider.EnumSource

class FlakinessDetectBBEMTest : SpringTestBase() {

companion object {
init {
shouldApplyInstrumentation = false
}

@BeforeAll
@JvmStatic
fun init() {
initClass(FlakinessDetectController())
}
}


@ParameterizedTest
@EnumSource
fun testBlackBoxOutput(outputFormat: OutputFormat) {
executeAndEvaluateBBTest(
outputFormat,
"flakinessdetect",
100,
3,
listOf("TimeAgo", "estimate","MultipleLines","Next","First")
){ args: MutableList<String> ->

setOption(args, "handleFlakiness", "true")

val solution = initAndRun(args)

assertTrue(solution.individuals.isNotEmpty())

}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.foo.rest.examples.spring.openapi.v3.flakinessdetect
Comment thread
arcuri82 marked this conversation as resolved.

import org.springframework.boot.SpringApplication
import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration

@SpringBootApplication(exclude = [SecurityAutoConfiguration::class])
open class FlakinessDetectApplication {
companion object {
@JvmStatic
fun main(args: Array<String>) {
SpringApplication.run(FlakinessDetectApplication::class.java, *args)
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
package com.foo.rest.examples.spring.openapi.v3.flakinessdetect

import org.h2.util.MathUtils.randomInt
import org.springframework.http.ResponseEntity
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.PathVariable
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RequestParam
import org.springframework.web.bind.annotation.RestController
import java.time.LocalDateTime
import java.time.format.DateTimeFormatter
import kotlin.math.max
import kotlin.math.min

@RestController
@RequestMapping(path = ["/api/flakinessdetect"])
class FlakinessDetectRest {

companion object{
val formatter = DateTimeFormatter.ofPattern("HH:mm:ss.SSS yyyy-MM-dd EEEE 'Week' ww")
}

@GetMapping(path = ["/stringfirst/{n}"])
open fun getFirst( @PathVariable("n") n: Int) : ResponseEntity<String> {

return ResponseEntity.ok(getPartialDate(n))
}

@GetMapping(path = ["/next/{n}"])
open fun getNext( @PathVariable("n") n: Int) : ResponseEntity<FlakinessDetectData> {

return ResponseEntity.ok(FlakinessDetectData(getPartialDate(n), randomInt(n)))
}

@GetMapping(path = ["/multiplelines/{num}"])
open fun getMultipleLines( @PathVariable("num") num: Int) : ResponseEntity<FlakinessDetectData> {

val num = min(20, max(2, randomInt(num)))

val msg = (1..num).joinToString(System.lineSeparator()) { "LINE $it" }
return ResponseEntity.ok(FlakinessDetectData(msg, num))
}

@GetMapping("/price/estimate")
fun estimatePrice(@RequestParam base: Int): Map<String, Int> {
val randomJitter = randomInt(1000)

val total = base + randomJitter

return mapOf(
"base" to base,
"jitter" to randomJitter,
"total" to total
)
}

@GetMapping("/calculate/timeago")
fun getTimeAgo(
@RequestParam(defaultValue = "0") day: Long,
@RequestParam(defaultValue = "0") hour: Long,
@RequestParam(defaultValue = "0") min: Long,
@RequestParam(defaultValue = "0") sec: Long
): ResponseEntity<TimeAgoData> {

val msg = listOf(day to "day", hour to "hour", min to "minute", sec to "second")
.filter { it.first > 0 }
.joinToString(", ") { (v, u) -> "$v $u${if (v > 1) "s" else ""}" }.takeIf { it.isNotEmpty() }
?.let { "$it ago" }
?: "just now"

val pastDate = LocalDateTime.now()
.minusDays(day).minusHours(hour).minusMinutes(min).minusSeconds(sec)

return ResponseEntity.ok(TimeAgoData(msg, pastDate.toString()))
}

private fun getPartialDate(n: Int) : String {
val now = LocalDateTime.now().format(formatter)
val size = max(12, min(now.toString().length, n))

return now.substring(0, size)
}
}

data class FlakinessDetectData(
val first : String, val next : Int)

data class TimeAgoData(
val message: String,
val calculatedPastTime: String
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package com.foo.rest.examples.spring.openapi.v3.flakinessdetect

import com.foo.rest.examples.spring.openapi.v3.SpringController

class FlakinessDetectController : SpringController(FlakinessDetectApplication::class.java)
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package org.evomaster.e2etests.spring.openapi.v3.flakinessdetect

import com.foo.rest.examples.spring.openapi.v3.flakinessdetect.FlakinessDetectController
import org.evomaster.e2etests.spring.openapi.v3.SpringTestBase
import org.junit.jupiter.api.Assertions.assertTrue
import org.junit.jupiter.api.BeforeAll
import org.junit.jupiter.api.Test
import java.util.function.Predicate

class FlakinessDetectBlackboxEMTest : SpringTestBase() {

companion object {
@BeforeAll
@JvmStatic
fun init() {
initClass(FlakinessDetectController())
}
}


@Test
fun testRunEM() {
defaultSeed = 123

val outputFolder = "FlakinessDetectBlackboxEM"
val outputClass = "org.foo.FlakinessDetectBlackboxEM"
val flakyMark = "Flaky"

runTestHandlingFlakyAndCompilation(
outputFolder,
outputClass,
100
) { args: MutableList<String> ->



setOption(args, "handleFlakiness", "true")

// we may still need to specify info in non bb-e2etest
setOption(args, "blackBox", "true")
setOption(args, "bbTargetUrl", baseUrlOfSut)
setOption(args, "bbSwaggerUrl", "$baseUrlOfSut/v3/api-docs")


val solution = initAndRun(args)

assertTrue(solution.individuals.isNotEmpty())
assertTextInTests(outputFolder,outputClass,flakyMark)
assertCountTextInTests(outputFolder,outputClass,
Predicate { it: String? -> it != null && it.contains(flakyMark) }, 3)

}
}
}
Loading