build: add file extension for js files + create sh scripts + lint

This commit is contained in:
Amin Yahyaabadi 2022-07-09 17:21:00 -07:00
parent 727c15bda2
commit c6a39b5887
22 changed files with 1046 additions and 918 deletions

61
script/bootstrap Executable file → Normal file
View File

@ -1,55 +1,10 @@
#!/usr/bin/env node #!/bin/sh
basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
'use strict' case `uname` in
*CYGWIN*|*MINGW*|*MSYS*) basedir=`cygpath -w "$basedir"`;;
esac
const CONFIG = require('./config') node "$basedir/bootstrap.js" "$@"
const childProcess = require('child_process') ret=$?
const cleanDependencies = require('./lib/clean-dependencies') exit $ret
const deleteMsbuildFromPath = require('./lib/delete-msbuild-from-path')
const dependenciesFingerprint = require('./lib/dependencies-fingerprint')
const installScriptRunnerDependencies = require('./lib/install-script-runner-dependencies')
const verifyMachineRequirements = require('./lib/verify-machine-requirements')
process.on('unhandledRejection', function (e) {
console.error(e.stack || e)
process.exit(1)
})
// We can't use yargs until installScriptDependencies() is executed, so...
let ci = process.argv.indexOf('--ci') !== -1
if (!ci && process.env.CI === 'true' && process.argv.indexOf('--no-ci') === -1) {
console.log('Automatically enabling --ci because CI is set in the environment')
ci = true
}
verifyMachineRequirements(ci)
async function bootstrap() {
if (dependenciesFingerprint.isOutdated()) {
await cleanDependencies()
}
if (process.platform === 'win32') deleteMsbuildFromPath()
installScriptRunnerDependencies()
const { spawn, Thread, Worker } = require(`${CONFIG.scriptRunnerModulesPath}/threads`)
const installScriptDependencies = await spawn(new Worker('./lib/install-script-dependencies'))
const installScriptDependenciesPromise = installScriptDependencies(ci)
const installApm = await spawn(new Worker('./lib/install-apm'))
await installApm(ci);
await Thread.terminate(installApm)
const runApmInstall = require('./lib/run-apm-install')
runApmInstall(CONFIG.repositoryRootPath, ci)
await installScriptDependenciesPromise;
await Thread.terminate(installScriptDependencies)
dependenciesFingerprint.write()
}
bootstrap().then(() => {process.exit(0)}).catch((e) => {throw e;})

View File

@ -1,6 +1 @@
@IF EXIST "%~dp0\node.exe" ( node "%~dp0\bootstrap.js" %*
"%~dp0\node.exe" "%~dp0\bootstrap" %*
) ELSE (
node "%~dp0\bootstrap" %*
)

70
script/bootstrap.js vendored Normal file
View File

@ -0,0 +1,70 @@
#!/usr/bin/env node
'use strict';
const CONFIG = require('./config');
const cleanDependencies = require('./lib/clean-dependencies');
const deleteMsbuildFromPath = require('./lib/delete-msbuild-from-path');
const dependenciesFingerprint = require('./lib/dependencies-fingerprint');
const installScriptRunnerDependencies = require('./lib/install-script-runner-dependencies');
const verifyMachineRequirements = require('./lib/verify-machine-requirements');
process.on('unhandledRejection', function(e) {
console.error(e.stack || e);
process.exit(1);
});
// We can't use yargs until installScriptDependencies() is executed, so...
let ci = process.argv.indexOf('--ci') !== -1;
if (
!ci &&
process.env.CI === 'true' &&
process.argv.indexOf('--no-ci') === -1
) {
console.log(
'Automatically enabling --ci because CI is set in the environment'
);
ci = true;
}
verifyMachineRequirements(ci);
async function bootstrap() {
if (dependenciesFingerprint.isOutdated()) {
await cleanDependencies();
}
if (process.platform === 'win32') deleteMsbuildFromPath();
installScriptRunnerDependencies();
const { spawn, Thread, Worker } = require(`${
CONFIG.scriptRunnerModulesPath
}/threads`);
const installScriptDependencies = await spawn(
new Worker('./lib/install-script-dependencies')
);
const installScriptDependenciesPromise = installScriptDependencies(ci);
const installApm = await spawn(new Worker('./lib/install-apm'));
await installApm(ci);
await Thread.terminate(installApm);
const runApmInstall = require('./lib/run-apm-install');
runApmInstall(CONFIG.repositoryRootPath, ci);
await installScriptDependenciesPromise;
await Thread.terminate(installScriptDependencies);
dependenciesFingerprint.write();
}
bootstrap()
.then(() => {
process.exit(0);
})
.catch(e => {
throw e;
});

201
script/build Executable file → Normal file
View File

