Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
Defines the lowest supported target framework for the extension.
Used by server download / integration tests to ensure they run when only this SDK is installed.
-->
<CheckEolTargetFramework>false</CheckEolTargetFramework>
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Noticed project loading did not like running on a .NET 10 preview while building net6.0 projects.

<LowestSupportedTargetFramework>net6.0</LowestSupportedTargetFramework>
</PropertyGroup>
</Project>
</Project>
7 changes: 3 additions & 4 deletions azure-pipelines/test-matrix.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,9 @@ jobs:
UnitTests:
npmCommand: test:unit
isIntegration: false
${{ if ne(parameters.os, 'windows') }}:
CSharpIntegrationTests:
npmCommand: test:integration:csharp
isIntegration: true
CSharpIntegrationTests:
npmCommand: test:integration:csharp
isIntegration: true
DevKitTests:
npmCommand: test:integration:devkit
isIntegration: true
Expand Down
55 changes: 55 additions & 0 deletions test/jestHelpers.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/

import * as vscode from 'vscode';
import { EOL, platform } from 'os';
import { describe, expect, test } from '@jest/globals';
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Separated these helpers out because they use @jest/globals and importing it isn't allowed in the test runner (index.ts).

import { usingDevKit } from './lsptoolshost/integrationTests/integrationHelpers';

export async function expectText(document: vscode.TextDocument, expectedLines: string[]) {
const expectedText = expectedLines.join(EOL);
expect(document.getText()).toBe(expectedText);
}

export function expectPath(expected: vscode.Uri, actual: vscode.Uri) {
if (isLinux()) {
expect(actual.path).toBe(expected.path);
} else {
const actualPath = actual.path.toLowerCase();
const expectedPath = expected.path.toLocaleLowerCase();
expect(actualPath).toBe(expectedPath);
}
}

export const describeIfCSharp = describeIf(!usingDevKit());
export const describeIfDevKit = describeIf(usingDevKit());
export const describeIfNotMacOS = describeIf(!isMacOS());
export const describeIfWindows = describeIf(isWindows());
export const testIfCSharp = testIf(!usingDevKit());
export const testIfDevKit = testIf(usingDevKit());
export const testIfNotMacOS = testIf(!isMacOS());
export const testIfWindows = testIf(isWindows());

function describeIf(condition: boolean) {
return condition ? describe : describe.skip;
}

function testIf(condition: boolean) {
return condition ? test : test.skip;
}

function isMacOS() {
const currentPlatform = platform();
return currentPlatform === 'darwin';
}

function isWindows() {
const currentPlatform = platform();
return currentPlatform === 'win32';
}

