diff --git a/.changelog/7869753.md b/.changelog/7869753.md new file mode 100644 index 0000000000..9f2c3cf7c6 --- /dev/null +++ b/.changelog/7869753.md @@ -0,0 +1,9 @@ +--- +applies_to: ["server"] +authors: ["drganjoo"] +references: ["smithy-rs#3813"] +breaking: true +new_feature: false +bug_fix: true +--- +Operations with event stream member shapes must include `ValidationException` in the errors list. This is necessary because the member shape is a required field, and the builder for the operation input or output returns a `std::result::Result` with the error set to `crate::model::ValidationExceptionField`. diff --git a/codegen-core/common-test-models/constraints.smithy b/codegen-core/common-test-models/constraints.smithy index 18bbdc252a..14accc4cd6 100644 --- a/codegen-core/common-test-models/constraints.smithy +++ b/codegen-core/common-test-models/constraints.smithy @@ -190,6 +190,7 @@ operation StreamingBlobOperation { operation EventStreamsOperation { input: EventStreamsOperationInputOutput, output: EventStreamsOperationInputOutput, + errors: [ValidationException] } structure ConstrainedShapesOperationInputOutput { diff --git a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/ValidateUnsupportedConstraints.kt b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/ValidateUnsupportedConstraints.kt index 6fb4379c39..4d17fa6d2e 100644 --- a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/ValidateUnsupportedConstraints.kt +++ b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/ValidateUnsupportedConstraints.kt @@ -28,6 +28,7 @@ import software.amazon.smithy.model.traits.UniqueItemsTrait import software.amazon.smithy.rust.codegen.core.smithy.DirectedWalker import software.amazon.smithy.rust.codegen.core.smithy.traits.SyntheticEventStreamUnionTrait import software.amazon.smithy.rust.codegen.core.util.expectTrait +import software.amazon.smithy.rust.codegen.core.util.hasEventStreamMember import software.amazon.smithy.rust.codegen.core.util.hasTrait import software.amazon.smithy.rust.codegen.core.util.inputShape import software.amazon.smithy.rust.codegen.core.util.orNull @@ -190,7 +191,7 @@ fun operationShapesThatMustHaveValidationException( .filter { operationShape -> // Walk the shapes reachable via this operation input. walker.walkShapes(operationShape.inputShape(model)) - .any { it is SetShape || it is EnumShape || it.hasConstraintTrait() } + .any { it is SetShape || it is EnumShape || it.hasConstraintTrait() || it.hasEventStreamMember(model) } } .toSet() } @@ -207,7 +208,6 @@ fun validateOperationsWithConstrainedInputHaveValidationExceptionAttached( // `ValidationException` attached in `errors`. https://github.com/smithy-lang/smithy-rs/pull/1199#discussion_r809424783 // TODO(https://github.com/smithy-lang/smithy-rs/issues/1401): This check will go away once we add support for // `disableDefaultValidation` set to `true`, allowing service owners to map from constraint violations to operation errors. - val walker = DirectedWalker(model) val operationsWithConstrainedInputWithoutValidationExceptionSet = operationShapesThatMustHaveValidationException(model, service) .filter { !it.errors.contains(validationExceptionShapeId) } diff --git a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/ValidateUnsupportedConstraintsAreNotUsedTest.kt b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/ValidateUnsupportedConstraintsAreNotUsedTest.kt index 72279a7a20..15d093ff21 100644 --- a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/ValidateUnsupportedConstraintsAreNotUsedTest.kt +++ b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/ValidateUnsupportedConstraintsAreNotUsedTest.kt @@ -81,6 +81,51 @@ internal class ValidateUnsupportedConstraintsAreNotUsedTest { """.trimIndent() } + @Test + fun `should detect when event streams are used, even without constraints, as the event member is required`() { + val model = + """ + $baseModel + structure TestInputOutput { + eventStream: EventStream + } + @streaming + union EventStream { + message: Message, + error: Error + } + structure Message { + lengthString: String + } + structure Error { + message: String + } + """.asSmithyModel() + val service = model.lookup("test#TestService") + val validationResult = + validateOperationsWithConstrainedInputHaveValidationExceptionAttached( + model, + service, + SmithyValidationExceptionConversionGenerator.SHAPE_ID, + ) + + validationResult.messages shouldHaveSize 1 + + // Asserts the exact message, to ensure the formatting is appropriate. + validationResult.messages[0].message shouldBe + """ + Operation test#TestOperation takes in input that is constrained (https://awslabs.github.io/smithy/2.0/spec/constraint-traits.html), and as such can fail with a validation exception. You must model this behavior in the operation shape in your model file. + ```smithy + use smithy.framework#ValidationException + + operation TestOperation { + ... + errors: [..., ValidationException] // <-- Add this. + } + ``` + """.trimIndent() + } + private val constraintTraitOnStreamingBlobShapeModel = """ $baseModel