From 5bb045fff63c878c1048af3a9177ff3a6f8ad24b Mon Sep 17 00:00:00 2001 From: RanVaknin <50976344+RanVaknin@users.noreply.github.com> Date: Thu, 19 Jun 2025 11:10:35 -0700 Subject: [PATCH 01/10] Adding compatibility tests and version constant to each service module --- .../tasks/CommonInternalGeneratorTasks.java | 20 ++++++ .../awssdk/codegen/poet/PoetExtension.java | 4 ++ .../client/specs/ServiceVersionInfoSpec.java | 64 +++++++++++++++++++ .../specs/VersionCompatibilityTestSpec.java | 63 ++++++++++++++++++ .../client/ServiceVersionInfoSpecTest.java | 63 ++++++++++++++++++ .../test-service-version-info-class.java | 15 +++++ .../testing/BaseVersionCompatibilityTest.java | 26 ++++++++ 7 files changed, 255 insertions(+) create mode 100644 codegen/src/main/java/software/amazon/awssdk/codegen/poet/client/specs/ServiceVersionInfoSpec.java create mode 100644 codegen/src/main/java/software/amazon/awssdk/codegen/poet/client/specs/VersionCompatibilityTestSpec.java create mode 100644 codegen/src/test/java/software/amazon/awssdk/codegen/poet/client/ServiceVersionInfoSpecTest.java create mode 100644 codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/specs/test-service-version-info-class.java create mode 100644 test/ruleset-testing-core/src/main/java/software/amazon/awssdk/core/rules/testing/BaseVersionCompatibilityTest.java diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/emitters/tasks/CommonInternalGeneratorTasks.java b/codegen/src/main/java/software/amazon/awssdk/codegen/emitters/tasks/CommonInternalGeneratorTasks.java index 1bafba5eed5d..5434c8643f2d 100644 --- a/codegen/src/main/java/software/amazon/awssdk/codegen/emitters/tasks/CommonInternalGeneratorTasks.java +++ b/codegen/src/main/java/software/amazon/awssdk/codegen/emitters/tasks/CommonInternalGeneratorTasks.java @@ -20,8 +20,11 @@ import software.amazon.awssdk.codegen.emitters.GeneratorTask; import software.amazon.awssdk.codegen.emitters.GeneratorTaskParams; import software.amazon.awssdk.codegen.emitters.PoetGeneratorTask; +import software.amazon.awssdk.codegen.internal.Utils; import software.amazon.awssdk.codegen.poet.client.EnvironmentTokenSystemSettingsClass; import software.amazon.awssdk.codegen.poet.client.SdkClientOptions; +import software.amazon.awssdk.codegen.poet.client.specs.ServiceVersionInfoSpec; +import software.amazon.awssdk.codegen.poet.client.specs.VersionCompatibilityTestSpec; import software.amazon.awssdk.codegen.poet.common.UserAgentUtilsSpec; public class CommonInternalGeneratorTasks extends BaseGeneratorTasks { @@ -40,6 +43,8 @@ protected List createTasks() throws Exception { if (params.getModel().getCustomizationConfig().isEnableEnvironmentBearerToken()) { tasks.add(createEnvironmentTokenSystemSettingTask()); } + tasks.add(createServiceVersionInfoTask()); + tasks.add(createVersionCompatibilityTestTask()); return tasks; } @@ -58,6 +63,21 @@ private GeneratorTask createEnvironmentTokenSystemSettingTask() { new EnvironmentTokenSystemSettingsClass(params.getModel())); } + private GeneratorTask createServiceVersionInfoTask() { + return new PoetGeneratorTask(clientOptionsDir(), params.getModel().getFileHeader(), + new ServiceVersionInfoSpec(params.getModel())); + } + + private GeneratorTask createVersionCompatibilityTestTask() { + return new PoetGeneratorTask(testDir(), params.getModel().getFileHeader(), + new VersionCompatibilityTestSpec(params.getModel())); + } + + private String testDir() { + return params.getPathProvider().getTestDirectory() + "/" + + Utils.packageToDirectory(params.getModel().getMetadata().getFullClientInternalPackageName()); + } + private String clientOptionsDir() { return params.getPathProvider().getClientInternalDirectory(); } diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/PoetExtension.java b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/PoetExtension.java index 4112188c6451..f119507809c2 100644 --- a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/PoetExtension.java +++ b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/PoetExtension.java @@ -79,6 +79,10 @@ public ClassName getUserAgentClass() { return ClassName.get(model.getMetadata().getFullClientInternalPackageName(), "UserAgentUtils"); } + public ClassName getServiceVersionInfoClass() { + return ClassName.get(model.getMetadata().getFullClientInternalPackageName(), "ServiceVersionInfo"); + } + public ClassName getEnvironmentTokenSystemSettingsClass() { return ClassName.get(model.getMetadata().getFullClientInternalPackageName(), "EnvironmentTokenSystemSettings"); } diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/client/specs/ServiceVersionInfoSpec.java b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/client/specs/ServiceVersionInfoSpec.java new file mode 100644 index 000000000000..3aeeecc018d7 --- /dev/null +++ b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/client/specs/ServiceVersionInfoSpec.java @@ -0,0 +1,64 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package software.amazon.awssdk.codegen.poet.client.specs; + +import static software.amazon.awssdk.core.util.VersionInfo.SDK_VERSION; + +import com.squareup.javapoet.ClassName; +import com.squareup.javapoet.FieldSpec; +import com.squareup.javapoet.MethodSpec; +import com.squareup.javapoet.TypeSpec; +import software.amazon.awssdk.codegen.model.intermediate.IntermediateModel; +import software.amazon.awssdk.codegen.poet.ClassSpec; +import software.amazon.awssdk.codegen.poet.PoetExtension; +import software.amazon.awssdk.codegen.poet.PoetUtils; + +import javax.lang.model.element.Modifier; + +public class ServiceVersionInfoSpec implements ClassSpec { + private final PoetExtension poetExtension; + + public ServiceVersionInfoSpec(IntermediateModel model) { + this.poetExtension = new PoetExtension(model); + } + + @Override + public TypeSpec poetSpec() { + TypeSpec.Builder builder = TypeSpec.classBuilder("ServiceVersionInfo") + .addModifiers(Modifier.PUBLIC, Modifier.FINAL) + .addAnnotation(PoetUtils.generatedAnnotation()) + .addField(FieldSpec.builder( + String.class, "VERSION", Modifier.PUBLIC, Modifier.STATIC, Modifier.FINAL) + .initializer("$S", SDK_VERSION) + .addJavadoc("Returns the current version for the AWS SDK in which" + + " this class is running.") + .build()) + .addMethod(privateConstructor()); + + return builder.build(); + } + + protected MethodSpec privateConstructor() { + return MethodSpec.constructorBuilder() + .addModifiers(Modifier.PRIVATE) + .build(); + } + + @Override + public ClassName className() { + return poetExtension.getServiceVersionInfoClass(); + } +} diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/client/specs/VersionCompatibilityTestSpec.java b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/client/specs/VersionCompatibilityTestSpec.java new file mode 100644 index 000000000000..04cca08e9e0b --- /dev/null +++ b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/client/specs/VersionCompatibilityTestSpec.java @@ -0,0 +1,63 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package software.amazon.awssdk.codegen.poet.client.specs; + +import com.squareup.javapoet.ClassName; +import com.squareup.javapoet.MethodSpec; +import com.squareup.javapoet.TypeSpec; +import org.junit.jupiter.api.Test; +import software.amazon.awssdk.codegen.model.intermediate.IntermediateModel; +import software.amazon.awssdk.codegen.poet.ClassSpec; +import software.amazon.awssdk.codegen.poet.PoetUtils; + +import javax.lang.model.element.Modifier; +import software.amazon.awssdk.core.rules.testing.BaseVersionCompatibilityTest; + +public class VersionCompatibilityTestSpec implements ClassSpec { + private final IntermediateModel model; + + public VersionCompatibilityTestSpec(IntermediateModel model) { + this.model = model; + } + + @Override + public TypeSpec poetSpec() { + return PoetUtils.createClassBuilder(className()) + .superclass(BaseVersionCompatibilityTest.class) + .addModifiers(Modifier.PUBLIC) + .addMethod(compatibilityTest()) + .build(); + } + + @Override + public ClassName className() { + return ClassName.get(model.getMetadata().getFullClientPackageName(), "VersionCompatibilityTest"); + } + + private MethodSpec compatibilityTest() { + ClassName serviceVersionInfo = ClassName.get( + model.getMetadata().getFullInternalPackageName(), + "ServiceVersionInfo" + ); + + return MethodSpec.methodBuilder("checkCompatibility") + .addModifiers(Modifier.PUBLIC) + .addAnnotation(Test.class) + .returns(void.class) + .addStatement("verifyVersionCompatibility($T.VERSION)", serviceVersionInfo) + .build(); + } +} diff --git a/codegen/src/test/java/software/amazon/awssdk/codegen/poet/client/ServiceVersionInfoSpecTest.java b/codegen/src/test/java/software/amazon/awssdk/codegen/poet/client/ServiceVersionInfoSpecTest.java new file mode 100644 index 000000000000..5a5d0e5d28d0 --- /dev/null +++ b/codegen/src/test/java/software/amazon/awssdk/codegen/poet/client/ServiceVersionInfoSpecTest.java @@ -0,0 +1,63 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package software.amazon.awssdk.codegen.poet.client; + +import static org.assertj.core.api.AssertionsForClassTypes.assertThat; + +import com.squareup.javapoet.JavaFile; +import com.squareup.javapoet.TypeSpec; +import java.io.InputStream; +import java.util.Scanner; +import org.junit.jupiter.api.Test; +import software.amazon.awssdk.codegen.poet.ClassSpec; +import software.amazon.awssdk.codegen.poet.ClientTestModels; +import software.amazon.awssdk.codegen.poet.client.specs.ServiceVersionInfoSpec; +import software.amazon.awssdk.core.util.VersionInfo; + +public class ServiceVersionInfoSpecTest { + + // a fixture test that dynamically updates the generated fixture with the current version + // this is needed because every time codegen runs, the version will change. + // we need a way to generate the fixture, and then edit it in place with the current version and only then make the assertion. + @Test + void testServiceVersionInfoClass() { + String currVersion = VersionInfo.SDK_VERSION; + ClassSpec serviceVersionInfoSpec = new ServiceVersionInfoSpec(ClientTestModels.restJsonServiceModels()); + + String expectedContent = loadFixtureFile("test-service-version-info-class.java"); + String[] parts = expectedContent.split("public static final String VERSION = \""); + if (parts.length == 2) { + String privateConstructor = parts[1].substring(parts[1].indexOf("\"")); + expectedContent = parts[0] + "public static final String VERSION = \"" + currVersion + + privateConstructor; + } + + String actualContent = generateContent(serviceVersionInfoSpec); + + assertThat(actualContent).isEqualTo(expectedContent); + } + + private String loadFixtureFile(String filename) { + InputStream is = getClass().getResourceAsStream("specs/" + filename); + return new Scanner(is).useDelimiter("\\A").next(); + } + + private String generateContent(ClassSpec spec) { + TypeSpec typeSpec = spec.poetSpec(); + JavaFile javaFile = JavaFile.builder(spec.className().packageName(), typeSpec).build(); + return javaFile.toString(); + } +} diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/specs/test-service-version-info-class.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/specs/test-service-version-info-class.java new file mode 100644 index 000000000000..62d60b103745 --- /dev/null +++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/specs/test-service-version-info-class.java @@ -0,0 +1,15 @@ +package software.amazon.awssdk.services.json.internal; + +import java.lang.String; +import software.amazon.awssdk.annotations.Generated; + +@Generated("software.amazon.awssdk:codegen") +public final class ServiceVersionInfo { + /** + * Returns the current version for the AWS SDK in which this class is running. + */ + public static final String VERSION = "{{VERSION}}"; + + private ServiceVersionInfo() { + } +} diff --git a/test/ruleset-testing-core/src/main/java/software/amazon/awssdk/core/rules/testing/BaseVersionCompatibilityTest.java b/test/ruleset-testing-core/src/main/java/software/amazon/awssdk/core/rules/testing/BaseVersionCompatibilityTest.java new file mode 100644 index 000000000000..6f7c3ade1085 --- /dev/null +++ b/test/ruleset-testing-core/src/main/java/software/amazon/awssdk/core/rules/testing/BaseVersionCompatibilityTest.java @@ -0,0 +1,26 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package software.amazon.awssdk.core.rules.testing; + +import static org.assertj.core.api.Assertions.assertThat; + +import software.amazon.awssdk.core.util.VersionInfo; + +public class BaseVersionCompatibilityTest { + protected final void verifyVersionCompatibility(String serviceVersion) { + assertThat(VersionInfo.SDK_VERSION).isEqualTo(serviceVersion); + } +} From dfc62bb433240f338b18701f05503e9b9a24993f Mon Sep 17 00:00:00 2001 From: RanVaknin <50976344+RanVaknin@users.noreply.github.com> Date: Thu, 19 Jun 2025 11:20:58 -0700 Subject: [PATCH 02/10] Add changelog --- .changes/next-release/feature-AWSSDKforJavav2-382b343.json | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 .changes/next-release/feature-AWSSDKforJavav2-382b343.json diff --git a/.changes/next-release/feature-AWSSDKforJavav2-382b343.json b/.changes/next-release/feature-AWSSDKforJavav2-382b343.json new file mode 100644 index 000000000000..ec4fc74f7815 --- /dev/null +++ b/.changes/next-release/feature-AWSSDKforJavav2-382b343.json @@ -0,0 +1,6 @@ +{ + "type": "feature", + "category": "AWS SDK for Java v2", + "contributor": "", + "description": "Adding compatibility tests between sdk-core and service packages" +} From 06efd2bf40eb0735832f1c7069e689142f9762ac Mon Sep 17 00:00:00 2001 From: RanVaknin <50976344+RanVaknin@users.noreply.github.com> Date: Fri, 20 Jun 2025 14:36:36 -0700 Subject: [PATCH 03/10] Remove BaseVersionCompatibilityTest --- .../specs/VersionCompatibilityTestSpec.java | 11 +++++--- .../core/BaseVersionCompatibilityTest.java | 26 +++++++++++++++++++ 2 files changed, 34 insertions(+), 3 deletions(-) create mode 100644 core/sdk-core/src/test/java/software/amazon/awssdk/core/BaseVersionCompatibilityTest.java diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/client/specs/VersionCompatibilityTestSpec.java b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/client/specs/VersionCompatibilityTestSpec.java index 04cca08e9e0b..e3895d6b6dfb 100644 --- a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/client/specs/VersionCompatibilityTestSpec.java +++ b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/client/specs/VersionCompatibilityTestSpec.java @@ -24,7 +24,6 @@ import software.amazon.awssdk.codegen.poet.PoetUtils; import javax.lang.model.element.Modifier; -import software.amazon.awssdk.core.rules.testing.BaseVersionCompatibilityTest; public class VersionCompatibilityTestSpec implements ClassSpec { private final IntermediateModel model; @@ -36,7 +35,6 @@ public VersionCompatibilityTestSpec(IntermediateModel model) { @Override public TypeSpec poetSpec() { return PoetUtils.createClassBuilder(className()) - .superclass(BaseVersionCompatibilityTest.class) .addModifiers(Modifier.PUBLIC) .addMethod(compatibilityTest()) .build(); @@ -53,11 +51,18 @@ private MethodSpec compatibilityTest() { "ServiceVersionInfo" ); + ClassName versionInfo = ClassName.get("software.amazon.awssdk.core.util", "VersionInfo"); + ClassName assertions = ClassName.get("org.assertj.core.api", "Assertions"); + return MethodSpec.methodBuilder("checkCompatibility") .addModifiers(Modifier.PUBLIC) .addAnnotation(Test.class) .returns(void.class) - .addStatement("verifyVersionCompatibility($T.VERSION)", serviceVersionInfo) + .addStatement("$T.assertThat($T.SDK_VERSION).isEqualTo($T.VERSION)", + assertions, + versionInfo, + serviceVersionInfo) .build(); } + } diff --git a/core/sdk-core/src/test/java/software/amazon/awssdk/core/BaseVersionCompatibilityTest.java b/core/sdk-core/src/test/java/software/amazon/awssdk/core/BaseVersionCompatibilityTest.java new file mode 100644 index 000000000000..206ed79d9601 --- /dev/null +++ b/core/sdk-core/src/test/java/software/amazon/awssdk/core/BaseVersionCompatibilityTest.java @@ -0,0 +1,26 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package software.amazon.awssdk.core; + +import static org.assertj.core.api.Assertions.assertThat; + +import software.amazon.awssdk.core.util.VersionInfo; + +public class BaseVersionCompatibilityTest { + protected final void verifyVersionCompatibility(String serviceVersion) { + assertThat(VersionInfo.SDK_VERSION).isEqualTo(serviceVersion); + } +} From 9649f5376f4d505a1827f4f3d7e4eb46acfc69d8 Mon Sep 17 00:00:00 2001 From: RanVaknin <50976344+RanVaknin@users.noreply.github.com> Date: Fri, 20 Jun 2025 15:09:41 -0700 Subject: [PATCH 04/10] Remove unused BaseVersionCompatibilityTest files --- .../core/BaseVersionCompatibilityTest.java | 26 ------------------- .../testing/BaseVersionCompatibilityTest.java | 26 ------------------- 2 files changed, 52 deletions(-) delete mode 100644 core/sdk-core/src/test/java/software/amazon/awssdk/core/BaseVersionCompatibilityTest.java delete mode 100644 test/ruleset-testing-core/src/main/java/software/amazon/awssdk/core/rules/testing/BaseVersionCompatibilityTest.java diff --git a/core/sdk-core/src/test/java/software/amazon/awssdk/core/BaseVersionCompatibilityTest.java b/core/sdk-core/src/test/java/software/amazon/awssdk/core/BaseVersionCompatibilityTest.java deleted file mode 100644 index 206ed79d9601..000000000000 --- a/core/sdk-core/src/test/java/software/amazon/awssdk/core/BaseVersionCompatibilityTest.java +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - */ - -package software.amazon.awssdk.core; - -import static org.assertj.core.api.Assertions.assertThat; - -import software.amazon.awssdk.core.util.VersionInfo; - -public class BaseVersionCompatibilityTest { - protected final void verifyVersionCompatibility(String serviceVersion) { - assertThat(VersionInfo.SDK_VERSION).isEqualTo(serviceVersion); - } -} diff --git a/test/ruleset-testing-core/src/main/java/software/amazon/awssdk/core/rules/testing/BaseVersionCompatibilityTest.java b/test/ruleset-testing-core/src/main/java/software/amazon/awssdk/core/rules/testing/BaseVersionCompatibilityTest.java deleted file mode 100644 index 6f7c3ade1085..000000000000 --- a/test/ruleset-testing-core/src/main/java/software/amazon/awssdk/core/rules/testing/BaseVersionCompatibilityTest.java +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - */ - -package software.amazon.awssdk.core.rules.testing; - -import static org.assertj.core.api.Assertions.assertThat; - -import software.amazon.awssdk.core.util.VersionInfo; - -public class BaseVersionCompatibilityTest { - protected final void verifyVersionCompatibility(String serviceVersion) { - assertThat(VersionInfo.SDK_VERSION).isEqualTo(serviceVersion); - } -} From 63c51e20bdf5baa8358b6edadede838378e81c21 Mon Sep 17 00:00:00 2001 From: RanVaknin <50976344+RanVaknin@users.noreply.github.com> Date: Fri, 20 Jun 2025 16:14:36 -0700 Subject: [PATCH 05/10] Checkstyle fix --- .../codegen/poet/client/specs/ServiceVersionInfoSpec.java | 3 +-- .../poet/client/specs/VersionCompatibilityTestSpec.java | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/client/specs/ServiceVersionInfoSpec.java b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/client/specs/ServiceVersionInfoSpec.java index 3aeeecc018d7..00963197bdee 100644 --- a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/client/specs/ServiceVersionInfoSpec.java +++ b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/client/specs/ServiceVersionInfoSpec.java @@ -21,13 +21,12 @@ import com.squareup.javapoet.FieldSpec; import com.squareup.javapoet.MethodSpec; import com.squareup.javapoet.TypeSpec; +import javax.lang.model.element.Modifier; import software.amazon.awssdk.codegen.model.intermediate.IntermediateModel; import software.amazon.awssdk.codegen.poet.ClassSpec; import software.amazon.awssdk.codegen.poet.PoetExtension; import software.amazon.awssdk.codegen.poet.PoetUtils; -import javax.lang.model.element.Modifier; - public class ServiceVersionInfoSpec implements ClassSpec { private final PoetExtension poetExtension; diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/client/specs/VersionCompatibilityTestSpec.java b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/client/specs/VersionCompatibilityTestSpec.java index e3895d6b6dfb..435d967a32f6 100644 --- a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/client/specs/VersionCompatibilityTestSpec.java +++ b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/client/specs/VersionCompatibilityTestSpec.java @@ -18,12 +18,12 @@ import com.squareup.javapoet.ClassName; import com.squareup.javapoet.MethodSpec; import com.squareup.javapoet.TypeSpec; +import javax.lang.model.element.Modifier; import org.junit.jupiter.api.Test; import software.amazon.awssdk.codegen.model.intermediate.IntermediateModel; import software.amazon.awssdk.codegen.poet.ClassSpec; import software.amazon.awssdk.codegen.poet.PoetUtils; -import javax.lang.model.element.Modifier; public class VersionCompatibilityTestSpec implements ClassSpec { private final IntermediateModel model; From f90abc1918d487e13bd10142bd1e8b243cdfcf94 Mon Sep 17 00:00:00 2001 From: RanVaknin <50976344+RanVaknin@users.noreply.github.com> Date: Mon, 23 Jun 2025 13:21:55 -0700 Subject: [PATCH 06/10] Refactor test to fail only when old version of core is used --- .../specs/VersionCompatibilityTestSpec.java | 41 ++++++++++++++++--- 1 file changed, 36 insertions(+), 5 deletions(-) diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/client/specs/VersionCompatibilityTestSpec.java b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/client/specs/VersionCompatibilityTestSpec.java index 435d967a32f6..3b58df159fd1 100644 --- a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/client/specs/VersionCompatibilityTestSpec.java +++ b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/client/specs/VersionCompatibilityTestSpec.java @@ -24,7 +24,6 @@ import software.amazon.awssdk.codegen.poet.ClassSpec; import software.amazon.awssdk.codegen.poet.PoetUtils; - public class VersionCompatibilityTestSpec implements ClassSpec { private final IntermediateModel model; @@ -37,6 +36,7 @@ public TypeSpec poetSpec() { return PoetUtils.createClassBuilder(className()) .addModifiers(Modifier.PUBLIC) .addMethod(compatibilityTest()) + .addMethod(isVersionCompatibleMethod()) .build(); } @@ -58,11 +58,42 @@ private MethodSpec compatibilityTest() { .addModifiers(Modifier.PUBLIC) .addAnnotation(Test.class) .returns(void.class) - .addStatement("$T.assertThat($T.SDK_VERSION).isEqualTo($T.VERSION)", - assertions, - versionInfo, - serviceVersionInfo) + .addStatement("String coreVersion = $T.SDK_VERSION", versionInfo) + .addStatement("String serviceVersion = $T.VERSION", serviceVersionInfo) + .addStatement("$T.assertThat(isVersionCompatible(coreVersion, serviceVersion))" + + ".withFailMessage(\"Core version %s must be equal to or newer than service version %s\", " + + "coreVersion, serviceVersion).isTrue()", + assertions) .build(); } + private MethodSpec isVersionCompatibleMethod() { + return MethodSpec.methodBuilder("isVersionCompatible") + .addModifiers(Modifier.PRIVATE) + .returns(boolean.class) + .addParameter(String.class, "coreVersion") + .addParameter(String.class, "serviceVersion") + .addStatement("String normalizedCore = coreVersion.replace(\"-SNAPSHOT\", \"\")") + .addStatement("String normalizedService = serviceVersion.replace(\"-SNAPSHOT\", \"\")") + .addStatement("String[] coreParts = normalizedCore.split(\"\\\\.\")") + .addStatement("String[] serviceParts = normalizedService.split(\"\\\\.\")") + .addCode("\n") + .addStatement("int coreMajor = Integer.parseInt(coreParts[0])") + .addStatement("int serviceMajor = Integer.parseInt(serviceParts[0])") + .beginControlFlow("if (coreMajor != serviceMajor)") + .addStatement("return coreMajor >= serviceMajor") + .endControlFlow() + .addCode("\n") + .addStatement("int coreMinor = Integer.parseInt(coreParts[1])") + .addStatement("int serviceMinor = Integer.parseInt(serviceParts[1])") + .beginControlFlow("if (coreMinor != serviceMinor)") + .addStatement("return coreMinor >= serviceMinor") + .endControlFlow() + .addCode("\n") + .addStatement("int corePatch = Integer.parseInt(coreParts[2])") + .addStatement("int servicePatch = Integer.parseInt(serviceParts[2])") + .addStatement("return corePatch >= servicePatch") + .build(); + } } + From d67931be811d5f242aa5d169547cecb4487188e9 Mon Sep 17 00:00:00 2001 From: RanVaknin <50976344+RanVaknin@users.noreply.github.com> Date: Mon, 23 Jun 2025 13:42:52 -0700 Subject: [PATCH 07/10] Checkstyle --- .../poet/client/specs/VersionCompatibilityTestSpec.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/client/specs/VersionCompatibilityTestSpec.java b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/client/specs/VersionCompatibilityTestSpec.java index 3b58df159fd1..7feab76195b3 100644 --- a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/client/specs/VersionCompatibilityTestSpec.java +++ b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/client/specs/VersionCompatibilityTestSpec.java @@ -61,8 +61,8 @@ private MethodSpec compatibilityTest() { .addStatement("String coreVersion = $T.SDK_VERSION", versionInfo) .addStatement("String serviceVersion = $T.VERSION", serviceVersionInfo) .addStatement("$T.assertThat(isVersionCompatible(coreVersion, serviceVersion))" + - ".withFailMessage(\"Core version %s must be equal to or newer than service version %s\", " + - "coreVersion, serviceVersion).isTrue()", + ".withFailMessage(\"Core version %s must be equal to or newer than service version %s\", " + + "coreVersion, serviceVersion).isTrue()", assertions) .build(); } From 4d7be90e1ccdb2e70e8d040a89f31f9dd2834387 Mon Sep 17 00:00:00 2001 From: RanVaknin <50976344+RanVaknin@users.noreply.github.com> Date: Tue, 24 Jun 2025 11:46:02 -0700 Subject: [PATCH 08/10] Remove codegen test --- .../tasks/CommonInternalGeneratorTasks.java | 13 --- .../specs/VersionCompatibilityTestSpec.java | 99 ------------------- 2 files changed, 112 deletions(-) delete mode 100644 codegen/src/main/java/software/amazon/awssdk/codegen/poet/client/specs/VersionCompatibilityTestSpec.java diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/emitters/tasks/CommonInternalGeneratorTasks.java b/codegen/src/main/java/software/amazon/awssdk/codegen/emitters/tasks/CommonInternalGeneratorTasks.java index 5434c8643f2d..c02571f181c0 100644 --- a/codegen/src/main/java/software/amazon/awssdk/codegen/emitters/tasks/CommonInternalGeneratorTasks.java +++ b/codegen/src/main/java/software/amazon/awssdk/codegen/emitters/tasks/CommonInternalGeneratorTasks.java @@ -20,11 +20,9 @@ import software.amazon.awssdk.codegen.emitters.GeneratorTask; import software.amazon.awssdk.codegen.emitters.GeneratorTaskParams; import software.amazon.awssdk.codegen.emitters.PoetGeneratorTask; -import software.amazon.awssdk.codegen.internal.Utils; import software.amazon.awssdk.codegen.poet.client.EnvironmentTokenSystemSettingsClass; import software.amazon.awssdk.codegen.poet.client.SdkClientOptions; import software.amazon.awssdk.codegen.poet.client.specs.ServiceVersionInfoSpec; -import software.amazon.awssdk.codegen.poet.client.specs.VersionCompatibilityTestSpec; import software.amazon.awssdk.codegen.poet.common.UserAgentUtilsSpec; public class CommonInternalGeneratorTasks extends BaseGeneratorTasks { @@ -44,7 +42,6 @@ protected List createTasks() throws Exception { tasks.add(createEnvironmentTokenSystemSettingTask()); } tasks.add(createServiceVersionInfoTask()); - tasks.add(createVersionCompatibilityTestTask()); return tasks; } @@ -68,16 +65,6 @@ private GeneratorTask createServiceVersionInfoTask() { new ServiceVersionInfoSpec(params.getModel())); } - private GeneratorTask createVersionCompatibilityTestTask() { - return new PoetGeneratorTask(testDir(), params.getModel().getFileHeader(), - new VersionCompatibilityTestSpec(params.getModel())); - } - - private String testDir() { - return params.getPathProvider().getTestDirectory() + "/" + - Utils.packageToDirectory(params.getModel().getMetadata().getFullClientInternalPackageName()); - } - private String clientOptionsDir() { return params.getPathProvider().getClientInternalDirectory(); } diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/client/specs/VersionCompatibilityTestSpec.java b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/client/specs/VersionCompatibilityTestSpec.java deleted file mode 100644 index 7feab76195b3..000000000000 --- a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/client/specs/VersionCompatibilityTestSpec.java +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - */ - -package software.amazon.awssdk.codegen.poet.client.specs; - -import com.squareup.javapoet.ClassName; -import com.squareup.javapoet.MethodSpec; -import com.squareup.javapoet.TypeSpec; -import javax.lang.model.element.Modifier; -import org.junit.jupiter.api.Test; -import software.amazon.awssdk.codegen.model.intermediate.IntermediateModel; -import software.amazon.awssdk.codegen.poet.ClassSpec; -import software.amazon.awssdk.codegen.poet.PoetUtils; - -public class VersionCompatibilityTestSpec implements ClassSpec { - private final IntermediateModel model; - - public VersionCompatibilityTestSpec(IntermediateModel model) { - this.model = model; - } - - @Override - public TypeSpec poetSpec() { - return PoetUtils.createClassBuilder(className()) - .addModifiers(Modifier.PUBLIC) - .addMethod(compatibilityTest()) - .addMethod(isVersionCompatibleMethod()) - .build(); - } - - @Override - public ClassName className() { - return ClassName.get(model.getMetadata().getFullClientPackageName(), "VersionCompatibilityTest"); - } - - private MethodSpec compatibilityTest() { - ClassName serviceVersionInfo = ClassName.get( - model.getMetadata().getFullInternalPackageName(), - "ServiceVersionInfo" - ); - - ClassName versionInfo = ClassName.get("software.amazon.awssdk.core.util", "VersionInfo"); - ClassName assertions = ClassName.get("org.assertj.core.api", "Assertions"); - - return MethodSpec.methodBuilder("checkCompatibility") - .addModifiers(Modifier.PUBLIC) - .addAnnotation(Test.class) - .returns(void.class) - .addStatement("String coreVersion = $T.SDK_VERSION", versionInfo) - .addStatement("String serviceVersion = $T.VERSION", serviceVersionInfo) - .addStatement("$T.assertThat(isVersionCompatible(coreVersion, serviceVersion))" + - ".withFailMessage(\"Core version %s must be equal to or newer than service version %s\", " - + "coreVersion, serviceVersion).isTrue()", - assertions) - .build(); - } - - private MethodSpec isVersionCompatibleMethod() { - return MethodSpec.methodBuilder("isVersionCompatible") - .addModifiers(Modifier.PRIVATE) - .returns(boolean.class) - .addParameter(String.class, "coreVersion") - .addParameter(String.class, "serviceVersion") - .addStatement("String normalizedCore = coreVersion.replace(\"-SNAPSHOT\", \"\")") - .addStatement("String normalizedService = serviceVersion.replace(\"-SNAPSHOT\", \"\")") - .addStatement("String[] coreParts = normalizedCore.split(\"\\\\.\")") - .addStatement("String[] serviceParts = normalizedService.split(\"\\\\.\")") - .addCode("\n") - .addStatement("int coreMajor = Integer.parseInt(coreParts[0])") - .addStatement("int serviceMajor = Integer.parseInt(serviceParts[0])") - .beginControlFlow("if (coreMajor != serviceMajor)") - .addStatement("return coreMajor >= serviceMajor") - .endControlFlow() - .addCode("\n") - .addStatement("int coreMinor = Integer.parseInt(coreParts[1])") - .addStatement("int serviceMinor = Integer.parseInt(serviceParts[1])") - .beginControlFlow("if (coreMinor != serviceMinor)") - .addStatement("return coreMinor >= serviceMinor") - .endControlFlow() - .addCode("\n") - .addStatement("int corePatch = Integer.parseInt(coreParts[2])") - .addStatement("int servicePatch = Integer.parseInt(serviceParts[2])") - .addStatement("return corePatch >= servicePatch") - .build(); - } -} - From eaae16eb5e9cc387a9fc6633d2cb7aa75747c085 Mon Sep 17 00:00:00 2001 From: RanVaknin <50976344+RanVaknin@users.noreply.github.com> Date: Tue, 24 Jun 2025 13:10:15 -0700 Subject: [PATCH 09/10] Refactor test, edit changelog --- .../next-release/feature-AWSSDKforJavav2-382b343.json | 2 +- .../poet/client/ServiceVersionInfoSpecTest.java | 10 +++------- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/.changes/next-release/feature-AWSSDKforJavav2-382b343.json b/.changes/next-release/feature-AWSSDKforJavav2-382b343.json index ec4fc74f7815..dbcb0e9dc42f 100644 --- a/.changes/next-release/feature-AWSSDKforJavav2-382b343.json +++ b/.changes/next-release/feature-AWSSDKforJavav2-382b343.json @@ -2,5 +2,5 @@ "type": "feature", "category": "AWS SDK for Java v2", "contributor": "", - "description": "Adding compatibility tests between sdk-core and service packages" + "description": "Adding constant to each SDK module to represent its version" } diff --git a/codegen/src/test/java/software/amazon/awssdk/codegen/poet/client/ServiceVersionInfoSpecTest.java b/codegen/src/test/java/software/amazon/awssdk/codegen/poet/client/ServiceVersionInfoSpecTest.java index 5a5d0e5d28d0..1f5edbaf8dc9 100644 --- a/codegen/src/test/java/software/amazon/awssdk/codegen/poet/client/ServiceVersionInfoSpecTest.java +++ b/codegen/src/test/java/software/amazon/awssdk/codegen/poet/client/ServiceVersionInfoSpecTest.java @@ -16,6 +16,7 @@ package software.amazon.awssdk.codegen.poet.client; import static org.assertj.core.api.AssertionsForClassTypes.assertThat; +import static org.hamcrest.Matchers.equalToIgnoringWhiteSpace; import com.squareup.javapoet.JavaFile; import com.squareup.javapoet.TypeSpec; @@ -38,16 +39,11 @@ void testServiceVersionInfoClass() { ClassSpec serviceVersionInfoSpec = new ServiceVersionInfoSpec(ClientTestModels.restJsonServiceModels()); String expectedContent = loadFixtureFile("test-service-version-info-class.java"); - String[] parts = expectedContent.split("public static final String VERSION = \""); - if (parts.length == 2) { - String privateConstructor = parts[1].substring(parts[1].indexOf("\"")); - expectedContent = parts[0] + "public static final String VERSION = \"" + currVersion - + privateConstructor; - } + expectedContent = expectedContent.replace("{{VERSION}}", currVersion); String actualContent = generateContent(serviceVersionInfoSpec); - assertThat(actualContent).isEqualTo(expectedContent); + assertThat(actualContent).isEqualToIgnoringWhitespace(expectedContent); } private String loadFixtureFile(String filename) { From ec2602ce92a870ac704242de01b9423810b160fb Mon Sep 17 00:00:00 2001 From: RanVaknin <50976344+RanVaknin@users.noreply.github.com> Date: Tue, 24 Jun 2025 20:25:52 -0700 Subject: [PATCH 10/10] Fix comment --- .../codegen/poet/client/ServiceVersionInfoSpecTest.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/codegen/src/test/java/software/amazon/awssdk/codegen/poet/client/ServiceVersionInfoSpecTest.java b/codegen/src/test/java/software/amazon/awssdk/codegen/poet/client/ServiceVersionInfoSpecTest.java index 1f5edbaf8dc9..496a35914030 100644 --- a/codegen/src/test/java/software/amazon/awssdk/codegen/poet/client/ServiceVersionInfoSpecTest.java +++ b/codegen/src/test/java/software/amazon/awssdk/codegen/poet/client/ServiceVersionInfoSpecTest.java @@ -30,9 +30,9 @@ public class ServiceVersionInfoSpecTest { - // a fixture test that dynamically updates the generated fixture with the current version - // this is needed because every time codegen runs, the version will change. - // we need a way to generate the fixture, and then edit it in place with the current version and only then make the assertion. + // Fixture test that compares generated ServiceVersionInfo class against expected output. + // The fixture file uses {{VERSION}} as a placeholder which gets replaced with the current + // SDK version at test time, since the generated code injects the actual version at build time. @Test void testServiceVersionInfoClass() { String currVersion = VersionInfo.SDK_VERSION;