Skip to content

Commit

Permalink
test(client-s3): convert some read ops to waiters (#6622)
Browse files Browse the repository at this point in the history
  • Loading branch information
kuhe authored Nov 5, 2024
1 parent 62ae71a commit 396fc77
Show file tree
Hide file tree
Showing 2 changed files with 102 additions and 19 deletions.
69 changes: 58 additions & 11 deletions clients/client-s3/test/e2e/S3.browser.e2e.spec.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import type { S3, SelectObjectContentEventStream } from "@aws-sdk/client-s3";
import { fromNodeProviderChain } from "@aws-sdk/credential-providers";
import { FetchHttpHandler } from "@smithy/fetch-http-handler";
import { afterEach, beforeAll, beforeEach, describe, expect, test as it } from "vitest";
import { afterAll, afterEach, beforeAll, beforeEach, describe, expect, onTestFailed, test as it } from "vitest";

import { getIntegTestResources } from "../../../../tests/e2e/get-integ-test-resources";
import { getRuntimeConfig } from "../../src/runtimeConfig.browser";
import { S3 as S3Impl } from "../browser-build/browser-s3-bundle";
import { S3 as S3Impl, waitUntilObjectExists } from "../browser-build/browser-s3-bundle";
import { createBuffer } from "./helpers";

describe("@aws-sdk/client-s3", () => {
Expand All @@ -14,6 +14,11 @@ describe("@aws-sdk/client-s3", () => {
let region: string;
let mrapArn: string;
let Key = `${Date.now()}`;
const errors = [] as any[];
let testFailed = false;
const setTestFailed = () => {
testFailed = true;
};

beforeAll(async () => {
const integTestResourcesEnv = await getIntegTestResources();
Expand All @@ -28,10 +33,28 @@ describe("@aws-sdk/client-s3", () => {
region,
credentials: fromNodeProviderChain(),
requestHandler: new FetchHttpHandler(),
logger: {
trace() {},
debug() {},
info() {},
warn() {},
error(entry: any) {
errors.push(entry);
},
},
})
) as unknown as S3;
});

afterAll(() => {
if (testFailed) {
console.info("Test failed, logging errors collecting during test.");
for (const error of errors) {
console.error(error);
}
}
});

describe("PutObject", () => {
beforeEach(() => {
Key = `${Date.now()}`;
Expand All @@ -47,6 +70,7 @@ describe("@aws-sdk/client-s3", () => {
// Caused by: RequestContentLengthMismatchError: Request body length does not match content-length header
// only in vitest + happy-dom.
it.skip("should succeed with blob body", async () => {
onTestFailed(setTestFailed);
const blob = new Blob([buf]);
const result = await client.putObject({
Bucket,
Expand All @@ -58,6 +82,7 @@ describe("@aws-sdk/client-s3", () => {
});

it("should succeed with TypedArray body", async () => {
onTestFailed(setTestFailed);
const result = await client.putObject({
Bucket,
Key,
Expand All @@ -67,6 +92,7 @@ describe("@aws-sdk/client-s3", () => {
});

it("should succeed with ReadableStream body", async () => {
onTestFailed(setTestFailed);
const length = 10 * 1000; // 10KB
const chunkSize = 10;
const readableStream = new ReadableStream({
Expand Down Expand Up @@ -102,6 +128,7 @@ describe("@aws-sdk/client-s3", () => {
});

it("should succeed with valid body payload", async () => {
onTestFailed(setTestFailed);
// prepare the object.
const body = createBuffer("1MB");

Expand Down Expand Up @@ -133,7 +160,9 @@ describe("@aws-sdk/client-s3", () => {
afterEach(async () => {
await client.deleteObject({ Bucket, Key });
});

it("should succeed with valid bucket", async () => {
onTestFailed(setTestFailed);
const result = await client.listObjects({
Bucket,
});
Expand All @@ -142,6 +171,7 @@ describe("@aws-sdk/client-s3", () => {
});

it("should throw with invalid bucket", () => {
onTestFailed(setTestFailed);
expect(() => client.listObjects({ Bucket: "invalid-bucket" })).rejects.toThrow();
});
});
Expand All @@ -150,9 +180,11 @@ describe("@aws-sdk/client-s3", () => {
let UploadId: string;
let Etag: string;
const multipartObjectKey = `${Key}-multipart`;

beforeEach(() => {
Key = `${Date.now()}`;
});

afterEach(async () => {
if (UploadId) {
await client.abortMultipartUpload({
Expand All @@ -168,7 +200,9 @@ describe("@aws-sdk/client-s3", () => {
});

it("should successfully create, upload list and complete", async () => {
//create multipart upload
onTestFailed(setTestFailed);

// create multipart upload
const createResult = await client.createMultipartUpload({
Bucket,
Key: multipartObjectKey,
Expand Down Expand Up @@ -209,15 +243,23 @@ describe("@aws-sdk/client-s3", () => {
expect(completeResult.$metadata.httpStatusCode).toEqual(200);

//validate the object is uploaded
const headResult = await client.headObject({
Bucket,
Key: multipartObjectKey,
});
expect(headResult.$metadata.httpStatusCode).toEqual(200);
const waiterState = await waitUntilObjectExists(
{
client,
maxWaitTime: 60,
},
{
Bucket,
Key: multipartObjectKey,
}
);
expect(waiterState.state).toEqual("SUCCESS");
});

it("should successfully create, abort, and list upload", async () => {
//create multipart upload
onTestFailed(setTestFailed);

// create multipart upload
const createResult = await client.createMultipartUpload({
Bucket,
Key: multipartObjectKey,
Expand Down Expand Up @@ -248,14 +290,18 @@ describe("@aws-sdk/client-s3", () => {
jsrocks,13
node4life,22
esfuture,29`;

beforeEach(async () => {
Key = `${Date.now()}`;
await client.putObject({ Bucket, Key, Body: csvFile });
});

afterEach(async () => {
await client.deleteObject({ Bucket, Key });
});

it("should succeed", async () => {
onTestFailed(setTestFailed);
const { Payload } = await client.selectObjectContent({
Bucket,
Key,
Expand Down Expand Up @@ -287,8 +333,9 @@ esfuture,29`;
beforeEach(async () => {
Key = `${Date.now()}`;
});
afterEach(async () => {});

it("should throw for aws-crt no available in browser", async () => {
onTestFailed(setTestFailed);
try {
await client.listObjects({
Bucket: mrapArn,
Expand All @@ -299,4 +346,4 @@ esfuture,29`;
}
});
});
});
}, 60_000);
Original file line number Diff line number Diff line change
@@ -1,15 +1,32 @@
import { S3 } from "@aws-sdk/client-s3";
import { S3, S3ClientConfig, waitUntilBucketExists, waitUntilBucketNotExists } from "@aws-sdk/client-s3";
import { GetCallerIdentityCommandOutput, STS } from "@aws-sdk/client-sts";
import { afterAll, beforeAll, describe, expect, test as it } from "vitest";
import { afterAll, beforeAll, describe, expect, onTestFailed, test as it } from "vitest";

const testValue = "Hello S3 global client!";

describe("S3 Global Client Test", () => {
const errors = [] as any[];
let testFailed = false;
const setTestFailed = () => {
testFailed = true;
};

const regionConfigs = [
{ region: "us-east-1", followRegionRedirects: true },
{ region: "eu-west-1", followRegionRedirects: true },
{ region: "us-west-2", followRegionRedirects: true },
];
{ region: "us-east-1", followRegionRedirects: true } as S3ClientConfig,
{ region: "eu-west-1", followRegionRedirects: true } as S3ClientConfig,
{ region: "us-west-2", followRegionRedirects: true } as S3ClientConfig,
].map((config) => {
config.logger = {
trace() {},
debug() {},
info() {},
warn() {},
error(entry: any) {
errors.push(entry);
},
};
return config;
});
const s3Clients = regionConfigs.map((config) => new S3(config));
const stsClient = new STS({});

Expand All @@ -24,16 +41,33 @@ describe("S3 Global Client Test", () => {
beforeAll(async () => {
callerID = await stsClient.getCallerIdentity({});
bucketNames = regionConfigs.map((config) => `${callerID.Account}-${randId}-redirect-${config.region}`);
await Promise.all(bucketNames.map((bucketName, index) => deleteBucket(s3Clients[index], bucketName)));
await Promise.all(bucketNames.map((bucketName, index) => s3Clients[index].createBucket({ Bucket: bucketName })));
await Promise.all(
bucketNames.map(async (bucketName, index) => {
await deleteBucket(s3Clients[index], bucketName);
return waitUntilBucketNotExists({ client: s3Clients[index], maxWaitTime: 60 }, { Bucket: bucketName });
})
);
await Promise.all(
bucketNames.map(async (bucketName, index) => {
await s3Clients[index].createBucket({ Bucket: bucketName });
return waitUntilBucketExists({ client: s3Clients[index], maxWaitTime: 60 }, { Bucket: bucketName });
})
);
await Promise.all(bucketNames.map((bucketName, index) => s3Clients[index].headBucket({ Bucket: bucketName })));
});

afterAll(async () => {
await Promise.all(bucketNames.map((bucketName, index) => deleteBucket(s3Clients[index], bucketName)));
if (testFailed) {
console.info("Test failed, logging errors collecting during test.");
for (const error of errors) {
console.error(error);
}
}
});

it("Should be able to put objects following region redirect", async () => {
onTestFailed(setTestFailed);
// Upload objects to each bucket
for (const bucketName of bucketNames) {
for (const s3Client of s3Clients) {
Expand All @@ -44,6 +78,7 @@ describe("S3 Global Client Test", () => {
});

it("Should be able to get objects following region redirect", async () => {
onTestFailed(setTestFailed);
// Fetch and assert objects
for (const bucketName of bucketNames) {
for (const s3Client of s3Clients) {
Expand All @@ -57,6 +92,7 @@ describe("S3 Global Client Test", () => {
});

it("Should delete objects following region redirect", async () => {
onTestFailed(setTestFailed);
for (const bucketName of bucketNames) {
for (const s3Client of s3Clients) {
const objKey = `object-from-${await s3Client.config.region()}-client`;
Expand Down

0 comments on commit 396fc77

Please sign in to comment.