@ -1,195 +1,10 @@
#!/usr/bin/env node #!/bin/sh
basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
'use strict' case `uname` in
*CYGWIN*|*MINGW*|*MSYS*) basedir=`cygpath -w "$basedir"`;;
esac
const CONFIG = require('./config') node "$basedir/build.js" "$@"
ret=$?
if (process.argv.includes('--no-bootstrap')) { exit $ret
console.log('Skipping bootstrap')
} else {
// Bootstrap first to ensure all the dependencies used later in this script
// are installed.
const path = require('path')
const childProcess = require('child_process')
childProcess.execFileSync(process.execPath, [path.join(CONFIG.scriptRootPath, 'bootstrap')], { env: process.env, cwd: CONFIG.repositoryRootPath, stdio: 'inherit' });
}
// Required to load CS files in this build script, such as those in `donna`
require('coffee-script/register')
require('colors')
const path = require('path')
const yargs = require('yargs')
const argv = yargs
.usage('Usage: $0 [options]')
.help('help')
.describe('existing-binaries', 'Use existing Atom binaries (skip clean/transpile/cache)')
.describe('code-sign', 'Code-sign executables (macOS and Windows only)')
.describe('test-sign', 'Test-sign executables (macOS only)')
.describe('create-windows-installer', 'Create installer (Windows only)')
.describe('create-debian-package', 'Create .deb package (Linux only)')
.describe('create-rpm-package', 'Create .rpm package (Linux only)')
.describe('compress-artifacts', 'Compress Atom binaries (and symbols on macOS)')
.describe('generate-api-docs', 'Only build the API documentation')
.describe('install', 'Install Atom')
.string('install')
.describe('ci', 'Install dependencies quickly (package-lock.json files must be up to date)')
.wrap(yargs.terminalWidth())
.argv
const checkChromedriverVersion = require('./lib/check-chromedriver-version')
const cleanOutputDirectory = require('./lib/clean-output-directory')
const codeSignOnMac = require('./lib/code-sign-on-mac')
const codeSignOnWindows = require('./lib/code-sign-on-windows')
const compressArtifacts = require('./lib/compress-artifacts')
const copyAssets = require('./lib/copy-assets')
const createDebianPackage = require('./lib/create-debian-package')
const createRpmPackage = require('./lib/create-rpm-package')
const createWindowsInstaller = require('./lib/create-windows-installer')
const dumpSymbols = require('./lib/dump-symbols')
const generateAPIDocs = require('./lib/generate-api-docs')
const generateMetadata = require('./lib/generate-metadata')
const generateModuleCache = require('./lib/generate-module-cache')
const generateStartupSnapshot = require('./lib/generate-startup-snapshot')
const installApplication = require('./lib/install-application')
const notarizeOnMac = require('./lib/notarize-on-mac')
const packageApplication = require('./lib/package-application')
const prebuildLessCache = require('./lib/prebuild-less-cache')
const testSignOnMac = require('./lib/test-sign-on-mac')
process.on('unhandledRejection', function (e) {
console.error(e.stack || e)
process.exit(1)
})
process.env.ELECTRON_VERSION = CONFIG.appMetadata.electronVersion
async function transpile() {
const { spawn, Thread, Worker } = require(`${CONFIG.scriptRunnerModulesPath}/threads`)
const transpilePackagesWithCustomTranspilerPaths = await spawn(new Worker('./lib/transpile-packages-with-custom-transpiler-paths'))
const transpilePackagesWithCustomTranspilerPathsPromise = transpilePackagesWithCustomTranspilerPaths()
const transpileBabelPaths = await spawn(new Worker('./lib/transpile-babel-paths'))
const transpileBabelPathsPromise = transpileBabelPaths()
const transpileCoffeeScriptPaths = await spawn(new Worker('./lib/transpile-coffee-script-paths'))
const transpileCoffeeScriptPathsPromise = transpileCoffeeScriptPaths()
const transpileCsonPaths = await spawn(new Worker('./lib/transpile-cson-paths'))
const transpileCsonPathsPromise = transpileCsonPaths()
const transpilePegJsPaths = await spawn(new Worker('./lib/transpile-peg-js-paths'))
const transpilePegJsPathsPromise = transpilePegJsPaths()
await transpilePackagesWithCustomTranspilerPathsPromise;
await Thread.terminate(transpilePackagesWithCustomTranspilerPaths)
await transpileBabelPathsPromise;
await Thread.terminate(transpileBabelPaths)
await transpileCoffeeScriptPathsPromise;
await Thread.terminate(transpileCoffeeScriptPaths)
await transpileCsonPathsPromise;
await Thread.terminate(transpileCsonPaths)
await transpilePegJsPathsPromise;
await Thread.terminate(transpilePegJsPaths)
}
async function singAndCreateInstaller(packagedAppPath) {
switch (process.platform) {
case 'darwin': {
if (argv.codeSign) {
await codeSignOnMac(packagedAppPath)
await notarizeOnMac(packagedAppPath)
} else if (argv.testSign) {
testSignOnMac(packagedAppPath)
} else {
console.log('Skipping code-signing. Specify the --code-sign option to perform code-signing'.gray)
}
break
}
case 'win32': {
if (argv.testSign) {
console.log('Test signing is not supported on Windows, skipping.'.gray)
}
if (argv.codeSign) {
const executablesToSign = [ path.join(packagedAppPath, CONFIG.executableName) ]
if (argv.createWindowsInstaller) {
executablesToSign.push(path.join(__dirname, 'node_modules', '@atom', 'electron-winstaller', 'vendor', 'Squirrel.exe'))
}
codeSignOnWindows(executablesToSign)
} else {
console.log('Skipping code-signing. Specify the --code-sign option to perform code-signing'.gray)
}
if (argv.createWindowsInstaller) {
return createWindowsInstaller(packagedAppPath)
.then((installerPath) => {
argv.codeSign && codeSignOnWindows([installerPath])
return packagedAppPath
})
} else {
console.log('Skipping creating installer. Specify the --create-windows-installer option to create a Squirrel-based Windows installer.'.gray)
}
break
}
case 'linux': {
if (argv.createDebianPackage) {
createDebianPackage(packagedAppPath)
} else {
console.log('Skipping creating debian package. Specify the --create-debian-package option to create it.'.gray)
}
if (argv.createRpmPackage) {
createRpmPackage(packagedAppPath)
} else {
console.log('Skipping creating rpm package. Specify the --create-rpm-package option to create it.'.gray)
}
break
}
}
return Promise.resolve(packagedAppPath)
}
async function build() {
if (!argv.existingBinaries) {
checkChromedriverVersion()
await cleanOutputDirectory()
await copyAssets()
await transpile()
generateModuleCache()
prebuildLessCache()
generateMetadata()
generateAPIDocs()
if (!argv.generateApiDocs) {
await dumpSymbols()
}
}
if (!argv.generateApiDocs) {
const packagedAppPath = await packageApplication()
await generateStartupSnapshot(packagedAppPath)
await singAndCreateInstaller(packagedAppPath)
if (argv.compressArtifacts) {
compressArtifacts(packagedAppPath)
} else {
console.log('Skipping artifacts compression. Specify the --compress-artifacts option to compress Atom binaries (and symbols on macOS)'.gray)
}
if (argv.install != null) {
installApplication(packagedAppPath, argv.install)
} else {
console.log('Skipping installation. Specify the --install option to install Atom'.gray)
}
}
}
build().then(() => {process.exit(0)}).catch((e) => {throw e;})

View File

@ -1,5 +1 @@
@IF EXIST "%~dp0\node.exe" ( node "%~dp0\build.js" %*
"%~dp0\node.exe" "%~dp0\build" %*
) ELSE (
node "%~dp0\build" %*
)

252
script/build.js Normal file
View File

