Skip to content

Commit 9e1a8d6

Browse files
authored
fix: correctly deserialize/render input values for smoke tests (#1181)
1 parent 1d3028e commit 9e1a8d6

File tree

4 files changed

+40
-107
lines changed

4 files changed

+40
-107
lines changed

codegen/smithy-kotlin-codegen/src/main/kotlin/software/amazon/smithy/kotlin/codegen/rendering/ShapeValueGenerator.kt

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ class ShapeValueGenerator(
7878
private fun classDeclaration(writer: KotlinWriter, shape: StructureShape, block: () -> Unit) {
7979
val symbol = symbolProvider.toSymbol(shape)
8080
// invoke the generated DSL builder for the class
81-
writer.writeInline("#L {", symbol.name)
81+
writer.writeInline("#T {", symbol)
8282
.ensureNewline()
8383
.indent()
8484
.call { block() }
@@ -129,7 +129,7 @@ class ShapeValueGenerator(
129129
val suffix = when {
130130
shape.isEnum -> {
131131
val symbol = symbolProvider.toSymbol(shape)
132-
writer.writeInline("#L.fromValue(", symbol.name)
132+
writer.writeInline("#T.fromValue(", symbol)
133133
")"
134134
}
135135

@@ -222,7 +222,7 @@ class ShapeValueGenerator(
222222
val currSymbol = generator.symbolProvider.toSymbol(currShape)
223223
val memberName = generator.symbolProvider.toMemberName(member)
224224
val variantName = memberName.replaceFirstChar { c -> c.uppercaseChar() }
225-
writer.writeInline("${currSymbol.name}.$variantName(")
225+
writer.writeInline("#T.#L(", currSymbol, variantName)
226226
generator.instantiateShapeInline(writer, memberShape, valueNode)
227227
writer.writeInline(")")
228228
}
@@ -243,14 +243,14 @@ class ShapeValueGenerator(
243243
ShapeType.DOUBLE,
244244
ShapeType.FLOAT,
245245
-> {
246-
val symbolName = generator.symbolProvider.toSymbol(currShape).name
246+
val symbol = generator.symbolProvider.toSymbol(currShape)
247247
val symbolMember = when (node.value) {
248248
"Infinity" -> "POSITIVE_INFINITY"
249249
"-Infinity" -> "NEGATIVE_INFINITY"
250250
"NaN" -> "NaN"
251-
else -> throw CodegenException("""Cannot interpret $symbolName value "${node.value}".""")
251+
else -> throw CodegenException("""Cannot interpret $symbol value "${node.value}".""")
252252
}
253-
writer.writeInline("#L", "$symbolName.$symbolMember")
253+
writer.writeInline("#T.#L", symbol, symbolMember)
254254
}
255255

256256
ShapeType.BIG_INTEGER -> writer.writeInline("#T(#S)", RuntimeTypes.Core.Content.BigInteger, node.value)

codegen/smithy-kotlin-codegen/src/main/kotlin/software/amazon/smithy/kotlin/codegen/rendering/smoketests/SmokeTestsRunnerGenerator.kt

Lines changed: 24 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -6,18 +6,16 @@ import software.amazon.smithy.kotlin.codegen.integration.SectionId
66
import software.amazon.smithy.kotlin.codegen.integration.SectionKey
77
import software.amazon.smithy.kotlin.codegen.model.getTrait
88
import software.amazon.smithy.kotlin.codegen.model.hasTrait
9-
import software.amazon.smithy.kotlin.codegen.model.isStringEnumShape
9+
import software.amazon.smithy.kotlin.codegen.rendering.ShapeValueGenerator
1010
import software.amazon.smithy.kotlin.codegen.rendering.endpoints.EndpointParametersGenerator
1111
import software.amazon.smithy.kotlin.codegen.rendering.endpoints.EndpointProviderGenerator
12-
import software.amazon.smithy.kotlin.codegen.rendering.protocol.stringToNumber
1312
import software.amazon.smithy.kotlin.codegen.rendering.smoketests.SmokeTestSectionIds.ClientConfig.EndpointParams
1413
import software.amazon.smithy.kotlin.codegen.rendering.smoketests.SmokeTestSectionIds.ClientConfig.EndpointProvider
1514
import software.amazon.smithy.kotlin.codegen.rendering.smoketests.SmokeTestSectionIds.ClientConfig.Name
1615
import software.amazon.smithy.kotlin.codegen.rendering.smoketests.SmokeTestSectionIds.ClientConfig.Value
1716
import software.amazon.smithy.kotlin.codegen.rendering.util.format
1817
import software.amazon.smithy.kotlin.codegen.utils.dq
1918
import software.amazon.smithy.kotlin.codegen.utils.toCamelCase
20-
import software.amazon.smithy.kotlin.codegen.utils.toPascalCase
2119
import software.amazon.smithy.kotlin.codegen.utils.topDownOperations
2220
import software.amazon.smithy.model.node.*
2321
import software.amazon.smithy.model.shapes.*
@@ -134,18 +132,19 @@ class SmokeTestsRunnerGenerator(
134132
}
135133
write("")
136134
withInlineBlock("try {", "} ") {
137-
renderClient(testCase)
138-
renderOperation(operation, testCase)
135+
renderTestCase(operation, testCase)
139136
}
140137
withBlock("catch (exception: Exception) {", "}") {
141138
renderCatchBlock(testCase)
142139
}
143140
}
144141
}
145142

146-
private fun renderClient(testCase: SmokeTestCase) {
147-
writer.withInlineBlock("#L {", "}", service) {
143+
private fun renderTestCase(operation: OperationShape, testCase: SmokeTestCase) {
144+
writer.withBlock("#T {", "}", service) {
148145
renderClientConfig(testCase)
146+
closeAndOpenBlock("}.#T { client ->", RuntimeTypes.Core.IO.use)
147+
renderOperation(operation, testCase)
149148
}
150149
}
151150

@@ -161,10 +160,8 @@ class SmokeTestsRunnerGenerator(
161160
return
162161
}
163162

164-
testCase.clientConfig!!.forEach { config ->
165-
val name = config.key.value.toCamelCase()
166-
val value = config.value.format()
167-
163+
testCase.clientConfig.forEach { (name, unformattedValue) ->
164+
val value = unformattedValue.format()
168165
writer.declareSection(
169166
SmokeTestSectionIds.ClientConfig,
170167
mapOf(
@@ -174,33 +171,23 @@ class SmokeTestsRunnerGenerator(
174171
EndpointParams to EndpointParametersGenerator.getSymbol(settings),
175172
),
176173
) {
177-
writer.writeInline("#L = #L", name, value)
174+
writer.write("#L = #L", name, value)
178175
}
179176
}
180177
}
181178

182179
private fun renderOperation(operation: OperationShape, testCase: SmokeTestCase) {
183-
val operationSymbol = symbolProvider.toSymbol(model.getShape(operation.input.get()).get())
184-
185-
writer.withBlock(".#T { client ->", "}", RuntimeTypes.Core.IO.use) {
186-
withBlock("client.#L(", ")", operation.defaultName()) {
187-
withBlock("#L {", "}", operationSymbol) {
188-
renderOperationParameters(operation, testCase)
189-
}
190-
}
191-
}
192-
}
193-
194-
private fun renderOperationParameters(operation: OperationShape, testCase: SmokeTestCase) {
195-
if (!testCase.hasOperationParameters) return
180+
val inputParams = testCase.params.getOrNull()
196181

197-
val paramsToShapes = mapOperationParametersToModeledShapes(operation)
182+
writer.writeInline("client.#L", operation.defaultName())
198183

199-
testCase.operationParameters.forEach { param ->
200-
val paramName = param.key.value.toCamelCase()
201-
writer.writeInline("#L = ", paramName)
202-
val paramShape = paramsToShapes[paramName] ?: throw IllegalArgumentException("Unable to find shape for operation parameter '$paramName' in smoke test '${testCase.functionName}'.")
203-
renderOperationParameter(paramName, param.value, paramShape, testCase)
184+
if (inputParams == null) {
185+
writer.write("()")
186+
} else {
187+
writer.withBlock("(", ")") {
188+
val inputShape = model.expectShape(operation.input.get())
189+
ShapeValueGenerator(model, symbolProvider).instantiateShapeInline(writer, inputShape, inputParams)
190+
}
204191
}
205192
}
206193

@@ -228,56 +215,6 @@ class SmokeTestsRunnerGenerator(
228215
}
229216

230217
// Helpers
231-
/**
232-
* Renders a [SmokeTestCase] operation parameter
233-
*/
234-
private fun renderOperationParameter(
235-
paramName: String,
236-
node: Node,
237-
shape: Shape,
238-
testCase: SmokeTestCase,
239-
) {
240-
when {
241-
// String enum
242-
node is StringNode && shape.isStringEnumShape -> {
243-
val enumSymbol = symbolProvider.toSymbol(shape)
244-
val enumValue = node.value.toPascalCase()
245-
writer.write("#T.#L", enumSymbol, enumValue)
246-
}
247-
// Int enum
248-
node is NumberNode && shape is IntEnumShape -> {
249-
val enumSymbol = symbolProvider.toSymbol(shape)
250-
val enumValue = node.format()
251-
writer.write("#T.fromValue(#L.toInt())", enumSymbol, enumValue)
252-
}
253-
// Number
254-
node is NumberNode && shape is NumberShape -> writer.write("#L.#L", node.format(), stringToNumber(shape))
255-
// Object
256-
node is ObjectNode -> {
257-
val shapeSymbol = symbolProvider.toSymbol(shape)
258-
writer.withBlock("#T {", "}", shapeSymbol) {
259-
node.members.forEach { member ->
260-
val memberName = member.key.value.toCamelCase()
261-
val memberShape = shape.allMembers[member.key.value] ?: throw IllegalArgumentException("Unable to find shape for operation parameter '$paramName' in smoke test '${testCase.functionName}'.")
262-
writer.writeInline("#L = ", memberName)
263-
renderOperationParameter(memberName, member.value, memberShape, testCase)
264-
}
265-
}
266-
}
267-
// List
268-
node is ArrayNode && shape is CollectionShape -> {
269-
writer.withBlock("listOf(", ")") {
270-
node.elements.forEach { element ->
271-
renderOperationParameter(paramName, element, model.expectShape(shape.member.target), testCase)
272-
writer.write(",")
273-
}
274-
}
275-
}
276-
// Everything else
277-
else -> writer.write("#L", node.format())
278-
}
279-
}
280-
281218
/**
282219
* Tries to get the specific exception required in the failure criterion of a test.
283220
* If no specific exception is required we default to the generic smoke tests failure exception.
@@ -304,14 +241,6 @@ class SmokeTestsRunnerGenerator(
304241
writer.write("println(#S)", testResult)
305242
}
306243

307-
/**
308-
* Maps an operations parameters to their shapes
309-
*/
310-
private fun mapOperationParametersToModeledShapes(operation: OperationShape): Map<String, Shape> =
311-
model.getShape(operation.inputShape).get().allMembers.map { (key, value) ->
312-
key.toCamelCase() to model.getShape(value.target).get()
313-
}.toMap()
314-
315244
/**
316245
* Derives a function name for a [SmokeTestCase]
317246
*/
@@ -345,8 +274,12 @@ class SmokeTestsRunnerGenerator(
345274
/**
346275
* Get the client configuration required for a [SmokeTestCase]
347276
*/
348-
private val SmokeTestCase.clientConfig: MutableMap<StringNode, Node>?
349-
get() = this.vendorParams.get().members
277+
private val SmokeTestCase.clientConfig: Map<String, Node>
278+
get() = vendorParams
279+
.getOrNull()
280+
?.members
281+
?.mapKeys { (key, _) -> key.value }
282+
.orEmpty()
350283

351284
// Constants
352285
private val model = ctx.model

codegen/smithy-kotlin-codegen/src/main/resources/META-INF/services/software.amazon.smithy.kotlin.codegen.integration.KotlinIntegration

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,4 +12,4 @@ software.amazon.smithy.kotlin.codegen.rendering.endpoints.discovery.EndpointDisc
1212
software.amazon.smithy.kotlin.codegen.rendering.endpoints.SdkEndpointBuiltinIntegration
1313
software.amazon.smithy.kotlin.codegen.rendering.compression.RequestCompressionIntegration
1414
software.amazon.smithy.kotlin.codegen.rendering.auth.SigV4AsymmetricAuthSchemeIntegration
15-
# software.amazon.smithy.kotlin.codegen.rendering.smoketests.SmokeTestsIntegration
15+
software.amazon.smithy.kotlin.codegen.rendering.smoketests.SmokeTestsIntegration

codegen/smithy-kotlin-codegen/src/test/kotlin/software/amazon/smithy/kotlin/codegen/rendering/smoketests/SmokeTestsRunnerGeneratorTest.kt

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,8 @@ class SmokeTestsRunnerGeneratorTest {
3030
}
3131
vendorParamsShape: AwsVendorParams,
3232
vendorParams: {
33-
region: "eu-central-1"
33+
region: "eu-central-1",
34+
uri: "https://foo.amazon.com"
3435
}
3536
}
3637
{
@@ -106,12 +107,13 @@ class SmokeTestsRunnerGeneratorTest {
106107
}
107108
108109
try {
109-
com.test.TestClient {
110+
TestClient {
110111
interceptors.add(SmokeTestsInterceptor())
111112
region = "eu-central-1"
113+
uri = "https://foo.amazon.com"
112114
}.use { client ->
113115
client.testOperation(
114-
com.test.model.TestOperationRequest {
116+
TestOperationRequest {
115117
bar = "2"
116118
}
117119
)
@@ -143,11 +145,10 @@ class SmokeTestsRunnerGeneratorTest {
143145
}
144146
145147
try {
146-
com.test.TestClient {
147-
148+
TestClient {
148149
}.use { client ->
149150
client.testOperation(
150-
com.test.model.TestOperationRequest {
151+
TestOperationRequest {
151152
bar = "föö"
152153
}
153154
)
@@ -179,12 +180,11 @@ class SmokeTestsRunnerGeneratorTest {
179180
}
180181
181182
try {
182-
com.test.TestClient {
183+
TestClient {
183184
interceptors.add(SmokeTestsInterceptor())
184-
185185
}.use { client ->
186186
client.testOperation(
187-
com.test.model.TestOperationRequest {
187+
TestOperationRequest {
188188
bar = "föö"
189189
}
190190
)

0 commit comments

Comments
 (0)