From 2613753954d95424ac412f308171336cf99a76d3 Mon Sep 17 00:00:00 2001 From: Dongie Agnir Date: Thu, 16 Apr 2026 14:47:14 -0700 Subject: [PATCH 1/2] Use AWS_NEW_RETRIES_2026 during mode resolution --- .../amazon/awssdk/core/retry/RetryMode.java | 11 +- .../core/SdkSystemSettingNewRetriesTest.java | 93 ++++++++++++++ .../core/retry/RetryModeGatedDefaultTest.java | 116 ++++++++++++++++++ 3 files changed, 217 insertions(+), 3 deletions(-) create mode 100644 core/sdk-core/src/test/java/software/amazon/awssdk/core/SdkSystemSettingNewRetriesTest.java create mode 100644 core/sdk-core/src/test/java/software/amazon/awssdk/core/retry/RetryModeGatedDefaultTest.java diff --git a/core/sdk-core/src/main/java/software/amazon/awssdk/core/retry/RetryMode.java b/core/sdk-core/src/main/java/software/amazon/awssdk/core/retry/RetryMode.java index fdfe4fa68a82..0f233b46326b 100644 --- a/core/sdk-core/src/main/java/software/amazon/awssdk/core/retry/RetryMode.java +++ b/core/sdk-core/src/main/java/software/amazon/awssdk/core/retry/RetryMode.java @@ -130,8 +130,6 @@ public static Resolver resolver() { * Allows customizing the variables used during determination of a {@link RetryMode}. Created via {@link #resolver()}. */ public static class Resolver { - private static final RetryMode SDK_DEFAULT_RETRY_MODE = LEGACY; - private Supplier profileFile; private String profileName; private RetryMode defaultRetryMode; @@ -204,7 +202,14 @@ private static Optional fromString(String string) { } private RetryMode fromDefaultMode() { - return defaultRetryMode != null ? defaultRetryMode : SDK_DEFAULT_RETRY_MODE; + return defaultRetryMode != null ? defaultRetryMode : sdkDefaultRetryMode(); + } + + /** + * Resolves the SDK default retry mode dynamically based on the {@code AWS_NEW_RETRIES_2026} gate. + */ + private static RetryMode sdkDefaultRetryMode() { + return SdkSystemSetting.AWS_NEW_RETRIES_2026.getBooleanValue().orElse(false) ? STANDARD : LEGACY; } } } diff --git a/core/sdk-core/src/test/java/software/amazon/awssdk/core/SdkSystemSettingNewRetriesTest.java b/core/sdk-core/src/test/java/software/amazon/awssdk/core/SdkSystemSettingNewRetriesTest.java new file mode 100644 index 000000000000..f7c420fe401c --- /dev/null +++ b/core/sdk-core/src/test/java/software/amazon/awssdk/core/SdkSystemSettingNewRetriesTest.java @@ -0,0 +1,93 @@ +/* + * 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 org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.Test; +import software.amazon.awssdk.testutils.EnvironmentVariableHelper; + +/** + * Tests for the {@link SdkSystemSetting#AWS_NEW_RETRIES_2026} system setting. + */ +class SdkSystemSettingNewRetriesTest { + + @AfterEach + void cleanup() { + System.clearProperty(SdkSystemSetting.AWS_NEW_RETRIES_2026.property()); + } + + @Test + void defaultsToFalse_whenUnset() { + assertThat(SdkSystemSetting.AWS_NEW_RETRIES_2026.getBooleanValue()).hasValue(false); + } + + @Test + void returnsFalse_whenSystemPropertySetToFalse() { + System.setProperty(SdkSystemSetting.AWS_NEW_RETRIES_2026.property(), "false"); + assertThat(SdkSystemSetting.AWS_NEW_RETRIES_2026.getBooleanValue()).hasValue(false); + } + + @Test + void returnsTrue_whenSystemPropertySetToTrue() { + System.setProperty(SdkSystemSetting.AWS_NEW_RETRIES_2026.property(), "true"); + assertThat(SdkSystemSetting.AWS_NEW_RETRIES_2026.getBooleanValue()).hasValue(true); + } + + @Test + void returnsFalse_whenEnvVarSetToFalse() { + EnvironmentVariableHelper.run(helper -> { + helper.set(SdkSystemSetting.AWS_NEW_RETRIES_2026, "false"); + assertThat(SdkSystemSetting.AWS_NEW_RETRIES_2026.getBooleanValue()).hasValue(false); + }); + } + + @Test + void returnsTrue_whenEnvVarSetToTrue() { + EnvironmentVariableHelper.run(helper -> { + helper.set(SdkSystemSetting.AWS_NEW_RETRIES_2026, "true"); + assertThat(SdkSystemSetting.AWS_NEW_RETRIES_2026.getBooleanValue()).hasValue(true); + }); + } + + @Test + void systemPropertyTakesPrecedenceOverEnvVar() { + EnvironmentVariableHelper.run(helper -> { + System.setProperty(SdkSystemSetting.AWS_NEW_RETRIES_2026.property(), "false"); + helper.set(SdkSystemSetting.AWS_NEW_RETRIES_2026, "true"); + assertThat(SdkSystemSetting.AWS_NEW_RETRIES_2026.getBooleanValue()).hasValue(false); + }); + } + + @Test + void environmentVariable_isCorrectName() { + assertThat(SdkSystemSetting.AWS_NEW_RETRIES_2026.environmentVariable()) + .isEqualTo("AWS_NEW_RETRIES_2026"); + } + + @Test + void systemProperty_isCorrectName() { + assertThat(SdkSystemSetting.AWS_NEW_RETRIES_2026.property()) + .isEqualTo("aws.newRetries2026"); + } + + @Test + void defaultValue_isFalse() { + assertThat(SdkSystemSetting.AWS_NEW_RETRIES_2026.defaultValue()) + .isEqualTo("false"); + } +} diff --git a/core/sdk-core/src/test/java/software/amazon/awssdk/core/retry/RetryModeGatedDefaultTest.java b/core/sdk-core/src/test/java/software/amazon/awssdk/core/retry/RetryModeGatedDefaultTest.java new file mode 100644 index 000000000000..79759771268d --- /dev/null +++ b/core/sdk-core/src/test/java/software/amazon/awssdk/core/retry/RetryModeGatedDefaultTest.java @@ -0,0 +1,116 @@ +/* + * 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.retry; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import software.amazon.awssdk.core.SdkSystemSetting; +import software.amazon.awssdk.testutils.EnvironmentVariableHelper; + +/** + * Tests for the gated default {@link RetryMode} behavior controlled by + * {@link SdkSystemSetting#AWS_NEW_RETRIES_2026}. + */ +class RetryModeGatedDefaultTest { + + @BeforeEach + @AfterEach + void cleanup() { + System.clearProperty(SdkSystemSetting.AWS_NEW_RETRIES_2026.property()); + System.clearProperty(SdkSystemSetting.AWS_RETRY_MODE.property()); + } + + @Test + void defaultRetryMode_returnsLegacy_whenGateIsUnset() { + assertThat(RetryMode.defaultRetryMode()).isEqualTo(RetryMode.LEGACY); + } + + @Test + void defaultRetryMode_returnsLegacy_whenGateSystemPropertyIsFalse() { + System.setProperty(SdkSystemSetting.AWS_NEW_RETRIES_2026.property(), "false"); + assertThat(RetryMode.defaultRetryMode()).isEqualTo(RetryMode.LEGACY); + } + + @Test + void defaultRetryMode_returnsStandard_whenGateSystemPropertyIsTrue() { + System.setProperty(SdkSystemSetting.AWS_NEW_RETRIES_2026.property(), "true"); + assertThat(RetryMode.defaultRetryMode()).isEqualTo(RetryMode.STANDARD); + } + + @Test + void defaultRetryMode_returnsLegacy_whenGateEnvVarIsFalse() { + EnvironmentVariableHelper.run(helper -> { + helper.set(SdkSystemSetting.AWS_NEW_RETRIES_2026, "false"); + assertThat(RetryMode.defaultRetryMode()).isEqualTo(RetryMode.LEGACY); + }); + } + + @Test + void defaultRetryMode_returnsStandard_whenGateEnvVarIsTrue() { + EnvironmentVariableHelper.run(helper -> { + helper.set(SdkSystemSetting.AWS_NEW_RETRIES_2026, "true"); + assertThat(RetryMode.defaultRetryMode()).isEqualTo(RetryMode.STANDARD); + }); + } + + @Test + void defaultRetryMode_changesDynamically_whenGateSystemPropertyChangesAtRuntime() { + // Initially unset — should be LEGACY + assertThat(RetryMode.defaultRetryMode()).isEqualTo(RetryMode.LEGACY); + + // Enable gate — should switch to STANDARD + System.setProperty(SdkSystemSetting.AWS_NEW_RETRIES_2026.property(), "true"); + assertThat(RetryMode.defaultRetryMode()).isEqualTo(RetryMode.STANDARD); + + // Disable gate — should revert to LEGACY + System.setProperty(SdkSystemSetting.AWS_NEW_RETRIES_2026.property(), "false"); + assertThat(RetryMode.defaultRetryMode()).isEqualTo(RetryMode.LEGACY); + + // Clear gate — should fall back to default (LEGACY) + System.clearProperty(SdkSystemSetting.AWS_NEW_RETRIES_2026.property()); + assertThat(RetryMode.defaultRetryMode()).isEqualTo(RetryMode.LEGACY); + } + + @Test + void resolve_returnsLegacy_whenExplicitlyConfigured_regardlessOfGate() { + System.setProperty(SdkSystemSetting.AWS_NEW_RETRIES_2026.property(), "true"); + System.setProperty(SdkSystemSetting.AWS_RETRY_MODE.property(), "legacy"); + assertThat(RetryMode.defaultRetryMode()).isEqualTo(RetryMode.LEGACY); + } + + @Test + void resolve_returnsStandard_whenExplicitlyConfigured_regardlessOfGate() { + // Gate is disabled, but explicit config should still return STANDARD + System.setProperty(SdkSystemSetting.AWS_RETRY_MODE.property(), "standard"); + assertThat(RetryMode.defaultRetryMode()).isEqualTo(RetryMode.STANDARD); + } + + @Test + void resolve_returnsAdaptiveV2_whenExplicitlyConfigured_regardlessOfGate() { + System.setProperty(SdkSystemSetting.AWS_RETRY_MODE.property(), "adaptive"); + assertThat(RetryMode.defaultRetryMode()).isEqualTo(RetryMode.ADAPTIVE_V2); + } + + @Test + void resolve_throwsIllegalStateException_whenInvalidRetryModeConfigured() { + System.setProperty(SdkSystemSetting.AWS_RETRY_MODE.property(), "invalid_mode"); + assertThatThrownBy(RetryMode::defaultRetryMode).isInstanceOf(IllegalStateException.class); + } +} From d079fc3e31135436489bfffe93b6e18db5c5483b Mon Sep 17 00:00:00 2001 From: Dongie Agnir Date: Fri, 17 Apr 2026 15:21:39 -0700 Subject: [PATCH 2/2] Review comments --- .../core/SdkSystemSettingNewRetriesTest.java | 40 +++++------ .../core/retry/RetryModeGatedDefaultTest.java | 68 ++++++++----------- 2 files changed, 46 insertions(+), 62 deletions(-) diff --git a/core/sdk-core/src/test/java/software/amazon/awssdk/core/SdkSystemSettingNewRetriesTest.java b/core/sdk-core/src/test/java/software/amazon/awssdk/core/SdkSystemSettingNewRetriesTest.java index f7c420fe401c..a55bcfc324ec 100644 --- a/core/sdk-core/src/test/java/software/amazon/awssdk/core/SdkSystemSettingNewRetriesTest.java +++ b/core/sdk-core/src/test/java/software/amazon/awssdk/core/SdkSystemSettingNewRetriesTest.java @@ -19,6 +19,8 @@ import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.CsvSource; import software.amazon.awssdk.testutils.EnvironmentVariableHelper; /** @@ -36,31 +38,25 @@ void defaultsToFalse_whenUnset() { assertThat(SdkSystemSetting.AWS_NEW_RETRIES_2026.getBooleanValue()).hasValue(false); } - @Test - void returnsFalse_whenSystemPropertySetToFalse() { - System.setProperty(SdkSystemSetting.AWS_NEW_RETRIES_2026.property(), "false"); - assertThat(SdkSystemSetting.AWS_NEW_RETRIES_2026.getBooleanValue()).hasValue(false); + @ParameterizedTest(name = "systemProperty=\"{0}\" -> {1}") + @CsvSource({ + "false, false", + "true, true" + }) + void getBooleanValue_reflectsSystemProperty(String propertyValue, boolean expected) { + System.setProperty(SdkSystemSetting.AWS_NEW_RETRIES_2026.property(), propertyValue); + assertThat(SdkSystemSetting.AWS_NEW_RETRIES_2026.getBooleanValue()).hasValue(expected); } - @Test - void returnsTrue_whenSystemPropertySetToTrue() { - System.setProperty(SdkSystemSetting.AWS_NEW_RETRIES_2026.property(), "true"); - assertThat(SdkSystemSetting.AWS_NEW_RETRIES_2026.getBooleanValue()).hasValue(true); - } - - @Test - void returnsFalse_whenEnvVarSetToFalse() { + @ParameterizedTest(name = "envVar=\"{0}\" -> {1}") + @CsvSource({ + "false, false", + "true, true" + }) + void getBooleanValue_reflectsEnvVar(String envVarValue, boolean expected) { EnvironmentVariableHelper.run(helper -> { - helper.set(SdkSystemSetting.AWS_NEW_RETRIES_2026, "false"); - assertThat(SdkSystemSetting.AWS_NEW_RETRIES_2026.getBooleanValue()).hasValue(false); - }); - } - - @Test - void returnsTrue_whenEnvVarSetToTrue() { - EnvironmentVariableHelper.run(helper -> { - helper.set(SdkSystemSetting.AWS_NEW_RETRIES_2026, "true"); - assertThat(SdkSystemSetting.AWS_NEW_RETRIES_2026.getBooleanValue()).hasValue(true); + helper.set(SdkSystemSetting.AWS_NEW_RETRIES_2026, envVarValue); + assertThat(SdkSystemSetting.AWS_NEW_RETRIES_2026.getBooleanValue()).hasValue(expected); }); } diff --git a/core/sdk-core/src/test/java/software/amazon/awssdk/core/retry/RetryModeGatedDefaultTest.java b/core/sdk-core/src/test/java/software/amazon/awssdk/core/retry/RetryModeGatedDefaultTest.java index 79759771268d..f14cad1efd9a 100644 --- a/core/sdk-core/src/test/java/software/amazon/awssdk/core/retry/RetryModeGatedDefaultTest.java +++ b/core/sdk-core/src/test/java/software/amazon/awssdk/core/retry/RetryModeGatedDefaultTest.java @@ -21,6 +21,8 @@ import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.CsvSource; import software.amazon.awssdk.core.SdkSystemSetting; import software.amazon.awssdk.testutils.EnvironmentVariableHelper; @@ -42,31 +44,25 @@ void defaultRetryMode_returnsLegacy_whenGateIsUnset() { assertThat(RetryMode.defaultRetryMode()).isEqualTo(RetryMode.LEGACY); } - @Test - void defaultRetryMode_returnsLegacy_whenGateSystemPropertyIsFalse() { - System.setProperty(SdkSystemSetting.AWS_NEW_RETRIES_2026.property(), "false"); - assertThat(RetryMode.defaultRetryMode()).isEqualTo(RetryMode.LEGACY); - } - - @Test - void defaultRetryMode_returnsStandard_whenGateSystemPropertyIsTrue() { - System.setProperty(SdkSystemSetting.AWS_NEW_RETRIES_2026.property(), "true"); - assertThat(RetryMode.defaultRetryMode()).isEqualTo(RetryMode.STANDARD); - } - - @Test - void defaultRetryMode_returnsLegacy_whenGateEnvVarIsFalse() { - EnvironmentVariableHelper.run(helper -> { - helper.set(SdkSystemSetting.AWS_NEW_RETRIES_2026, "false"); - assertThat(RetryMode.defaultRetryMode()).isEqualTo(RetryMode.LEGACY); - }); + @ParameterizedTest(name = "gate=\"{0}\" -> {1}") + @CsvSource({ + "false, LEGACY", + "true, STANDARD" + }) + void defaultRetryMode_reflectsGate_whenSetViaSystemProperty(String gateValue, RetryMode expected) { + System.setProperty(SdkSystemSetting.AWS_NEW_RETRIES_2026.property(), gateValue); + assertThat(RetryMode.defaultRetryMode()).isEqualTo(expected); } - @Test - void defaultRetryMode_returnsStandard_whenGateEnvVarIsTrue() { + @ParameterizedTest(name = "gate=\"{0}\" -> {1}") + @CsvSource({ + "false, LEGACY", + "true, STANDARD" + }) + void defaultRetryMode_reflectsGate_whenSetViaEnvVar(String gateValue, RetryMode expected) { EnvironmentVariableHelper.run(helper -> { - helper.set(SdkSystemSetting.AWS_NEW_RETRIES_2026, "true"); - assertThat(RetryMode.defaultRetryMode()).isEqualTo(RetryMode.STANDARD); + helper.set(SdkSystemSetting.AWS_NEW_RETRIES_2026, gateValue); + assertThat(RetryMode.defaultRetryMode()).isEqualTo(expected); }); } @@ -88,24 +84,16 @@ void defaultRetryMode_changesDynamically_whenGateSystemPropertyChangesAtRuntime( assertThat(RetryMode.defaultRetryMode()).isEqualTo(RetryMode.LEGACY); } - @Test - void resolve_returnsLegacy_whenExplicitlyConfigured_regardlessOfGate() { - System.setProperty(SdkSystemSetting.AWS_NEW_RETRIES_2026.property(), "true"); - System.setProperty(SdkSystemSetting.AWS_RETRY_MODE.property(), "legacy"); - assertThat(RetryMode.defaultRetryMode()).isEqualTo(RetryMode.LEGACY); - } - - @Test - void resolve_returnsStandard_whenExplicitlyConfigured_regardlessOfGate() { - // Gate is disabled, but explicit config should still return STANDARD - System.setProperty(SdkSystemSetting.AWS_RETRY_MODE.property(), "standard"); - assertThat(RetryMode.defaultRetryMode()).isEqualTo(RetryMode.STANDARD); - } - - @Test - void resolve_returnsAdaptiveV2_whenExplicitlyConfigured_regardlessOfGate() { - System.setProperty(SdkSystemSetting.AWS_RETRY_MODE.property(), "adaptive"); - assertThat(RetryMode.defaultRetryMode()).isEqualTo(RetryMode.ADAPTIVE_V2); + @ParameterizedTest(name = "gate=\"{0}\" retryMode=\"{1}\" -> {2}") + @CsvSource({ + "true, legacy, LEGACY", + "false, standard, STANDARD", + "false, adaptive, ADAPTIVE_V2" + }) + void resolve_honorsExplicitRetryMode_regardlessOfGate(String gateValue, String retryModeValue, RetryMode expected) { + System.setProperty(SdkSystemSetting.AWS_NEW_RETRIES_2026.property(), gateValue); + System.setProperty(SdkSystemSetting.AWS_RETRY_MODE.property(), retryModeValue); + assertThat(RetryMode.defaultRetryMode()).isEqualTo(expected); } @Test