@ -0,0 +1,252 @@
#!/usr/bin/env node
'use strict';
const CONFIG = require('./config');
if (process.argv.includes('--no-bootstrap')) {
console.log('Skipping bootstrap');
} else {
// Bootstrap first to ensure all the dependencies used later in this script
// are installed.
const path = require('path');
const childProcess = require('child_process');
childProcess.execFileSync(
process.execPath,
[path.join(CONFIG.scriptRootPath, 'bootstrap')],
{ env: process.env, cwd: CONFIG.repositoryRootPath, stdio: 'inherit' }
);
}
// Required to load CS files in this build script, such as those in `donna`
require('coffee-script/register');
require('colors');
const path = require('path');
const yargs = require('yargs');
const argv = yargs
.usage('Usage: $0 [options]')
.help('help')
.describe(
'existing-binaries',
'Use existing Atom binaries (skip clean/transpile/cache)'
)
.describe('code-sign', 'Code-sign executables (macOS and Windows only)')
.describe('test-sign', 'Test-sign executables (macOS only)')
.describe('create-windows-installer', 'Create installer (Windows only)')
.describe('create-debian-package', 'Create .deb package (Linux only)')
.describe('create-rpm-package', 'Create .rpm package (Linux only)')
.describe(
'compress-artifacts',
'Compress Atom binaries (and symbols on macOS)'
)
.describe('generate-api-docs', 'Only build the API documentation')
.describe('install', 'Install Atom')
.string('install')
.describe(
'ci',
'Install dependencies quickly (package-lock.json files must be up to date)'
)
.wrap(yargs.terminalWidth()).argv;
const checkChromedriverVersion = require('./lib/check-chromedriver-version');
const cleanOutputDirectory = require('./lib/clean-output-directory');
const codeSignOnMac = require('./lib/code-sign-on-mac');
const codeSignOnWindows = require('./lib/code-sign-on-windows');
const compressArtifacts = require('./lib/compress-artifacts');
const copyAssets = require('./lib/copy-assets');
const createDebianPackage = require('./lib/create-debian-package');
const createRpmPackage = require('./lib/create-rpm-package');
const createWindowsInstaller = require('./lib/create-windows-installer');
const dumpSymbols = require('./lib/dump-symbols');
const generateAPIDocs = require('./lib/generate-api-docs');
const generateMetadata = require('./lib/generate-metadata');
const generateModuleCache = require('./lib/generate-module-cache');
const generateStartupSnapshot = require('./lib/generate-startup-snapshot');
const installApplication = require('./lib/install-application');
const notarizeOnMac = require('./lib/notarize-on-mac');
const packageApplication = require('./lib/package-application');
const prebuildLessCache = require('./lib/prebuild-less-cache');
const testSignOnMac = require('./lib/test-sign-on-mac');
process.on('unhandledRejection', function(e) {
console.error(e.stack || e);
process.exit(1);
});
process.env.ELECTRON_VERSION = CONFIG.appMetadata.electronVersion;
async function transpile() {
const { spawn, Thread, Worker } = require(`${
CONFIG.scriptRunnerModulesPath
}/threads`);
const transpilePackagesWithCustomTranspilerPaths = await spawn(
new Worker('./lib/transpile-packages-with-custom-transpiler-paths')
);
const transpilePackagesWithCustomTranspilerPathsPromise = transpilePackagesWithCustomTranspilerPaths();
const transpileBabelPaths = await spawn(
new Worker('./lib/transpile-babel-paths')
);
const transpileBabelPathsPromise = transpileBabelPaths();
const transpileCoffeeScriptPaths = await spawn(
new Worker('./lib/transpile-coffee-script-paths')
);
const transpileCoffeeScriptPathsPromise = transpileCoffeeScriptPaths();
const transpileCsonPaths = await spawn(
new Worker('./lib/transpile-cson-paths')
);
const transpileCsonPathsPromise = transpileCsonPaths();
const transpilePegJsPaths = await spawn(
new Worker('./lib/transpile-peg-js-paths')
);
const transpilePegJsPathsPromise = transpilePegJsPaths();
await transpilePackagesWithCustomTranspilerPathsPromise;
await Thread.terminate(transpilePackagesWithCustomTranspilerPaths);
await transpileBabelPathsPromise;
await Thread.terminate(transpileBabelPaths);
await transpileCoffeeScriptPathsPromise;
await Thread.terminate(transpileCoffeeScriptPaths);
await transpileCsonPathsPromise;
await Thread.terminate(transpileCsonPaths);
await transpilePegJsPathsPromise;
await Thread.terminate(transpilePegJsPaths);
}
async function singAndCreateInstaller(packagedAppPath) {
switch (process.platform) {
case 'darwin': {
if (argv.codeSign) {
await codeSignOnMac(packagedAppPath);
await notarizeOnMac(packagedAppPath);
} else if (argv.testSign) {
testSignOnMac(packagedAppPath);
} else {
console.log(
'Skipping code-signing. Specify the --code-sign option to perform code-signing'
.gray
);
}
break;
}
case 'win32': {
if (argv.testSign) {
console.log('Test signing is not supported on Windows, skipping.'.gray);
}
if (argv.codeSign) {
const executablesToSign = [
path.join(packagedAppPath, CONFIG.executableName)
];
if (argv.createWindowsInstaller) {
executablesToSign.push(
path.join(
__dirname,
'node_modules',
'@atom',
'electron-winstaller',
'vendor',
'Squirrel.exe'
)
);
}
codeSignOnWindows(executablesToSign);
} else {
console.log(
'Skipping code-signing. Specify the --code-sign option to perform code-signing'
.gray
);
}
if (argv.createWindowsInstaller) {
return createWindowsInstaller(packagedAppPath).then(installerPath => {
argv.codeSign && codeSignOnWindows([installerPath]);
return packagedAppPath;
});
} else {
console.log(
'Skipping creating installer. Specify the --create-windows-installer option to create a Squirrel-based Windows installer.'
.gray
);
}
break;
}
case 'linux': {
if (argv.createDebianPackage) {
createDebianPackage(packagedAppPath);
} else {
console.log(
'Skipping creating debian package. Specify the --create-debian-package option to create it.'
.gray
);
}
if (argv.createRpmPackage) {
createRpmPackage(packagedAppPath);
} else {
console.log(
'Skipping creating rpm package. Specify the --create-rpm-package option to create it.'
.gray
);
}
break;
}
}
return Promise.resolve(packagedAppPath);
}
async function build() {
if (!argv.existingBinaries) {
checkChromedriverVersion();
await cleanOutputDirectory();
await copyAssets();
await transpile();
generateModuleCache();
prebuildLessCache();
generateMetadata();
generateAPIDocs();
if (!argv.generateApiDocs) {
await dumpSymbols();
}
}
if (!argv.generateApiDocs) {
const packagedAppPath = await packageApplication();
await generateStartupSnapshot(packagedAppPath);
await singAndCreateInstaller(packagedAppPath);
if (argv.compressArtifacts) {
compressArtifacts(packagedAppPath);
} else {
console.log(
'Skipping artifacts compression. Specify the --compress-artifacts option to compress Atom binaries (and symbols on macOS)'
.gray
);
}
if (argv.install != null) {
installApplication(packagedAppPath, argv.install);
} else {
console.log(
'Skipping installation. Specify the --install option to install Atom'
.gray
);
}
}
}
build()
.then(() => {
process.exit(0);
})
.catch(e => {
throw e;
});

View File

@ -1,2 +0,0 @@
echo "Builds for this version of Atom no longer run on Janky."
echo "See https://github.com/atom/atom/pull/12410 for more information."

25
script/clean Executable file → Normal file
View File

@ -1,19 +1,10 @@
#!/usr/bin/env node #!/bin/sh
basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
'use strict' case `uname` in
*CYGWIN*|*MINGW*|*MSYS*) basedir=`cygpath -w "$basedir"`;;
esac
const cleanCaches = require('./lib/clean-caches') node "$basedir/clean.js" "$@"
const cleanDependencies = require('./lib/clean-dependencies') ret=$?
const cleanOutputDirectory = require('./lib/clean-output-directory') exit $ret
const killRunningAtomInstances = require('./lib/kill-running-atom-instances')
async function clean() {
killRunningAtomInstances()
return Promise.all([
cleanDependencies(),
cleanCaches(),
cleanOutputDirectory()
])
}
clean().then(() => {process.exit(0)}).catch((e) => {throw e;})

View File

@ -1,5 +1 @@
@IF EXIST "%~dp0\node.exe" ( node "%~dp0\clean.js" %*
"%~dp0\node.exe" "%~dp0\clean" %*
) ELSE (
node "%~dp0\clean" %*
)

25
script/clean.js Normal file
View File

@ -0,0 +1,25 @@
#!/usr/bin/env node
'use strict';
const cleanCaches = require('./lib/clean-caches');
const cleanDependencies = require('./lib/clean-dependencies');
const cleanOutputDirectory = require('./lib/clean-output-directory');
const killRunningAtomInstances = require('./lib/kill-running-atom-instances');
async function clean() {
killRunningAtomInstances();
return Promise.all([
cleanDependencies(),
cleanCaches(),
cleanOutputDirectory()
]);
}
clean()
.then(() => {
process.exit(0);
})
.catch(e => {
throw e;
});

