
software.amazon.smithy.kotlin.codegen.rendering.protocol.HttpProtocolUnitTestGenerator.kt Maven / Gradle / Ivy
/*
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0
*/
package software.amazon.smithy.kotlin.codegen.rendering.protocol
import software.amazon.smithy.codegen.core.SymbolProvider
import software.amazon.smithy.kotlin.codegen.core.KotlinDependency
import software.amazon.smithy.kotlin.codegen.core.KotlinWriter
import software.amazon.smithy.model.Model
import software.amazon.smithy.model.shapes.OperationShape
import software.amazon.smithy.model.shapes.ServiceShape
import software.amazon.smithy.model.traits.IdempotencyTokenTrait
import software.amazon.smithy.protocoltests.traits.HttpMessageTestCase
/**
* Abstract base implementation for protocol test generators to extend in order to generate HttpMessageTestCase
* specific protocol tests.
*
* @param T Specific HttpMessageTestCase the protocol test generator is for.
*/
abstract class HttpProtocolUnitTestGenerator
protected constructor(builder: Builder) {
protected val ctx: ProtocolGenerator.GenerationContext = requireNotNull(builder.ctx) { "protocol generator ctx is required" }
protected val symbolProvider: SymbolProvider = requireNotNull(builder.symbolProvider) { "symbol provider is required" }
protected val model: Model = requireNotNull(builder.model) { "model is required" }
protected val testCases: List = requireNotNull(builder.testCases) { "list of test cases is required" }
protected val operation: OperationShape = requireNotNull(builder.operation) { "operation shape is required" }
protected val writer: KotlinWriter = requireNotNull(builder.writer) { "writer is required" }
protected val serviceShape: ServiceShape = requireNotNull(builder.service) { "service shape is required" }
protected val idempotentFieldsInModel: Boolean by lazy {
operation.input.isPresent &&
model.expectShape(operation.input.get()).members().any { it.hasTrait(IdempotencyTokenTrait.ID.name) }
}
/**
* Render a test class and unit tests for the specified [testCases]
*/
fun renderTestClass(testClassName: String) {
writer.addImport(KotlinDependency.KOTLIN_TEST.namespace, "Test")
writer.write("")
.openBlock("class $testClassName {")
.call {
for (test in testCases) {
renderTestFunction(test)
}
}
.closeBlock("}")
}
protected open fun openTestFunctionBlock(): String = "{"
/**
* Write a single unit test function using the given [writer]
*/
private fun renderTestFunction(test: T) {
test.documentation.ifPresent {
writer.dokka(it)
}
writer.write("@Test")
.openBlock("fun `${test.id}`() ${openTestFunctionBlock()}")
.call { renderTestBody(test) }
.closeBlock("}")
}
/**
* Render the body of a unit test
*/
protected abstract fun renderTestBody(test: T)
abstract class Builder {
var ctx: ProtocolGenerator.GenerationContext? = null
var symbolProvider: SymbolProvider? = null
var model: Model? = null
var testCases: List? = null
var operation: OperationShape? = null
var writer: KotlinWriter? = null
var service: ServiceShape? = null
fun ctx(ctx: ProtocolGenerator.GenerationContext): Builder = apply { this.ctx = ctx }
fun symbolProvider(provider: SymbolProvider): Builder = apply { this.symbolProvider = provider }
fun model(model: Model): Builder = apply { this.model = model }
fun testCases(testCases: List): Builder = apply { this.testCases = testCases }
fun operation(operation: OperationShape): Builder = apply { this.operation = operation }
fun writer(writer: KotlinWriter): Builder = apply { this.writer = writer }
fun service(service: ServiceShape): Builder = apply { this.service = service }
abstract fun build(): HttpProtocolUnitTestGenerator
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy