AWS SDK

AWS SDK

rev. 2493670155f3f484f4055f00c7816463c1a2ced2..ac5e22252d1e170d05dd8b11ceb2a7a284cd7f2e

Files changed:

tmp-codegen-diff/services/polly/generated-src/main/kotlin/aws/sdk/kotlin/services/polly/model/Gender.kt

@@ -9,9 +44,44 @@
   29     29   
            "Female" -> Female
   30     30   
            "Male" -> Male
   31     31   
            else -> SdkUnknown(value)
   32     32   
        }
   33     33   
   34     34   
        /**
   35     35   
         * Get a list of all possible variants
   36     36   
         */
   37     37   
        public fun values(): kotlin.collections.List<aws.sdk.kotlin.services.polly.model.Gender> = values
   38     38   
   39         -
        private val values: kotlin.collections.List<aws.sdk.kotlin.services.polly.model.Gender> = listOf(
          39  +
        private val values: kotlin.collections.List<aws.sdk.kotlin.services.polly.model.Gender> by lazy { listOf(
   40     40   
            Female,
   41     41   
            Male,
   42         -
        )
          42  +
        ) }
   43     43   
    }
   44     44   
}

tmp-codegen-diff/services/polly/generated-src/main/kotlin/aws/sdk/kotlin/services/polly/model/LanguageCode.kt

@@ -249,249 +324,324 @@
  269    269   
            "tr-TR" -> TrTr
  270    270   
            "yue-CN" -> YueCn
  271    271   
            else -> SdkUnknown(value)
  272    272   
        }
  273    273   
  274    274   
        /**
  275    275   
         * Get a list of all possible variants
  276    276   
         */
  277    277   
        public fun values(): kotlin.collections.List<aws.sdk.kotlin.services.polly.model.LanguageCode> = values
  278    278   
  279         -
        private val values: kotlin.collections.List<aws.sdk.kotlin.services.polly.model.LanguageCode> = listOf(
         279  +
        private val values: kotlin.collections.List<aws.sdk.kotlin.services.polly.model.LanguageCode> by lazy { listOf(
  280    280   
            ArAe,
  281    281   
            Arb,
  282    282   
            CaEs,
  283    283   
            CmnCn,
  284    284   
            CsCz,
  285    285   
            CyGb,
  286    286   
            DaDk,
  287    287   
            DeAt,
  288    288   
            DeCh,
  289    289   
            DeDe,
  290    290   
            EnAu,
  291    291   
            EnGb,
  292    292   
            EnGbWls,
  293    293   
            EnIe,
  294    294   
            EnIn,
  295    295   
            EnNz,
  296    296   
            EnSg,
  297    297   
            EnUs,
  298    298   
            EnZa,
  299    299   
            EsEs,
  300    300   
            EsMx,
  301    301   
            EsUs,
  302    302   
            FiFi,
  303    303   
            FrBe,
  304    304   
            FrCa,
  305    305   
            FrFr,
  306    306   
            HiIn,
  307    307   
            IsIs,
  308    308   
            ItIt,
  309    309   
            JaJp,
  310    310   
            KoKr,
  311    311   
            NbNo,
  312    312   
            NlBe,
  313    313   
            NlNl,
  314    314   
            PlPl,
  315    315   
            PtBr,
  316    316   
            PtPt,
  317    317   
            RoRo,
  318    318   
            RuRu,
  319    319   
            SvSe,
  320    320   
            TrTr,
  321    321   
            YueCn,
  322         -
        )
         322  +
        ) }
  323    323   
    }
  324    324   
}

tmp-codegen-diff/services/polly/generated-src/main/kotlin/aws/sdk/kotlin/services/polly/model/OutputFormat.kt

@@ -39,39 +79,79 @@
   59     59   
            "ogg_vorbis" -> OggVorbis
   60     60   
            "pcm" -> Pcm
   61     61   
            else -> SdkUnknown(value)
   62     62   
        }
   63     63   
   64     64   
        /**
   65     65   
         * Get a list of all possible variants
   66     66   
         */
   67     67   
        public fun values(): kotlin.collections.List<aws.sdk.kotlin.services.polly.model.OutputFormat> = values
   68     68   
   69         -
        private val values: kotlin.collections.List<aws.sdk.kotlin.services.polly.model.OutputFormat> = listOf(
          69  +
        private val values: kotlin.collections.List<aws.sdk.kotlin.services.polly.model.OutputFormat> by lazy { listOf(
   70     70   
            Alaw,
   71     71   
            Json,
   72     72   
            Mp3,
   73     73   
            Mulaw,
   74     74   
            OggOpus,
   75     75   
            OggVorbis,
   76     76   
            Pcm,
   77         -
        )
          77  +
        ) }
   78     78   
    }
   79     79   
}

tmp-codegen-diff/services/polly/generated-src/main/kotlin/aws/sdk/kotlin/services/polly/model/QuotaCode.kt

@@ -9,9 +44,44 @@
   29     29   
            "input-stream-inbound-event-timeout" -> InputStreamInboundEventTimeout
   30     30   
            "input-stream-timeout" -> InputStreamTimeout
   31     31   
            else -> SdkUnknown(value)
   32     32   
        }
   33     33   
   34     34   
        /**
   35     35   
         * Get a list of all possible variants
   36     36   
         */
   37     37   
        public fun values(): kotlin.collections.List<aws.sdk.kotlin.services.polly.model.QuotaCode> = values
   38     38   
   39         -
        private val values: kotlin.collections.List<aws.sdk.kotlin.services.polly.model.QuotaCode> = listOf(
          39  +
        private val values: kotlin.collections.List<aws.sdk.kotlin.services.polly.model.QuotaCode> by lazy { listOf(
   40     40   
            InputStreamInboundEventTimeout,
   41     41   
            InputStreamTimeout,
   42         -
        )
          42  +
        ) }
   43     43   
    }
   44     44   
}

