mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-17 02:51:36 -05:00
Refresh master with initial release/0.24 snapshot (#332)
* Initial port of release/0.24 source code * Fix additional headers * Fix a typo in launch.json
This commit is contained in:
@@ -3,220 +3,242 @@
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
const fs = require('fs');
|
||||
const https = require('https');
|
||||
const program = require('commander');
|
||||
const git = require('simple-git')();
|
||||
const child_process = require('child_process');
|
||||
const path = require('path');
|
||||
const mkdirp = require('mkdirp');
|
||||
import * as fs from 'fs';
|
||||
import * as https from 'https';
|
||||
import * as cp from 'child_process';
|
||||
import * as path from 'path';
|
||||
import * as minimist from 'minimist';
|
||||
import * as tmp from 'tmp';
|
||||
import * as rimraf from 'rimraf';
|
||||
import * as mkdirp from 'mkdirp';
|
||||
import { SpectronApplication, Quality } from './spectron/application';
|
||||
|
||||
const testDataPath = path.join(process.cwd(), 'test_data');
|
||||
const codeWorkspacePath = path.join(testDataPath, 'smoketest.code-workspace');
|
||||
const testRepoUrl = 'https://github.com/Microsoft/vscode-smoketest-express';
|
||||
const testRepoLocalDir = path.join(testDataPath, 'vscode-smoketest-express');
|
||||
const keybindingsUrl = 'https://raw.githubusercontent.com/Microsoft/vscode-docs/master/scripts/keybindings';
|
||||
const tmpDir = tmp.dirSync({ prefix: 't' }) as { name: string; removeCallback: Function; };
|
||||
const testDataPath = tmpDir.name;
|
||||
process.once('exit', () => rimraf.sync(testDataPath));
|
||||
|
||||
mkdirp.sync(testDataPath);
|
||||
|
||||
program
|
||||
.option('-l, --latest <file path>', 'path to the latest VS Code to test')
|
||||
.option('-s, --stable [file path]', 'path to the stable VS Code to be used in data migration tests');
|
||||
|
||||
program.on('--help', () => {
|
||||
console.log(' Examples:');
|
||||
console.log('');
|
||||
console.log(' $ npm test -- --latest path/to/binary');
|
||||
console.log(' $ npm test -- -l path/to/binary');
|
||||
console.log('');
|
||||
console.log(' $ npm test -- --latest path/to/latest/binary --stable path/to/stable/binary');
|
||||
console.log(' $ npm test -- -l path/to/latest/binary -s path/to/stable/binary');
|
||||
console.log('');
|
||||
const [, , ...args] = process.argv;
|
||||
const opts = minimist(args, {
|
||||
string: [
|
||||
'build',
|
||||
'stable-build',
|
||||
'log',
|
||||
'wait-time'
|
||||
]
|
||||
});
|
||||
program.parse(process.argv);
|
||||
|
||||
if (!program.latest) {
|
||||
fail('You must specify the binary to run the smoke test against');
|
||||
}
|
||||
if (!binaryExists(program.latest) || (program.stable && !binaryExists(program.stable))) {
|
||||
fail('The file path to electron binary does not exist or permissions do not allow to execute it. Please check the path provided.');
|
||||
}
|
||||
if (parseInt(process.version.substr(1)) < 6) {
|
||||
fail('Please update your Node version to greater than 6 to run the smoke test.');
|
||||
}
|
||||
const artifactsPath = opts.log || '';
|
||||
|
||||
// Setting up environment variables
|
||||
process.env.VSCODE_LATEST_PATH = program.latest;
|
||||
if (program.stable) {
|
||||
process.env.VSCODE_STABLE_PATH = program.stable;
|
||||
}
|
||||
process.env.SMOKETEST_REPO = testRepoLocalDir;
|
||||
if (program.latest && (program.latest.indexOf('Code - Insiders') /* macOS/Windows */ || program.latest.indexOf('code-insiders') /* Linux */) >= 0) {
|
||||
process.env.VSCODE_EDITION = 'insiders';
|
||||
}
|
||||
process.env.VSCODE_WORKSPACE_PATH = codeWorkspacePath;
|
||||
|
||||
// Setting up 'vscode-smoketest-express' project
|
||||
let os = process.platform.toString();
|
||||
if (os === 'darwin') {
|
||||
os = 'osx';
|
||||
}
|
||||
else if (os === 'win32') {
|
||||
os = 'win';
|
||||
}
|
||||
|
||||
main().catch(err => console.error(err));
|
||||
|
||||
async function main(): Promise<void> {
|
||||
await getKeybindings(`${keybindingsUrl}/doc.keybindings.${os}.json`, path.join(testDataPath, 'keybindings.json'));
|
||||
|
||||
const workspace = {
|
||||
id: (Date.now() + Math.round(Math.random() * 1000)).toString(),
|
||||
folders: [
|
||||
toUri(path.join(testRepoLocalDir, 'public')),
|
||||
toUri(path.join(testRepoLocalDir, 'routes')),
|
||||
toUri(path.join(testRepoLocalDir, 'views'))
|
||||
]
|
||||
};
|
||||
|
||||
await createWorkspaceFile(codeWorkspacePath, workspace);
|
||||
await cleanOrClone(testRepoUrl, testRepoLocalDir);
|
||||
await execute('npm install', testRepoLocalDir);
|
||||
await runTests();
|
||||
}
|
||||
const workspaceFilePath = path.join(testDataPath, 'smoketest.code-workspace');
|
||||
const testRepoUrl = 'https://github.com/Microsoft/vscode-smoketest-express';
|
||||
const workspacePath = path.join(testDataPath, 'vscode-smoketest-express');
|
||||
const keybindingsPath = path.join(testDataPath, 'keybindings.json');
|
||||
const extensionsPath = path.join(testDataPath, 'extensions-dir');
|
||||
mkdirp.sync(extensionsPath);
|
||||
|
||||
function fail(errorMessage): void {
|
||||
console.error(errorMessage);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
if (parseInt(process.version.substr(1)) < 6) {
|
||||
fail('Please update your Node version to greater than 6 to run the smoke test.');
|
||||
}
|
||||
|
||||
const repoPath = path.join(__dirname, '..', '..', '..');
|
||||
|
||||
function getDevElectronPath(): string {
|
||||
const buildPath = path.join(repoPath, '.build');
|
||||
const product = require(path.join(repoPath, 'product.json'));
|
||||
|
||||
switch (process.platform) {
|
||||
case 'darwin':
|
||||
return path.join(buildPath, 'electron', `${product.nameLong}.app`, 'Contents', 'MacOS', 'Electron');
|
||||
case 'linux':
|
||||
return path.join(buildPath, 'electron', `${product.applicationName}`);
|
||||
case 'win32':
|
||||
return path.join(buildPath, 'electron', `${product.nameShort}.exe`);
|
||||
default:
|
||||
throw new Error('Unsupported platform.');
|
||||
}
|
||||
}
|
||||
|
||||
function getBuildElectronPath(root: string): string {
|
||||
switch (process.platform) {
|
||||
case 'darwin':
|
||||
return path.join(root, 'Contents', 'MacOS', 'Electron');
|
||||
case 'linux': {
|
||||
const product = require(path.join(root, 'resources', 'app', 'product.json'));
|
||||
return path.join(root, product.applicationName);
|
||||
}
|
||||
case 'win32': {
|
||||
const product = require(path.join(root, 'resources', 'app', 'product.json'));
|
||||
return path.join(root, `${product.nameShort}.exe`);
|
||||
}
|
||||
default:
|
||||
throw new Error('Unsupported platform.');
|
||||
}
|
||||
}
|
||||
|
||||
let testCodePath = opts.build;
|
||||
let stableCodePath = opts['stable-build'];
|
||||
let electronPath: string;
|
||||
|
||||
if (testCodePath) {
|
||||
electronPath = getBuildElectronPath(testCodePath);
|
||||
|
||||
if (stableCodePath) {
|
||||
process.env.VSCODE_STABLE_PATH = getBuildElectronPath(stableCodePath);
|
||||
}
|
||||
} else {
|
||||
testCodePath = getDevElectronPath();
|
||||
electronPath = testCodePath;
|
||||
process.env.VSCODE_REPOSITORY = repoPath;
|
||||
process.env.VSCODE_DEV = '1';
|
||||
process.env.VSCODE_CLI = '1';
|
||||
}
|
||||
|
||||
if (!fs.existsSync(electronPath || '')) {
|
||||
fail(`Can't find Code at ${electronPath}.`);
|
||||
}
|
||||
|
||||
const userDataDir = path.join(testDataPath, 'd');
|
||||
// process.env.VSCODE_WORKSPACE_PATH = workspaceFilePath;
|
||||
process.env.VSCODE_KEYBINDINGS_PATH = keybindingsPath;
|
||||
|
||||
let quality: Quality;
|
||||
if (process.env.VSCODE_DEV === '1') {
|
||||
quality = Quality.Dev;
|
||||
} else if ((testCodePath.indexOf('Code - Insiders') /* macOS/Windows */ || testCodePath.indexOf('code-insiders') /* Linux */) >= 0) {
|
||||
quality = Quality.Insiders;
|
||||
} else {
|
||||
quality = Quality.Stable;
|
||||
}
|
||||
|
||||
function getKeybindingPlatform(): string {
|
||||
switch (process.platform) {
|
||||
case 'darwin': return 'osx';
|
||||
case 'win32': return 'win';
|
||||
default: return process.platform;
|
||||
}
|
||||
}
|
||||
|
||||
function toUri(path: string): string {
|
||||
if (os === 'win') {
|
||||
return `file:///${path.replace(/\\/g, '/')}`;
|
||||
if (process.platform === 'win32') {
|
||||
return `${path.replace(/\\/g, '/')}`;
|
||||
}
|
||||
|
||||
return `file://${path}`;
|
||||
return `${path}`;
|
||||
}
|
||||
|
||||
function runTests(): void {
|
||||
console.log('Running tests...');
|
||||
var proc = child_process.spawn(process.execPath, [
|
||||
'out/mocha-runner.js'
|
||||
]);
|
||||
proc.stdout.on('data', data => {
|
||||
console.log(data.toString());
|
||||
async function setup(): Promise<void> {
|
||||
console.log('*** Test data:', testDataPath);
|
||||
console.log('*** Preparing smoketest setup...');
|
||||
|
||||
const keybindingsUrl = `https://raw.githubusercontent.com/Microsoft/vscode-docs/master/scripts/keybindings/doc.keybindings.${getKeybindingPlatform()}.json`;
|
||||
console.log('*** Fetching keybindings...');
|
||||
|
||||
await new Promise((c, e) => {
|
||||
https.get(keybindingsUrl, res => {
|
||||
const output = fs.createWriteStream(keybindingsPath);
|
||||
res.on('error', e);
|
||||
output.on('error', e);
|
||||
output.on('close', c);
|
||||
res.pipe(output);
|
||||
}).on('error', e);
|
||||
});
|
||||
proc.stderr.on('data', data => {
|
||||
var date = new Date().toLocaleString();
|
||||
fs.appendFile(path.join(testDataPath, 'errors.log'), `${date}: ${data.toString()}`, (err) => {
|
||||
if (err) {
|
||||
throw new Error(`Could not write stderr to errors.log with the following error: ${err}`);
|
||||
};
|
||||
});
|
||||
});
|
||||
proc.on('exit', (code) => {
|
||||
process.exit(code);
|
||||
});
|
||||
}
|
||||
|
||||
async function cleanOrClone(repo: string, dir: string): Promise<any> {
|
||||
console.log('Cleaning or cloning test project repository...');
|
||||
|
||||
if (!folderExists(dir)) {
|
||||
await gitClone(repo, dir);
|
||||
} else {
|
||||
git.cwd(dir);
|
||||
await new Promise((c, e) => git.fetch(err => err ? e(err) : c()));
|
||||
await gitResetAndClean();
|
||||
}
|
||||
}
|
||||
|
||||
function gitClone(repo: string, dir: string): Promise<any> {
|
||||
return new Promise((res, rej) => {
|
||||
git.clone(repo, dir, () => {
|
||||
console.log('Test repository successfully cloned.');
|
||||
res();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
async function gitResetAndClean(): Promise<any> {
|
||||
await new Promise((c, e) => git.reset(['FETCH_HEAD', '--hard'], err => err ? e(err) : c()));
|
||||
await new Promise((c, e) => git.clean('f', ['-d'], err => err ? e(err) : c()));
|
||||
console.log('Test project was successfully reset to initial state.');
|
||||
}
|
||||
|
||||
function execute(cmd: string, dir: string): Promise<any> {
|
||||
return new Promise((res, rej) => {
|
||||
console.log(`Running ${cmd}...`);
|
||||
child_process.exec(cmd, { cwd: dir, stdio: [0, 1, 2] }, (error, stdout, stderr) => {
|
||||
if (error) {
|
||||
rej(error);
|
||||
}
|
||||
if (stderr) {
|
||||
console.error(stderr);
|
||||
}
|
||||
console.log(stdout);
|
||||
res();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function getKeybindings(url: string, location: string): Promise<any> {
|
||||
console.log(`Fetching keybindings from ${url}...`);
|
||||
return new Promise((resolve, reject) => {
|
||||
https.get(url, (res) => {
|
||||
if (res.statusCode !== 200) {
|
||||
reject(`Failed to obtain key bindings with response code: ${res.statusCode}`);
|
||||
}
|
||||
|
||||
var buffer: Buffer[] = [];
|
||||
res.on('data', (chunk) => buffer.push(chunk));
|
||||
res.on('end', () => {
|
||||
fs.writeFile(location, Buffer.concat(buffer), 'utf8', () => {
|
||||
console.log('Keybindings were successfully fetched.');
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
}).on('error', (e) => {
|
||||
reject(`Failed to obtain key bindings with an error: ${e}`);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function createWorkspaceFile(path: string, workspace: any): Promise<any> {
|
||||
console.log(`Creating workspace file at ${path}...`);
|
||||
return new Promise((resolve, reject) => {
|
||||
fs.exists(path, exists => {
|
||||
if (exists) {
|
||||
return resolve();
|
||||
}
|
||||
|
||||
fs.writeFile(path, JSON.stringify(workspace, null, '\t'), error => {
|
||||
if (error) {
|
||||
reject(error);
|
||||
} else {
|
||||
resolve();
|
||||
if (!fs.existsSync(workspaceFilePath)) {
|
||||
console.log('*** Creating workspace file...');
|
||||
const workspace = {
|
||||
folders: [
|
||||
{
|
||||
path: toUri(path.join(workspacePath, 'public'))
|
||||
},
|
||||
{
|
||||
path: toUri(path.join(workspacePath, 'routes'))
|
||||
},
|
||||
{
|
||||
path: toUri(path.join(workspacePath, 'views'))
|
||||
}
|
||||
});
|
||||
});
|
||||
]
|
||||
};
|
||||
|
||||
fs.writeFileSync(workspaceFilePath, JSON.stringify(workspace, null, '\t'));
|
||||
}
|
||||
|
||||
if (!fs.existsSync(workspacePath)) {
|
||||
console.log('*** Cloning test project repository...');
|
||||
cp.spawnSync('git', ['clone', testRepoUrl, workspacePath]);
|
||||
} else {
|
||||
console.log('*** Cleaning test project repository...');
|
||||
cp.spawnSync('git', ['fetch'], { cwd: workspacePath });
|
||||
cp.spawnSync('git', ['reset', '--hard', 'FETCH_HEAD'], { cwd: workspacePath });
|
||||
cp.spawnSync('git', ['clean', '-xdf'], { cwd: workspacePath });
|
||||
}
|
||||
|
||||
console.log('*** Running npm install...');
|
||||
cp.execSync('npm install', { cwd: workspacePath, stdio: 'inherit' });
|
||||
|
||||
console.log('*** Smoketest setup done!\n');
|
||||
}
|
||||
|
||||
/**
|
||||
* WebDriverIO 4.8.0 outputs all kinds of "deprecation" warnings
|
||||
* for common commands like `keys` and `moveToObject`.
|
||||
* According to https://github.com/Codeception/CodeceptJS/issues/531,
|
||||
* these deprecation warnings are for Firefox, and have no alternative replacements.
|
||||
* Since we can't downgrade WDIO as suggested (it's Spectron's dep, not ours),
|
||||
* we must suppress the warning with a classic monkey-patch.
|
||||
*
|
||||
* @see webdriverio/lib/helpers/depcrecationWarning.js
|
||||
* @see https://github.com/webdriverio/webdriverio/issues/2076
|
||||
*/
|
||||
// Filter out the following messages:
|
||||
const wdioDeprecationWarning = /^WARNING: the "\w+" command will be depcrecated soon./; // [sic]
|
||||
// Monkey patch:
|
||||
const warn = console.warn;
|
||||
console.warn = function suppressWebdriverWarnings(message) {
|
||||
if (wdioDeprecationWarning.test(message)) { return; }
|
||||
warn.apply(console, arguments);
|
||||
};
|
||||
|
||||
before(async function () {
|
||||
// allow two minutes for setup
|
||||
this.timeout(2 * 60 * 1000);
|
||||
await setup();
|
||||
|
||||
const app = new SpectronApplication({
|
||||
quality,
|
||||
electronPath,
|
||||
workspacePath,
|
||||
userDataDir,
|
||||
extensionsPath,
|
||||
artifactsPath,
|
||||
workspaceFilePath,
|
||||
waitTime: parseInt(opts['wait-time'] || '0') || 20
|
||||
});
|
||||
}
|
||||
|
||||
function folderExists(folder: string): boolean {
|
||||
try {
|
||||
fs.accessSync(folder, 'rw');
|
||||
return true;
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
await app.start();
|
||||
this.app = app;
|
||||
});
|
||||
|
||||
function binaryExists(filePath: string): boolean {
|
||||
try {
|
||||
fs.accessSync(filePath, 'x');
|
||||
return true;
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
after(async function () {
|
||||
await this.app.stop();
|
||||
await new Promise((c, e) => rimraf(testDataPath, { maxBusyTries: 10 }, err => err ? e(err) : c()));
|
||||
});
|
||||
|
||||
// import './areas/workbench/data-migration.test';
|
||||
import './areas/workbench/data-loss.test';
|
||||
import './areas/explorer/explorer.test';
|
||||
import './areas/preferences/preferences.test';
|
||||
import './areas/search/search.test';
|
||||
import './areas/css/css.test';
|
||||
import './areas/editor/editor.test';
|
||||
import './areas/debug/debug.test';
|
||||
import './areas/git/git.test';
|
||||
// import './areas/terminal/terminal.test';
|
||||
import './areas/statusbar/statusbar.test';
|
||||
import './areas/extensions/extensions.test';
|
||||
import './areas/multiroot/multiroot.test';
|
||||
import './areas/workbench/localization.test';
|
||||
Reference in New Issue
Block a user