41
script/lint Executable file → Normal file
View File

@ -1,35 +1,10 @@
#!/usr/bin/env node #!/bin/sh
basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
'use strict' case `uname` in
*CYGWIN*|*MINGW*|*MSYS*) basedir=`cygpath -w "$basedir"`;;
esac
require('colors') node "$basedir/lint.js" "$@"
ret=$?
const lintCoffeeScriptPaths = require('./lib/lint-coffee-script-paths') exit $ret
const lintJavaScriptPaths = require('./lib/lint-java-script-paths')
const lintLessPaths = require('./lib/lint-less-paths')
const path = require('path')
const CONFIG = require('./config')
process.on('unhandledRejection', function (e) {
console.error(e.stack || e)
process.exit(1)
})
Promise.all([lintCoffeeScriptPaths(), lintJavaScriptPaths(), lintLessPaths()])
.then((lintResults) => {
let hasLintErrors = false
for (let errors of lintResults) {
for (let error of errors) {
hasLintErrors = true
const relativePath = path.relative(CONFIG.repositoryRootPath, error.path)
console.log(`${relativePath}:${error.lineNumber}`.yellow + ` ${error.message} (${error.rule})`.red)
}
}
if (hasLintErrors) {
process.exit(1)
} else {
console.log('No lint errors!'.green)
process.exit(0)
}
})

View File

@ -1,5 +1 @@
@IF EXIST "%~dp0\node.exe" ( node "%~dp0\lint.js" %*
"%~dp0\node.exe" "%~dp0\lint" %*
) ELSE (
node "%~dp0\lint" %*
)

41
script/lint.js Normal file
View File

@ -0,0 +1,41 @@
#!/usr/bin/env node
'use strict';
require('colors');
const lintCoffeeScriptPaths = require('./lib/lint-coffee-script-paths');
const lintJavaScriptPaths = require('./lib/lint-java-script-paths');
const lintLessPaths = require('./lib/lint-less-paths');
const path = require('path');
const CONFIG = require('./config');
process.on('unhandledRejection', function(e) {
console.error(e.stack || e);
process.exit(1);
});
Promise.all([
lintCoffeeScriptPaths(),
lintJavaScriptPaths(),
lintLessPaths()
]).then(lintResults => {
let hasLintErrors = false;
for (let errors of lintResults) {
for (let error of errors) {
hasLintErrors = true;
const relativePath = path.relative(CONFIG.repositoryRootPath, error.path);
console.log(
`${relativePath}:${error.lineNumber}`.yellow +
` ${error.message} (${error.rule})`.red
);
}
}
if (hasLintErrors) {
process.exit(1);
} else {
console.log('No lint errors!'.green);
process.exit(0);
}
});

93
script/postprocess-junit-results Executable file → Normal file
View File

@ -1,87 +1,10 @@
#!/usr/bin/env node #!/bin/sh
basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
const yargs = require('yargs') case `uname` in
*CYGWIN*|*MINGW*|*MSYS*) basedir=`cygpath -w "$basedir"`;;
esac
const argv = yargs node "$basedir/postprocess-junit-results.js" "$@"
.usage('Usage: $0 [options]') ret=$?
.help('help') exit $ret
.option('search-folder', {
string: true,
demandOption: true,
requiresArg: true,
describe: 'Directory to search for JUnit XML results'
})
.option('test-results-files', {
string: true,
demandOption: true,
requiresArg: true,
describe: 'Glob that matches JUnit XML files within searchFolder'
})
.wrap(yargs.terminalWidth())
.argv
const fs = require('fs')
const path = require('path')
const glob = require('glob')
const cheerio = require('cheerio')
function discoverTestFiles() {
return new Promise((resolve, reject) => {
glob(argv.testResultsFiles, {cwd: argv.searchFolder}, (err, paths) => {
if (err) {
reject(err)
} else {
resolve(paths)
}
})
})
}
async function postProcessJUnitXML(junitXmlPath) {
const fullPath = path.resolve(argv.searchFolder, junitXmlPath)
const friendlyName = path.basename(junitXmlPath, '.xml').replace(/-+/g, ' ')
console.log(`${fullPath}: loading`)
const original = await new Promise((resolve, reject) => {
fs.readFile(fullPath, {encoding: 'utf8'}, (err, content) => {
if (err) {
reject(err)
} else {
resolve(content)
}
})
})
const $ = cheerio.load(original, { xmlMode: true })
$('testcase').attr('name', (i, oldName) => `[${friendlyName}] ${oldName}`)
const modified = $.xml()
await new Promise((resolve, reject) => {
fs.writeFile(fullPath, modified, {encoding: 'utf8'}, err => {
if (err) {
reject(err)
} else {
resolve()
}
})
})
console.log(`${fullPath}: complete`)
}
;(async function() {
const testResultFiles = await discoverTestFiles()
console.log(`Post-processing ${testResultFiles.length} JUnit XML files`)
await Promise.all(
testResultFiles.map(postProcessJUnitXML)
)
console.log(`${testResultFiles.length} JUnit XML files complete`)
})().then(
() => process.exit(0),
err => {
console.error(err.stack || err)
process.exit(1)
}
)

View File

@ -1,5 +1 @@
@IF EXIST "%~dp0\node.exe" ( node "%~dp0\postprocess-junit-results.js" %*
"%~dp0\node.exe" "%~dp0\postprocess-junit-results" %*
) ELSE (
node "%~dp0\postprocess-junit-results" %*
)

View File

@ -0,0 +1,84 @@
#!/usr/bin/env node
const yargs = require('yargs');
const argv = yargs
.usage('Usage: $0 [options]')
.help('help')
.option('search-folder', {
string: true,
demandOption: true,
requiresArg: true,
describe: 'Directory to search for JUnit XML results'
})
.option('test-results-files', {
string: true,
demandOption: true,
requiresArg: true,
describe: 'Glob that matches JUnit XML files within searchFolder'
})
.wrap(yargs.terminalWidth()).argv;
const fs = require('fs');
const path = require('path');
const glob = require('glob');
const cheerio = require('cheerio');
function discoverTestFiles() {
return new Promise((resolve, reject) => {
glob(argv.testResultsFiles, { cwd: argv.searchFolder }, (err, paths) => {
if (err) {
reject(err);
} else {
resolve(paths);
}
});
});
}
async function postProcessJUnitXML(junitXmlPath) {
const fullPath = path.resolve(argv.searchFolder, junitXmlPath);
const friendlyName = path.basename(junitXmlPath, '.xml').replace(/-+/g, ' ');
console.log(`${fullPath}: loading`);
const original = await new Promise((resolve, reject) => {
fs.readFile(fullPath, { encoding: 'utf8' }, (err, content) => {
if (err) {
reject(err);
} else {
resolve(content);
}
});
});
const $ = cheerio.load(original, { xmlMode: true });
$('testcase').attr('name', (i, oldName) => `[${friendlyName}] ${oldName}`);
const modified = $.xml();
await new Promise((resolve, reject) => {
fs.writeFile(fullPath, modified, { encoding: 'utf8' }, err => {
if (err) {
reject(err);
} else {
resolve();
}
});
});
console.log(`${fullPath}: complete`);
}
(async function() {
const testResultFiles = await discoverTestFiles();
console.log(`Post-processing ${testResultFiles.length} JUnit XML files`);
await Promise.all(testResultFiles.map(postProcessJUnitXML));
console.log(`${testResultFiles.length} JUnit XML files complete`);
})().then(
() => process.exit(0),
err => {
console.error(err.stack || err);
process.exit(1);
}
);

