1
- import { S3 } from "@aws-sdk/client-s3" ;
1
+ import { ChecksumAlgorithm , S3 } from "@aws-sdk/client-s3" ;
2
2
import { Upload } from "@aws-sdk/lib-storage" ;
3
3
import { randomBytes } from "crypto" ;
4
4
import { Readable } from "stream" ;
@@ -7,153 +7,130 @@ import { afterAll, beforeAll, describe, expect, test as it } from "vitest";
7
7
import { getIntegTestResources } from "../../../tests/e2e/get-integ-test-resources" ;
8
8
9
9
describe ( "@aws-sdk/lib-storage" , ( ) => {
10
- let Key : string ;
11
- let client : S3 ;
12
- let data : Uint8Array ;
13
- let dataString : string ;
14
- let Bucket : string ;
15
- let region : string ;
16
-
17
- beforeAll ( async ( ) => {
18
- const integTestResourcesEnv = await getIntegTestResources ( ) ;
19
- Object . assign ( process . env , integTestResourcesEnv ) ;
20
-
21
- region = process ?. env ?. AWS_SMOKE_TEST_REGION as string ;
22
- Bucket = process ?. env ?. AWS_SMOKE_TEST_BUCKET as string ;
23
-
24
- Key = `` ;
25
- data = randomBytes ( 20_240_000 ) ;
26
- dataString = data . toString ( ) ;
27
-
28
- client = new S3 ( {
29
- region,
30
- // ToDo(JS-5678): Remove this when default checksum is supported by Upload.
31
- requestChecksumCalculation : "WHEN_REQUIRED" ,
32
- } ) ;
33
- } ) ;
34
-
35
- describe ( "Upload" , ( ) => {
36
- beforeAll ( ( ) => {
37
- Key = `multi-part-file-${ Date . now ( ) } ` ;
38
- } ) ;
39
- afterAll ( async ( ) => {
40
- await client . deleteObject ( { Bucket, Key } ) ;
41
- } ) ;
42
-
43
- it ( "should upload in parts for input type bytes" , async ( ) => {
44
- const s3Upload = new Upload ( {
45
- client,
46
- params : {
47
- Bucket,
48
- Key,
49
- Body : data ,
50
- } ,
51
- } ) ;
52
- await s3Upload . done ( ) ;
53
-
54
- const object = await client . getObject ( {
55
- Bucket,
56
- Key,
57
- } ) ;
58
-
59
- expect ( await object . Body ?. transformToString ( ) ) . toEqual ( dataString ) ;
60
- } ) ;
61
-
62
- it ( "should upload in parts for input type string" , async ( ) => {
63
- const s3Upload = new Upload ( {
64
- client,
65
- params : {
66
- Bucket,
67
- Key,
68
- Body : dataString ,
69
- } ,
70
- } ) ;
71
- await s3Upload . done ( ) ;
72
-
73
- const object = await client . getObject ( {
74
- Bucket,
75
- Key,
76
- } ) ;
77
-
78
- expect ( await object . Body ?. transformToString ( ) ) . toEqual ( dataString ) ;
79
- } ) ;
80
-
81
- it ( "should upload in parts for input type Readable" , async ( ) => {
82
- const s3Upload = new Upload ( {
83
- client,
84
- params : {
85
- Bucket,
86
- Key,
87
- Body : Readable . from ( data ) ,
88
- } ,
89
- } ) ;
90
- await s3Upload . done ( ) ;
91
-
92
- const object = await client . getObject ( {
93
- Bucket,
94
- Key,
95
- } ) ;
96
-
97
- expect ( await object . Body ?. transformToString ( ) ) . toEqual ( dataString ) ;
98
- } ) ;
99
-
100
- it ( "should call AbortMultipartUpload if unable to complete a multipart upload." , async ( ) => {
101
- class MockFailureS3 extends S3 {
102
- public counter = 0 ;
103
- async send ( command : any , ...rest : any [ ] ) {
104
- if ( command ?. constructor ?. name === "UploadPartCommand" && this . counter ++ % 3 === 0 ) {
105
- throw new Error ( "simulated upload part error" ) ;
10
+ describe . each ( [ undefined , "WHEN_REQUIRED" , "WHEN_SUPPORTED" ] ) (
11
+ "requestChecksumCalculation: %s" ,
12
+ ( 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 ( ) } ` ;
44
+ } ) ;
45
+
46
+ afterAll ( async ( ) => {
47
+ await client . deleteObject ( { Bucket, Key } ) ;
48
+ } ) ;
49
+
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 ( ) ;
56
+
57
+ const object = await client . getObject ( { Bucket, Key } ) ;
58
+ expect ( await object . Body ?. transformToString ( ) ) . toEqual ( dataString ) ;
59
+ } ) ;
60
+
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 ( ) ;
67
+
68
+ const object = await client . getObject ( { Bucket, Key } ) ;
69
+ expect ( await object . Body ?. transformToString ( ) ) . toEqual ( dataString ) ;
70
+ } ) ;
71
+
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 ( ) ;
78
+
79
+ const object = await client . getObject ( { Bucket, Key } ) ;
80
+ expect ( await object . Body ?. transformToString ( ) ) . toEqual ( dataString ) ;
81
+ } ) ;
82
+
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
+ }
106
92
}
107
- return super . send ( command , ...rest ) ;
108
- }
109
- }
110
-
111
- const client = new MockFailureS3 ( {
112
- region,
113
- } ) ;
114
93
115
- const requestLog = [ ] as string [ ] ;
116
-
117
- client . middlewareStack . add (
118
- ( next , context ) => async ( args ) => {
119
- const result = await next ( args ) ;
120
- requestLog . push ( [ context . clientName , context . commandName , result . output . $metadata . httpStatusCode ] . join ( " " ) ) ;
121
- return result ;
122
- } ,
123
- {
124
- name : "E2eRequestLog" ,
125
- step : "build" ,
126
- override : true ,
127
- }
128
- ) ;
129
-
130
- const s3Upload = new Upload ( {
131
- client,
132
- params : {
133
- Bucket,
134
- Key,
135
- Body : data ,
136
- } ,
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 ( / N o S u c h U p l o a d : ( .* ?) a b o r t e d o r c o m p l e t e d \. / ) ;
126
+ expect ( requestLog ) . toEqual ( [
127
+ "S3Client CreateMultipartUploadCommand 200" ,
128
+ "S3Client UploadPartCommand 200" ,
129
+ "S3Client UploadPartCommand 200" ,
130
+ "S3Client AbortMultipartUploadCommand 204" ,
131
+ ] ) ;
132
+ } ) ;
137
133
} ) ;
138
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
139
- await s3Upload . done ( ) . catch ( ( ignored ) => { } ) ;
140
-
141
- const uploadStatus = await client
142
- . listParts ( {
143
- Bucket,
144
- Key,
145
- UploadId : s3Upload . uploadId ,
146
- } )
147
- . then ( ( listParts ) => listParts . $metadata . httpStatusCode )
148
- . catch ( ( err ) => err . toString ( ) ) ;
149
-
150
- expect ( uploadStatus ) . toMatch ( / N o S u c h U p l o a d : ( .* ?) a b o r t e d o r c o m p l e t e d \. / ) ;
151
- expect ( requestLog ) . toEqual ( [
152
- "S3Client CreateMultipartUploadCommand 200" ,
153
- "S3Client UploadPartCommand 200" ,
154
- "S3Client UploadPartCommand 200" ,
155
- "S3Client AbortMultipartUploadCommand 204" ,
156
- ] ) ;
157
- } ) ;
158
- } ) ;
134
+ }
135
+ ) ;
159
136
} , 45_000 ) ;
0 commit comments