Permalink
Browse files

handling of headers as part of the search

  • Loading branch information...
arcuri82 committed Nov 19, 2017
1 parent 01c1cf8 commit a25cfd5049e1a2a258a756aa2ad15676dada989e
@@ -2,8 +2,8 @@ package org.evomaster.core.output
import org.evomaster.core.problem.rest.RestCallAction
import org.evomaster.core.problem.rest.RestCallResult
import org.evomaster.core.problem.rest.auth.NoAuth
import org.evomaster.core.problem.rest.param.BodyParam
import org.evomaster.core.problem.rest.param.HeaderParam
import org.evomaster.core.search.EvaluatedAction
@@ -100,7 +100,7 @@ class TestCaseWriter {
addRestCallLines(call, lines, res, baseUrlOfSut)
if(! res.getTimedout()) {
if (!res.getTimedout()) {
/*
Fail test if exception is not thrown, but not if it was a timeout,
otherwise the test would become flaky
@@ -127,7 +127,7 @@ class TestCaseWriter {
handleFirstLine(call, lines, res)
lines.indent(2)
handleAuth(call, lines)
handleHeaders(call, lines)
handleBody(call, lines)
@@ -154,7 +154,7 @@ class TestCaseWriter {
lines.addEmpty()
lines.deindent(2)
val baseUri: String = if(call.locationId != null){
val baseUri: String = if (call.locationId != null) {
locationVar(call.locationId!!)
} else {
call.path.resolveOnlyPath(call.parameters)
@@ -173,7 +173,7 @@ class TestCaseWriter {
lines.addEmpty()
if (call.saveLocation && !res.stopping) {
if(! res.getHeuristicsForChainedLocation()) {
if (!res.getHeuristicsForChainedLocation()) {
lines.append("${locationVar(call.path.lastElement())} = ")
} else {
lines.append("String id_$counter = ")
@@ -253,12 +253,19 @@ class TestCaseWriter {
}
}
private fun handleAuth(call: RestCallAction, lines: Lines) {
if (call.auth !is NoAuth) {
call.auth.headers.forEach { h ->
lines.add(".header(\"${h.name}\", \"${h.value}\") // ${call.auth.name}")
}
private fun handleHeaders(call: RestCallAction, lines: Lines) {
val prechosenAuthHeaders = call.auth.headers.map { it.name }
call.auth.headers.forEach {
lines.add(".header(\"${it.name}\", \"${it.value}\") // ${call.auth.name}")
}
call.parameters.filterIsInstance<HeaderParam>()
.filter { !prechosenAuthHeaders.contains(it.name) }
.forEach {
lines.add(".header(\"${it.name}\", ${it.gene.getValueAsPrintableString()})")
}
}
private fun getAcceptHeader(): String {
@@ -0,0 +1,11 @@
package org.evomaster.core.problem.rest.param
import org.evomaster.core.search.gene.Gene
class HeaderParam(name: String, gene: Gene) : Param(name, gene){
override fun copy(): Param {
return HeaderParam(name, gene.copy())
}
}
@@ -152,7 +152,7 @@ class RestActionBuilder {
when (p.`in`) {
"query" -> params.add(QueryParam(name, gene))
"path" -> params.add(PathParam(name, DisruptiveGene("d_", gene, 1.0)))
"header" -> throw IllegalStateException("TODO header")
"header" -> params.add(HeaderParam(name, gene))
"formData" -> params.add(FormParam(name, gene))
else -> throw IllegalStateException("Unrecognized: ${p.getIn()}")
}
@@ -72,12 +72,12 @@ class RestFitness : FitnessFunction<RestIndividual>() {
log.debug("Done initializing {}", RestFitness::class.simpleName)
}
override open fun reinitialize() : Boolean{
override open fun reinitialize(): Boolean {
try {
rc.stopSUT()
initialize()
} catch(e: Exception){
} catch (e: Exception) {
log.warn("Failed to re-initialize the SUT: $e")
return false
}
@@ -110,13 +110,13 @@ class RestFitness : FitnessFunction<RestIndividual>() {
throw IllegalStateException("Cannot handle: ${a.javaClass}")
}
if(!ok){
if (!ok) {
break
}
if(configuration.heuristicsForSQL) {
if (configuration.heuristicsForSQL) {
val extra = rc.getExtraHeuristics()
if(extra == null) {
if (extra == null) {
log.warn("Cannot retrieve extra heuristics")
return null
}
@@ -137,7 +137,7 @@ class RestFitness : FitnessFunction<RestIndividual>() {
val ids = randomness.choose(archive.notCoveredTargets(), 100)
val dto = rc.getTargetCoverage(ids)
if(dto == null) {
if (dto == null) {
log.warn("Cannot retrieve coverage")
return null
}
@@ -220,17 +220,24 @@ class RestFitness : FitnessFunction<RestIndividual>() {
val builder = client.target(fullUri).request()
if (a.auth !is NoAuth) {
a.auth.headers.forEach { h ->
builder.header(h.name, h.value)
}
a.auth.headers.forEach {
builder.header(it.name, it.value)
}
val prechosenAuthHeaders = a.auth.headers.map { it.name }
/*
TODO: When handling headers, check that they do not
conflict with the auth ones
TODO: optimization, avoid mutating header gene if anyway
using pre-chosen one
*/
a.parameters.filterIsInstance<org.evomaster.core.problem.rest.param.HeaderParam>()
.filter { !prechosenAuthHeaders.contains(it.name) }
.forEach {
builder.header(it.name, it.gene.getValueAsRawString())
}
/*
TODO: need to handle "accept" of returned resource
*/
@@ -243,7 +250,7 @@ class RestFitness : FitnessFunction<RestIndividual>() {
val body = a.parameters.find { p -> p is BodyParam }
val forms = a.getBodyFormData()
if(body != null && !forms.isBlank()){
if (body != null && !forms.isBlank()) {
throw IllegalStateException("Issue in Swagger configuration: both Body and FormData definitions in the same endpoint")
}
@@ -267,16 +274,16 @@ class RestFitness : FitnessFunction<RestIndividual>() {
val rcr = RestCallResult()
actionResults.add(rcr)
val response = try{
val response = try {
invocation.invoke()
} catch (e: ProcessingException){
} catch (e: ProcessingException) {
//this can happen for example if call ends up in an infinite redirection loop
if((e.cause?.message?.contains("redirected too many") ?: false) && e.cause is ProtocolException){
if ((e.cause?.message?.contains("redirected too many") ?: false) && e.cause is ProtocolException) {
rcr.setInfiniteLoop(true)
rcr.setErrorMessage(e.cause!!.message!!)
return false
} else if(e.cause is SocketTimeoutException) {
} else if (e.cause is SocketTimeoutException) {
/*
This is very tricky. In theory it shouldn't happen that a REST call
does timeout (eg 10 seconds). But it might happen due to glitch,
@@ -310,7 +317,7 @@ class RestFitness : FitnessFunction<RestIndividual>() {
*/
val body = response.readEntity(String::class.java)
if(body.length < configuration.maxResponseByteSize) {
if (body.length < configuration.maxResponseByteSize) {
rcr.setBody(body)
} else {
log.warn("A very large response body was retrieved from the endpoint '${a.path}'." +
@@ -331,7 +338,7 @@ class RestFitness : FitnessFunction<RestIndividual>() {
}
if (! handleSaveLocation(a, response, rcr, chainState)) return false
if (!handleSaveLocation(a, response, rcr, chainState)) return false
return true
}
@@ -363,7 +370,7 @@ class RestFitness : FitnessFunction<RestIndividual>() {
*/
val id = rcr.getResourceId()
if(id != null && hasParameterChild(a)){
if (id != null && hasParameterChild(a)) {
location = a.resolvedPath() + "/" + id
rcr.setHeuristicsForChainedLocation(true)
}
@@ -26,6 +26,7 @@ abstract class Gene(var name: String) {
* Once printed, it would be equivalent to the actual value, eg
*
* 1 -> "1" -> printed as 1
*
* "foo" -> "\"foo\"" -> printed as "foo"
*/
abstract fun getValueAsPrintableString() : String
@@ -25,6 +25,11 @@ internal class RestActionBuilderTest {
return actions
}
@Test
fun testCatWatch() {
loadAndAssertActions("/swagger/catwatch.json", 23)
}
@Test
fun testProxyPrint() {
loadAndAssertActions("/swagger/proxyprint.json", 115)
Oops, something went wrong.

0 comments on commit a25cfd5

Please sign in to comment.