From c31ed4418fbd12634985aa37c8009c7e60984623 Mon Sep 17 00:00:00 2001 From: david-perez Date: Fri, 28 Jun 2024 17:53:04 +0200 Subject: [PATCH 1/2] Improve broken protocol test case generation We currently "hotfix" a broken protocol test in-memory, but there's no mechanism that alerts us when the broken protocol test has been fixed upstream when updating our Smithy version. This commit introduces such a mechanism by generating both the original and the fixed test, with a `#[should_panic]` attribute on the former, so that the test fails when all its assertions succeed. With this change, in general this approach of fixing tests in-memory should now be used over adding the broken test to `expectFail` and adding the fixed test to a `-extras.smithy` Smithy model, which is substantially more effort. --- .../protocol/ClientProtocolTestGenerator.kt | 10 +- .../protocol/ProtocolTestGenerator.kt | 212 ++++++++++++++++-- .../protocol/ServerProtocolTestGenerator.kt | 201 ++++++++--------- 3 files changed, 289 insertions(+), 134 deletions(-) diff --git a/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/protocol/ClientProtocolTestGenerator.kt b/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/protocol/ClientProtocolTestGenerator.kt index 24c5fa5d67..8cfb496023 100644 --- a/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/protocol/ClientProtocolTestGenerator.kt +++ b/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/protocol/ClientProtocolTestGenerator.kt @@ -23,12 +23,12 @@ import software.amazon.smithy.rust.codegen.core.rustlang.rust import software.amazon.smithy.rust.codegen.core.rustlang.rustBlock import software.amazon.smithy.rust.codegen.core.rustlang.rustTemplate import software.amazon.smithy.rust.codegen.core.rustlang.writable +import software.amazon.smithy.rust.codegen.core.smithy.generators.protocol.BrokenTest import software.amazon.smithy.rust.codegen.core.smithy.generators.protocol.FailingTest import software.amazon.smithy.rust.codegen.core.smithy.generators.protocol.ProtocolSupport import software.amazon.smithy.rust.codegen.core.smithy.generators.protocol.ProtocolTestGenerator import software.amazon.smithy.rust.codegen.core.smithy.generators.protocol.ServiceShapeId.AWS_JSON_10 import software.amazon.smithy.rust.codegen.core.smithy.generators.protocol.TestCase -import software.amazon.smithy.rust.codegen.core.smithy.generators.protocol.TestCaseKind import software.amazon.smithy.rust.codegen.core.util.PANIC import software.amazon.smithy.rust.codegen.core.util.dq import software.amazon.smithy.rust.codegen.core.util.hasTrait @@ -70,9 +70,9 @@ class ClientProtocolTestGenerator( private val ExpectFail = setOf( // Failing because we don't serialize default values if they match the default. - FailingTest(AWS_JSON_10, "AwsJson10ClientPopulatesDefaultsValuesWhenMissingInResponse", TestCaseKind.Request), - FailingTest(AWS_JSON_10, "AwsJson10ClientUsesExplicitlyProvidedMemberValuesOverDefaults", TestCaseKind.Request), - FailingTest(AWS_JSON_10, "AwsJson10ClientPopulatesDefaultValuesInInput", TestCaseKind.Request), + FailingTest.RequestTest(AWS_JSON_10, "AwsJson10ClientPopulatesDefaultsValuesWhenMissingInResponse"), + FailingTest.RequestTest(AWS_JSON_10, "AwsJson10ClientUsesExplicitlyProvidedMemberValuesOverDefaults"), + FailingTest.RequestTest(AWS_JSON_10, "AwsJson10ClientPopulatesDefaultValuesInInput"), ) } @@ -84,6 +84,8 @@ class ClientProtocolTestGenerator( get() = emptySet() override val disabledTests: Set get() = emptySet() + override val brokenTests: Set + get() = emptySet() override val logger: Logger = Logger.getLogger(javaClass.name) diff --git a/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/generators/protocol/ProtocolTestGenerator.kt b/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/generators/protocol/ProtocolTestGenerator.kt index 2202063a56..45fdbc1ac9 100644 --- a/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/generators/protocol/ProtocolTestGenerator.kt +++ b/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/generators/protocol/ProtocolTestGenerator.kt @@ -31,6 +31,7 @@ import software.amazon.smithy.rust.codegen.core.rustlang.withBlock import software.amazon.smithy.rust.codegen.core.smithy.CodegenContext import software.amazon.smithy.rust.codegen.core.smithy.RuntimeType import software.amazon.smithy.rust.codegen.core.testutil.testDependenciesOnly +import software.amazon.smithy.rust.codegen.core.util.PANIC import software.amazon.smithy.rust.codegen.core.util.dq import software.amazon.smithy.rust.codegen.core.util.getTrait import software.amazon.smithy.rust.codegen.core.util.orNull @@ -51,9 +52,17 @@ abstract class ProtocolTestGenerator { /** * We expect these tests to fail due to shortcomings in our implementation. * They will _fail_ if they pass, so we will discover and remove them if we fix them by accident. - **/ + */ abstract val expectFail: Set + /** + * We expect these tests to fail because their definitions are broken. + * We map from a failing test to a "hotfix" function that can mutate the test in-memory and return a fixed version of it. + * The tests will _fail_ if they pass, so we will discover and remove the hotfix if we're updating to a newer + * version of Smithy where the test was fixed upstream. + */ + abstract val brokenTests: Set + /** Only generate these tests; useful to temporarily set and shorten development cycles */ abstract val runOnly: Set @@ -63,18 +72,22 @@ abstract class ProtocolTestGenerator { */ abstract val disabledTests: Set + private val serviceShapeId: ShapeId + get() = codegenContext.serviceShape.id + /** The Rust module in which we should generate the protocol tests for [operationShape]. */ private fun protocolTestsModule(): RustModule.LeafModule { val operationName = codegenContext.symbolProvider.toSymbol(operationShape).name val testModuleName = "${operationName.toSnakeCase()}_test" - val additionalAttributes = - listOf(Attribute(allow("unreachable_code", "unused_variables"))) + val additionalAttributes = listOf(Attribute(allow("unreachable_code", "unused_variables"))) return RustModule.inlineTests(testModuleName, additionalAttributes = additionalAttributes) } /** The entry point to render the protocol tests, invoked by the code generators. */ fun render(writer: RustWriter) { - val allTests = allMatchingTestCases().fixBroken() + val allTests = allMatchingTestCases().flatMap { + fixBrokenTestCase(it) + } if (allTests.isEmpty()) { return } @@ -84,15 +97,60 @@ abstract class ProtocolTestGenerator { } } - /** Implementors should describe how to render the test cases. **/ - abstract fun RustWriter.renderAllTestCases(allTests: List) - /** - * This function applies a "fix function" to each broken test before we synthesize it. - * Broken tests are those whose definitions in the `awslabs/smithy` repository are wrong. - * We try to contribute fixes upstream to pare down this function to the identity function. + * This function applies a "hotfix function" to a broken test case before we synthesize it. + * Broken tests are those whose definitions in the `smithy-lang/smithy` repository are wrong. + * We try to contribute fixes upstream to pare down the list of broken tests. + * If the test is broken, we synthesize it in two versions: the original broken test with a `#[should_panic]` + * attribute, so get alerted if the test now passes, and the fixed version, which should pass. */ - open fun List.fixBroken(): List = this + private fun fixBrokenTestCase(it: TestCase): List = if (!it.isBroken()) { + listOf(it) + } else { + assert(it.expectFail()) + + val brokenTest = it.findInBroken()!! + var fixed = brokenTest.fixIt(it) + + val intro = "The hotfix function for broken test case ${it.kind} ${it.id}" + val moreInfo = + """This test case was identified to be broken in at least these Smithy versions: [${brokenTest.inAtLeast.joinToString()}]. + |We are tracking things here: [${brokenTest.trackedIn.joinToString()}].""".trimMargin() + + // Something must change... + if (it == fixed) { + PANIC( + """$intro did not make any modifications. It is likely that the test case was + |fixed upstream, and you're now updating the Smithy version; in this case, remove the hotfix + |function, as the test is no longer broken. + |$moreInfo""".trimMargin(), + ) + } + + // ... but the hotfix function is not allowed to change the test case kind... + if (it.kind != fixed.kind) { + PANIC( + """$intro changed the test case kind. This is not allowed. + |$moreInfo""".trimMargin(), + ) + } + + // ... nor its id. + if (it.id != fixed.id) { + PANIC( + """$intro changed the test case id. This is not allowed. + |$moreInfo""".trimMargin(), + ) + } + + // The latter is because we're going to generate the fixed version with an identifiable suffix. + fixed = fixed.suffixIdWith("_hotfixed") + + listOf(it, fixed) + } + + /** Implementors should describe how to render the test cases. **/ + abstract fun RustWriter.renderAllTestCases(allTests: List) /** Filter out test cases that are disabled or don't match the service protocol. */ private fun List.filterMatching(): List = @@ -103,11 +161,23 @@ abstract class ProtocolTestGenerator { this.filter { testCase -> runOnly.contains(testCase.id) } } - /** Do we expect this [testCase] to fail? */ - private fun expectFail(testCase: TestCase): Boolean = - expectFail.find { - it.id == testCase.id && it.kind == testCase.kind && it.service == codegenContext.serviceShape.id.toString() - } != null + private fun TestCase.toFailingTest(): FailingTest = when (this) { + is TestCase.MalformedRequestTest -> FailingTest.MalformedRequestTest(serviceShapeId.toString(), this.id) + is TestCase.RequestTest -> FailingTest.RequestTest(serviceShapeId.toString(), this.id) + is TestCase.ResponseTest -> FailingTest.ResponseTest(serviceShapeId.toString(), this.id) + } + + /** Do we expect this test case to fail? */ + private fun TestCase.expectFail(): Boolean = this.isBroken() || expectFail.contains(this.toFailingTest()) + + /** Is this test case broken? */ + private fun TestCase.isBroken(): Boolean = this.findInBroken() != null + + private fun TestCase.findInBroken(): BrokenTest? = brokenTests.find { brokenTest -> + (this is TestCase.RequestTest && brokenTest is BrokenTest.RequestTest && this.id == brokenTest.id) || + (this is TestCase.ResponseTest && brokenTest is BrokenTest.ResponseTest && this.id == brokenTest.id) || + (this is TestCase.MalformedRequestTest && brokenTest is BrokenTest.MalformedRequestTest && this.id == brokenTest.id) + } fun requestTestCases(): List { val requestTests = @@ -160,6 +230,7 @@ abstract class ProtocolTestGenerator { block: Writable, ) { if (testCase.documentation != null) { + testModuleWriter.rust("") testModuleWriter.docs(testCase.documentation!!, templating = false) } testModuleWriter.docs("Test ID: ${testCase.id}") @@ -171,7 +242,7 @@ abstract class ProtocolTestGenerator { Attribute.TokioTest.render(testModuleWriter) Attribute.TracedTest.render(testModuleWriter) - if (expectFail(testCase)) { + if (testCase.expectFail()) { shouldPanic().render(testModuleWriter) } val fnNameSuffix = @@ -281,6 +352,52 @@ abstract class ProtocolTestGenerator { } } +sealed class BrokenTest( + open val serviceShapeId: String, + open val id: String, + + /** A non-exhaustive set of Smithy versions where the test was found to be broken. */ + open val inAtLeast: Set, + /** + * GitHub URLs related to the test brokenness, like a GitHub issue in Smithy where we reported the test was broken, + * or a PR where we fixed it. + **/ + open val trackedIn: Set +) { + data class RequestTest( + override val serviceShapeId: String, + override val id: String, + override val inAtLeast: Set, + override val trackedIn: Set, + val howToFixItFn: (TestCase.RequestTest) -> TestCase.RequestTest, + ) : BrokenTest(serviceShapeId, id, inAtLeast, trackedIn) + + data class ResponseTest( + override val serviceShapeId: String, + override val id: String, + override val inAtLeast: Set, + override val trackedIn: Set, + val howToFixItFn: (TestCase.ResponseTest) -> TestCase.ResponseTest, + ) : BrokenTest(serviceShapeId, id, inAtLeast, trackedIn) + + data class MalformedRequestTest( + override val serviceShapeId: String, + override val id: String, + override val inAtLeast: Set, + override val trackedIn: Set, + val howToFixItFn: (TestCase.MalformedRequestTest) -> TestCase.MalformedRequestTest, + ) : BrokenTest(serviceShapeId, id, inAtLeast, trackedIn) + + fun fixIt(testToFix: TestCase): TestCase { + check(testToFix.id == this.id) + return when (this) { + is MalformedRequestTest -> howToFixItFn(testToFix as TestCase.MalformedRequestTest) + is RequestTest -> howToFixItFn(testToFix as TestCase.RequestTest) + is ResponseTest -> howToFixItFn(testToFix as TestCase.ResponseTest) + } + } +} + /** * Service shape IDs in common protocol test suites defined upstream. */ @@ -291,7 +408,14 @@ object ServiceShapeId { const val REST_JSON_VALIDATION = "aws.protocoltests.restjson.validation#RestJsonValidation" } -data class FailingTest(val service: String, val id: String, val kind: TestCaseKind) +sealed class FailingTest(open val serviceShapeId: String, open val id: String) { + data class RequestTest(override val serviceShapeId: String, override val id: String) : + FailingTest(serviceShapeId, id) + data class ResponseTest(override val serviceShapeId: String, override val id: String) : + FailingTest(serviceShapeId, id) + data class MalformedRequestTest(override val serviceShapeId: String, override val id: String) : + FailingTest(serviceShapeId, id) +} sealed class TestCaseKind { data object Request : TestCaseKind() @@ -302,11 +426,57 @@ sealed class TestCaseKind { } sealed class TestCase { - data class RequestTest(val testCase: HttpRequestTestCase) : TestCase() + /* + * The properties of these data classes don't implement `equals()` usefully in Smithy, so we delegate to `equals()` + * of their `Node` representations. + */ + + data class RequestTest(val testCase: HttpRequestTestCase) : TestCase() { + override fun equals(other: Any?): Boolean { + if (this === other) return true + if (other !is RequestTest) return false + return testCase.toNode().equals(other.testCase.toNode()) + } + + override fun hashCode(): Int = testCase.hashCode() + } + + data class ResponseTest(val testCase: HttpResponseTestCase, val targetShape: StructureShape) : TestCase() { + override fun equals(other: Any?): Boolean { + if (this === other) return true + if (other !is ResponseTest) return false + return testCase.toNode().equals(other.testCase.toNode()) + } + + override fun hashCode(): Int = testCase.hashCode() + } + + data class MalformedRequestTest(val testCase: HttpMalformedRequestTestCase) : TestCase() { + override fun equals(other: Any?): Boolean { + if (this === other) return true + if (other !is MalformedRequestTest) return false + return this.protocol == other.protocol && this.id == other.id && this.documentation == other.documentation && this.testCase.request.toNode() + .equals(other.testCase.request.toNode()) && this.testCase.response.toNode() + .equals(other.testCase.response.toNode()) + } + + override fun hashCode(): Int = testCase.hashCode() + } + + fun suffixIdWith(suffix: String): TestCase = when (this) { + is RequestTest -> RequestTest(this.testCase.suffixIdWith(suffix)) + is MalformedRequestTest -> MalformedRequestTest(this.testCase.suffixIdWith(suffix)) + is ResponseTest -> ResponseTest(this.testCase.suffixIdWith(suffix), this.targetShape) + } + + private fun HttpRequestTestCase.suffixIdWith(suffix: String): HttpRequestTestCase = + this.toBuilder().id(this.id + suffix).build() - data class ResponseTest(val testCase: HttpResponseTestCase, val targetShape: StructureShape) : TestCase() + private fun HttpResponseTestCase.suffixIdWith(suffix: String): HttpResponseTestCase = + this.toBuilder().id(this.id + suffix).build() - data class MalformedRequestTest(val testCase: HttpMalformedRequestTestCase) : TestCase() + private fun HttpMalformedRequestTestCase.suffixIdWith(suffix: String): HttpMalformedRequestTestCase = + this.toBuilder().id(this.id + suffix).build() /* * `HttpRequestTestCase` and `HttpResponseTestCase` both implement `HttpMessageTestCase`, but diff --git a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/protocol/ServerProtocolTestGenerator.kt b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/protocol/ServerProtocolTestGenerator.kt index 194fa3eb2c..453a8605af 100644 --- a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/protocol/ServerProtocolTestGenerator.kt +++ b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/protocol/ServerProtocolTestGenerator.kt @@ -30,6 +30,7 @@ import software.amazon.smithy.rust.codegen.core.rustlang.withBlock import software.amazon.smithy.rust.codegen.core.rustlang.writable import software.amazon.smithy.rust.codegen.core.smithy.CodegenContext import software.amazon.smithy.rust.codegen.core.smithy.RuntimeType +import software.amazon.smithy.rust.codegen.core.smithy.generators.protocol.BrokenTest import software.amazon.smithy.rust.codegen.core.smithy.generators.protocol.FailingTest import software.amazon.smithy.rust.codegen.core.smithy.generators.protocol.ProtocolSupport import software.amazon.smithy.rust.codegen.core.smithy.generators.protocol.ProtocolTestGenerator @@ -38,7 +39,6 @@ import software.amazon.smithy.rust.codegen.core.smithy.generators.protocol.Servi import software.amazon.smithy.rust.codegen.core.smithy.generators.protocol.ServiceShapeId.REST_JSON import software.amazon.smithy.rust.codegen.core.smithy.generators.protocol.ServiceShapeId.REST_JSON_VALIDATION import software.amazon.smithy.rust.codegen.core.smithy.generators.protocol.TestCase -import software.amazon.smithy.rust.codegen.core.smithy.generators.protocol.TestCaseKind import software.amazon.smithy.rust.codegen.core.smithy.transformers.allErrors import software.amazon.smithy.rust.codegen.core.util.dq import software.amazon.smithy.rust.codegen.core.util.hasStreamingMember @@ -52,7 +52,6 @@ import software.amazon.smithy.rust.codegen.core.util.toSnakeCase import software.amazon.smithy.rust.codegen.server.smithy.ServerCargoDependency import software.amazon.smithy.rust.codegen.server.smithy.generators.ServerInstantiator import java.util.logging.Logger -import kotlin.reflect.KFunction1 /** * Generate server protocol tests for an [operationShape]. @@ -66,87 +65,105 @@ class ServerProtocolTestGenerator( private val ExpectFail: Set = setOf( // Endpoint trait is not implemented yet, see https://github.com/smithy-lang/smithy-rs/issues/950. - FailingTest(REST_JSON, "RestJsonEndpointTrait", TestCaseKind.Request), - FailingTest(REST_JSON, "RestJsonEndpointTraitWithHostLabel", TestCaseKind.Request), - FailingTest(REST_JSON, "RestJsonOmitsEmptyListQueryValues", TestCaseKind.Request), + FailingTest.RequestTest(REST_JSON, "RestJsonEndpointTrait"), + FailingTest.RequestTest(REST_JSON, "RestJsonEndpointTraitWithHostLabel"), + FailingTest.RequestTest(REST_JSON, "RestJsonOmitsEmptyListQueryValues"), // TODO(https://github.com/smithy-lang/smithy/pull/2315): Can be deleted when fixed tests are consumed in next Smithy version - FailingTest(REST_JSON, "RestJsonEnumPayloadRequest", TestCaseKind.Request), - FailingTest(REST_JSON, "RestJsonStringPayloadRequest", TestCaseKind.Request), + FailingTest.RequestTest(REST_JSON, "RestJsonEnumPayloadRequest"), + FailingTest.RequestTest(REST_JSON, "RestJsonStringPayloadRequest"), // Tests involving `@range` on floats. // Pending resolution from the Smithy team, see https://github.com/smithy-lang/smithy-rs/issues/2007. - FailingTest(REST_JSON_VALIDATION, "RestJsonMalformedRangeFloat_case0", TestCaseKind.MalformedRequest), - FailingTest(REST_JSON_VALIDATION, "RestJsonMalformedRangeFloat_case1", TestCaseKind.MalformedRequest), - FailingTest(REST_JSON_VALIDATION, "RestJsonMalformedRangeMaxFloat", TestCaseKind.MalformedRequest), - FailingTest(REST_JSON_VALIDATION, "RestJsonMalformedRangeMinFloat", TestCaseKind.MalformedRequest), + FailingTest.MalformedRequestTest(REST_JSON_VALIDATION, "RestJsonMalformedRangeFloat_case0"), + FailingTest.MalformedRequestTest(REST_JSON_VALIDATION, "RestJsonMalformedRangeFloat_case1"), + FailingTest.MalformedRequestTest(REST_JSON_VALIDATION, "RestJsonMalformedRangeMaxFloat"), + FailingTest.MalformedRequestTest(REST_JSON_VALIDATION, "RestJsonMalformedRangeMinFloat"), // Tests involving floating point shapes and the `@range` trait; see https://github.com/smithy-lang/smithy-rs/issues/2007 - FailingTest(REST_JSON_VALIDATION, "RestJsonMalformedRangeFloatOverride_case0", TestCaseKind.MalformedRequest), - FailingTest(REST_JSON_VALIDATION, "RestJsonMalformedRangeFloatOverride_case1", TestCaseKind.MalformedRequest), - FailingTest(REST_JSON_VALIDATION, "RestJsonMalformedRangeMaxFloatOverride", TestCaseKind.MalformedRequest), - FailingTest(REST_JSON_VALIDATION, "RestJsonMalformedRangeMinFloatOverride", TestCaseKind.MalformedRequest), + FailingTest.MalformedRequestTest(REST_JSON_VALIDATION, "RestJsonMalformedRangeFloatOverride_case0"), + FailingTest.MalformedRequestTest(REST_JSON_VALIDATION, "RestJsonMalformedRangeFloatOverride_case1"), + FailingTest.MalformedRequestTest(REST_JSON_VALIDATION, "RestJsonMalformedRangeMaxFloatOverride"), + FailingTest.MalformedRequestTest(REST_JSON_VALIDATION, "RestJsonMalformedRangeMinFloatOverride"), // Some tests for the S3 service (restXml). - FailingTest("com.amazonaws.s3#AmazonS3", "GetBucketLocationUnwrappedOutput", TestCaseKind.Response), - FailingTest("com.amazonaws.s3#AmazonS3", "S3DefaultAddressing", TestCaseKind.Request), - FailingTest("com.amazonaws.s3#AmazonS3", "S3VirtualHostAddressing", TestCaseKind.Request), - FailingTest("com.amazonaws.s3#AmazonS3", "S3PathAddressing", TestCaseKind.Request), - FailingTest("com.amazonaws.s3#AmazonS3", "S3VirtualHostDualstackAddressing", TestCaseKind.Request), - FailingTest("com.amazonaws.s3#AmazonS3", "S3VirtualHostAccelerateAddressing", TestCaseKind.Request), - FailingTest("com.amazonaws.s3#AmazonS3", "S3VirtualHostDualstackAccelerateAddressing", TestCaseKind.Request), - FailingTest("com.amazonaws.s3#AmazonS3", "S3OperationAddressingPreferred", TestCaseKind.Request), - FailingTest("com.amazonaws.s3#AmazonS3", "S3OperationNoErrorWrappingResponse", TestCaseKind.Response), + FailingTest.ResponseTest("com.amazonaws.s3#AmazonS3", "GetBucketLocationUnwrappedOutput"), + FailingTest.RequestTest("com.amazonaws.s3#AmazonS3", "S3DefaultAddressing"), + FailingTest.RequestTest("com.amazonaws.s3#AmazonS3", "S3VirtualHostAddressing"), + FailingTest.RequestTest("com.amazonaws.s3#AmazonS3", "S3PathAddressing"), + FailingTest.RequestTest("com.amazonaws.s3#AmazonS3", "S3VirtualHostDualstackAddressing"), + FailingTest.RequestTest("com.amazonaws.s3#AmazonS3", "S3VirtualHostAccelerateAddressing"), + FailingTest.RequestTest("com.amazonaws.s3#AmazonS3", "S3VirtualHostDualstackAccelerateAddressing"), + FailingTest.RequestTest("com.amazonaws.s3#AmazonS3", "S3OperationAddressingPreferred"), + FailingTest.ResponseTest("com.amazonaws.s3#AmazonS3", "S3OperationNoErrorWrappingResponse"), // AwsJson1.0 failing tests. - FailingTest("aws.protocoltests.json10#JsonRpc10", "AwsJson10EndpointTraitWithHostLabel", TestCaseKind.Request), - FailingTest("aws.protocoltests.json10#JsonRpc10", "AwsJson10EndpointTrait", TestCaseKind.Request), + FailingTest.RequestTest("aws.protocoltests.json10#JsonRpc10", "AwsJson10EndpointTraitWithHostLabel"), + FailingTest.RequestTest("aws.protocoltests.json10#JsonRpc10", "AwsJson10EndpointTrait"), // AwsJson1.1 failing tests. - FailingTest(AWS_JSON_11, "AwsJson11EndpointTraitWithHostLabel", TestCaseKind.Request), - FailingTest(AWS_JSON_11, "AwsJson11EndpointTrait", TestCaseKind.Request), - FailingTest(AWS_JSON_11, "parses_the_request_id_from_the_response", TestCaseKind.Response), + FailingTest.RequestTest(AWS_JSON_11, "AwsJson11EndpointTraitWithHostLabel"), + FailingTest.RequestTest(AWS_JSON_11, "AwsJson11EndpointTrait"), + FailingTest.ResponseTest(AWS_JSON_11, "parses_the_request_id_from_the_response"), // TODO(https://github.com/awslabs/smithy/issues/1683): This has been marked as failing until resolution of said issue - FailingTest(REST_JSON_VALIDATION, "RestJsonMalformedUniqueItemsBlobList", TestCaseKind.MalformedRequest), - FailingTest(REST_JSON_VALIDATION, "RestJsonMalformedUniqueItemsBooleanList_case0", TestCaseKind.MalformedRequest), - FailingTest(REST_JSON_VALIDATION, "RestJsonMalformedUniqueItemsBooleanList_case1", TestCaseKind.MalformedRequest), - FailingTest(REST_JSON_VALIDATION, "RestJsonMalformedUniqueItemsStringList", TestCaseKind.MalformedRequest), - FailingTest(REST_JSON_VALIDATION, "RestJsonMalformedUniqueItemsByteList", TestCaseKind.MalformedRequest), - FailingTest(REST_JSON_VALIDATION, "RestJsonMalformedUniqueItemsShortList", TestCaseKind.MalformedRequest), - FailingTest(REST_JSON_VALIDATION, "RestJsonMalformedUniqueItemsIntegerList", TestCaseKind.MalformedRequest), - FailingTest(REST_JSON_VALIDATION, "RestJsonMalformedUniqueItemsLongList", TestCaseKind.MalformedRequest), - FailingTest(REST_JSON_VALIDATION, "RestJsonMalformedUniqueItemsTimestampList", TestCaseKind.MalformedRequest), - FailingTest(REST_JSON_VALIDATION, "RestJsonMalformedUniqueItemsDateTimeList", TestCaseKind.MalformedRequest), - FailingTest( + FailingTest.MalformedRequestTest(REST_JSON_VALIDATION, "RestJsonMalformedUniqueItemsBlobList"), + FailingTest.MalformedRequestTest(REST_JSON_VALIDATION, "RestJsonMalformedUniqueItemsBooleanList_case0"), + FailingTest.MalformedRequestTest(REST_JSON_VALIDATION, "RestJsonMalformedUniqueItemsBooleanList_case1"), + FailingTest.MalformedRequestTest(REST_JSON_VALIDATION, "RestJsonMalformedUniqueItemsStringList"), + FailingTest.MalformedRequestTest(REST_JSON_VALIDATION, "RestJsonMalformedUniqueItemsByteList"), + FailingTest.MalformedRequestTest(REST_JSON_VALIDATION, "RestJsonMalformedUniqueItemsShortList"), + FailingTest.MalformedRequestTest(REST_JSON_VALIDATION, "RestJsonMalformedUniqueItemsIntegerList"), + FailingTest.MalformedRequestTest(REST_JSON_VALIDATION, "RestJsonMalformedUniqueItemsLongList"), + FailingTest.MalformedRequestTest(REST_JSON_VALIDATION, "RestJsonMalformedUniqueItemsTimestampList"), + FailingTest.MalformedRequestTest(REST_JSON_VALIDATION, "RestJsonMalformedUniqueItemsDateTimeList"), + FailingTest.MalformedRequestTest( REST_JSON_VALIDATION, "RestJsonMalformedUniqueItemsHttpDateList_case0", - TestCaseKind.MalformedRequest, ), - FailingTest( + FailingTest.MalformedRequestTest( REST_JSON_VALIDATION, "RestJsonMalformedUniqueItemsHttpDateList_case1", - TestCaseKind.MalformedRequest, ), - FailingTest(REST_JSON_VALIDATION, "RestJsonMalformedUniqueItemsEnumList", TestCaseKind.MalformedRequest), - FailingTest(REST_JSON_VALIDATION, "RestJsonMalformedUniqueItemsIntEnumList", TestCaseKind.MalformedRequest), - FailingTest(REST_JSON_VALIDATION, "RestJsonMalformedUniqueItemsListList", TestCaseKind.MalformedRequest), - FailingTest(REST_JSON_VALIDATION, "RestJsonMalformedUniqueItemsStructureList", TestCaseKind.MalformedRequest), - FailingTest(REST_JSON_VALIDATION, "RestJsonMalformedUniqueItemsUnionList_case0", TestCaseKind.MalformedRequest), - FailingTest(REST_JSON_VALIDATION, "RestJsonMalformedUniqueItemsUnionList_case1", TestCaseKind.MalformedRequest), + FailingTest.MalformedRequestTest(REST_JSON_VALIDATION, "RestJsonMalformedUniqueItemsEnumList"), + FailingTest.MalformedRequestTest(REST_JSON_VALIDATION, "RestJsonMalformedUniqueItemsIntEnumList"), + FailingTest.MalformedRequestTest(REST_JSON_VALIDATION, "RestJsonMalformedUniqueItemsListList"), + FailingTest.MalformedRequestTest(REST_JSON_VALIDATION, "RestJsonMalformedUniqueItemsStructureList"), + FailingTest.MalformedRequestTest(REST_JSON_VALIDATION, "RestJsonMalformedUniqueItemsUnionList_case0"), + FailingTest.MalformedRequestTest(REST_JSON_VALIDATION, "RestJsonMalformedUniqueItemsUnionList_case1"), // TODO(https://github.com/smithy-lang/smithy-rs/issues/2472): We don't respect the `@internal` trait - FailingTest(REST_JSON_VALIDATION, "RestJsonMalformedEnumList_case0", TestCaseKind.MalformedRequest), - FailingTest(REST_JSON_VALIDATION, "RestJsonMalformedEnumList_case1", TestCaseKind.MalformedRequest), - FailingTest(REST_JSON_VALIDATION, "RestJsonMalformedEnumMapKey_case0", TestCaseKind.MalformedRequest), - FailingTest(REST_JSON_VALIDATION, "RestJsonMalformedEnumMapKey_case1", TestCaseKind.MalformedRequest), - FailingTest(REST_JSON_VALIDATION, "RestJsonMalformedEnumMapValue_case0", TestCaseKind.MalformedRequest), - FailingTest(REST_JSON_VALIDATION, "RestJsonMalformedEnumMapValue_case1", TestCaseKind.MalformedRequest), - FailingTest(REST_JSON_VALIDATION, "RestJsonMalformedEnumString_case0", TestCaseKind.MalformedRequest), - FailingTest(REST_JSON_VALIDATION, "RestJsonMalformedEnumString_case1", TestCaseKind.MalformedRequest), - FailingTest(REST_JSON_VALIDATION, "RestJsonMalformedEnumUnion_case0", TestCaseKind.MalformedRequest), - FailingTest(REST_JSON_VALIDATION, "RestJsonMalformedEnumUnion_case1", TestCaseKind.MalformedRequest), + FailingTest.MalformedRequestTest(REST_JSON_VALIDATION, "RestJsonMalformedEnumList_case0"), + FailingTest.MalformedRequestTest(REST_JSON_VALIDATION, "RestJsonMalformedEnumList_case1"), + FailingTest.MalformedRequestTest(REST_JSON_VALIDATION, "RestJsonMalformedEnumMapKey_case0"), + FailingTest.MalformedRequestTest(REST_JSON_VALIDATION, "RestJsonMalformedEnumMapKey_case1"), + FailingTest.MalformedRequestTest(REST_JSON_VALIDATION, "RestJsonMalformedEnumMapValue_case0"), + FailingTest.MalformedRequestTest(REST_JSON_VALIDATION, "RestJsonMalformedEnumMapValue_case1"), + FailingTest.MalformedRequestTest(REST_JSON_VALIDATION, "RestJsonMalformedEnumString_case0"), + FailingTest.MalformedRequestTest(REST_JSON_VALIDATION, "RestJsonMalformedEnumString_case1"), + FailingTest.MalformedRequestTest(REST_JSON_VALIDATION, "RestJsonMalformedEnumUnion_case0"), + FailingTest.MalformedRequestTest(REST_JSON_VALIDATION, "RestJsonMalformedEnumUnion_case1"), // TODO(https://github.com/awslabs/smithy/issues/1737): Specs on @internal, @tags, and enum values need to be clarified - FailingTest(REST_JSON_VALIDATION, "RestJsonMalformedEnumTraitString_case0", TestCaseKind.MalformedRequest), - FailingTest(REST_JSON_VALIDATION, "RestJsonMalformedEnumTraitString_case1", TestCaseKind.MalformedRequest), + FailingTest.MalformedRequestTest(REST_JSON_VALIDATION, "RestJsonMalformedEnumTraitString_case0"), + FailingTest.MalformedRequestTest(REST_JSON_VALIDATION, "RestJsonMalformedEnumTraitString_case1"), // These tests are broken because they are missing a target header. - FailingTest(AWS_JSON_10, "AwsJson10ServerPopulatesNestedDefaultsWhenMissingInRequestBody", TestCaseKind.Request), - FailingTest(AWS_JSON_10, "AwsJson10ServerPopulatesDefaultsWhenMissingInRequestBody", TestCaseKind.Request), + FailingTest.RequestTest(AWS_JSON_10, "AwsJson10ServerPopulatesNestedDefaultsWhenMissingInRequestBody"), + FailingTest.RequestTest(AWS_JSON_10, "AwsJson10ServerPopulatesDefaultsWhenMissingInRequestBody"), // Response defaults are not set when builders are not used https://github.com/smithy-lang/smithy-rs/issues/3339 - FailingTest(AWS_JSON_10, "AwsJson10ServerPopulatesDefaultsInResponseWhenMissingInParams", TestCaseKind.Response), - FailingTest(AWS_JSON_10, "AwsJson10ServerPopulatesNestedDefaultValuesWhenMissingInInResponseParams", TestCaseKind.Response), + FailingTest.ResponseTest(AWS_JSON_10, "AwsJson10ServerPopulatesDefaultsInResponseWhenMissingInParams"), + FailingTest.ResponseTest( + AWS_JSON_10, + "AwsJson10ServerPopulatesNestedDefaultValuesWhenMissingInInResponseParams", + ), + ) + + private val BrokenTests: + Set = + setOf( + BrokenTest.MalformedRequestTest( + REST_JSON_VALIDATION, + "RestJsonMalformedPatternReDOSString", + howToFixItFn = ::fixRestJsonMalformedPatternReDOSString, + inAtLeast = setOf("1.26.2", "1.49.0"), + trackedIn = setOf( + // TODO(https://github.com/awslabs/smithy/issues/1506) + "https://github.com/awslabs/smithy/issues/1506", + // TODO(https://github.com/smithy-lang/smithy/pull/2340) + "https://github.com/smithy-lang/smithy/pull/2340", + ), + ), ) private val DisabledTests = @@ -171,11 +188,8 @@ class ServerProtocolTestGenerator( "S3PreservesEmbeddedDotSegmentInUriLabel", ) - // TODO(https://github.com/awslabs/smithy/issues/1506) - private fun fixRestJsonMalformedPatternReDOSString( - testCase: HttpMalformedRequestTestCase, - ): HttpMalformedRequestTestCase { - val brokenResponse = testCase.response + private fun fixRestJsonMalformedPatternReDOSString(testCase: TestCase.MalformedRequestTest): TestCase.MalformedRequestTest { + val brokenResponse = testCase.testCase.response val brokenBody = brokenResponse.body.get() val fixedBody = HttpMalformedResponseBodyDefinition.builder() @@ -190,31 +204,20 @@ class ServerProtocolTestGenerator( ) .build() - return testCase.toBuilder() - .response(brokenResponse.toBuilder().body(fixedBody).build()) - .build() - } - - // TODO(https://github.com/smithy-lang/smithy-rs/issues/1288): Move the fixed versions into - // `rest-json-extras.smithy` and put the unfixed ones in `ExpectFail`: this has the - // advantage that once our upstream PRs get merged and we upgrade to the next Smithy release, our build will - // fail and we will take notice to remove the fixes from `rest-json-extras.smithy`. This is exactly what the - // client does. - private val BrokenMalformedRequestTests: - Map, KFunction1> = - // TODO(https://github.com/awslabs/smithy/issues/1506) - mapOf( - Pair( - REST_JSON_VALIDATION, - "RestJsonMalformedPatternReDOSString", - ) to ::fixRestJsonMalformedPatternReDOSString, + return TestCase.MalformedRequestTest( + testCase.testCase.toBuilder() + .response(brokenResponse.toBuilder().body(fixedBody).build()) + .build(), ) + } } override val appliesTo: AppliesTo get() = AppliesTo.SERVER override val expectFail: Set get() = ExpectFail + override val brokenTests: Set + get() = BrokenTests override val runOnly: Set get() = emptySet() override val disabledTests: Set @@ -274,26 +277,6 @@ class ServerProtocolTestGenerator( } } - /** - * Broken tests in the `awslabs/smithy` repository are usually wrong because they have not been written - * with a server-side perspective in mind. - */ - override fun List.fixBroken(): List = - this.map { - when (it) { - is TestCase.MalformedRequestTest -> { - val howToFixIt = BrokenMalformedRequestTests[Pair(codegenContext.serviceShape.id.toString(), it.id)] - if (howToFixIt == null) { - it - } else { - val fixed = howToFixIt(it.testCase) - TestCase.MalformedRequestTest(fixed) - } - } - else -> it - } - } - /** * Renders an HTTP request test case. * We are given an HTTP request in the test case, and we assert that when we deserialize said HTTP request into @@ -338,7 +321,7 @@ class ServerProtocolTestGenerator( if (!protocolSupport.responseSerialization || ( !protocolSupport.errorSerialization && shape.hasTrait() - ) + ) ) { rust("/* test case disabled for this protocol (not yet supported) */") return From 830885bbdcaf8bd47757bf6ea0fd93de47e1db38 Mon Sep 17 00:00:00 2001 From: david-perez Date: Fri, 28 Jun 2024 18:11:05 +0200 Subject: [PATCH 2/2] ./gradlew ktlintFormat --- .../protocol/ProtocolTestGenerator.kt | 134 ++++++++++-------- .../protocol/ServerProtocolTestGenerator.kt | 19 +-- 2 files changed, 84 insertions(+), 69 deletions(-) diff --git a/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/generators/protocol/ProtocolTestGenerator.kt b/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/generators/protocol/ProtocolTestGenerator.kt index 45fdbc1ac9..20121535a8 100644 --- a/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/generators/protocol/ProtocolTestGenerator.kt +++ b/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/generators/protocol/ProtocolTestGenerator.kt @@ -85,9 +85,10 @@ abstract class ProtocolTestGenerator { /** The entry point to render the protocol tests, invoked by the code generators. */ fun render(writer: RustWriter) { - val allTests = allMatchingTestCases().flatMap { - fixBrokenTestCase(it) - } + val allTests = + allMatchingTestCases().flatMap { + fixBrokenTestCase(it) + } if (allTests.isEmpty()) { return } @@ -104,50 +105,55 @@ abstract class ProtocolTestGenerator { * If the test is broken, we synthesize it in two versions: the original broken test with a `#[should_panic]` * attribute, so get alerted if the test now passes, and the fixed version, which should pass. */ - private fun fixBrokenTestCase(it: TestCase): List = if (!it.isBroken()) { - listOf(it) - } else { - assert(it.expectFail()) - - val brokenTest = it.findInBroken()!! - var fixed = brokenTest.fixIt(it) - - val intro = "The hotfix function for broken test case ${it.kind} ${it.id}" - val moreInfo = - """This test case was identified to be broken in at least these Smithy versions: [${brokenTest.inAtLeast.joinToString()}]. - |We are tracking things here: [${brokenTest.trackedIn.joinToString()}].""".trimMargin() - - // Something must change... - if (it == fixed) { - PANIC( - """$intro did not make any modifications. It is likely that the test case was + private fun fixBrokenTestCase(it: TestCase): List = + if (!it.isBroken()) { + listOf(it) + } else { + assert(it.expectFail()) + + val brokenTest = it.findInBroken()!! + var fixed = brokenTest.fixIt(it) + + val intro = "The hotfix function for broken test case ${it.kind} ${it.id}" + val moreInfo = + """This test case was identified to be broken in at least these Smithy versions: [${brokenTest.inAtLeast.joinToString()}]. + |We are tracking things here: [${brokenTest.trackedIn.joinToString()}]. + """.trimMargin() + + // Something must change... + if (it == fixed) { + PANIC( + """$intro did not make any modifications. It is likely that the test case was |fixed upstream, and you're now updating the Smithy version; in this case, remove the hotfix |function, as the test is no longer broken. - |$moreInfo""".trimMargin(), - ) - } + |$moreInfo + """.trimMargin(), + ) + } - // ... but the hotfix function is not allowed to change the test case kind... - if (it.kind != fixed.kind) { - PANIC( - """$intro changed the test case kind. This is not allowed. - |$moreInfo""".trimMargin(), - ) - } + // ... but the hotfix function is not allowed to change the test case kind... + if (it.kind != fixed.kind) { + PANIC( + """$intro changed the test case kind. This is not allowed. + |$moreInfo + """.trimMargin(), + ) + } - // ... nor its id. - if (it.id != fixed.id) { - PANIC( - """$intro changed the test case id. This is not allowed. - |$moreInfo""".trimMargin(), - ) - } + // ... nor its id. + if (it.id != fixed.id) { + PANIC( + """$intro changed the test case id. This is not allowed. + |$moreInfo + """.trimMargin(), + ) + } - // The latter is because we're going to generate the fixed version with an identifiable suffix. - fixed = fixed.suffixIdWith("_hotfixed") + // The latter is because we're going to generate the fixed version with an identifiable suffix. + fixed = fixed.suffixIdWith("_hotfixed") - listOf(it, fixed) - } + listOf(it, fixed) + } /** Implementors should describe how to render the test cases. **/ abstract fun RustWriter.renderAllTestCases(allTests: List) @@ -161,11 +167,12 @@ abstract class ProtocolTestGenerator { this.filter { testCase -> runOnly.contains(testCase.id) } } - private fun TestCase.toFailingTest(): FailingTest = when (this) { - is TestCase.MalformedRequestTest -> FailingTest.MalformedRequestTest(serviceShapeId.toString(), this.id) - is TestCase.RequestTest -> FailingTest.RequestTest(serviceShapeId.toString(), this.id) - is TestCase.ResponseTest -> FailingTest.ResponseTest(serviceShapeId.toString(), this.id) - } + private fun TestCase.toFailingTest(): FailingTest = + when (this) { + is TestCase.MalformedRequestTest -> FailingTest.MalformedRequestTest(serviceShapeId.toString(), this.id) + is TestCase.RequestTest -> FailingTest.RequestTest(serviceShapeId.toString(), this.id) + is TestCase.ResponseTest -> FailingTest.ResponseTest(serviceShapeId.toString(), this.id) + } /** Do we expect this test case to fail? */ private fun TestCase.expectFail(): Boolean = this.isBroken() || expectFail.contains(this.toFailingTest()) @@ -173,11 +180,12 @@ abstract class ProtocolTestGenerator { /** Is this test case broken? */ private fun TestCase.isBroken(): Boolean = this.findInBroken() != null - private fun TestCase.findInBroken(): BrokenTest? = brokenTests.find { brokenTest -> - (this is TestCase.RequestTest && brokenTest is BrokenTest.RequestTest && this.id == brokenTest.id) || - (this is TestCase.ResponseTest && brokenTest is BrokenTest.ResponseTest && this.id == brokenTest.id) || - (this is TestCase.MalformedRequestTest && brokenTest is BrokenTest.MalformedRequestTest && this.id == brokenTest.id) - } + private fun TestCase.findInBroken(): BrokenTest? = + brokenTests.find { brokenTest -> + (this is TestCase.RequestTest && brokenTest is BrokenTest.RequestTest && this.id == brokenTest.id) || + (this is TestCase.ResponseTest && brokenTest is BrokenTest.ResponseTest && this.id == brokenTest.id) || + (this is TestCase.MalformedRequestTest && brokenTest is BrokenTest.MalformedRequestTest && this.id == brokenTest.id) + } fun requestTestCases(): List { val requestTests = @@ -355,14 +363,13 @@ abstract class ProtocolTestGenerator { sealed class BrokenTest( open val serviceShapeId: String, open val id: String, - /** A non-exhaustive set of Smithy versions where the test was found to be broken. */ open val inAtLeast: Set, /** * GitHub URLs related to the test brokenness, like a GitHub issue in Smithy where we reported the test was broken, * or a PR where we fixed it. **/ - open val trackedIn: Set + open val trackedIn: Set, ) { data class RequestTest( override val serviceShapeId: String, @@ -411,8 +418,10 @@ object ServiceShapeId { sealed class FailingTest(open val serviceShapeId: String, open val id: String) { data class RequestTest(override val serviceShapeId: String, override val id: String) : FailingTest(serviceShapeId, id) + data class ResponseTest(override val serviceShapeId: String, override val id: String) : FailingTest(serviceShapeId, id) + data class MalformedRequestTest(override val serviceShapeId: String, override val id: String) : FailingTest(serviceShapeId, id) } @@ -455,19 +464,22 @@ sealed class TestCase { override fun equals(other: Any?): Boolean { if (this === other) return true if (other !is MalformedRequestTest) return false - return this.protocol == other.protocol && this.id == other.id && this.documentation == other.documentation && this.testCase.request.toNode() - .equals(other.testCase.request.toNode()) && this.testCase.response.toNode() - .equals(other.testCase.response.toNode()) + return this.protocol == other.protocol && this.id == other.id && this.documentation == other.documentation && + this.testCase.request.toNode() + .equals(other.testCase.request.toNode()) && + this.testCase.response.toNode() + .equals(other.testCase.response.toNode()) } override fun hashCode(): Int = testCase.hashCode() } - fun suffixIdWith(suffix: String): TestCase = when (this) { - is RequestTest -> RequestTest(this.testCase.suffixIdWith(suffix)) - is MalformedRequestTest -> MalformedRequestTest(this.testCase.suffixIdWith(suffix)) - is ResponseTest -> ResponseTest(this.testCase.suffixIdWith(suffix), this.targetShape) - } + fun suffixIdWith(suffix: String): TestCase = + when (this) { + is RequestTest -> RequestTest(this.testCase.suffixIdWith(suffix)) + is MalformedRequestTest -> MalformedRequestTest(this.testCase.suffixIdWith(suffix)) + is ResponseTest -> ResponseTest(this.testCase.suffixIdWith(suffix), this.targetShape) + } private fun HttpRequestTestCase.suffixIdWith(suffix: String): HttpRequestTestCase = this.toBuilder().id(this.id + suffix).build() diff --git a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/protocol/ServerProtocolTestGenerator.kt b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/protocol/ServerProtocolTestGenerator.kt index 453a8605af..cb03181d7c 100644 --- a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/protocol/ServerProtocolTestGenerator.kt +++ b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/protocol/ServerProtocolTestGenerator.kt @@ -157,12 +157,13 @@ class ServerProtocolTestGenerator( "RestJsonMalformedPatternReDOSString", howToFixItFn = ::fixRestJsonMalformedPatternReDOSString, inAtLeast = setOf("1.26.2", "1.49.0"), - trackedIn = setOf( - // TODO(https://github.com/awslabs/smithy/issues/1506) - "https://github.com/awslabs/smithy/issues/1506", - // TODO(https://github.com/smithy-lang/smithy/pull/2340) - "https://github.com/smithy-lang/smithy/pull/2340", - ), + trackedIn = + setOf( + // TODO(https://github.com/awslabs/smithy/issues/1506) + "https://github.com/awslabs/smithy/issues/1506", + // TODO(https://github.com/smithy-lang/smithy/pull/2340) + "https://github.com/smithy-lang/smithy/pull/2340", + ), ), ) @@ -188,7 +189,9 @@ class ServerProtocolTestGenerator( "S3PreservesEmbeddedDotSegmentInUriLabel", ) - private fun fixRestJsonMalformedPatternReDOSString(testCase: TestCase.MalformedRequestTest): TestCase.MalformedRequestTest { + private fun fixRestJsonMalformedPatternReDOSString( + testCase: TestCase.MalformedRequestTest, + ): TestCase.MalformedRequestTest { val brokenResponse = testCase.testCase.response val brokenBody = brokenResponse.body.get() val fixedBody = @@ -321,7 +324,7 @@ class ServerProtocolTestGenerator( if (!protocolSupport.responseSerialization || ( !protocolSupport.errorSerialization && shape.hasTrait() - ) + ) ) { rust("/* test case disabled for this protocol (not yet supported) */") return