mirror of
				https://kkgithub.com/actions/setup-python.git
				synced 2025-11-04 12:44:05 +08:00 
			
		
		
		
	* Add ESLint, update Prettier * Update docs * Update tests * Update licenses * Fix review points
		
			
				
	
	
		
			357 lines
		
	
	
		
			9.9 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
			
		
		
	
	
			357 lines
		
	
	
		
			9.9 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
import fs from 'fs';
 | 
						|
 | 
						|
import {HttpClient} from '@actions/http-client';
 | 
						|
import * as ifm from '@actions/http-client/interfaces';
 | 
						|
import * as tc from '@actions/tool-cache';
 | 
						|
import * as exec from '@actions/exec';
 | 
						|
import * as core from '@actions/core';
 | 
						|
import * as path from 'path';
 | 
						|
 | 
						|
import * as installer from '../src/install-pypy';
 | 
						|
import {
 | 
						|
  IPyPyManifestRelease,
 | 
						|
  IPyPyManifestAsset,
 | 
						|
  IS_WINDOWS
 | 
						|
} from '../src/utils';
 | 
						|
 | 
						|
import manifestData from './data/pypy.json';
 | 
						|
 | 
						|
let architecture: string;
 | 
						|
if (IS_WINDOWS) {
 | 
						|
  architecture = 'x86';
 | 
						|
} else {
 | 
						|
  architecture = 'x64';
 | 
						|
}
 | 
						|
 | 
						|
const toolDir = path.join(__dirname, 'runner', 'tools');
 | 
						|
const tempDir = path.join(__dirname, 'runner', 'temp');
 | 
						|
 | 
						|
describe('pypyVersionToSemantic', () => {
 | 
						|
  it.each([
 | 
						|
    ['7.3.3rc1', '7.3.3-rc.1'],
 | 
						|
    ['7.3.3', '7.3.3'],
 | 
						|
    ['7.3.x', '7.3.x'],
 | 
						|
    ['7.x', '7.x'],
 | 
						|
    ['nightly', 'nightly']
 | 
						|
  ])('%s -> %s', (input, expected) => {
 | 
						|
    expect(installer.pypyVersionToSemantic(input)).toEqual(expected);
 | 
						|
  });
 | 
						|
});
 | 
						|
 | 
						|
