Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Handling the ContinuedEvent (Tests) #336

Closed
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
30 changes: 30 additions & 0 deletions src/events/continuedEvent.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/*********************************************************************
* Copyright (c) 2024 Renesas Electronics Corporation and others
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*********************************************************************/
import { Event } from '@vscode/debugadapter';
import { DebugProtocol } from '@vscode/debugprotocol';

export class ContinuedEvent
extends Event
implements DebugProtocol.ContinuedEvent
{
public body: {
threadId: number;
allThreadsContinued?: boolean;
};

constructor(threadId: number, allThreadsContinued = false) {
super('continued');

this.body = {
threadId,
allThreadsContinued,
};
}
}
File renamed without changes.
42 changes: 39 additions & 3 deletions src/gdb/GDBDebugSessionBase.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@ import {
TerminatedEvent,
} from '@vscode/debugadapter';
import { DebugProtocol } from '@vscode/debugprotocol';
import { StoppedEvent } from '../stoppedEvent';
import { ContinuedEvent } from '../events/continuedEvent';
import { StoppedEvent } from '../events/stoppedEvent';
import { VarObjType } from '../varManager';
import {
FrameReference,
Expand Down Expand Up @@ -1601,6 +1602,37 @@ export abstract class GDBDebugSessionBase extends LoggingDebugSession {
}
}

protected sendContinuedEvent(
threadId: number,
allThreadsContinued?: boolean
) {
// Reset frame handles and variables for new context
this.frameHandles.reset();
this.variableHandles.reset();
// Send the event
this.sendEvent(new ContinuedEvent(threadId, allThreadsContinued));
}

protected handleGDBResume(result: any) {
const getThreadId = (resultData: any) => {
return parseInt(resultData['thread-id'], 10);
};
const getAllThreadsContinued = (resultData: any) => {
return (
!!resultData['thread-id'] && resultData['thread-id'] === 'all'
);
};

const isAllThreadsContinued = getAllThreadsContinued(result);
if (isAllThreadsContinued) {
// If all threads continued, then the value of the 'thread-id' is 'all',
// hence, there isn't a thread id number. We are sending the thread id as '1'
// along with the allThreadsContinued=true information.
return this.sendContinuedEvent(1, true);
}
return this.sendContinuedEvent(getThreadId(result));
}

protected handleGDBAsync(resultClass: string, resultData: any) {
const updateIsRunning = () => {
this.isRunning = this.threads.length ? true : false;
Expand All @@ -1613,9 +1645,10 @@ export abstract class GDBDebugSessionBase extends LoggingDebugSession {
switch (resultClass) {
case 'running':
if (this.gdb.isNonStopMode()) {
const id = parseInt(resultData['thread-id'], 10);
const rawId = resultData['thread-id'];
const id = parseInt(rawId, 10);
for (const thread of this.threads) {
if (thread.id === id) {
if (thread.id === id || rawId === 'all') {
thread.running = true;
}
}
Expand All @@ -1625,6 +1658,9 @@ export abstract class GDBDebugSessionBase extends LoggingDebugSession {
}
}
updateIsRunning();
if (this.isInitialized) {
this.handleGDBResume(resultData);
}
break;
case 'stopped': {
let suppressHandleGDBStopped = false;
Expand Down
34 changes: 33 additions & 1 deletion src/integration-tests/continues.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import {
getScopes,
gdbNonStop,
} from './utils';
import { expect } from 'chai';
import { expect, assert } from 'chai';
import * as path from 'path';

describe('continues', async function () {
Expand Down Expand Up @@ -55,4 +55,36 @@ describe('continues', async function () {
});
expect(continueResponse.body.allThreadsContinued).to.eq(!gdbNonStop);
});

it('handles async continued events', async function () {
await dc.setBreakpointsRequest({
source: {
name: 'count.c',
path: path.join(testProgramsDir, 'count.c'),
},
breakpoints: [
{
column: 1,
line: 4,
},
],
});
await dc.configurationDoneRequest();
await dc.waitForEvent('stopped');
const scope = await getScopes(dc);
dc.continueRequest({
threadId: scope.thread.id,
});
const event = await dc.waitForEvent('continued');

assert.deepEqual<any>(
event.body,
gdbNonStop
? {
threadId: 1,
allThreadsContinued: false,
}
: { threadId: 1, allThreadsContinued: true }
);
});
});
93 changes: 92 additions & 1 deletion src/integration-tests/multithread.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import {
gdbNonStop,
fillDefaults,
} from './utils';
import { expect } from 'chai';
import { assert, expect } from 'chai';
import * as path from 'path';
import { fail } from 'assert';
import * as os from 'os';
Expand All @@ -36,6 +36,7 @@ describe('multithread', async function () {

const lineTags = {
LINE_MAIN_ALL_THREADS_STARTED: 0,
LINE_THREAD_IN_HELLO: 0,
};

before(function () {
Expand Down Expand Up @@ -182,4 +183,94 @@ describe('multithread', async function () {
}
}
});

it.only('async resume for gdb-non-stop off', async function () {
if (gdbNonStop) {
// This test is covering only gdb-non-stop off
this.skip();
}

await dc.launchRequest(
fillDefaults(this.test, {
program,
})
);
await dc.setBreakpointsRequest({
source: {
path: source,
},
breakpoints: [
{
line: lineTags['LINE_MAIN_ALL_THREADS_STARTED'],
},
{
line: lineTags['LINE_THREAD_IN_HELLO'],
},
],
});


await dc.configurationDoneRequest();
await dc.waitForEvent('stopped');

const threads = await dc.threadsRequest();

// make sure that there is at least 6 threads.
expect(threads.body.threads).length.greaterThanOrEqual(6);

// Any thread receive a continue
dc.continueRequest({ threadId: 3 });

const event = await dc.waitForEvent('continued');

assert.deepEqual(event.body, {
threadId: 1,
allThreadsContinued: true,
});
});

it.only('async resume for gdb-non-stop on', async function () {
if (!gdbNonStop) {
// This test is covering only gdb-non-stop on
this.skip();
}

await dc.hitBreakpoint(
fillDefaults(this.test, {
program: program,
}),
{
path: source,
line: lineTags['LINE_MAIN_ALL_THREADS_STARTED'],
}
);

const threads = await dc.threadsRequest();

// make sure that there is at least 6 threads.
expect(threads.body.threads).length.greaterThanOrEqual(6);

// stop the running threads
const runningThreads = threads.body.threads.filter(
(t) => (t as unknown as { running?: boolean }).running
);
for (const thread of runningThreads) {
await dc.pauseRequest({ threadId: thread.id });
await dc.waitForEvent('stopped');
}

for (const thread of threads.body.threads) {
// Send an async continue request and wait for the continue event.
dc.continueRequest({ threadId: thread.id });
const event = await dc.waitForEvent('continued');

assert.deepEqual<any>(
event.body,
{
threadId: thread.id,
allThreadsContinued: false,
}
);
}
});
});
Loading