Skip to content

Commit

Permalink
refactor: Event based macro tracer tests
Browse files Browse the repository at this point in the history
  • Loading branch information
slavek-kucera authored Jan 18, 2023
1 parent c2a2af9 commit 67913e6
Show file tree
Hide file tree
Showing 12 changed files with 130 additions and 64 deletions.
6 changes: 3 additions & 3 deletions clients/vscode-hlasmplugin/src/test/suite/debugging.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,8 @@ suite('Debugging Test Suite', () => {
}).timeout(20000).slow(10000);

test('Breakpoint test', async () => {
await helper.toggleBreakpoints(path.join('libs', 'mac.asm'), [3]);
await helper.toggleBreakpoints('open', [3, 9]);
await helper.addBreakpoints(path.join('libs', 'mac.asm'), [3]);
await helper.addBreakpoints('open', [3, 9]);

await helper.debugStartSession();

Expand All @@ -75,7 +75,7 @@ suite('Debugging Test Suite', () => {

// verify that virtual files are working
test('Virtual files', async () => {
await helper.toggleBreakpoints('virtual', [7, 11, 12]);
await helper.addBreakpoints('virtual', [7, 11, 12]);

await helper.debugStartSession();

Expand Down
22 changes: 18 additions & 4 deletions clients/vscode-hlasmplugin/src/test/suite/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,10 @@ import * as Mocha from 'mocha';
import * as glob from 'glob';
import * as vscode from 'vscode';
import * as process from 'process';
import { timeout } from './testHelper';
import { popWaitRequestResolver, timeout } from './testHelper';
import { EXTENSION_ID } from '../../extension';

async function primeExtension() {
async function primeExtension(): Promise<vscode.Disposable[]> {
const ext = await vscode.extensions.getExtension(EXTENSION_ID).activate();
const lang: {
onReady(): Promise<void>;
Expand All @@ -30,6 +30,20 @@ async function primeExtension() {
await Promise.race([lang.onReady(), timeout(30000, 'Language server initialization failed')]);
// prime opcode suggestions to avoid timeouts
await Promise.race([lang.sendRequest<object>('textDocument/$/opcode_suggestion', { opcodes: ['OPCODE'] }), timeout(30000, 'Opcode suggestion request failed')]);

return [vscode.debug.registerDebugAdapterTrackerFactory('hlasm', {
createDebugAdapterTracker: function (session: vscode.DebugSession): vscode.ProviderResult<vscode.DebugAdapterTracker> {
return {
onDidSendMessage: (message: any) => {
if (message.type !== 'response')
return;
const resolver = popWaitRequestResolver(message.command, session.id);
if (resolver)
resolver();
}
};
}
})];
}

export async function run(): Promise<void> {
Expand All @@ -51,7 +65,7 @@ export async function run(): Promise<void> {
// Add files to the test suite
files.forEach(file => mocha.addFile(path.resolve(testsPath, file)));

await primeExtension();
const toDispose = await primeExtension();

await new Promise((resolve, reject) => {
// Run the mocha test
Expand All @@ -64,7 +78,7 @@ export async function run(): Promise<void> {
resolve(undefined);
}
});
});
}).finally(() => { toDispose.forEach(d => d.dispose()) });

if (!is_vscode)
console.log('>>>THEIA TESTS PASSED<<<');
Expand Down
35 changes: 17 additions & 18 deletions clients/vscode-hlasmplugin/src/test/suite/integration.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import * as assert from 'assert';
import * as vscode from 'vscode';
import * as path from 'path';
import * as helper from './testHelper';
import { waitForDiagnostics } from './testHelper';

suite('Integration Test Suite', () => {
const workspace_file = 'open';
Expand Down Expand Up @@ -51,18 +52,22 @@ suite('Integration Test Suite', () => {
assert.ok(openDiags.length == 1 && openDiags[0].code == 'M003', 'Wrong diagnostic');
}).timeout(10000).slow(1000);

// test completion for instructions
test('Completion Instructions test', async () => {
await helper.insertString(editor, new vscode.Position(7, 1), 'L');

async function insertBestCompletion() {
// for some reason insertBestCompletion does not do anything
await vscode.commands.executeCommand('editor.action.triggerSuggest');
await helper.sleep(1000);

await vscode.commands.executeCommand('acceptSelectedSuggestion');
await helper.sleep(1000);
}

// test completion for instructions
test('Completion Instructions test', async () => {
await helper.insertString(editor, new vscode.Position(7, 1), 'L');

const text = editor.document.getText();
const acceptedLine = text.split('\n')[7];
await insertBestCompletion();

const acceptedLine = editor.document.getText(new vscode.Range(7, 0, 8, 0));

assert.ok(acceptedLine.includes('L R1,D12U2(X2,B2)'), 'Wrong suggestion result' + acceptedLine);
}).timeout(10000).slow(4000);
Expand All @@ -71,14 +76,9 @@ suite('Integration Test Suite', () => {
test('Completion Variable symbol test', async () => {
await helper.insertString(editor, new vscode.Position(8, 0), '&');

await vscode.commands.executeCommand('editor.action.triggerSuggest');
await helper.sleep(1000);

await vscode.commands.executeCommand('acceptSelectedSuggestion')
await helper.sleep(1000);
await insertBestCompletion();

const text = editor.document.getText();
const acceptedLine = text.split('\n')[8];
const acceptedLine = editor.document.getText(new vscode.Range(8, 0, 9, 0));

assert.ok(acceptedLine.includes('&VAR'), 'Wrong suggestion result' + acceptedLine);
}).timeout(10000).slow(4000);
Expand Down Expand Up @@ -133,13 +133,12 @@ suite('Integration Test Suite', () => {
}).timeout(20000).slow(10000);

async function openDocumentAndCheckDiags(workspace_file: string) {
await helper.showDocument(workspace_file);
await helper.sleep(1500);
const diagsChange = waitForDiagnostics(workspace_file);
const uri = (await helper.showDocument(workspace_file)).document.uri.toString();

const allDiags = vscode.languages.getDiagnostics();
const patternDiags = allDiags.find(pair => pair[0].path.endsWith(workspace_file));
const [, diags] = (await diagsChange).find(pair => pair[0].toString() === uri);

assert.ok(patternDiags === undefined, "Library patterns are not working for file: " + workspace_file);
assert.ok(diags && diags.length === 1 && diags[0].code === 'MNOTE' && diags[0].message === 'DONE', "Library patterns are not working for file: " + workspace_file);
}

// verify that library patterns are working
Expand Down
116 changes: 77 additions & 39 deletions clients/vscode-hlasmplugin/src/test/suite/testHelper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,94 +13,122 @@
*/
import * as assert from 'assert';
import * as vscode from 'vscode';
import { integer } from 'vscode-languageclient';

const debuggerWaitRequests = new Map<string, () => void>();

export function registerWaitRequest(message: string, sessionId: string): Promise<void> {
return new Promise<void>((resolve) => debuggerWaitRequests.set(sessionId + '_' + message, resolve));
}

export function popWaitRequestResolver(message: string, sessionId: string): () => void {
const key = sessionId + '_' + message;

const result = debuggerWaitRequests.get(key);
if (result)
debuggerWaitRequests.delete(key);

return result;
}

export function activeEditorChanged(): Promise<void> {
return new Promise<void>((resolve) => {
const listener = vscode.window.onDidChangeActiveTextEditor(() => {
listener.dispose();
resolve();
})
});
}

export function getWorkspacePath(): string {
return vscode.workspace.workspaceFolders[0].uri.fsPath;
}

export async function showDocument(workspace_file: string, language_id: string | undefined = undefined) {
export async function getWorkspaceFile(workspace_file: string) {
const files = await vscode.workspace.findFiles(workspace_file);

assert.ok(files && files[0]);
const file = files[0];

return files[0];
}

export async function showDocument(workspace_file: string, language_id: string | undefined = undefined) {
// open and show the file
let document = await vscode.workspace.openTextDocument(file);
let document = await vscode.workspace.openTextDocument(await getWorkspaceFile(workspace_file));
if (language_id)
document = await vscode.languages.setTextDocumentLanguage(document, language_id);

return { editor: await vscode.window.showTextDocument(document), document };
const visible = activeEditorChanged();
const result = { editor: await vscode.window.showTextDocument(document), document };
await visible;
return result;
}

export async function closeAllEditors() {
await vscode.commands.executeCommand('workbench.action.files.revert');
// workbench.action.closeAllEditors et al. saves content
while (vscode.window.activeTextEditor !== undefined) {
await vscode.commands.executeCommand('workbench.action.closeActiveEditor');
await sleep(500);
}
}

export function moveCursor(editor: vscode.TextEditor, position: vscode.Position) {
editor.selection = new vscode.Selection(position, position);
await vscode.commands.executeCommand('workbench.action.closeAllEditors');
}

export async function toggleBreakpoints(file: string, lines: Array<integer>) {
const editor = (await showDocument(file)).editor;
await sleep(1000);
export async function addBreakpoints(file: string, lines: Array<number>) {
const document = (await showDocument(file, 'hlasm')).document;

for (const line of lines) {
moveCursor(editor, new vscode.Position(line, 0));
await vscode.commands.executeCommand('editor.debug.action.toggleBreakpoint');
}

await sleep(1000);
await vscode.debug.addBreakpoints(lines.map(l => new vscode.SourceBreakpoint(new vscode.Location(document.uri, new vscode.Position(l, 0)), true)));
}

export async function removeAllBreakpoints() {
await vscode.debug.removeBreakpoints(vscode.debug.breakpoints);
}

await vscode.commands.executeCommand('workbench.debug.viewlet.action.removeAllBreakpoints');
await sleep(1000);
function sessionStoppedEvent(session: vscode.DebugSession = vscode.debug.activeDebugSession) {
if (!session)
return Promise.resolve();
else
return registerWaitRequest("scopes", session.id);
}

export async function debugStartSession(): Promise<vscode.DebugSession> {
export async function debugStartSession(waitForStopped = true): Promise<vscode.DebugSession> {
const session_started_event = new Promise<vscode.DebugSession>((resolve) => {
// when the debug session starts
const disposable = vscode.debug.onDidStartDebugSession((session) => {
disposable.dispose();
resolve(session);
if (waitForStopped)
sessionStoppedEvent(session).then(() => resolve(session));
else
resolve(session);
});
});
// start debugging
if (!await vscode.debug.startDebugging(vscode.workspace.workspaceFolders[0], 'Macro tracer: current program'))
throw new Error("Failed to start a debugging session");

const session = await session_started_event;
await sleep(1000);

return session;
}

export async function debugContinue() {
const ready = sessionStoppedEvent();
await vscode.commands.executeCommand('workbench.action.debug.continue');
await sleep(1000);
await ready;
}

export async function debugStepOver(steps: integer) {
export async function debugStepOver(steps: number) {
while (steps) {
const ready = sessionStoppedEvent();
await vscode.commands.executeCommand('workbench.action.debug.stepOver');
await sleep(1000);
await ready;
steps--;
}
}

export async function debugStepInto() {
const ready = sessionStoppedEvent();
await vscode.commands.executeCommand('workbench.action.debug.stepInto');
await sleep(1000);
await ready;
}

export async function debugStop() {
await vscode.commands.executeCommand('workbench.action.debug.stop');
await vscode.debug.stopDebugging();
}

export async function insertString(editor: vscode.TextEditor, position: vscode.Position, str: string): Promise<vscode.Position> {
Expand All @@ -113,6 +141,7 @@ export async function insertString(editor: vscode.TextEditor, position: vscode.P
const lines = str_split.length;

const movePosition = new vscode.Position(position.line + lines - 1, lines == 1 ? position.character + str.length : str_split[lines].length);

editor.selection = new vscode.Selection(movePosition, movePosition);

return movePosition;
Expand All @@ -126,13 +155,22 @@ export function timeout(ms: number, error_message: string | undefined = undefine
return new Promise<void>((_, reject) => { setTimeout(() => reject(error_message && Error(error_message)), ms); });
}

export async function waitForDiagnostics(filename: string) {
return new Promise<[vscode.Uri, vscode.Diagnostic[]][]>((resolve, reject) => {
const listener = vscode.languages.onDidChangeDiagnostics((e) => {
if (!e.uris.find(v => v.path.endsWith('/' + filename)))
return;
listener.dispose();
resolve(vscode.languages.getDiagnostics());
export async function waitForDiagnostics(file: string | vscode.Uri) {
const result = new Promise<[vscode.Uri, vscode.Diagnostic[]][]>((resolve) => {
const file_promise = typeof file === 'string' ? getWorkspaceFile(file).then(uri => uri.toString()) : Promise.resolve(file.toString());

let listener = vscode.languages.onDidChangeDiagnostics((e) => {
file_promise.then((file) => {
if (!listener)
return;
if (!e.uris.find(v => v.toString() === file))
return;
listener.dispose();
listener = null;
resolve(vscode.languages.getDiagnostics());
});
});
});

return result;
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,6 @@
TEST
!#$%&'()+,-.0123456789;=@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`{}~macro

MNOTE 'DONE'

END
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,6 @@
TEST_4_BYTE
TEST_2_BYTE

MNOTE 'DONE'

END
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,6 @@
TEST1
TEST2

MNOTE 'DONE'

END
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,6 @@
TEST
TEST_1_BYTE

MNOTE 'DONE'

END
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,6 @@
TEST
TEST_2_BYTE

MNOTE 'DONE'

END
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,6 @@
TEST
TEST_3_BYTE

MNOTE 'DONE'

END
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,6 @@
TEST
TEST_4_BYTE

MNOTE 'DONE'

END
Loading

0 comments on commit 67913e6

Please sign in to comment.