Commit 9cb910b9 authored by Peifeng Yu's avatar Peifeng Yu
Browse files

Improve gdb plugin unit tests

Summary:
This is a side effect of my work on lldb plugin unit tests, in which I tried to fix the somewhat unreliable test results.

- Move unit test debugees to common folder, make gdb uses common unit test helpers
- Make gdb plugin unit tests more reliable. waitForState now guarantees the session state after returning is exactly the requested one (otherwise fails the test).

The main problem is that DebugSession could end and get deleted when running event loop (i.e. in QTest::qWait).
And this fix adds proper checks to it. This by itself doesn't fix any tests, but it helps when some tests
did goes wrong. Without this fix, they could crash the whole test process due to accessing to deleted object.

Test Plan: gdb plugin unit tests (and actually some lldb plugin unit tests, which is only on local yet)

Reviewers: #kdevelop, apol, kfunk

Reviewed By: #kdevelop, apol, kfunk

Subscribers: kfunk, kdevelop-devel

Differential Revision: https://phabricator.kde.org/D1985
parent 6d7a4cfe
......@@ -254,14 +254,18 @@ private:
} while(0)
#define COMPARE_DATA(index, expected) \
compareData((index), (expected), __FILE__, __LINE__)
do { if(!compareData((index), (expected), __FILE__, __LINE__)) return; } while (0)
void compareData(QModelIndex index, QString expected, const char *file, int line)
bool compareData(QModelIndex index, QString expected, const char *file, int line)
{
QString s = index.model()->data(index, Qt::DisplayRole).toString();
if (s != expected) {
QFAIL(qPrintable(QString("'%0' didn't match expected '%1' in %2:%3").arg(s).arg(expected).arg(file).arg(line)));
QTest::qFail(qPrintable(QString("'%0' didn't match expected '%1' in %2:%3")
.arg(s).arg(expected).arg(file).arg(line)),
file, line);
return false;
}
return true;
}
static const QString debugeeFileName = findSourceFile("debugee.cpp");
......@@ -1997,29 +2001,31 @@ void GdbTest::testPathWithSpace()
bool GdbTest::waitForState(DebugSession *session, DebugSession::DebuggerState state,
const char *file, int line, bool waitForIdle)
{
QPointer<DebugSession> s(session); //session can get deleted in DebugController
QPointer<MIDebugSession> s(session); //session can get deleted in DebugController
QTime stopWatch;
stopWatch.start();
while (s.data()->state() != state || (waitForIdle && s->debuggerStateIsOn(s_dbgBusy))) {
// legacy behavior for tests that implicitly may require waiting for idle,
// but which were written before waitForIdle was added
waitForIdle = waitForIdle || state != MIDebugSession::EndedState;
while (s && (s->state() != state || (waitForIdle && s->debuggerStateIsOn(s_dbgBusy)))) {
if (stopWatch.elapsed() > 5000) {
qWarning() << "current state" << s.data()->state() << "waiting for" << state;
qWarning() << "current state" << s->state() << "waiting for" << state;
QTest::qFail(qPrintable(QString("Timeout before reaching state %0").arg(state)),
file, line);
file, line);
return false;
}
QTest::qWait(20);
if (!s) {
if (state == DebugSession::EndedState)
break;
QTest::qFail(qPrintable(QString("Session ended before reaching state %0").arg(state)),
file, line);
return false;
}
}
if (!waitForIdle && state != DebugSession::EndedState) {
// legacy behavior for tests that implicitly may require waiting for idle,
// but which were written before waitForIdle was added
QTest::qWait(100);
// NOTE: don't wait anymore after leaving the loop. Waiting re-enters event loop and
// may change session state.
if (!s && state != MIDebugSession::EndedState) {
QTest::qFail(qPrintable(QString("Session ended before reaching state %0").arg(state)),
file, line);
return false;
}
qDebug() << "Reached state " << state << " in " << file << ':' << line;
......
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