Skip to content

Commit 94be0e1

Browse files
authored
Merge branch 'master' into dse/sql-z3-correctness
2 parents 9394c12 + d2090a6 commit 94be0e1

19 files changed

Lines changed: 916 additions & 460 deletions

File tree

.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,10 @@
1313
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
1414
hs_err_pid*
1515

16+
# IntelliJ ANTLR plugin recognizer default locations:
17+
core/gen/
18+
core/src/main/antlr4/org/evomaster/core/parser/gen
19+
1620
**/*.DS_Store
1721
/.idea/
1822
.idea/
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
package com.foo.rest.examples.spring.openapi.v3.httporacle.invalidallow.auth
2+
3+
import org.springframework.boot.SpringApplication
4+
import org.springframework.boot.autoconfigure.SpringBootApplication
5+
import org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration
6+
import org.springframework.http.ResponseEntity
7+
import org.springframework.web.bind.annotation.GetMapping
8+
import org.springframework.web.bind.annotation.PathVariable
9+
import org.springframework.web.bind.annotation.PutMapping
10+
import org.springframework.web.bind.annotation.RequestHeader
11+
import org.springframework.web.bind.annotation.RequestMapping
12+
import org.springframework.web.bind.annotation.RequestMethod
13+
import org.springframework.web.bind.annotation.RestController
14+
15+
16+
@SpringBootApplication(exclude = [SecurityAutoConfiguration::class])
17+
@RequestMapping(path = ["/api"])
18+
@RestController
19+
open class HttpInvalidAllowAuthApplication {
20+
21+
companion object {
22+
@JvmStatic
23+
fun main(args: Array<String>) {
24+
SpringApplication.run(HttpInvalidAllowAuthApplication::class.java, *args)
25+
}
26+
27+
val USERS = setOf("FOO", "BAR")
28+
29+
private val products = mutableMapOf<Int, String>()
30+
private val orders = mutableMapOf<Int, String>()
31+
32+
fun reset() {
33+
products.clear()
34+
orders.clear()
35+
}
36+
}
37+
38+
private fun isValidUser(auth: String?) = auth != null && USERS.contains(auth)
39+
40+
// OPTIONS is gated behind auth: without a valid user it returns 401, so the Allow
41+
// header can only be read after the oracle retries with an authenticated user.
42+
// The Allow lists DELETE, which is not declared in the schema (extra verb) -> fault.
43+
@RequestMapping(path = ["/products/{id}"], method = [RequestMethod.OPTIONS])
44+
open fun optionsProduct(
45+
@RequestHeader(value = "Authorization", required = false) auth: String?
46+
): ResponseEntity<Any> {
47+
if (!isValidUser(auth)) return ResponseEntity.status(401).build()
48+
return ResponseEntity.status(200).header("Allow", "GET,PUT,DELETE,HEAD,OPTIONS").build()
49+
}
50+
51+
@GetMapping(path = ["/products/{id}"])
52+
open fun getProduct(
53+
@RequestHeader(value = "Authorization", required = false) auth: String?,
54+
@PathVariable("id") id: Int
55+
): ResponseEntity<String> {
56+
if (!isValidUser(auth)) return ResponseEntity.status(401).build()
57+
val value = products[id] ?: return ResponseEntity.status(404).build()
58+
return ResponseEntity.status(200).body(value)
59+
}
60+
61+
@PutMapping(path = ["/products/{id}"])
62+
open fun putProduct(
63+
@RequestHeader(value = "Authorization", required = false) auth: String?,
64+
@PathVariable("id") id: Int
65+
): ResponseEntity<Any> {
66+
if (!isValidUser(auth)) return ResponseEntity.status(401).build()
67+
val isNew = !products.containsKey(id)
68+
products[id] = "$id"
69+
return ResponseEntity.status(if (isNew) 201 else 200).build()
70+
}
71+
72+
// Clean resource: Allow matches the schema (ignoring HEAD/OPTIONS).
73+
@RequestMapping(path = ["/orders/{id}"], method = [RequestMethod.OPTIONS])
74+
open fun optionsOrder(
75+
@RequestHeader(value = "Authorization", required = false) auth: String?
76+
): ResponseEntity<Any> {
77+
if (!isValidUser(auth)) return ResponseEntity.status(401).build()
78+
return ResponseEntity.status(200).header("Allow", "GET,PUT,HEAD,OPTIONS").build()
79+
}
80+
81+
@GetMapping(path = ["/orders/{id}"])
82+
open fun getOrder(
83+
@RequestHeader(value = "Authorization", required = false) auth: String?,
84+
@PathVariable("id") id: Int
85+
): ResponseEntity<String> {
86+
if (!isValidUser(auth)) return ResponseEntity.status(401).build()
87+
val value = orders[id] ?: return ResponseEntity.status(404).build()
88+
return ResponseEntity.status(200).body(value)
89+
}
90+
91+
@PutMapping(path = ["/orders/{id}"])
92+
open fun putOrder(
93+
@RequestHeader(value = "Authorization", required = false) auth: String?,
94+
@PathVariable("id") id: Int
95+
): ResponseEntity<Any> {
96+
if (!isValidUser(auth)) return ResponseEntity.status(401).build()
97+
val isNew = !orders.containsKey(id)
98+
orders[id] = "$id"
99+
return ResponseEntity.status(if (isNew) 201 else 200).build()
100+
}
101+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package com.foo.rest.examples.spring.openapi.v3.httporacle.invalidallow.auth
2+
3+
import com.foo.rest.examples.spring.openapi.v3.SpringController
4+
import org.evomaster.client.java.controller.AuthUtils
5+
import org.evomaster.client.java.controller.api.dto.auth.AuthenticationDto
6+
7+
8+
class HttpInvalidAllowAuthController : SpringController(HttpInvalidAllowAuthApplication::class.java) {
9+
10+
override fun getInfoForAuthentication(): List<AuthenticationDto> {
11+
return listOf(
12+
AuthUtils.getForAuthorizationHeader("FOO", "FOO"),
13+
AuthUtils.getForAuthorizationHeader("BAR", "BAR"),
14+
)
15+
}
16+
17+
override fun resetStateOfSUT() {
18+
HttpInvalidAllowAuthApplication.reset()
19+
}
20+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
package org.evomaster.e2etests.spring.openapi.v3.httporacle.invalidallow
2+
3+
import com.foo.rest.examples.spring.openapi.v3.httporacle.invalidallow.auth.HttpInvalidAllowAuthController
4+
import org.evomaster.core.problem.enterprise.DetectedFaultUtils
5+
import org.evomaster.core.problem.enterprise.ExperimentalFaultCategory
6+
import org.evomaster.e2etests.spring.openapi.v3.SpringTestBase
7+
import org.junit.jupiter.api.Assertions.assertTrue
8+
import org.junit.jupiter.api.BeforeAll
9+
import org.junit.jupiter.api.Test
10+
11+
class HttpInvalidAllowAuthEMTest : SpringTestBase() {
12+
13+
companion object {
14+
@BeforeAll
15+
@JvmStatic
16+
fun init() {
17+
initClass(HttpInvalidAllowAuthController())
18+
}
19+
}
20+
21+
22+
@Test
23+
fun testRunEM() {
24+
25+
runTestHandlingFlakyAndCompilation(
26+
"HttpInvalidAllowAuthEM",
27+
20
28+
) { args: MutableList<String> ->
29+
30+
setOption(args, "security", "false")
31+
setOption(args, "schemaOracles", "false")
32+
setOption(args, "httpOracles", "true")
33+
setOption(args, "useExperimentalOracles", "true")
34+
35+
val solution = initAndRun(args)
36+
37+
assertTrue(solution.individuals.size >= 1)
38+
39+
// OPTIONS is 401 without auth: the fault is only found once the oracle
40+
// retries with an authenticated user and reads the 2xx Allow header.
41+
val faults = DetectedFaultUtils.getDetectedFaultCategories(solution)
42+
assertTrue({ ExperimentalFaultCategory.HTTP_INVALID_ALLOW in faults })
43+
44+
val allowFaults = DetectedFaultUtils.getDetectedFaults(solution)
45+
.filter { it.category == ExperimentalFaultCategory.HTTP_INVALID_ALLOW }
46+
47+
assertTrue(allowFaults.any { it.operationId.contains("/api/products/") })
48+
assertTrue(allowFaults.none { it.operationId.contains("/api/orders/") })
49+
}
50+
}
51+
}

core-tests/e2e-tests/spring/spring-rest-openapi-v3/src/test/kotlin/org/evomaster/e2etests/spring/openapi/v3/httporacle/invalidallow/missing/HttpMissingAllowEMTest.kt renamed to core-tests/e2e-tests/spring/spring-rest-openapi-v3/src/test/kotlin/org/evomaster/e2etests/spring/openapi/v3/httporacle/invalidallow/HttpMissingAllowEMTest.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package org.evomaster.e2etests.spring.openapi.v3.httporacle.invalidallow.missing
1+
package org.evomaster.e2etests.spring.openapi.v3.httporacle.invalidallow
22

33
import com.foo.rest.examples.spring.openapi.v3.httporacle.invalidallow.missing.HttpMissingAllowController
44
import org.evomaster.core.problem.enterprise.DetectedFaultUtils
@@ -46,4 +46,4 @@ class HttpMissingAllowEMTest : SpringTestBase() {
4646
assertTrue(allowFaults.none { it.operationId.contains("/api/orders/") })
4747
}
4848
}
49-
}
49+
}

0 commit comments

Comments
 (0)