Skip to content

Commit 7545774

Browse files
committed
chore(lib-storage): support passing of ChecksumAlgorithm
1 parent fbdde38 commit 7545774

File tree

2 files changed

+107
-109
lines changed

2 files changed

+107
-109
lines changed

lib/lib-storage/src/Upload.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -204,7 +204,7 @@ export class Upload extends EventEmitter {
204204
if (!this.createMultiPartPromise) {
205205
const createCommandParams = { ...this.params, Body: undefined };
206206
if (requestChecksumCalculation === "WHEN_SUPPORTED") {
207-
createCommandParams.ChecksumAlgorithm = ChecksumAlgorithm.CRC32;
207+
createCommandParams.ChecksumAlgorithm = this.params.ChecksumAlgorithm || ChecksumAlgorithm.CRC32;
208208
}
209209
this.createMultiPartPromise = this.client
210210
.send(new CreateMultipartUploadCommand(createCommandParams))

lib/lib-storage/src/lib-storage.e2e.spec.ts

Lines changed: 106 additions & 108 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { S3 } from "@aws-sdk/client-s3";
1+
import { ChecksumAlgorithm, S3 } from "@aws-sdk/client-s3";
22
import { Upload } from "@aws-sdk/lib-storage";
33
import { randomBytes } from "crypto";
44
import { Readable } from "stream";
@@ -10,128 +10,126 @@ describe("@aws-sdk/lib-storage", () => {
1010
describe.each([undefined, "WHEN_REQUIRED", "WHEN_SUPPORTED"])(
1111
"requestChecksumCalculation: %s",
1212
(requestChecksumCalculation) => {
13-
let Key: string;
14-
let client: S3;
15-
let data: Uint8Array;
16-
let dataString: string;
17-
let Bucket: string;
18-
let region: string;
19-
20-
beforeAll(async () => {
21-
const integTestResourcesEnv = await getIntegTestResources();
22-
Object.assign(process.env, integTestResourcesEnv);
23-
24-
region = process?.env?.AWS_SMOKE_TEST_REGION as string;
25-
Bucket = process?.env?.AWS_SMOKE_TEST_BUCKET as string;
26-
27-
Key = ``;
28-
data = randomBytes(20_240_000);
29-
dataString = data.toString();
30-
31-
// @ts-expect-error: Types of property 'requestChecksumCalculation' are incompatible
32-
client = new S3({
33-
region,
34-
requestChecksumCalculation,
13+
describe.each([
14+
undefined,
15+
ChecksumAlgorithm.SHA1,
16+
ChecksumAlgorithm.SHA256,
17+
ChecksumAlgorithm.CRC32,
18+
ChecksumAlgorithm.CRC32C,
19+
])("ChecksumAlgorithm: %s", (ChecksumAlgorithm) => {
20+
let Key: string;
21+
let client: S3;
22+
let data: Uint8Array;
23+
let dataString: string;
24+
let Bucket: string;
25+
let region: string;
26+
27+
beforeAll(async () => {
28+
const integTestResourcesEnv = await getIntegTestResources();
29+
Object.assign(process.env, integTestResourcesEnv);
30+
31+
region = process?.env?.AWS_SMOKE_TEST_REGION as string;
32+
Bucket = process?.env?.AWS_SMOKE_TEST_BUCKET as string;
33+
34+
Key = ``;
35+
data = randomBytes(20_240_000);
36+
dataString = data.toString();
37+
38+
// @ts-expect-error: Types of property 'requestChecksumCalculation' are incompatible
39+
client = new S3({
40+
region,
41+
requestChecksumCalculation,
42+
});
43+
Key = `multi-part-file-${requestChecksumCalculation}-${ChecksumAlgorithm}-${Date.now()}`;
3544
});
36-
Key = `multi-part-file-${requestChecksumCalculation}-${Date.now()}`;
37-
});
38-
39-
afterAll(async () => {
40-
await client.deleteObject({ Bucket, Key });
41-
});
4245

43-
it("should upload in parts for input type bytes", async () => {
44-
const s3Upload = new Upload({
45-
client,
46-
params: { Bucket, Key, Body: data },
46+
afterAll(async () => {
47+
await client.deleteObject({ Bucket, Key });
4748
});
48-
await s3Upload.done();
4949

50-
const object = await client.getObject({ Bucket, Key });
51-
expect(await object.Body?.transformToString()).toEqual(dataString);
52-
});
50+
it("should upload in parts for input type bytes", async () => {
51+
const s3Upload = new Upload({
52+
client,
53+
params: { Bucket, Key, Body: data, ChecksumAlgorithm },
54+
});
55+
await s3Upload.done();
5356

54-
it("should upload in parts for input type string", async () => {
55-
const s3Upload = new Upload({
56-
client,
57-
params: { Bucket, Key, Body: dataString },
57+
const object = await client.getObject({ Bucket, Key });
58+
expect(await object.Body?.transformToString()).toEqual(dataString);
5859
});
59-
await s3Upload.done();
6060

61-
const object = await client.getObject({ Bucket, Key });
62-
expect(await object.Body?.transformToString()).toEqual(dataString);
63-
});
61+
it("should upload in parts for input type string", async () => {
62+
const s3Upload = new Upload({
63+
client,
64+
params: { Bucket, Key, Body: dataString, ChecksumAlgorithm },
65+
});
66+
await s3Upload.done();
6467

65-
it("should upload in parts for input type Readable", async () => {
66-
const s3Upload = new Upload({
67-
client,
68-
params: { Bucket, Key, Body: Readable.from(data) },
68+
const object = await client.getObject({ Bucket, Key });
69+
expect(await object.Body?.transformToString()).toEqual(dataString);
6970
});
70-
await s3Upload.done();
71-
72-
const object = await client.getObject({ Bucket, Key });
73-
expect(await object.Body?.transformToString()).toEqual(dataString);
74-
});
7571

76-
it("should call AbortMultipartUpload if unable to complete a multipart upload.", async () => {
77-
class MockFailureS3 extends S3 {
78-
public counter = 0;
79-
async send(command: any, ...rest: any[]) {
80-
if (command?.constructor?.name === "UploadPartCommand" && this.counter++ % 3 === 0) {
81-
throw new Error("simulated upload part error");
82-
}
83-
return super.send(command, ...rest);
84-
}
85-
}
72+
it("should upload in parts for input type Readable", async () => {
73+
const s3Upload = new Upload({
74+
client,
75+
params: { Bucket, Key, Body: Readable.from(data), ChecksumAlgorithm },
76+
});
77+
await s3Upload.done();
8678

87-
const client = new MockFailureS3({
88-
region,
79+
const object = await client.getObject({ Bucket, Key });
80+
expect(await object.Body?.transformToString()).toEqual(dataString);
8981
});
9082

91-
const requestLog = [] as string[];
92-
93-
client.middlewareStack.add(
94-
(next, context) => async (args) => {
95-
const result = await next(args);
96-
requestLog.push(
97-
[context.clientName, context.commandName, result.output.$metadata.httpStatusCode].join(" ")
98-
);
99-
return result;
100-
},
101-
{
102-
name: "E2eRequestLog",
103-
step: "build",
104-
override: true,
83+
it("should call AbortMultipartUpload if unable to complete a multipart upload.", async () => {
84+
class MockFailureS3 extends S3 {
85+
public counter = 0;
86+
async send(command: any, ...rest: any[]) {
87+
if (command?.constructor?.name === "UploadPartCommand" && this.counter++ % 3 === 0) {
88+
throw new Error("simulated upload part error");
89+
}
90+
return super.send(command, ...rest);
91+
}
10592
}
106-
);
107-
108-
const s3Upload = new Upload({
109-
client,
110-
params: {
111-
Bucket,
112-
Key,
113-
Body: data,
114-
},
93+
94+
const client = new MockFailureS3({ region });
95+
96+
const requestLog = [] as string[];
97+
98+
client.middlewareStack.add(
99+
(next, context) => async (args) => {
100+
const result = await next(args);
101+
requestLog.push(
102+
[context.clientName, context.commandName, result.output.$metadata.httpStatusCode].join(" ")
103+
);
104+
return result;
105+
},
106+
{
107+
name: "E2eRequestLog",
108+
step: "build",
109+
override: true,
110+
}
111+
);
112+
113+
const s3Upload = new Upload({
114+
client,
115+
params: { Bucket, Key, Body: data, ChecksumAlgorithm },
116+
});
117+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
118+
await s3Upload.done().catch((ignored) => {});
119+
120+
const uploadStatus = await client
121+
.listParts({ Bucket, Key, UploadId: s3Upload.uploadId })
122+
.then((listParts) => listParts.$metadata.httpStatusCode)
123+
.catch((err) => err.toString());
124+
125+
expect(uploadStatus).toMatch(/NoSuchUpload:(.*?)aborted or completed\./);
126+
expect(requestLog).toEqual([
127+
"S3Client CreateMultipartUploadCommand 200",
128+
"S3Client UploadPartCommand 200",
129+
"S3Client UploadPartCommand 200",
130+
"S3Client AbortMultipartUploadCommand 204",
131+
]);
115132
});
116-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
117-
await s3Upload.done().catch((ignored) => {});
118-
119-
const uploadStatus = await client
120-
.listParts({
121-
Bucket,
122-
Key,
123-
UploadId: s3Upload.uploadId,
124-
})
125-
.then((listParts) => listParts.$metadata.httpStatusCode)
126-
.catch((err) => err.toString());
127-
128-
expect(uploadStatus).toMatch(/NoSuchUpload:(.*?)aborted or completed\./);
129-
expect(requestLog).toEqual([
130-
"S3Client CreateMultipartUploadCommand 200",
131-
"S3Client UploadPartCommand 200",
132-
"S3Client UploadPartCommand 200",
133-
"S3Client AbortMultipartUploadCommand 204",
134-
]);
135133
});
136134
}
137135
);

0 commit comments

Comments
 (0)