Skip to content

Commit c3ae6f7

Browse files
authored
Refactor event stream tests with {client,server}IntegrationTests (#2342)
* Refactor `ClientEventStreamUnmarshallerGeneratorTest` to use `clientIntegrationTest` (WIP) * Refactor `ClientEventStreamUnmarshallerGeneratorTest` with `clientIntegrationTest` * Refactor `ClientEventStreamUnmarshallerGeneratorTest` to use generic test cases * Start refactoring `ServerEventStreamUnmarshallerGeneratorTest` * Make `ServerEventStreamUnmarshallerGeneratorTest` tests work * Uncomment other test models * Allow unused on `parse_generic_error` * Rename `ServerEventStreamUnmarshallerGeneratorTest` * Make `EventStreamUnmarshallTestCases` codegenTarget-agnostic * Refactor `ClientEventStreamMarshallerGeneratorTest`: Tests run but fail * Refactor `ServerEventStreamMarshallerGeneratorTest` * Move `.into()` calls to `conditionalBuilderInput` * Add "context" to TODO * Fix client unmarshall tests * Fix clippy lint * Fix more clippy lints * Add docs for `event_stream_serde` module * Fix client tests * Remove `#[allow(missing_docs)]` from event stream module * Remove unused `EventStreamTestTools` * Add `smithy-validation-model` test dep to `codegen-client` * Temporarily add docs to make tests compile * Undo change in model * Make event stream unmarshaller tests a unit test * Remove unused code * Make `ServerEventStreamUnmarshallerGeneratorTest` a unit test * Make `ServerEventStreamMarshallerGeneratorTest` a unit test * Make `ServerEventStreamMarshallerGeneratorTest` pass * Make remaining tests non-integration tests * Make event stream serde module private again * Remove unnecessary clippy allowances * Remove clippy allowance * Remove docs for `event_stream_serde` module * Remove docs for `$unmarshallerTypeName::new` * Remove more unnecessary docs * Remove more superfluous docs * Undo unnecessary diffs * Uncomment last test * Make `conditionalBuilderInput` internal
1 parent 72df844 commit c3ae6f7

File tree

17 files changed

+541
-898
lines changed

17 files changed

+541
-898
lines changed

codegen-client/build.gradle.kts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,10 @@ dependencies {
2828
implementation("software.amazon.smithy:smithy-protocol-test-traits:$smithyVersion")
2929
implementation("software.amazon.smithy:smithy-waiters:$smithyVersion")
3030
implementation("software.amazon.smithy:smithy-rules-engine:$smithyVersion")
31+
32+
// `smithy.framework#ValidationException` is defined here, which is used in event stream
33+
// marshalling/unmarshalling tests.
34+
testImplementation("software.amazon.smithy:smithy-validation-model:$smithyVersion")
3135
}
3236

3337
tasks.compileKotlin {

codegen-client/src/test/kotlin/software/amazon/smithy/rust/codegen/client/smithy/protocols/eventstream/ClientEventStreamBaseRequirements.kt

Lines changed: 0 additions & 98 deletions
This file was deleted.

codegen-client/src/test/kotlin/software/amazon/smithy/rust/codegen/client/smithy/protocols/eventstream/ClientEventStreamMarshallerGeneratorTest.kt

Lines changed: 17 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -5,43 +5,30 @@
55

66
package software.amazon.smithy.rust.codegen.client.smithy.protocols.eventstream
77

8+
import org.junit.jupiter.api.extension.ExtensionContext
89
import org.junit.jupiter.params.ParameterizedTest
10+
import org.junit.jupiter.params.provider.Arguments
11+
import org.junit.jupiter.params.provider.ArgumentsProvider
912
import org.junit.jupiter.params.provider.ArgumentsSource
10-
import software.amazon.smithy.rust.codegen.client.smithy.ClientCodegenContext
11-
import software.amazon.smithy.rust.codegen.core.smithy.CodegenTarget
12-
import software.amazon.smithy.rust.codegen.core.smithy.RuntimeType
13-
import software.amazon.smithy.rust.codegen.core.smithy.protocols.Protocol
14-
import software.amazon.smithy.rust.codegen.core.smithy.protocols.serialize.EventStreamMarshallerGenerator
13+
import software.amazon.smithy.rust.codegen.client.testutil.clientIntegrationTest
14+
import software.amazon.smithy.rust.codegen.core.testutil.EventStreamMarshallTestCases.writeMarshallTestCases
1515
import software.amazon.smithy.rust.codegen.core.testutil.EventStreamTestModels
16-
import software.amazon.smithy.rust.codegen.core.testutil.EventStreamTestTools
17-
import software.amazon.smithy.rust.codegen.core.testutil.EventStreamTestVariety
18-
import software.amazon.smithy.rust.codegen.core.testutil.TestEventStreamProject
19-
import software.amazon.smithy.rust.codegen.core.testutil.TestRuntimeConfig
20-
import software.amazon.smithy.rust.codegen.core.testutil.compileAndTest
16+
import software.amazon.smithy.rust.codegen.core.testutil.testModule
17+
import java.util.stream.Stream
2118

2219
class ClientEventStreamMarshallerGeneratorTest {
2320
@ParameterizedTest
2421
@ArgumentsSource(TestCasesProvider::class)
2522
fun test(testCase: EventStreamTestModels.TestCase) {
26-
EventStreamTestTools.setupTestCase(
27-
testCase,
28-
object : ClientEventStreamBaseRequirements() {
29-
override fun renderGenerator(
30-
codegenContext: ClientCodegenContext,
31-
project: TestEventStreamProject,
32-
protocol: Protocol,
33-
): RuntimeType = EventStreamMarshallerGenerator(
34-
project.model,
35-
CodegenTarget.CLIENT,
36-
TestRuntimeConfig,
37-
project.symbolProvider,
38-
project.streamShape,
39-
protocol.structuredDataSerializer(project.operationShape),
40-
testCase.requestContentType,
41-
).render()
42-
},
43-
CodegenTarget.CLIENT,
44-
EventStreamTestVariety.Marshall,
45-
).compileAndTest()
23+
clientIntegrationTest(testCase.model) { _, rustCrate ->
24+
rustCrate.testModule {
25+
writeMarshallTestCases(testCase, optionalBuilderInputs = false)
26+
}
27+
}
4628
}
4729
}
30+
31+
class TestCasesProvider : ArgumentsProvider {
32+
override fun provideArguments(context: ExtensionContext?): Stream<out Arguments> =
33+
EventStreamTestModels.TEST_CASES.map { Arguments.of(it) }.stream()
34+
}

codegen-client/src/test/kotlin/software/amazon/smithy/rust/codegen/client/smithy/protocols/eventstream/ClientEventStreamUnmarshallerGeneratorTest.kt

Lines changed: 49 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -7,39 +7,60 @@ package software.amazon.smithy.rust.codegen.client.smithy.protocols.eventstream
77

88
import org.junit.jupiter.params.ParameterizedTest
99
import org.junit.jupiter.params.provider.ArgumentsSource
10-
import software.amazon.smithy.rust.codegen.client.smithy.ClientCodegenContext
11-
import software.amazon.smithy.rust.codegen.core.smithy.CodegenTarget
12-
import software.amazon.smithy.rust.codegen.core.smithy.RuntimeType
13-
import software.amazon.smithy.rust.codegen.core.smithy.protocols.Protocol
14-
import software.amazon.smithy.rust.codegen.core.smithy.protocols.parse.EventStreamUnmarshallerGenerator
10+
import software.amazon.smithy.rust.codegen.client.testutil.clientIntegrationTest
11+
import software.amazon.smithy.rust.codegen.core.rustlang.rust
1512
import software.amazon.smithy.rust.codegen.core.testutil.EventStreamTestModels
16-
import software.amazon.smithy.rust.codegen.core.testutil.EventStreamTestTools
17-
import software.amazon.smithy.rust.codegen.core.testutil.EventStreamTestVariety
18-
import software.amazon.smithy.rust.codegen.core.testutil.TestEventStreamProject
19-
import software.amazon.smithy.rust.codegen.core.testutil.compileAndTest
13+
import software.amazon.smithy.rust.codegen.core.testutil.EventStreamUnmarshallTestCases.writeUnmarshallTestCases
14+
import software.amazon.smithy.rust.codegen.core.testutil.IntegrationTestParams
15+
import software.amazon.smithy.rust.codegen.core.testutil.testModule
16+
import software.amazon.smithy.rust.codegen.core.testutil.unitTest
2017

2118
class ClientEventStreamUnmarshallerGeneratorTest {
2219
@ParameterizedTest
2320
@ArgumentsSource(TestCasesProvider::class)
2421
fun test(testCase: EventStreamTestModels.TestCase) {
25-
EventStreamTestTools.setupTestCase(
26-
testCase,
27-
object : ClientEventStreamBaseRequirements() {
28-
override fun renderGenerator(
29-
codegenContext: ClientCodegenContext,
30-
project: TestEventStreamProject,
31-
protocol: Protocol,
32-
): RuntimeType {
33-
return EventStreamUnmarshallerGenerator(
34-
protocol,
35-
codegenContext,
36-
project.operationShape,
37-
project.streamShape,
38-
).render()
39-
}
40-
},
41-
CodegenTarget.CLIENT,
42-
EventStreamTestVariety.Unmarshall,
43-
).compileAndTest()
22+
clientIntegrationTest(
23+
testCase.model,
24+
IntegrationTestParams(service = "test#TestService", addModuleToEventStreamAllowList = true),
25+
) { _, rustCrate ->
26+
val generator = "crate::event_stream_serde::TestStreamUnmarshaller"
27+
28+
rustCrate.testModule {
29+
rust("##![allow(unused_imports, dead_code)]")
30+
writeUnmarshallTestCases(testCase, optionalBuilderInputs = false)
31+
32+
unitTest(
33+
"unknown_message",
34+
"""
35+
let message = msg("event", "NewUnmodeledMessageType", "application/octet-stream", b"hello, world!");
36+
let result = $generator::new().unmarshall(&message);
37+
assert!(result.is_ok(), "expected ok, got: {:?}", result);
38+
assert!(expect_event(result.unwrap()).is_unknown());
39+
""",
40+
)
41+
42+
unitTest(
43+
"generic_error",
44+
"""
45+
let message = msg(
46+
"exception",
47+
"UnmodeledError",
48+
"${testCase.responseContentType}",
49+
br#"${testCase.validUnmodeledError}"#
50+
);
51+
let result = $generator::new().unmarshall(&message);
52+
assert!(result.is_ok(), "expected ok, got: {:?}", result);
53+
match expect_error(result.unwrap()) {
54+
TestStreamError::Unhandled(err) => {
55+
let message = format!("{}", aws_smithy_types::error::display::DisplayErrorContext(&err));
56+
let expected = "message: \"unmodeled error\"";
57+
assert!(message.contains(expected), "Expected '{message}' to contain '{expected}'");
58+
}
59+
kind => panic!("expected generic error, but got {:?}", kind),
60+
}
61+
""",
62+
)
63+
}
64+
}
4465
}
4566
}

codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/rustlang/RustType.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -470,9 +470,11 @@ class Attribute(val inner: Writable) {
470470
val AllowDeprecated = Attribute(allow("deprecated"))
471471
val AllowIrrefutableLetPatterns = Attribute(allow("irrefutable_let_patterns"))
472472
val AllowUnreachableCode = Attribute(allow("unreachable_code"))
473+
val AllowUnreachablePatterns = Attribute(allow("unreachable_patterns"))
473474
val AllowUnusedImports = Attribute(allow("unused_imports"))
474475
val AllowUnusedMut = Attribute(allow("unused_mut"))
475476
val AllowUnusedVariables = Attribute(allow("unused_variables"))
477+
val AllowMissingDocs = Attribute(allow("missing_docs"))
476478
val CfgTest = Attribute(cfg("test"))
477479
val DenyMissingDocs = Attribute(deny("missing_docs"))
478480
val DocHidden = Attribute(doc("hidden"))

codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/rustlang/RustWriter.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ private fun <T : AbstractCodeWriter<T>, U> T.withTemplate(
116116
* This enables conditionally wrapping a block in a prefix/suffix, e.g.
117117
*
118118
* ```
119-
* writer.withBlock("Some(", ")", conditional = symbol.isOptional()) {
119+
* writer.conditionalBlock("Some(", ")", conditional = symbol.isOptional()) {
120120
* write("symbolValue")
121121
* }
122122
* ```

codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/protocols/parse/EventStreamUnmarshallerGenerator.kt

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,9 @@ import software.amazon.smithy.rust.codegen.core.util.expectTrait
4343
import software.amazon.smithy.rust.codegen.core.util.hasTrait
4444
import software.amazon.smithy.rust.codegen.core.util.toPascalCase
4545

46+
fun RustModule.Companion.eventStreamSerdeModule(): RustModule.LeafModule =
47+
private("event_stream_serde")
48+
4649
class EventStreamUnmarshallerGenerator(
4750
private val protocol: Protocol,
4851
codegenContext: CodegenContext,
@@ -60,7 +63,7 @@ class EventStreamUnmarshallerGenerator(
6063
symbolProvider.symbolForEventStreamError(unionShape)
6164
}
6265
private val smithyEventStream = RuntimeType.smithyEventStream(runtimeConfig)
63-
private val eventStreamSerdeModule = RustModule.private("event_stream_serde")
66+
private val eventStreamSerdeModule = RustModule.eventStreamSerdeModule()
6467
private val codegenScope = arrayOf(
6568
"Blob" to RuntimeType.blob(runtimeConfig),
6669
"expect_fns" to smithyEventStream.resolve("smithy"),
@@ -84,15 +87,16 @@ class EventStreamUnmarshallerGenerator(
8487
}
8588

8689
private fun RustWriter.renderUnmarshaller(unmarshallerType: RuntimeType, unionSymbol: Symbol) {
90+
val unmarshallerTypeName = unmarshallerType.name
8791
rust(
8892
"""
8993
##[non_exhaustive]
9094
##[derive(Debug)]
91-
pub struct ${unmarshallerType.name};
95+
pub struct $unmarshallerTypeName;
9296
93-
impl ${unmarshallerType.name} {
97+
impl $unmarshallerTypeName {
9498
pub fn new() -> Self {
95-
${unmarshallerType.name}
99+
$unmarshallerTypeName
96100
}
97101
}
98102
""",
@@ -154,6 +158,7 @@ class EventStreamUnmarshallerGenerator(
154158
"Output" to unionSymbol,
155159
*codegenScope,
156160
)
161+
157162
false -> rustTemplate(
158163
"return Err(#{Error}::unmarshalling(format!(\"unrecognized :event-type: {}\", _unknown_variant)));",
159164
*codegenScope,
@@ -179,6 +184,7 @@ class EventStreamUnmarshallerGenerator(
179184
*codegenScope,
180185
)
181186
}
187+
182188
payloadOnly -> {
183189
withBlock("let parsed = ", ";") {
184190
renderParseProtocolPayload(unionMember)
@@ -189,6 +195,7 @@ class EventStreamUnmarshallerGenerator(
189195
*codegenScope,
190196
)
191197
}
198+
192199
else -> {
193200
rust("let mut builder = #T::default();", symbolProvider.symbolForBuilder(unionStruct))
194201
val payloadMember = unionStruct.members().firstOrNull { it.hasTrait<EventPayloadTrait>() }
@@ -265,6 +272,7 @@ class EventStreamUnmarshallerGenerator(
265272
is BlobShape -> {
266273
rustTemplate("#{Blob}::new(message.payload().as_ref())", *codegenScope)
267274
}
275+
268276
is StringShape -> {
269277
rustTemplate(
270278
"""
@@ -275,6 +283,7 @@ class EventStreamUnmarshallerGenerator(
275283
*codegenScope,
276284
)
277285
}
286+
278287
is UnionShape, is StructureShape -> {
279288
renderParseProtocolPayload(member)
280289
}
@@ -312,6 +321,7 @@ class EventStreamUnmarshallerGenerator(
312321
*codegenScope,
313322
)
314323
}
324+
315325
CodegenTarget.SERVER -> {}
316326
}
317327

@@ -350,6 +360,7 @@ class EventStreamUnmarshallerGenerator(
350360
)
351361
}
352362
}
363+
353364
CodegenTarget.SERVER -> {
354365
val target = model.expectShape(member.target, StructureShape::class.java)
355366
val parser = protocol.structuredDataParser(operationShape).errorParser(target)
@@ -391,6 +402,7 @@ class EventStreamUnmarshallerGenerator(
391402
CodegenTarget.CLIENT -> {
392403
rustTemplate("Ok(#{UnmarshalledMessage}::Error(#{OpError}::generic(generic)))", *codegenScope)
393404
}
405+
394406
CodegenTarget.SERVER -> {
395407
rustTemplate(
396408
"""

0 commit comments

Comments
 (0)