From 15ed5868693f7ab8a8cb415071894949f63655cf Mon Sep 17 00:00:00 2001 From: Trivikram Kamat <16024985+trivikr@users.noreply.github.com> Date: Mon, 28 Feb 2022 10:25:31 -0800 Subject: [PATCH] test(middleware-flexible-checksums): add tests for edge cases (#3362) --- .../src/flexibleChecksumsMiddleware.spec.ts | 39 ++++++++++++++----- .../src/getChecksum.spec.ts | 7 +++- .../getChecksumAlgorithmForRequest.spec.ts | 9 +++-- ...etChecksumAlgorithmListForResponse.spec.ts | 38 ++++++++++++++++-- .../src/validateChecksumFromResponse.spec.ts | 3 ++ 5 files changed, 76 insertions(+), 20 deletions(-) diff --git a/packages/middleware-flexible-checksums/src/flexibleChecksumsMiddleware.spec.ts b/packages/middleware-flexible-checksums/src/flexibleChecksumsMiddleware.spec.ts index 492d8c4d3295..17423ad38837 100644 --- a/packages/middleware-flexible-checksums/src/flexibleChecksumsMiddleware.spec.ts +++ b/packages/middleware-flexible-checksums/src/flexibleChecksumsMiddleware.spec.ts @@ -7,7 +7,6 @@ import { flexibleChecksumsMiddleware } from "./flexibleChecksumsMiddleware"; import { getChecksum } from "./getChecksum"; import { getChecksumAlgorithmForRequest } from "./getChecksumAlgorithmForRequest"; import { getChecksumLocationName } from "./getChecksumLocationName"; -import { FlexibleChecksumsMiddlewareConfig } from "./getFlexibleChecksumsPlugin"; import { hasHeader } from "./hasHeader"; import { isStreaming } from "./isStreaming"; import { selectChecksumAlgorithmFunction } from "./selectChecksumAlgorithmFunction"; @@ -31,13 +30,13 @@ describe(flexibleChecksumsMiddleware.name, () => { const mockInput = {}; const mockConfig = {} as PreviouslyResolved; - const mockMiddlewareConfig = { input: mockInput } as FlexibleChecksumsMiddlewareConfig; + const mockMiddlewareConfig = { input: mockInput, requestChecksumRequired: false }; - const mockBody = { body: "mockBody" }; + const mockBody = { body: "mockRequestBody" }; const mockHeaders = { "content-length": 100 }; const mockRequest = { body: mockBody, headers: mockHeaders }; const mockArgs = { request: mockRequest } as BuildHandlerArguments; - const mockResult = { response: {} }; + const mockResult = { response: { body: "mockResponsebody" } }; beforeEach(() => { mockNext.mockResolvedValueOnce(mockResult); @@ -89,9 +88,8 @@ describe(flexibleChecksumsMiddleware.name, () => { }; (hasHeader as jest.Mock).mockReturnValue(true); await handler(mockArgsWithChecksumHeader); - expect(getChecksumLocationName).toHaveBeenCalledTimes(1); - expect(selectChecksumAlgorithmFunction).toHaveBeenCalledTimes(1); - expect(hasHeader).toHaveBeenCalledTimes(1); + expect(getChecksumLocationName).toHaveBeenCalledWith(ChecksumAlgorithm.MD5); + expect(selectChecksumAlgorithmFunction).toHaveBeenCalledWith(ChecksumAlgorithm.MD5, mockConfig); expect(mockNext).toHaveBeenCalledWith(mockArgsWithChecksumHeader); expect(hasHeader).toHaveBeenCalledWith(mockChecksumLocationName, mockHeadersWithChecksumHeader); }); @@ -126,10 +124,20 @@ describe(flexibleChecksumsMiddleware.name, () => { it("for streaming body", async () => { (isStreaming as jest.Mock).mockReturnValue(true); const mockUpdatedBody = { body: "mockUpdatedBody" }; + + const mockBase64Encoder = jest.fn(); + const mockStreamHasher = jest.fn(); + const mockBodyLengthChecker = jest.fn(); const mockGetAwsChunkedEncodingStream = jest.fn().mockReturnValue(mockUpdatedBody); const handler = flexibleChecksumsMiddleware( - { ...mockConfig, getAwsChunkedEncodingStream: mockGetAwsChunkedEncodingStream }, + { + ...mockConfig, + base64Encoder: mockBase64Encoder, + bodyLengthChecker: mockBodyLengthChecker, + getAwsChunkedEncodingStream: mockGetAwsChunkedEncodingStream, + streamHasher: mockStreamHasher, + }, mockMiddlewareConfig )(mockNext, {}); await handler(mockArgs); @@ -150,7 +158,13 @@ describe(flexibleChecksumsMiddleware.name, () => { body: mockUpdatedBody, }, }); - expect(mockGetAwsChunkedEncodingStream).toHaveBeenCalledTimes(1); + expect(mockGetAwsChunkedEncodingStream).toHaveBeenCalledWith(mockRequest.body, { + base64Encoder: mockBase64Encoder, + bodyLengthChecker: mockBodyLengthChecker, + checksumLocationName: mockChecksumLocationName, + checksumAlgorithmFn: mockChecksumAlgorithmFunction, + streamHasher: mockStreamHasher, + }); }); it("for non-streaming body", async () => { @@ -172,14 +186,19 @@ describe(flexibleChecksumsMiddleware.name, () => { it("validates checksum from the response header", async () => { const mockRequestValidationModeMember = "mockRequestValidationModeMember"; const mockInput = { [mockRequestValidationModeMember]: "ENABLED" }; + const mockResponseAlgorithms = ["ALGO1", "ALGO2"]; const handler = flexibleChecksumsMiddleware(mockConfig, { ...mockMiddlewareConfig, input: mockInput, requestValidationModeMember: mockRequestValidationModeMember, + responseAlgorithms: mockResponseAlgorithms, })(mockNext, {}); await handler(mockArgs); - expect(validateChecksumFromResponse).toHaveBeenCalledTimes(1); + expect(validateChecksumFromResponse).toHaveBeenCalledWith(mockResult.response, { + config: mockConfig, + responseAlgorithms: mockResponseAlgorithms, + }); }); }); diff --git a/packages/middleware-flexible-checksums/src/getChecksum.spec.ts b/packages/middleware-flexible-checksums/src/getChecksum.spec.ts index d1a2a54d9594..187719a67561 100644 --- a/packages/middleware-flexible-checksums/src/getChecksum.spec.ts +++ b/packages/middleware-flexible-checksums/src/getChecksum.spec.ts @@ -14,6 +14,7 @@ describe(getChecksum.name, () => { const mockBody = "mockBody"; const mockOutput = "mockOutput"; + const mockRawOutput = Buffer.from(mockOutput); beforeEach(() => { mockOptions.base64Encoder.mockResolvedValueOnce(mockOutput); @@ -25,17 +26,19 @@ describe(getChecksum.name, () => { it("gets checksum from streamHasher if body is streaming", async () => { (isStreaming as jest.Mock).mockReturnValue(true); + mockOptions.streamHasher.mockResolvedValue(mockRawOutput); const checksum = await getChecksum(mockBody, mockOptions); expect(checksum).toEqual(mockOutput); expect(stringHasher).not.toHaveBeenCalled(); - expect(mockOptions.streamHasher).toHaveBeenCalledTimes(1); + expect(mockOptions.streamHasher).toHaveBeenCalledWith(mockOptions.checksumAlgorithmFn, mockBody); }); it("gets checksum from stringHasher if body is not streaming", async () => { (isStreaming as jest.Mock).mockReturnValue(false); + (stringHasher as jest.Mock).mockResolvedValue(mockRawOutput); const checksum = await getChecksum(mockBody, mockOptions); expect(checksum).toEqual(mockOutput); - expect(stringHasher).toHaveBeenCalledTimes(1); expect(mockOptions.streamHasher).not.toHaveBeenCalled(); + expect(stringHasher).toHaveBeenCalledWith(mockOptions.checksumAlgorithmFn, mockBody); }); }); diff --git a/packages/middleware-flexible-checksums/src/getChecksumAlgorithmForRequest.spec.ts b/packages/middleware-flexible-checksums/src/getChecksumAlgorithmForRequest.spec.ts index eb175cd906dc..49e51a7782eb 100644 --- a/packages/middleware-flexible-checksums/src/getChecksumAlgorithmForRequest.spec.ts +++ b/packages/middleware-flexible-checksums/src/getChecksumAlgorithmForRequest.spec.ts @@ -10,21 +10,22 @@ describe(getChecksumAlgorithmForRequest.name, () => { expect(getChecksumAlgorithmForRequest({}, { requestChecksumRequired: true })).toEqual(ChecksumAlgorithm.MD5); }); - it("returns undefined if requestChecksumRequired is not set", () => { - expect(getChecksumAlgorithmForRequest({}, { requestChecksumRequired: false })).toBeUndefined(); + it.each([false, undefined])("returns undefined if requestChecksumRequired=%s", (requestChecksumRequired) => { + expect(getChecksumAlgorithmForRequest({}, { requestChecksumRequired })).toBeUndefined(); }); }); describe("when requestAlgorithmMember is not set in input", () => { const mockOptions = { requestAlgorithmMember: mockRequestAlgorithmMember }; + it("returns MD5 if requestChecksumRequired is set", () => { expect(getChecksumAlgorithmForRequest({}, { ...mockOptions, requestChecksumRequired: true })).toEqual( ChecksumAlgorithm.MD5 ); }); - it("returns undefined if requestChecksumRequired is not set", () => { - expect(getChecksumAlgorithmForRequest({}, { ...mockOptions, requestChecksumRequired: false })).toBeUndefined(); + it.each([false, undefined])("returns undefined if requestChecksumRequired=%s", (requestChecksumRequired) => { + expect(getChecksumAlgorithmForRequest({}, { ...mockOptions, requestChecksumRequired })).toBeUndefined(); }); }); diff --git a/packages/middleware-flexible-checksums/src/getChecksumAlgorithmListForResponse.spec.ts b/packages/middleware-flexible-checksums/src/getChecksumAlgorithmListForResponse.spec.ts index a78dff0bf3c3..4084925e827a 100644 --- a/packages/middleware-flexible-checksums/src/getChecksumAlgorithmListForResponse.spec.ts +++ b/packages/middleware-flexible-checksums/src/getChecksumAlgorithmListForResponse.spec.ts @@ -2,16 +2,46 @@ import { getChecksumAlgorithmListForResponse } from "./getChecksumAlgorithmListF import { PRIORITY_ORDER_ALGORITHMS } from "./types"; describe(getChecksumAlgorithmListForResponse.name, () => { + const unknownAlgorithm = "UNKNOWNALGO"; + it("returns empty if responseAlgorithms is empty", () => { expect(getChecksumAlgorithmListForResponse([])).toEqual([]); }); it("returns empty if contents of responseAlgorithms is not in priority order", () => { - expect(getChecksumAlgorithmListForResponse(["UNKNOWNALGO"])).toEqual([]); + expect(getChecksumAlgorithmListForResponse([unknownAlgorithm])).toEqual([]); + }); + + describe("returns list as per priority order", () => { + it("when all algorithms are passed in reverse order", () => { + expect(getChecksumAlgorithmListForResponse([...PRIORITY_ORDER_ALGORITHMS].reverse())).toEqual( + PRIORITY_ORDER_ALGORITHMS + ); + }); + + it.each([...Array(PRIORITY_ORDER_ALGORITHMS.length).keys()].filter((num) => num !== 0))( + "when subset of algorithms are passed in reverse order starting with element at '%s'", + (start) => { + const responseAlgorithms = PRIORITY_ORDER_ALGORITHMS.slice(start); + expect(getChecksumAlgorithmListForResponse([...responseAlgorithms].reverse())).toEqual(responseAlgorithms); + } + ); + + it.each([...Array(PRIORITY_ORDER_ALGORITHMS.length).keys()].filter((num) => num !== 0))( + "when subset of algorithms are passed in reverse order ending with element at '%s' from last", + (end) => { + const responseAlgorithms = PRIORITY_ORDER_ALGORITHMS.slice(PRIORITY_ORDER_ALGORITHMS.length - end); + expect(getChecksumAlgorithmListForResponse([...responseAlgorithms].reverse())).toEqual(responseAlgorithms); + } + ); }); - it("returns list as per priority order", () => { - const responseAlgorithms = [...PRIORITY_ORDER_ALGORITHMS]; - expect(getChecksumAlgorithmListForResponse(responseAlgorithms.reverse())).toEqual(PRIORITY_ORDER_ALGORITHMS); + it("ignores algorithms not present in priority list", () => { + expect(getChecksumAlgorithmListForResponse([unknownAlgorithm, ...PRIORITY_ORDER_ALGORITHMS].reverse())).toEqual( + PRIORITY_ORDER_ALGORITHMS + ); + expect(getChecksumAlgorithmListForResponse([...PRIORITY_ORDER_ALGORITHMS, unknownAlgorithm].reverse())).toEqual( + PRIORITY_ORDER_ALGORITHMS + ); }); }); diff --git a/packages/middleware-flexible-checksums/src/validateChecksumFromResponse.spec.ts b/packages/middleware-flexible-checksums/src/validateChecksumFromResponse.spec.ts index cce1f4097417..abf9805f170d 100644 --- a/packages/middleware-flexible-checksums/src/validateChecksumFromResponse.spec.ts +++ b/packages/middleware-flexible-checksums/src/validateChecksumFromResponse.spec.ts @@ -92,6 +92,7 @@ describe(validateChecksumFromResponse.name, () => { responseAlgorithms: mockResponseAlgorithms, }); expect(getChecksumLocationName).toHaveBeenCalledTimes(1); + expect(getChecksumLocationName).toHaveBeenCalledWith(mockResponseAlgorithms[0]); }); it("when checksum is populated for second algorithm", async () => { @@ -101,6 +102,8 @@ describe(validateChecksumFromResponse.name, () => { responseAlgorithms: mockResponseAlgorithms, }); expect(getChecksumLocationName).toHaveBeenCalledTimes(2); + expect(getChecksumLocationName).toHaveBeenNthCalledWith(1, mockResponseAlgorithms[0]); + expect(getChecksumLocationName).toHaveBeenNthCalledWith(2, mockResponseAlgorithms[1]); }); });