506
script/test Executable file → Normal file
View File

@ -1,500 +1,10 @@
#!/usr/bin/env node #!/bin/sh
basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
'use strict'; case `uname` in
*CYGWIN*|*MINGW*|*MSYS*) basedir=`cygpath -w "$basedir"`;;
esac
require('colors'); node "$basedir/test.js" "$@"
const argv = require('yargs') ret=$?
.option('core-main', { exit $ret
describe: 'Run core main process tests',
boolean: true,
default: false
})
.option('skip-main', {
describe:
'Skip main process tests if they would otherwise run on your platform',
boolean: true,
default: false,
conflicts: 'core-main'
})
.option('core-renderer', {
describe: 'Run core renderer process tests',
boolean: true,
default: false
})
.option('core-benchmark', {
describe: 'Run core benchmarks',
boolean: true,
default: false
})
.option('package', {
describe: 'Run bundled package specs',
boolean: true,
default: false
})
.help().argv;
const assert = require('assert');
const asyncSeries = require('async/series');
const childProcess = require('child_process');
const fs = require('fs-extra');
const glob = require('glob');
const path = require('path');
const temp = require('temp').track();
const CONFIG = require('./config');
const backupNodeModules = require('./lib/backup-node-modules');
const runApmInstall = require('./lib/run-apm-install');
function assertExecutablePaths(executablePaths) {
assert(
executablePaths.length !== 0,
`No atom build found. Please run "script/build" and try again.`
);
assert(
executablePaths.length === 1,
`More than one application to run tests against was found. ${executablePaths.join(
','
)}`
);
}
const resourcePath = CONFIG.repositoryRootPath;
let executablePath;
if (process.platform === 'darwin') {
const executablePaths = glob.sync(path.join(CONFIG.buildOutputPath, '*.app'));
assertExecutablePaths(executablePaths);
executablePath = path.join(
executablePaths[0],
'Contents',
'MacOS',
path.basename(executablePaths[0], '.app')
);
} else if (process.platform === 'linux') {
const executablePaths = glob.sync(
path.join(CONFIG.buildOutputPath, 'atom-*', 'atom')
);
assertExecutablePaths(executablePaths);
executablePath = executablePaths[0];
} else if (process.platform === 'win32') {
const executablePaths = glob.sync(
path.join(CONFIG.buildOutputPath, '**', 'atom*.exe')
);
assertExecutablePaths(executablePaths);
executablePath = executablePaths[0];
} else {
throw new Error('##[error] Running tests on this platform is not supported.');
}
function prepareEnv(suiteName) {
const atomHomeDirPath = temp.mkdirSync(suiteName);
const env = Object.assign({}, process.env, { ATOM_HOME: atomHomeDirPath });
if (process.env.TEST_JUNIT_XML_ROOT) {
// Tell Jasmine to output this suite's results as a JUnit XML file to a subdirectory of the root, so that a
// CI system can interpret it.
const fileName = suiteName + '.xml';
const outputPath = path.join(process.env.TEST_JUNIT_XML_ROOT, fileName);
env.TEST_JUNIT_XML_PATH = outputPath;
}
return env;
}
function spawnTest(
executablePath,
testArguments,
options,
callback,
testName,
finalize = null
) {
const cp = childProcess.spawn(executablePath, testArguments, options);
// collect outputs and errors
let stderrOutput = '';
if (cp.stdout) {
cp.stderr.on('data', data => {
stderrOutput += data;
});
cp.stdout.on('data', data => {
stderrOutput += data;
});
}
// on error
cp.on('error', error => {
console.log(error, 'error');
if (finalize) {
finalize();
} // if finalizer provided
callback(error);
});
// on close
cp.on('close', exitCode => {
if (exitCode !== 0) {
retryOrFailTest(
stderrOutput,
exitCode,
executablePath,
testArguments,
options,
callback,
testName,
finalize
);
} else {
// successful test
if (finalize) {
finalize();
} // if finalizer provided
callback(null, {
exitCode,
step: testName,
testCommand: `You can run the test again using: \n\t ${executablePath} ${testArguments.join(
' '
)}`
});
}
});
}
const retryNumber = 6; // the number of times a tests repeats
const retriedTests = new Map(); // a cache of retried tests
// Retries the tests if it is timed out for a number of times. Fails the rest of the tests or those that are tried enough times.
function retryOrFailTest(
stderrOutput,
exitCode,
executablePath,
testArguments,
options,
callback,
testName,
finalize
) {
const testKey = createTestKey(executablePath, testArguments, testName);
if (isTimedOut(stderrOutput) && shouldTryAgain(testKey)) {
// retry the timed out test
let triedNumber = retriedTests.get(testKey) || 0;
retriedTests.set(testKey, triedNumber + 1);
console.warn(`\n##[warning] Retrying the timed out step: ${testName} \n`);
spawnTest(
executablePath,
testArguments,
options,
callback,
testName,
finalize
);
} else {
// fail the test
if (finalize) {
finalize();
} // if finalizer provided
console.log(`##[error] Tests for ${testName} failed.`.red);
console.log(stderrOutput);
callback(null, {
exitCode,
step: testName,
testCommand: `You can run the test again using: \n\t ${executablePath} ${testArguments.join(
' '
)}`
});
}
}
// creates a key that is specific to a certain test
function createTestKey(executablePath, testArguments, testName) {
return `${executablePath} ${testArguments.join(' ')} ${testName}`;
}
// check if a test is timed out
function isTimedOut(stderrOutput) {
if (stderrOutput) {
return (
stderrOutput.includes('timeout: timed out after') || // happens in core renderer tests
stderrOutput.includes('Error: Timed out waiting on') || // happens in core renderer tests
stderrOutput.includes('Error: timeout of') || // happens in core main tests
stderrOutput.includes(
'Error Downloading Update: Could not get code signature for running application'
) // happens in github tests
);
} else {
return false;
}
}
// check if a tests should be tried again
function shouldTryAgain(testKey) {
if (retriedTests.has(testKey)) {
return retriedTests.get(testKey) < retryNumber;
} else {
return true;
}
}
function runCoreMainProcessTests(callback) {
const testPath = path.join(CONFIG.repositoryRootPath, 'spec', 'main-process');
const testArguments = [
'--resource-path',
resourcePath,
'--test',
'--main-process',
testPath
];
if (process.env.CI && process.platform === 'linux') {
testArguments.push('--no-sandbox');
}
const testEnv = Object.assign({}, prepareEnv('core-main-process'), {
ATOM_GITHUB_INLINE_GIT_EXEC: 'true'
});
console.log('##[command] Executing core main process tests'.bold.green);
spawnTest(
executablePath,
testArguments,
{ stdio: 'inherit', env: testEnv },
callback,
'core-main-process'
);
}
function getCoreRenderProcessTestSuites() {
// Build an array of functions, each running tests for a different rendering test
const coreRenderProcessTestSuites = [];
const testPath = path.join(CONFIG.repositoryRootPath, 'spec');
let testFiles = glob.sync(
path.join(testPath, '*-spec.+(js|coffee|ts|jsx|tsx|mjs)')
);
for (let testFile of testFiles) {
const testArguments = ['--resource-path', resourcePath, '--test', testFile];
// the function which runs by async:
coreRenderProcessTestSuites.push(function(callback) {
const testEnv = prepareEnv('core-render-process');
console.log(
`##[command] Executing core render process tests for ${testFile}`.bold
.green
);
spawnTest(
executablePath,
testArguments,
{ env: testEnv },
callback,
`core-render-process in ${testFile}.`
);
});
}
return coreRenderProcessTestSuites;
}
function getPackageTestSuites() {
// Build an array of functions, each running tests for a different bundled package
const packageTestSuites = [];
for (let packageName in CONFIG.appMetadata.packageDependencies) {
if (process.env.ATOM_PACKAGES_TO_TEST) {
const packagesToTest = process.env.ATOM_PACKAGES_TO_TEST.split(',').map(
pkg => pkg.trim()
);
if (!packagesToTest.includes(packageName)) continue;
}
const repositoryPackagePath = path.join(
CONFIG.repositoryRootPath,
'node_modules',
packageName
);
const testSubdir = ['spec', 'test'].find(subdir =>
fs.existsSync(path.join(repositoryPackagePath, subdir))
);
if (!testSubdir) {
console.log(`No test folder found for package: ${packageName}`.yellow);
continue;
}
const testFolder = path.join(repositoryPackagePath, testSubdir);
const testArguments = [
'--resource-path',
resourcePath,
'--test',
testFolder
];
const pkgJsonPath = path.join(repositoryPackagePath, 'package.json');
const nodeModulesPath = path.join(repositoryPackagePath, 'node_modules');
// the function which runs by async:
packageTestSuites.push(function(callback) {
const testEnv = prepareEnv(`bundled-package-${packageName}`);
let finalize = () => null;
if (require(pkgJsonPath).atomTestRunner) {
console.log(
`##[command] Installing test runner dependencies for ${packageName}`
.bold.green
);
if (fs.existsSync(nodeModulesPath)) {
const backup = backupNodeModules(repositoryPackagePath);
finalize = backup.restore;
} else {
finalize = () => fs.removeSync(nodeModulesPath);
}
runApmInstall(repositoryPackagePath);
console.log(`##[command] Executing ${packageName} tests`.green);
} else {
console.log(`##[command] Executing ${packageName} tests`.bold.green);
}
spawnTest(
executablePath,
testArguments,
{ env: testEnv },
callback,
`${packageName} package`,
finalize
);
});
}
return packageTestSuites;
}
function runBenchmarkTests(callback) {
const benchmarksPath = path.join(CONFIG.repositoryRootPath, 'benchmarks');
const testArguments = ['--benchmark-test', benchmarksPath];
const testEnv = prepareEnv('benchmark');
console.log('##[command] Executing benchmark tests'.bold.green);
spawnTest(
executablePath,
testArguments,
{ stdio: 'inherit', env: testEnv },
callback,
`core-benchmarks`
);
}
let testSuitesToRun = requestedTestSuites(process.platform);
function requestedTestSuites(platform) {
// env variable or argv options
let coreAll = process.env.ATOM_RUN_CORE_TESTS === 'true';
let coreMain =
process.env.ATOM_RUN_CORE_MAIN_TESTS === 'true' || argv.coreMain;
let coreRenderer =
argv.coreRenderer || process.env.ATOM_RUN_CORE_RENDER_TESTS === 'true';
let coreRenderer1 = process.env.ATOM_RUN_CORE_RENDER_TESTS === '1';
let coreRenderer2 = process.env.ATOM_RUN_CORE_RENDER_TESTS === '2';
let packageAll =
argv.package || process.env.ATOM_RUN_PACKAGE_TESTS === 'true';
let packages1 = process.env.ATOM_RUN_PACKAGE_TESTS === '1';
let packages2 = process.env.ATOM_RUN_PACKAGE_TESTS === '2';
let benchmark = argv.coreBenchmark;
// Operating system overrides:
coreMain =
coreMain ||
platform === 'linux' ||
(platform === 'win32' && process.arch === 'x86');
// split package tests (used for macos in CI)
const PACKAGES_TO_TEST_IN_PARALLEL = 23;
// split core render test (used for windows x64 in CI)
const CORE_RENDER_TO_TEST_IN_PARALLEL = 45;
let suites = [];
// Core tess
if (coreAll) {
suites.push(
...[runCoreMainProcessTests, ...getCoreRenderProcessTestSuites()]
);
} else {
// Core main tests
if (coreMain) {
suites.push(runCoreMainProcessTests);
}
// Core renderer tests
if (coreRenderer) {
suites.push(...getCoreRenderProcessTestSuites());
} else {
// split
if (coreRenderer1) {
suites.push(
...getCoreRenderProcessTestSuites().slice(
0,
CORE_RENDER_TO_TEST_IN_PARALLEL
)
);
}
if (coreRenderer2) {
suites.push(
...getCoreRenderProcessTestSuites().slice(
CORE_RENDER_TO_TEST_IN_PARALLEL
)
);
}
}
}
// Package tests
if (packageAll) {
suites.push(...getPackageTestSuites());
} else {
// split
if (packages1) {
suites.push(
...getPackageTestSuites().slice(0, PACKAGES_TO_TEST_IN_PARALLEL)
);
}
if (packages2) {
suites.push(
...getPackageTestSuites().slice(PACKAGES_TO_TEST_IN_PARALLEL)
);
}
}
// Benchmark tests
if (benchmark) {
suites.push(runBenchmarkTests);
}
if (argv.skipMainProcessTests) {
suites = suites.filter(suite => suite !== runCoreMainProcessTests);
}
// Remove duplicates
suites = Array.from(new Set(suites));
if (suites.length === 0) {
throw new Error('No tests was requested');
}
return suites;
}
asyncSeries(testSuitesToRun, function(err, results) {
if (err) {
console.error(err);
process.exit(1);
} else {
const failedSteps = results.filter(({ exitCode }) => exitCode !== 0);
if (failedSteps.length > 0) {
console.warn(
'\n \n ##[error] *** Reporting the errors that happened in all of the tests: *** \n \n'
);
for (const { step, testCommand } of failedSteps) {
console.error(
`##[error] The '${step}' test step finished with a non-zero exit code \n ${testCommand}`
);
}
process.exit(1);
}
process.exit(0);
}
});

