-
Notifications
You must be signed in to change notification settings - Fork 103
Add support to xml data type #1393
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
suarezrominajulieta
wants to merge
24
commits into
WebFuzzing:master
Choose a base branch
from
suarezrominajulieta:master
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
24 commits
Select commit
Hold shift + click to select a range
473da27
New branch_xml due to changes from master
suarezrominajulieta 4456f71
Update HttpWsTestCaseWriter.kt
suarezrominajulieta 4b4bb0b
Fix restActionBuilderV3
suarezrominajulieta 664b7e4
Fix cuantity of genes
suarezrominajulieta 20863bf
Changes from pr
suarezrominajulieta df3f5de
Fix
suarezrominajulieta 5617fa1
Try
suarezrominajulieta 93abfaa
Merge branch 'WebFuzzing:master' into master
suarezrominajulieta 0869cd7
Merge branch 'WebFuzzing:master' into master
suarezrominajulieta af2b540
Merge branch 'WebFuzzing:master' into master
suarezrominajulieta 319e839
Merge branch 'WebFuzzing:master' into master
suarezrominajulieta e3eca4a
Merge branch 'WebFuzzing:master' into master
suarezrominajulieta 1354ec1
Merge branch 'WebFuzzing:master' into master
suarezrominajulieta 39de778
Merge branch 'WebFuzzing:master' into master
suarezrominajulieta 7d0333f
Merge branch 'WebFuzzing:master' into master
suarezrominajulieta 8fcd380
Merge branch 'WebFuzzing:master' into master
suarezrominajulieta 994f40e
Squashed commit of the following:
suarezrominajulieta 2a21eb7
Fix, clean sqlRangeGene changes
suarezrominajulieta 791bf8c
Merge branch 'WebFuzzing:master' into master
suarezrominajulieta cdd80b7
Merge branch 'WebFuzzing:master' into master
suarezrominajulieta 15713e0
Remove unintended change; align file with upstream
suarezrominajulieta 2f36392
Merge branch 'WebFuzzing:master' into master
suarezrominajulieta 21041b4
Merge branch 'WebFuzzing:master' into master
suarezrominajulieta 5d41b1d
Merge branch 'WebFuzzing:master' into master
suarezrominajulieta File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
291 changes: 291 additions & 0 deletions
291
...ts/spring/spring-rest-bb/src/main/kotlin/com/foo/rest/examples/bb/xml/BBXMLApplication.kt
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,291 @@ | ||
| package com.foo.rest.examples.bb.xml | ||
|
|
||
| import org.springframework.http.ResponseEntity | ||
| import org.springframework.web.bind.annotation.* | ||
| import org.springframework.boot.SpringApplication | ||
| import org.springframework.boot.autoconfigure.SpringBootApplication | ||
| import org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration | ||
| import org.springframework.http.MediaType | ||
| import javax.xml.bind.annotation.* | ||
|
|
||
| @SpringBootApplication(exclude = [SecurityAutoConfiguration::class]) | ||
| @RequestMapping(path = ["/api/bbxml"]) | ||
| @RestController | ||
| open class BBXMLApplication { | ||
|
|
||
| companion object { | ||
| @JvmStatic | ||
| fun main(args: Array<String>) { | ||
| SpringApplication.run(BBXMLApplication::class.java, *args) | ||
| } | ||
| } | ||
|
|
||
| /* ===================== ENDPOINTS ===================== */ | ||
|
|
||
| // 1. String -> XML | ||
| @PostMapping( | ||
| "/receive-string-respond-xml", | ||
| consumes = ["text/plain"], | ||
| produces = ["application/xml"] | ||
| ) | ||
| fun stringToXml(@RequestBody body: String): ResponseEntity<Person> { | ||
| if (body.isBlank()) | ||
| return ResponseEntity.status(400).build() | ||
|
|
||
| return ResponseEntity.status(200) | ||
| .body(Person(name = body, age = body.length)) | ||
| } | ||
|
|
||
| // 2. XML -> String | ||
| @PostMapping( | ||
| "/receive-xml-respond-string", | ||
| consumes = ["application/xml"], | ||
| produces = ["text/plain"] | ||
| ) | ||
| fun xmlToString(@RequestBody person: Person): ResponseEntity<String> { | ||
| if (!isValid(person)) | ||
| return ResponseEntity | ||
| .status(400).contentType(MediaType.TEXT_PLAIN).body("") | ||
|
|
||
| return ResponseEntity.status(200).body("not ok") | ||
| } | ||
|
|
||
| // 3. Employee (2-level nesting) | ||
| @PostMapping( | ||
| "/employee", | ||
| consumes = ["application/xml"], | ||
| produces = ["text/plain"] | ||
| ) | ||
| fun employee(@RequestBody employee: Employee): ResponseEntity<String> { | ||
| if (!isValid(employee)) | ||
| return ResponseEntity.status(400) | ||
| .contentType(MediaType.TEXT_PLAIN) | ||
| .body("invalid input") | ||
|
|
||
| return ResponseEntity.status(200) | ||
| .body( | ||
| if (employee.role == Role.ADMIN && employee.person.age > 30) | ||
| "admin" | ||
| else | ||
| "not admin or too young" | ||
| ) | ||
| } | ||
|
|
||
| // 4. Company (3-level nesting) | ||
| @PostMapping( | ||
| "/company", | ||
| consumes = ["application/xml"], | ||
| produces = ["text/plain"] | ||
| ) | ||
| fun company(@RequestBody company: Company): ResponseEntity<String> { | ||
| if (!isValid(company)) | ||
| return ResponseEntity.status(400).body("") | ||
|
|
||
| return ResponseEntity.status(200) | ||
| .body(if (company.employees.isEmpty()) "small company" else "big company") | ||
| } | ||
|
|
||
| // 5. Department (recursive) | ||
| @PostMapping( | ||
| "/department", | ||
| consumes = ["application/xml"], | ||
| produces = ["text/plain"] | ||
| ) | ||
| fun department(@RequestBody department: Department): ResponseEntity<String> { | ||
| if (!isValid(department)) | ||
| return ResponseEntity.status(400) | ||
| .contentType(MediaType.TEXT_PLAIN) | ||
| .body("invalid input") | ||
|
|
||
| return ResponseEntity.status(200) | ||
| .body("department with ${department.employees.size + 1} employees") | ||
| } | ||
|
|
||
| // 6. Organization (3 lists) | ||
| @PostMapping( | ||
| "/organization", | ||
| consumes = ["application/xml"], | ||
| produces = ["text/plain"] | ||
| ) | ||
| fun organization(@RequestBody organization: Organization): ResponseEntity<String> { | ||
| if (!isValid(organization)) | ||
| return ResponseEntity.status(400) | ||
| .contentType(MediaType.TEXT_PLAIN) | ||
| .body("invalid input") | ||
|
|
||
| return ResponseEntity.status(200) | ||
| .body("organization with ${organization.people.size} people") | ||
| } | ||
|
|
||
| // 7. Project (attributes) | ||
| @PostMapping( | ||
| "/project", | ||
| consumes = ["application/xml"], | ||
| produces = ["text/plain"] | ||
| ) | ||
| fun project(@RequestBody project: Project): ResponseEntity<String> { | ||
| if (!isValid(project)) | ||
| return ResponseEntity.status(400).body("") | ||
|
|
||
| var adults = 0 | ||
| for (m in project.members) { | ||
| if (m.id.isNotBlank() && m.age >= 18) | ||
| adults++ | ||
| } | ||
|
|
||
| return ResponseEntity.status(200).body( | ||
| if (adults > 0) | ||
| "project ${project.code} has $adults adult members" | ||
| else | ||
| "project ${project.code} has only minors" | ||
| ) | ||
| } | ||
|
|
||
| // 8. Project list | ||
| @PostMapping( | ||
| "/projects", | ||
| consumes = ["application/xml"], | ||
| produces = ["text/plain"] | ||
| ) | ||
| fun postProjects(@RequestBody list: ProjectList): ResponseEntity<String> { | ||
| if (!isValid(list)) | ||
| return ResponseEntity.status(400).body("") | ||
|
|
||
| var members = 0 | ||
| var hasCode = false | ||
|
|
||
| for (p in list.projects) { | ||
| if (p.code.isNotBlank()) | ||
| hasCode = true | ||
| for (m in p.members) { | ||
| if (m.id.isNotBlank()) | ||
| members++ | ||
| } | ||
| } | ||
|
|
||
| return ResponseEntity.status(200) | ||
| .body( | ||
| if (hasCode && members > 0) | ||
| "valid projects with $members members" | ||
| else | ||
| "invalid projects" | ||
| ) | ||
| } | ||
|
|
||
| // 9. Person with attributes | ||
| @PostMapping( | ||
| "/person-with-attr", | ||
| consumes = ["application/xml"], | ||
| produces = ["text/plain"] | ||
| ) | ||
| fun personWithAttr(@RequestBody person: PersonWithAttr): ResponseEntity<String> { | ||
|
|
||
| if (!isValid(person)) | ||
| return ResponseEntity.status(400).body("invalid person") | ||
|
|
||
| return ResponseEntity.status(200) | ||
| .body("person ${person.id} is valid") | ||
| } | ||
|
|
||
| /* ===================== SCHEMA-LIKE VALIDATION ===================== */ | ||
|
|
||
| private fun isValid(p: Person): Boolean = | ||
| p.name.isNotBlank() && p.age >= 0 | ||
|
|
||
| private fun isValid(e: Employee): Boolean = | ||
| isValid(e.person) | ||
|
|
||
| private fun isValid(c: Company): Boolean = | ||
| c.name.isNotBlank() | ||
|
|
||
| private fun isValid(d: Department): Boolean = | ||
| d.name.isNotBlank() | ||
|
|
||
| private fun isValid(o: Organization): Boolean = | ||
| o.name.isNotBlank() | ||
|
|
||
| private fun isValid(p: PersonWithAttr): Boolean = | ||
| p.id.isNotBlank() && | ||
| p.name.isNotBlank() && | ||
| p.age >= 0 | ||
|
|
||
| private fun isValid(p: Project): Boolean = | ||
| p.code.isNotBlank() | ||
|
|
||
| private fun isValid(pl: ProjectList): Boolean = | ||
| true | ||
| } | ||
|
|
||
| /* ===================== MODELS (JAXB) ===================== */ | ||
|
|
||
| @XmlRootElement(name = "person") | ||
| @XmlAccessorType(XmlAccessType.FIELD) | ||
| open class Person( | ||
| var name: String = "", | ||
| var age: Int = 0 | ||
| ) | ||
|
|
||
| @XmlRootElement(name = "employee") | ||
| @XmlAccessorType(XmlAccessType.FIELD) | ||
| open class Employee( | ||
| var person: Person = Person(), | ||
| var role: Role = Role.USER | ||
| ) | ||
|
|
||
| @XmlRootElement(name = "company") | ||
| @XmlAccessorType(XmlAccessType.FIELD) | ||
| open class Company( | ||
| var name: String = "", | ||
| @field:XmlElement(name = "Person", namespace = "") | ||
| var employees: MutableList<Person> = mutableListOf() | ||
| ) | ||
|
|
||
| enum class Role { ADMIN, USER, GUEST } | ||
|
|
||
| @XmlRootElement(name = "department") | ||
| @XmlAccessorType(XmlAccessType.FIELD) | ||
| open class Department( | ||
| var name: String = "", | ||
| @field:XmlElement(name = "Employee", namespace = "") | ||
| var employees: List<Employee> = emptyList(), | ||
| @field:XmlElement(name = "Department", namespace = "") | ||
| var subDepartments: MutableList<Department> = mutableListOf() | ||
| ) | ||
|
|
||
| @XmlRootElement(name = "organization") | ||
| @XmlAccessorType(XmlAccessType.FIELD) | ||
| open class Organization( | ||
| var name: String = "", | ||
| @field:XmlElement(name = "Person", namespace = "") | ||
| var people: MutableList<Person> = mutableListOf(), | ||
| @field:XmlElement(name = "Employee", namespace = "") | ||
| var employees: MutableList<Employee> = mutableListOf(), | ||
| @field:XmlElement(name = "Company", namespace = "") | ||
| var companies: MutableList<Company> = mutableListOf() | ||
| ) | ||
|
|
||
| @XmlRootElement(name = "personWithAttr") | ||
| @XmlAccessorType(XmlAccessType.FIELD) | ||
| open class PersonWithAttr( | ||
| @XmlAttribute(name = "id") | ||
| var id: String = "", | ||
| var name: String = "", | ||
| var age: Int = 0 | ||
| ) | ||
|
|
||
| @XmlRootElement(name = "project") | ||
| @XmlAccessorType(XmlAccessType.FIELD) | ||
| open class Project( | ||
| @XmlAttribute(name = "code") | ||
| var code: String = "", | ||
| @field:XmlElement(name = "PersonWithAttr", namespace = "") | ||
| var members: MutableList<PersonWithAttr> = mutableListOf() | ||
| ) | ||
|
|
||
| @XmlRootElement(name = "projectList") | ||
| @XmlAccessorType(XmlAccessType.FIELD) | ||
| open class ProjectList( | ||
| @field:XmlElement(name = "Project", namespace = "") | ||
| var projects: MutableList<Project> = mutableListOf() | ||
| ) | ||
|
|
5 changes: 5 additions & 0 deletions
5
...sts/spring/spring-rest-bb/src/test/kotlin/com/foo/rest/examples/bb/xml/BBXMLController.kt
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| package com.foo.rest.examples.bb.xml | ||
|
|
||
| import com.foo.rest.examples.bb.SpringController | ||
|
|
||
| class BBXMLController : SpringController(BBXMLApplication::class.java) |
76 changes: 76 additions & 0 deletions
76
...ing/spring-rest-bb/src/test/kotlin/org/evomaster/e2etests/spring/rest/bb/xml/BBXMLTest.kt
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,76 @@ | ||
| package org.evomaster.e2etests.spring.rest.bb.xml | ||
|
|
||
| import com.foo.rest.examples.bb.xml.BBXMLController | ||
| import org.evomaster.core.EMConfig | ||
| import org.evomaster.core.output.OutputFormat | ||
| import org.evomaster.core.problem.rest.data.HttpVerb | ||
| 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.api.Test | ||
|
|
||
|
|
||
| class BBXMLTest : SpringTestBase() { | ||
|
|
||
| companion object { | ||
| @BeforeAll | ||
| @JvmStatic | ||
| fun init() { | ||
| val config = EMConfig() | ||
| initClass(BBXMLController(), config) | ||
| } | ||
| } | ||
|
|
||
| @Test | ||
| fun testRunEM() { | ||
| runTestHandlingFlakyAndCompilation( | ||
| "BBXmlEM", | ||
| "org.foo.BBXmlEM", | ||
| null, // terminations | ||
| 1000, // iterations | ||
| false, // createTests - skip compilation phase | ||
| { args: MutableList<String> -> | ||
|
|
||
| addBlackBoxOptions(args, OutputFormat.JAVA_JUNIT_5) | ||
| args.add("--enableBasicAssertions") | ||
| args.add("true") | ||
|
|
||
| val solution = initAndRun(args) | ||
| assertTrue(solution.individuals.size >= 1) | ||
|
|
||
| /* ========= basic XML endpoints ========= */ | ||
| assertHasAtLeastOne(solution, HttpVerb.POST, 200, "/api/bbxml/receive-string-respond-xml", null) | ||
| // 400 for receive-string-respond-xml requires blank string - hard to generate | ||
|
|
||
| assertHasAtLeastOne(solution, HttpVerb.POST, 200, "/api/bbxml/receive-xml-respond-string", null) | ||
| assertHasAtLeastOne(solution, HttpVerb.POST, 400, "/api/bbxml/receive-xml-respond-string", null) | ||
|
|
||
| /* ========= nested XML objects ========= */ | ||
| assertHasAtLeastOne(solution, HttpVerb.POST, 200, "/api/bbxml/employee", null) | ||
| assertHasAtLeastOne(solution, HttpVerb.POST, 400, "/api/bbxml/employee", null) | ||
|
|
||
| assertHasAtLeastOne(solution, HttpVerb.POST, 200, "/api/bbxml/company", null) | ||
| assertHasAtLeastOne(solution, HttpVerb.POST, 400, "/api/bbxml/company", null) | ||
|
|
||
| assertHasAtLeastOne(solution, HttpVerb.POST, 200, "/api/bbxml/department", null) | ||
| assertHasAtLeastOne(solution, HttpVerb.POST, 400, "/api/bbxml/department", null) | ||
|
|
||
| assertHasAtLeastOne(solution, HttpVerb.POST, 200, "/api/bbxml/organization", null) | ||
|
|
||
| /* ========= XML with attributes (main test objective) ========= */ | ||
|
|
||
| // person-with-attr: simple object with @XmlAttribute | ||
| assertHasAtLeastOne(solution, HttpVerb.POST, 200, "/api/bbxml/person-with-attr", null) | ||
| assertHasAtLeastOne(solution, HttpVerb.POST, 400, "/api/bbxml/person-with-attr", null) | ||
|
|
||
| // project: object with @XmlAttribute and list of PersonWithAttr | ||
| assertHasAtLeastOne(solution, HttpVerb.POST, 200, "/api/bbxml/project", null) | ||
| assertHasAtLeastOne(solution, HttpVerb.POST, 400, "/api/bbxml/project", null) | ||
|
|
||
| // projects: list of Project objects | ||
| assertHasAtLeastOne(solution, HttpVerb.POST, 200, "/api/bbxml/projects", null) | ||
| }, | ||
| 3 // timeoutMinutes | ||
| ) | ||
| } | ||
| } | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is not how BB tests should be written in this module. they should follow the structure:
see all other tests in this module, in particular the use of
CoveredTargets.cover()