Skip to content

Commit 41d6270

Browse files
Add CBOR Tests and update Protocol test models to 1.0.5931.0 and Smithy Version 1.58.0
1 parent dad3441 commit 41d6270

File tree

19 files changed

+843
-7
lines changed

19 files changed

+843
-7
lines changed

extensions/AWSSDK.Extensions.sln

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,12 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AWSSDK.CommonTest", "..\sdk
7474
EndProject
7575
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AWSSDK.S3.NetFramework", "..\sdk\src\Services\S3\AWSSDK.S3.NetFramework.csproj", "{1A313326-988F-4FF2-992E-6D7E50DCF598}"
7676
EndProject
77+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AWSSDK.Extensions.CborProtocol.NetFramework", "src\AWSSDK.Extensions.CborProtocol\AWSSDK.Extensions.CborProtocol.NetFramework.csproj", "{4FCCBD72-8E9B-D74B-6538-D8684D181230}"
78+
EndProject
79+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AWSSDK.Extensions.CborProtocol.NetStandard", "src\AWSSDK.Extensions.CborProtocol\AWSSDK.Extensions.CborProtocol.NetStandard.csproj", "{24CBBC97-409E-BAC8-0553-D260AB0B8C6A}"
80+
EndProject
81+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CborProtocol.Tests.NetFramework", "test\CborProtocol.Tests\CborProtocol.Tests.NetFramework.csproj", "{9FFDECAB-94D6-7EB1-1A5B-487492600755}"
82+
EndProject
7783
Global
7884
GlobalSection(SolutionConfigurationPlatforms) = preSolution
7985
Debug|Any CPU = Debug|Any CPU
@@ -204,6 +210,18 @@ Global
204210
{1A313326-988F-4FF2-992E-6D7E50DCF598}.Debug|Any CPU.Build.0 = Debug|Any CPU
205211
{1A313326-988F-4FF2-992E-6D7E50DCF598}.Release|Any CPU.ActiveCfg = Release|Any CPU
206212
{1A313326-988F-4FF2-992E-6D7E50DCF598}.Release|Any CPU.Build.0 = Release|Any CPU
213+
{4FCCBD72-8E9B-D74B-6538-D8684D181230}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
214+
{4FCCBD72-8E9B-D74B-6538-D8684D181230}.Debug|Any CPU.Build.0 = Debug|Any CPU
215+
{4FCCBD72-8E9B-D74B-6538-D8684D181230}.Release|Any CPU.ActiveCfg = Release|Any CPU
216+
{4FCCBD72-8E9B-D74B-6538-D8684D181230}.Release|Any CPU.Build.0 = Release|Any CPU
217+
{24CBBC97-409E-BAC8-0553-D260AB0B8C6A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
218+
{24CBBC97-409E-BAC8-0553-D260AB0B8C6A}.Debug|Any CPU.Build.0 = Debug|Any CPU
219+
{24CBBC97-409E-BAC8-0553-D260AB0B8C6A}.Release|Any CPU.ActiveCfg = Release|Any CPU
220+
{24CBBC97-409E-BAC8-0553-D260AB0B8C6A}.Release|Any CPU.Build.0 = Release|Any CPU
221+
{9FFDECAB-94D6-7EB1-1A5B-487492600755}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
222+
{9FFDECAB-94D6-7EB1-1A5B-487492600755}.Debug|Any CPU.Build.0 = Debug|Any CPU
223+
{9FFDECAB-94D6-7EB1-1A5B-487492600755}.Release|Any CPU.ActiveCfg = Release|Any CPU
224+
{9FFDECAB-94D6-7EB1-1A5B-487492600755}.Release|Any CPU.Build.0 = Release|Any CPU
207225
EndGlobalSection
208226
GlobalSection(SolutionProperties) = preSolution
209227
HideSolutionNode = FALSE
@@ -240,6 +258,9 @@ Global
240258
{58BD3C7A-087C-4ECB-87C6-A3445025BEF5} = {A960D001-40B3-4B1A-A890-D1049FB7586E}
241259
{AF5B5402-7C9A-4E5E-B0C2-9278BAE0435C} = {A960D001-40B3-4B1A-A890-D1049FB7586E}
242260
{1A313326-988F-4FF2-992E-6D7E50DCF598} = {0BA39F07-84D6-420B-82D3-6DC3AF016C65}
261+
{4FCCBD72-8E9B-D74B-6538-D8684D181230} = {3D822DC2-ED2E-4434-BC4F-CE7FCD846B02}
262+
{24CBBC97-409E-BAC8-0553-D260AB0B8C6A} = {3D822DC2-ED2E-4434-BC4F-CE7FCD846B02}
263+
{9FFDECAB-94D6-7EB1-1A5B-487492600755} = {A960D001-40B3-4B1A-A890-D1049FB7586E}
243264
EndGlobalSection
244265
GlobalSection(ExtensibilityGlobals) = postSolution
245266
SolutionGuid = {949367A4-5683-4FD3-93F4-A2CEA6EECB21}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
<PropertyGroup>
3+
<TargetFrameworks>net472</TargetFrameworks>
4+
<AssemblyName>CborProtocol.Tests</AssemblyName>
5+
<PackageId>CborProtocol.Tests</PackageId>
6+
<GenerateAssemblyTitleAttribute>false</GenerateAssemblyTitleAttribute>
7+
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute>
8+
<GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute>
9+
<GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute>
10+
<GenerateAssemblyDescriptionAttribute>false</GenerateAssemblyDescriptionAttribute>
11+
<GenerateAssemblyCopyrightAttribute>false</GenerateAssemblyCopyrightAttribute>
12+
<GenerateAssemblyVersionAttribute>false</GenerateAssemblyVersionAttribute>
13+
<GenerateAssemblyFileVersionAttribute>false</GenerateAssemblyFileVersionAttribute>
14+
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
15+
<LangVersion>Latest</LangVersion>
16+
</PropertyGroup>
17+
<ItemGroup>
18+
<PackageReference Include="xunit" Version="2.9.3" />
19+
<PackageReference Include="xunit.runner.visualstudio" Version="3.1.1">
20+
<PrivateAssets>all</PrivateAssets>
21+
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
22+
</PackageReference>
23+
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.14.1" />
24+
</ItemGroup>
25+
26+
<ItemGroup>
27+
<ProjectReference Include="../../../sdk/src/Core/AWSSDK.Core.NetFramework.csproj" />
28+
<ProjectReference Include="../../src/AWSSDK.Extensions.CborProtocol/AWSSDK.Extensions.CborProtocol.NetFramework.csproj" />
29+
</ItemGroup>
30+
</Project>
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
using System;
2+
using System.Formats.Cbor;
3+
using Xunit;
4+
using AWSSDK.Extensions.CborProtocol;
5+
6+
namespace Amazon.CborProtocol.Tests;
7+
8+
public class WriteDateTimeTests
9+
{
10+
[Theory]
11+
[InlineData("1969-12-31T23:59:59Z", -1.0, CborReaderState.NegativeInteger, 2)]
12+
[InlineData("1970-01-01T00:00:01Z", 1.0, CborReaderState.UnsignedInteger, 2)]
13+
[InlineData("1970-01-01T00:00:00.500Z", 0.5, CborReaderState.SinglePrecisionFloat, 6)]
14+
[InlineData("2025-01-01T00:00:00Z", 1735689600.0, CborReaderState.UnsignedInteger, 6)]
15+
[InlineData("2025-06-19T20:15:28.468Z", 1750364128.468, CborReaderState.DoublePrecisionFloat, 10)]
16+
public void WriteDateTime_EncodesCorrectly(string isoDate, double expectedUnixEpoch, CborReaderState expectedState, int expectedTotalBytes)
17+
{
18+
var dt = DateTime.Parse(isoDate).ToUniversalTime();
19+
var writer = new CborWriter();
20+
writer.WriteDateTime(dt);
21+
22+
var encoded = writer.Encode();
23+
var reader = new CborReader(encoded);
24+
var tag = reader.ReadTag();
25+
26+
Assert.Equal(CborTag.UnixTimeSeconds, tag);
27+
Assert.Equal(expectedState, reader.PeekState());
28+
29+
double value = 0;
30+
31+
if (expectedState == CborReaderState.SinglePrecisionFloat)
32+
value = reader.ReadSingle();
33+
else if (expectedState == CborReaderState.DoublePrecisionFloat)
34+
value = reader.ReadDouble();
35+
else if (expectedState == CborReaderState.UnsignedInteger)
36+
value = reader.ReadUInt64();
37+
else if (expectedState == CborReaderState.NegativeInteger)
38+
value = reader.ReadInt64();
39+
else
40+
Assert.Fail($"CBOR state not found: ${reader.PeekState()}");
41+
42+
Assert.Equal(expectedUnixEpoch, value);
43+
Assert.Equal(expectedTotalBytes, encoded.Length);
44+
}
45+
}
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
using System.Formats.Cbor;
2+
using Xunit;
3+
using AWSSDK.Extensions.CborProtocol;
4+
5+
namespace Amazon.CborProtocol.Tests;
6+
7+
public class WriteOptimizedNumberTests
8+
{
9+
[Theory]
10+
[InlineData(0, 1)] // Fits in initial byte (major type + value)
11+
[InlineData(23, 1)] // Still in initial byte
12+
[InlineData(24, 2)] // One additional byte for UInt8
13+
[InlineData(255, 2)] // UInt8
14+
[InlineData(256, 3)] // UInt16
15+
[InlineData(65535, 3)] // UInt16 max
16+
[InlineData(65536, 5)] // UInt32
17+
[InlineData(uint.MaxValue, 5)] // UInt32
18+
[InlineData((long)uint.MaxValue + 1, 9)] // UInt64
19+
public void WriteOptimizedNumber_UsesExpectedEncodingLength_ForUInt64(double value, int expectedBytes)
20+
{
21+
var writer = new CborWriter();
22+
writer.WriteOptimizedNumber((double)value);
23+
var encoded = writer.Encode();
24+
25+
Assert.Equal(expectedBytes, encoded.Length);
26+
}
27+
28+
[Theory]
29+
[InlineData(-1, 1)] // Negative integers encoded compactly
30+
[InlineData(-24, 1)]
31+
[InlineData(-25, 2)] // Beyond negative byte range
32+
[InlineData(int.MinValue, 5)] // Should require full 32 bits
33+
[InlineData(long.MinValue, 9)] // Full 64-bit negative integer
34+
public void WriteOptimizedNumber_UsesExpectedEncodingLength_ForNegativeIntegers(long value, int expectedBytes)
35+
{
36+
var writer = new CborWriter();
37+
writer.WriteOptimizedNumber((double)value);
38+
var encoded = writer.Encode();
39+
40+
Assert.Equal(expectedBytes, encoded.Length);
41+
}
42+
43+
[Theory]
44+
[InlineData(1.5, 5, 0xFA)] // float32 marker + 4 bytes
45+
[InlineData(123456789.12345, 9, 0xFB)] // Doesn't fit in float32
46+
public void WriteOptimizedNumber_Float32_IsManuallyEncodedAsFiveBytes(double value, int expectedBytes, byte floatMarker)
47+
{
48+
var writer = new CborWriter();
49+
writer.WriteOptimizedNumber(value);
50+
var encoded = writer.Encode();
51+
52+
Assert.Equal(expectedBytes, encoded.Length);
53+
Assert.Equal(floatMarker, encoded[0]); // Check float32 CBOR marker
54+
}
55+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
2+
{
3+
"core": {
4+
"changeLogMessages": [
5+
"Add support for RPCv2 CBOR protocol."
6+
],
7+
"type": "patch",
8+
"updateMinimum": false
9+
}
10+
}

generator/ProtocolTestsGenerator/settings.gradle.kts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@ dependencyResolutionManagement {
1313
versionCatalogs {
1414
create("codegen") {
1515
version("smithy", "1.60.3")
16-
library("protocol-tests", "software.amazon.smithy", "smithy-aws-protocol-tests").versionRef("smithy")
16+
library("protocol-tests", "software.amazon.smithy", "smithy-protocol-tests").versionRef("smithy")
17+
library("protocol-aws-tests", "software.amazon.smithy", "smithy-aws-protocol-tests").versionRef("smithy")
1718
library("codegen-core", "software.amazon.smithy", "smithy-codegen-core").versionRef("smithy")
1819
library("protocol-tests-traits", "software.amazon.smithy", "smithy-protocol-test-traits").versionRef("smithy")
1920
library("aws-traits", "software.amazon.smithy", "smithy-aws-traits").versionRef("smithy")

generator/ProtocolTestsGenerator/smithy-dotnet-codegen/src/main/java/software/amazon/smithy/dotnet/codegen/HttpProtocolTestGenerator.java

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
package software.amazon.smithy.dotnet.codegen;
1717

1818
import software.amazon.smithy.aws.traits.ServiceTrait;
19+
import software.amazon.smithy.model.traits.TitleTrait;
1920
import software.amazon.smithy.codegen.core.CodegenException;
2021
import software.amazon.smithy.dotnet.codegen.utils.ProtocolTestUtils;
2122
import software.amazon.smithy.model.Model;
@@ -51,7 +52,14 @@ public HttpProtocolTestGenerator(
5152
this.model = context.model();
5253
this.service = settings.getService(model);
5354
this.context = context;
54-
this.serviceNamespace = service.getTrait(ServiceTrait.class).get().getSdkId().replace(" ", "");
55+
56+
String serviceNamespace = null;
57+
if(service.getTrait(ServiceTrait.class).isPresent())
58+
serviceNamespace = service.getTrait(ServiceTrait.class).get().getSdkId();
59+
else if(service.getTrait(TitleTrait.class).isPresent())
60+
serviceNamespace = service.getTrait(TitleTrait.class).get().getValue().replace("Service", "");
61+
62+
this.serviceNamespace = serviceNamespace.replace(" ", "");
5563
}
5664

5765
@Override
@@ -60,6 +68,8 @@ public void run() {
6068
OperationIndex operationIndex = OperationIndex.of(model);
6169
for (OperationShape operation : new TreeSet<>(topDownIndex.getContainedOperations(service))) {
6270
var operationName = operation.getId().getName();
71+
if (ProtocolTestCustomizations.OperationsToSkip.contains(operationName))
72+
continue;
6373
context.writerDelegator().useFileWriter(operationName + ".cs", serviceName, writer -> {
6474
this.writer = writer;
6575
addServiceProtocolSpecificImports();
@@ -87,16 +97,18 @@ private void addServiceProtocolSpecificImports() {
8797
} else if (this.serviceName.toLowerCase().contains("xml")) {
8898
writer.addImport(serviceName, "System.Xml");
8999
writer.addImport(serviceName, "System.Xml.Linq");
100+
} else if (this.serviceName.toLowerCase().contains("rpcv2")) {
101+
writer.addImport(serviceName, "AWSSDK.Extensions.CborProtocol.Internal");
90102
}
91103
}
92104

93105
private void generateErrorResponseTests(OperationShape operation, OperationIndex index) {
94106
for (StructureShape error : index.getErrors(operation, service)) {
95107
error.getTrait(HttpResponseTestsTrait.class).ifPresent(trait -> {
96108
for (HttpResponseTestCase httpResponseTestCase : trait.getTestCasesFor(AppliesTo.CLIENT)) {
97-
if (!ProtocolTestCustomizations.TestsToSkip.contains(httpResponseTestCase.getId())){
109+
if(!ProtocolTestCustomizations.TestsToSkip.contains(httpResponseTestCase.getId())&&
110+
!trait.getTestCasesFor(AppliesTo.CLIENT).getFirst().getProtocol().getName().toLowerCase().contains("cbor")) // Skip CBOR response tests until the unmarshallers are ready
98111
generateErrorResponseTest(operation, error, httpResponseTestCase);
99-
}
100112
}
101113
});
102114
}
@@ -285,6 +297,9 @@ private void assertRequestBody(HttpRequestTestCase httpRequestTestCase) {
285297
} else if (httpRequestTestCase.getProtocol().getName().equals("restXml")) {
286298
writer.write("var expectedBody = $S;", httpRequestTestCase.getBody());
287299
writer.write("XmlTestUtils.AssertBody(marshalledRequest,expectedBody);");
300+
} else if (this.marshallerType.equals("Cbor")) {
301+
writer.write("var expectedBody = $S;", httpRequestTestCase.getBody());
302+
writer.write("CborProtocolUtils.AssertBody(marshalledRequest, expectedBody);");
288303
} else {
289304
throw new CodegenException("Unsupported protocol detected while generating request test block.");
290305
}
@@ -296,7 +311,8 @@ private void generateResponseTests(OperationShape operation) {
296311
setMarshallerType(trait.getTestCasesFor(AppliesTo.CLIENT).getFirst().getProtocol().getName());
297312
}
298313
for (HttpResponseTestCase httpResponseTestCase : trait.getTestCasesFor(AppliesTo.CLIENT)) {
299-
if (ProtocolTestCustomizations.TestsToSkip.contains(httpResponseTestCase.getId()) || httpResponseTestCase.hasTag("defaults"))
314+
if (ProtocolTestCustomizations.TestsToSkip.contains(httpResponseTestCase.getId()) || httpResponseTestCase.hasTag("defaults")
315+
|| trait.getTestCasesFor(AppliesTo.CLIENT).getFirst().getProtocol().getName().toLowerCase().contains("cbor")) // Skip CBOR response tests until the unmarshallers are ready
300316
continue;
301317
generateResponseTest(operation, httpResponseTestCase);
302318
}
@@ -345,6 +361,8 @@ private void setMarshallerType(String protocol) {
345361
this.marshallerType = "Json";
346362
} else if (protocol.toLowerCase().contains("xml") || protocol.toLowerCase().contains("query")) {
347363
this.marshallerType = "Xml";
364+
} else if (protocol.toLowerCase().contains("cbor")) {
365+
this.marshallerType = "Cbor";
348366
}
349367
}
350368

generator/ProtocolTestsGenerator/smithy-dotnet-codegen/src/main/java/software/amazon/smithy/dotnet/codegen/customizations/ProtocolTestCustomizations.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,14 @@ private ProtocolTestCustomizations() {
2020
"SparseBooleanMap",
2121
"SparseNumberMap"
2222
);
23+
24+
// These operations don't exist in C2J
25+
public static final List<String> OperationsToSkip = Arrays.asList(
26+
"RpcV2CborSparseMaps",
27+
"OperationWithDefaults",
28+
"SparseNullsOperation"
29+
);
30+
2331
//The rename is written in smithy and since we're generating from the C2J structures we will skip this test.
2432
public static final List<String> TestsToSkip = Arrays.asList(
2533
"RestJsonSerializeRenamedStructureUnionValue",

generator/ProtocolTestsGenerator/smithy-dotnet-protocol-test/build.gradle.kts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ repositories {
2727

2828
dependencies {
2929
implementation(project(":smithy-dotnet-codegen"))
30+
implementation(codegen.protocol.aws.tests)
3031
implementation(codegen.protocol.tests)
3132
}
3233

generator/ProtocolTestsGenerator/smithy-dotnet-protocol-test/smithy-build.json

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,24 @@
145145
"packageVersion": "0.0.1"
146146
}
147147
}
148+
},
149+
"RpcV2Protocol": {
150+
"transforms": [
151+
{
152+
"name": "includeServices",
153+
"args": {
154+
"services": [
155+
"smithy.protocoltests.rpcv2Cbor#RpcV2Protocol"
156+
]
157+
}
158+
}
159+
],
160+
"plugins": {
161+
"dotnet-protocol-test-codegen": {
162+
"service": "smithy.protocoltests.rpcv2Cbor#RpcV2Protocol",
163+
"packageVersion": "0.0.1"
164+
}
165+
}
148166
}
149167
}
150168
}

0 commit comments

Comments
 (0)