tmp-codegen-diff/services/polly/generated-src/main/kotlin/aws/sdk/kotlin/services/polly/model/ServiceCode.kt

@@ -3,3 +37,37 @@
   23     23   
        public fun fromValue(value: kotlin.String): aws.sdk.kotlin.services.polly.model.ServiceCode = when (value) {
   24     24   
            "polly" -> Polly
   25     25   
            else -> SdkUnknown(value)
   26     26   
        }
   27     27   
   28     28   
        /**
   29     29   
         * Get a list of all possible variants
   30     30   
         */
   31     31   
        public fun values(): kotlin.collections.List<aws.sdk.kotlin.services.polly.model.ServiceCode> = values
   32     32   
   33         -
        private val values: kotlin.collections.List<aws.sdk.kotlin.services.polly.model.ServiceCode> = listOf(
          33  +
        private val values: kotlin.collections.List<aws.sdk.kotlin.services.polly.model.ServiceCode> by lazy { listOf(
   34     34   
            Polly,
   35         -
        )
          35  +
        ) }
   36     36   
    }
   37     37   
}

tmp-codegen-diff/services/polly/generated-src/main/kotlin/aws/sdk/kotlin/services/polly/model/SpeechMarkType.kt

@@ -21,21 +58,58 @@
   41     41   
            "viseme" -> Viseme
   42     42   
            "word" -> Word
   43     43   
            else -> SdkUnknown(value)
   44     44   
        }
   45     45   
   46     46   
        /**
   47     47   
         * Get a list of all possible variants
   48     48   
         */
   49     49   
        public fun values(): kotlin.collections.List<aws.sdk.kotlin.services.polly.model.SpeechMarkType> = values
   50     50   
   51         -
        private val values: kotlin.collections.List<aws.sdk.kotlin.services.polly.model.SpeechMarkType> = listOf(
          51  +
        private val values: kotlin.collections.List<aws.sdk.kotlin.services.polly.model.SpeechMarkType> by lazy { listOf(
   52     52   
            Sentence,
   53     53   
            Ssml,
   54     54   
            Viseme,
   55     55   
            Word,
   56         -
        )
          56  +
        ) }
   57     57   
    }
   58     58   
}

tmp-codegen-diff/services/polly/generated-src/main/kotlin/aws/sdk/kotlin/services/polly/model/TaskStatus.kt

@@ -21,21 +58,58 @@
   41     41   
            "inProgress" -> InProgress
   42     42   
            "scheduled" -> Scheduled
   43     43   
            else -> SdkUnknown(value)
   44     44   
        }
   45     45   
   46     46   
        /**
   47     47   
         * Get a list of all possible variants
   48     48   
         */
   49     49   
        public fun values(): kotlin.collections.List<aws.sdk.kotlin.services.polly.model.TaskStatus> = values
   50     50   
   51         -
        private val values: kotlin.collections.List<aws.sdk.kotlin.services.polly.model.TaskStatus> = listOf(
          51  +
        private val values: kotlin.collections.List<aws.sdk.kotlin.services.polly.model.TaskStatus> by lazy { listOf(
   52     52   
            Completed,
   53     53   
            Failed,
   54     54   
            InProgress,
   55     55   
            Scheduled,
   56         -
        )
          56  +
        ) }
   57     57   
    }
   58     58   
}

tmp-codegen-diff/services/polly/generated-src/main/kotlin/aws/sdk/kotlin/services/polly/model/TextType.kt

@@ -9,9 +44,44 @@
   29     29   
            "ssml" -> Ssml
   30     30   
            "text" -> Text
   31     31   
            else -> SdkUnknown(value)
   32     32   
        }
   33     33   
   34     34   
        /**
   35     35   
         * Get a list of all possible variants
   36     36   
         */
   37     37   
        public fun values(): kotlin.collections.List<aws.sdk.kotlin.services.polly.model.TextType> = values
   38     38   
   39         -
        private val values: kotlin.collections.List<aws.sdk.kotlin.services.polly.model.TextType> = listOf(
          39  +
        private val values: kotlin.collections.List<aws.sdk.kotlin.services.polly.model.TextType> by lazy { listOf(
   40     40   
            Ssml,
   41     41   
            Text,
   42         -
        )
          42  +
        ) }
   43     43   
    }
   44     44   
}

tmp-codegen-diff/services/polly/generated-src/main/kotlin/aws/sdk/kotlin/services/polly/model/ValidationExceptionReason.kt

@@ -21,21 +58,58 @@
   41     41   
            "other" -> Other
   42     42   
            "unsupportedOperation" -> UnsupportedOperation
   43     43   
            else -> SdkUnknown(value)
   44     44   
        }
   45     45   
   46     46   
        /**
   47     47   
         * Get a list of all possible variants
   48     48   
         */
   49     49   
        public fun values(): kotlin.collections.List<aws.sdk.kotlin.services.polly.model.ValidationExceptionReason> = values
   50     50   
   51         -
        private val values: kotlin.collections.List<aws.sdk.kotlin.services.polly.model.ValidationExceptionReason> = listOf(
          51  +
        private val values: kotlin.collections.List<aws.sdk.kotlin.services.polly.model.ValidationExceptionReason> by lazy { listOf(
   52     52   
            FieldValidationFailed,
   53     53   
            InvalidInboundEvent,
   54     54   
            Other,
   55     55   
            UnsupportedOperation,
   56         -
        )
          56  +
        ) }
   57     57   
    }
   58     58   
}

tmp-codegen-diff/services/polly/generated-src/main/kotlin/aws/sdk/kotlin/services/polly/model/VoiceId.kt

