diff --git a/.gitignore b/.gitignore index 8229cf2d9f..a2bb29b96d 100644 --- a/.gitignore +++ b/.gitignore @@ -9,3 +9,6 @@ out install.* *.vsix + +obj/ +bin/ diff --git a/.travis.yml b/.travis.yml index ff571682bd..00d04dd15b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -14,9 +14,12 @@ addons: apt: sources: - ubuntu-toolchain-r-test + - sourceline: 'deb https://packages.microsoft.com/repos/microsoft-ubuntu-trusty-prod trusty main' + key_url: 'https://packages.microsoft.com/keys/microsoft.asc' packages: - g++-4.9 - libsecret-1-dev + - dotnet-sdk-2.0.2 install: - npm install diff --git a/.vscode/launch.json b/.vscode/launch.json index b89fcb9578..c094fe619c 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -16,11 +16,46 @@ ] }, { - "name": "Launch Tests", + "name": "Launch Unit Tests", "type": "extensionHost", "request": "launch", "runtimeExecutable": "${execPath}", - "args": ["--extensionDevelopmentPath=${workspaceRoot}", "--extensionTestsPath=${workspaceRoot}/out/test" ], + "args": [ + "--extensionDevelopmentPath=${workspaceRoot}", + "--extensionTestsPath=${workspaceRoot}/out/test/unitTests" + ], + "stopOnEntry": false, + "sourceMaps": true, + "outFiles": [ + "${workspaceRoot}/out/test/**/*.js" + ] + }, + { + "name": "Launch singleCsproj Workspace Tests", + "type": "extensionHost", + "request": "launch", + "runtimeExecutable": "${execPath}", + "args": [ + "${workspaceRoot}/test/integrationTests/testAssets/singleCsproj", + "--extensionDevelopmentPath=${workspaceRoot}", + "--extensionTestsPath=${workspaceRoot}/out/test/integrationTests" + ], + "stopOnEntry": false, + "sourceMaps": true, + "outFiles": [ + "${workspaceRoot}/out/test/**/*.js" + ] + }, + { + "name": "Launch slnWithCsproj Workspace Tests", + "type": "extensionHost", + "request": "launch", + "runtimeExecutable": "${execPath}", + "args": [ + "${workspaceRoot}/test/integrationTests/testAssets/slnWithCsproj", + "--extensionDevelopmentPath=${workspaceRoot}", + "--extensionTestsPath=${workspaceRoot}/out/test/integrationTests" + ], "stopOnEntry": false, "sourceMaps": true, "outFiles": [ @@ -28,4 +63,4 @@ ] } ] -} \ No newline at end of file +} diff --git a/.vscode/settings.json b/.vscode/settings.json index e438260534..5095069000 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -11,6 +11,8 @@ "**/node_modules": true, "out/": true }, + + "csharp.suppressDotnetRestoreNotification": true, "tslint.rulesDirectory": "node_modules/tslint-microsoft-contrib", "typescript.tsdk": "./node_modules/typescript/lib" diff --git a/package.json b/package.json index 959705d77a..7fd35fa6e4 100644 --- a/package.json +++ b/package.json @@ -26,7 +26,13 @@ "vscode:prepublish": "tsc -p ./", "compile": "tsc -p ./ && gulp tslint", "watch": "tsc -watch -p ./", - "test": "node ./node_modules/vscode/bin/test", + "test": "npm-run-all test:unit test:integration", + "test:unit": "cross-env CODE_TESTS_PATH=./out/test/unitTests npm run test:runInVsCode", + "test:integration": "npm-run-all test:integration:*", + "test:integration:singleCsproj": "cross-env OSVC_SUITE=singleCsproj npm run test:runSuiteInVsCode", + "test:integration:slnWithCsproj": "cross-env OSVC_SUITE=slnWithCsproj npm run test:runSuiteInVsCode", + "test:runSuiteInVsCode": "cross-env CODE_TESTS_PATH=./out/test/integrationTests CODE_TESTS_WORKSPACE=./test/integrationTests/testAssets/$OSVC_SUITE npm run test:runInVsCode", + "test:runInVsCode": "node ./test/runVsCodeTestsWithAbsolutePaths.js", "postinstall": "node ./node_modules/vscode/bin/install" }, "dependencies": { @@ -46,18 +52,24 @@ }, "devDependencies": { "@types/chai": "^3.4.34", + "@types/chai-arrays": "^1.0.2", "@types/fs-extra": "4.0.3", "@types/mkdirp": "^0.3.29", "@types/mocha": "^2.2.32", "@types/node": "^6.0.40", "@types/semver": "^5.3.30", "@types/tmp": "0.0.32", + "async-file": "^2.0.2", "chai": "^3.5.0", + "chai-arrays": "^2.0.0", + "chai-fs": "^1.0.0", + "cross-env": "^5.1.1", "del": "^2.0.2", "gulp": "^3.9.1", "gulp-mocha": "^2.1.3", "gulp-tslint": "^4.3.0", "mocha": "^2.3.3", + "npm-run-all": "^4.1.1", "plist": "^2.0.1", "tslint": "^3.15.1", "tslint-microsoft-contrib": "^2.0.12", diff --git a/src/assets.ts b/src/assets.ts index 4a26cc8f0a..0efce2f484 100644 --- a/src/assets.ts +++ b/src/assets.ts @@ -5,16 +5,17 @@ import * as fs from 'fs-extra'; import * as path from 'path'; -import * as vscode from 'vscode'; +import * as protocol from './omnisharp/protocol'; +import * as serverUtils from './omnisharp/utils'; import * as tasks from 'vscode-tasks'; +import * as util from './common'; +import * as vscode from 'vscode'; + import { OmniSharpServer } from './omnisharp/server'; -import * as serverUtils from './omnisharp/utils'; -import * as protocol from './omnisharp/protocol'; import { tolerantParse } from './json'; -import * as util from './common'; export class AssetGenerator { - public rootPath: string; + public workspaceFolder: vscode.WorkspaceFolder; public vscodeFolder: string; public tasksJsonPath: string; public launchJsonPath: string; @@ -26,13 +27,33 @@ export class AssetGenerator { private executableName: string; private configurationName: string; - public constructor(workspaceInfo: protocol.WorkspaceInformationResponse, rootPath: string = vscode.workspace.rootPath) { - if (rootPath === null || rootPath === undefined) { - throw new Error('rootPath must set.'); + public constructor(workspaceInfo: protocol.WorkspaceInformationResponse, workspaceFolder: vscode.WorkspaceFolder = undefined) { + if (workspaceFolder) { + this.workspaceFolder = workspaceFolder; } + else { + let resourcePath: string = undefined; + + if (!resourcePath && workspaceInfo.Cake) { + resourcePath = workspaceInfo.Cake.Path; + } - this.rootPath = rootPath; - this.vscodeFolder = path.join(this.rootPath, '.vscode'); + if (!resourcePath && workspaceInfo.ScriptCs) { + resourcePath = workspaceInfo.ScriptCs.Path; + } + + if (!resourcePath && workspaceInfo.DotNet && workspaceInfo.DotNet.Projects.length > 0) { + resourcePath = workspaceInfo.DotNet.Projects[0].Path; + } + + if (!resourcePath && workspaceInfo.MsBuild) { + resourcePath = workspaceInfo.MsBuild.SolutionPath; + } + + this.workspaceFolder = vscode.workspace.getWorkspaceFolder(vscode.Uri.file(resourcePath)); + } + + this.vscodeFolder = path.join(this.workspaceFolder.uri.fsPath, '.vscode'); this.tasksJsonPath = path.join(this.vscodeFolder, 'tasks.json'); this.launchJsonPath = path.join(this.vscodeFolder, 'launch.json'); @@ -132,7 +153,7 @@ export class AssetGenerator { let result = '${workspaceFolder}'; if (this.projectPath) { - result = path.join(result, path.relative(this.rootPath, this.projectPath)); + result = path.join(result, path.relative(this.workspaceFolder.uri.fsPath, this.projectPath)); } result = path.join(result, `bin/${this.configurationName}/${this.targetFramework}/${this.executableName}`); @@ -140,7 +161,7 @@ export class AssetGenerator { return result; } - private computeWorkingDirectory() : string { + private computeWorkingDirectory(): string { if (!this.hasProject) { // If there's no target project data, use a placeholder for the path. return '${workspaceFolder}'; @@ -149,7 +170,7 @@ export class AssetGenerator { let result = '${workspaceFolder}'; if (this.projectPath) { - result = path.join(result, path.relative(this.rootPath, this.projectPath)); + result = path.join(result, path.relative(this.workspaceFolder.uri.fsPath, this.projectPath)); } return result; @@ -179,7 +200,7 @@ export class AssetGenerator { private createBuildTaskDescription(): tasks.TaskDescription { let buildPath = ''; if (this.hasProject) { - buildPath = path.join('${workspaceFolder}', path.relative(this.rootPath, this.projectFilePath)); + buildPath = path.join('${workspaceFolder}', path.relative(this.workspaceFolder.uri.fsPath, this.projectFilePath)); } return { @@ -235,7 +256,7 @@ export function createWebLaunchConfiguration(programPath: string, workingDirecto }`; } - export function createLaunchConfiguration(programPath: string, workingDirectory: string): string { +export function createLaunchConfiguration(programPath: string, workingDirectory: string): string { return ` { "name": ".NET Core Launch (console)", @@ -378,13 +399,13 @@ interface PromptItem extends vscode.MessageItem { result: PromptResult; } -function promptToAddAssets() { +function promptToAddAssets(workspaceFolder: vscode.WorkspaceFolder) { return new Promise((resolve, reject) => { const yesItem: PromptItem = { title: 'Yes', result: PromptResult.Yes }; const noItem: PromptItem = { title: 'Not Now', result: PromptResult.No, isCloseAffordance: true }; const disableItem: PromptItem = { title: "Don't Ask Again", result: PromptResult.Disable }; - const projectName = path.basename(vscode.workspace.rootPath); + const projectName = path.basename(workspaceFolder.uri.fsPath); vscode.window.showWarningMessage( `Required assets to build and debug are missing from '${projectName}'. Add them?`, disableItem, noItem, yesItem) @@ -463,7 +484,7 @@ export enum AddAssetResult { export function addAssetsIfNecessary(server: OmniSharpServer): Promise { return new Promise((resolve, reject) => { - if (!vscode.workspace.rootPath) { + if (!vscode.workspace.workspaceFolders) { return resolve(AddAssetResult.NotApplicable); } @@ -476,7 +497,7 @@ export function addAssetsIfNecessary(server: OmniSharpServer): Promise { + promptToAddAssets(generator.workspaceFolder).then(result => { if (result === PromptResult.Disable) { return resolve(AddAssetResult.Disable); } @@ -546,24 +567,20 @@ function shouldGenerateAssets(generator: AssetGenerator) { }); } -export function generateAssets(server: OmniSharpServer) { - serverUtils.requestWorkspaceInformation(server).then(info => { - if (protocol.containsDotNetCoreProjects(info)) { - const generator = new AssetGenerator(info); - getOperations(generator).then(operations => { - if (hasAddOperations(operations)) { - shouldGenerateAssets(generator).then(res => { - if (res) { - fs.ensureDir(generator.vscodeFolder, err => { - addAssets(generator, operations); - }); - } - }); - } - }); - } - else { - vscode.window.showErrorMessage("Could not locate .NET Core project. Assets were not generated."); +export async function generateAssets(server: OmniSharpServer) { + let workspaceInformation = await serverUtils.requestWorkspaceInformation(server); + if (protocol.containsDotNetCoreProjects(workspaceInformation)) { + const generator = new AssetGenerator(workspaceInformation); + let operations = await getOperations(generator); + if (hasAddOperations(operations)) { + let doGenerateAssets = await shouldGenerateAssets(generator); + if (doGenerateAssets) { + await fs.ensureDir(generator.vscodeFolder); + await addAssets(generator, operations); + } } - }); + } + else { + await vscode.window.showErrorMessage("Could not locate .NET Core project. Assets were not generated."); + } } diff --git a/src/configurationProvider.ts b/src/configurationProvider.ts index d4dcdea569..34edf902e7 100644 --- a/src/configurationProvider.ts +++ b/src/configurationProvider.ts @@ -3,15 +3,17 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import * as vscode from 'vscode'; import * as fs from 'fs-extra'; import * as path from 'path'; -import { parse } from 'jsonc-parser'; -import { OmniSharpServer } from './omnisharp/server'; import * as serverUtils from './omnisharp/utils'; +import * as vscode from 'vscode'; + +import { AssetGenerator, addTasksJsonIfNecessary, createAttachConfiguration, createLaunchConfiguration, createWebLaunchConfiguration } from './assets'; + +import { OmniSharpServer } from './omnisharp/server'; import { containsDotNetCoreProjects } from './omnisharp/protocol'; -import { AssetGenerator, addTasksJsonIfNecessary, createLaunchConfiguration, createAttachConfiguration, createWebLaunchConfiguration } from './assets'; import { isSubfolderOf } from './common'; +import { parse } from 'jsonc-parser'; export class CSharpConfigurationProvider implements vscode.DebugConfigurationProvider { private server: OmniSharpServer; @@ -101,7 +103,7 @@ export class CSharpConfigurationProvider implements vscode.DebugConfigurationPro /** * Try to add all missing attributes to the debug configuration being launched. */ - resolveDebugConfiguration(folder: vscode.WorkspaceFolder | undefined, config: vscode.DebugConfiguration, token?: vscode.CancellationToken): vscode.ProviderResult { + resolveDebugConfiguration(folder: vscode.WorkspaceFolder | undefined, config: vscode.DebugConfiguration, token?: vscode.CancellationToken): vscode.ProviderResult { // vsdbg does the error checking return config; } diff --git a/src/coreclr-debug/activate.ts b/src/coreclr-debug/activate.ts index 9a3bfc603a..455dc7b30c 100644 --- a/src/coreclr-debug/activate.ts +++ b/src/coreclr-debug/activate.ts @@ -4,40 +4,49 @@ *--------------------------------------------------------------------------------------------*/ 'use strict'; -import * as vscode from 'vscode'; +import * as debugInstall from './install'; import * as os from 'os'; -import TelemetryReporter from 'vscode-extension-telemetry'; +import * as vscode from 'vscode'; + import { CoreClrDebugUtil, DotnetInfo, } from './util'; -import * as debugInstall from './install'; + import { Logger } from './../logger'; import { PlatformInformation } from './../platform'; +import TelemetryReporter from 'vscode-extension-telemetry'; let _debugUtil: CoreClrDebugUtil = null; let _reporter: TelemetryReporter = null; let _logger: Logger = null; -export function activate(thisExtension : vscode.Extension, context: vscode.ExtensionContext, reporter: TelemetryReporter, logger: Logger, channel: vscode.OutputChannel) { +export async function activate(thisExtension : vscode.Extension, context: vscode.ExtensionContext, reporter: TelemetryReporter, logger: Logger, channel: vscode.OutputChannel) { _debugUtil = new CoreClrDebugUtil(context.extensionPath, logger); _reporter = reporter; _logger = logger; if (!CoreClrDebugUtil.existsSync(_debugUtil.debugAdapterDir())) { - PlatformInformation.GetCurrent().then((info) => { - if (info.architecture !== "x86_64") { - if (info.isWindows() && info.architecture === "x86") { + let platformInformation: PlatformInformation; + + try { + platformInformation = await PlatformInformation.GetCurrent(); + } + catch (err) { + // Somehow we couldn't figure out the platform we are on + logger.appendLine("[ERROR]: C# Extension failed to install the debugger package"); + showInstallErrorMessage(channel); + } + + if (platformInformation) { + if (platformInformation.architecture !== "x86_64") { + if (platformInformation.isWindows() && platformInformation.architecture === "x86") { logger.appendLine(`[WARNING]: x86 Windows is not currently supported by the .NET Core debugger. Debugging will not be available.`); } else { - logger.appendLine(`[WARNING]: Processor architecture '${info.architecture}' is not currently supported by the .NET Core debugger. Debugging will not be available.`); + logger.appendLine(`[WARNING]: Processor architecture '${platformInformation.architecture}' is not currently supported by the .NET Core debugger. Debugging will not be available.`); } } else { logger.appendLine("[ERROR]: C# Extension failed to install the debugger package"); showInstallErrorMessage(channel); } - }, (err) => { - // Somehow we couldn't figure out the platform we are on - logger.appendLine("[ERROR]: C# Extension failed to install the debugger package"); - showInstallErrorMessage(channel); - }); + } } else if (!CoreClrDebugUtil.existsSync(_debugUtil.installCompleteFilePath())) { completeDebuggerInstall(logger, channel); } diff --git a/src/features/definitionMetadataDocumentProvider.ts b/src/features/definitionMetadataDocumentProvider.ts index f9a337da12..e4cb4545d9 100644 --- a/src/features/definitionMetadataDocumentProvider.ts +++ b/src/features/definitionMetadataDocumentProvider.ts @@ -1,4 +1,10 @@ -import { workspace, Uri, TextDocument, Disposable, TextDocumentContentProvider} from 'vscode'; +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { Disposable, TextDocument, TextDocumentContentProvider, Uri, workspace } from 'vscode'; + import { MetadataResponse } from '../omnisharp/protocol'; export default class DefinitionMetadataDocumentProvider implements TextDocumentContentProvider, Disposable { diff --git a/src/main.ts b/src/main.ts index bc862ac331..fc0b95c35b 100644 --- a/src/main.ts +++ b/src/main.ts @@ -3,19 +3,19 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import * as vscode from 'vscode'; -import TelemetryReporter from 'vscode-extension-telemetry'; - -import * as coreclrdebug from './coreclr-debug/activate'; import * as OmniSharp from './omnisharp/extension'; +import * as coreclrdebug from './coreclr-debug/activate'; import * as util from './common'; -import { Logger } from './logger'; +import * as vscode from 'vscode'; + import { CSharpExtDownloader } from './CSharpExtDownloader'; +import { Logger } from './logger'; +import TelemetryReporter from 'vscode-extension-telemetry'; import { addJSONProviders } from './features/json/jsonContributions'; let _channel: vscode.OutputChannel = null; -export function activate(context: vscode.ExtensionContext): any { +export async function activate(context: vscode.ExtensionContext): Promise<{ initializationFinished: Promise }> { const extensionId = 'ms-vscode.csharp'; const extension = vscode.extensions.getExtension(extensionId); @@ -29,19 +29,24 @@ export function activate(context: vscode.ExtensionContext): any { let logger = new Logger(text => _channel.append(text)); - ensureRuntimeDependencies(extension, logger, reporter) - .then((success : boolean) => { - // activate language services - OmniSharp.activate(context, reporter, _channel); - - // register JSON completion & hover providers for project.json - context.subscriptions.push(addJSONProviders()); - - if (success) { - // activate coreclr-debug - coreclrdebug.activate(extension, context, reporter, logger, _channel); - } - }); + let runtimeDependenciesExist = await ensureRuntimeDependencies(extension, logger, reporter); + + // activate language services + let omniSharpPromise = OmniSharp.activate(context, reporter, _channel); + + // register JSON completion & hover providers for project.json + context.subscriptions.push(addJSONProviders()); + + let coreClrDebugPromise = Promise.resolve(); + if (runtimeDependenciesExist) { + // activate coreclr-debug + coreClrDebugPromise = coreclrdebug.activate(extension, context, reporter, logger, _channel); + } + + return { + initializationFinished: Promise.all([omniSharpPromise, coreClrDebugPromise]) + .then(a => {}) + }; } function ensureRuntimeDependencies(extension: vscode.Extension, logger: Logger, reporter: TelemetryReporter): Promise { diff --git a/src/omnisharp/extension.ts b/src/omnisharp/extension.ts index f415e637fb..41a3a75ff4 100644 --- a/src/omnisharp/extension.ts +++ b/src/omnisharp/extension.ts @@ -3,34 +3,35 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ +import * as utils from './utils'; import * as vscode from 'vscode'; -import TelemetryReporter from 'vscode-extension-telemetry'; -import DefinitionProvider from '../features/definitionProvider'; -import ImplementationProvider from '../features/implementationProvider'; +import { AddAssetResult, addAssetsIfNecessary } from '../assets'; +import reportDiagnostics, { Advisor } from '../features/diagnosticsProvider'; +import { safeLength, sum } from '../common'; + +import { CSharpConfigurationProvider } from '../configurationProvider'; +import CodeActionProvider from '../features/codeActionProvider'; import CodeLensProvider from '../features/codeLensProvider'; +import CompletionItemProvider from '../features/completionItemProvider'; import DefinitionMetadataDocumentProvider from '../features/definitionMetadataDocumentProvider'; +import DefinitionProvider from '../features/definitionProvider'; import DocumentHighlightProvider from '../features/documentHighlightProvider'; import DocumentSymbolProvider from '../features/documentSymbolProvider'; -import CodeActionProvider from '../features/codeActionProvider'; -import ReferenceProvider from '../features/referenceProvider'; +import FormatProvider from '../features/formattingEditProvider'; import HoverProvider from '../features/hoverProvider'; +import ImplementationProvider from '../features/implementationProvider'; +import { OmniSharpServer } from './server'; +import { Options } from './options'; +import ReferenceProvider from '../features/referenceProvider'; import RenameProvider from '../features/renameProvider'; -import FormatProvider from '../features/formattingEditProvider'; -import CompletionItemProvider from '../features/completionItemProvider'; -import WorkspaceSymbolProvider from '../features/workspaceSymbolProvider'; -import reportDiagnostics, { Advisor } from '../features/diagnosticsProvider'; import SignatureHelpProvider from '../features/signatureHelpProvider'; +import TelemetryReporter from 'vscode-extension-telemetry'; import TestManager from '../features/dotnetTest'; -import registerCommands from '../features/commands'; +import WorkspaceSymbolProvider from '../features/workspaceSymbolProvider'; import forwardChanges from '../features/changeForwarding'; +import registerCommands from '../features/commands'; import reportStatus from '../features/status'; -import { OmniSharpServer } from './server'; -import { Options } from './options'; -import { addAssetsIfNecessary, AddAssetResult } from '../assets'; -import { sum, safeLength } from '../common'; -import * as utils from './utils'; -import { CSharpConfigurationProvider } from '../configurationProvider'; export function activate(context: vscode.ExtensionContext, reporter: TelemetryReporter, channel: vscode.OutputChannel) { const documentSelector: vscode.DocumentSelector = { @@ -156,4 +157,6 @@ export function activate(context: vscode.ExtensionContext, reporter: TelemetryRe disposables.push(vscode.debug.registerDebugConfigurationProvider('coreclr', new CSharpConfigurationProvider(server))); context.subscriptions.push(...disposables); + + return new Promise(resolve => server.onServerStart(e => resolve(e))); } \ No newline at end of file diff --git a/src/tools/GenerateOptionsSchema.ts b/src/tools/GenerateOptionsSchema.ts index 54ff3bd26c..a14dedf993 100644 --- a/src/tools/GenerateOptionsSchema.ts +++ b/src/tools/GenerateOptionsSchema.ts @@ -1,3 +1,8 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + import * as fs from 'fs'; import * as os from 'os'; diff --git a/src/tools/UpdatePackageDependencies.ts b/src/tools/UpdatePackageDependencies.ts index 6e973b0b4a..e0a69edfc3 100644 --- a/src/tools/UpdatePackageDependencies.ts +++ b/src/tools/UpdatePackageDependencies.ts @@ -1,5 +1,11 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + import * as fs from 'fs'; import * as os from 'os'; + import { Package } from '../packages'; interface PackageJSONFile diff --git a/test/integrationTests/index.ts b/test/integrationTests/index.ts new file mode 100644 index 0000000000..9de6cb03a1 --- /dev/null +++ b/test/integrationTests/index.ts @@ -0,0 +1,29 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +// +// PLEASE DO NOT MODIFY / DELETE UNLESS YOU KNOW WHAT YOU ARE DOING +// +// This file is providing the test runner to use when running extension tests. +// By default the test runner in use is Mocha based. +// +// You can provide your own test runner if you want to override it by exporting +// a function run(testRoot: string, clb: (error:Error) => void) that the extension +// host can call to run the tests. The test runner is expected to use console.log +// to report the results back to the caller. When the tests are finished, return +// a possible error to the callback or null if none. + +var testRunner = require('vscode/lib/testrunner'); + +// You can directly control Mocha options by uncommenting the following lines +// See https://github.com/mochajs/mocha/wiki/Using-mocha-programmatically#set-options for more info + +testRunner.configure({ + timeout: 60000, + ui: 'tdd', // the TDD UI is being used in extension.test.ts (suite, test, etc.) + useColors: true // colored output from test results +}); + +module.exports = testRunner; \ No newline at end of file diff --git a/test/integrationTests/launchConfiguration.integration.test.ts b/test/integrationTests/launchConfiguration.integration.test.ts new file mode 100644 index 0000000000..a38fd9b355 --- /dev/null +++ b/test/integrationTests/launchConfiguration.integration.test.ts @@ -0,0 +1,48 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import * as fs from 'async-file'; +import * as vscode from 'vscode'; + +import poll from './poll'; +import { should } from 'chai'; +import testAssetWorkspace from './testAssets/testAssetWorkspace'; + +const chai = require('chai'); +chai.use(require('chai-arrays')); +chai.use(require('chai-fs')); + +suite(`Tasks generation: ${testAssetWorkspace.description}`, function() { + suiteSetup(async function() { + should(); + + let csharpExtension = vscode.extensions.getExtension("ms-vscode.csharp"); + if (!csharpExtension.isActive) { + await csharpExtension.activate(); + } + + testAssetWorkspace.deleteBuildArtifacts(); + + await fs.rimraf(testAssetWorkspace.vsCodeDirectoryPath); + + await csharpExtension.exports.initializationFinished; + + await vscode.commands.executeCommand("dotnet.generateAssets"); + + await poll(async () => await fs.exists(testAssetWorkspace.launchJsonPath), 10000, 100); + }); + + test("Starting .NET Core Launch (console) from the workspace root should create an Active Debug Session", async () => { + await vscode.debug.startDebugging(vscode.workspace.workspaceFolders[0], ".NET Core Launch (console)"); + + let debugSessionTerminated = new Promise(resolve => { + vscode.debug.onDidTerminateDebugSession((e) => resolve()); + }); + + vscode.debug.activeDebugSession.type.should.equal("coreclr"); + + await debugSessionTerminated; + }); +}); \ No newline at end of file diff --git a/test/integrationTests/poll.ts b/test/integrationTests/poll.ts new file mode 100644 index 0000000000..2ada6c7d7e --- /dev/null +++ b/test/integrationTests/poll.ts @@ -0,0 +1,24 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +export default async function poll(getValue: () => T, duration: number, step: number): Promise { + while (duration > 0) { + let value = await getValue(); + + if (value) { + return value; + } + + await sleep(step); + + duration -= step; + } + + throw new Error("Polling did not succeed within the alotted duration."); +} + +function sleep(ms = 0) { + return new Promise(r => setTimeout(r, ms)); +} \ No newline at end of file diff --git a/test/integrationTests/testAssets/singleCsproj.ts b/test/integrationTests/testAssets/singleCsproj.ts new file mode 100644 index 0000000000..6db898e311 --- /dev/null +++ b/test/integrationTests/testAssets/singleCsproj.ts @@ -0,0 +1,15 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { ITestAssetWorkspace } from "./testAssets"; + +let workspace: ITestAssetWorkspace = { + description: "single csproj at root of workspace", + projects: [{ + relativePath: "singleCsproj.csproj" + }] +}; + +export default workspace; \ No newline at end of file diff --git a/test/integrationTests/testAssets/singleCsproj/Program.cs b/test/integrationTests/testAssets/singleCsproj/Program.cs new file mode 100644 index 0000000000..8f20c6374b --- /dev/null +++ b/test/integrationTests/testAssets/singleCsproj/Program.cs @@ -0,0 +1,12 @@ +using System; + +namespace singleCsproj +{ + class Program + { + static void Main(string[] args) + { + Console.WriteLine("Hello World!"); + } + } +} diff --git a/test/integrationTests/testAssets/singleCsproj/singleCsproj.csproj b/test/integrationTests/testAssets/singleCsproj/singleCsproj.csproj new file mode 100644 index 0000000000..8e047a019c --- /dev/null +++ b/test/integrationTests/testAssets/singleCsproj/singleCsproj.csproj @@ -0,0 +1,8 @@ + + + + Exe + netcoreapp2.0 + + + diff --git a/test/integrationTests/testAssets/slnWithCsproj.ts b/test/integrationTests/testAssets/slnWithCsproj.ts new file mode 100644 index 0000000000..ea68da1f28 --- /dev/null +++ b/test/integrationTests/testAssets/slnWithCsproj.ts @@ -0,0 +1,19 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { ITestAssetWorkspace } from "./testAssets"; + +let workspace: ITestAssetWorkspace = { + description: "sln with several csproj's", + projects: [{ + relativePath: "src/app/app.csproj" + },{ + relativePath: "src/lib/lib.csproj" + },{ + relativePath: "test/test.csproj" + }] +}; + +export default workspace; \ No newline at end of file diff --git a/test/integrationTests/testAssets/slnWithCsproj/slnWithCsproj.sln b/test/integrationTests/testAssets/slnWithCsproj/slnWithCsproj.sln new file mode 100644 index 0000000000..213e6c66b7 --- /dev/null +++ b/test/integrationTests/testAssets/slnWithCsproj/slnWithCsproj.sln @@ -0,0 +1,68 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +VisualStudioVersion = 15.0.26124.0 +MinimumVisualStudioVersion = 15.0.26124.0 +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{D28FC441-C95D-47D2-8D5C-E401ABAD7C64}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "app", "src\app\app.csproj", "{D36E1CC9-62CA-45A3-8BD0-6ADC2767FFB3}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "lib", "src\lib\lib.csproj", "{717BE881-D74C-45FC-B55D-2085499E1BF8}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "test", "test\test.csproj", "{4679428B-0CA0-4228-B8C0-B676B34A1B30}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|Any CPU = Release|Any CPU + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {D36E1CC9-62CA-45A3-8BD0-6ADC2767FFB3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D36E1CC9-62CA-45A3-8BD0-6ADC2767FFB3}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D36E1CC9-62CA-45A3-8BD0-6ADC2767FFB3}.Debug|x64.ActiveCfg = Debug|x64 + {D36E1CC9-62CA-45A3-8BD0-6ADC2767FFB3}.Debug|x64.Build.0 = Debug|x64 + {D36E1CC9-62CA-45A3-8BD0-6ADC2767FFB3}.Debug|x86.ActiveCfg = Debug|x86 + {D36E1CC9-62CA-45A3-8BD0-6ADC2767FFB3}.Debug|x86.Build.0 = Debug|x86 + {D36E1CC9-62CA-45A3-8BD0-6ADC2767FFB3}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D36E1CC9-62CA-45A3-8BD0-6ADC2767FFB3}.Release|Any CPU.Build.0 = Release|Any CPU + {D36E1CC9-62CA-45A3-8BD0-6ADC2767FFB3}.Release|x64.ActiveCfg = Release|x64 + {D36E1CC9-62CA-45A3-8BD0-6ADC2767FFB3}.Release|x64.Build.0 = Release|x64 + {D36E1CC9-62CA-45A3-8BD0-6ADC2767FFB3}.Release|x86.ActiveCfg = Release|x86 + {D36E1CC9-62CA-45A3-8BD0-6ADC2767FFB3}.Release|x86.Build.0 = Release|x86 + {717BE881-D74C-45FC-B55D-2085499E1BF8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {717BE881-D74C-45FC-B55D-2085499E1BF8}.Debug|Any CPU.Build.0 = Debug|Any CPU + {717BE881-D74C-45FC-B55D-2085499E1BF8}.Debug|x64.ActiveCfg = Debug|x64 + {717BE881-D74C-45FC-B55D-2085499E1BF8}.Debug|x64.Build.0 = Debug|x64 + {717BE881-D74C-45FC-B55D-2085499E1BF8}.Debug|x86.ActiveCfg = Debug|x86 + {717BE881-D74C-45FC-B55D-2085499E1BF8}.Debug|x86.Build.0 = Debug|x86 + {717BE881-D74C-45FC-B55D-2085499E1BF8}.Release|Any CPU.ActiveCfg = Release|Any CPU + {717BE881-D74C-45FC-B55D-2085499E1BF8}.Release|Any CPU.Build.0 = Release|Any CPU + {717BE881-D74C-45FC-B55D-2085499E1BF8}.Release|x64.ActiveCfg = Release|x64 + {717BE881-D74C-45FC-B55D-2085499E1BF8}.Release|x64.Build.0 = Release|x64 + {717BE881-D74C-45FC-B55D-2085499E1BF8}.Release|x86.ActiveCfg = Release|x86 + {717BE881-D74C-45FC-B55D-2085499E1BF8}.Release|x86.Build.0 = Release|x86 + {4679428B-0CA0-4228-B8C0-B676B34A1B30}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4679428B-0CA0-4228-B8C0-B676B34A1B30}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4679428B-0CA0-4228-B8C0-B676B34A1B30}.Debug|x64.ActiveCfg = Debug|x64 + {4679428B-0CA0-4228-B8C0-B676B34A1B30}.Debug|x64.Build.0 = Debug|x64 + {4679428B-0CA0-4228-B8C0-B676B34A1B30}.Debug|x86.ActiveCfg = Debug|x86 + {4679428B-0CA0-4228-B8C0-B676B34A1B30}.Debug|x86.Build.0 = Debug|x86 + {4679428B-0CA0-4228-B8C0-B676B34A1B30}.Release|Any CPU.ActiveCfg = Release|Any CPU + {4679428B-0CA0-4228-B8C0-B676B34A1B30}.Release|Any CPU.Build.0 = Release|Any CPU + {4679428B-0CA0-4228-B8C0-B676B34A1B30}.Release|x64.ActiveCfg = Release|x64 + {4679428B-0CA0-4228-B8C0-B676B34A1B30}.Release|x64.Build.0 = Release|x64 + {4679428B-0CA0-4228-B8C0-B676B34A1B30}.Release|x86.ActiveCfg = Release|x86 + {4679428B-0CA0-4228-B8C0-B676B34A1B30}.Release|x86.Build.0 = Release|x86 + EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {D36E1CC9-62CA-45A3-8BD0-6ADC2767FFB3} = {D28FC441-C95D-47D2-8D5C-E401ABAD7C64} + {717BE881-D74C-45FC-B55D-2085499E1BF8} = {D28FC441-C95D-47D2-8D5C-E401ABAD7C64} + EndGlobalSection +EndGlobal diff --git a/test/integrationTests/testAssets/slnWithCsproj/src/app/Program.cs b/test/integrationTests/testAssets/slnWithCsproj/src/app/Program.cs new file mode 100644 index 0000000000..a29e982532 --- /dev/null +++ b/test/integrationTests/testAssets/slnWithCsproj/src/app/Program.cs @@ -0,0 +1,12 @@ +using System; + +namespace app +{ + class Program + { + static void Main(string[] args) + { + Console.WriteLine("Hello World!"); + } + } +} diff --git a/test/integrationTests/testAssets/slnWithCsproj/src/app/app.csproj b/test/integrationTests/testAssets/slnWithCsproj/src/app/app.csproj new file mode 100644 index 0000000000..998c6a2eac --- /dev/null +++ b/test/integrationTests/testAssets/slnWithCsproj/src/app/app.csproj @@ -0,0 +1,12 @@ + + + + + + + + Exe + netcoreapp2.0 + + + diff --git a/test/integrationTests/testAssets/slnWithCsproj/src/lib/Class1.cs b/test/integrationTests/testAssets/slnWithCsproj/src/lib/Class1.cs new file mode 100644 index 0000000000..d07297bc60 --- /dev/null +++ b/test/integrationTests/testAssets/slnWithCsproj/src/lib/Class1.cs @@ -0,0 +1,8 @@ +using System; + +namespace lib +{ + public class Class1 + { + } +} diff --git a/test/integrationTests/testAssets/slnWithCsproj/src/lib/lib.csproj b/test/integrationTests/testAssets/slnWithCsproj/src/lib/lib.csproj new file mode 100644 index 0000000000..72764a6641 --- /dev/null +++ b/test/integrationTests/testAssets/slnWithCsproj/src/lib/lib.csproj @@ -0,0 +1,7 @@ + + + + netstandard2.0 + + + diff --git a/test/integrationTests/testAssets/slnWithCsproj/test/UnitTest1.cs b/test/integrationTests/testAssets/slnWithCsproj/test/UnitTest1.cs new file mode 100644 index 0000000000..fa542cf33e --- /dev/null +++ b/test/integrationTests/testAssets/slnWithCsproj/test/UnitTest1.cs @@ -0,0 +1,14 @@ +using System; +using Xunit; + +namespace test +{ + public class UnitTest1 + { + [Fact] + public void Test1() + { + + } + } +} diff --git a/test/integrationTests/testAssets/slnWithCsproj/test/test.csproj b/test/integrationTests/testAssets/slnWithCsproj/test/test.csproj new file mode 100644 index 0000000000..edd8c463de --- /dev/null +++ b/test/integrationTests/testAssets/slnWithCsproj/test/test.csproj @@ -0,0 +1,15 @@ + + + + netcoreapp2.0 + + false + + + + + + + + + diff --git a/test/integrationTests/testAssets/testAssetWorkspace.ts b/test/integrationTests/testAssets/testAssetWorkspace.ts new file mode 100644 index 0000000000..1a16fc81b9 --- /dev/null +++ b/test/integrationTests/testAssets/testAssetWorkspace.ts @@ -0,0 +1,25 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import * as path from 'path'; +import * as vscode from 'vscode'; + +import {ITestAssetWorkspace, TestAssetWorkspace} from './testAssets'; + +import singleCsproj from './singleCsproj'; +import slnWithCsproj from './slnWithCsproj'; + +const testAssetWorkspaces: { [x: string]: ITestAssetWorkspace } = { + singleCsproj, + slnWithCsproj +}; + +const workspaceName = vscode.workspace.rootPath + .split(path.sep) + .pop(); + +const activeTestAssetWorkspace = new TestAssetWorkspace(testAssetWorkspaces[workspaceName]); + +export default activeTestAssetWorkspace; \ No newline at end of file diff --git a/test/integrationTests/testAssets/testAssets.ts b/test/integrationTests/testAssets/testAssets.ts new file mode 100644 index 0000000000..407bd72976 --- /dev/null +++ b/test/integrationTests/testAssets/testAssets.ts @@ -0,0 +1,73 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import * as fs from 'async-file'; +import * as path from 'path'; +import * as vscode from 'vscode'; + +export class TestAssetProject { + constructor(project: ITestAssetProject) { + this.relativePath = project.relativePath; + } + + relativePath: string; + + get projectDirectoryPath(): string { + return path.join(vscode.workspace.workspaceFolders[0].uri.fsPath, + this.relativePath); + } + + get binDirectoryPath(): string { + return path.join(this.projectDirectoryPath, 'bin'); + } + + get objDirectoryPath(): string { + return path.join(this.projectDirectoryPath, 'obj'); + } + + async deleteBuildArtifacts(): Promise { + await fs.rimraf(this.binDirectoryPath); + await fs.rimraf(this.objDirectoryPath); + } +} + +export class TestAssetWorkspace { + constructor(workspace: ITestAssetWorkspace) { + this.projects = workspace.projects.map( + w => new TestAssetProject(w) + ); + + this.description = workspace.description; + } + + async deleteBuildArtifacts(): Promise { + this.projects.forEach(async p => await p.deleteBuildArtifacts()); + } + + get vsCodeDirectoryPath(): string { + return path.join(vscode.workspace.rootPath, ".vscode");; + } + + get launchJsonPath(): string { + return path.join(this.vsCodeDirectoryPath, "launch.json"); + } + + get tasksJsonPath(): string { + return path.join(this.vsCodeDirectoryPath, "tasks.json"); + } + + description: string; + + projects: TestAssetProject []; +} + +export interface ITestAssetProject { + relativePath: string; +} + +export interface ITestAssetWorkspace { + description: string; + projects: ITestAssetProject[]; +} \ No newline at end of file diff --git a/test/runVsCodeTestsWithAbsolutePaths.js b/test/runVsCodeTestsWithAbsolutePaths.js new file mode 100644 index 0000000000..a4a5176cbc --- /dev/null +++ b/test/runVsCodeTestsWithAbsolutePaths.js @@ -0,0 +1,15 @@ +#!/usr/bin/env node + +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +path=require('path'); + +if (process.env.CODE_TESTS_PATH + && process.env.CODE_TESTS_PATH.startsWith('.')){ + process.env.CODE_TESTS_PATH = path.join(process.cwd(), process.env.CODE_TESTS_PATH.substr(2)); +} + +require(path.resolve(__dirname, '../node_modules/vscode/bin/test')); \ No newline at end of file diff --git a/test/sanity.test.ts b/test/sanity.test.ts deleted file mode 100644 index ac1fbb53fc..0000000000 --- a/test/sanity.test.ts +++ /dev/null @@ -1,26 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -// -// Note: This example test is leveraging the Mocha test framework. -// Please refer to their documentation on https://mochajs.org/ for help. -// - -// The module 'assert' provides assertion methods from node -import * as assert from 'assert'; - -// You can import and use all API from the 'vscode' module -// as well as import your extension to test it -import * as vscode from 'vscode'; -import * as myExtension from '../src/main'; - -suite("Sanity Tests", () => { - test("Boolean checks", () => { - assert.equal(true, true, "true is not true"); - assert.notEqual(true, false, "true is false"); - assert.equal(false, false, "false is not false"); - assert.notEqual(false, true, "false is true"); - }); -}); \ No newline at end of file diff --git a/test/assets.test.ts b/test/unitTests/assets.test.ts similarity index 88% rename from test/assets.test.ts rename to test/unitTests/assets.test.ts index fd3effd2ae..cb8bddec0a 100644 --- a/test/assets.test.ts +++ b/test/unitTests/assets.test.ts @@ -3,11 +3,21 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { should } from 'chai'; import * as path from 'path'; -import * as protocol from '../src/omnisharp/protocol'; -import { AssetGenerator } from '../src/assets'; +import * as protocol from '../../src/omnisharp/protocol'; +import * as vscode from 'vscode'; + +import { AssetGenerator } from '../../src/assets'; import { parse } from 'jsonc-parser'; +import { should } from 'chai'; + +function createMockWorkspaceFolder(rootPath: string) : vscode.WorkspaceFolder { + return { + uri: vscode.Uri.file(rootPath), + name: undefined, + index: undefined + } +} suite("Asset generation: project.json", () => { suiteSetup(() => should()); @@ -15,7 +25,7 @@ suite("Asset generation: project.json", () => { test("Create tasks.json for project opened in workspace", () => { let rootPath = path.resolve('testRoot'); let info = createDotNetWorkspaceInformation(rootPath, 'testApp.dll', 'netcoreapp1.0'); - let generator = new AssetGenerator(info, rootPath); + let generator = new AssetGenerator(info, createMockWorkspaceFolder(rootPath)); let tasksJson = generator.createTasksConfiguration(); let buildPath = tasksJson.tasks[0].args[1]; @@ -27,7 +37,7 @@ suite("Asset generation: project.json", () => { test("Create tasks.json for nested project opened in workspace", () => { let rootPath = path.resolve('testRoot'); let info = createDotNetWorkspaceInformation(path.join(rootPath, 'nested'), 'testApp.dll', 'netcoreapp1.0'); - let generator = new AssetGenerator(info, rootPath); + let generator = new AssetGenerator(info, createMockWorkspaceFolder(rootPath)); let tasksJson = generator.createTasksConfiguration(); let buildPath = tasksJson.tasks[0].args[1]; @@ -39,7 +49,7 @@ suite("Asset generation: project.json", () => { test("Create launch.json for project opened in workspace", () => { let rootPath = path.resolve('testRoot'); let info = createDotNetWorkspaceInformation(rootPath, 'testApp.dll', 'netcoreapp1.0'); - let generator = new AssetGenerator(info, rootPath); + let generator = new AssetGenerator(info, createMockWorkspaceFolder(rootPath)); let launchJson = parse(generator.createLaunchJson(/*isWebProject*/ false), undefined, { disallowComments: true }); let programPath = launchJson[0].program; @@ -51,7 +61,7 @@ suite("Asset generation: project.json", () => { test("Create launch.json for nested project opened in workspace", () => { let rootPath = path.resolve('testRoot'); let info = createDotNetWorkspaceInformation(path.join(rootPath, 'nested'), 'testApp.dll', 'netcoreapp1.0'); - let generator = new AssetGenerator(info, rootPath); + let generator = new AssetGenerator(info, createMockWorkspaceFolder(rootPath)); let launchJson = parse(generator.createLaunchJson(/*isWebProject*/ false), undefined, { disallowComments: true }); let programPath = launchJson[0].program; @@ -63,7 +73,7 @@ suite("Asset generation: project.json", () => { test("Create launch.json for web project opened in workspace", () => { let rootPath = path.resolve('testRoot'); let info = createDotNetWorkspaceInformation(rootPath, 'testApp.dll', 'netcoreapp1.0'); - let generator = new AssetGenerator(info, rootPath); + let generator = new AssetGenerator(info, createMockWorkspaceFolder(rootPath)); let launchJson = parse(generator.createLaunchJson(/*isWebProject*/ true), undefined, { disallowComments: true }); let programPath = launchJson[0].program; @@ -75,7 +85,7 @@ suite("Asset generation: project.json", () => { test("Create launch.json for nested web project opened in workspace", () => { let rootPath = path.resolve('testRoot'); let info = createDotNetWorkspaceInformation(path.join(rootPath, 'nested'), 'testApp.dll', 'netcoreapp1.0'); - let generator = new AssetGenerator(info, rootPath); + let generator = new AssetGenerator(info, createMockWorkspaceFolder(rootPath)); let launchJson = parse(generator.createLaunchJson(/*isWebProject*/ true), undefined, { disallowComments: true }); let programPath = launchJson[0].program; @@ -123,7 +133,7 @@ suite("Asset generation: csproj", () => { test("Create tasks.json for project opened in workspace", () => { let rootPath = path.resolve('testRoot'); let info = createMSBuildWorkspaceInformation(path.join(rootPath, 'testApp.csproj'), 'testApp', 'netcoreapp1.0'); - let generator = new AssetGenerator(info, rootPath); + let generator = new AssetGenerator(info, createMockWorkspaceFolder(rootPath)); let tasksJson = generator.createTasksConfiguration(); let buildPath = tasksJson.tasks[0].args[1]; @@ -135,7 +145,7 @@ suite("Asset generation: csproj", () => { test("Create tasks.json for nested project opened in workspace", () => { let rootPath = path.resolve('testRoot'); let info = createMSBuildWorkspaceInformation(path.join(rootPath, 'nested', 'testApp.csproj'), 'testApp', 'netcoreapp1.0'); - let generator = new AssetGenerator(info, rootPath); + let generator = new AssetGenerator(info, createMockWorkspaceFolder(rootPath)); let tasksJson = generator.createTasksConfiguration(); let buildPath = tasksJson.tasks[0].args[1]; @@ -147,7 +157,7 @@ suite("Asset generation: csproj", () => { test("Create launch.json for project opened in workspace", () => { let rootPath = path.resolve('testRoot'); let info = createMSBuildWorkspaceInformation(path.join(rootPath, 'testApp.csproj'), 'testApp', 'netcoreapp1.0'); - let generator = new AssetGenerator(info, rootPath); + let generator = new AssetGenerator(info, createMockWorkspaceFolder(rootPath)); let launchJson = parse(generator.createLaunchJson(/*isWebProject*/ false), undefined, { disallowComments: true }); let programPath = launchJson[0].program; @@ -159,7 +169,7 @@ suite("Asset generation: csproj", () => { test("Create launch.json for nested project opened in workspace", () => { let rootPath = path.resolve('testRoot'); let info = createMSBuildWorkspaceInformation(path.join(rootPath, 'nested', 'testApp.csproj'), 'testApp', 'netcoreapp1.0'); - let generator = new AssetGenerator(info, rootPath); + let generator = new AssetGenerator(info, createMockWorkspaceFolder(rootPath)); let launchJson = parse(generator.createLaunchJson(/*isWebProject*/ false), undefined, { disallowComments: true }); let programPath = launchJson[0].program; @@ -171,7 +181,7 @@ suite("Asset generation: csproj", () => { test("Create launch.json for web project opened in workspace", () => { let rootPath = path.resolve('testRoot'); let info = createMSBuildWorkspaceInformation(path.join(rootPath, 'testApp.csproj'), 'testApp', 'netcoreapp1.0'); - let generator = new AssetGenerator(info, rootPath); + let generator = new AssetGenerator(info, createMockWorkspaceFolder(rootPath)); let launchJson = parse(generator.createLaunchJson(/*isWebProject*/ true), undefined, { disallowComments: true }); let programPath = launchJson[0].program; @@ -183,7 +193,7 @@ suite("Asset generation: csproj", () => { test("Create launch.json for nested web project opened in workspace", () => { let rootPath = path.resolve('testRoot'); let info = createMSBuildWorkspaceInformation(path.join(rootPath, 'nested', 'testApp.csproj'), 'testApp', 'netcoreapp1.0'); - let generator = new AssetGenerator(info, rootPath); + let generator = new AssetGenerator(info, createMockWorkspaceFolder(rootPath)); let launchJson = parse(generator.createLaunchJson(/*isWebProject*/ true), undefined, { disallowComments: true }); let programPath = launchJson[0].program; diff --git a/test/common.test.ts b/test/unitTests/common.test.ts similarity index 97% rename from test/common.test.ts rename to test/unitTests/common.test.ts index 483586fc84..fbfe309e8c 100644 --- a/test/common.test.ts +++ b/test/unitTests/common.test.ts @@ -4,8 +4,10 @@ *--------------------------------------------------------------------------------------------*/ import * as path from 'path'; + +import { buildPromiseChain, isSubfolderOf, safeLength, sum } from '../../src/common'; + import { should } from 'chai'; -import { buildPromiseChain, safeLength, sum, isSubfolderOf } from '../src/common'; suite("Common", () => { suiteSetup(() => should()); diff --git a/test/index.ts b/test/unitTests/index.ts similarity index 99% rename from test/index.ts rename to test/unitTests/index.ts index 2bf0a6fde4..cda6a4004a 100644 --- a/test/index.ts +++ b/test/unitTests/index.ts @@ -19,6 +19,7 @@ var testRunner = require('vscode/lib/testrunner'); // You can directly control Mocha options by uncommenting the following lines // See https://github.com/mochajs/mocha/wiki/Using-mocha-programmatically#set-options for more info + testRunner.configure({ timeout: 10000, ui: 'tdd', // the TDD UI is being used in extension.test.ts (suite, test, etc.) diff --git a/test/json.test.ts b/test/unitTests/json.test.ts similarity index 99% rename from test/json.test.ts rename to test/unitTests/json.test.ts index 08b34ec776..7cb9d88847 100644 --- a/test/json.test.ts +++ b/test/unitTests/json.test.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import { should } from 'chai'; -import { tolerantParse } from '../src/json'; +import { tolerantParse } from '../../src/json'; suite("JSON", () => { suiteSetup(() => should()); diff --git a/test/platform.test.ts b/test/unitTests/platform.test.ts similarity index 97% rename from test/platform.test.ts rename to test/unitTests/platform.test.ts index a5499f75d3..83aed13e2f 100644 --- a/test/platform.test.ts +++ b/test/unitTests/platform.test.ts @@ -3,8 +3,8 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ +import { LinuxDistribution } from '../../src/platform'; import { should } from 'chai'; -import { LinuxDistribution, PlatformInformation } from '../src/platform'; suite("Platform", () => { suiteSetup(() => should()); diff --git a/test/processPicker.test.ts b/test/unitTests/processPicker.test.ts similarity index 95% rename from test/processPicker.test.ts rename to test/unitTests/processPicker.test.ts index cfbcaf5d33..736536b16e 100644 --- a/test/processPicker.test.ts +++ b/test/unitTests/processPicker.test.ts @@ -1,5 +1,10 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { RemoteAttachPicker } from '../../src/features/processPicker'; import { should } from 'chai'; -import { RemoteAttachPicker } from '../src/features/processPicker'; suite("Remote Process Picker: Validate quoting arguments.", () => { suiteSetup(() => should()); @@ -159,7 +164,7 @@ function GetWindowsWSLLaunchJSONWithArrayArgs() { pipeCwd: "${workspaceFolder}", pipeProgram: "C:\\System32\\bash.exe", pipeArgs: ["-c"] - } + }; } function GetWindowsWSLLaunchJSONWithArrayArgsAndDebuggerCommand() { @@ -167,7 +172,7 @@ function GetWindowsWSLLaunchJSONWithArrayArgsAndDebuggerCommand() { pipeCwd: "${workspaceFolder}", pipeProgram: "C:\\System32\\bash.exe", pipeArgs: ["-c", "${debuggerCommand}", "--", "ignored"] - } + }; } function GetWindowsWSLLaunchJSONWithStringArgs() { @@ -175,7 +180,7 @@ function GetWindowsWSLLaunchJSONWithStringArgs() { pipeCwd: "${workspaceFolder}", pipeProgram: "C:\\System32\\bash.exe", pipeArgs: "-c" - } + }; } function GetWindowsWSLLaunchJSONWithStringArgsAndDebuggerCommand() { @@ -183,7 +188,7 @@ function GetWindowsWSLLaunchJSONWithStringArgsAndDebuggerCommand() { pipeCwd: "${workspaceFolder}", pipeProgram: "C:\\System32\\bash.exe", pipeArgs: "-c ${debuggerCommand} -- ignored" - } + }; } function GetWindowsDockerLaunchJSONWithArrayArgs() { @@ -192,7 +197,7 @@ function GetWindowsDockerLaunchJSONWithArrayArgs() { pipeProgram: "docker", pipeArgs: ["-i", "exec", "1234567"], quoteArgs: false - } + }; }; function GetWindowsDockerLaunchJSONWithStringArgsAndDebuggerCommand() { @@ -201,7 +206,7 @@ function GetWindowsDockerLaunchJSONWithStringArgsAndDebuggerCommand() { pipeProgram: "docker", pipeArgs: "-i exec 1234567 ${debuggerCommand}", quoteArgs: false - } + }; } function GetLinuxLaunchJSONWithArrayArgs() { @@ -210,7 +215,7 @@ function GetLinuxLaunchJSONWithArrayArgs() { pipeProgram: "/usr/bin/shared/dotnet", pipeArgs: ["bin/framework/myprogram.dll", "argument with spaces"], quoteArg: true - } + }; } function GetOSSpecificJSON() { @@ -229,5 +234,5 @@ function GetOSSpecificJSON() { linux: { pipeProgram: "Linux pipeProgram", } - } + }; } \ No newline at end of file diff --git a/tslint.json b/tslint.json index 682162074d..a5115d4988 100644 --- a/tslint.json +++ b/tslint.json @@ -7,6 +7,8 @@ "no-var-keyword": true, "promise-must-complete": true, "curly": true, - "semicolon": true + "semicolon": true, + "indent": [true, "spaces", 4], + "file-header": [true, ".*"] } } \ No newline at end of file