describe('findRelease', () => {
 | 
						|
  const result = JSON.stringify(manifestData);
 | 
						|
  const releases = JSON.parse(result) as IPyPyManifestRelease[];
 | 
						|
  const extension = IS_WINDOWS ? '.zip' : '.tar.bz2';
 | 
						|
  const extensionName = IS_WINDOWS
 | 
						|
    ? `${process.platform}${extension}`
 | 
						|
    : `${process.platform}64${extension}`;
 | 
						|
  const files: IPyPyManifestAsset = {
 | 
						|
    filename: `pypy3.6-v7.3.3-${extensionName}`,
 | 
						|
    arch: architecture,
 | 
						|
    platform: process.platform,
 | 
						|
    download_url: `https://test.download.python.org/pypy/pypy3.6-v7.3.3-${extensionName}`
 | 
						|
  };
 | 
						|
  const filesRC1: IPyPyManifestAsset = {
 | 
						|
    filename: `pypy3.6-v7.4.0rc1-${extensionName}`,
 | 
						|
    arch: architecture,
 | 
						|
    platform: process.platform,
 | 
						|
    download_url: `https://test.download.python.org/pypy/pypy3.6-v7.4.0rc1-${extensionName}`
 | 
						|
  };
 | 
						|
 | 
						|
  let getBooleanInputSpy: jest.SpyInstance;
 | 
						|
  let warningSpy: jest.SpyInstance;
 | 
						|
  let debugSpy: jest.SpyInstance;
 | 
						|
  let infoSpy: jest.SpyInstance;
 | 
						|
 | 
						|
  beforeEach(() => {
 | 
						|
    infoSpy = jest.spyOn(core, 'info');
 | 
						|
    infoSpy.mockImplementation(() => {});
 | 
						|
 | 
						|
    warningSpy = jest.spyOn(core, 'warning');
 | 
						|
    warningSpy.mockImplementation(() => null);
 | 
						|
 | 
						|
    debugSpy = jest.spyOn(core, 'debug');
 | 
						|
    debugSpy.mockImplementation(() => null);
 | 
						|
  });
 | 
						|
 | 
						|
  it("Python version is found, but PyPy version doesn't match", () => {
 | 
						|
    const pythonVersion = '3.6';
 | 
						|
    const pypyVersion = '7.3.7';
 | 
						|
    expect(
 | 
						|
      installer.findRelease(
 | 
						|
        releases,
 | 
						|
        pythonVersion,
 | 
						|
        pypyVersion,
 | 
						|
        architecture,
 | 
						|
        false
 | 
						|
      )
 | 
						|
    ).toEqual(null);
 | 
						|
  });
 | 
						|
 | 
						|
  it('Python version is found and PyPy version matches', () => {
 | 
						|
    const pythonVersion = '3.6';
 | 
						|
    const pypyVersion = '7.3.3';
 | 
						|
    expect(
 | 
						|
      installer.findRelease(
 | 
						|
        releases,
 | 
						|
        pythonVersion,
 | 
						|
        pypyVersion,
 | 
						|
        architecture,
 | 
						|
        false
 | 
						|
      )
 | 
						|
    ).toEqual({
 | 
						|
      foundAsset: files,
 | 
						|
      resolvedPythonVersion: '3.6.12',
 | 
						|
      resolvedPyPyVersion: pypyVersion
 | 
						|
    });
 | 
						|
  });
 | 
						|
 | 
						|
  it('Python version is found in toolcache and PyPy version matches semver', () => {
 | 
						|
    const pythonVersion = '3.6';
 | 
						|
    const pypyVersion = '7.x';
 | 
						|
    expect(
 | 
						|
      installer.findRelease(
 | 
						|
        releases,
 | 
						|
        pythonVersion,
 | 
						|
        pypyVersion,
 | 
						|
        architecture,
 | 
						|
        false
 | 
						|
      )
 | 
						|
    ).toEqual({
 | 
						|
      foundAsset: files,
 | 
						|
      resolvedPythonVersion: '3.6.12',
 | 
						|
      resolvedPyPyVersion: '7.3.3'
 | 
						|
    });
 | 
						|
  });
 | 
						|
 | 
						|
  it('Python and preview version of PyPy are found', () => {
 | 
						|
    const pythonVersion = '3.7';
 | 
						|
    const pypyVersion = installer.pypyVersionToSemantic('7.3.3rc2');
 | 
						|
    expect(
 | 
						|
      installer.findRelease(
 | 
						|
        releases,
 | 
						|
        pythonVersion,
 | 
						|
        pypyVersion,
 | 
						|
        architecture,
 | 
						|
        false
 | 
						|
      )
 | 
						|
    ).toEqual({
 | 
						|
      foundAsset: {
 | 
						|
        filename: `test${extension}`,
 | 
						|
        arch: architecture,
 | 
						|
        platform: process.platform,
 | 
						|
        download_url: `test${extension}`
 | 
						|
      },
 | 
						|
      resolvedPythonVersion: '3.7.7',
 | 
						|
      resolvedPyPyVersion: '7.3.3rc2'
 | 
						|
    });
 | 
						|
  });
 | 
						|
 | 
						|
  it('Python version with latest PyPy is found', () => {
 | 
						|
    const pythonVersion = '3.6';
 | 
						|
    const pypyVersion = 'x';
 | 
						|
    expect(
 | 
						|
      installer.findRelease(
 | 
						|
        releases,
 | 
						|
        pythonVersion,
 | 
						|
        pypyVersion,
 | 
						|
        architecture,
 | 
						|
        false
 | 
						|
      )
 | 
						|
    ).toEqual({
 | 
						|
      foundAsset: files,
 | 
						|
      resolvedPythonVersion: '3.6.12',
 | 
						|
      resolvedPyPyVersion: '7.3.3'
 | 
						|
    });
 | 
						|
  });
 | 
						|
 | 
						|
  it('Python version and PyPy version matches semver (pre-release)', () => {
 | 
						|
    const pythonVersion = '3.6';
 | 
						|
    const pypyVersion = '7.4.x';
 | 
						|
    expect(
 | 
						|
      installer.findRelease(
 | 
						|
        releases,
 | 
						|
        pythonVersion,
 | 
						|
        pypyVersion,
 | 
						|
        architecture,
 | 
						|
        false
 | 
						|
      )
 | 
						|
    ).toBeNull();
 | 
						|
    expect(
 | 
						|
      installer.findRelease(
 | 
						|
        releases,
 | 
						|
        pythonVersion,
 | 
						|
        pypyVersion,
 | 
						|
        architecture,
 | 
						|
        true
 | 
						|
      )
 | 
						|
    ).toEqual({
 | 
						|
      foundAsset: filesRC1,
 | 
						|
      resolvedPythonVersion: '3.6.12',
 | 
						|
      resolvedPyPyVersion: '7.4.0rc1'
 | 
						|
    });
 | 
						|
  });
 | 
						|
 | 
						|
  it('Nightly release is found', () => {
 | 
						|
    const pythonVersion = '3.6';
 | 
						|
    const pypyVersion = 'nightly';
 | 
						|
    const filename = IS_WINDOWS ? 'filename.zip' : 'filename.tar.bz2';
 | 
						|
    expect(
 | 
						|
      installer.findRelease(
 | 
						|
        releases,
 | 
						|
        pythonVersion,
 | 
						|
        pypyVersion,
 | 
						|
        architecture,
 | 
						|
        false
 | 
						|
      )
 | 
						|
    ).toEqual({
 | 
						|
      foundAsset: {
 | 
						|
        filename: filename,
 | 
						|
        arch: architecture,
 | 
						|
        platform: process.platform,
 | 
						|
        download_url: `http://nightlyBuilds.org/${filename}`
 | 
						|
      },
 | 
						|
      resolvedPythonVersion: '3.6',
 | 
						|
      resolvedPyPyVersion: pypyVersion
 | 
						|
    });
 | 
						|
  });
 | 
						|
});
 | 
						|
 | 
						|