@@ -633,633 +693,693 @@
  653    653   
            "Zeina" -> Zeina
  654    654   
            "Zhiyu" -> Zhiyu
  655    655   
            else -> SdkUnknown(value)
  656    656   
        }
  657    657   
  658    658   
        /**
  659    659   
         * Get a list of all possible variants
  660    660   
         */
  661    661   
        public fun values(): kotlin.collections.List<aws.sdk.kotlin.services.polly.model.VoiceId> = values
  662    662   
  663         -
        private val values: kotlin.collections.List<aws.sdk.kotlin.services.polly.model.VoiceId> = listOf(
         663  +
        private val values: kotlin.collections.List<aws.sdk.kotlin.services.polly.model.VoiceId> by lazy { listOf(
  664    664   
            Aditi,
  665    665   
            Adriano,
  666    666   
            Ambre,
  667    667   
            Amy,
  668    668   
            Andres,
  669    669   
            Aria,
  670    670   
            Arlet,
  671    671   
            Arthur,
  672    672   
            Astrid,
  673    673   
            Ayanda,
@@ -740,740 +772,772 @@
  760    760   
            Takumi,
  761    761   
            Tatyana,
  762    762   
            Thiago,
  763    763   
            Tiffany,
  764    764   
            Tomoko,
  765    765   
            Vicki,
  766    766   
            Vitoria,
  767    767   
            Zayd,
  768    768   
            Zeina,
  769    769   
            Zhiyu,
  770         -
        )
         770  +
        ) }
  771    771   
    }
  772    772   
}

tmp-codegen-diff/services/s3/build.gradle.kts

@@ -1,1 +40,40 @@
    1      1   
    2      2   
description = "The AWS SDK for Kotlin client for S3"
    3      3   
project.ext.set("aws.sdk.id", "S3")
    4      4   
    5      5   
kotlin {
    6      6   
    sourceSets {
    7      7   
        commonMain {
    8      8   
            dependencies {
    9         -
                implementation("aws.smithy.kotlin:aws-credentials:1.6.8-SNAPSHOT")
   10         -
                implementation("aws.smithy.kotlin:aws-event-stream:1.6.8-SNAPSHOT")
           9  +
                implementation("aws.smithy.kotlin:aws-credentials:1.6.13-SNAPSHOT")
          10  +
                implementation("aws.smithy.kotlin:aws-event-stream:1.6.13-SNAPSHOT")
   11     11   
                implementation(project(":aws-runtime:aws-http"))
   12         -
                implementation("aws.smithy.kotlin:aws-protocol-core:1.6.8-SNAPSHOT")
   13         -
                implementation("aws.smithy.kotlin:aws-signing-common:1.6.8-SNAPSHOT")
   14         -
                implementation("aws.smithy.kotlin:aws-signing-default:1.6.8-SNAPSHOT")
   15         -
                implementation("aws.smithy.kotlin:aws-xml-protocols:1.6.8-SNAPSHOT")
   16         -
                implementation("aws.smithy.kotlin:http:1.6.8-SNAPSHOT")
   17         -
                implementation("aws.smithy.kotlin:http-auth:1.6.8-SNAPSHOT")
   18         -
                implementation("aws.smithy.kotlin:http-auth-aws:1.6.8-SNAPSHOT")
   19         -
                implementation("aws.smithy.kotlin:http-client-engine-default:1.6.8-SNAPSHOT")
   20         -
                implementation("aws.smithy.kotlin:identity-api:1.6.8-SNAPSHOT")
   21         -
                implementation("aws.smithy.kotlin:serde:1.6.8-SNAPSHOT")
   22         -
                implementation("aws.smithy.kotlin:serde-xml:1.6.8-SNAPSHOT")
   23         -
                implementation("aws.smithy.kotlin:telemetry-defaults:1.6.8-SNAPSHOT")
          12  +
                implementation("aws.smithy.kotlin:aws-protocol-core:1.6.13-SNAPSHOT")
          13  +
                implementation("aws.smithy.kotlin:aws-signing-common:1.6.13-SNAPSHOT")
          14  +
                implementation("aws.smithy.kotlin:aws-signing-default:1.6.13-SNAPSHOT")
          15  +
                implementation("aws.smithy.kotlin:aws-xml-protocols:1.6.13-SNAPSHOT")
          16  +
                implementation("aws.smithy.kotlin:http:1.6.13-SNAPSHOT")
          17  +
                implementation("aws.smithy.kotlin:http-auth:1.6.13-SNAPSHOT")
          18  +
                implementation("aws.smithy.kotlin:http-auth-aws:1.6.13-SNAPSHOT")
          19  +
                implementation("aws.smithy.kotlin:http-client-engine-default:1.6.13-SNAPSHOT")
          20  +
                implementation("aws.smithy.kotlin:identity-api:1.6.13-SNAPSHOT")
          21  +
                implementation("aws.smithy.kotlin:serde:1.6.13-SNAPSHOT")
          22  +
                implementation("aws.smithy.kotlin:serde-xml:1.6.13-SNAPSHOT")
          23  +
                implementation("aws.smithy.kotlin:telemetry-defaults:1.6.13-SNAPSHOT")
   24     24   
                api(project(":aws-runtime:aws-config"))
   25     25   
                api(project(":aws-runtime:aws-core"))
   26     26   
                api(project(":aws-runtime:aws-endpoint"))
   27         -
                api("aws.smithy.kotlin:http-client:1.6.8-SNAPSHOT")
   28         -
                api("aws.smithy.kotlin:runtime-core:1.6.8-SNAPSHOT")
   29         -
                api("aws.smithy.kotlin:smithy-client:1.6.8-SNAPSHOT")
   30         -
                api("aws.smithy.kotlin:telemetry-api:1.6.8-SNAPSHOT")
          27  +
                api("aws.smithy.kotlin:http-client:1.6.13-SNAPSHOT")
          28  +
                api("aws.smithy.kotlin:runtime-core:1.6.13-SNAPSHOT")
          29  +
                api("aws.smithy.kotlin:smithy-client:1.6.13-SNAPSHOT")
          30  +
                api("aws.smithy.kotlin:telemetry-api:1.6.13-SNAPSHOT")
   31     31   
            }
   32     32   
        }
   33     33   
        commonTest {
   34     34   
            dependencies {
   35     35   
                implementation("org.jetbrains.kotlin:kotlin-test:2.3.0")
   36         -
                implementation("aws.smithy.kotlin:smithy-test:1.6.8-SNAPSHOT")
          36  +
                implementation("aws.smithy.kotlin:smithy-test:1.6.13-SNAPSHOT")
   37     37   
            }
   38     38   
        }
   39     39   
    }
   40     40   
}

