Skip to content
This repository has been archived by the owner on Jan 26, 2022. It is now read-only.

Commit

Permalink
Merge pull request #13 from jtpio/test-protocol
Browse files Browse the repository at this point in the history
Add tests for stackTrace, scopes, variables
  • Loading branch information
afshin committed Aug 30, 2019
2 parents 29a1910 + 23b2a81 commit 6d08bed
Show file tree
Hide file tree
Showing 5 changed files with 192 additions and 6 deletions.
2 changes: 0 additions & 2 deletions README.md
Expand Up @@ -39,8 +39,6 @@ XEUS_LOG=1 jupyter lab --no-browser --watch

### Tests

Make sure `xeus-python` is installed and `jupyter --paths` points to where the kernel is installed.

To run the tests:

```bash
Expand Down
1 change: 0 additions & 1 deletion azure-pipelines.yml
Expand Up @@ -28,7 +28,6 @@ steps:

- bash: |
source activate jupyterlab-debugger
export JUPYTER_PATH=${CONDA_PREFIX}/share/jupyter
export XEUS_LOG=1
jlpm run test
displayName: Run the tests
Expand Down
1 change: 1 addition & 0 deletions src/tokens.ts
Expand Up @@ -114,6 +114,7 @@ export namespace IDebugger {
terminateThreads: DebugProtocol.TerminateThreadsArguments;
threads: {};
updateCell: IUpdateCellArguments;
variables: DebugProtocol.VariablesArguments;
};

/**
Expand Down
28 changes: 27 additions & 1 deletion tests/run-test.py
@@ -1,10 +1,36 @@
# Copyright (c) Jupyter Development Team.
# Distributed under the terms of the Modified BSD License.

import json
import os
from jupyterlab.tests.test_app import run_jest
from os.path import join as pjoin

from jupyter_core import paths
from jupyterlab.tests.test_app import run_jest, JestApp

HERE = os.path.realpath(os.path.dirname(__file__))


def _install_xpython_kernel():
# Mimics: https://github.com/jupyterlab/jupyterlab/blob/cd2fb6ac3ecfae2bb4bcab84797932e625e9bb2f/jupyterlab/tests/test_app.py#L80-L95
kernel_json = {
'argv': [
'xpython',
'-f', '{connection_file}'
],
'display_name': "xpython",
'language': 'python'
}
kernel_dir = pjoin(paths.jupyter_data_dir(), 'kernels', 'xpython')
os.makedirs(kernel_dir)
with open(pjoin(kernel_dir, 'kernel.json'), 'w') as f:
f.write(json.dumps(kernel_json))


if __name__ == '__main__':
jest_app = JestApp.instance()

# install the kernel spec for xeus-python
_install_xpython_kernel()

run_jest(HERE)
166 changes: 164 additions & 2 deletions tests/src/session.spec.ts
Expand Up @@ -5,7 +5,15 @@ import { expect } from 'chai';

import { ClientSession, IClientSession } from '@jupyterlab/apputils';

import { createClientSession } from '@jupyterlab/testutils';
import { createClientSession, sleep } from '@jupyterlab/testutils';

import { find } from '@phosphor/algorithm';

import { PromiseDelegate } from '@phosphor/coreutils';

import { DebugProtocol } from 'vscode-debugprotocol';

import { IDebugger } from '../../lib/tokens';

import { DebugSession } from '../../lib/session';

Expand Down Expand Up @@ -71,7 +79,7 @@ describe('DebugSession', () => {
expect(reply.body.sourcePath).to.contain('.py');
});

it('should handle replies with success false', async () => {
it.skip('should handle replies with success false', async () => {
const reply = await debugSession.sendRequest('evaluate', {
expression: 'a'
});
Expand All @@ -81,3 +89,157 @@ describe('DebugSession', () => {
});
});
});

describe('protocol', () => {
const code = [
'i = 0',
'i += 1',
'i += 1',
'j = i**2',
'j += 1',
'print(i, j)'
].join('\n');

const breakpoints: DebugProtocol.SourceBreakpoint[] = [
{ line: 3 },
{ line: 5 }
];

let client: IClientSession;
let debugSession: DebugSession;
let threadId: number = 1;

beforeEach(async () => {
client = await createClientSession({
kernelPreference: {
name: 'xpython'
}
});
await (client as ClientSession).initialize();
await client.kernel.ready;
debugSession = new DebugSession({ client });
await debugSession.start();

debugSession.eventMessage.connect(
(sender: DebugSession, event: IDebugger.ISession.Event) => {
const eventName = event.event;
if (eventName === 'thread') {
const msg = event as DebugProtocol.ThreadEvent;
threadId = msg.body.threadId;
}
}
);

const reply = await debugSession.sendRequest('updateCell', {
cellId: 0,
nextId: 1,
code
});
await debugSession.sendRequest('setBreakpoints', {
breakpoints,
source: { path: reply.body.sourcePath },
sourceModified: false
});
await debugSession.sendRequest('configurationDone', {});

// trigger an execute_request
client.kernel.requestExecute({ code });

// TODO: handle events instead
await sleep(2000);
});

afterEach(async () => {
await debugSession.stop();
debugSession.dispose();
await client.shutdown();
client.dispose();
});

describe('#stackTrace', () => {
it('should return the correct stackframes', async () => {
const reply = await debugSession.sendRequest('stackTrace', {
threadId
});
expect(reply.success).to.be.true;
const stackFrames = reply.body.stackFrames;
expect(stackFrames.length).to.equal(2);
const frame = stackFrames[0];
// first breakpoint
expect(frame.line).to.equal(3);
});
});

describe('#scopes', () => {
it('should return the correct scopes', async () => {
const stackFramesReply = await debugSession.sendRequest('stackTrace', {
threadId
});
const frameId = stackFramesReply.body.stackFrames[0].id;
const scopesReply = await debugSession.sendRequest('scopes', {
frameId
});
const scopes = scopesReply.body.scopes;
expect(scopes.length).to.equal(1);
expect(scopes[0].name).to.equal('Locals');
});
});

const getVariables = async () => {
const stackFramesReply = await debugSession.sendRequest('stackTrace', {
threadId
});
const frameId = stackFramesReply.body.stackFrames[0].id;
const scopesReply = await debugSession.sendRequest('scopes', {
frameId
});
const scopes = scopesReply.body.scopes;
const variablesReference = scopes[0].variablesReference;
const variablesReply = await debugSession.sendRequest('variables', {
variablesReference
});
return variablesReply.body.variables;
};

describe('#variables', () => {
it('should return the variables and their values', async () => {
const variables = await getVariables();
expect(variables.length).to.be.greaterThan(0);
const i = find(variables, variable => variable.name === 'i');
expect(i).to.exist;
expect(i.type).to.equal('int');
expect(i.value).to.equal('1');
});
});

describe('#continue', () => {
it.skip('should proceed to the next breakpoint', async () => {
let events: string[] = [];
const eventsFuture = new PromiseDelegate<string[]>();
debugSession.eventMessage.connect((sender, event) => {
events.push(event.event);
// aggregate the next 2 debug events
if (events.length === 2) {
eventsFuture.resolve(events);
}
});

await debugSession.sendRequest('continue', { threadId });

// wait for debug events
const debugEvents = await eventsFuture.promise;
expect(debugEvents).to.deep.equal(['continued', 'stopped']);

const variables = await getVariables();
const i = find(variables, variable => variable.name === 'i');
expect(i).to.exist;
expect(i.type).to.equal('int');
expect(i.value).to.equal('2');

const j = find(variables, variable => variable.name === 'j');
expect(j).to.exist;
expect(j.type).to.equal('int');
expect(j.value).to.equal('4');
});
});
});

0 comments on commit 6d08bed

Please sign in to comment.