import fs from 'fs'; import {HttpClient} from '@actions/http-client'; import * as ifm from '@actions/http-client/lib/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-graalpy'; import { IGraalPyManifestRelease, IGraalPyManifestAsset, IS_WINDOWS } from '../src/utils'; import manifestData from './data/graalpy.json'; const architecture = 'x64'; const toolDir = path.join(__dirname, 'runner', 'tools'); const tempDir = path.join(__dirname, 'runner', 'temp'); describe('graalpyVersionToSemantic', () => { it.each([ ['graalpy-24.1.0-ea.09', '24.1.0-ea.9'], ['graal-23.0.0', '23.0.0'], ['vm-23.0.x', '23.0.x'], ['graal-23.x', '23.x'] ])('%s -> %s', (input, expected) => { expect(installer.graalPyTagToVersion(input)).toEqual(expected); }); }); describe('findRelease', () => { const result = JSON.stringify(manifestData); const releases = JSON.parse(result) as IGraalPyManifestRelease[]; const extension = IS_WINDOWS ? 'zip' : 'tar.gz'; const arch = installer.toGraalPyArchitecture(architecture); const platform = installer.toGraalPyPlatform(process.platform); const extensionName = `${platform}-${arch}.${extension}`; const files: IGraalPyManifestAsset = { name: `graalpython-23.0.0-${extensionName}`, browser_download_url: `https://github.com/oracle/graalpython/releases/download/graal-23.0.0/graalpython-23.0.0-${extensionName}` }; const filesRC1: IGraalPyManifestAsset = { name: `graalpy-24.1.0-ea.09-${extensionName}`, browser_download_url: `https://github.com/graalvm/graal-languages-ea-builds/releases/download/graalpy-24.1.0-ea.09/graalpy-24.1.0-ea.09-${extensionName}` }; 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("GraalPy version doesn't match", () => { const graalpyVersion = '12.0.0'; expect( installer.findRelease(releases, graalpyVersion, architecture, false) ).toEqual(null); }); it('GraalPy version matches', () => { const graalpyVersion = '23.0.0'; expect( installer.findRelease(releases, graalpyVersion, architecture, false) ).toMatchObject({ foundAsset: files, resolvedGraalPyVersion: graalpyVersion }); }); it('Preview version of GraalPy is found', () => { const graalpyVersion = installer.graalPyTagToVersion('vm-24.1.0-ea.09'); expect( installer.findRelease(releases, graalpyVersion, architecture, false) ).toMatchObject({ foundAsset: { name: `graalpy-24.1.0-ea.09-${extensionName}`, browser_download_url: `https://github.com/graalvm/graal-languages-ea-builds/releases/download/graalpy-24.1.0-ea.09/graalpy-24.1.0-ea.09-${extensionName}` }, resolvedGraalPyVersion: '24.1.0-ea.9' }); }); it('Latest GraalPy is found', () => { const graalpyVersion = 'x'; expect( installer.findRelease(releases, graalpyVersion, architecture, false) ).toMatchObject({ foundAsset: files, resolvedGraalPyVersion: '23.0.0' }); }); it('GraalPy version matches semver (pre-release)', () => { const graalpyVersion = '24.1.x'; expect( installer.findRelease(releases, graalpyVersion, architecture, false) ).toBeNull(); expect( installer.findRelease(releases, graalpyVersion, architecture, true) ).toMatchObject({ foundAsset: filesRC1, resolvedGraalPyVersion: '24.1.0-ea.9' }); }); }); describe('installGraalPy', () => { let tcFind: 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('GraalPy', '3.6.12', architecture) ); spyDownloadTool = jest.spyOn(tc, 'downloadTool'); spyDownloadTool.mockImplementation(() => path.join(tempDir, 'GraalPy')); 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(() => ['GraalPyTest']); spyFsWriteFile = jest.spyOn(fs, 'writeFileSync'); spyFsWriteFile.mockImplementation(() => undefined); spyHttpClient = jest.spyOn(HttpClient.prototype, 'getJson'); spyHttpClient.mockImplementation( async (): Promise> => { const result = JSON.stringify(manifestData); return { statusCode: 200, headers: {}, result: JSON.parse(result) as IGraalPyManifestRelease[] }; } ); 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.installGraalPy('7.3.3', architecture, false, undefined) ).rejects.toThrow( `GraalPy version 7.3.3 with arch ${architecture} not found` ); expect(spyHttpClient).toHaveBeenCalled(); expect(spyDownloadTool).not.toHaveBeenCalled(); expect(spyExec).not.toHaveBeenCalled(); }); it('found and install GraalPy', async () => { spyCacheDir = jest.spyOn(tc, 'cacheDir'); spyCacheDir.mockImplementation(() => path.join(toolDir, 'GraalPy', '21.3.0', architecture) ); spyChmodSync = jest.spyOn(fs, 'chmodSync'); spyChmodSync.mockImplementation(() => undefined); await expect( installer.installGraalPy('21.x', architecture, false, undefined) ).resolves.toEqual({ installDir: path.join(toolDir, 'GraalPy', '21.3.0', architecture), resolvedGraalPyVersion: '21.3.0' }); expect(spyHttpClient).toHaveBeenCalled(); expect(spyDownloadTool).toHaveBeenCalled(); expect(spyCacheDir).toHaveBeenCalled(); expect(spyExec).toHaveBeenCalled(); }); it('found and install GraalPy, pre-release fallback', async () => { spyCacheDir = jest.spyOn(tc, 'cacheDir'); spyCacheDir.mockImplementation(() => path.join(toolDir, 'GraalPy', '24.1.0', architecture) ); spyChmodSync = jest.spyOn(fs, 'chmodSync'); spyChmodSync.mockImplementation(() => undefined); await expect( installer.installGraalPy('24.1.x', architecture, false, undefined) ).rejects.toThrow(); await expect( installer.installGraalPy('24.1.x', architecture, true, undefined) ).resolves.toEqual({ installDir: path.join(toolDir, 'GraalPy', '24.1.0', architecture), resolvedGraalPyVersion: '24.1.0-ea.9' }); expect(spyHttpClient).toHaveBeenCalled(); expect(spyDownloadTool).toHaveBeenCalled(); expect(spyCacheDir).toHaveBeenCalled(); expect(spyExec).toHaveBeenCalled(); }); });