tmp-codegen-diff/services/s3/build/tmp/jvmJar/MANIFEST.MF

@@ -1,0 +2,0 @@
    1         -
Manifest-Version: 1.0
    2         -

tmp-codegen-diff/services/s3/e2eTest/src/ConnectionResetTest.kt

@@ -1,1 +79,80 @@
    1      1   
/*
    2      2   
 * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
    3      3   
 * SPDX-License-Identifier: Apache-2.0
    4      4   
 */
    5      5   
package aws.sdk.kotlin.e2etest
    6      6   
    7         -
import aws.sdk.kotlin.services.s3.S3Client
    8      7   
import aws.sdk.kotlin.services.s3.model.PutObjectRequest
    9      8   
import aws.smithy.kotlin.runtime.content.ByteStream
   10      9   
import aws.smithy.kotlin.runtime.http.HttpException
   11         -
import aws.smithy.kotlin.runtime.util.Uuid
          10  +
import aws.smithy.kotlin.runtime.testing.AfterAll
          11  +
import aws.smithy.kotlin.runtime.testing.BeforeAll
          12  +
import aws.smithy.kotlin.runtime.testing.TestInstance
          13  +
import aws.smithy.kotlin.runtime.testing.TestLifecycle
   12     14   
import kotlinx.coroutines.async
   13     15   
import kotlinx.coroutines.awaitAll
   14     16   
import kotlinx.coroutines.delay
   15         -
import kotlinx.coroutines.invoke
   16     17   
import kotlinx.coroutines.runBlocking
   17         -
import org.junit.jupiter.api.AfterAll
   18         -
import org.junit.jupiter.api.BeforeAll
   19         -
import org.junit.jupiter.api.TestInstance
   20     18   
import java.io.IOException
   21     19   
import kotlin.test.Test
   22     20   
import kotlin.time.Duration.Companion.seconds
   23     21   
   24     22   
/**
   25     23   
 * Reproduces "unexpected end of stream" errors as seen in https://github.com/aws/aws-sdk-kotlin/issues/1214
   26     24   
 * and ensures they are resolved by OkHttp's retryOnConnectionFailure option
   27     25   
 */
   28         -
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
          26  +
@TestInstance(TestLifecycle.PER_CLASS)
   29     27   
