-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Clean up args and arrange imports * Arrange args in restore tests * Add unit tests for save * Use const instead of let (linting)
- Loading branch information
Josh Gross
authored and
GitHub
committed
Nov 14, 2019
1 parent
c0584c4
commit 8d14a21
Showing
5 changed files
with
390 additions
and
44 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,329 @@ | ||
| import * as core from "@actions/core"; | ||
| import * as exec from "@actions/exec"; | ||
| import * as io from "@actions/io"; | ||
| import * as path from "path"; | ||
| import * as cacheHttpClient from "../src/cacheHttpClient"; | ||
| import { Inputs } from "../src/constants"; | ||
| import { ArtifactCacheEntry } from "../src/contracts"; | ||
| import run from "../src/save"; | ||
| import * as actionUtils from "../src/utils/actionUtils"; | ||
| import * as testUtils from "../src/utils/testUtils"; | ||
|
|
||
| jest.mock("@actions/core"); | ||
| jest.mock("@actions/exec"); | ||
| jest.mock("@actions/io"); | ||
| jest.mock("../src/utils/actionUtils"); | ||
| jest.mock("../src/cacheHttpClient"); | ||
|
|
||
| beforeAll(() => { | ||
| jest.spyOn(core, "getInput").mockImplementation((name, options) => { | ||
| return jest.requireActual("@actions/core").getInput(name, options); | ||
| }); | ||
|
|
||
| jest.spyOn(actionUtils, "getCacheState").mockImplementation(() => { | ||
| return jest.requireActual("../src/utils/actionUtils").getCacheState(); | ||
| }); | ||
|
|
||
| jest.spyOn(actionUtils, "isExactKeyMatch").mockImplementation( | ||
| (key, cacheResult) => { | ||
| return jest | ||
| .requireActual("../src/utils/actionUtils") | ||
| .isExactKeyMatch(key, cacheResult); | ||
| } | ||
| ); | ||
|
|
||
| jest.spyOn(actionUtils, "resolvePath").mockImplementation(filePath => { | ||
| return path.resolve(filePath); | ||
| }); | ||
|
|
||
| jest.spyOn(actionUtils, "createTempDirectory").mockImplementation(() => { | ||
| return Promise.resolve("/foo/bar"); | ||
| }); | ||
|
|
||
| jest.spyOn(io, "which").mockImplementation(tool => { | ||
| return Promise.resolve(tool); | ||
| }); | ||
| }); | ||
|
|
||
| afterEach(() => { | ||
| testUtils.clearInputs(); | ||
| }); | ||
|
|
||
| test("save with no primary key in state outputs warning", async () => { | ||
| const warningMock = jest.spyOn(core, "warning"); | ||
| const failedMock = jest.spyOn(core, "setFailed"); | ||
|
|
||
| const cacheEntry: ArtifactCacheEntry = { | ||
| cacheKey: "Linux-node-bb828da54c148048dd17899ba9fda624811cfb43", | ||
| scope: "refs/heads/master", | ||
| creationTime: "2019-11-13T19:18:02+00:00", | ||
| archiveLocation: "www.actionscache.test/download" | ||
| }; | ||
|
|
||
| jest.spyOn(core, "getState") | ||
| // Cache Entry State | ||
| .mockImplementationOnce(() => { | ||
| return JSON.stringify(cacheEntry); | ||
| }) | ||
| // Cache Key State | ||
| .mockImplementationOnce(() => { | ||
| return ""; | ||
| }); | ||
|
|
||
| await run(); | ||
|
|
||
| expect(warningMock).toHaveBeenCalledWith( | ||
| `Error retrieving key from state.` | ||
| ); | ||
| expect(warningMock).toHaveBeenCalledTimes(1); | ||
| expect(failedMock).toHaveBeenCalledTimes(0); | ||
| }); | ||
|
|
||
| test("save with exact match returns early", async () => { | ||
| const infoMock = jest.spyOn(core, "info"); | ||
| const warningMock = jest.spyOn(core, "warning"); | ||
| const failedMock = jest.spyOn(core, "setFailed"); | ||
|
|
||
| const primaryKey = "Linux-node-bb828da54c148048dd17899ba9fda624811cfb43"; | ||
| const cacheEntry: ArtifactCacheEntry = { | ||
| cacheKey: primaryKey, | ||
| scope: "refs/heads/master", | ||
| creationTime: "2019-11-13T19:18:02+00:00", | ||
| archiveLocation: "www.actionscache.test/download" | ||
| }; | ||
|
|
||
| jest.spyOn(core, "getState") | ||
| // Cache Entry State | ||
| .mockImplementationOnce(() => { | ||
| return JSON.stringify(cacheEntry); | ||
| }) | ||
| // Cache Key State | ||
| .mockImplementationOnce(() => { | ||
| return primaryKey; | ||
| }); | ||
|
|
||
| const execMock = jest.spyOn(exec, "exec"); | ||
|
|
||
| await run(); | ||
|
|
||
| expect(infoMock).toHaveBeenCalledWith( | ||
| `Cache hit occurred on the primary key ${primaryKey}, not saving cache.` | ||
| ); | ||
|
|
||
| expect(execMock).toHaveBeenCalledTimes(0); | ||
|
|
||
| expect(warningMock).toHaveBeenCalledTimes(0); | ||
| expect(failedMock).toHaveBeenCalledTimes(0); | ||
| }); | ||
|
|
||
| test("save with missing input outputs warning", async () => { | ||
| const warningMock = jest.spyOn(core, "warning"); | ||
| const failedMock = jest.spyOn(core, "setFailed"); | ||
|
|
||
| const primaryKey = "Linux-node-bb828da54c148048dd17899ba9fda624811cfb43"; | ||
| const cacheEntry: ArtifactCacheEntry = { | ||
| cacheKey: "Linux-node-", | ||
| scope: "refs/heads/master", | ||
| creationTime: "2019-11-13T19:18:02+00:00", | ||
| archiveLocation: "www.actionscache.test/download" | ||
| }; | ||
|
|
||
| jest.spyOn(core, "getState") | ||
| // Cache Entry State | ||
| .mockImplementationOnce(() => { | ||
| return JSON.stringify(cacheEntry); | ||
| }) | ||
| // Cache Key State | ||
| .mockImplementationOnce(() => { | ||
| return primaryKey; | ||
| }); | ||
|
|
||
| await run(); | ||
|
|
||
| expect(warningMock).toHaveBeenCalledWith( | ||
| "Input required and not supplied: path" | ||
| ); | ||
| expect(warningMock).toHaveBeenCalledTimes(1); | ||
| expect(failedMock).toHaveBeenCalledTimes(0); | ||
| }); | ||
|
|
||
| test("save with large cache outputs warning", async () => { | ||
| const warningMock = jest.spyOn(core, "warning"); | ||
| const failedMock = jest.spyOn(core, "setFailed"); | ||
|
|
||
| const primaryKey = "Linux-node-bb828da54c148048dd17899ba9fda624811cfb43"; | ||
| const cacheEntry: ArtifactCacheEntry = { | ||
| cacheKey: "Linux-node-", | ||
| scope: "refs/heads/master", | ||
| creationTime: "2019-11-13T19:18:02+00:00", | ||
| archiveLocation: "www.actionscache.test/download" | ||
| }; | ||
|
|
||
| jest.spyOn(core, "getState") | ||
| // Cache Entry State | ||
| .mockImplementationOnce(() => { | ||
| return JSON.stringify(cacheEntry); | ||
| }) | ||
| // Cache Key State | ||
| .mockImplementationOnce(() => { | ||
| return primaryKey; | ||
| }); | ||
|
|
||
| const inputPath = "node_modules"; | ||
| const cachePath = path.resolve(inputPath); | ||
| testUtils.setInput(Inputs.Path, inputPath); | ||
|
|
||
| const execMock = jest.spyOn(exec, "exec"); | ||
|
|
||
| const cacheSize = 1024 * 1024 * 1024; //~1GB, over the 400MB limit | ||
| jest.spyOn(actionUtils, "getArchiveFileSize").mockImplementationOnce(() => { | ||
| return cacheSize; | ||
| }); | ||
|
|
||
| await run(); | ||
|
|
||
| const archivePath = path.join("/foo/bar", "cache.tgz"); | ||
|
|
||
| const IS_WINDOWS = process.platform === "win32"; | ||
| const args = IS_WINDOWS | ||
| ? [ | ||
| "-cz", | ||
| "--force-local", | ||
| "-f", | ||
| archivePath.replace(/\\/g, "/"), | ||
| "-C", | ||
| cachePath.replace(/\\/g, "/"), | ||
| "." | ||
| ] | ||
| : ["-cz", "-f", archivePath, "-C", cachePath, "."]; | ||
|
|
||
| expect(execMock).toHaveBeenCalledTimes(1); | ||
| expect(execMock).toHaveBeenCalledWith(`"tar"`, args); | ||
|
|
||
| expect(warningMock).toHaveBeenCalledTimes(1); | ||
| expect(warningMock).toHaveBeenCalledWith( | ||
| "Cache size of ~1024 MB (1073741824 B) is over the 400MB limit, not saving cache." | ||
| ); | ||
|
|
||
| expect(failedMock).toHaveBeenCalledTimes(0); | ||
| }); | ||
|
|
||
| test("save with server error outputs warning", async () => { | ||
| const warningMock = jest.spyOn(core, "warning"); | ||
| const failedMock = jest.spyOn(core, "setFailed"); | ||
|
|
||
| const primaryKey = "Linux-node-bb828da54c148048dd17899ba9fda624811cfb43"; | ||
| const cacheEntry: ArtifactCacheEntry = { | ||
| cacheKey: "Linux-node-", | ||
| scope: "refs/heads/master", | ||
| creationTime: "2019-11-13T19:18:02+00:00", | ||
| archiveLocation: "www.actionscache.test/download" | ||
| }; | ||
|
|
||
| jest.spyOn(core, "getState") | ||
| // Cache Entry State | ||
| .mockImplementationOnce(() => { | ||
| return JSON.stringify(cacheEntry); | ||
| }) | ||
| // Cache Key State | ||
| .mockImplementationOnce(() => { | ||
| return primaryKey; | ||
| }); | ||
|
|
||
| const inputPath = "node_modules"; | ||
| const cachePath = path.resolve(inputPath); | ||
| testUtils.setInput(Inputs.Path, inputPath); | ||
|
|
||
| const execMock = jest.spyOn(exec, "exec"); | ||
|
|
||
| const saveCacheMock = jest | ||
| .spyOn(cacheHttpClient, "saveCache") | ||
| .mockImplementationOnce(() => { | ||
| throw new Error("HTTP Error Occurred"); | ||
| }); | ||
|
|
||
| await run(); | ||
|
|
||
| const archivePath = path.join("/foo/bar", "cache.tgz"); | ||
|
|
||
| const IS_WINDOWS = process.platform === "win32"; | ||
| const args = IS_WINDOWS | ||
| ? [ | ||
| "-cz", | ||
| "--force-local", | ||
| "-f", | ||
| archivePath.replace(/\\/g, "/"), | ||
| "-C", | ||
| cachePath.replace(/\\/g, "/"), | ||
| "." | ||
| ] | ||
| : ["-cz", "-f", archivePath, "-C", cachePath, "."]; | ||
|
|
||
| expect(execMock).toHaveBeenCalledTimes(1); | ||
| expect(execMock).toHaveBeenCalledWith(`"tar"`, args); | ||
|
|
||
| expect(saveCacheMock).toHaveBeenCalledTimes(1); | ||
| expect(saveCacheMock).toHaveBeenCalledWith(primaryKey, archivePath); | ||
|
|
||
| expect(warningMock).toHaveBeenCalledTimes(1); | ||
| expect(warningMock).toHaveBeenCalledWith("HTTP Error Occurred"); | ||
|
|
||
| expect(failedMock).toHaveBeenCalledTimes(0); | ||
| }); | ||
|
|
||
| test("save with valid inputs uploads a cache", async () => { | ||
| const warningMock = jest.spyOn(core, "warning"); | ||
| const failedMock = jest.spyOn(core, "setFailed"); | ||
|
|
||
| const primaryKey = "Linux-node-bb828da54c148048dd17899ba9fda624811cfb43"; | ||
| const cacheEntry: ArtifactCacheEntry = { | ||
| cacheKey: "Linux-node-", | ||
| scope: "refs/heads/master", | ||
| creationTime: "2019-11-13T19:18:02+00:00", | ||
| archiveLocation: "www.actionscache.test/download" | ||
| }; | ||
|
|
||
| jest.spyOn(core, "getState") | ||
| // Cache Entry State | ||
| .mockImplementationOnce(() => { | ||
| return JSON.stringify(cacheEntry); | ||
| }) | ||
| // Cache Key State | ||
| .mockImplementationOnce(() => { | ||
| return primaryKey; | ||
| }); | ||
|
|
||
| const inputPath = "node_modules"; | ||
| const cachePath = path.resolve(inputPath); | ||
| testUtils.setInput(Inputs.Path, inputPath); | ||
|
|
||
| const execMock = jest.spyOn(exec, "exec"); | ||
|
|
||
| const saveCacheMock = jest.spyOn(cacheHttpClient, "saveCache"); | ||
|
|
||
| await run(); | ||
|
|
||
| const archivePath = path.join("/foo/bar", "cache.tgz"); | ||
|
|
||
| const IS_WINDOWS = process.platform === "win32"; | ||
| const args = IS_WINDOWS | ||
| ? [ | ||
| "-cz", | ||
| "--force-local", | ||
| "-f", | ||
| archivePath.replace(/\\/g, "/"), | ||
| "-C", | ||
| cachePath.replace(/\\/g, "/"), | ||
| "." | ||
| ] | ||
| : ["-cz", "-f", archivePath, "-C", cachePath, "."]; | ||
|
|
||
| expect(execMock).toHaveBeenCalledTimes(1); | ||
| expect(execMock).toHaveBeenCalledWith(`"tar"`, args); | ||
|
|
||
| expect(saveCacheMock).toHaveBeenCalledTimes(1); | ||
| expect(saveCacheMock).toHaveBeenCalledWith(primaryKey, archivePath); | ||
|
|
||
| expect(warningMock).toHaveBeenCalledTimes(0); | ||
| expect(failedMock).toHaveBeenCalledTimes(0); | ||
| }); |
Oops, something went wrong.