Changeset View
Changeset View
Standalone View
Standalone View
debuggers/gdb/unittests/test_gdb.cpp
Show All 18 Lines | |||||
19 | 19 | | |||
20 | #include "test_gdb.h" | 20 | #include "test_gdb.h" | ||
21 | 21 | | |||
22 | #include "debugsession.h" | 22 | #include "debugsession.h" | ||
23 | #include "gdbframestackmodel.h" | 23 | #include "gdbframestackmodel.h" | ||
24 | #include "mi/micommand.h" | 24 | #include "mi/micommand.h" | ||
25 | #include "mi/milexer.h" | 25 | #include "mi/milexer.h" | ||
26 | #include "mi/miparser.h" | 26 | #include "mi/miparser.h" | ||
27 | #include "unittest/unittest.h" | ||||
27 | 28 | | |||
28 | #include <execute/iexecuteplugin.h> | 29 | #include <execute/iexecuteplugin.h> | ||
29 | #include <debugger/breakpoint/breakpoint.h> | 30 | #include <debugger/breakpoint/breakpoint.h> | ||
30 | #include <debugger/breakpoint/breakpointmodel.h> | 31 | #include <debugger/breakpoint/breakpointmodel.h> | ||
31 | #include <debugger/framestack/framestackmodel.h> | 32 | #include <debugger/framestack/framestackmodel.h> | ||
32 | #include <debugger/interfaces/ibreakpointcontroller.h> | 33 | #include <debugger/interfaces/ibreakpointcontroller.h> | ||
33 | #include <debugger/interfaces/ivariablecontroller.h> | 34 | #include <debugger/interfaces/ivariablecontroller.h> | ||
34 | #include <debugger/variable/variablecollection.h> | 35 | #include <debugger/variable/variablecollection.h> | ||
Show All 13 Lines | |||||
48 | #include <QDir> | 49 | #include <QDir> | ||
49 | #include <QFileInfo> | 50 | #include <QFileInfo> | ||
50 | #include <QStandardPaths> | 51 | #include <QStandardPaths> | ||
51 | #include <QSignalSpy> | 52 | #include <QSignalSpy> | ||
52 | #include <QtTest/QTest> | 53 | #include <QtTest/QTest> | ||
53 | #include <QTemporaryFile> | 54 | #include <QTemporaryFile> | ||
54 | 55 | | |||
55 | using KDevelop::AutoTestShell; | 56 | using KDevelop::AutoTestShell; | ||
56 | 57 | using namespace KDevMI::UnitTest; | |||
57 | namespace KDevMI { namespace GDB { | | |||
58 | | ||||
59 | QUrl findExecutable(const QString& name) | | |||
60 | { | | |||
61 | QFileInfo info(qApp->applicationDirPath() + "/unittests/" + name); | | |||
62 | Q_ASSERT(info.exists()); | | |||
63 | Q_ASSERT(info.isExecutable()); | | |||
64 | return QUrl::fromLocalFile(info.canonicalFilePath()); | | |||
65 | } | | |||
66 | | ||||
67 | QString findSourceFile(const QString& name) | | |||
68 | { | | |||
69 | QFileInfo info(QFileInfo(__FILE__).dir().absoluteFilePath(name)); | | |||
70 | Q_ASSERT(info.exists()); | | |||
71 | return info.canonicalFilePath(); | | |||
72 | } | | |||
73 | | ||||
74 | static bool isAttachForbidden(const char * file, int line) | | |||
75 | { | | |||
76 | // if on linux, ensure we can actually attach | | |||
77 | QFile canRun("/proc/sys/kernel/yama/ptrace_scope"); | | |||
78 | if (canRun.exists()) { | | |||
79 | if (!canRun.open(QIODevice::ReadOnly)) { | | |||
80 | QTest::qFail("Something is wrong: /proc/sys/kernel/yama/ptrace_scope exists but cannot be read", file, line); | | |||
81 | return true; | | |||
82 | } | | |||
83 | if (canRun.read(1).toInt() != 0) { | | |||
84 | QTest::qSkip("ptrace attaching not allowed, skipping test. To enable it, set /proc/sys/kernel/yama/ptrace_scope to 0.", file, line); | | |||
85 | return true; | | |||
86 | } | | |||
87 | } | | |||
88 | | ||||
89 | return false; | | |||
90 | } | | |||
91 | 58 | | |||
92 | #define SKIP_IF_ATTACH_FORBIDDEN() \ | 59 | #define SKIP_IF_ATTACH_FORBIDDEN() \ | ||
93 | do { \ | 60 | do { \ | ||
94 | if (isAttachForbidden(__FILE__, __LINE__)) \ | 61 | if (isAttachForbidden(__FILE__, __LINE__)) \ | ||
95 | return; \ | 62 | return; \ | ||
96 | } while(0) | 63 | } while(0) | ||
97 | 64 | | |||
65 | #define findSourceFile(name) \ | ||||
66 | findSourceFile(__FILE__, (name)) | ||||
67 | | ||||
68 | namespace KDevMI { namespace GDB { | ||||
69 | | ||||
98 | void GdbTest::initTestCase() | 70 | void GdbTest::initTestCase() | ||
99 | { | 71 | { | ||
100 | AutoTestShell::init(); | 72 | AutoTestShell::init(); | ||
101 | KDevelop::TestCore::initialize(KDevelop::Core::NoUi); | 73 | KDevelop::TestCore::initialize(KDevelop::Core::NoUi); | ||
102 | 74 | | |||
103 | m_iface = KDevelop::ICore::self()->pluginController()->pluginForExtension("org.kdevelop.IExecutePlugin", "kdevexecute")->extension<IExecutePlugin>(); | 75 | m_iface = KDevelop::ICore::self()->pluginController()->pluginForExtension("org.kdevelop.IExecutePlugin", "kdevexecute")->extension<IExecutePlugin>(); | ||
104 | Q_ASSERT(m_iface); | 76 | Q_ASSERT(m_iface); | ||
105 | } | 77 | } | ||
▲ Show 20 Lines • Show All 130 Lines • ▼ Show 20 Line(s) | |||||
236 | private: | 208 | private: | ||
237 | QTime stopWatch; | 209 | QTime stopWatch; | ||
238 | QPointer<DebugSession> session; | 210 | QPointer<DebugSession> session; | ||
239 | const char * condition; | 211 | const char * condition; | ||
240 | const char * file; | 212 | const char * file; | ||
241 | int line; | 213 | int line; | ||
242 | }; | 214 | }; | ||
243 | 215 | | |||
244 | #define WAIT_FOR_STATE(session, state) \ | | |||
245 | do { if (!waitForState((session), (state), __FILE__, __LINE__)) return; } while (0) | | |||
246 | | ||||
247 | #define WAIT_FOR_STATE_AND_IDLE(session, state) \ | | |||
248 | do { if (!waitForState((session), (state), __FILE__, __LINE__, true)) return; } while (0) | | |||
249 | | ||||
250 | #define WAIT_FOR(session, condition) \ | | |||
251 | do { \ | | |||
252 | TestWaiter w((session), #condition, __FILE__, __LINE__); \ | | |||
253 | while (w.waitUnless((condition))) /* nothing */ ; \ | | |||
254 | } while(0) | | |||
255 | | ||||
256 | #define COMPARE_DATA(index, expected) \ | | |||
257 | compareData((index), (expected), __FILE__, __LINE__) | | |||
258 | | ||||
259 | void compareData(QModelIndex index, QString expected, const char *file, int line) | | |||
260 | { | | |||
261 | QString s = index.model()->data(index, Qt::DisplayRole).toString(); | | |||
262 | if (s != expected) { | | |||
263 | QFAIL(qPrintable(QString("'%0' didn't match expected '%1' in %2:%3").arg(s).arg(expected).arg(file).arg(line))); | | |||
264 | } | | |||
265 | } | | |||
266 | | ||||
267 | static const QString debugeeFileName = findSourceFile("debugee.cpp"); | 216 | static const QString debugeeFileName = findSourceFile("debugee.cpp"); | ||
268 | 217 | | |||
269 | KDevelop::BreakpointModel* breakpoints() | 218 | KDevelop::BreakpointModel* breakpoints() | ||
270 | { | 219 | { | ||
271 | return KDevelop::ICore::self()->debugController()->breakpointModel(); | 220 | return KDevelop::ICore::self()->debugController()->breakpointModel(); | ||
272 | } | 221 | } | ||
273 | 222 | | |||
274 | void GdbTest::testStdOut() | 223 | void GdbTest::testStdOut() | ||
▲ Show 20 Lines • Show All 1714 Lines • ▼ Show 20 Line(s) | 1930 | #ifdef HAVE_PATH_WITH_SPACES_TEST | |||
1989 | 1938 | | |||
1990 | WAIT_FOR_STATE(session, DebugSession::PausedState); | 1939 | WAIT_FOR_STATE(session, DebugSession::PausedState); | ||
1991 | QCOMPARE(b->state(), KDevelop::Breakpoint::CleanState); | 1940 | QCOMPARE(b->state(), KDevelop::Breakpoint::CleanState); | ||
1992 | session->run(); | 1941 | session->run(); | ||
1993 | WAIT_FOR_STATE(session, DebugSession::EndedState); | 1942 | WAIT_FOR_STATE(session, DebugSession::EndedState); | ||
1994 | #endif | 1943 | #endif | ||
1995 | } | 1944 | } | ||
1996 | 1945 | | |||
1997 | bool GdbTest::waitForState(DebugSession *session, DebugSession::DebuggerState state, | | |||
1998 | const char *file, int line, bool waitForIdle) | | |||
1999 | { | | |||
2000 | QPointer<DebugSession> s(session); //session can get deleted in DebugController | | |||
2001 | QTime stopWatch; | | |||
2002 | stopWatch.start(); | | |||
2003 | while (s.data()->state() != state || (waitForIdle && s->debuggerStateIsOn(s_dbgBusy))) { | | |||
2004 | if (stopWatch.elapsed() > 5000) { | | |||
2005 | qWarning() << "current state" << s.data()->state() << "waiting for" << state; | | |||
2006 | QTest::qFail(qPrintable(QString("Timeout before reaching state %0").arg(state)), | | |||
2007 | file, line); | | |||
2008 | return false; | | |||
2009 | } | | |||
2010 | QTest::qWait(20); | | |||
2011 | if (!s) { | | |||
2012 | if (state == DebugSession::EndedState) | | |||
2013 | break; | | |||
2014 | QTest::qFail(qPrintable(QString("Session ended before reaching state %0").arg(state)), | | |||
2015 | file, line); | | |||
2016 | return false; | | |||
2017 | } | | |||
2018 | } | | |||
2019 | if (!waitForIdle && state != DebugSession::EndedState) { | | |||
2020 | // legacy behavior for tests that implicitly may require waiting for idle, | | |||
2021 | // but which were written before waitForIdle was added | | |||
2022 | QTest::qWait(100); | | |||
2023 | } | | |||
2024 | | ||||
2025 | qDebug() << "Reached state " << state << " in " << file << ':' << line; | | |||
2026 | return true; | | |||
2027 | } | | |||
2028 | } // end of namespace GDB | 1946 | } // end of namespace GDB | ||
2029 | } // end of namespace KDevMI | 1947 | } // end of namespace KDevMI | ||
2030 | 1948 | | |||
2031 | QTEST_MAIN(KDevMI::GDB::GdbTest) | 1949 | QTEST_MAIN(KDevMI::GDB::GdbTest) | ||
2032 | 1950 | | |||
2033 | 1951 | | |||
2034 | #include "test_gdb.moc" | 1952 | #include "test_gdb.moc" | ||
2035 | #include "moc_test_gdb.cpp" | 1953 | #include "moc_test_gdb.cpp" | ||
2036 | 1954 | |