Commit ba4a7221 authored by Peifeng Yu's avatar Peifeng Yu
Browse files

Fix GDB unit tests for 5.0 branch

Summary:
This fixes
- testStdOut (based on D2175)
- testUpdateBreakpoint (already in master)
- testStackSwitchThread

Test Plan: GDB unit tests

Reviewers: #kdevelop, kfunk

Reviewed By: #kdevelop, kfunk

Subscribers: kdevelop-devel

Differential Revision: https://phabricator.kde.org/D2179
parent a844f606
......@@ -35,6 +35,7 @@
#include "debug.h"
#include <QFileInfo>
#include <QRegularExpression>
#include <KI18n/KLocalizedString>
using namespace GDBDebugger;
......@@ -50,6 +51,11 @@ DebugJob::DebugJob( GDBDebugger::CppDebuggerPlugin* p, KDevelop::ILaunchConfigur
m_session = p->createSession();
connect(m_session, &DebugSession::applicationStandardOutputLines, this, &DebugJob::stderrReceived);
connect(m_session, &DebugSession::applicationStandardErrorLines, this, &DebugJob::stdoutReceived);
connect(m_session, &DebugSession::gdbInternalCommandStdout,
this, [this](const QString &output){
this->stdoutReceived(output.split(QRegularExpression("[\r\n]"), QString::SkipEmptyParts));
});
connect(m_session, &DebugSession::finished, this, &DebugJob::done );
if (launchcfg->project()) {
......
......@@ -884,6 +884,8 @@ bool DebugSession::startDebugger(KDevelop::ILaunchConfiguration* cfg)
&DebugSession::gdbUserCommandStdout);
connect(gdb, &GDB::internalCommandOutput, this,
&DebugSession::gdbInternalCommandStdout);
connect(gdb, &GDB::debuggerInternalOutput, this,
&DebugSession::gdbInternalOutput);
connect(gdb, &GDB::ready, this, &DebugSession::gdbReady);
connect(gdb, &GDB::gdbExited, this, &DebugSession::gdbExited);
......
......@@ -254,6 +254,7 @@ Q_SIGNALS:
void ttyStderr (const QByteArray& output);
void gdbInternalCommandStdout (const QString& output);
void gdbUserCommandStdout (const QString& output);
void gdbInternalOutput (const QString& output);
void gdbStateChanged(DBGStateFlags oldState, DBGStateFlags newState);
void debuggerAbnormalExit();
......
......@@ -192,7 +192,7 @@ void GDB::readyReadStandardOutput()
void GDB::readyReadStandardError()
{
process_->setReadChannel(QProcess::StandardOutput);
emit internalCommandOutput(QString::fromUtf8(process_->readAll()));
emit debuggerInternalOutput(QString::fromUtf8(process_->readAll()));
}
void GDB::processLine(const QByteArray& line)
......@@ -308,17 +308,16 @@ void GDB::processLine(const QByteArray& line)
if (s.subkind == GDBMI::StreamRecord::Target) {
emit applicationOutput(s.message);
} else {
} else if (s.subkind == GDBMI::StreamRecord::Console) {
if (currentCmd_ && currentCmd_->isUserCommand())
emit userCommandOutput(s.message);
else if (s.subkind == GDBMI::StreamRecord::Console) {
emit applicationOutput(s.message);
} else {
else
emit internalCommandOutput(s.message);
}
if (currentCmd_)
currentCmd_->newOutput(s.message);
} else {
emit debuggerInternalOutput(s.message);
}
emit streamRecord(s);
......
......@@ -113,10 +113,13 @@ Q_SIGNALS:
void userCommandOutput(const QString& s);
/** Reports output of a command issued internally
by KDevelop. At the moment, stderr output from
GDB and the 'log' MI channel will be also routed here. */
by KDevelop. */
void internalCommandOutput(const QString& s);
/** Reports debugger interal output, including stderr output from debugger
and the 'log' MI channel */
void debuggerInternalOutput(const QString& s);
private Q_SLOTS:
void readyReadStandardOutput();
void readyReadStandardError();
......
......@@ -24,6 +24,8 @@
#include <KLocalizedString>
#include <algorithm>
using namespace KDevelop;
QString getFunctionOrAddress(const GDBMI::Value &frame)
......@@ -59,25 +61,26 @@ void GdbFrameStackModel::handleThreadInfo(const GDBMI::ResultRecord& r)
{
const GDBMI::Value& threads = r["threads"];
// Traverse GDB threads in backward order -- since GDB
// reports them in backward order. We want UI to
// show thread IDs in the natural order.
// FIXME: make the code independent of whatever craziness
// gdb might have tomorrow.
QList<KDevelop::FrameStackModel::ThreadItem> threadsList;
int gidx = threads.size()-1;
for (; gidx >= 0; --gidx) {
KDevelop::FrameStackModel::ThreadItem i;
const GDBMI::Value & threadMI = threads[gidx];
i.nr = threadMI["id"].toInt();
QList<FrameStackModel::ThreadItem> threadsList;
for (int i = 0; i!= threads.size(); ++i) {
const auto &threadMI = threads[i];
FrameStackModel::ThreadItem threadItem;
threadItem.nr = threadMI["id"].toInt();
if (threadMI["state"].literal() == "stopped") {
i.name = getFunctionOrAddress(threads[gidx]["frame"]);
threadItem.name = getFunctionOrAddress(threadMI["frame"]);
} else {
i.name = i18n("(running)");
i18n("(running)");
}
threadsList << i;
threadsList << threadItem;
}
// Sort the list by id, some old version of GDB
// reports them in backward order. We want UI to
// show thread IDs in the natural order.
std::sort(threadsList.begin(), threadsList.end(),
[](const FrameStackModel::ThreadItem &a, const FrameStackModel::ThreadItem &b){
return a.nr < b.nr;
});
setThreads(threadsList);
if (r.hasField("current-thread-id")) {
int currentThreadId = r["current-thread-id"].toInt();
......
......@@ -137,6 +137,9 @@ void GDBOutputWidget::currentSessionChanged(KDevelop::IDebugSession* s)
this, &GDBOutputWidget::slotInternalCommandStdout);
connect(session, &DebugSession::gdbUserCommandStdout,
this, &GDBOutputWidget::slotUserCommandStdout);
// debugger internal output, treat it as an internal command output
connect(session, &DebugSession::gdbInternalOutput,
this, &GDBOutputWidget::slotInternalCommandStdout);
connect(session, &DebugSession::gdbStateChanged,
this, &GDBOutputWidget::slotStateChanged);
......
......@@ -437,23 +437,26 @@ void GdbTest::testUpdateBreakpoint()
TestDebugSession *session = new TestDebugSession;
TestLaunchConfiguration cfg;
// breakpoint 1: line 29
KDevelop::Breakpoint * b = breakpoints()->addCodeBreakpoint(QUrl::fromLocalFile(debugeeFileName), 28);
QCOMPARE(breakpoints()->rowCount(), 1);
session->startProgram(&cfg, m_iface);
// breakpoint 2: line 28
//insert custom command as user might do it using GDB console
session->addCommand(new UserCommand(GDBMI::NonMI, "break "+debugeeFileName+":28"));
WAIT_FOR_STATE(session, DebugSession::PausedState);
QTest::qWait(100);
WAIT_FOR_STATE_AND_IDLE(session, DebugSession::PausedState); // stop at line 28
session->stepInto();
WAIT_FOR_STATE(session, DebugSession::PausedState);
WAIT_FOR_STATE_AND_IDLE(session, DebugSession::PausedState); // stop after step
QCOMPARE(breakpoints()->rowCount(), 2);
b = breakpoints()->breakpoint(1);
QCOMPARE(b->url(), QUrl::fromLocalFile(debugeeFileName));
QCOMPARE(b->line(), 27);
session->run();
WAIT_FOR_STATE(session, DebugSession::PausedState); // stop at line 29
session->run();
WAIT_FOR_STATE(session, DebugSession::EndedState);
}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment