Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
Browse the repository at this point in the history
Refactor and update unit-tests (#418)
* Update unit-tests and dotnet-install scripts
Ivan
authored and
GitHub
committed
May 15, 2023
Unverified
No user is associated with the committer email.
1 parent
fc8786b
commit 0f534f5
Showing
9 changed files
with
867 additions
and
641 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
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 |
---|---|---|
@@ -1,21 +1,45 @@ | ||
import cscFile from '../.github/csc.json'; | ||
describe('csc tests', () => { | ||
it('Valid regular expression', async () => { | ||
const regex = cscFile['problemMatcher'][0]['pattern'][0]['regexp']; | ||
test('regular expression in csc.json is valid', async () => { | ||
const regexPattern = cscFile['problemMatcher'][0]['pattern'][0]['regexp']; | ||
const regexResultsMap = cscFile['problemMatcher'][0]['pattern'][0]; | ||
|
||
console.log(regex); | ||
const re = new RegExp(regex); | ||
const regex = new RegExp(regexPattern); | ||
|
||
// Ideally we would verify that this | ||
const stringsToMatch = [ | ||
'Program.cs(10,79): error CS1002: ; expected [/Users/zacharyeisinger/Documents/repo/setup-dotnet/__tests__/sample-broken-csproj/sample.csproj]', | ||
"S:\\Msbuild\\src\\Build\\Evaluation\\ExpressionShredder.cs(33,7): error CS1003: Syntax error, ',' expected [S:\\msbuild\\src\\Build\\Microsoft.Build.csproj > Properties:prop]" | ||
]; | ||
// Expected results are calculated according to the csc matcher located in csc.json file | ||
const expectedResults = [ | ||
{ | ||
file: 'Program.cs', | ||
line: '10', | ||
severity: 'error', | ||
code: 'CS1002', | ||
message: '; expected', | ||
fromPath: | ||
'/Users/zacharyeisinger/Documents/repo/setup-dotnet/__tests__/sample-broken-csproj/sample.csproj' | ||
}, | ||
{ | ||
file: 'S:\\Msbuild\\src\\Build\\Evaluation\\ExpressionShredder.cs', | ||
line: '33', | ||
severity: 'error', | ||
code: 'CS1003', | ||
message: "Syntax error, ',' expected", | ||
fromPath: | ||
'S:\\msbuild\\src\\Build\\Microsoft.Build.csproj > Properties:prop' | ||
} | ||
]; | ||
|
||
stringsToMatch.forEach(string => { | ||
const matchStr = string.match(re); | ||
console.log(matchStr); | ||
expect(matchStr).toEqual(expect.anything()); | ||
stringsToMatch.map((string, index) => { | ||
const matchedResultsArray = string.match(regex); | ||
for (const propName in expectedResults[index]) { | ||
const propertyIndex = regexResultsMap[propName]; | ||
const expectedPropValue = expectedResults[index][propName]; | ||
const matchedPropValue = matchedResultsArray![propertyIndex]; | ||
expect(matchedPropValue).toEqual(expectedPropValue); | ||
} | ||
}); | ||
}, 10000); | ||
}); |
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,52 @@ | ||
import path from 'path'; | ||
import fs from 'fs'; | ||
import * as hc from '@actions/http-client'; | ||
|
||
describe('Dotnet installation scripts tests', () => { | ||
it('Uses an up to date bash download script', async () => { | ||
const httpCallbackClient = new hc.HttpClient('setup-dotnet-test', [], { | ||
allowRetries: true, | ||
maxRetries: 3 | ||
}); | ||
const response: hc.HttpClientResponse = await httpCallbackClient.get( | ||
'https://dot.net/v1/dotnet-install.sh' | ||
); | ||
expect(response.message.statusCode).toBe(200); | ||
const upToDateContents: string = await response.readBody(); | ||
const currentContents: string = fs | ||
.readFileSync( | ||
path.join(__dirname, '..', 'externals', 'install-dotnet.sh') | ||
) | ||
.toString(); | ||
expect(normalizeFileContents(currentContents)).toBe( | ||
normalizeFileContents(upToDateContents) | ||
); | ||
}, 30000); | ||
|
||
it('Uses an up to date powershell download script', async () => { | ||
const httpCallbackClient = new hc.HttpClient('setup-dotnet-test', [], { | ||
allowRetries: true, | ||
maxRetries: 3 | ||
}); | ||
const response: hc.HttpClientResponse = await httpCallbackClient.get( | ||
'https://dot.net/v1/dotnet-install.ps1' | ||
); | ||
expect(response.message.statusCode).toBe(200); | ||
const upToDateContents: string = await response.readBody(); | ||
const currentContents: string = fs | ||
.readFileSync( | ||
path.join(__dirname, '..', 'externals', 'install-dotnet.ps1') | ||
) | ||
.toString(); | ||
expect(normalizeFileContents(currentContents)).toBe( | ||
normalizeFileContents(upToDateContents) | ||
); | ||
}, 30000); | ||
}); | ||
|
||
function normalizeFileContents(contents: string): string { | ||
return contents | ||
.trim() | ||
.replace(new RegExp('\r\n', 'g'), '\n') | ||
.replace(new RegExp('\r', 'g'), '\n'); | ||
} |
Large diffs are not rendered by default.
Oops, something went wrong.
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 |
---|---|---|
@@ -1,114 +1,146 @@ | ||
import * as io from '@actions/io'; | ||
import * as core from '@actions/core'; | ||
import fs from 'fs'; | ||
import os from 'os'; | ||
import path from 'path'; | ||
import semver from 'semver'; | ||
import * as auth from '../src/authutil'; | ||
|
||
import * as setup from '../src/setup-dotnet'; | ||
import {IS_WINDOWS} from '../src/utils'; | ||
import {IS_LINUX} from '../src/utils'; | ||
|
||
let toolDir: string; | ||
|
||
if (IS_WINDOWS) { | ||
toolDir = path.join(process.env['PROGRAMFILES'] + '', 'dotnet'); | ||
} else if (IS_LINUX) { | ||
toolDir = '/usr/share/dotnet'; | ||
} else { | ||
toolDir = path.join(process.env['HOME'] + '', '.dotnet'); | ||
} | ||
|
||
function createGlobalJsonPath(dotnetVersion: string) { | ||
const globalJsonPath = path.join(process.cwd(), 'global.json'); | ||
const jsonContents = `{${os.EOL}"sdk": {${os.EOL}"version": "${dotnetVersion}"${os.EOL}}${os.EOL}}`; | ||
if (!fs.existsSync(globalJsonPath)) { | ||
fs.writeFileSync(globalJsonPath, jsonContents); | ||
} | ||
return globalJsonPath; | ||
} | ||
|
||
const tempDir = path.join(__dirname, 'runner', 'temp2'); | ||
import {DotnetCoreInstaller} from '../src/installer'; | ||
|
||
describe('setup-dotnet tests', () => { | ||
const inputs = {} as any; | ||
|
||
const getInputSpy = jest.spyOn(core, 'getInput'); | ||
const getMultilineInputSpy = jest.spyOn(core, 'getMultilineInput'); | ||
const setFailedSpy = jest.spyOn(core, 'setFailed'); | ||
const debugSpy = jest.spyOn(core, 'debug'); | ||
const infoSpy = jest.spyOn(core, 'info'); | ||
const setOutputSpy = jest.spyOn(core, 'setOutput'); | ||
|
||
const inputs = {} as any; | ||
const existsSyncSpy = jest.spyOn(fs, 'existsSync'); | ||
|
||
const maxSatisfyingSpy = jest.spyOn(semver, 'maxSatisfying'); | ||
|
||
const installDotnetSpy = jest.spyOn( | ||
DotnetCoreInstaller.prototype, | ||
'installDotnet' | ||
); | ||
const addToPathSpy = jest.spyOn(DotnetCoreInstaller, 'addToPath'); | ||
|
||
const configAuthenticationSpy = jest.spyOn(auth, 'configAuthentication'); | ||
|
||
describe('run() tests', () => { | ||
beforeEach(() => { | ||
getMultilineInputSpy.mockImplementation(input => inputs[input as string]); | ||
getInputSpy.mockImplementation(input => inputs[input as string]); | ||
}); | ||
|
||
afterEach(() => { | ||
jest.clearAllMocks(); | ||
jest.resetAllMocks(); | ||
}); | ||
|
||
it('should fail the action if global-json-file input is present, but the file does not exist in the file system', async () => { | ||
inputs['global-json-file'] = 'fictitious.json'; | ||
inputs['dotnet-version'] = []; | ||
|
||
const expectedErrorMessage = `The specified global.json file '${inputs['global-json-file']}' does not exist`; | ||
|
||
await setup.run(); | ||
expect(setFailedSpy).toHaveBeenCalledWith(expectedErrorMessage); | ||
}); | ||
|
||
test(`if 'dotnet-version' and 'global-json-file' inputs aren't present, should log into debug output, try to find global.json in the repo root, fail and log message into info output`, async () => { | ||
inputs['global-json-file'] = ''; | ||
inputs['dotnet-version'] = []; | ||
|
||
beforeAll(async () => { | ||
process.env.RUNNER_TOOL_CACHE = toolDir; | ||
process.env.DOTNET_INSTALL_DIR = toolDir; | ||
process.env.RUNNER_TEMP = tempDir; | ||
try { | ||
await io.rmRF(`${toolDir}/*`); | ||
await io.rmRF(`${tempDir}/*`); | ||
} catch (err) { | ||
console.log(err.message); | ||
console.log('Failed to remove test directories'); | ||
} | ||
}, 30000); | ||
maxSatisfyingSpy.mockImplementation(() => null); | ||
setOutputSpy.mockImplementation(() => {}); | ||
|
||
afterEach(async () => { | ||
try { | ||
await io.rmRF(path.join(process.cwd(), 'global.json')); | ||
await io.rmRF(`${toolDir}/*`); | ||
await io.rmRF(`${tempDir}/*`); | ||
} catch (err) { | ||
console.log(err.message); | ||
console.log('Failed to remove test directories'); | ||
} | ||
}, 30000); | ||
const expectedDebugMessage = | ||
'No version found, trying to find version from global.json'; | ||
const expectedInfoMessage = `global.json wasn't found in the root directory. No .NET version will be installed.`; | ||
|
||
it('Acquires version of dotnet from global.json if no matching version is installed', async () => { | ||
createGlobalJsonPath('3.1.201'); | ||
await setup.run(); | ||
await setup.run(); | ||
|
||
expect(fs.existsSync(path.join(toolDir, 'sdk', '3.1.201'))).toBe(true); | ||
if (IS_WINDOWS) { | ||
expect(fs.existsSync(path.join(toolDir, 'dotnet.exe'))).toBe(true); | ||
} else { | ||
expect(fs.existsSync(path.join(toolDir, 'dotnet'))).toBe(true); | ||
} | ||
}, 400000); | ||
expect(debugSpy).toHaveBeenCalledWith(expectedDebugMessage); | ||
expect(existsSyncSpy).toHaveBeenCalled(); | ||
expect(infoSpy).toHaveBeenCalledWith(expectedInfoMessage); | ||
}); | ||
|
||
it("Sets output with the latest installed by action version if global.json file isn't specified", async () => { | ||
inputs['dotnet-version'] = ['3.1.201', '6.0.401']; | ||
it('should fail the action if quality is supplied but its value is not supported', async () => { | ||
inputs['global-json-file'] = ''; | ||
inputs['dotnet-version'] = ['6.0']; | ||
inputs['dotnet-quality'] = 'fictitiousQuality'; | ||
|
||
getMultilineInputSpy.mockImplementation(input => inputs[input]); | ||
const expectedErrorMessage = `${inputs['dotnet-quality']} is not a supported value for 'dotnet-quality' option. Supported values are: daily, signed, validated, preview, ga.`; | ||
|
||
await setup.run(); | ||
await setup.run(); | ||
expect(setFailedSpy).toHaveBeenCalledWith(expectedErrorMessage); | ||
}); | ||
|
||
expect(setOutputSpy).toHaveBeenCalledWith('dotnet-version', '6.0.401'); | ||
}, 400000); | ||
it('should call installDotnet() multiple times if dotnet-version multiline input is provided', async () => { | ||
inputs['global-json-file'] = ''; | ||
inputs['dotnet-version'] = ['6.0', '7.0']; | ||
inputs['dotnet-quality'] = ''; | ||
|
||
it("Sets output with the version specified in global.json, if it's present", async () => { | ||
createGlobalJsonPath('3.0.103'); | ||
installDotnetSpy.mockImplementation(() => Promise.resolve('')); | ||
|
||
inputs['dotnet-version'] = ['3.1.201', '6.0.401']; | ||
inputs['global-json-file'] = './global.json'; | ||
await setup.run(); | ||
expect(installDotnetSpy).toHaveBeenCalledTimes(2); | ||
}); | ||
|
||
getMultilineInputSpy.mockImplementation(input => inputs[input]); | ||
it('should call addToPath() after installation complete', async () => { | ||
inputs['global-json-file'] = ''; | ||
inputs['dotnet-version'] = ['6.0', '7.0']; | ||
inputs['dotnet-quality'] = ''; | ||
|
||
getInputSpy.mockImplementation(input => inputs[input]); | ||
installDotnetSpy.mockImplementation(() => Promise.resolve('')); | ||
addToPathSpy.mockImplementation(() => {}); | ||
|
||
await setup.run(); | ||
await setup.run(); | ||
expect(addToPathSpy).toHaveBeenCalledTimes(1); | ||
}); | ||
|
||
expect(setOutputSpy).toHaveBeenCalledWith('dotnet-version', '3.0.103'); | ||
}, 400000); | ||
it('should call auth.configAuthentication() if source-url input is provided', async () => { | ||
inputs['global-json-file'] = ''; | ||
inputs['dotnet-version'] = []; | ||
inputs['dotnet-quality'] = ''; | ||
inputs['source-url'] = 'fictitious.source.url'; | ||
|
||
it('Sets output with the version specified in global.json with absolute path', async () => { | ||
const globalJsonPath = createGlobalJsonPath('3.0.103'); | ||
configAuthenticationSpy.mockImplementation(() => {}); | ||
|
||
inputs['dotnet-version'] = ['3.1.201', '6.0.401']; | ||
inputs['global-json-file'] = globalJsonPath; | ||
await setup.run(); | ||
expect(configAuthenticationSpy).toHaveBeenCalledWith( | ||
inputs['source-url'], | ||
undefined | ||
); | ||
}); | ||
|
||
getMultilineInputSpy.mockImplementation(input => inputs[input]); | ||
it('should call auth.configAuthentication() with proper parameters if source-url and config-file inputs are provided', async () => { | ||
inputs['global-json-file'] = ''; | ||
inputs['dotnet-version'] = []; | ||
inputs['dotnet-quality'] = ''; | ||
inputs['source-url'] = 'fictitious.source.url'; | ||
inputs['config-file'] = 'fictitious.path'; | ||
|
||
configAuthenticationSpy.mockImplementation(() => {}); | ||
setOutputSpy.mockImplementation(() => {}); | ||
|
||
getInputSpy.mockImplementation(input => inputs[input]); | ||
await setup.run(); | ||
expect(configAuthenticationSpy).toHaveBeenCalledWith( | ||
inputs['source-url'], | ||
inputs['config-file'] | ||
); | ||
}); | ||
|
||
await setup.run(); | ||
it('should call setOutput() after installation complete', async () => { | ||
inputs['dotnet-version'] = ['6.0.300']; | ||
|
||
installDotnetSpy.mockImplementation(() => Promise.resolve('')); | ||
addToPathSpy.mockImplementation(() => {}); | ||
|
||
expect(setOutputSpy).toHaveBeenCalledWith('dotnet-version', '3.0.103'); | ||
}, 400000); | ||
await setup.run(); | ||
expect(setOutputSpy).toHaveBeenCalledTimes(1); | ||
}); | ||
}); | ||
}); |
Large diffs are not rendered by default.
Oops, something went wrong.
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