diff --git a/core-it/pom.xml b/core-it/pom.xml
index 14c4fe2da7..7ff4625e64 100644
--- a/core-it/pom.xml
+++ b/core-it/pom.xml
@@ -85,6 +85,29 @@
org.springframework.boot
spring-boot-starter-web
+
+ org.springdoc
+ springdoc-openapi-ui
+
+
+
+
+
+
+ org.springdoc
+ springdoc-openapi-kotlin
+
+
+ io.swagger.core.v3
+ swagger-annotations
+
+
+
+ org.evomaster
+ evomaster-e2e-tests-utils
+ test-jar
+ ${project.version}
+
diff --git a/core-it/src/main/kotlin/bar/examples/it/spring/pathstatus/PathStatusApplication.kt b/core-it/src/main/kotlin/bar/examples/it/spring/pathstatus/PathStatusApplication.kt
new file mode 100644
index 0000000000..cf487e2d73
--- /dev/null
+++ b/core-it/src/main/kotlin/bar/examples/it/spring/pathstatus/PathStatusApplication.kt
@@ -0,0 +1,39 @@
+package bar.examples.it.spring.pathstatus
+
+import org.springframework.boot.SpringApplication
+import org.springframework.boot.autoconfigure.SpringBootApplication
+import org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration
+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.RestController
+
+@SpringBootApplication(exclude = [SecurityAutoConfiguration::class])
+@RequestMapping(path = ["/api/pathstatus"])
+@RestController
+open class PathStatusApplication {
+
+
+ companion object {
+ @JvmStatic
+ fun main(args: Array) {
+ SpringApplication.run(PathStatusApplication::class.java, *args)
+ }
+ }
+
+ @GetMapping("/byStatus/{status}")
+ open fun getByStatus(@PathVariable status: Int) : ResponseEntity {
+
+ return ResponseEntity.status(status).body("byStatus")
+ }
+
+ @GetMapping("/others/{x}")
+ open fun getOthers(@PathVariable x: Int) : ResponseEntity {
+
+ return ResponseEntity.status(200).body("$x")
+ }
+
+
+
+}
\ No newline at end of file
diff --git a/core-it/src/test/kotlin/bar/examples/it/spring/SpringController.kt b/core-it/src/test/kotlin/bar/examples/it/spring/SpringController.kt
new file mode 100644
index 0000000000..4e39710cd6
--- /dev/null
+++ b/core-it/src/test/kotlin/bar/examples/it/spring/SpringController.kt
@@ -0,0 +1,67 @@
+package bar.examples.it.spring
+
+import org.evomaster.client.java.controller.EmbeddedSutController
+import org.evomaster.client.java.controller.api.dto.auth.AuthenticationDto
+import org.evomaster.client.java.controller.api.dto.SutInfoDto
+import org.evomaster.client.java.sql.DbSpecification
+import org.evomaster.client.java.controller.problem.ProblemInfo
+import org.evomaster.client.java.controller.problem.RestProblem
+import org.springframework.boot.SpringApplication
+import org.springframework.context.ConfigurableApplicationContext
+
+
+abstract class SpringController(protected val applicationClass: Class<*>) : EmbeddedSutController() {
+
+ init {
+ super.setControllerPort(0)
+ }
+
+
+ protected var ctx: ConfigurableApplicationContext? = null
+
+ override fun startSut(): String {
+ ctx = SpringApplication.run(applicationClass, "--server.port=0")
+ return "http://localhost:$sutPort"
+ }
+
+ protected val sutPort: Int
+ get() = (ctx!!.environment
+ .propertySources["server.ports"].source as Map<*, *>)["local.server.port"] as Int
+
+ override fun isSutRunning(): Boolean {
+ return ctx != null && ctx!!.isRunning
+ }
+
+ override fun stopSut() {
+ ctx?.stop()
+ ctx?.close()
+ }
+
+ override fun getPackagePrefixesToCover(): String {
+ return "bar.foo."
+ }
+
+ override fun resetStateOfSUT() { //nothing to do
+ }
+
+ override fun getProblemInfo(): ProblemInfo {
+ return RestProblem(
+ "http://localhost:$sutPort/v3/api-docs",
+ null
+ )
+ }
+
+ override fun getInfoForAuthentication(): List {
+ return listOf()
+ }
+
+ override fun getDbSpecifications(): MutableList? {
+ return null
+ }
+
+
+ override fun getPreferredOutputFormat(): SutInfoDto.OutputFormat {
+ return SutInfoDto.OutputFormat.KOTLIN_JUNIT_5
+ }
+
+}
\ No newline at end of file
diff --git a/core-it/src/test/kotlin/bar/examples/it/spring/pathstatus/PathStatusController.kt b/core-it/src/test/kotlin/bar/examples/it/spring/pathstatus/PathStatusController.kt
new file mode 100644
index 0000000000..0ccd1dc97a
--- /dev/null
+++ b/core-it/src/test/kotlin/bar/examples/it/spring/pathstatus/PathStatusController.kt
@@ -0,0 +1,5 @@
+package bar.examples.it.spring.pathstatus
+
+import bar.examples.it.spring.SpringController
+
+class PathStatusController : SpringController(PathStatusApplication::class.java)
\ No newline at end of file
diff --git a/core-it/src/test/kotlin/org/evomaster/core/problem/rest/IntegrationTestRestBase.kt b/core-it/src/test/kotlin/org/evomaster/core/problem/rest/IntegrationTestRestBase.kt
new file mode 100644
index 0000000000..3f1f2feff9
--- /dev/null
+++ b/core-it/src/test/kotlin/org/evomaster/core/problem/rest/IntegrationTestRestBase.kt
@@ -0,0 +1,50 @@
+package org.evomaster.core.problem.rest
+
+import com.google.inject.Injector
+import org.evomaster.core.problem.enterprise.SampleType
+import org.evomaster.core.problem.rest.service.AbstractRestFitness
+import org.evomaster.core.problem.rest.service.AbstractRestSampler
+import org.evomaster.core.search.EvaluatedIndividual
+import org.evomaster.core.search.service.SearchGlobalState
+import org.evomaster.core.seeding.service.rest.PirToRest
+import org.evomaster.e2etests.utils.RestTestBase
+import org.junit.jupiter.api.BeforeEach
+
+abstract class IntegrationTestRestBase : RestTestBase() {
+
+
+ protected lateinit var injector: Injector
+
+ @BeforeEach
+ fun initInjector(){
+ val args = listOf(
+ "--sutControllerPort", "" + controllerPort,
+ "--createConfigPathIfMissing", "false"
+ )
+ injector = init(args)
+ }
+
+ fun getPirToRest() = injector.getInstance(PirToRest::class.java)
+
+
+ fun createIndividual(actions: List): EvaluatedIndividual {
+
+// val searchGlobalState = injector.getInstance(SearchGlobalState::class.java)
+
+// val ind = RestIndividual(actions.toMutableList(), SampleType.SEEDED)
+// ind.doGlobalInitialize(searchGlobalState)
+
+ val sampler = injector.getInstance(AbstractRestSampler::class.java)
+ /*
+ the method `createIndividual` can be overridden
+ in this case, the sampler is an instance of ResourceSampler,
+ then check its implementation in ResourceSampler.createIndividual(...)
+ */
+ val ind = sampler.createIndividual(SampleType.SEEDED, actions.toMutableList())
+
+ val ff = injector.getInstance(AbstractRestFitness::class.java)
+ val ei = ff.calculateCoverage(ind)!!
+
+ return ei
+ }
+}
\ No newline at end of file
diff --git a/core-it/src/test/kotlin/org/evomaster/core/problem/rest/selectorutils/RestIndividualSelectorUtilsPathStatusTest.kt b/core-it/src/test/kotlin/org/evomaster/core/problem/rest/selectorutils/RestIndividualSelectorUtilsPathStatusTest.kt
new file mode 100644
index 0000000000..6c34662a22
--- /dev/null
+++ b/core-it/src/test/kotlin/org/evomaster/core/problem/rest/selectorutils/RestIndividualSelectorUtilsPathStatusTest.kt
@@ -0,0 +1,50 @@
+package org.evomaster.core.problem.rest.selectorutils
+
+import bar.examples.it.spring.pathstatus.PathStatusController
+import org.evomaster.core.problem.rest.HttpVerb
+import org.evomaster.core.problem.rest.IntegrationTestRestBase
+import org.evomaster.core.problem.rest.RestIndividualSelectorUtils
+import org.evomaster.core.problem.rest.RestPath
+import org.junit.jupiter.api.Assertions.assertEquals
+import org.junit.jupiter.api.BeforeAll
+import org.junit.jupiter.api.Test
+
+class RestIndividualSelectorUtilsPathStatusTest : IntegrationTestRestBase(){
+
+ companion object {
+ @BeforeAll
+ @JvmStatic
+ fun init() {
+ initClass(PathStatusController())
+ }
+ }
+
+
+ @Test
+ fun testPathStatus(){
+
+ val pirTest = getPirToRest()
+
+ val byStatus = RestPath("/api/pathstatus/byStatus/{status}")
+ val others = RestPath("/api/pathstatus/others/{x}")
+
+ val s200 = pirTest.fromVerbPath("get", "/api/pathstatus/byStatus/200")!!
+ val s400 = pirTest.fromVerbPath("get", "/api/pathstatus/byStatus/400")!!
+ val o200 = pirTest.fromVerbPath("get", "/api/pathstatus/others/200")!!
+ val o500 = pirTest.fromVerbPath("get", "/api/pathstatus/others/500")!!
+
+ val x0 = createIndividual(listOf(s200))
+ val x1 = createIndividual(listOf(s400))
+ val x2 = createIndividual(listOf(o200))
+ val x3 = createIndividual(listOf(o500))
+
+ val individuals = listOf(x0,x1,x2,x3)
+
+ val r0 = RestIndividualSelectorUtils.findIndividuals(individuals, HttpVerb.GET, byStatus, 200)
+ assertEquals(1, r0.size)
+
+ val r1 = RestIndividualSelectorUtils.findIndividuals(individuals, HttpVerb.GET, byStatus, 500)
+ assertEquals(0, r1.size)
+ }
+
+}
\ No newline at end of file
diff --git a/core/src/main/kotlin/org/evomaster/core/problem/api/param/Param.kt b/core/src/main/kotlin/org/evomaster/core/problem/api/param/Param.kt
index 84e5e48e7a..296837c82e 100644
--- a/core/src/main/kotlin/org/evomaster/core/problem/api/param/Param.kt
+++ b/core/src/main/kotlin/org/evomaster/core/problem/api/param/Param.kt
@@ -9,7 +9,7 @@ abstract class Param(
val genes : MutableList
) : StructuralElement(genes){
- //TODO need refactoring
+ //TODO need refactoring. eg shared abstract class for cases in which only 1 gene for sure
@Deprecated("Assumes there is only 1 gene")
val gene : Gene = genes[0]
diff --git a/core/src/main/kotlin/org/evomaster/core/problem/rest/RestIndividual.kt b/core/src/main/kotlin/org/evomaster/core/problem/rest/RestIndividual.kt
index c784678a88..d35fa3a4cc 100644
--- a/core/src/main/kotlin/org/evomaster/core/problem/rest/RestIndividual.kt
+++ b/core/src/main/kotlin/org/evomaster/core/problem/rest/RestIndividual.kt
@@ -28,6 +28,9 @@ import kotlin.math.max
*
* @property trackOperator indicates which operator create this individual.
* @property index indicates when the individual is created, ie, using num of evaluated individual.
+ *
+ *
+ * FIXME: why having to use AbstractRestSampler.createIndividual() instead of having such code here in constructor???
*/
class RestIndividual(
sampleType: SampleType,
diff --git a/core/src/main/kotlin/org/evomaster/core/problem/rest/RestIndividualSelectorUtils.kt b/core/src/main/kotlin/org/evomaster/core/problem/rest/RestIndividualSelectorUtils.kt
index 796ca92c66..431be6559a 100644
--- a/core/src/main/kotlin/org/evomaster/core/problem/rest/RestIndividualSelectorUtils.kt
+++ b/core/src/main/kotlin/org/evomaster/core/problem/rest/RestIndividualSelectorUtils.kt
@@ -52,7 +52,7 @@ object RestIndividualSelectorUtils {
return null
}
- fun findIndividuals(
+ fun old_findIndividuals(
individuals: List>,
verb: HttpVerb,
statusGroup: String
@@ -88,9 +88,11 @@ object RestIndividualSelectorUtils {
/*
Find individuals containing a certain action and STATUS
*/
- fun getIndividualsWithActionAndStatus(individualsInSolution: List>,
- verb: HttpVerb, statusCode: Int)
- :List> {
+ fun getIndividualsWithActionAndStatus(
+ individualsInSolution: List>,
+ verb: HttpVerb,
+ statusCode: Int
+ ):List> {
val individualsList = mutableListOf>()
@@ -143,7 +145,7 @@ object RestIndividualSelectorUtils {
return foundRestAction
}
- fun getIndividualsWithActionAndStatus(
+ fun findIndividuals(
individuals: List>,
verb: HttpVerb,
path: RestPath,
diff --git a/core/src/main/kotlin/org/evomaster/core/problem/rest/seeding/AbstractParser.kt b/core/src/main/kotlin/org/evomaster/core/problem/rest/seeding/AbstractParser.kt
index 27594560fb..c758342c46 100644
--- a/core/src/main/kotlin/org/evomaster/core/problem/rest/seeding/AbstractParser.kt
+++ b/core/src/main/kotlin/org/evomaster/core/problem/rest/seeding/AbstractParser.kt
@@ -28,6 +28,7 @@ import java.util.regex.Pattern
* the set of default actions (i.e., actions representing single calls to each API
* operation) and the Swagger specification.
*/
+@Deprecated("Code here will be replaced with intermediate representation. See new 'seeding' package")
abstract class AbstractParser(
protected val defaultRestCallActions: List,
protected val swagger: OpenAPI
diff --git a/core/src/main/kotlin/org/evomaster/core/problem/rest/seeding/Parser.kt b/core/src/main/kotlin/org/evomaster/core/problem/rest/seeding/Parser.kt
index 90934b759f..8bc09ecba7 100644
--- a/core/src/main/kotlin/org/evomaster/core/problem/rest/seeding/Parser.kt
+++ b/core/src/main/kotlin/org/evomaster/core/problem/rest/seeding/Parser.kt
@@ -2,6 +2,8 @@ package org.evomaster.core.problem.rest.seeding
import org.evomaster.core.problem.rest.RestCallAction
+
+@Deprecated("Code here will be replaced with intermediate representation. See new 'seeding' package")
interface Parser {
/**
diff --git a/core/src/main/kotlin/org/evomaster/core/problem/rest/seeding/postman/PostmanParser.kt b/core/src/main/kotlin/org/evomaster/core/problem/rest/seeding/postman/PostmanParser.kt
index 1069f5d4db..8c1591f74c 100644
--- a/core/src/main/kotlin/org/evomaster/core/problem/rest/seeding/postman/PostmanParser.kt
+++ b/core/src/main/kotlin/org/evomaster/core/problem/rest/seeding/postman/PostmanParser.kt
@@ -17,6 +17,7 @@ import java.lang.IllegalStateException
import java.net.URLDecoder
import java.nio.charset.StandardCharsets
+@Deprecated("Code here will be replaced with intermediate representation. See new 'seeding' package")
class PostmanParser(
defaultRestCallActions: List,
swagger: OpenAPI
diff --git a/core/src/main/kotlin/org/evomaster/core/problem/rest/service/AbstractRestFitness.kt b/core/src/main/kotlin/org/evomaster/core/problem/rest/service/AbstractRestFitness.kt
index 6df3f365a6..e6add341ff 100755
--- a/core/src/main/kotlin/org/evomaster/core/problem/rest/service/AbstractRestFitness.kt
+++ b/core/src/main/kotlin/org/evomaster/core/problem/rest/service/AbstractRestFitness.kt
@@ -49,7 +49,7 @@ import javax.ws.rs.core.NewCookie
import javax.ws.rs.core.Response
-abstract class AbstractRestFitness : HttpWsFitness() where T : Individual {
+abstract class AbstractRestFitness : HttpWsFitness() {
// TODO: This will moved under ApiWsFitness once RPC and GraphQL support is completed
@Inject
@@ -760,7 +760,7 @@ abstract class AbstractRestFitness : HttpWsFitness() where T : Individual
return null
}
- val dto = updateFitnessAfterEvaluation(targets, allCovered, individual as T, fv)
+ val dto = updateFitnessAfterEvaluation(targets, allCovered, individual, fv)
?: return null
handleExtra(dto, fv)
diff --git a/core/src/main/kotlin/org/evomaster/core/problem/rest/service/AbstractRestSampler.kt b/core/src/main/kotlin/org/evomaster/core/problem/rest/service/AbstractRestSampler.kt
index 87fef95987..66b6194c6b 100644
--- a/core/src/main/kotlin/org/evomaster/core/problem/rest/service/AbstractRestSampler.kt
+++ b/core/src/main/kotlin/org/evomaster/core/problem/rest/service/AbstractRestSampler.kt
@@ -307,6 +307,9 @@ abstract class AbstractRestSampler : HttpWsSampler() {
/**
* @return a created individual with specified actions, i.e., [restCalls].
* All actions must have been already initialized
+ *
+ *
+ * FIXME: why this function instead of dealing with this directly in the constructor of RestIndividual???
*/
open fun createIndividual(sampleType: SampleType, restCalls: MutableList): RestIndividual {
if(restCalls.any { !it.isInitialized() }){
diff --git a/core/src/main/kotlin/org/evomaster/core/problem/rest/service/BlackBoxRestModule.kt b/core/src/main/kotlin/org/evomaster/core/problem/rest/service/BlackBoxRestModule.kt
index 7986c3d743..28463dfd57 100644
--- a/core/src/main/kotlin/org/evomaster/core/problem/rest/service/BlackBoxRestModule.kt
+++ b/core/src/main/kotlin/org/evomaster/core/problem/rest/service/BlackBoxRestModule.kt
@@ -12,6 +12,7 @@ import org.evomaster.core.search.service.Archive
import org.evomaster.core.search.service.FitnessFunction
import org.evomaster.core.search.service.Minimizer
import org.evomaster.core.search.service.Sampler
+import org.evomaster.core.seeding.service.rest.PirToRest
class BlackBoxRestModule(
val usingRemoteController: Boolean
@@ -69,5 +70,9 @@ class BlackBoxRestModule(
bind(SecurityRest::class.java)
.asEagerSingleton()
+
+ bind(PirToRest::class.java)
+ .asEagerSingleton()
+
}
}
\ No newline at end of file
diff --git a/core/src/main/kotlin/org/evomaster/core/problem/rest/service/ResourceRestModule.kt b/core/src/main/kotlin/org/evomaster/core/problem/rest/service/ResourceRestModule.kt
index 8ebd8d70bf..3b3852554d 100755
--- a/core/src/main/kotlin/org/evomaster/core/problem/rest/service/ResourceRestModule.kt
+++ b/core/src/main/kotlin/org/evomaster/core/problem/rest/service/ResourceRestModule.kt
@@ -17,6 +17,7 @@ import org.evomaster.core.search.service.Sampler
import org.evomaster.core.search.service.mutator.Mutator
import org.evomaster.core.search.service.mutator.StandardMutator
import org.evomaster.core.search.service.mutator.StructureMutator
+import org.evomaster.core.seeding.service.rest.PirToRest
class ResourceRestModule(private val bindRemote : Boolean = true) : AbstractModule(){
@@ -59,7 +60,7 @@ class ResourceRestModule(private val bindRemote : Boolean = true) : AbstractModu
.to(RestResourceFitness::class.java)
.asEagerSingleton()
- bind(object : TypeLiteral>() {})
+ bind(object : TypeLiteral() {})
.to(RestResourceFitness::class.java)
.asEagerSingleton()
@@ -112,5 +113,8 @@ class ResourceRestModule(private val bindRemote : Boolean = true) : AbstractModu
bind(SecurityRest::class.java)
.asEagerSingleton()
+ bind(PirToRest::class.java)
+ .asEagerSingleton()
+
}
}
\ No newline at end of file
diff --git a/core/src/main/kotlin/org/evomaster/core/problem/rest/service/RestFitness.kt b/core/src/main/kotlin/org/evomaster/core/problem/rest/service/RestFitness.kt
index 7e6e33a476..2a082c8dce 100644
--- a/core/src/main/kotlin/org/evomaster/core/problem/rest/service/RestFitness.kt
+++ b/core/src/main/kotlin/org/evomaster/core/problem/rest/service/RestFitness.kt
@@ -12,7 +12,7 @@ import org.evomaster.core.search.FitnessValue
import org.slf4j.Logger
import org.slf4j.LoggerFactory
-open class RestFitness : AbstractRestFitness() {
+open class RestFitness : AbstractRestFitness() {
companion object {
private val log: Logger = LoggerFactory.getLogger(RestFitness::class.java)
diff --git a/core/src/main/kotlin/org/evomaster/core/problem/rest/service/RestModule.kt b/core/src/main/kotlin/org/evomaster/core/problem/rest/service/RestModule.kt
index 9277f7c1c4..8ed74f46fd 100644
--- a/core/src/main/kotlin/org/evomaster/core/problem/rest/service/RestModule.kt
+++ b/core/src/main/kotlin/org/evomaster/core/problem/rest/service/RestModule.kt
@@ -14,6 +14,7 @@ import org.evomaster.core.search.service.mutator.StandardMutator
import org.evomaster.core.search.service.*
import org.evomaster.core.search.service.mutator.Mutator
import org.evomaster.core.search.service.mutator.StructureMutator
+import org.evomaster.core.seeding.service.rest.PirToRest
class RestModule(private val bindRemote : Boolean = true) : AbstractModule(){
@@ -88,5 +89,7 @@ class RestModule(private val bindRemote : Boolean = true) : AbstractModule(){
bind(SecurityRest::class.java)
.asEagerSingleton()
+ bind(PirToRest::class.java)
+ .asEagerSingleton()
}
}
\ No newline at end of file
diff --git a/core/src/main/kotlin/org/evomaster/core/problem/rest/service/RestResourceFitness.kt b/core/src/main/kotlin/org/evomaster/core/problem/rest/service/RestResourceFitness.kt
index 125d8f5516..b94c34b39d 100755
--- a/core/src/main/kotlin/org/evomaster/core/problem/rest/service/RestResourceFitness.kt
+++ b/core/src/main/kotlin/org/evomaster/core/problem/rest/service/RestResourceFitness.kt
@@ -23,7 +23,7 @@ import javax.ws.rs.core.NewCookie
/**
* take care of calculating/collecting fitness of [RestIndividual]
*/
-class RestResourceFitness : AbstractRestFitness() {
+class RestResourceFitness : AbstractRestFitness() {
@Inject
diff --git a/core/src/main/kotlin/org/evomaster/core/problem/rest/service/SecurityRest.kt b/core/src/main/kotlin/org/evomaster/core/problem/rest/service/SecurityRest.kt
index f01196853f..975057e816 100644
--- a/core/src/main/kotlin/org/evomaster/core/problem/rest/service/SecurityRest.kt
+++ b/core/src/main/kotlin/org/evomaster/core/problem/rest/service/SecurityRest.kt
@@ -3,27 +3,16 @@ package org.evomaster.core.problem.rest.service
import com.google.inject.Inject
import javax.annotation.PostConstruct
-import org.apache.http.HttpStatus
-
-import org.evomaster.client.java.controller.api.dto.SutInfoDto
-import org.evomaster.client.java.controller.api.dto.auth.AuthenticationDto
-
import org.evomaster.core.logging.LoggingUtil
import org.evomaster.core.problem.enterprise.SampleType
import org.evomaster.core.problem.enterprise.auth.AuthSettings
import org.evomaster.core.problem.httpws.auth.HttpWsAuthenticationInfo
import org.evomaster.core.problem.rest.*
-import org.evomaster.core.problem.rest.param.PathParam
-import org.evomaster.core.remote.service.RemoteController
-import org.evomaster.core.remote.service.RemoteControllerImplementation
import org.evomaster.core.search.*
-import org.evomaster.core.search.action.ActionResult
-import org.evomaster.core.search.gene.string.StringGene
import org.evomaster.core.search.service.Archive
import org.evomaster.core.search.service.FitnessFunction
import org.evomaster.core.search.service.Randomness
-import org.evomaster.core.search.service.Sampler
//FIXME this needs to be cleaned-up
@@ -167,7 +156,7 @@ class SecurityRest {
// from archive, search if there is any test with a DELETE returning a 403
val existing403 : List> =
- RestIndividualSelectorUtils.getIndividualsWithActionAndStatus(individualsInSolution, HttpVerb.DELETE, delete.path, 403)
+ RestIndividualSelectorUtils.findIndividuals(individualsInSolution, HttpVerb.DELETE, delete.path, 403)
var individualToChooseForTest : RestIndividual
diff --git a/core/src/main/kotlin/org/evomaster/core/search/gene/Gene.kt b/core/src/main/kotlin/org/evomaster/core/search/gene/Gene.kt
index 39c7ea27dd..319fc1640f 100644
--- a/core/src/main/kotlin/org/evomaster/core/search/gene/Gene.kt
+++ b/core/src/main/kotlin/org/evomaster/core/search/gene/Gene.kt
@@ -767,6 +767,17 @@ abstract class Gene(
open fun possiblySame(gene : Gene) : Boolean = gene.name == name && gene::class == this::class
+ /**
+ * Given a string value, apply it to the current state of this gene (and possibly recursively to its children).
+ * If it fails for any reason, return false, without modifying its state.
+ */
+ open fun setFromStringValue(value: String) : Boolean{
+ //TODO in future this should be abstract, to force each gene to handle it.
+ //few implementations can be based on AbstractParser class for Postman
+ throw IllegalStateException("setFromStringValue() is not implemented for gene ${this::class.simpleName}")
+ }
+
+
//========================= handing binding genes ===================================
//TODO make sure all public methods keep the gene in a valid state.
diff --git a/core/src/main/kotlin/org/evomaster/core/search/gene/numeric/IntegerGene.kt b/core/src/main/kotlin/org/evomaster/core/search/gene/numeric/IntegerGene.kt
index 48b4f149fb..64e79b2af0 100644
--- a/core/src/main/kotlin/org/evomaster/core/search/gene/numeric/IntegerGene.kt
+++ b/core/src/main/kotlin/org/evomaster/core/search/gene/numeric/IntegerGene.kt
@@ -52,6 +52,15 @@ class IntegerGene(
private val log: Logger = LoggerFactory.getLogger(IntegerGene::class.java)
}
+ override fun setFromStringValue(value: String) : Boolean{
+ try{
+ this.value = value.toInt()
+ return true
+ }catch (e: NumberFormatException){
+ return false
+ }
+ }
+
override fun copyContent(): Gene {
return IntegerGene(
name,
diff --git a/core/src/main/kotlin/org/evomaster/core/search/gene/optional/CustomMutationRateGene.kt b/core/src/main/kotlin/org/evomaster/core/search/gene/optional/CustomMutationRateGene.kt
index 867292e06b..d166aedadb 100644
--- a/core/src/main/kotlin/org/evomaster/core/search/gene/optional/CustomMutationRateGene.kt
+++ b/core/src/main/kotlin/org/evomaster/core/search/gene/optional/CustomMutationRateGene.kt
@@ -52,6 +52,10 @@ class CustomMutationRateGene(
}
+ override fun setFromStringValue(value: String) : Boolean{
+ return gene.setFromStringValue(value)
+ }
+
override fun getWrappedGene(klass: Class) : T? where T : Gene{
if(this.javaClass == klass){
return this as T
diff --git a/core/src/main/kotlin/org/evomaster/core/search/gene/string/StringGene.kt b/core/src/main/kotlin/org/evomaster/core/search/gene/string/StringGene.kt
index aa692b5c9f..a297c9e982 100644
--- a/core/src/main/kotlin/org/evomaster/core/search/gene/string/StringGene.kt
+++ b/core/src/main/kotlin/org/evomaster/core/search/gene/string/StringGene.kt
@@ -69,7 +69,7 @@ class StringGene(
init {
if (minLength>maxLength) {
- throw IllegalArgumentException("Cannot create string gene ${this.name} with mininum length ${this.minLength} and maximum length ${this.maxLength}")
+ throw IllegalArgumentException("Cannot create string gene ${this.name} with minimum length ${this.minLength} and maximum length ${this.maxLength}")
}
}
@@ -983,4 +983,20 @@ class StringGene(
return otherelements.none { it is Gene && it.flatView().any { g-> g is StringGene && g.getPossiblyTaintedValue().equals(getPossiblyTaintedValue(), ignoreCase = true) } }
}
+
+ override fun setFromStringValue(value: String): Boolean {
+
+ val previousSpecialization = selectedSpecialization
+ val previousValue = value
+
+ this.value = value
+ selectedSpecialization = -1
+ if(!isLocallyValid() || !checkForGloballyValid()){
+ this.value = previousValue
+ this.selectedSpecialization = previousSpecialization
+ return false
+ }
+
+ return true
+ }
}
diff --git a/core/src/main/kotlin/org/evomaster/core/seeding/pir/PirTestCase.kt b/core/src/main/kotlin/org/evomaster/core/seeding/pir/PirTestCase.kt
new file mode 100644
index 0000000000..9371cf7c9b
--- /dev/null
+++ b/core/src/main/kotlin/org/evomaster/core/seeding/pir/PirTestCase.kt
@@ -0,0 +1,4 @@
+package org.evomaster.core.seeding.pir
+
+class PirTestCase {
+}
\ No newline at end of file
diff --git a/core/src/main/kotlin/org/evomaster/core/seeding/service/PirToIndividual.kt b/core/src/main/kotlin/org/evomaster/core/seeding/service/PirToIndividual.kt
new file mode 100644
index 0000000000..de6ff46eca
--- /dev/null
+++ b/core/src/main/kotlin/org/evomaster/core/seeding/service/PirToIndividual.kt
@@ -0,0 +1,25 @@
+package org.evomaster.core.seeding.service
+
+import com.google.inject.Inject
+import org.evomaster.core.problem.rest.service.AbstractRestSampler
+import org.evomaster.core.search.service.Randomness
+
+/**
+ * From Pojo Internal Representation (PIR), possibly derived from a textual representation (eg in JSON) of a test case,
+ * do create an individual, based on actual schema of the SUT.
+ * Note: we can assume that schema might change, and so the "old" test cases might not fully match the constraint
+ * in the current schema. Also, text might be manually modified by users.
+ * In other words, we can assume errors in parsing... in such cases, we should NOT crash EM, but rather issue warning
+ * messages.
+ *
+ * TODO should consider if this should be made a "service"
+ *
+ * TODO this will be the core of new "seeding" mechanism, eg seed from previous runs or manual edits from users,
+ * but for now we just need something basic to enable integration tests
+ */
+abstract class PirToIndividual {
+
+ @Inject
+ protected lateinit var randomness: Randomness
+
+}
\ No newline at end of file
diff --git a/core/src/main/kotlin/org/evomaster/core/seeding/service/rest/PirToRest.kt b/core/src/main/kotlin/org/evomaster/core/seeding/service/rest/PirToRest.kt
new file mode 100644
index 0000000000..f50168e092
--- /dev/null
+++ b/core/src/main/kotlin/org/evomaster/core/seeding/service/rest/PirToRest.kt
@@ -0,0 +1,83 @@
+package org.evomaster.core.seeding.service.rest
+
+import com.google.inject.Inject
+import org.evomaster.core.problem.enterprise.auth.AuthSettings
+import org.evomaster.core.problem.rest.HttpVerb
+import org.evomaster.core.problem.rest.RestCallAction
+import org.evomaster.core.problem.rest.param.PathParam
+import org.evomaster.core.problem.rest.service.AbstractRestSampler
+import org.evomaster.core.search.service.Randomness
+import org.evomaster.core.seeding.service.PirToIndividual
+import org.slf4j.Logger
+import org.slf4j.LoggerFactory
+import javax.annotation.PostConstruct
+
+class PirToRest: PirToIndividual(){
+
+ companion object{
+ private val log: Logger = LoggerFactory.getLogger(PirToRest::class.java)
+ }
+
+ @Inject
+ private lateinit var sampler: AbstractRestSampler
+
+
+ //TODO move up, once doing refactoring
+ private lateinit var authSettings: AuthSettings
+
+
+ /**
+ * All actions that can be defined from the OpenAPI schema
+ */
+ private lateinit var actionDefinitions : List
+
+ @PostConstruct
+ fun initialize() {
+ actionDefinitions = sampler.getActionDefinitions() as List
+ authSettings = sampler.authentications
+ }
+
+
+ fun fromVerbPath(verb: String, path: String) : RestCallAction?{
+
+ val v = try{HttpVerb.valueOf(verb.uppercase())}
+ catch (e: IllegalArgumentException){
+ log.warn("Unrecognized http verb: $verb")
+ return null
+ }
+
+ val candidates = actionDefinitions.filter { it.verb == v }
+ .filter { it.path.matches(path) }
+
+ if(candidates.isEmpty()){
+ log.warn("No match for endpoint path: $path")
+ return null
+ }
+
+ if(candidates.size > 1){
+ log.warn("Ambiguity issue, as ${candidates.size} endpoints are a match for: $path")
+ }
+
+ val x = candidates[0].copy() as RestCallAction
+ x.doInitialize(randomness)
+
+ x.parameters.forEach { p ->
+ when(p){
+ is PathParam -> {
+ val toSeed = x.path.getKeyValues(path)?.get(p.name)!!
+ val isSet = p.gene.setFromStringValue(toSeed)
+ if(!isSet){
+ log.warn("Failed to update path parameter ${p.name} with value: $toSeed")
+ return null
+ }
+ }
+ else -> {
+ //TODO other cases
+ }
+ }
+ }
+
+ return x
+ }
+
+}
\ No newline at end of file
diff --git a/core/src/test/kotlin/org/evomaster/core/problem/rest/individual/RestIndividualDisabledHMTest.kt b/core/src/test/kotlin/org/evomaster/core/problem/rest/individual/RestIndividualDisabledHMTest.kt
index d95816f3c1..7eb7152dfa 100644
--- a/core/src/test/kotlin/org/evomaster/core/problem/rest/individual/RestIndividualDisabledHMTest.kt
+++ b/core/src/test/kotlin/org/evomaster/core/problem/rest/individual/RestIndividualDisabledHMTest.kt
@@ -40,7 +40,7 @@ class RestIndividualDisabledHMTest : RestIndividualTestBase(){
override fun getMutator(): StandardMutator = mutator
- override fun getFitnessFunction(): AbstractRestFitness = ff
+ override fun getFitnessFunction(): AbstractRestFitness = ff
}
\ No newline at end of file
diff --git a/core/src/test/kotlin/org/evomaster/core/problem/rest/individual/RestIndividualResourceTest.kt b/core/src/test/kotlin/org/evomaster/core/problem/rest/individual/RestIndividualResourceTest.kt
index afc3b93f0f..540b1e0510 100644
--- a/core/src/test/kotlin/org/evomaster/core/problem/rest/individual/RestIndividualResourceTest.kt
+++ b/core/src/test/kotlin/org/evomaster/core/problem/rest/individual/RestIndividualResourceTest.kt
@@ -25,7 +25,7 @@ class RestIndividualResourceTest : RestIndividualTestBase() {
override fun getProblemModule() = ResourceRestModule(false)
override fun getMutator(): StandardMutator = mutator
- override fun getFitnessFunction(): AbstractRestFitness = ff
+ override fun getFitnessFunction(): AbstractRestFitness = ff
override fun getSampler(): AbstractRestSampler = sampler
diff --git a/core/src/test/kotlin/org/evomaster/core/problem/rest/individual/RestIndividualTestBase.kt b/core/src/test/kotlin/org/evomaster/core/problem/rest/individual/RestIndividualTestBase.kt
index 4827c74e2b..a14ac059d1 100644
--- a/core/src/test/kotlin/org/evomaster/core/problem/rest/individual/RestIndividualTestBase.kt
+++ b/core/src/test/kotlin/org/evomaster/core/problem/rest/individual/RestIndividualTestBase.kt
@@ -175,7 +175,7 @@ abstract class RestIndividualTestBase {
abstract fun getSampler() : AbstractRestSampler
abstract fun getMutator() : StandardMutator
- abstract fun getFitnessFunction() : AbstractRestFitness
+ abstract fun getFitnessFunction() : AbstractRestFitness
@ParameterizedTest
@MethodSource("getBudgetAndNumOfResourceForSampler")
diff --git a/core/src/test/kotlin/org/evomaster/core/problem/rest/individual/RestResourceIndividualDisabledHMTest.kt b/core/src/test/kotlin/org/evomaster/core/problem/rest/individual/RestResourceIndividualDisabledHMTest.kt
index cc5bbad676..11ee5993f7 100644
--- a/core/src/test/kotlin/org/evomaster/core/problem/rest/individual/RestResourceIndividualDisabledHMTest.kt
+++ b/core/src/test/kotlin/org/evomaster/core/problem/rest/individual/RestResourceIndividualDisabledHMTest.kt
@@ -80,7 +80,7 @@ class RestResourceIndividualDisabledHMTest : RestIndividualTestBase(){
override fun getMutator(): StandardMutator = mutator
- override fun getFitnessFunction(): AbstractRestFitness = ff
+ override fun getFitnessFunction(): AbstractRestFitness = ff
private fun sampleDbAction(table : Table) : List{
val actions = sqlInsertBuilder!!.createSqlInsertionAction(table.name)