View File

@ -1,5 +1 @@
@IF EXIST "%~dp0\node.exe" ( node "%~dp0\test.js" %*
"%~dp0\node.exe" "%~dp0\test" %*
) ELSE (
node "%~dp0\test" %*
)

500
script/test.js Normal file
View File

@ -0,0 +1,500 @@
#!/usr/bin/env node
'use strict';
require('colors');
const argv = require('yargs')
.option('core-main', {
describe: 'Run core main process tests',
boolean: true,
default: false
})
.option('skip-main', {
describe:
'Skip main process tests if they would otherwise run on your platform',
boolean: true,
default: false,
conflicts: 'core-main'
})
.option('core-renderer', {
describe: 'Run core renderer process tests',
boolean: true,
default: false
})
.option('core-benchmark', {
describe: 'Run core benchmarks',
boolean: true,
default: false
})
.option('package', {
describe: 'Run bundled package specs',
boolean: true,
default: false
})
.help().argv;
const assert = require('assert');
const asyncSeries = require('async/series');
const childProcess = require('child_process');
const fs = require('fs-extra');
const glob = require('glob');
const path = require('path');
const temp = require('temp').track();
const CONFIG = require('./config');
const backupNodeModules = require('./lib/backup-node-modules');
const runApmInstall = require('./lib/run-apm-install');
function assertExecutablePaths(executablePaths) {
assert(
executablePaths.length !== 0,
`No atom build found. Please run "script/build" and try again.`
);
assert(
executablePaths.length === 1,
`More than one application to run tests against was found. ${executablePaths.join(
','
)}`
);
}
const resourcePath = CONFIG.repositoryRootPath;
let executablePath;
if (process.platform === 'darwin') {
const executablePaths = glob.sync(path.join(CONFIG.buildOutputPath, '*.app'));
assertExecutablePaths(executablePaths);
executablePath = path.join(
executablePaths[0],
'Contents',
'MacOS',
path.basename(executablePaths[0], '.app')
);
} else if (process.platform === 'linux') {
const executablePaths = glob.sync(
path.join(CONFIG.buildOutputPath, 'atom-*', 'atom')
);
assertExecutablePaths(executablePaths);
executablePath = executablePaths[0];
} else if (process.platform === 'win32') {
const executablePaths = glob.sync(
path.join(CONFIG.buildOutputPath, '**', 'atom*.exe')
);
assertExecutablePaths(executablePaths);
executablePath = executablePaths[0];
} else {
throw new Error('##[error] Running tests on this platform is not supported.');
}
function prepareEnv(suiteName) {
const atomHomeDirPath = temp.mkdirSync(suiteName);
const env = Object.assign({}, process.env, { ATOM_HOME: atomHomeDirPath });
if (process.env.TEST_JUNIT_XML_ROOT) {
// Tell Jasmine to output this suite's results as a JUnit XML file to a subdirectory of the root, so that a
// CI system can interpret it.
const fileName = suiteName + '.xml';
const outputPath = path.join(process.env.TEST_JUNIT_XML_ROOT, fileName);
env.TEST_JUNIT_XML_PATH = outputPath;
}
return env;
}
function spawnTest(
executablePath,
testArguments,
options,
callback,
testName,
finalize = null
) {
const cp = childProcess.spawn(executablePath, testArguments, options);
// collect outputs and errors
let stderrOutput = '';
if (cp.stdout) {
cp.stderr.on('data', data => {
stderrOutput += data;
});
cp.stdout.on('data', data => {
stderrOutput += data;
});
}
// on error
cp.on('error', error => {
console.log(error, 'error');
if (finalize) {
finalize();
} // if finalizer provided
callback(error);
});
// on close
cp.on('close', exitCode => {
if (exitCode !== 0) {
retryOrFailTest(
stderrOutput,
exitCode,
executablePath,
testArguments,
options,
callback,
testName,
finalize
);
} else {
// successful test
if (finalize) {
finalize();
} // if finalizer provided
callback(null, {
exitCode,
step: testName,
testCommand: `You can run the test again using: \n\t ${executablePath} ${testArguments.join(
' '
)}`
});
}
});
}
const retryNumber = 6; // the number of times a tests repeats
const retriedTests = new Map(); // a cache of retried tests
// Retries the tests if it is timed out for a number of times. Fails the rest of the tests or those that are tried enough times.
function retryOrFailTest(
stderrOutput,
exitCode,
executablePath,
testArguments,
options,
callback,
testName,
finalize
) {
const testKey = createTestKey(executablePath, testArguments, testName);
if (isTimedOut(stderrOutput) && shouldTryAgain(testKey)) {
// retry the timed out test
let triedNumber = retriedTests.get(testKey) || 0;
retriedTests.set(testKey, triedNumber + 1);
console.warn(`\n##[warning] Retrying the timed out step: ${testName} \n`);
spawnTest(
executablePath,
testArguments,
options,
callback,
testName,
finalize
);
} else {
// fail the test
if (finalize) {
finalize();
} // if finalizer provided
console.log(`##[error] Tests for ${testName} failed.`.red);
console.log(stderrOutput);
callback(null, {
exitCode,
step: testName,
testCommand: `You can run the test again using: \n\t ${executablePath} ${testArguments.join(
' '
)}`
});
}
}
// creates a key that is specific to a certain test
function createTestKey(executablePath, testArguments, testName) {
return `${executablePath} ${testArguments.join(' ')} ${testName}`;
}
// check if a test is timed out
function isTimedOut(stderrOutput) {
if (stderrOutput) {
return (
stderrOutput.includes('timeout: timed out after') || // happens in core renderer tests
stderrOutput.includes('Error: Timed out waiting on') || // happens in core renderer tests
stderrOutput.includes('Error: timeout of') || // happens in core main tests
stderrOutput.includes(
'Error Downloading Update: Could not get code signature for running application'
) // happens in github tests
);
} else {
return false;
}
}
// check if a tests should be tried again
function shouldTryAgain(testKey) {
if (retriedTests.has(testKey)) {
return retriedTests.get(testKey) < retryNumber;
} else {
return true;
}
}
function runCoreMainProcessTests(callback) {
const testPath = path.join(CONFIG.repositoryRootPath, 'spec', 'main-process');
const testArguments = [
'--resource-path',
resourcePath,
'--test',
'--main-process',
testPath
];
if (process.env.CI && process.platform === 'linux') {
testArguments.push('--no-sandbox');
}
const testEnv = Object.assign({}, prepareEnv('core-main-process'), {
ATOM_GITHUB_INLINE_GIT_EXEC: 'true'
});
console.log('##[command] Executing core main process tests'.bold.green);
spawnTest(
executablePath,
testArguments,
{ stdio: 'inherit', env: testEnv },
callback,
'core-main-process'
);
}
function getCoreRenderProcessTestSuites() {
// Build an array of functions, each running tests for a different rendering test
const coreRenderProcessTestSuites = [];
const testPath = path.join(CONFIG.repositoryRootPath, 'spec');
let testFiles = glob.sync(
path.join(testPath, '*-spec.+(js|coffee|ts|jsx|tsx|mjs)')
);
for (let testFile of testFiles) {
const testArguments = ['--resource-path', resourcePath, '--test', testFile];
// the function which runs by async:
coreRenderProcessTestSuites.push(function(callback) {
const testEnv = prepareEnv('core-render-process');
console.log(
`##[command] Executing core render process tests for ${testFile}`.bold
.green
);
spawnTest(
executablePath,
testArguments,
{ env: testEnv },
callback,
`core-render-process in ${testFile}.`
);
});
}
return coreRenderProcessTestSuites;
}
function getPackageTestSuites() {
// Build an array of functions, each running tests for a different bundled package
const packageTestSuites = [];
for (let packageName in CONFIG.appMetadata.packageDependencies) {
if (process.env.ATOM_PACKAGES_TO_TEST) {
const packagesToTest = process.env.ATOM_PACKAGES_TO_TEST.split(',').map(
pkg => pkg.trim()
);
if (!packagesToTest.includes(packageName)) continue;
}
const repositoryPackagePath = path.join(
CONFIG.repositoryRootPath,
'node_modules',
packageName
);
const testSubdir = ['spec', 'test'].find(subdir =>
fs.existsSync(path.join(repositoryPackagePath, subdir))
);
if (!testSubdir) {
console.log(`No test folder found for package: ${packageName}`.yellow);
continue;
}
const testFolder = path.join(repositoryPackagePath, testSubdir);
const testArguments = [
'--resource-path',
resourcePath,
'--test',
testFolder
];
const pkgJsonPath = path.join(repositoryPackagePath, 'package.json');
const nodeModulesPath = path.join(repositoryPackagePath, 'node_modules');
// the function which runs by async:
packageTestSuites.push(function(callback) {
const testEnv = prepareEnv(`bundled-package-${packageName}`);
let finalize = () => null;
if (require(pkgJsonPath).atomTestRunner) {
console.log(
`##[command] Installing test runner dependencies for ${packageName}`
.bold.green
);
if (fs.existsSync(nodeModulesPath)) {
const backup = backupNodeModules(repositoryPackagePath);
finalize = backup.restore;
} else {
finalize = () => fs.removeSync(nodeModulesPath);
}
runApmInstall(repositoryPackagePath);
console.log(`##[command] Executing ${packageName} tests`.green);
} else {
console.log(`##[command] Executing ${packageName} tests`.bold.green);
}
spawnTest(
executablePath,
testArguments,
{ env: testEnv },
callback,
`${packageName} package`,
finalize
);
});
}
return packageTestSuites;
}
function runBenchmarkTests(callback) {
const benchmarksPath = path.join(CONFIG.repositoryRootPath, 'benchmarks');
const testArguments = ['--benchmark-test', benchmarksPath];
const testEnv = prepareEnv('benchmark');
console.log('##[command] Executing benchmark tests'.bold.green);
spawnTest(
executablePath,
testArguments,
{ stdio: 'inherit', env: testEnv },
callback,
`core-benchmarks`
);
}
let testSuitesToRun = requestedTestSuites(process.platform);
function requestedTestSuites(platform) {
// env variable or argv options
let coreAll = process.env.ATOM_RUN_CORE_TESTS === 'true';
let coreMain =
process.env.ATOM_RUN_CORE_MAIN_TESTS === 'true' || argv.coreMain;
let coreRenderer =
argv.coreRenderer || process.env.ATOM_RUN_CORE_RENDER_TESTS === 'true';
let coreRenderer1 = process.env.ATOM_RUN_CORE_RENDER_TESTS === '1';
let coreRenderer2 = process.env.ATOM_RUN_CORE_RENDER_TESTS === '2';
let packageAll =
argv.package || process.env.ATOM_RUN_PACKAGE_TESTS === 'true';
let packages1 = process.env.ATOM_RUN_PACKAGE_TESTS === '1';
let packages2 = process.env.ATOM_RUN_PACKAGE_TESTS === '2';
let benchmark = argv.coreBenchmark;
// Operating system overrides:
coreMain =
coreMain ||
platform === 'linux' ||
(platform === 'win32' && process.arch === 'x86');
// split package tests (used for macos in CI)
const PACKAGES_TO_TEST_IN_PARALLEL = 23;
// split core render test (used for windows x64 in CI)
const CORE_RENDER_TO_TEST_IN_PARALLEL = 45;
let suites = [];
// Core tess
if (coreAll) {
suites.push(
...[runCoreMainProcessTests, ...getCoreRenderProcessTestSuites()]
);
} else {
// Core main tests
if (coreMain) {
suites.push(runCoreMainProcessTests);
}
// Core renderer tests
if (coreRenderer) {
suites.push(...getCoreRenderProcessTestSuites());
} else {
// split
if (coreRenderer1) {
suites.push(
...getCoreRenderProcessTestSuites().slice(
0,
CORE_RENDER_TO_TEST_IN_PARALLEL
)
);
}
if (coreRenderer2) {
suites.push(
...getCoreRenderProcessTestSuites().slice(
CORE_RENDER_TO_TEST_IN_PARALLEL
)
);
}
}
}
// Package tests
if (packageAll) {
suites.push(...getPackageTestSuites());
} else {
// split
if (packages1) {
suites.push(
...getPackageTestSuites().slice(0, PACKAGES_TO_TEST_IN_PARALLEL)
);
}
if (packages2) {
suites.push(
...getPackageTestSuites().slice(PACKAGES_TO_TEST_IN_PARALLEL)
);
}
}
// Benchmark tests
if (benchmark) {
suites.push(runBenchmarkTests);
}
if (argv.skipMainProcessTests) {
suites = suites.filter(suite => suite !== runCoreMainProcessTests);
}
// Remove duplicates
suites = Array.from(new Set(suites));
if (suites.length === 0) {
throw new Error('No tests was requested');
}
return suites;
}
asyncSeries(testSuitesToRun, function(err, results) {
if (err) {
console.error(err);
process.exit(1);
} else {
const failedSteps = results.filter(({ exitCode }) => exitCode !== 0);
if (failedSteps.length > 0) {
console.warn(
'\n \n ##[error] *** Reporting the errors that happened in all of the tests: *** \n \n'
);
for (const { step, testCommand } of failedSteps) {
console.error(
`##[error] The '${step}' test step finished with a non-zero exit code \n ${testCommand}`
);
}
process.exit(1);
}
process.exit(0);
}
});

16
script/verify-snapshot-script Executable file → Normal file
View File

@ -1,6 +1,10 @@
#!/usr/bin/env node #!/bin/sh
const fs = require('fs') basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
const vm = require('vm')
const snapshotScriptPath = process.argv[2] case `uname` in
const snapshotScript = fs.readFileSync(snapshotScriptPath, 'utf8') *CYGWIN*|*MINGW*|*MSYS*) basedir=`cygpath -w "$basedir"`;;
vm.runInNewContext(snapshotScript, undefined, {filename: snapshotScriptPath, displayErrors: true}) esac
node "$basedir/verify-snapshot-script.js" "$@"
ret=$?
exit $ret

View File

@ -0,0 +1 @@
node "%~dp0\verify-snapshot-script.js" %*

View File

@ -0,0 +1,9 @@
#!/usr/bin/env node
const fs = require('fs');
const vm = require('vm');
const snapshotScriptPath = process.argv[2];
const snapshotScript = fs.readFileSync(snapshotScriptPath, 'utf8');
vm.runInNewContext(snapshotScript, undefined, {
filename: snapshotScriptPath,
displayErrors: true
});