mirror of
https://github.com/actions/setup-python.git
synced 2024-12-26 17:40:36 +01:00
253 lines
8.3 KiB
TypeScript
253 lines
8.3 KiB
TypeScript
import * as core from '@actions/core';
|
|
import * as cache from '@actions/cache';
|
|
import * as exec from '@actions/exec';
|
|
import * as io from '@actions/io';
|
|
import {getCacheDistributor} from '../src/cache-distributions/cache-factory';
|
|
import * as utils from './../src/utils';
|
|
|
|
describe('restore-cache', () => {
|
|
const pipFileLockHash =
|
|
'a3bdcc71289e4979ca9e051810d81999cc99823109faf6912e17ff14c8e621a6';
|
|
const requirementsHash =
|
|
'd8110e0006d7fb5ee76365d565eef9d37df1d11598b912d3eb66d398d57a1121';
|
|
const requirementsLinuxHash =
|
|
'2d0ff7f46b0e120e3d3294db65768b474934242637b9899b873e6283dfd16d7c';
|
|
const poetryLockHash =
|
|
'571bf984f8d210e6a97f854e479fdd4a2b5af67b5fdac109ec337a0ea16e7836';
|
|
const poetryConfigOutput = `
|
|
cache-dir = "/Users/patrick/Library/Caches/pypoetry"
|
|
experimental.new-installer = false
|
|
installer.parallel = true
|
|
virtualenvs.create = true
|
|
virtualenvs.in-project = true
|
|
virtualenvs.path = "{cache-dir}/virtualenvs" # /Users/patrick/Library/Caches/pypoetry/virtualenvs
|
|
`;
|
|
|
|
// core spy
|
|
let infoSpy: jest.SpyInstance;
|
|
let warningSpy: jest.SpyInstance;
|
|
let debugSpy: jest.SpyInstance;
|
|
let saveSatetSpy: jest.SpyInstance;
|
|
let getStateSpy: jest.SpyInstance;
|
|
let setOutputSpy: jest.SpyInstance;
|
|
let getLinuxOSReleaseInfoSpy: jest.SpyInstance;
|
|
|
|
// cache spy
|
|
let restoreCacheSpy: jest.SpyInstance;
|
|
|
|
// exec spy
|
|
let getExecOutputSpy: jest.SpyInstance;
|
|
|
|
// io spy
|
|
let whichSpy: jest.SpyInstance;
|
|
|
|
beforeEach(() => {
|
|
process.env['RUNNER_OS'] = process.env['RUNNER_OS'] ?? 'linux';
|
|
|
|
infoSpy = jest.spyOn(core, 'info');
|
|
infoSpy.mockImplementation(input => undefined);
|
|
|
|
warningSpy = jest.spyOn(core, 'warning');
|
|
warningSpy.mockImplementation(input => undefined);
|
|
|
|
debugSpy = jest.spyOn(core, 'debug');
|
|
debugSpy.mockImplementation(input => undefined);
|
|
|
|
saveSatetSpy = jest.spyOn(core, 'saveState');
|
|
saveSatetSpy.mockImplementation(input => undefined);
|
|
|
|
getStateSpy = jest.spyOn(core, 'getState');
|
|
getStateSpy.mockImplementation(input => undefined);
|
|
|
|
getExecOutputSpy = jest.spyOn(exec, 'getExecOutput');
|
|
getExecOutputSpy.mockImplementation((input: string) => {
|
|
if (input.includes('pip')) {
|
|
return {stdout: 'pip', stderr: '', exitCode: 0};
|
|
}
|
|
if (input.includes('poetry')) {
|
|
return {stdout: poetryConfigOutput, stderr: '', exitCode: 0};
|
|
}
|
|
|
|
return {stdout: '', stderr: 'Error occured', exitCode: 2};
|
|
});
|
|
|
|
setOutputSpy = jest.spyOn(core, 'setOutput');
|
|
setOutputSpy.mockImplementation(input => undefined);
|
|
|
|
restoreCacheSpy = jest.spyOn(cache, 'restoreCache');
|
|
restoreCacheSpy.mockImplementation(
|
|
(cachePaths: string[], primaryKey: string, restoreKey?: string) => {
|
|
return primaryKey;
|
|
}
|
|
);
|
|
|
|
whichSpy = jest.spyOn(io, 'which');
|
|
whichSpy.mockImplementation(() => '/path/to/python');
|
|
getLinuxOSReleaseInfoSpy = jest.spyOn(utils, 'getLinuxOSReleaseInfo');
|
|
});
|
|
|
|
describe('Validate provided package manager', () => {
|
|
it.each(['npm', 'pip2', 'pip21', 'pip21.3', 'pipenv32'])(
|
|
'Throw an error because %s is not supported',
|
|
async packageManager => {
|
|
expect(() =>
|
|
getCacheDistributor(packageManager, '3.8.12', undefined)
|
|
).toThrowError(`Caching for '${packageManager}' is not supported`);
|
|
}
|
|
);
|
|
});
|
|
|
|
describe('Restore dependencies', () => {
|
|
it.each([
|
|
['pip', '3.8.12', undefined, requirementsHash],
|
|
['pip', '3.8.12', '**/requirements-linux.txt', requirementsLinuxHash],
|
|
[
|
|
'pip',
|
|
'3.8.12',
|
|
'__tests__/data/requirements-linux.txt',
|
|
requirementsLinuxHash
|
|
],
|
|
['pip', '3.8.12', '__tests__/data/requirements.txt', requirementsHash],
|
|
['pipenv', '3.9.1', undefined, pipFileLockHash],
|
|
['pipenv', '3.9.12', '__tests__/data/requirements.txt', requirementsHash],
|
|
['poetry', '3.9.1', undefined, poetryLockHash]
|
|
])(
|
|
'restored dependencies for %s by primaryKey',
|
|
async (packageManager, pythonVersion, dependencyFile, fileHash) => {
|
|
const cacheDistributor = getCacheDistributor(
|
|
packageManager,
|
|
pythonVersion,
|
|
dependencyFile
|
|
);
|
|
|
|
if (process.platform === 'linux') {
|
|
getLinuxOSReleaseInfoSpy.mockImplementation(() =>
|
|
Promise.resolve('Ubuntu-20.4')
|
|
);
|
|
}
|
|
|
|
await cacheDistributor.restoreCache();
|
|
|
|
if (process.platform === 'linux' && packageManager === 'pip') {
|
|
expect(infoSpy).toHaveBeenCalledWith(
|
|
`Cache restored from key: setup-python-${process.env['RUNNER_OS']}-Ubuntu-20.4-python-${pythonVersion}-${packageManager}-${fileHash}`
|
|
);
|
|
} else {
|
|
expect(infoSpy).toHaveBeenCalledWith(
|
|
`Cache restored from key: setup-python-${process.env['RUNNER_OS']}-python-${pythonVersion}-${packageManager}-${fileHash}`
|
|
);
|
|
}
|
|
},
|
|
30000
|
|
);
|
|
|
|
it.each([
|
|
['pip', '3.8.12', 'requirements-linux.txt', 'requirements-linux.txt'],
|
|
['pip', '3.8.12', 'requirements.txt', 'requirements.txt'],
|
|
['pipenv', '3.9.12', 'requirements.txt', 'requirements.txt']
|
|
])(
|
|
'Should throw an error because dependency file is not found',
|
|
async (
|
|
packageManager,
|
|
pythonVersion,
|
|
dependencyFile,
|
|
cacheDependencyPath
|
|
) => {
|
|
const cacheDistributor = getCacheDistributor(
|
|
packageManager,
|
|
pythonVersion,
|
|
dependencyFile
|
|
);
|
|
await expect(cacheDistributor.restoreCache()).rejects.toThrowError(
|
|
`No file in ${process.cwd()} matched to [${cacheDependencyPath
|
|
.split('\n')
|
|
.join(',')}], make sure you have checked out the target repository`
|
|
);
|
|
}
|
|
);
|
|
});
|
|
|
|
describe('Dependencies changed', () => {
|
|
it.each([
|
|
['pip', '3.8.12', undefined, pipFileLockHash],
|
|
['pip', '3.8.12', '**/requirements-linux.txt', pipFileLockHash],
|
|
[
|
|
'pip',
|
|
'3.8.12',
|
|
'__tests__/data/requirements-linux.txt',
|
|
pipFileLockHash
|
|
],
|
|
['pip', '3.8.12', '__tests__/data/requirements.txt', pipFileLockHash],
|
|
['pipenv', '3.9.1', undefined, requirementsHash],
|
|
['pipenv', '3.9.12', '__tests__/data/requirements.txt', requirementsHash],
|
|
['poetry', '3.9.1', undefined, requirementsHash]
|
|
])(
|
|
'restored dependencies for %s by primaryKey',
|
|
async (packageManager, pythonVersion, dependencyFile, fileHash) => {
|
|
restoreCacheSpy.mockImplementation(
|
|
(cachePaths: string[], primaryKey: string, restoreKey?: string) => {
|
|
return primaryKey !== fileHash && restoreKey ? pipFileLockHash : '';
|
|
}
|
|
);
|
|
const cacheDistributor = getCacheDistributor(
|
|
packageManager,
|
|
pythonVersion,
|
|
dependencyFile
|
|
);
|
|
await cacheDistributor.restoreCache();
|
|
let result = '';
|
|
|
|
switch (packageManager) {
|
|
case 'pip':
|
|
result = `Cache restored from key: ${fileHash}`;
|
|
break;
|
|
case 'pipenv':
|
|
result = 'pipenv cache is not found';
|
|
break;
|
|
case 'poetry':
|
|
result = 'poetry cache is not found';
|
|
break;
|
|
}
|
|
|
|
expect(infoSpy).toHaveBeenCalledWith(result);
|
|
}
|
|
);
|
|
});
|
|
|
|
describe('Check if handleMatchResult', () => {
|
|
it.each([
|
|
['pip', '3.8.12', 'requirements.txt', 'someKey', 'someKey', true],
|
|
['pipenv', '3.9.1', 'requirements.txt', 'someKey', 'someKey', true],
|
|
['poetry', '3.8.12', 'requirements.txt', 'someKey', 'someKey', true],
|
|
['pip', '3.9.2', 'requirements.txt', undefined, 'someKey', false],
|
|
['pipenv', '3.8.12', 'requirements.txt', undefined, 'someKey', false],
|
|
['poetry', '3.9.12', 'requirements.txt', undefined, 'someKey', false]
|
|
])(
|
|
'sets correct outputs',
|
|
async (
|
|
packageManager,
|
|
pythonVersion,
|
|
dependencyFile,
|
|
matchedKey,
|
|
restoredKey,
|
|
expectedOutputValue
|
|
) => {
|
|
const cacheDistributor = getCacheDistributor(
|
|
packageManager,
|
|
pythonVersion,
|
|
dependencyFile
|
|
);
|
|
cacheDistributor.handleMatchResult(matchedKey, restoredKey);
|
|
expect(setOutputSpy).toHaveBeenCalledWith(
|
|
'cache-hit',
|
|
expectedOutputValue
|
|
);
|
|
}
|
|
);
|
|
});
|
|
|
|
afterEach(() => {
|
|
jest.resetAllMocks();
|
|
jest.clearAllMocks();
|
|
});
|
|
});
|