Skip to content

Commit

Permalink
test(middleware-flexible-checksums): add tests for edge cases (#3362)
Browse files Browse the repository at this point in the history
  • Loading branch information
trivikr committed Feb 28, 2022
1 parent a331a3b commit 15ed586
Show file tree
Hide file tree
Showing 5 changed files with 76 additions and 20 deletions.
Expand Up @@ -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";
Expand All @@ -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<any>;
const mockResult = { response: {} };
const mockResult = { response: { body: "mockResponsebody" } };

beforeEach(() => {
mockNext.mockResolvedValueOnce(mockResult);
Expand Down Expand Up @@ -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);
});
Expand Down Expand Up @@ -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);
Expand All @@ -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 () => {
Expand All @@ -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,
});
});
});
Expand Up @@ -14,6 +14,7 @@ describe(getChecksum.name, () => {

const mockBody = "mockBody";
const mockOutput = "mockOutput";
const mockRawOutput = Buffer.from(mockOutput);

beforeEach(() => {
mockOptions.base64Encoder.mockResolvedValueOnce(mockOutput);
Expand All @@ -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);
});
});
Expand Up @@ -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();
});
});

Expand Down
Expand Up @@ -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
);
});
});
Expand Up @@ -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 () => {
Expand All @@ -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]);
});
});

Expand Down

0 comments on commit 15ed586

Please sign in to comment.