2019-11-06 21:41:45 +03:00
import * as core from "@actions/core" ;
import * as path from "path" ;
import * as cacheHttpClient from "../src/cacheHttpClient" ;
2019-11-13 18:54:39 +03:00
import { Events , Inputs } from "../src/constants" ;
2019-11-06 21:41:45 +03:00
import { ArtifactCacheEntry } from "../src/contracts" ;
import run from "../src/restore" ;
2019-12-14 01:24:37 +03:00
import * as tar from "../src/tar" ;
2019-11-06 21:41:45 +03:00
import * as actionUtils from "../src/utils/actionUtils" ;
import * as testUtils from "../src/utils/testUtils" ;
jest . mock ( "../src/cacheHttpClient" ) ;
2019-12-14 01:24:37 +03:00
jest . mock ( "../src/tar" ) ;
jest . mock ( "../src/utils/actionUtils" ) ;
2019-11-06 21:41:45 +03:00
beforeAll ( ( ) = > {
jest . spyOn ( actionUtils , "resolvePath" ) . mockImplementation ( filePath = > {
return path . resolve ( filePath ) ;
} ) ;
jest . spyOn ( actionUtils , "isExactKeyMatch" ) . mockImplementation (
( key , cacheResult ) = > {
const actualUtils = jest . requireActual ( "../src/utils/actionUtils" ) ;
return actualUtils . isExactKeyMatch ( key , cacheResult ) ;
}
) ;
2019-11-13 18:54:39 +03:00
jest . spyOn ( actionUtils , "isValidEvent" ) . mockImplementation ( ( ) = > {
const actualUtils = jest . requireActual ( "../src/utils/actionUtils" ) ;
return actualUtils . isValidEvent ( ) ;
} ) ;
jest . spyOn ( actionUtils , "getSupportedEvents" ) . mockImplementation ( ( ) = > {
const actualUtils = jest . requireActual ( "../src/utils/actionUtils" ) ;
return actualUtils . getSupportedEvents ( ) ;
} ) ;
2019-11-06 21:41:45 +03:00
} ) ;
2019-11-13 18:54:39 +03:00
beforeEach ( ( ) = > {
process . env [ Events . Key ] = Events . Push ;
} ) ;
2019-11-06 21:41:45 +03:00
afterEach ( ( ) = > {
testUtils . clearInputs ( ) ;
2019-11-13 18:54:39 +03:00
delete process . env [ Events . Key ] ;
} ) ;
2019-11-21 22:37:54 +03:00
test ( "restore with invalid event outputs warning" , async ( ) = > {
const logWarningMock = jest . spyOn ( actionUtils , "logWarning" ) ;
2019-11-13 18:54:39 +03:00
const failedMock = jest . spyOn ( core , "setFailed" ) ;
const invalidEvent = "commit_comment" ;
process . env [ Events . Key ] = invalidEvent ;
await run ( ) ;
2019-11-21 22:37:54 +03:00
expect ( logWarningMock ) . toHaveBeenCalledWith (
2019-11-13 18:54:39 +03:00
` Event Validation Error: The event type ${ invalidEvent } is not supported. Only push, pull_request events are supported at this time. `
) ;
2019-11-21 22:37:54 +03:00
expect ( failedMock ) . toHaveBeenCalledTimes ( 0 ) ;
2019-11-06 21:41:45 +03:00
} ) ;
test ( "restore with no path should fail" , async ( ) = > {
const failedMock = jest . spyOn ( core , "setFailed" ) ;
await run ( ) ;
expect ( failedMock ) . toHaveBeenCalledWith (
"Input required and not supplied: path"
) ;
} ) ;
test ( "restore with no key" , async ( ) = > {
testUtils . setInput ( Inputs . Path , "node_modules" ) ;
const failedMock = jest . spyOn ( core , "setFailed" ) ;
await run ( ) ;
expect ( failedMock ) . toHaveBeenCalledWith (
"Input required and not supplied: key"
) ;
} ) ;
test ( "restore with too many keys should fail" , async ( ) = > {
const key = "node-test" ;
const restoreKeys = [ . . . Array ( 20 ) . keys ( ) ] . map ( x = > x . toString ( ) ) ;
testUtils . setInputs ( {
path : "node_modules" ,
key ,
restoreKeys
} ) ;
const failedMock = jest . spyOn ( core , "setFailed" ) ;
await run ( ) ;
expect ( failedMock ) . toHaveBeenCalledWith (
` Key Validation Error: Keys are limited to a maximum of 10. `
) ;
} ) ;
test ( "restore with large key should fail" , async ( ) = > {
const key = "foo" . repeat ( 512 ) ; // Over the 512 character limit
testUtils . setInputs ( {
path : "node_modules" ,
key
} ) ;
const failedMock = jest . spyOn ( core , "setFailed" ) ;
await run ( ) ;
expect ( failedMock ) . toHaveBeenCalledWith (
` Key Validation Error: ${ key } cannot be larger than 512 characters. `
) ;
} ) ;
test ( "restore with invalid key should fail" , async ( ) = > {
const key = "comma,comma" ;
testUtils . setInputs ( {
path : "node_modules" ,
key
} ) ;
const failedMock = jest . spyOn ( core , "setFailed" ) ;
await run ( ) ;
expect ( failedMock ) . toHaveBeenCalledWith (
` Key Validation Error: ${ key } cannot contain commas. `
) ;
} ) ;
test ( "restore with no cache found" , async ( ) = > {
const key = "node-test" ;
testUtils . setInputs ( {
path : "node_modules" ,
key
} ) ;
const infoMock = jest . spyOn ( core , "info" ) ;
const failedMock = jest . spyOn ( core , "setFailed" ) ;
const stateMock = jest . spyOn ( core , "saveState" ) ;
const clientMock = jest . spyOn ( cacheHttpClient , "getCacheEntry" ) ;
2019-11-13 00:48:02 +03:00
clientMock . mockImplementation ( ( ) = > {
2019-11-06 21:41:45 +03:00
return Promise . resolve ( null ) ;
} ) ;
await run ( ) ;
expect ( stateMock ) . toHaveBeenCalledWith ( "CACHE_KEY" , key ) ;
expect ( failedMock ) . toHaveBeenCalledTimes ( 0 ) ;
expect ( infoMock ) . toHaveBeenCalledWith (
` Cache not found for input keys: ${ key } . `
) ;
} ) ;
test ( "restore with server error should fail" , async ( ) = > {
const key = "node-test" ;
testUtils . setInputs ( {
path : "node_modules" ,
key
} ) ;
2019-11-21 22:37:54 +03:00
const logWarningMock = jest . spyOn ( actionUtils , "logWarning" ) ;
2019-11-06 21:41:45 +03:00
const failedMock = jest . spyOn ( core , "setFailed" ) ;
const stateMock = jest . spyOn ( core , "saveState" ) ;
const clientMock = jest . spyOn ( cacheHttpClient , "getCacheEntry" ) ;
2019-11-13 00:48:02 +03:00
clientMock . mockImplementation ( ( ) = > {
2019-11-06 21:41:45 +03:00
throw new Error ( "HTTP Error Occurred" ) ;
} ) ;
const setCacheHitOutputMock = jest . spyOn ( actionUtils , "setCacheHitOutput" ) ;
await run ( ) ;
expect ( stateMock ) . toHaveBeenCalledWith ( "CACHE_KEY" , key ) ;
2019-11-21 22:37:54 +03:00
expect ( logWarningMock ) . toHaveBeenCalledTimes ( 1 ) ;
expect ( logWarningMock ) . toHaveBeenCalledWith ( "HTTP Error Occurred" ) ;
2019-11-06 21:41:45 +03:00
expect ( setCacheHitOutputMock ) . toHaveBeenCalledTimes ( 1 ) ;
expect ( setCacheHitOutputMock ) . toHaveBeenCalledWith ( false ) ;
expect ( failedMock ) . toHaveBeenCalledTimes ( 0 ) ;
} ) ;
test ( "restore with restore keys and no cache found" , async ( ) = > {
const key = "node-test" ;
const restoreKey = "node-" ;
testUtils . setInputs ( {
path : "node_modules" ,
key ,
restoreKeys : [ restoreKey ]
} ) ;
const infoMock = jest . spyOn ( core , "info" ) ;
const failedMock = jest . spyOn ( core , "setFailed" ) ;
const stateMock = jest . spyOn ( core , "saveState" ) ;
const clientMock = jest . spyOn ( cacheHttpClient , "getCacheEntry" ) ;
2019-11-13 00:48:02 +03:00
clientMock . mockImplementation ( ( ) = > {
2019-11-06 21:41:45 +03:00
return Promise . resolve ( null ) ;
} ) ;
await run ( ) ;
expect ( stateMock ) . toHaveBeenCalledWith ( "CACHE_KEY" , key ) ;
expect ( failedMock ) . toHaveBeenCalledTimes ( 0 ) ;
expect ( infoMock ) . toHaveBeenCalledWith (
` Cache not found for input keys: ${ key } , ${ restoreKey } . `
) ;
} ) ;
test ( "restore with cache found" , async ( ) = > {
const key = "node-test" ;
const cachePath = path . resolve ( "node_modules" ) ;
testUtils . setInputs ( {
path : "node_modules" ,
key
} ) ;
const infoMock = jest . spyOn ( core , "info" ) ;
const failedMock = jest . spyOn ( core , "setFailed" ) ;
const stateMock = jest . spyOn ( core , "saveState" ) ;
const cacheEntry : ArtifactCacheEntry = {
cacheKey : key ,
scope : "refs/heads/master" ,
archiveLocation : "www.actionscache.test/download"
} ;
const getCacheMock = jest . spyOn ( cacheHttpClient , "getCacheEntry" ) ;
2019-11-13 00:48:02 +03:00
getCacheMock . mockImplementation ( ( ) = > {
2019-11-06 21:41:45 +03:00
return Promise . resolve ( cacheEntry ) ;
} ) ;
const tempPath = "/foo/bar" ;
const createTempDirectoryMock = jest . spyOn (
actionUtils ,
"createTempDirectory"
) ;
createTempDirectoryMock . mockImplementation ( ( ) = > {
return Promise . resolve ( tempPath ) ;
} ) ;
const archivePath = path . join ( tempPath , "cache.tgz" ) ;
const setCacheStateMock = jest . spyOn ( actionUtils , "setCacheState" ) ;
const downloadCacheMock = jest . spyOn ( cacheHttpClient , "downloadCache" ) ;
const fileSize = 142 ;
const getArchiveFileSizeMock = jest
. spyOn ( actionUtils , "getArchiveFileSize" )
. mockReturnValue ( fileSize ) ;
2019-12-14 01:24:37 +03:00
const extractTarMock = jest . spyOn ( tar , "extractTar" ) ;
2019-11-06 21:41:45 +03:00
const setCacheHitOutputMock = jest . spyOn ( actionUtils , "setCacheHitOutput" ) ;
await run ( ) ;
expect ( stateMock ) . toHaveBeenCalledWith ( "CACHE_KEY" , key ) ;
2019-11-13 18:54:39 +03:00
expect ( getCacheMock ) . toHaveBeenCalledWith ( [ key ] ) ;
expect ( setCacheStateMock ) . toHaveBeenCalledWith ( cacheEntry ) ;
expect ( createTempDirectoryMock ) . toHaveBeenCalledTimes ( 1 ) ;
2020-01-06 21:05:50 +03:00
expect ( downloadCacheMock ) . toHaveBeenCalledWith (
cacheEntry . archiveLocation ,
archivePath
) ;
2019-11-13 18:54:39 +03:00
expect ( getArchiveFileSizeMock ) . toHaveBeenCalledWith ( archivePath ) ;
2019-12-14 01:24:37 +03:00
expect ( extractTarMock ) . toHaveBeenCalledTimes ( 1 ) ;
expect ( extractTarMock ) . toHaveBeenCalledWith ( archivePath , cachePath ) ;
2019-11-13 18:54:39 +03:00
expect ( setCacheHitOutputMock ) . toHaveBeenCalledTimes ( 1 ) ;
expect ( setCacheHitOutputMock ) . toHaveBeenCalledWith ( true ) ;
expect ( infoMock ) . toHaveBeenCalledWith ( ` Cache restored from key: ${ key } ` ) ;
expect ( failedMock ) . toHaveBeenCalledTimes ( 0 ) ;
} ) ;
test ( "restore with a pull request event and cache found" , async ( ) = > {
const key = "node-test" ;
const cachePath = path . resolve ( "node_modules" ) ;
testUtils . setInputs ( {
path : "node_modules" ,
key
} ) ;
process . env [ Events . Key ] = Events . PullRequest ;
const infoMock = jest . spyOn ( core , "info" ) ;
const failedMock = jest . spyOn ( core , "setFailed" ) ;
const stateMock = jest . spyOn ( core , "saveState" ) ;
const cacheEntry : ArtifactCacheEntry = {
cacheKey : key ,
scope : "refs/heads/master" ,
2019-11-14 00:13:00 +03:00
archiveLocation : "www.actionscache.test/download"
2019-11-13 18:54:39 +03:00
} ;
const getCacheMock = jest . spyOn ( cacheHttpClient , "getCacheEntry" ) ;
getCacheMock . mockImplementation ( ( ) = > {
return Promise . resolve ( cacheEntry ) ;
} ) ;
const tempPath = "/foo/bar" ;
const createTempDirectoryMock = jest . spyOn (
actionUtils ,
"createTempDirectory"
) ;
createTempDirectoryMock . mockImplementation ( ( ) = > {
return Promise . resolve ( tempPath ) ;
} ) ;
const archivePath = path . join ( tempPath , "cache.tgz" ) ;
const setCacheStateMock = jest . spyOn ( actionUtils , "setCacheState" ) ;
const downloadCacheMock = jest . spyOn ( cacheHttpClient , "downloadCache" ) ;
2019-11-13 19:00:46 +03:00
const fileSize = 62915000 ;
2019-11-13 18:54:39 +03:00
const getArchiveFileSizeMock = jest
. spyOn ( actionUtils , "getArchiveFileSize" )
. mockReturnValue ( fileSize ) ;
2019-12-14 01:24:37 +03:00
const extractTarMock = jest . spyOn ( tar , "extractTar" ) ;
2019-11-13 18:54:39 +03:00
const setCacheHitOutputMock = jest . spyOn ( actionUtils , "setCacheHitOutput" ) ;
await run ( ) ;
expect ( stateMock ) . toHaveBeenCalledWith ( "CACHE_KEY" , key ) ;
2019-11-06 21:41:45 +03:00
expect ( getCacheMock ) . toHaveBeenCalledWith ( [ key ] ) ;
expect ( setCacheStateMock ) . toHaveBeenCalledWith ( cacheEntry ) ;
expect ( createTempDirectoryMock ) . toHaveBeenCalledTimes ( 1 ) ;
2020-01-06 21:05:50 +03:00
expect ( downloadCacheMock ) . toHaveBeenCalledWith (
cacheEntry . archiveLocation ,
archivePath
) ;
2019-11-06 21:41:45 +03:00
expect ( getArchiveFileSizeMock ) . toHaveBeenCalledWith ( archivePath ) ;
2019-11-13 19:00:46 +03:00
expect ( infoMock ) . toHaveBeenCalledWith ( ` Cache Size: ~60 MB (62915000 B) ` ) ;
2019-12-14 01:24:37 +03:00
expect ( extractTarMock ) . toHaveBeenCalledTimes ( 1 ) ;
expect ( extractTarMock ) . toHaveBeenCalledWith ( archivePath , cachePath ) ;
2019-11-06 21:41:45 +03:00
expect ( setCacheHitOutputMock ) . toHaveBeenCalledTimes ( 1 ) ;
expect ( setCacheHitOutputMock ) . toHaveBeenCalledWith ( true ) ;
expect ( infoMock ) . toHaveBeenCalledWith ( ` Cache restored from key: ${ key } ` ) ;
expect ( failedMock ) . toHaveBeenCalledTimes ( 0 ) ;
} ) ;
test ( "restore with cache found for restore key" , async ( ) = > {
const key = "node-test" ;
const restoreKey = "node-" ;
const cachePath = path . resolve ( "node_modules" ) ;
testUtils . setInputs ( {
path : "node_modules" ,
key ,
restoreKeys : [ restoreKey ]
} ) ;
const infoMock = jest . spyOn ( core , "info" ) ;
const failedMock = jest . spyOn ( core , "setFailed" ) ;
const stateMock = jest . spyOn ( core , "saveState" ) ;
const cacheEntry : ArtifactCacheEntry = {
cacheKey : restoreKey ,
scope : "refs/heads/master" ,
archiveLocation : "www.actionscache.test/download"
} ;
const getCacheMock = jest . spyOn ( cacheHttpClient , "getCacheEntry" ) ;
2019-11-13 00:48:02 +03:00
getCacheMock . mockImplementation ( ( ) = > {
2019-11-06 21:41:45 +03:00
return Promise . resolve ( cacheEntry ) ;
} ) ;
const tempPath = "/foo/bar" ;
const createTempDirectoryMock = jest . spyOn (
actionUtils ,
"createTempDirectory"
) ;
createTempDirectoryMock . mockImplementation ( ( ) = > {
return Promise . resolve ( tempPath ) ;
} ) ;
const archivePath = path . join ( tempPath , "cache.tgz" ) ;
const setCacheStateMock = jest . spyOn ( actionUtils , "setCacheState" ) ;
const downloadCacheMock = jest . spyOn ( cacheHttpClient , "downloadCache" ) ;
const fileSize = 142 ;
const getArchiveFileSizeMock = jest
. spyOn ( actionUtils , "getArchiveFileSize" )
. mockReturnValue ( fileSize ) ;
2019-12-14 01:24:37 +03:00
const extractTarMock = jest . spyOn ( tar , "extractTar" ) ;
2019-11-06 21:41:45 +03:00
const setCacheHitOutputMock = jest . spyOn ( actionUtils , "setCacheHitOutput" ) ;
await run ( ) ;
expect ( stateMock ) . toHaveBeenCalledWith ( "CACHE_KEY" , key ) ;
expect ( getCacheMock ) . toHaveBeenCalledWith ( [ key , restoreKey ] ) ;
expect ( setCacheStateMock ) . toHaveBeenCalledWith ( cacheEntry ) ;
expect ( createTempDirectoryMock ) . toHaveBeenCalledTimes ( 1 ) ;
2020-01-06 21:05:50 +03:00
expect ( downloadCacheMock ) . toHaveBeenCalledWith (
cacheEntry . archiveLocation ,
archivePath
) ;
2019-11-06 21:41:45 +03:00
expect ( getArchiveFileSizeMock ) . toHaveBeenCalledWith ( archivePath ) ;
2019-11-13 19:00:46 +03:00
expect ( infoMock ) . toHaveBeenCalledWith ( ` Cache Size: ~0 MB (142 B) ` ) ;
2019-12-14 01:24:37 +03:00
expect ( extractTarMock ) . toHaveBeenCalledTimes ( 1 ) ;
expect ( extractTarMock ) . toHaveBeenCalledWith ( archivePath , cachePath ) ;
2019-11-06 21:41:45 +03:00
expect ( setCacheHitOutputMock ) . toHaveBeenCalledTimes ( 1 ) ;
expect ( setCacheHitOutputMock ) . toHaveBeenCalledWith ( false ) ;
expect ( infoMock ) . toHaveBeenCalledWith (
` Cache restored from key: ${ restoreKey } `
) ;
expect ( failedMock ) . toHaveBeenCalledTimes ( 0 ) ;
} ) ;