Skip to content

Commit f455021

Browse files
committed
Support for ChoiceGene in DTO generated test cases
1 parent ab11963 commit f455021

File tree

5 files changed

+80
-71
lines changed

5 files changed

+80
-71
lines changed

core-tests/e2e-tests/spring-rest-openapi-v3/src/main/kotlin/com/foo/rest/examples/spring/openapi/v3/dtoreflectiveassert/DtoReflectiveAssertRest.kt

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -14,17 +14,15 @@ class DtoReflectiveAssertRest {
1414
return ResponseEntity.ok("OK")
1515
}
1616

17-
// TODO: Restore when support for ChoiceGene has been added
18-
// @PostMapping(path = ["/anyof"], consumes = [MediaType.APPLICATION_JSON_VALUE])
19-
// open fun anyof(@RequestBody body: AnyOfDto) : ResponseEntity<String>{
20-
// return ResponseEntity.ok("OK")
21-
// }
22-
23-
// TODO: Restore when support for ChoiceGene has been added
24-
// @PostMapping(path = ["/oneof"], consumes = [MediaType.APPLICATION_JSON_VALUE])
25-
// open fun oneof(@RequestBody body: OneOfDto) : ResponseEntity<String>{
26-
// return ResponseEntity.ok("OK")
27-
// }
17+
@PostMapping(path = ["/anyof"], consumes = [MediaType.APPLICATION_JSON_VALUE])
18+
open fun anyof(@RequestBody body: AnyOfDto) : ResponseEntity<String>{
19+
return ResponseEntity.ok("OK")
20+
}
21+
22+
@PostMapping(path = ["/oneof"], consumes = [MediaType.APPLICATION_JSON_VALUE])
23+
open fun oneof(@RequestBody body: OneOfDto) : ResponseEntity<String>{
24+
return ResponseEntity.ok("OK")
25+
}
2826