function isLinux() {
return !(isMacOS() || isWindows());
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {
} from '../../../src/lsptoolshost/diagnostics/buildDiagnosticsService';
import * as integrationHelpers from './integrationHelpers';
import path from 'path';

describe(`Build and live diagnostics dedupe`, () => {
beforeAll(async () => {
await integrationHelpers.activateCSharpExtension();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,8 @@ import * as vscode from 'vscode';
import * as path from 'path';
import { describe, beforeAll, beforeEach, afterAll, test, expect, afterEach } from '@jest/globals';
import testAssetWorkspace from './testAssets/testAssetWorkspace';
import {
activateCSharpExtension,
closeAllEditorsAsync,
expectText,
openFileInWorkspaceAsync,
} from './integrationHelpers';
import { activateCSharpExtension, closeAllEditorsAsync, openFileInWorkspaceAsync } from './integrationHelpers';
import { expectText } from '../../jestHelpers';

describe(`Code Actions Tests`, () => {
beforeAll(async () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,15 @@

import { expect, beforeAll, afterAll, describe } from '@jest/globals';
import * as vscode from 'vscode';
import { activateCSharpExtension, testIfCSharp, testIfDevKit } from './integrationHelpers';
import { activateCSharpExtension } from './integrationHelpers';
import testAssetWorkspace from './testAssets/testAssetWorkspace';
import {
RoslynDevKitCommands,
RoslynStandaloneCommands,
UnexpectedRoslynDevKitCommands,
UnexpectedRoslynStandaloneCommands,
} from './expectedCommands';
import { testIfCSharp, testIfDevKit } from '../../jestHelpers';

describe(`Command Enablement Tests`, () => {
beforeAll(async () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,8 @@ import testAssetWorkspace from './testAssets/testAssetWorkspace';
import { AnalysisSetting } from '../../../src/lsptoolshost/diagnostics/buildDiagnosticsService';
import path from 'path';
import { getCode, setDiagnosticSettings, waitForExpectedDiagnostics } from './diagnosticsHelpers';
import {
activateCSharpExtension,
closeAllEditorsAsync,
describeIfCSharp,
openFileInWorkspaceAsync,
} from './integrationHelpers';
import { activateCSharpExtension, closeAllEditorsAsync, openFileInWorkspaceAsync } from './integrationHelpers';
import { describeIfCSharp } from '../../jestHelpers';

// Restarting the server is required for these tests, but not supported with C# Dev Kit.
describeIfCSharp(`Document Diagnostics Tests`, () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,10 @@
import * as vscode from 'vscode';
import * as path from 'path';
import testAssetWorkspace from './testAssets/testAssetWorkspace';
import {
activateCSharpExtension,
closeAllEditorsAsync,
expectText,
openFileInWorkspaceAsync,
} from './integrationHelpers';
import { activateCSharpExtension, closeAllEditorsAsync, openFileInWorkspaceAsync } from './integrationHelpers';
import { describe, beforeEach, afterAll, test, afterEach } from '@jest/globals';
import { formatDocumentAsync, formatOnTypeAsync, formatRangeAsync } from './formattingTestHelpers';
import { expectText } from '../../jestHelpers';

describe(`Formatting Tests`, () => {
beforeEach(async () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,10 @@
import * as vscode from 'vscode';
import * as path from 'path';
import testAssetWorkspace from './testAssets/testAssetWorkspace';
import {
activateCSharpExtension,
closeAllEditorsAsync,
expectText,
openFileInWorkspaceAsync,
} from './integrationHelpers';
import { activateCSharpExtension, closeAllEditorsAsync, openFileInWorkspaceAsync } from './integrationHelpers';
import { describe, beforeAll, beforeEach, afterAll, test, afterEach } from '@jest/globals';
import { formatDocumentAsync, formatOnTypeAsync, formatRangeAsync } from './formattingTestHelpers';
import { expectText } from '../../jestHelpers';

describe(`Formatting With EditorConfig Tests`, () => {
beforeAll(async () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,9 @@ import {
findRangeOfString,
navigate,
openFileInWorkspaceAsync,
testIfCSharp,
testIfDevKit,
} from './integrationHelpers';
import { describe, beforeAll, beforeEach, afterAll, test, expect, afterEach } from '@jest/globals';
import { testIfCSharp, testIfDevKit } from '../../jestHelpers';

describe(`Go To Definition Tests`, () => {
beforeAll(async () => {
Expand Down
64 changes: 63 additions & 1 deletion test/lsptoolshost/integrationTests/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,73 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/

import * as vscode from 'vscode';
import * as fsExtra from 'fs-extra';
import path from 'path';
import { AggregatedResult } from '@jest/test-result';
import { runIntegrationTests } from '../../runIntegrationTests';
import { jestIntegrationTestProjectName } from './jest.config';
import { activateCSharpExtension } from './integrationHelpers';

export async function run() {
process.env.RUNNING_INTEGRATION_TESTS = 'true';

await runIntegrationTests(jestIntegrationTestProjectName);
await activateCSharpExtension();
await moveLogs('activated');

let anyFailures = false;
let results: AggregatedResult | undefined;
if (process.env.TEST_FILE_FILTER) {
results = await runIntegrationTests(jestIntegrationTestProjectName);
await moveLogs(path.basename(process.env.TEST_FILE_FILTER, '.integration.test.ts'));
anyFailures = anyFailures || !results.success;
} else {
const workingDirectory = process.cwd();

const testFiles = (await fsExtra.readdir(__dirname))
.filter((file) => file.endsWith('.integration.test.js'))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

instead of doing this, I think you could probably simplify all this by getting the rootPath here, and then just go directly to the typescript files?

.map((file) => path.join(__dirname, file));

for (let file of testFiles) {
// We have to fix up the file path because the test file was discovered in the /out/ directory.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do sourcemaps still work if we do this? e.g. f5 launching integration tests is fine?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

our launch targets set the TEST_FILTER_FILE so it shouldn't run this bit of code.

file = file.substring(0, file.length - 2) + 'ts';
file = file.replace(/[\\/]out[\\/]/, path.sep);
file = workingDirectory[0] + file.substring(1);
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So locally __dirname is returning the drive letter lowercased and the filepaths also are lowercased. Jest fails to match the paths to a test suite if I don't bring in a correct drive letter. Thankfully the working directory has the correct casing. Figure on unix-like platforms it should basically be a no-op.


console.log('');
console.log(`-- Running integration tests for ${path.basename(file)} --`);
console.log('');

process.env.TEST_FILE_FILTER = file;

results = await runIntegrationTests(jestIntegrationTestProjectName);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm wondering if this (or something above it) needs to catch errors and then move the logs - I noticed that in the 'Test Linux (.NET 9) CSharpIntegrationTests' leg, it looks like the sourceGenerator.integration.test.ts fail with an extension host crash, and there are no logs uploaded for it.

Image

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The current runs logs should still be in the logs folder even if they aren't moved.

await moveLogs(path.basename(process.env.TEST_FILE_FILTER, '.integration.test.ts'));
anyFailures = anyFailures || !results.success;
}
}

// Explicitly exit the process - VSCode likes to write a bunch of cancellation errors to the console after this
// which make it look like the tests always fail. We're done with the tests at this point, so just exit.
process.exit(anyFailures ? 1 : 0);
}

async function moveLogs(name: string) {
const exports = vscode.extensions.getExtension('ms-dotnettools.csharp')?.exports;
if (!exports) {
throw new Error('Failed to get C# extension exports for cleanup');
}

if (!exports.logDirectory) {
console.warn(`Failed to get log directory from C# extension exports`);
return;
}

const targetLogDir = path.join(
path.dirname(exports.logDirectory),
`${name ?? 'unknown'}_${path.basename(exports.logDirectory)}`
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can remove unknown, name isn't nullable here

);
await fsExtra.copy(exports.logDirectory, targetLogDir);
console.log(`Copied extension logs from ${exports.logDirectory} to ${targetLogDir}`);

await new Promise((resolve) => fsExtra.rm(path.join(exports.logDirectory, '*.log'), resolve));
}
50 changes: 0 additions & 50 deletions test/lsptoolshost/integrationTests/integrationHelpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,6 @@ import { CSharpExtensionExports } from '../../../src/csharpExtensionExports';
import { existsSync } from 'fs';
import { ServerState } from '../../../src/lsptoolshost/server/languageServerEvents';
import testAssetWorkspace from './testAssets/testAssetWorkspace';
import { EOL, platform } from 'os';
import { describe, expect, test } from '@jest/globals';

export async function activateCSharpExtension(): Promise<void> {
const csharpExtension = vscode.extensions.getExtension<CSharpExtensionExports>('ms-dotnettools.csharp');
Expand Down Expand Up @@ -191,8 +189,6 @@ export async function navigate(

// Navigation happens asynchronously when a different file is opened, so we need to wait for the window to change.
await windowChanged;

expect(vscode.window.activeTextEditor?.document.fileName).toContain(expectedFileName);
}

export function sortLocations(locations: vscode.Location[]): vscode.Location[] {
Expand Down Expand Up @@ -253,49 +249,3 @@ export async function waitForExpectedResult<T>(
export async function sleep(ms = 0) {
return new Promise((r) => setTimeout(r, ms));
}

export async function expectText(document: vscode.TextDocument, expectedLines: string[]) {
const expectedText = expectedLines.join(EOL);
expect(document.getText()).toBe(expectedText);
}

export function expectPath(expected: vscode.Uri, actual: vscode.Uri) {
if (isLinux()) {
expect(actual.path).toBe(expected.path);
} else {
const actualPath = actual.path.toLowerCase();
const expectedPath = expected.path.toLocaleLowerCase();
expect(actualPath).toBe(expectedPath);
}
}

export const describeIfCSharp = describeIf(!usingDevKit());
export const describeIfDevKit = describeIf(usingDevKit());
export const describeIfNotMacOS = describeIf(!isMacOS());
export const describeIfWindows = describeIf(isWindows());
export const testIfCSharp = testIf(!usingDevKit());
export const testIfDevKit = testIf(usingDevKit());
export const testIfNotMacOS = testIf(!isMacOS());
export const testIfWindows = testIf(isWindows());

function describeIf(condition: boolean) {
return condition ? describe : describe.skip;
}

function testIf(condition: boolean) {
return condition ? test : test.skip;
}

function isMacOS() {
const currentPlatform = platform();
return currentPlatform === 'darwin';
}

function isWindows() {
const currentPlatform = platform();
return currentPlatform === 'win32';
}

function isLinux() {
return !(isMacOS() || isWindows());
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,11 @@ import testAssetWorkspace from './testAssets/testAssetWorkspace';
import {
activateCSharpExtension,
closeAllEditorsAsync,
describeIfCSharp,
getCodeLensesAsync,
openFileInWorkspaceAsync,
} from './integrationHelpers';
import { TestProgress } from '../../../src/lsptoolshost/server/roslynProtocol';
import { describeIfCSharp } from '../../jestHelpers';

describeIfCSharp(`Unit Testing Tests`, () => {
beforeAll(async () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ import { describe, test, expect, beforeAll, afterAll } from '@jest/globals';
import testAssetWorkspace from './testAssets/testAssetWorkspace';
import { AnalysisSetting } from '../../../src/lsptoolshost/diagnostics/buildDiagnosticsService';
import { getCode, setDiagnosticSettings, waitForExpectedDiagnostics } from './diagnosticsHelpers';
import { activateCSharpExtension, describeIfCSharp } from './integrationHelpers';
import { activateCSharpExtension } from './integrationHelpers';
import { describeIfCSharp } from '../../jestHelpers';

// Restarting the server is required for these tests, but not supported with C# Dev Kit.
describeIfCSharp(`Workspace Diagnostic Tests`, () => {
Expand Down
6 changes: 5 additions & 1 deletion test/omnisharp/omnisharpIntegrationTests/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,9 @@ import { jestIntegrationTestProjectName } from './jest.config';
export async function run() {
process.env.RUNNING_INTEGRATION_TESTS = 'true';

await runIntegrationTests(jestIntegrationTestProjectName);
const results = await runIntegrationTests(jestIntegrationTestProjectName);

// Explicitly exit the process - VSCode likes to write a bunch of cancellation errors to the console after this
// which make it look like the tests always fail. We're done with the tests at this point, so just exit.
process.exit(results.success ? 0 : 1);
}
6 changes: 5 additions & 1 deletion test/razor/razorIntegrationTests/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,9 @@ import { jestIntegrationTestProjectName } from './jest.config';
export async function run() {
process.env.RUNNING_INTEGRATION_TESTS = 'true';

await runIntegrationTests(jestIntegrationTestProjectName);
const results = await runIntegrationTests(jestIntegrationTestProjectName);

// Explicitly exit the process - VSCode likes to write a bunch of cancellation errors to the console after this
// which make it look like the tests always fail. We're done with the tests at this point, so just exit.
process.exit(results.success ? 0 : 1);
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import * as vscode from 'vscode';
import { beforeAll, afterAll, test, expect, beforeEach, describe } from '@jest/globals';
import testAssetWorkspace from './testAssets/testAssetWorkspace';
import * as integrationHelpers from '../../lsptoolshost/integrationTests/integrationHelpers';
import * as jestHelpers from '../../jestHelpers';

describe(`Razor References ${testAssetWorkspace.description}`, function () {
beforeAll(async function () {
Expand Down Expand Up @@ -151,9 +152,9 @@ describe(`Razor References ${testAssetWorkspace.description}`, function () {
const razorFile = integrationHelpers.getFilePath(path.join('Pages', 'References.razor'));
const csharpFile = integrationHelpers.getFilePath(path.join('Pages', 'References.razor.cs'));

integrationHelpers.expectPath(razorFile, sortedLocations[0].uri);
integrationHelpers.expectPath(csharpFile, sortedLocations[1].uri);
integrationHelpers.expectPath(csharpFile, sortedLocations[2].uri);
jestHelpers.expectPath(razorFile, sortedLocations[0].uri);
jestHelpers.expectPath(csharpFile, sortedLocations[1].uri);
jestHelpers.expectPath(csharpFile, sortedLocations[2].uri);
}
);
});
Expand Down
Loading
Loading