class ConnectionResetTest {
   30         -
    private val client = S3Client {
   31         -
        region = S3TestUtils.DEFAULT_REGION
          28  +
    private val client = S3TestUtils.createClient()
          29  +
          30  +
    companion object {
          31  +
        private const val CONN_TEST_CONCURRENCY = 10
   32     32   
    }
   33     33   
   34     34   
    private lateinit var testBucket: String
   35     35   
   36     36   
    @BeforeAll
   37     37   
    fun createResources(): Unit = runBlocking {
   38         -
        testBucket = S3TestUtils.getTestBucket(client)
          38  +
        testBucket = S3TestUtils.createTestBucket(client, "conn-reset")
   39     39   
    }
   40     40   
   41     41   
    @AfterAll
   42     42   
    fun cleanup() = runBlocking {
   43         -
        S3TestUtils.deleteBucketAndAllContents(client, testBucket)
          43  +
        S3TestUtils.deleteBucket(client, testBucket)
          44  +
        client.close()
   44     45   
    }
   45     46   
   46     47   
    @Test
   47     48   
    fun testConnectionResetDoesntThrow(): Unit = runBlocking {
   48     49   
        // Launch multiple coroutines to populate connection pool
   49         -
        val jobs = (1..10).map {
   50         -
            async { client.putTestObject() }
          50  +
        val jobs = (1..CONN_TEST_CONCURRENCY).map { index ->
          51  +
            async { putTestObject(index) }
   51     52   
        }
   52     53   
        jobs.awaitAll()
   53     54   
        // Connections are now idle in the pool
   54     55   
   55     56   
        // Wait for S3 to close stale connections
   56     57   
        delay(7.seconds)
   57     58   
   58     59   
        // Try to re-use a connection
   59         -
        client.putTestObject()
          60  +
        putTestObject(CONN_TEST_CONCURRENCY + 1)
   60     61   
    }
   61     62   
   62         -
    suspend fun S3Client.putTestObject() {
          63  +
    suspend fun putTestObject(index: Int) {
   63     64   
        val putObjectRequest = PutObjectRequest {
   64     65   
            bucket = testBucket
   65         -
            key = Uuid.random().toString()
          66  +
            key = "conn-reset-test-object-$index"
   66     67   
            body = ByteStream.fromString("Content")
   67     68   
        }
   68     69   
   69     70   
        try {
   70     71   
            client.putObject(putObjectRequest)
   71     72   
        } catch (e: HttpException) {
   72     73   
            if (e.cause is IOException && e.cause?.message?.contains("unexpected end of stream") == true) {
   73     74   
                throw RetryOnConnectionFailureException("SDK unexpectedly threw java.io.IOException which should have been retried by OkHttp's retryOnConnectionFailure feature", e)
   74     75   
            }
   75     76   
        }

tmp-codegen-diff/services/s3/e2eTest/src/MultiRegionAccessPointTest.kt

@@ -1,1 +136,148 @@
    1      1   
/*
    2      2   
 * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
    3      3   
 * SPDX-License-Identifier: Apache-2.0
    4      4   
 */
    5      5   
package aws.sdk.kotlin.e2etest
    6      6   
    7         -
import aws.sdk.kotlin.e2etest.S3TestUtils.deleteBucketAndAllContents
    8         -
import aws.sdk.kotlin.e2etest.S3TestUtils.getAccountId
    9         -
import aws.sdk.kotlin.e2etest.S3TestUtils.getBucketWithPrefix
   10      7   
import aws.sdk.kotlin.services.s3.S3Client
   11      8   
import aws.sdk.kotlin.services.s3.deleteObject
   12      9   
import aws.sdk.kotlin.services.s3.putObject
   13     10   
import aws.sdk.kotlin.services.s3.withConfig
   14         -
import aws.sdk.kotlin.services.s3control.S3ControlClient
   15         -
import aws.sdk.kotlin.services.s3control.createMultiRegionAccessPoint
   16         -
import aws.sdk.kotlin.services.s3control.deleteMultiRegionAccessPoint
   17         -
import aws.sdk.kotlin.services.s3control.describeMultiRegionAccessPointOperation
   18         -
import aws.sdk.kotlin.services.s3control.getMultiRegionAccessPoint
          11  +
import aws.sdk.kotlin.services.s3control.*
   19     12   
import aws.sdk.kotlin.services.s3control.model.Region
   20         -
import aws.smithy.kotlin.runtime.auth.awssigning.AwsSigner
          13  +
import aws.sdk.kotlin.services.s3control.paginators.listMultiRegionAccessPointsPaginated
   21     14   
import aws.smithy.kotlin.runtime.auth.awssigning.DefaultAwsSigner
   22     15   
import aws.smithy.kotlin.runtime.auth.awssigning.crt.CrtAwsSigner
   23     16   
import aws.smithy.kotlin.runtime.http.auth.SigV4AsymmetricAuthScheme
          17  +
import aws.smithy.kotlin.runtime.testing.AfterAll
          18  +
import aws.smithy.kotlin.runtime.testing.BeforeAll
          19  +
import aws.smithy.kotlin.runtime.testing.TestInstance
          20  +
import aws.smithy.kotlin.runtime.testing.TestLifecycle
          21  +
import aws.smithy.kotlin.runtime.testing.parameterized
   24     22   
import kotlinx.coroutines.delay
          23  +
import kotlinx.coroutines.flow.toList
   25     24   
import kotlinx.coroutines.runBlocking
   26     25   
import kotlinx.coroutines.withTimeout
   27         -
import org.junit.jupiter.api.AfterAll
   28         -
import org.junit.jupiter.api.BeforeAll
   29         -
import org.junit.jupiter.api.TestInstance
   30         -
import org.junit.jupiter.params.ParameterizedTest
   31         -
import org.junit.jupiter.params.provider.Arguments
   32         -
import org.junit.jupiter.params.provider.MethodSource
   33         -
import java.util.stream.Stream
   34         -
import kotlin.random.Random
          26  +
import kotlin.test.Test
   35     27   
import kotlin.time.Duration
   36     28   
import kotlin.time.Duration.Companion.minutes
   37     29   
import kotlin.time.Duration.Companion.seconds
   38     30   
   39         -
private const val MRAP_BUCKET_PREFIX = "s3-mrap-test-bucket-"
   40         -
private val MULTI_REGION_ACCESS_POINT_NAME = "aws-sdk-for-kotlin-mrap-${Random.nextInt(0, 9999)}"
   41     31   
private const val TEST_OBJECT_KEY = "test.txt"
   42     32   
   43         -
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
   44         -
class MutliRegionAccessPointTest {
          33  +
@TestInstance(TestLifecycle.PER_CLASS)
          34  +
class MultiRegionAccessPointTest {
   45     35   
    private lateinit var s3West: S3Client
   46     36   
    private lateinit var s3East: S3Client
   47     37   
    private lateinit var s3Control: S3ControlClient
   48     38   
   49     39   
    private lateinit var accountId: String
          40  +
    private lateinit var multiRegionAccessPointName: String
   50     41   
    private lateinit var multiRegionAccessPointArn: String
   51     42   
    private lateinit var usWestBucket: String
   52     43   
    private lateinit var usEastBucket: String
   53     44   
   54     45   
    @BeforeAll
   55     46   
    fun setup(): Unit = runBlocking {
   56         -
        s3West = S3Client { region = "us-west-2" }
   57         -
        s3East = S3Client { region = "us-east-2" }
          47  +
        s3West = S3TestUtils.createClient { region = "us-west-2" }
          48  +
        s3East = S3TestUtils.createClient { region = "us-east-2" }
   58     49   
        s3Control = S3ControlClient { region = "us-west-2" }
   59     50   
   60         -
        accountId = getAccountId()
   61         -
        usWestBucket = getBucketWithPrefix(s3West, MRAP_BUCKET_PREFIX, "us-west-2", accountId)
   62         -
        usEastBucket = getBucketWithPrefix(s3East, MRAP_BUCKET_PREFIX, "us-east-2", accountId)
          51  +
        accountId = S3TestUtils.getAccountId()
          52  +
        usWestBucket = S3TestUtils.createTestBucket(s3West, "mrap-west")
          53  +
        usEastBucket = S3TestUtils.createTestBucket(s3East, "mrap-east")
   63     54   
          55  +
        multiRegionAccessPointName = "s3-test-mrap-${S3TestUtils.testRunId}"
   64     56   
        multiRegionAccessPointArn = s3Control.createMultiRegionAccessPoint(
   65         -
            MULTI_REGION_ACCESS_POINT_NAME,
          57  +
            multiRegionAccessPointName,
   66     58   
            accountId,
   67     59   
            listOf(usWestBucket, usEastBucket),
   68     60   
        )
   69     61   
    }
   70     62   
   71     63   
    @AfterAll
   72     64   
    fun cleanup(): Unit = runBlocking {
   73         -
        s3Control.deleteMultiRegionAccessPoint(MULTI_REGION_ACCESS_POINT_NAME, accountId)
          65  +
        s3Control.deleteMultiRegionAccessPoint(multiRegionAccessPointName, accountId)
   74     66   
   75         -
        deleteBucketAndAllContents(s3West, usWestBucket)
   76         -
        deleteBucketAndAllContents(s3East, usEastBucket)
          67  +
        val resp = s3Control.listMultiRegionAccessPointsPaginated {
          68  +
            accountId = this@MultiRegionAccessPointTest.accountId
          69  +
        }.toList().flatMap { it.accessPoints.orEmpty() }
          70  +
          71  +
        val mrapManifest = buildString {
          72  +
            appendLine("Existing multi-region access points for account ID $accountId (${resp.size}):")
          73  +
            resp.forEach { accessPoint ->
          74  +
                appendLine("* ${accessPoint.name}:")
          75  +
                appendLine("  * Alias: ${accessPoint.alias}")
          76  +
                appendLine("  * Created: ${accessPoint.createdAt}")
          77  +
                appendLine("  * Status: ${accessPoint.status}")
          78  +
          79  +
                val regions = accessPoint.regions.orEmpty()
          80  +
                appendLine("  * Regions (${regions.size}):")
          81  +
          82  +
                regions.forEach { region ->
          83  +
                    appendLine("    * ${region.region}: ${region.bucket} (account ID ${region.bucketAccountId})")
          84  +
                }
          85  +
            }
          86  +
        }
          87  +
        print(mrapManifest)
          88  +
          89  +
        S3TestUtils.deleteBucket(s3West, usWestBucket)
          90  +
        S3TestUtils.deleteBucket(s3East, usEastBucket)
   77     91   
   78     92   
        s3West.close()
   79     93   
        s3East.close()
   80     94   
        s3Control.close()
   81     95   
    }
   82     96   
   83         -
    @ParameterizedTest
   84         -
    @MethodSource("signerProvider")
   85         -
    fun testMultiRegionAccessPointOperation(signer: AwsSigner): Unit = runBlocking {
   86         -
        println("Testing multi-region access point operations with $signer")
          97  +
    @Test
          98  +
    fun testMultiRegionAccessPointOperation(): Unit = parameterized(
          99  +
        listOf(DefaultAwsSigner, CrtAwsSigner),
         100  +
    ) { signer ->
         101  +
        runBlocking {
         102  +
            println("Testing multi-region access point operations with $signer")
   87    103   
   88         -
        val s3SigV4a = s3West.withConfig {
   89         -
            authSchemes = listOf(SigV4AsymmetricAuthScheme(signer))
   90         -
        }
         104  +
            val s3SigV4a = s3West.withConfig {
         105  +
                authSchemes = listOf(SigV4AsymmetricAuthScheme(signer))
         106  +
            }
   91    107   
   92         -
        s3SigV4a.putObject {
   93         -
            bucket = multiRegionAccessPointArn
   94         -
            key = TEST_OBJECT_KEY
   95         -
        }
         108  +
            s3SigV4a.putObject {
         109  +
                bucket = multiRegionAccessPointArn
         110  +
                key = TEST_OBJECT_KEY
         111  +
            }
   96    112   
   97         -
        s3SigV4a.deleteObject {
   98         -
            bucket = multiRegionAccessPointArn
   99         -
            key = TEST_OBJECT_KEY
         113  +
            s3SigV4a.deleteObject {
         114  +
                bucket = multiRegionAccessPointArn
         115  +
                key = TEST_OBJECT_KEY
         116  +
            }
  100    117   
        }
  101    118   
    }
  102         -
  103         -
    fun signerProvider(): Stream<Arguments> = Stream.of(
  104         -
        Arguments.of(DefaultAwsSigner),
  105         -
        Arguments.of(CrtAwsSigner),
  106         -
    )
  107    119   
}
  108    120   
  109    121   
/**
  110    122   
 * Create a multi-region access point named [name] in account [accountId] with [buckets] buckets.
  111    123   
 * @return the ARN of the multi-region access point that was created
  112    124   
 */
  113    125   
private suspend fun S3ControlClient.createMultiRegionAccessPoint(
  114    126   
    name: String,
  115    127   
    accountId: String,
  116    128   
    buckets: List<String>,

tmp-codegen-diff/services/s3/e2eTest/src/PaginatorTest.kt

@@ -1,1 +70,69 @@
    1      1   
/*
    2      2   
 * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
    3      3   
 * SPDX-License-Identifier: Apache-2.0
    4      4   
 */
    5      5   
package aws.sdk.kotlin.e2etest
    6      6   
    7         -
import aws.sdk.kotlin.services.s3.S3Client
    8      7   
import aws.sdk.kotlin.services.s3.abortMultipartUpload
    9      8   
import aws.sdk.kotlin.services.s3.createMultipartUpload
   10      9   
import aws.sdk.kotlin.services.s3.model.CompletedPart
   11     10   
import aws.sdk.kotlin.services.s3.paginators.listPartsPaginated
   12     11   
import aws.sdk.kotlin.services.s3.uploadPart
   13     12   
import aws.smithy.kotlin.runtime.content.ByteStream
          13  +
import aws.smithy.kotlin.runtime.testing.AfterAll
          14  +
import aws.smithy.kotlin.runtime.testing.BeforeAll
          15  +
import aws.smithy.kotlin.runtime.testing.TestInstance
          16  +
import aws.smithy.kotlin.runtime.testing.TestLifecycle
   14     17   
import kotlinx.coroutines.flow.toList
   15     18   
import kotlinx.coroutines.flow.transform
   16     19   
import kotlinx.coroutines.runBlocking
   17     20   
import kotlinx.coroutines.withTimeout
   18         -
import org.junit.jupiter.api.AfterAll
   19         -
import org.junit.jupiter.api.BeforeAll
   20         -
import org.junit.jupiter.api.Test
   21         -
import org.junit.jupiter.api.TestInstance
          21  +
import kotlin.test.Test
   22     22   
import kotlin.test.assertContentEquals
   23     23   
import kotlin.time.Duration.Companion.seconds
   24     24   
   25         -
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
          25  +
@TestInstance(TestLifecycle.PER_CLASS)
   26     26   
class PaginatorTest {
   27         -
    private val client = S3Client {
   28         -
        region = S3TestUtils.DEFAULT_REGION
   29         -
    }
          27  +
    private val client = S3TestUtils.createClient()
   30     28   
   31     29   
    private lateinit var testBucket: String
   32     30   
   33     31   
    @BeforeAll
   34     32   
    fun createResources(): Unit = runBlocking {
   35         -
        testBucket = S3TestUtils.getTestBucket(client)
          33  +
        testBucket = S3TestUtils.createTestBucket(client, "pagination")
   36     34   
    }
   37     35   
   38     36   
    @AfterAll
   39     37   
    fun cleanup() = runBlocking {
   40         -
        S3TestUtils.deleteBucketAndAllContents(client, testBucket)
          38  +
        S3TestUtils.deleteBucket(client, testBucket)
          39  +
        client.close()
   41     40   
    }
   42     41   
   43     42   
    // ListParts has a strange pagination termination condition via [IsTerminated]. Verify it actually works correctly.
   44     43   
    @Test
   45     44   
    fun testListPartsPagination() = runBlocking {
   46     45   
        val chunk = "!".repeat(5 * 1024 * 1024).encodeToByteArray() // Parts must be at least 5MB
   47     46   
        val expectedParts = (1..10).toList()
   48     47   
   49     48   
        val id = client.createMultipartUpload {
   50     49   
            bucket = testBucket

tmp-codegen-diff/services/s3/e2eTest/src/S3ChecksumTest.kt

@@ -1,1 +198,197 @@
    1      1   
/*
    2      2   
 * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
    3      3   
 * SPDX-License-Identifier: Apache-2.0
    4      4   
 */
    5      5   
    6      6   
package aws.sdk.kotlin.e2etest
    7      7   
    8         -
import aws.sdk.kotlin.e2etest.S3TestUtils.deleteBucketContents
    9         -
import aws.sdk.kotlin.e2etest.S3TestUtils.deleteMultiPartUploads
   10         -
import aws.sdk.kotlin.e2etest.S3TestUtils.getAccountId
   11         -
import aws.sdk.kotlin.e2etest.S3TestUtils.getTestBucket
   12         -
import aws.sdk.kotlin.e2etest.S3TestUtils.responseCodeFromPut
   13      8   
import aws.sdk.kotlin.services.s3.*
   14      9   
import aws.sdk.kotlin.services.s3.model.*
   15     10   
import aws.sdk.kotlin.services.s3.presigners.presignPutObject
   16     11   
import aws.smithy.kotlin.runtime.content.*
   17     12   
import aws.smithy.kotlin.runtime.hashing.crc32
          13  +
import aws.smithy.kotlin.runtime.testing.AfterAll
          14  +
import aws.smithy.kotlin.runtime.testing.BeforeAll
   18     15   
import aws.smithy.kotlin.runtime.testing.RandomTempFile
          16  +
import aws.smithy.kotlin.runtime.testing.TestInstance
          17  +
import aws.smithy.kotlin.runtime.testing.TestLifecycle
          18  +
import kotlinx.coroutines.async
          19  +
import kotlinx.coroutines.awaitAll
   19     20   
import kotlinx.coroutines.runBlocking
   20         -
import org.junit.jupiter.api.*
   21     21   
import java.io.File
   22     22   
import java.io.FileInputStream
   23     23   
import java.util.*
          24  +
import kotlin.test.Test
   24     25   
import kotlin.test.assertEquals
   25     26   
import kotlin.test.assertFalse
   26     27   
import kotlin.test.assertTrue
   27     28   
import kotlin.time.Duration.Companion.seconds
   28     29   
   29         -
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
          30  +
@TestInstance(TestLifecycle.PER_CLASS)
   30     31   
class S3ChecksumTest {
   31         -
    private val client = S3Client { region = "us-west-2" }
          32  +
    private val client = S3TestUtils.createClient()
   32     33   
    private lateinit var testBucket: String
   33         -
    private fun testKey(): String = "test-object" + UUID.randomUUID()
          34  +
    private fun testKey(suffix: String): String = "test-object-$suffix"
   34     35   
   35     36   
    @BeforeAll
   36     37   
    private fun setUp(): Unit = runBlocking {
   37         -
        val accountId = getAccountId()
   38         -
        testBucket = getTestBucket(client, "us-west-2", accountId)
          38  +
        testBucket = S3TestUtils.createTestBucket(client, "checksums")
   39     39   
    }
   40     40   
   41     41   
    @AfterAll
   42     42   
    private fun cleanUp(): Unit = runBlocking {
   43         -
        deleteMultiPartUploads(client, testBucket)
   44         -
        deleteBucketContents(client, testBucket)
          43  +
        S3TestUtils.deleteBucket(client, testBucket)
   45     44   
        client.close()
   46     45   
    }
   47     46   
   48     47   
    @Test
   49     48   
    fun testPutObject(): Unit = runBlocking {
   50     49   
        val testBody = "Hello World"
   51         -
        val testKey = testKey()
          50  +
        val testKey = testKey("basic")
   52     51   
   53     52   
        client.putObject {
   54     53   
            bucket = testBucket
   55     54   
            key = testKey
   56     55   
            body = ByteStream.fromString(testBody)
   57     56   
        }
   58     57   
   59     58   
        client.getObject(
   60     59   
            GetObjectRequest {
   61     60   
                bucket = testBucket
   62     61   
                key = testKey
   63     62   
            },
   64     63   
        ) { actual ->
   65     64   
            assertEquals(testBody, actual.body?.decodeToString() ?: "")
   66     65   
        }
   67     66   
    }
   68     67   
   69     68   
    @Test
   70     69   
    fun testPutObjectWithEmptyBody(): Unit = runBlocking {
   71         -
        val testKey = testKey()
          70  +
        val testKey = testKey("empty")
   72     71   
        val testBody = ""
   73     72   
   74     73   
        client.putObject {
   75     74   
            bucket = testBucket
   76     75   
            key = testKey
   77     76   
        }
   78     77   
   79     78   
        client.getObject(
   80     79   
            GetObjectRequest {
   81     80   
                bucket = testBucket
   82     81   
                key = testKey
   83     82   
            },
   84     83   
        ) { actual ->
   85     84   
            assertEquals(testBody, actual.body?.decodeToString() ?: "")
   86     85   
        }
   87     86   
    }
   88     87   
   89     88   
    @Test
   90     89   
    fun testPutObjectAwsChunkedEncoded(): Unit = runBlocking {
   91         -
        val testKey = testKey()
          90  +
        val testKey = testKey("chunked")
   92     91   
        val testBody = "Hello World"
   93     92   
   94     93   
        val tempFile = File.createTempFile("test", ".txt").also {
   95     94   
            it.writeText(testBody)
   96     95   
            it.deleteOnExit()
   97     96   
        }
   98     97   
        val inputStream = FileInputStream(tempFile)
   99     98   
  100     99   
        client.putObject {
  101    100   
            bucket = testBucket
  102    101   
            key = testKey
  103    102   
            body = ByteStream.fromInputStream(inputStream, testBody.length.toLong())
  104    103   
        }
  105    104   
  106    105   
        client.getObject(
  107    106   
            GetObjectRequest {
  108    107   
                bucket = testBucket
  109    108   
                key = testKey
  110    109   
            },
  111    110   
        ) { actual ->
  112    111   
            assertEquals(testBody, actual.body?.decodeToString() ?: "")
  113    112   
        }
  114    113   
    }
  115    114   
  116    115   
    @Test
  117    116   
    fun testMultiPartUpload(): Unit = runBlocking {
  118         -
        val testKey = testKey()
         117  +
        val testKey = testKey("multipart")
  119    118   
  120    119   
        val partSize = 5 * 1024 * 1024 // 5 MB - min part size
  121    120   
        val contentSize: Long = 8 * 1024 * 1024 // 2 parts
  122    121   
        val file = RandomTempFile(sizeInBytes = contentSize)
  123    122   
  124    123   
        val expectedChecksum = file.readBytes().crc32()
  125    124   
  126    125   
        val testUploadId = client.createMultipartUpload {
  127    126   
            bucket = testBucket
  128    127   
            key = testKey
  129    128   
        }.uploadId
  130    129   
  131         -
        val uploadedParts = file.chunk(partSize).mapIndexed { index, chunk ->
         130  +
        val uploadedParts = file.chunk(partSize).toList().mapIndexed { index, chunk ->
  132    131   
            val adjustedIndex = index + 1 // index starts from 0 but partNumber needs to start from 1
  133    132   
  134         -
            runBlocking {
         133  +
            async {
  135    134   
                client.uploadPart {
  136    135   
                    bucket = testBucket
  137    136   
                    key = testKey
  138    137   
                    partNumber = adjustedIndex
  139    138   
                    uploadId = testUploadId
  140    139   
                    body = file.asByteStream(chunk)
  141    140   
                }.let {
  142    141   
                    CompletedPart {
  143    142   
                        partNumber = adjustedIndex
  144    143   
                        eTag = it.eTag
  145    144   
                    }
  146    145   
                }
  147    146   
            }
  148         -
        }.toList()
         147  +
        }.awaitAll()
  149    148   
  150    149   
        client.completeMultipartUpload {
  151    150   
            bucket = testBucket
  152    151   
            key = testKey
  153    152   
            uploadId = testUploadId
  154    153   
            multipartUpload = CompletedMultipartUpload {
  155    154   
                parts = uploadedParts
  156    155   
            }
  157    156   
        }
  158    157   
  159    158   
        client.getObject(
  160    159   
            GetObjectRequest {
  161    160   
                bucket = testBucket
  162    161   
                key = testKey
  163    162   
            },
  164    163   
        ) { actual ->
  165    164   
            val actualChecksum = actual.body!!.toByteArray().crc32()
  166    165   
            assertEquals(actualChecksum, expectedChecksum)
  167    166   
        }
  168    167   
    }
  169    168   
  170    169   
    @Test
  171    170   
    fun testPresignedUrlNoDefault() = runBlocking {
  172    171   
        val contents = "presign-test"
  173    172   
  174    173   
        val unsignedPutRequest = PutObjectRequest {
  175    174   
            bucket = testBucket
  176         -
            key = testKey()
         175  +
            key = testKey("presigned-auto-checksum")
  177    176   
        }
  178    177   
        val presignedPutRequest = client.presignPutObject(unsignedPutRequest, 60.seconds)
  179    178   
  180    179   
        assertFalse(presignedPutRequest.url.toString().contains("x-amz-checksum-crc32"))
  181         -
        assertTrue(responseCodeFromPut(presignedPutRequest, contents) in 200..299)
         180  +
        assertTrue(S3TestUtils.responseCodeFromPut(presignedPutRequest, contents) in 200..299)
  182    181   
    }
  183    182   
  184    183   
    @Test
  185    184   
    fun testPresignedUrlChecksumValue() = runBlocking {
  186    185   
        val contents = "presign-test"
  187    186   
  188    187   
        val unsignedPutRequest = PutObjectRequest {
  189    188   
            bucket = testBucket
  190         -
            key = testKey()
         189  +
            key = testKey("presigned-provided-checksum")
  191    190   
            checksumCrc32 = "dBBx+Q=="
  192    191   
        }
  193    192   
        val presignedPutRequest = client.presignPutObject(unsignedPutRequest, 60.seconds)
  194    193   
  195    194   
        assertTrue(presignedPutRequest.url.toString().contains("x-amz-checksum-crc32"))
  196         -
        assertTrue(responseCodeFromPut(presignedPutRequest, contents) in 200..299)
         195  +
        assertTrue(S3TestUtils.responseCodeFromPut(presignedPutRequest, contents) in 200..299)
  197    196   
    }
  198    197   
}