2927
@PostMapping(path = ["/primitiveTypes"], consumes = [MediaType.APPLICATION_JSON_VALUE])
3028
open fun primitiveTypes(@RequestBody body: PrimitiveTypesDto) : ResponseEntity<String>{

core-tests/e2e-tests/spring-rest-openapi-v3/src/main/resources/static/openapi-dto-reflective-assert.yaml

Lines changed: 41 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
openapi: 3.0.3
22
info:
3-
title: allOf with Component Schemas
3+
title: Schema for E2E DTO Testing
44
version: 1.0.0
55

66
paths:
@@ -126,47 +126,46 @@ paths:
126126
responses:
127127
'200':
128128
description: OK
129-
# TODO: Restore when support for ChoiceGene has been added
130-
# /anyof:
131-
# post:
132-
# summary: Accepts either an email (component) or phone (inline)
133-
# requestBody:
134-
# required: true
135-
# content:
136-
# application/json:
137-
# schema:
138-
# anyOf:
139-
# - $ref: '#/components/schemas/EmailPayload'
140-
# - type: object
141-
# required: [phone]
142-
# properties:
143-
# phone:
144-
# type: string
145-
# responses:
146-
# '200':
147-
# description: OK
148-
# /oneof:
149-
# post:
150-
# summary: Accepts either cat or dog object (but not both)
151-
# requestBody:
152-
# required: true
153-
# content:
154-
# application/json:
155-
# schema:
156-
# oneOf:
157-
# - type: object
158-
# required: [cat]
159-
# properties:
160-
# cat:
161-
# type: string
162-
# - type: object
163-
# required: [mouse]
164-
# properties:
165-
# mouse:
166-
# type: string
167-
# responses:
168-
# '200':
169-
# description: OK
129+
/anyof:
130+
post:
131+
summary: Accepts either an email (component) or phone (inline)
132+
requestBody:
133+
required: true
134+
content:
135+
application/json:
136+
schema:
137+
anyOf:
138+
- $ref: '#/components/schemas/EmailPayload'
139+
- type: object
140+
required: [phone]
141+
properties:
142+
phone:
143+
type: string
144+
responses:
145+
'200':
146+
description: OK
147+
/oneof:
148+
post:
149+
summary: Accepts either cat or mouse object (but not both)
150+
requestBody:
151+
required: true
152+
content:
153+
application/json:
154+
schema:
155+
oneOf:
156+
- type: object
157+
required: [cat]
158+
properties:
159+
cat:
160+
type: string
161+
- type: object
162+
required: [mouse]
163+
properties:
164+
mouse:
165+
type: string
166+
responses:
167+
'200':
168+
description: OK
170169

171170
components:
172171
schemas:

core-tests/e2e-tests/spring-rest-openapi-v3/src/test/kotlin/org/evomaster/e2etests/spring/openapi/v3/dtoreflectiveassert/DtoReflectiveAssertEMTest.kt

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import kotlin.reflect.full.createInstance
1313
import kotlin.reflect.full.memberProperties
1414
import kotlin.reflect.jvm.isAccessible
1515

16+
@Suppress("LanguageDetectionInspection")
1617
class DtoReflectiveAssertEMTest: SpringTestBase() {
1718

1819
companion object {
@@ -37,6 +38,8 @@ class DtoReflectiveAssertEMTest: SpringTestBase() {
3738

3839
Assertions.assertTrue(solution.individuals.size >= 1)
3940
assertHasAtLeastOne(solution, HttpVerb.POST, 200, "/allof", "OK")
41+
assertHasAtLeastOne(solution, HttpVerb.POST, 200, "/anyof", "OK")
42+
assertHasAtLeastOne(solution, HttpVerb.POST, 200, "/oneof", "OK")
4043
assertHasAtLeastOne(solution, HttpVerb.POST, 200, "/primitiveTypes", "OK")
4144
assertHasAtLeastOne(solution, HttpVerb.POST, 200, "/parent", "OK")
4245
assertHasAtLeastOne(solution, HttpVerb.POST, 200, "/items-inline", "OK")
@@ -45,11 +48,10 @@ class DtoReflectiveAssertEMTest: SpringTestBase() {
4548

4649
assertPrimitiveTypeDtoCreated()
4750
assertParentAndChildDtosCreated()
48-
assertAllOfDtoCreated()
4951
assertItemsInlineDtoCreated()
50-
// TODO: Restore when support for ChoiceGene has been added
51-
// assertAnyOfDtoCreated()
52-
// assertOneOfDtoCreated()
52+
assertAllOfDtoCreated()
53+
assertAnyOfDtoCreated()
54+
assertOneOfDtoCreated()
5355
}
5456

5557
private fun assertPrimitiveTypeDtoCreated() {

core/src/main/kotlin/org/evomaster/core/output/dto/GeneToDto.kt

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -61,20 +61,20 @@ class GeneToDto(
6161
/**
6262
* @param gene from which to extract the setter calls
6363
* @param dtoName that will be instantiated for payload
64-
* @param counter to provide uniqueness under the same DTO being used in a single test case
64+
* @param counters to provide uniqueness under the same DTO being used in a single test case
6565
*
6666
* @return a [DtoCall] object that can be written to the test case
6767
*/
68-
fun getDtoCall(gene: Gene, dtoName: String, counter: MutableList<Int>, capitalize: Boolean): DtoCall {
68+
fun getDtoCall(gene: Gene, dtoName: String, counters: MutableList<Int>, capitalize: Boolean): DtoCall {
6969
return when(gene) {
70-
is ObjectGene -> getObjectDtoCall(gene, dtoName, counter, capitalize)
71-
is ArrayGene<*> -> getArrayDtoCall(gene, dtoName, counter, null, capitalize)
70+
is ObjectGene -> getObjectDtoCall(gene, dtoName, counters)
71+
is ArrayGene<*> -> getArrayDtoCall(gene, dtoName, counters, null, capitalize)
7272
else -> throw RuntimeException("BUG: Gene $gene (with type ${this::class.java.simpleName}) should not be creating DTOs")
7373
}
7474
}
7575

76-
private fun getObjectDtoCall(gene: ObjectGene, dtoName: String, counter: MutableList<Int>, capitalize: Boolean): DtoCall {
77-
val dtoVarName = "dto_${dtoName}_${counter.joinToString("_")}"
76+
private fun getObjectDtoCall(gene: ObjectGene, dtoName: String, counters: MutableList<Int>): DtoCall {
77+
val dtoVarName = "dto_${dtoName}_${counters.joinToString("_")}"
7878

7979
val result = mutableListOf<String>()
8080
result.add(dtoOutput.getNewObjectStatement(dtoName, dtoVarName))
@@ -88,13 +88,13 @@ class GeneToDto(
8888
val attributeName = it.name
8989
when (leafGene) {
9090
is ObjectGene -> {
91-
val childDtoCall = getDtoCall(leafGene, getDtoName(leafGene, attributeName, true), counter, true)
91+
val childDtoCall = getDtoCall(leafGene, getDtoName(leafGene, attributeName, true), counters, true)
9292

9393
result.addAll(childDtoCall.objectCalls)
9494
result.add(dtoOutput.getSetterStatement(dtoVarName, attributeName, childDtoCall.varName))
9595
}
9696
is ArrayGene<*> -> {
97-
val childDtoCall = getArrayDtoCall(leafGene, getDtoName(leafGene, attributeName, true), counter, attributeName, true)
97+
val childDtoCall = getArrayDtoCall(leafGene, getDtoName(leafGene, attributeName, true), counters, attributeName, true)
9898

9999
result.addAll(childDtoCall.objectCalls)
100100
result.add(dtoOutput.getSetterStatement(dtoVarName, attributeName, childDtoCall.varName))
@@ -108,20 +108,20 @@ class GeneToDto(
108108
return DtoCall(dtoVarName, result)
109109
}
110110

111-
private fun getArrayDtoCall(gene: ArrayGene<*>, dtoName: String, counter: MutableList<Int>, targetAttribute: String?, capitalize: Boolean): DtoCall {
111+
private fun getArrayDtoCall(gene: ArrayGene<*>, dtoName: String, counters: MutableList<Int>, targetAttribute: String?, capitalize: Boolean): DtoCall {
112112
val result = mutableListOf<String>()
113113
val template = gene.template
114114

115115
val listType = getListType(dtoName,template, capitalize)
116-
val listVarName = "list_${targetAttribute?:dtoName}_${counter.joinToString("_")}"
116+
val listVarName = "list_${targetAttribute?:dtoName}_${counters.joinToString("_")}"
117117
result.add(dtoOutput.getNewListStatement(listType, listVarName))
118118

119119
if (template is ObjectGene) {
120120
val childDtoName = template.refType?: if (capitalize) StringUtils.capitalization(dtoName) else dtoName
121121
var listCounter = 1
122122
gene.getViewOfElements().forEach {
123123
val childCounter = mutableListOf<Int>()
124-
childCounter.addAll(counter)
124+
childCounter.addAll(counters)
125125
childCounter.add(listCounter++)
126126
val childDtoCall = getDtoCall(it,childDtoName, childCounter, true)
127127
result.addAll(childDtoCall.objectCalls)

core/src/main/kotlin/org/evomaster/core/output/service/HttpWsTestCaseWriter.kt

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -129,10 +129,20 @@ abstract class HttpWsTestCaseWriter : ApiTestCaseWriter() {
129129
if (choiceGene != null) {
130130
// TODO add support for payloads from choice genes
131131
if (hasObjectOrArrayGene(choiceGene)) {
132-
// this because when using `example` and `default` entries, "primitive" genes are represented as ChoiceGene with
133-
// an EnumGene and the actual String/Integer/Number/etc gene
134-
throw IllegalStateException("Choice genes not yet supported for dto payload")
132+
val geneToDto = GeneToDto(format)
133+
134+
val dtoName = TestWriterUtils.safeVariableName(actionName)
135+
val dtoCall = geneToDto.getDtoCall(choiceGene.activeGene(), dtoName, mutableListOf(counter++), false)
136+
137+
dtoCall.objectCalls.forEach {
138+
lines.add(it)
139+
}
140+
lines.addEmpty()
141+
return dtoCall.varName
135142
}
143+
// this because when using `example` and `default` entries, "primitive" genes are represented as ChoiceGene with
144+
// an EnumGene and the actual String/Integer/Number/etc gene
145+
throw IllegalStateException("Choice genes not yet supported for dto payload")
136146
} else {
137147
val leafGene = primaryGene.getLeafGene()
138148
if (leafGene is ObjectGene || leafGene is ArrayGene<*>) {

0 commit comments

Comments
 (0)