describe('installPyPy', () => {
 | 
						|
  let tcFind: jest.SpyInstance;
 | 
						|
  let getBooleanInputSpy: jest.SpyInstance;
 | 
						|
  let warningSpy: jest.SpyInstance;
 | 
						|
  let debugSpy: jest.SpyInstance;
 | 
						|
  let infoSpy: jest.SpyInstance;
 | 
						|
  let spyExtractZip: jest.SpyInstance;
 | 
						|
  let spyExtractTar: jest.SpyInstance;
 | 
						|
  let spyFsReadDir: jest.SpyInstance;
 | 
						|
  let spyFsWriteFile: jest.SpyInstance;
 | 
						|
  let spyHttpClient: jest.SpyInstance;
 | 
						|
  let spyExistsSync: jest.SpyInstance;
 | 
						|
  let spyExec: jest.SpyInstance;
 | 
						|
  let spySymlinkSync: jest.SpyInstance;
 | 
						|
  let spyDownloadTool: jest.SpyInstance;
 | 
						|
  let spyCacheDir: jest.SpyInstance;
 | 
						|
  let spyChmodSync: jest.SpyInstance;
 | 
						|
 | 
						|
  beforeEach(() => {
 | 
						|
    tcFind = jest.spyOn(tc, 'find');
 | 
						|
    tcFind.mockImplementation(() => path.join('PyPy', '3.6.12', architecture));
 | 
						|
 | 
						|
    spyDownloadTool = jest.spyOn(tc, 'downloadTool');
 | 
						|
    spyDownloadTool.mockImplementation(() => path.join(tempDir, 'PyPy'));
 | 
						|
 | 
						|
    spyExtractZip = jest.spyOn(tc, 'extractZip');
 | 
						|
    spyExtractZip.mockImplementation(() => tempDir);
 | 
						|
 | 
						|
    spyExtractTar = jest.spyOn(tc, 'extractTar');
 | 
						|
    spyExtractTar.mockImplementation(() => tempDir);
 | 
						|
 | 
						|
    infoSpy = jest.spyOn(core, 'info');
 | 
						|
    infoSpy.mockImplementation(() => {});
 | 
						|
 | 
						|
    warningSpy = jest.spyOn(core, 'warning');
 | 
						|
    warningSpy.mockImplementation(() => null);
 | 
						|
 | 
						|
    debugSpy = jest.spyOn(core, 'debug');
 | 
						|
    debugSpy.mockImplementation(() => null);
 | 
						|
 | 
						|
    spyFsReadDir = jest.spyOn(fs, 'readdirSync');
 | 
						|
    spyFsReadDir.mockImplementation(() => ['PyPyTest']);
 | 
						|
 | 
						|
    spyFsWriteFile = jest.spyOn(fs, 'writeFileSync');
 | 
						|
    spyFsWriteFile.mockImplementation(() => undefined);
 | 
						|
 | 
						|
    spyHttpClient = jest.spyOn(HttpClient.prototype, 'getJson');
 | 
						|
    spyHttpClient.mockImplementation(
 | 
						|
      async (): Promise<ifm.ITypedResponse<IPyPyManifestRelease[]>> => {
 | 
						|
        const result = JSON.stringify(manifestData);
 | 
						|
        return {
 | 
						|
          statusCode: 200,
 | 
						|
          headers: {},
 | 
						|
          result: JSON.parse(result) as IPyPyManifestRelease[]
 | 
						|
        };
 | 
						|
      }
 | 
						|
    );
 | 
						|
 | 
						|
    spyExec = jest.spyOn(exec, 'exec');
 | 
						|
    spyExec.mockImplementation(() => undefined);
 | 
						|
 | 
						|
    spySymlinkSync = jest.spyOn(fs, 'symlinkSync');
 | 
						|
    spySymlinkSync.mockImplementation(() => undefined);
 | 
						|
 | 
						|
    spyExistsSync = jest.spyOn(fs, 'existsSync');
 | 
						|
    spyExistsSync.mockImplementation(() => false);
 | 
						|
  });
 | 
						|
 | 
						|
  afterEach(() => {
 | 
						|
    jest.resetAllMocks();
 | 
						|
    jest.clearAllMocks();
 | 
						|
    jest.restoreAllMocks();
 | 
						|
  });
 | 
						|
 | 
						|
  it('throw if release is not found', async () => {
 | 
						|
    await expect(
 | 
						|
      installer.installPyPy('7.3.3', '3.6.17', architecture, false, undefined)
 | 
						|
    ).rejects.toThrow(
 | 
						|
      `PyPy version 3.6.17 (7.3.3) with arch ${architecture} not found`
 | 
						|
    );
 | 
						|
 | 
						|
    expect(spyHttpClient).toHaveBeenCalled();
 | 
						|
    expect(spyDownloadTool).not.toHaveBeenCalled();
 | 
						|
    expect(spyExec).not.toHaveBeenCalled();
 | 
						|
  });
 | 
						|
 | 
						|
  it('found and install PyPy', async () => {
 | 
						|
    spyCacheDir = jest.spyOn(tc, 'cacheDir');
 | 
						|
    spyCacheDir.mockImplementation(() =>
 | 
						|
      path.join(toolDir, 'PyPy', '3.6.12', architecture)
 | 
						|
    );
 | 
						|
 | 
						|
    spyChmodSync = jest.spyOn(fs, 'chmodSync');
 | 
						|
    spyChmodSync.mockImplementation(() => undefined);
 | 
						|
 | 
						|
    await expect(
 | 
						|
      installer.installPyPy('7.x', '3.6.12', architecture, false, undefined)
 | 
						|
    ).resolves.toEqual({
 | 
						|
      installDir: path.join(toolDir, 'PyPy', '3.6.12', architecture),
 | 
						|
      resolvedPythonVersion: '3.6.12',
 | 
						|
      resolvedPyPyVersion: '7.3.3'
 | 
						|
    });
 | 
						|
 | 
						|
    expect(spyHttpClient).toHaveBeenCalled();
 | 
						|
    expect(spyDownloadTool).toHaveBeenCalled();
 | 
						|
    expect(spyExistsSync).toHaveBeenCalled();
 | 
						|
    expect(spyCacheDir).toHaveBeenCalled();
 | 
						|
    expect(spyExec).toHaveBeenCalled();
 | 
						|
  });
 | 
						|
 | 
						|
  it('found and install PyPy, pre-release fallback', async () => {
 | 
						|
    spyCacheDir = jest.spyOn(tc, 'cacheDir');
 | 
						|
    spyCacheDir.mockImplementation(() =>
 | 
						|
      path.join(toolDir, 'PyPy', '3.6.12', architecture)
 | 
						|
    );
 | 
						|
 | 
						|
    spyChmodSync = jest.spyOn(fs, 'chmodSync');
 | 
						|
    spyChmodSync.mockImplementation(() => undefined);
 | 
						|
 | 
						|
    await expect(
 | 
						|
      installer.installPyPy('7.4.x', '3.6.12', architecture, false, undefined)
 | 
						|
    ).rejects.toThrow();
 | 
						|
    await expect(
 | 
						|
      installer.installPyPy('7.4.x', '3.6.12', architecture, true, undefined)
 | 
						|
    ).resolves.toEqual({
 | 
						|
      installDir: path.join(toolDir, 'PyPy', '3.6.12', architecture),
 | 
						|
      resolvedPythonVersion: '3.6.12',
 | 
						|
      resolvedPyPyVersion: '7.4.0rc1'
 | 
						|
    });
 | 
						|
 | 
						|
    expect(spyHttpClient).toHaveBeenCalled();
 | 
						|
    expect(spyDownloadTool).toHaveBeenCalled();
 | 
						|
    expect(spyExistsSync).toHaveBeenCalled();
 | 
						|
    expect(spyCacheDir).toHaveBeenCalled();
 | 
						|
    expect(spyExec).toHaveBeenCalled();
 | 
						|
  });
 | 
						|
});
 |