11import { HttpResponse } from "@smithy/protocol-http" ;
2+ import { createChecksumStream } from "@smithy/util-stream" ;
23import { afterEach , beforeEach , describe , expect , test as it , vi } from "vitest" ;
34
45import { PreviouslyResolved } from "./configuration" ;
56import { ChecksumAlgorithm } from "./constants" ;
67import { getChecksum } from "./getChecksum" ;
78import { getChecksumAlgorithmListForResponse } from "./getChecksumAlgorithmListForResponse" ;
89import { getChecksumLocationName } from "./getChecksumLocationName" ;
10+ import { isStreaming } from "./isStreaming" ;
911import { selectChecksumAlgorithmFunction } from "./selectChecksumAlgorithmFunction" ;
1012import { validateChecksumFromResponse } from "./validateChecksumFromResponse" ;
1113
14+ vi . mock ( "@smithy/util-stream" ) ;
1215vi . mock ( "./getChecksum" ) ;
1316vi . mock ( "./getChecksumLocationName" ) ;
1417vi . mock ( "./getChecksumAlgorithmListForResponse" ) ;
18+ vi . mock ( "./isStreaming" ) ;
1519vi . mock ( "./selectChecksumAlgorithmFunction" ) ;
1620
1721describe ( validateChecksumFromResponse . name , ( ) => {
1822 const mockConfig = {
19- streamHasher : vi . fn ( ) ,
2023 base64Encoder : vi . fn ( ) ,
2124 } as unknown as PreviouslyResolved ;
2225
2326 const mockBody = { } ;
27+ const mockBodyStream = { isStream : true } ;
2428 const mockHeaders = { } ;
2529 const mockResponse = {
2630 body : mockBody ,
@@ -50,6 +54,7 @@ describe(validateChecksumFromResponse.name, () => {
5054 vi . mocked ( getChecksumAlgorithmListForResponse ) . mockImplementation ( ( responseAlgorithms ) => responseAlgorithms ) ;
5155 vi . mocked ( selectChecksumAlgorithmFunction ) . mockReturnValue ( mockChecksumAlgorithmFn ) ;
5256 vi . mocked ( getChecksum ) . mockResolvedValue ( mockChecksum ) ;
57+ vi . mocked ( createChecksumStream ) . mockReturnValue ( mockBodyStream ) ;
5358 } ) ;
5459
5560 afterEach ( ( ) => {
@@ -85,31 +90,56 @@ describe(validateChecksumFromResponse.name, () => {
8590 } ) ;
8691
8792 describe ( "successful validation" , ( ) => {
88- afterEach ( ( ) => {
93+ const validateCalls = ( isStream : boolean , checksumAlgoFn : ChecksumAlgorithm ) => {
8994 expect ( getChecksumAlgorithmListForResponse ) . toHaveBeenCalledWith ( mockResponseAlgorithms ) ;
9095 expect ( selectChecksumAlgorithmFunction ) . toHaveBeenCalledTimes ( 1 ) ;
91- expect ( getChecksum ) . toHaveBeenCalledTimes ( 1 ) ;
92- } ) ;
9396
94- it ( "when checksum is populated for first algorithm" , async ( ) => {
97+ if ( isStream ) {
98+ expect ( getChecksum ) . not . toHaveBeenCalled ( ) ;
99+ expect ( createChecksumStream ) . toHaveBeenCalledTimes ( 1 ) ;
100+ expect ( createChecksumStream ) . toHaveBeenCalledWith ( {
101+ expectedChecksum : mockChecksum ,
102+ checksumSourceLocation : checksumAlgoFn ,
103+ checksum : new mockChecksumAlgorithmFn ( ) ,
104+ source : mockBody ,
105+ base64Encoder : mockConfig . base64Encoder ,
106+ } ) ;
107+ } else {
108+ expect ( getChecksum ) . toHaveBeenCalledTimes ( 1 ) ;
109+ expect ( getChecksum ) . toHaveBeenCalledWith ( mockBody , {
110+ checksumAlgorithmFn : mockChecksumAlgorithmFn ,
111+ base64Encoder : mockConfig . base64Encoder ,
112+ } ) ;
113+ expect ( createChecksumStream ) . not . toHaveBeenCalled ( ) ;
114+ }
115+ } ;
116+
117+ it . each ( [ false , true ] ) ( "when checksum is populated for first algorithm when streaming: %s" , async ( isStream ) => {
118+ vi . mocked ( isStreaming ) . mockReturnValue ( isStream ) ;
95119 const responseWithChecksum = getMockResponseWithHeader ( mockResponseAlgorithms [ 0 ] , mockChecksum ) ;
96120 await validateChecksumFromResponse ( responseWithChecksum , mockOptions ) ;
97121 expect ( getChecksumLocationName ) . toHaveBeenCalledTimes ( 1 ) ;
98122 expect ( getChecksumLocationName ) . toHaveBeenCalledWith ( mockResponseAlgorithms [ 0 ] ) ;
123+ validateCalls ( isStream , mockResponseAlgorithms [ 0 ] ) ;
99124 } ) ;
100125
101- it ( "when checksum is populated for second algorithm" , async ( ) => {
126+ it . each ( [ false , true ] ) ( "when checksum is populated for second algorithm when streaming: %s" , async ( isStream ) => {
127+ vi . mocked ( isStreaming ) . mockReturnValue ( isStream ) ;
102128 const responseWithChecksum = getMockResponseWithHeader ( mockResponseAlgorithms [ 1 ] , mockChecksum ) ;
103129 await validateChecksumFromResponse ( responseWithChecksum , mockOptions ) ;
104130 expect ( getChecksumLocationName ) . toHaveBeenCalledTimes ( 2 ) ;
105131 expect ( getChecksumLocationName ) . toHaveBeenNthCalledWith ( 1 , mockResponseAlgorithms [ 0 ] ) ;
106132 expect ( getChecksumLocationName ) . toHaveBeenNthCalledWith ( 2 , mockResponseAlgorithms [ 1 ] ) ;
133+ validateCalls ( isStream , mockResponseAlgorithms [ 1 ] ) ;
107134 } ) ;
108135 } ) ;
109136
110- it ( "throw error if checksum value is not accurate" , async ( ) => {
137+ it ( "throw error if checksum value is not accurate when not streaming" , async ( ) => {
138+ vi . mocked ( isStreaming ) . mockReturnValue ( false ) ;
139+
111140 const incorrectChecksum = "incorrectChecksum" ;
112141 const responseWithChecksum = getMockResponseWithHeader ( mockResponseAlgorithms [ 0 ] , incorrectChecksum ) ;
142+
113143 try {
114144 await validateChecksumFromResponse ( responseWithChecksum , mockOptions ) ;
115145 fail ( "should throw checksum mismatch error" ) ;
@@ -119,9 +149,28 @@ describe(validateChecksumFromResponse.name, () => {
119149 ` in response header "${ mockResponseAlgorithms [ 0 ] } ".`
120150 ) ;
121151 }
152+
122153 expect ( getChecksumAlgorithmListForResponse ) . toHaveBeenCalledWith ( mockResponseAlgorithms ) ;
123154 expect ( selectChecksumAlgorithmFunction ) . toHaveBeenCalledTimes ( 1 ) ;
124155 expect ( getChecksumLocationName ) . toHaveBeenCalledTimes ( 1 ) ;
125156 expect ( getChecksum ) . toHaveBeenCalledTimes ( 1 ) ;
157+ expect ( createChecksumStream ) . not . toHaveBeenCalled ( ) ;
158+ } ) ;
159+
160+ it ( "return if checksum value is not accurate when streaming, as error will be thrown when stream is consumed" , async ( ) => {
161+ vi . mocked ( isStreaming ) . mockReturnValue ( true ) ;
162+
163+ // This override does not matter for the purpose of unit test, but is kept for completeness.
164+ const incorrectChecksum = "incorrectChecksum" ;
165+ const responseWithChecksum = getMockResponseWithHeader ( mockResponseAlgorithms [ 0 ] , incorrectChecksum ) ;
166+
167+ await validateChecksumFromResponse ( responseWithChecksum , mockOptions ) ;
168+
169+ expect ( getChecksumAlgorithmListForResponse ) . toHaveBeenCalledWith ( mockResponseAlgorithms ) ;
170+ expect ( selectChecksumAlgorithmFunction ) . toHaveBeenCalledTimes ( 1 ) ;
171+ expect ( getChecksumLocationName ) . toHaveBeenCalledTimes ( 1 ) ;
172+ expect ( getChecksum ) . not . toHaveBeenCalled ( ) ;
173+ expect ( createChecksumStream ) . toHaveBeenCalledTimes ( 1 ) ;
174+ expect ( responseWithChecksum . body ) . toBe ( mockBodyStream ) ;
126175 } ) ;
127176} ) ;
0 commit comments