mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-12 19:18:32 -05:00
Merge vscode 1.67 (#20883)
* Fix initial build breaks from 1.67 merge (#2514) * Update yarn lock files * Update build scripts * Fix tsconfig * Build breaks * WIP * Update yarn lock files * Misc breaks * Updates to package.json * Breaks * Update yarn * Fix breaks * Breaks * Build breaks * Breaks * Breaks * Breaks * Breaks * Breaks * Missing file * Breaks * Breaks * Breaks * Breaks * Breaks * Fix several runtime breaks (#2515) * Missing files * Runtime breaks * Fix proxy ordering issue * Remove commented code * Fix breaks with opening query editor * Fix post merge break * Updates related to setup build and other breaks (#2516) * Fix bundle build issues * Update distro * Fix distro merge and update build JS files * Disable pipeline steps * Remove stats call * Update license name * Make new RPM dependencies a warning * Fix extension manager version checks * Update JS file * Fix a few runtime breaks * Fixes * Fix runtime issues * Fix build breaks * Update notebook tests (part 1) * Fix broken tests * Linting errors * Fix hygiene * Disable lint rules * Bump distro * Turn off smoke tests * Disable integration tests * Remove failing "activate" test * Remove failed test assertion * Disable other broken test * Disable query history tests * Disable extension unit tests * Disable failing tasks
This commit is contained in:
@@ -3,9 +3,9 @@
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import minimist = require('minimist');
|
||||
import { Suite, Context } from 'mocha';
|
||||
import { Application, ApplicationOptions } from '../../automation';
|
||||
import { dirname, join } from 'path';
|
||||
import { Application, ApplicationOptions, Logger } from '../../automation';
|
||||
|
||||
export function describeRepeat(n: number, description: string, callback: (this: Suite) => void): void {
|
||||
for (let i = 0; i < n; i++) {
|
||||
@@ -19,32 +19,131 @@ export function itRepeat(n: number, description: string, callback: (this: Contex
|
||||
}
|
||||
}
|
||||
|
||||
export function beforeSuite(opts: minimist.ParsedArgs, optionsTransform?: (opts: ApplicationOptions) => Promise<ApplicationOptions>) {
|
||||
before(async function () {
|
||||
let options: ApplicationOptions = { ...this.defaultOptions };
|
||||
/**
|
||||
* Defines a test-case that will run but will be skips it if it throws an exception. This is useful
|
||||
* to get some runs in CI when trying to stabilize a flaky test, without failing the build. Note
|
||||
* that this only works if something inside the test throws, so a test's overall timeout won't work
|
||||
* but throwing due to a polling timeout will.
|
||||
* @param title The test-case title.
|
||||
* @param callback The test-case callback.
|
||||
*/
|
||||
export function itSkipOnFail(title: string, callback: (this: Context) => any): void {
|
||||
it(title, function () {
|
||||
return Promise.resolve().then(() => {
|
||||
return callback.apply(this, arguments);
|
||||
}).catch(e => {
|
||||
console.warn(`Test "${title}" failed but was marked as skip on fail:`, e);
|
||||
this.skip();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
if (optionsTransform) {
|
||||
options = await optionsTransform(options);
|
||||
export function installAllHandlers(logger: Logger, optionsTransform?: (opts: ApplicationOptions) => ApplicationOptions) {
|
||||
installDiagnosticsHandler(logger);
|
||||
installAppBeforeHandler(optionsTransform);
|
||||
installAppAfterHandler();
|
||||
}
|
||||
|
||||
export function installDiagnosticsHandler(logger: Logger, appFn?: () => Application | undefined) {
|
||||
|
||||
// Before each suite
|
||||
before(async function () {
|
||||
const suiteTitle = this.currentTest?.parent?.title;
|
||||
logger.log('');
|
||||
logger.log(`>>> Suite start: '${suiteTitle ?? 'unknown'}' <<<`);
|
||||
logger.log('');
|
||||
});
|
||||
|
||||
// Before each test
|
||||
beforeEach(async function () {
|
||||
const testTitle = this.currentTest?.title;
|
||||
logger.log('');
|
||||
logger.log(`>>> Test start: '${testTitle ?? 'unknown'}' <<<`);
|
||||
logger.log('');
|
||||
|
||||
const app: Application = appFn?.() ?? this.app;
|
||||
await app?.startTracing(testTitle ?? 'unknown');
|
||||
});
|
||||
|
||||
// After each test
|
||||
afterEach(async function () {
|
||||
const currentTest = this.currentTest;
|
||||
if (!currentTest) {
|
||||
return;
|
||||
}
|
||||
|
||||
// https://github.com/microsoft/vscode/issues/34988
|
||||
const userDataPathSuffix = [...Array(8)].map(() => Math.random().toString(36)[3]).join('');
|
||||
const userDataDir = options.userDataDir.concat(`-${userDataPathSuffix}`);
|
||||
const failed = currentTest.state === 'failed';
|
||||
const testTitle = currentTest.title;
|
||||
logger.log('');
|
||||
if (failed) {
|
||||
logger.log(`>>> !!! FAILURE !!! Test end: '${testTitle}' !!! FAILURE !!! <<<`);
|
||||
} else {
|
||||
logger.log(`>>> Test end: '${testTitle}' <<<`);
|
||||
}
|
||||
logger.log('');
|
||||
|
||||
const app = new Application({ ...options, userDataDir });
|
||||
await app.start();
|
||||
this.app = app;
|
||||
const app: Application = appFn?.() ?? this.app;
|
||||
await app?.stopTracing(testTitle.replace(/[^a-z0-9\-]/ig, '_'), failed);
|
||||
});
|
||||
}
|
||||
|
||||
if (opts.log) {
|
||||
const title = this.currentTest!.fullTitle();
|
||||
app.logger.log('*** Test start:', title);
|
||||
let logsCounter = 1;
|
||||
|
||||
export function suiteLogsPath(options: ApplicationOptions, suiteName: string): string {
|
||||
return join(dirname(options.logsPath), `${logsCounter++}_suite_${suiteName.replace(/[^a-z0-9\-]/ig, '_')}`);
|
||||
}
|
||||
|
||||
function installAppBeforeHandler(optionsTransform?: (opts: ApplicationOptions) => ApplicationOptions) {
|
||||
before(async function () {
|
||||
const suiteName = this.test?.parent?.title ?? 'unknown';
|
||||
|
||||
this.app = createApp({
|
||||
...this.defaultOptions,
|
||||
logsPath: suiteLogsPath(this.defaultOptions, suiteName)
|
||||
}, optionsTransform);
|
||||
await this.app.start();
|
||||
});
|
||||
}
|
||||
|
||||
export function installAppAfterHandler(appFn?: () => Application | undefined, joinFn?: () => Promise<unknown>) {
|
||||
after(async function () {
|
||||
const app: Application = appFn?.() ?? this.app;
|
||||
if (app) {
|
||||
await app.stop();
|
||||
}
|
||||
|
||||
if (joinFn) {
|
||||
await joinFn();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
export function afterSuite(opts: minimist.ParsedArgs) {
|
||||
export function createApp(options: ApplicationOptions, optionsTransform?: (opts: ApplicationOptions) => ApplicationOptions): Application {
|
||||
if (optionsTransform) {
|
||||
options = optionsTransform({ ...options });
|
||||
}
|
||||
|
||||
const app = new Application({
|
||||
...options,
|
||||
userDataDir: getRandomUserDataDir(options)
|
||||
});
|
||||
|
||||
return app;
|
||||
}
|
||||
|
||||
export function getRandomUserDataDir(options: ApplicationOptions): string {
|
||||
|
||||
// Pick a random user data dir suffix that is not
|
||||
// too long to not run into max path length issues
|
||||
// https://github.com/microsoft/vscode/issues/34988
|
||||
const userDataPathSuffix = [...Array(8)].map(() => Math.random().toString(36)[3]).join('');
|
||||
|
||||
return options.userDataDir.concat(`-${userDataPathSuffix}`);
|
||||
}
|
||||
|
||||
export function installCommonAfterHandlers(opts: minimist.ParsedArgs, appFn?: () => Application | undefined, joinFn?: () => Promise<unknown>) {
|
||||
afterEach(async function () {
|
||||
const app = this.app as Application;
|
||||
const app: Application = appFn?.() ?? this.app;
|
||||
|
||||
if (this.currentTest?.state === 'failed' && opts.screenshots) {
|
||||
const name = this.currentTest!.fullTitle().replace(/[^a-z0-9\-]/ig, '_');
|
||||
@@ -62,6 +161,14 @@ export function afterSuite(opts: minimist.ParsedArgs) {
|
||||
if (app) {
|
||||
await app.stop();
|
||||
}
|
||||
|
||||
if (joinFn) {
|
||||
await joinFn();
|
||||
}
|
||||
});
|
||||
|
||||
afterEach(async function () {
|
||||
await this.app?.stopTracing(this.currentTest?.title, this.currentTest?.state === 'failed');
|
||||
});
|
||||
}
|
||||
|
||||
@@ -73,15 +180,44 @@ export function timeout(i: number) {
|
||||
});
|
||||
}
|
||||
|
||||
export async function retryWithRestart(app: Application, testFn: () => Promise<unknown>, retries = 3, timeoutMs = 20000): Promise<unknown> {
|
||||
let lastError: Error | undefined = undefined;
|
||||
for (let i = 0; i < retries; i++) {
|
||||
const result = await Promise.race([
|
||||
testFn().then(() => true, error => {
|
||||
lastError = error;
|
||||
return false;
|
||||
}),
|
||||
timeout(timeoutMs).then(() => false)
|
||||
]);
|
||||
|
||||
if (result) {
|
||||
return;
|
||||
}
|
||||
|
||||
await app.restart();
|
||||
}
|
||||
|
||||
throw lastError ?? new Error('retryWithRestart failed with an unknown error');
|
||||
}
|
||||
|
||||
export interface ITask<T> {
|
||||
(): T;
|
||||
}
|
||||
|
||||
export async function retry<T>(task: ITask<Promise<T>>, delay: number, retries: number): Promise<T> {
|
||||
export async function retry<T>(task: ITask<Promise<T>>, delay: number, retries: number, onBeforeRetry?: () => Promise<unknown>): Promise<T> {
|
||||
let lastError: Error | undefined;
|
||||
|
||||
for (let i = 0; i < retries; i++) {
|
||||
try {
|
||||
if (i > 0 && typeof onBeforeRetry === 'function') {
|
||||
try {
|
||||
await onBeforeRetry();
|
||||
} catch (error) {
|
||||
console.warn(`onBeforeRetry failed with: ${error}`);
|
||||
}
|
||||
}
|
||||
|
||||
return await task();
|
||||
} catch (error) {
|
||||
lastError = error;
|
||||
|
||||
Reference in New Issue
Block a user