Skip to content

Commit 7b481fa

Browse files
authored
fix: Use full UUIDs for random identifiers in integration tests (#2043)
1 parent 1a3dcff commit 7b481fa

File tree

18 files changed

+112
-69
lines changed

18 files changed

+112
-69
lines changed
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
//
2+
// Copyright Amazon.com Inc. or its affiliates.
3+
// All Rights Reserved.
4+
//
5+
// SPDX-License-Identifier: Apache-2.0
6+
//
7+
8+
import struct Foundation.UUID
9+
10+
package extension String {
11+
12+
/// Returns an identifier that contains a UUID and is 63 or less chars in length.
13+
///
14+
/// Size is selected to be compatible with the requirement that bucket names be 63 characters or less.
15+
/// - Parameter service: The name (or abbreviation) of the service being identified.
16+
/// May contain only A-Z, a-z, 0-9, and dash(-). May not be empty. May not be long enough to result in an
17+
/// identifier 64 chars or longer. Uppercase characters in the service will be downcased in the identifier.
18+
/// - Returns: The identifier.
19+
static func uniqueID(service: String) -> String {
20+
let prefix = "sdkinttest-"
21+
guard !service.isEmpty else {
22+
fatalError("Service cannot be empty")
23+
}
24+
guard service.lowercased().allSatisfy({ "abcdefghijklmnopqrstuvwxyz0123456789-".contains($0) }) else {
25+
fatalError("Service cannot contain characters other than alphanumeric & dash")
26+
}
27+
guard prefix.count + service.count + 36 < 64 else {
28+
fatalError("Service name is too long. Limit is \(63 - prefix.count - 36)")
29+
}
30+
return (prefix + service + UUID().uuidString).lowercased()
31+
}
32+
}

IntegrationTests/Services/AWSCloudFrontKeyValueStoreIntegrationTests/CloudFrontKeyValueStoreSigV4ATests.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import ClientRuntime
1111
import AWSClientRuntime
1212
import AWSCloudFront
1313
import AWSCloudFrontKeyValueStore
14+
import AWSIntegrationTestUtils
1415

1516
/// Tests SigV4a signing flow using CloudFrontKeyValueStore.
1617
class CloudFrontKeyValueStoreSigV4ATests: XCTestCase {
@@ -23,7 +24,7 @@ class CloudFrontKeyValueStoreSigV4ATests: XCTestCase {
2324
private let region = "us-east-1"
2425

2526
// Temporary name of the KVS to use for the test
26-
private let kvsName = "sigv4a-test-kvs-" + UUID().uuidString.split(separator: "-").first!.lowercased()
27+
private let kvsName = String.uniqueID(service: "sigv4a-kvs")
2728

2829
// The Etag to use to call CloudFront::deletKeyValueStore
2930
private var cfEtag: String!

IntegrationTests/Services/AWSCognitoIdentityIntegrationTests/CognitoAWSCredentialIdentityResolverTests.swift

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,15 @@ import AWSSTS
1212
import ClientRuntime
1313
import SmithyWaitersAPI
1414
import XCTest
15+
import AWSIntegrationTestUtils
1516

1617
/// Tests CognitoAWSCredentialIdentityResolver using STS::getCallerIdentity.
1718
class CognitoAWSCredentialIdentityResolverTests: XCTestCase {
1819
private let region = "us-west-2"
1920

2021
private var cognitoIdentityClient: CognitoIdentityClient!
2122
private var iamClient: IAMClient!
22-
private let identityPoolName = "aws-cognito-integration-test-\(UUID().uuidString.split(separator: "-").first!.lowercased())"
23+
private let identityPoolName = String.uniqueID(service: "cognito")
2324
private var identityPoolId: String!
2425
private var roleName: String!
2526

@@ -38,7 +39,7 @@ class CognitoAWSCredentialIdentityResolverTests: XCTestCase {
3839
)
3940
).identityPoolId
4041
// Create an IAM role for unauthenticated users
41-
roleName = "CognitoUnauth_\(identityPoolName)"
42+
roleName = String.uniqueID(service: "cog-role")
4243
let trustPolicy = """
4344
{
4445
"Version": "2012-10-17",

IntegrationTests/Services/AWSCognitoIdentityIntegrationTests/UnauthenticatedAPITests.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import AWSClientRuntime
1212
import ClientRuntime
1313
import class SmithyHTTPAPI.HTTPRequest
1414
import class SmithyHTTPAPI.HTTPResponse
15+
import AWSIntegrationTestUtils
1516

1617
/// Tests unauthenciated API using AWSCognitoIdentity::getId
1718
class UnauthenticatedAPITests: XCTestCase {
@@ -22,7 +23,7 @@ class UnauthenticatedAPITests: XCTestCase {
2223

2324
private var accountID: String!
2425
private var identityPoolID: String!
25-
private let identityPoolName = "idpool" + UUID().uuidString.split(separator: "-").first!.lowercased()
26+
private let identityPoolName = String.uniqueID(service: "idpool")
2627

2728
override func setUp() async throws {
2829
// STS client for getting the account ID, an input parameter for the unauthenticated API, getId().

IntegrationTests/Services/AWSEventBridgeIntegrationTests/EventBridgeSigV4ATests.swift

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import AWSEventBridge
1111
import ClientRuntime
1212
import AWSClientRuntime
1313
import AWSRoute53
14+
import AWSIntegrationTestUtils
1415

1516
/// Tests SigV4a signing flow using EventBridge's global endpoint.
1617
class EventBridgeSigV4ATests: XCTestCase {
@@ -28,8 +29,8 @@ class EventBridgeSigV4ATests: XCTestCase {
2829
private let secondaryRegion = "us-east-1"
2930

3031
// Name for the EventBridge global endpoint
31-
private let endpointName = "sigv4a-test-global-endpoint-\(UUID().uuidString.split(separator: "-").first!.lowercased())"
32-
private let eventBusName = "sigv4a-integ-test-eventbus-\(UUID().uuidString.split(separator: "-").first!.lowercased())"
32+
private let endpointName = String.uniqueID(service: "eb-globalendpt")
33+
private let eventBusName = String.uniqueID(service: "eb-eventbus")
3334
private var endpointId: String!
3435

3536
private var healthCheckId: String!
@@ -58,7 +59,7 @@ class EventBridgeSigV4ATests: XCTestCase {
5859
type: .https
5960
)
6061
let createHealthCheckInput = CreateHealthCheckInput(
61-
callerReference: UUID().uuidString.split(separator: "-").first!.lowercased(),
62+
callerReference: String.uniqueID(service: "r53-healthchk"),
6263
healthCheckConfig: healthCheckConfig
6364
)
6465
let healthCheck = try await route53Client.createHealthCheck(input: createHealthCheckInput)

IntegrationTests/Services/AWSGlacierIntegrationTests/GlacierTests.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,15 @@ import AWSGlacier
1111
import AWSSTS
1212
import enum Smithy.ByteStream
1313
import SmithyWaitersAPI
14+
import AWSIntegrationTestUtils
1415

1516
/// Tests that Glacier operations run successfully
1617
class GlacierTests: XCTestCase {
1718
var glacierClient: GlacierClient!
1819
var stsClient: STSClient!
1920
var accountId: String!
2021
var archiveId: String!
21-
let vaultName = UUID().uuidString.split(separator: "-").first!.lowercased() + "integ-test-vault"
22+
let vaultName = String.uniqueID(service: "s3-glacier")
2223

2324
override func setUp() async throws {
2425
stsClient = try STSClient(region: "us-east-1")

IntegrationTests/Services/AWSKinesisIntegrationTests/KinesisTests.swift

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import AWSKinesis
1010
import ClientRuntime
1111
import AWSClientRuntime
1212
import SmithyWaitersAPI
13+
import AWSIntegrationTestUtils
1314

1415
class KinesisTests: XCTestCase {
1516

@@ -23,7 +24,7 @@ class KinesisTests: XCTestCase {
2324
// Client must have AWS credentials set that allow access to the Kinesis service.
2425
// Resources will be cleaned up before the test concludes, pass or fail, unless the test crashes.
2526

26-
let streamName = UUID().uuidString
27+
let streamName = String.uniqueID(service: "kinesis")
2728
let client = try KinesisClient(region: "us-west-2")
2829

2930
do {
@@ -36,7 +37,7 @@ class KinesisTests: XCTestCase {
3637
let streamARN = stream.streamDescription?.streamARN
3738

3839
// Make a set of 10 records, add them to the stream
39-
var recordStrings = (1...10).map { _ in UUID().uuidString }
40+
var recordStrings = (1...10).map { _ in String.uniqueID(service: "kinesis") }
4041
for record in recordStrings {
4142
let putRecordInput = PutRecordInput(data: record.data(using: .utf8), explicitHashKey: nil, partitionKey: "Test", sequenceNumberForOrdering: nil, streamName: streamName)
4243
let _ = try await client.putRecord(input: putRecordInput)
@@ -48,7 +49,7 @@ class KinesisTests: XCTestCase {
4849
let shard = shardList.shards?.first!
4950

5051
// Create a consumer for the shard
51-
let consumerName = UUID().uuidString
52+
let consumerName = String.uniqueID(service: "kinesis")
5253
let consumerInput = RegisterStreamConsumerInput(consumerName: consumerName, streamARN: stream.streamDescription?.streamARN)
5354
let consumer = try await client.registerStreamConsumer(input: consumerInput)
5455
let consumerARN = consumer.consumer?.consumerARN

IntegrationTests/Services/AWSS3IntegrationTests/S3ConcurrentTests.swift

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -41,18 +41,18 @@ final class S3ConcurrentTests: S3XCTestCase, @unchecked Sendable {
4141
// Puts data to S3, gets the uploaded file, asserts retrieved data == original data, deletes S3 object
4242
@Sendable
4343
private func getObject(data: Data) async throws {
44-
let objectKey = UUID().uuidString.split(separator: "-").first!.lowercased()
45-
let putObjectInput = PutObjectInput(body: .data(data), bucket: bucketName, key: objectKey)
44+
let objectKey = String.uniqueID(service: "s3")
45+
let putObjectInput = PutObjectInput(body: .data(data), bucket: bucketName, key: objectKey)
4646

47-
_ = try await client.putObject(input: putObjectInput)
47+
_ = try await client.putObject(input: putObjectInput)
4848

49-
let retrievedData = try await client.getObject(input: GetObjectInput(
50-
bucket: bucketName, key: objectKey
51-
)).body?.readData()
49+
let retrievedData = try await client.getObject(input: GetObjectInput(
50+
bucket: bucketName, key: objectKey
51+
)).body?.readData()
5252

53-
XCTAssertEqual(data, retrievedData)
53+
XCTAssertEqual(data, retrievedData)
5454

55-
let deleteObjectInput = DeleteObjectInput(bucket: bucketName, key: objectKey)
56-
_ = try await client.deleteObject(input: deleteObjectInput)
55+
let deleteObjectInput = DeleteObjectInput(bucket: bucketName, key: objectKey)
56+
_ = try await client.deleteObject(input: deleteObjectInput)
5757
}
5858
}

IntegrationTests/Services/AWSS3IntegrationTests/S3ContentMD5HeaderTests.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ final class S3ContentMD5HeaderTests: S3XCTestCase {
1717
try await super.setUp()
1818
// Generate 3 UUIDs to use as object keys and save them
1919
for _ in 1...3 {
20-
objectKeys.append("key-\(UUID().uuidString.split(separator: "-").first!.lowercased())")
20+
objectKeys.append(String.uniqueID(service: "s3"))
2121
}
2222
}
2323

IntegrationTests/Services/AWSS3IntegrationTests/S3EmptyBody404Tests.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ class S3EmptyBody404Tests: S3XCTestCase {
3030

3131
// Perform the S3 HeadObject operation on a nonexistent object.
3232
// This will cause the 404 error without a body.
33-
let input = HeadObjectInput(bucket: bucketName, key: UUID().uuidString)
33+
let input = HeadObjectInput(bucket: bucketName, key: String.uniqueID(service: "s3"))
3434
_ = try await client.headObject(input: input)
3535

3636
// If an error was not thrown by the HeadObject call, fail the test.

0 commit comments

Comments
 (0)