diff --git a/debuggers/common/tests/CMakeLists.txt b/debuggers/common/tests/CMakeLists.txt --- a/debuggers/common/tests/CMakeLists.txt +++ b/debuggers/common/tests/CMakeLists.txt @@ -4,6 +4,8 @@ message(WARNING "Disabling 'path with spaces' test, this CMake version would create a faulty build.ninja file. Upgrade to at least CMake v3.0") endif() +get_filename_component(GDB_SRC_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../../gdb ABSOLUTE) +get_filename_component(LLDB_SRC_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../../lldb ABSOLUTE) configure_file(debuggers-tests-config.h.in debuggers-tests-config.h) add_subdirectory(debuggees) diff --git a/debuggers/common/tests/debuggees/qhashstring.cpp b/debuggers/common/tests/debuggees/qhashstring.cpp --- a/debuggers/common/tests/debuggees/qhashstring.cpp +++ b/debuggers/common/tests/debuggees/qhashstring.cpp @@ -3,8 +3,8 @@ int main() { QHash h; - h[QStringLiteral("10")] = QStringLiteral("100"); - h[QStringLiteral("20")] = QStringLiteral("200"); - h[QStringLiteral("30")] = QStringLiteral("300"); + h["10"] = "100"; + h["20"] = "200"; + h["30"] = "300"; return 0; } diff --git a/debuggers/common/tests/debuggees/qlistcontainer.cpp b/debuggers/common/tests/debuggees/qlistcontainer.cpp --- a/debuggers/common/tests/debuggees/qlistcontainer.cpp +++ b/debuggers/common/tests/debuggees/qlistcontainer.cpp @@ -39,7 +39,7 @@ stringList << "d"; Container structList; - structList << A(QStringLiteral("a"), QStringLiteral("b"), 100, -200); + structList << A("a", "b", 100, -200); structList << A(); Container pointerList; diff --git a/debuggers/common/tests/debuggees/qmapstring.cpp b/debuggers/common/tests/debuggees/qmapstring.cpp --- a/debuggers/common/tests/debuggees/qmapstring.cpp +++ b/debuggers/common/tests/debuggees/qmapstring.cpp @@ -3,8 +3,8 @@ int main() { QMap m; - m[QStringLiteral("10")] = QStringLiteral("100"); - m[QStringLiteral("20")] = QStringLiteral("200"); - m[QStringLiteral("30")] = QStringLiteral("300"); + m["10"] = "100"; + m["20"] = "200"; + m["30"] = "300"; return 0; } diff --git a/debuggers/common/tests/debuggees/qmapstringbool.cpp b/debuggers/common/tests/debuggees/qmapstringbool.cpp --- a/debuggers/common/tests/debuggees/qmapstringbool.cpp +++ b/debuggers/common/tests/debuggees/qmapstringbool.cpp @@ -3,8 +3,8 @@ int main() { QMap m; - m[QStringLiteral("10")] = true; - m[QStringLiteral("20")] = false; - m[QStringLiteral("30")] = true; + m["10"] = true; + m["20"] = false; + m["30"] = true; return 0; } diff --git a/debuggers/common/tests/debuggees/qsetstring.cpp b/debuggers/common/tests/debuggees/qsetstring.cpp --- a/debuggers/common/tests/debuggees/qsetstring.cpp +++ b/debuggers/common/tests/debuggees/qsetstring.cpp @@ -3,8 +3,8 @@ int main() { QSet s; - s.insert(QStringLiteral("10")); - s.insert(QStringLiteral("20")); - s.insert(QStringLiteral("30")); + s.insert("10"); + s.insert("20"); + s.insert("30"); return 0; } diff --git a/debuggers/common/tests/debuggees/qstring.cpp b/debuggers/common/tests/debuggees/qstring.cpp --- a/debuggers/common/tests/debuggees/qstring.cpp +++ b/debuggers/common/tests/debuggees/qstring.cpp @@ -1,7 +1,7 @@ #include int main() { - QString s = QStringLiteral("test最后一个不是特殊字符'\"\\u6211"); + QString s = QString::fromUtf8("test最后一个不是特殊字符'\"\\u6211"); s.append("x"); return 0; } diff --git a/debuggers/common/tests/debuggers-tests-config.h.in b/debuggers/common/tests/debuggers-tests-config.h.in --- a/debuggers/common/tests/debuggers-tests-config.h.in +++ b/debuggers/common/tests/debuggers-tests-config.h.in @@ -2,4 +2,6 @@ #define DEBUGGEE_BIN_DIR "${CMAKE_CURRENT_BINARY_DIR}/debuggees" #define DEBUGGEE_SRC_DIR "${CMAKE_CURRENT_SOURCE_DIR}/debuggees" +#cmakedefine GDB_SRC_DIR "${GDB_SRC_DIR}" +#cmakedefine LLDB_SRC_DIR "${LLDB_SRC_DIR}" #cmakedefine01 HAVE_PATH_WITH_SPACES_TEST diff --git a/debuggers/common/tests/testhelper.h b/debuggers/common/tests/testhelper.h --- a/debuggers/common/tests/testhelper.h +++ b/debuggers/common/tests/testhelper.h @@ -23,40 +23,44 @@ #ifndef KDEVDBG_TESTHELPER_H #define KDEVDBG_TESTHELPER_H +#include "debuggers-tests-config.h" + #include #include #include #include #include -namespace KDevMI { +namespace KDevMI +{ class MIDebugSession; QUrl findExecutable(const QString& name); QString findSourceFile(const QString& name); -bool isAttachForbidden(const char *file, int line); +QString findFile(const char* dir, const QString& name); +bool isAttachForbidden(const char* file, int line); -bool compareData(QModelIndex index, const QString& expected, const char *file, int line, bool useRE = false); +bool compareData(QModelIndex index, const QString& expected, const char* file, int line, bool useRE = false); -bool waitForState(MIDebugSession *session, KDevelop::IDebugSession::DebuggerState state, - const char *file, int line, bool waitForIdle = false); +bool waitForState(MIDebugSession* session, KDevelop::IDebugSession::DebuggerState state, const char* file, int line, + bool waitForIdle = false); -bool waitForAWhile(MIDebugSession *session, int ms, const char *file, int line); +bool waitForAWhile(MIDebugSession* session, int ms, const char* file, int line); class TestWaiter { public: - TestWaiter(MIDebugSession * session_, const char * condition_, const char * file_, int line_); + TestWaiter(MIDebugSession* session_, const char* condition_, const char* file_, int line_); bool waitUnless(bool ok); private: QTime stopWatch; QPointer session; - const char * condition; - const char * file; + const char* condition; + const char* file; int line; }; diff --git a/debuggers/common/tests/testhelper.cpp b/debuggers/common/tests/testhelper.cpp --- a/debuggers/common/tests/testhelper.cpp +++ b/debuggers/common/tests/testhelper.cpp @@ -44,8 +44,13 @@ QString findSourceFile(const QString& name) { - QFileInfo info(QString::fromLocal8Bit(DEBUGGEE_SRC_DIR), name); - Q_ASSERT_X(info.exists(), "findSourceFile", info.filePath().toLocal8Bit()); + return findFile(DEBUGGEE_SRC_DIR, name); +} + +QString findFile(const char* dir, const QString& name) +{ + QFileInfo info(QString::fromLocal8Bit(dir), name); + Q_ASSERT_X(info.exists(), "findFile", info.filePath().toLocal8Bit()); return info.canonicalFilePath(); } @@ -78,13 +83,9 @@ } else { matched = s == expected; } - if (!matched) { - 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; + return QTest::qVerify(matched, "Comparsion of data", qPrintable(QString("'%0' didn't match expected '%1' in %2:%3") + .arg(s).arg(expected).arg(file).arg(line)), + file, line); } bool waitForAWhile(MIDebugSession *session, int ms, const char *file, int line) diff --git a/debuggers/gdb/unittests/test_gdb.cpp b/debuggers/gdb/unittests/test_gdb.cpp --- a/debuggers/gdb/unittests/test_gdb.cpp +++ b/debuggers/gdb/unittests/test_gdb.cpp @@ -63,6 +63,7 @@ using KDevelop::AutoTestShell; using KDevMI::findExecutable; using KDevMI::findSourceFile; +using KDevMI::findFile; namespace KDevMI { namespace GDB { @@ -547,7 +548,7 @@ session->run(); WAIT_FOR_STATE(session, DebugSession::PausedState); - QCOMPARE(session->line(), 23); + QCOMPARE(session->line(), 22); // line 23: ++i; int j = i; session->run(); WAIT_FOR_STATE(session, DebugSession::PausedState); QCOMPARE(session->line(), 24); @@ -573,7 +574,7 @@ session->run(); WAIT_FOR_STATE(session, DebugSession::PausedState); - QCOMPARE(session->line(), 23); + QCOMPARE(session->line(), 22); // line 23: ++i; int j = i; session->run(); WAIT_FOR_STATE(session, DebugSession::PausedState); QCOMPARE(session->line(), 24); @@ -616,7 +617,11 @@ session->run(); WAIT_FOR_STATE(session, DebugSession::PausedState); - QCOMPARE(session->line(), 22); + QCOMPARE(session->line(), 22); // ++i + + session->run(); + WAIT_FOR_STATE(session, DebugSession::PausedState); + QCOMPARE(session->line(), 22); // int j = i session->run(); WAIT_FOR_STATE(session, DebugSession::PausedState); @@ -642,12 +647,15 @@ session->run(); WAIT_FOR_STATE(session, DebugSession::PausedState); - QCOMPARE(session->line(), 22); + QCOMPARE(session->line(), 22); // line 23: ++i (read) session->run(); WAIT_FOR_STATE(session, DebugSession::PausedState); - QCOMPARE(session->line(), 23); + QCOMPARE(session->line(), 22); // line 23: ++i (write) + session->run(); + WAIT_FOR_STATE(session, DebugSession::PausedState); + QCOMPARE(session->line(), 22); // line 23: int j = i (read) session->run(); WAIT_FOR_STATE(session, DebugSession::PausedState); @@ -885,18 +893,18 @@ stackModel->fetchMoreFrames(); QTest::qWait(200); QCOMPARE(stackModel->fetchFramesCalled, 4); - QCOMPARE(stackModel->rowCount(tIdx), 301); + QCOMPARE(stackModel->rowCount(tIdx), 299); COMPARE_DATA(stackModel->index(120, 0, tIdx), "120"); COMPARE_DATA(stackModel->index(121, 0, tIdx), "121"); COMPARE_DATA(stackModel->index(122, 0, tIdx), "122"); - COMPARE_DATA(stackModel->index(300, 0, tIdx), "300"); - COMPARE_DATA(stackModel->index(300, 1, tIdx), "main"); - COMPARE_DATA(stackModel->index(300, 2, tIdx), fileName+":30"); + COMPARE_DATA(stackModel->index(298, 0, tIdx), "298"); + COMPARE_DATA(stackModel->index(298, 1, tIdx), "main"); + COMPARE_DATA(stackModel->index(298, 2, tIdx), fileName+":30"); stackModel->fetchMoreFrames(); //nothing to fetch, we are at the end QTest::qWait(200); QCOMPARE(stackModel->fetchFramesCalled, 4); - QCOMPARE(stackModel->rowCount(tIdx), 301); + QCOMPARE(stackModel->rowCount(tIdx), 299); session->run(); WAIT_FOR_STATE(session, DebugSession::EndedState); @@ -1005,7 +1013,9 @@ TestDebugSession *session = new TestDebugSession; TestLaunchConfiguration cfg; - cfg.config().writeEntry(Config::RemoteGdbRunEntry, QUrl::fromLocalFile(findSourceFile(QStringLiteral("gdb_script_empty")))); + cfg.config().writeEntry(Config::RemoteGdbRunEntry, + QUrl::fromLocalFile(findFile(GDB_SRC_DIR, + QStringLiteral("unittests/gdb_script_empty")))); QVERIFY(session->startDebugging(&cfg, m_iface)); session->addCommand(MI::NonMI, QStringLiteral("attach %0").arg(debugeeProcess.pid())); @@ -1019,7 +1029,10 @@ void GdbTest::testCoreFile() { QFileInfo f(QStringLiteral("core")); - if (f.exists()) QFile::remove(f.canonicalFilePath()); + f.setCaching(false); // don't cache information + if (f.exists()) { + QVERIFY(QFile::remove(f.canonicalFilePath())); + } KProcess debugeeProcess; debugeeProcess.setOutputChannelMode(KProcess::MergedChannels); @@ -1035,7 +1048,7 @@ // Try to use coredumpctl auto coredumpctl = QStandardPaths::findExecutable(QStringLiteral("coredumpctl")); if (!coredumpctl.isEmpty()) { - KProcess::execute(coredumpctl, {"-1", "-o", f.canonicalFilePath(), "dump", "debugeecrash"}); + KProcess::execute(coredumpctl, {"-1", "-o", f.absoluteFilePath(), "dump", "debuggee_crash"}); coreFileFound = f.exists(); } } @@ -1080,14 +1093,18 @@ QCOMPARE(variableCollection()->rowCount(), 2); QModelIndex i = variableCollection()->index(1, 0); COMPARE_DATA(i, "Locals"); - QCOMPARE(variableCollection()->rowCount(i), 1); + QCOMPARE(variableCollection()->rowCount(i), 2); COMPARE_DATA(variableCollection()->index(0, 0, i), "i"); COMPARE_DATA(variableCollection()->index(0, 1, i), "0"); + COMPARE_DATA(variableCollection()->index(1, 0, i), "j"); + // COMPARE_DATA(variableCollection()->index(1, 1, i), "1"); // j is not initialized yet session->run(); QTest::qWait(1000); WAIT_FOR_STATE(session, DebugSession::PausedState); COMPARE_DATA(variableCollection()->index(0, 0, i), "i"); COMPARE_DATA(variableCollection()->index(0, 1, i), "1"); + COMPARE_DATA(variableCollection()->index(1, 0, i), "j"); + COMPARE_DATA(variableCollection()->index(1, 1, i), "1"); session->run(); WAIT_FOR_STATE(session, DebugSession::EndedState); } @@ -1338,9 +1355,10 @@ QModelIndex i = variableCollection()->index(1, 0); COMPARE_DATA(i, "Locals"); - QCOMPARE(variableCollection()->rowCount(i), 1); + QCOMPARE(variableCollection()->rowCount(i), 2); COMPARE_DATA(variableCollection()->index(0, 0, i), "i"); COMPARE_DATA(variableCollection()->index(0, 1, i), "1"); + COMPARE_DATA(variableCollection()->index(1, 0, i), "j"); stackModel->setCurrentFrame(1); QTest::qWait(200); @@ -1371,9 +1389,10 @@ QModelIndex i = variableCollection()->index(1, 0); COMPARE_DATA(i, "Locals"); - QCOMPARE(variableCollection()->rowCount(i), 1); + QCOMPARE(variableCollection()->rowCount(i), 2); COMPARE_DATA(variableCollection()->index(0, 0, i), "i"); COMPARE_DATA(variableCollection()->index(0, 1, i), "1"); + COMPARE_DATA(variableCollection()->index(1, 0, i), "j"); stackModel->setCurrentFrame(1); QTest::qWait(300); diff --git a/debuggers/lldb/formatters/helpers.py b/debuggers/lldb/formatters/helpers.py --- a/debuggers/lldb/formatters/helpers.py +++ b/debuggers/lldb/formatters/helpers.py @@ -184,6 +184,11 @@ self._name2idx = {} # whether to add original children self._add_original = True + # some useful info + process = self.valobj.GetProcess() + self._endianness = process.GetByteOrder() + self._pointer_size = process.GetAddressByteSize() + self._char_type = valobj.GetType().GetBasicType(lldb.eBasicTypeChar) def has_children(self): return self._num_children != 0 @@ -214,16 +219,7 @@ if isinstance(child, AutoCacheValue): child = child.get() - if isinstance(child, lldb.SBValue): - return child - else: - # we don't cache (const char[]) SBValue, ceate it on the fly - # LLDB tends to reuse a static data space for c-string literal type expressions, - # it might be overwriten by others if we cache them. - # child is a (name, expr) tuple in this case - if len(child) != 2: - print('error, const char[] value should be a tuple with two elements, it is', child) - return self.valobj.CreateValueFromExpression(*child) + return child @staticmethod def _getName(var): @@ -270,5 +266,21 @@ pass def _addChild(self, var, hidden=False): + if not isinstance(var, lldb.SBValue): + # special handling for (name, expr) tuple of string constants + if len(var) != 2: + print('error, const char[] value should be a tuple with two elements, it is', var) + name, content = var + + if isinstance(content, unicode): + content = content.encode() + + try: + char_arr_type = self._char_type.GetArrayType(len(content)); + strdata = lldb.SBData.CreateDataFromCString(self._endianness, self._pointer_size, content) + var = self.valobj.CreateValueFromData(name, strdata, char_arr_type) + except: + pass + cache = self._hiddens if hidden else self._members cache.append(var) diff --git a/debuggers/lldb/formatters/qt.py b/debuggers/lldb/formatters/qt.py --- a/debuggers/lldb/formatters/qt.py +++ b/debuggers/lldb/formatters/qt.py @@ -153,11 +153,20 @@ def QStringSummaryProvider(valobj, internal_dict): if valobj.IsValid(): - content = valobj.GetChildMemberWithName('(content)') - if content.IsValid(): - summary = content.GetSummary() - if summary is not None: - return summary + # content = valobj.GetChildMemberWithName('(content)') + # if content.IsValid(): + # try: + # error = lldb.SBError() + # rawprintable = content.GetData().GetString(error, 0) + # if error.Success(): + # printable = rawprintable.decode() + # return quote(printable) + # except: + # pass + + # FIXME: there's no reliable way to pass data from formatter to + # summary provider currently. So directly pull data from inferior + # Something wrong with synthetic provider, or # no synthetic provider installed, get the content by ourselves printable, _, _ = printableQString(valobj) @@ -185,8 +194,7 @@ dataPointer + idx * self._qchar_size, self._qchar_type) self._addChild(var) - quoted_printable_expr = quote(printable) - self._addChild(('(content)', quoted_printable_expr), hidden=True) + # self._addChild(('(content)', quote(printable)), hidden=True) def QCharSummaryProvider(valobj, internal_dict): @@ -294,11 +302,8 @@ # first replace " to \", and suround by "", no need to escape other things which # are handled in printableQByteArray. - printable = '"{}"'.format(printable.replace('"', '\\"')) - # then we need to quote again, as the quoted_printable_expr is parsed by the lldb to - # produce the final content, which removes one level of quotation - quoted_printable_expr = quote(printable) - self._addChild(('(content)', quoted_printable_expr), hidden=True) + printable = b'"{}"'.format(printable.replace(b'"', b'\\"')) + self._addChild(('(content)', printable), hidden=True) class BasicListFormatter(HiddenMemberProvider): @@ -905,14 +910,14 @@ return # (ISO) iso_str = pydate.isoformat().decode().__repr__()[2:-1] - self._addChild(('(ISO)', quote(iso_str))) + self._addChild(('(ISO)', iso_str)) # (Locale) locale_encoding = [locale.getlocale()[1]] if locale_encoding[0] is None: locale_encoding = [] locale_str = pydate.strftime('%x').decode(*locale_encoding).__repr__()[2:-1] - self._addChild(('(Locale)', quote(locale_str))) + self._addChild(('(Locale)', locale_str)) def QDateSummaryProvider(valobj, internal_dict): @@ -967,14 +972,14 @@ return # (ISO) iso_str = pytime.isoformat().decode().__repr__()[2:-1] - self._addChild(('(ISO)', quote(iso_str))) + self._addChild(('(ISO)', iso_str)) # (Locale) locale_encoding = [locale.getlocale()[1]] if locale_encoding[0] is None: locale_encoding = [] locale_str = pytime.strftime('%X').decode(*locale_encoding).__repr__()[2:-1] - self._addChild(('(Locale)', quote(locale_str))) + self._addChild(('(Locale)', locale_str)) def QTimeSummaryProvider(valobj, internal_dict): @@ -1033,11 +1038,11 @@ # (ISO) formatted = time.strftime('%Y-%m-%d %H:%M:%S', utc_tt).decode(*locale_encoding).__repr__() formatted = formatted[2:-1] - self._addChild(('(ISO)', quote(formatted))) + self._addChild(('(ISO)', formatted)) def locale_fmt(name, tt): formatted = time.strftime('%c', tt).decode(*locale_encoding).__repr__()[2:-1] - self._addChild((name, quote(formatted))) + self._addChild((name, formatted)) # (Locale) locale_fmt('(Locale)', local_tt) @@ -1067,7 +1072,9 @@ # No synthetic provider installed, get the content by ourselves pytime = QDateTimeFormatter.parse(QDateTimeFormatter.getdata(valobj).GetValueAsUnsigned(0)) if pytime is not None: - return pytime.isoformat().decode().__repr__()[2:-1] + formatted = time.strftime('%Y-%m-%d %H:%M:%S', pytime).decode().__repr__() + formatted = formatted[2:-1] + return formatted return None @@ -1106,7 +1113,7 @@ printableQString(fragment)[0])) encoded = None if len(url) > 0: - encoded = ('(encoded)', quote(url)) + encoded = ('(encoded)', url) return (encoded, port, scheme, username, password, host, path, query, fragment) # try if there's debug info available @@ -1159,14 +1166,14 @@ return (None,) * 9 res = urlsplit(url) port = dataobj.CreateValueFromExpression('(port)', str(res.port if res.port is not None else -1)) - scheme = ('(scheme)', quote(res.scheme)) - username = ('(username)', quote(res.username if res.username is not None else '')) - password = ('(password)', quote(res.password if res.password is not None else '')) - host = ('(host)', quote(res.hostname if res.hostname is not None else '')) - path = ('(path)', quote(res.path)) - query = ('(query)', quote(res.query)) - fragment = ('(fragment)', quote(res.fragment)) - encoded = ('(encoded)', quote(url)) + scheme = ('(scheme)', res.scheme) + username = ('(username)', res.username if res.username is not None else '') + password = ('(password)', res.password if res.password is not None else '') + host = ('(host)', res.hostname if res.hostname is not None else '') + path = ('(path)', res.path) + query = ('(query)', res.query) + fragment = ('(fragment)', res.fragment) + encoded = ('(encoded)', url) return (encoded, port, scheme, username, password, host, path, query, fragment) encodedOriginal = dataobj.GetChildMemberWithName('encodedOriginal') diff --git a/debuggers/lldb/unittests/test_lldb.cpp b/debuggers/lldb/unittests/test_lldb.cpp --- a/debuggers/lldb/unittests/test_lldb.cpp +++ b/debuggers/lldb/unittests/test_lldb.cpp @@ -79,6 +79,7 @@ using namespace KDevelop; using namespace KDevMI::LLDB; using KDevMI::findExecutable; +using KDevMI::findFile; using KDevMI::findSourceFile; namespace { @@ -150,9 +151,8 @@ TestDebugSession() : DebugSession() { // explicit set formatter path to force use in-tree formatters, not the one installed in system. - QFileInfo info(QFileInfo(__FILE__).path(), "../formatters/all.py"); - Q_ASSERT(info.exists()); - setFormatterPath(info.canonicalFilePath()); + auto formatter = findFile(LLDB_SRC_DIR, "formatters/all.py"); + setFormatterPath(formatter); setSourceInitFile(false); m_frameStackModel = new TestFrameStackModel(this); @@ -750,7 +750,6 @@ void LldbTest::testManualBreakpoint() { - QSKIP("Skipping... lldb-mi output malformated response which breaks this"); TestDebugSession *session = new TestDebugSession; TestLaunchConfiguration cfg; @@ -776,11 +775,14 @@ session->addCommand(MI::NonMI, QStringLiteral("break modify -i 1 2")); WAIT_FOR_A_WHILE(session, 1000); QCOMPARE(b->enabled(), false); + QEXPECT_FAIL("", "LLDB 4.0 does not report condition in mi response", Continue); QCOMPARE(b->condition(), QString("i == 1")); + QEXPECT_FAIL("", "LLDB 4.0 does not report ignore hits in mi response", Continue); QCOMPARE(b->ignoreHits(), 1); session->addCommand(MI::NonMI, QStringLiteral("break delete 2")); WAIT_FOR_A_WHILE(session, 100); + QEXPECT_FAIL("", "LLDB 4.0 does not report breakpoint deletion as mi notification", Continue); QCOMPARE(breakpoints()->rowCount(), 0); session->run(); @@ -889,6 +891,7 @@ QVERIFY(session->startDebugging(&cfg, m_iface)); WAIT_FOR_STATE_AND_IDLE(session, DebugSession::PausedState); + QEXPECT_FAIL("", "See LLDB bug 28703: -d flag has no effect", Abort); QCOMPARE(session->currentLine(), 29); b->setData(KDevelop::Breakpoint::EnableColumn, Qt::Checked); @@ -1313,7 +1316,10 @@ void LldbTest::testCoreFile() { QFileInfo f(QStringLiteral("core")); - if (f.exists()) QFile::remove(f.canonicalFilePath()); + f.setCaching(false); // don't cache information + if (f.exists()) { + QVERIFY(QFile::remove(f.canonicalFilePath())); + } KProcess debugeeProcess; debugeeProcess.setOutputChannelMode(KProcess::MergedChannels); @@ -1327,9 +1333,10 @@ bool coreFileFound = f.exists(); if (!coreFileFound) { // Try to use coredumpctl + qDebug() << "try to use coredumpctl"; auto coredumpctl = QStandardPaths::findExecutable(QStringLiteral("coredumpctl")); if (!coredumpctl.isEmpty()) { - KProcess::execute(coredumpctl, {"-1", "-o", f.canonicalFilePath(), "dump", "debuggee_crash"}); + KProcess::execute(coredumpctl, {"-1", "-o", f.absoluteFilePath(), "dump", "debuggee_crash"}); coreFileFound = f.exists(); } } @@ -1492,6 +1499,10 @@ QModelIndex i = variableCollection()->index(0, 0); QCOMPARE(variableCollection()->rowCount(i), 1); COMPARE_DATA(variableCollection()->index(0, 0, i), quotedTestString); + + QEXPECT_FAIL("", + "LLDB 4.0 cannot deal with string literal in expression when debugging, causing memory access error", + Abort); COMPARE_DATA(variableCollection()->index(0, 1, i), quotedTestString); QModelIndex testStr = variableCollection()->index(0, 0, i); diff --git a/debuggers/lldb/unittests/test_lldbformatters.cpp b/debuggers/lldb/unittests/test_lldbformatters.cpp --- a/debuggers/lldb/unittests/test_lldbformatters.cpp +++ b/debuggers/lldb/unittests/test_lldbformatters.cpp @@ -84,6 +84,7 @@ using namespace KDevMI::LLDB; using KDevMI::findExecutable; using KDevMI::findSourceFile; +using KDevMI::findFile; using KDevMI::compareData; class TestLaunchConfiguration : public ILaunchConfiguration @@ -123,9 +124,8 @@ { setSourceInitFile(false); // explicit set formatter path to force use in-tree formatters, not the one installed in system. - QFileInfo info(QFileInfo(__FILE__).path(), "../formatters/all.py"); - Q_ASSERT(info.exists()); - setFormatterPath(info.canonicalFilePath()); + auto formatter = findFile(LLDB_SRC_DIR, "formatters/all.py"); + setFormatterPath(formatter); KDevelop::ICore::self()->debugController()->addSession(this); @@ -434,6 +434,8 @@ // m_session->stepOver(); WAIT_FOR_STATE_AND_IDLE(m_session, DebugSession::PausedState); + QCOMPARE(m_session->currentLine(), 33); // line 34: intList << 10 << 20; + auto var = variableCollection()->watches()->add(QStringLiteral("intList")); WAIT_FOR_A_WHILE_AND_IDLE(m_session, 50); @@ -444,6 +446,7 @@ m_session->stepOver(); WAIT_FOR_STATE_AND_IDLE(m_session, DebugSession::PausedState); + QCOMPARE(m_session->currentLine(), 34); // line 35: intList << 30; variableCollection()->expanded(watchVariableIndexAt(0)); // expand this node for correct update. WAIT_FOR_A_WHILE_AND_IDLE(m_session, 50); @@ -455,6 +458,7 @@ m_session->stepOver(); WAIT_FOR_STATE_AND_IDLE(m_session, DebugSession::PausedState); + QCOMPARE(m_session->currentLine(), 36); // line 37: Container stringList; if (!verifyVariable(0, QStringLiteral("intList"), QStringLiteral(""), QStringList{"10", "20", "30"}, __FILE__, __LINE__, false, false, unordered)) { @@ -465,6 +469,8 @@ // m_session->stepOver(); WAIT_FOR_STATE_AND_IDLE(m_session, DebugSession::PausedState); + QCOMPARE(m_session->currentLine(), 37); // line 38: stringList << "a" << "bc"; + var = variableCollection()->watches()->add(QStringLiteral("stringList")); WAIT_FOR_A_WHILE_AND_IDLE(m_session, 50); @@ -475,6 +481,7 @@ m_session->stepOver(); WAIT_FOR_STATE_AND_IDLE(m_session, DebugSession::PausedState); + QCOMPARE(m_session->currentLine(), 38); // line 39: stringList << "d"; variableCollection()->expanded(watchVariableIndexAt(0)); // expand this node for correct update. WAIT_FOR_A_WHILE_AND_IDLE(m_session, 50); @@ -487,6 +494,7 @@ m_session->stepOver(); WAIT_FOR_STATE_AND_IDLE(m_session, DebugSession::PausedState); + QCOMPARE(m_session->currentLine(), 40); // line 41: Container structList; if (!verifyVariable(0, QStringLiteral("stringList"), QStringLiteral(""), QStringList{"\"a\"", "\"bc\"", "\"d\""}, __FILE__, __LINE__, false, false, unordered)) { @@ -497,16 +505,19 @@ // m_session->stepOver(); WAIT_FOR_STATE_AND_IDLE(m_session, DebugSession::PausedState); + QCOMPARE(m_session->currentLine(), 41); // line 42: structList << A(QStringLiteral("a"), QStringLiteral("b"), 100, -200); + var = variableCollection()->watches()->add(QStringLiteral("structList")); WAIT_FOR_A_WHILE_AND_IDLE(m_session, 50); if (!verifyVariable(0, QStringLiteral("structList"), QStringLiteral(""), QStringList{}, __FILE__, __LINE__, false, false, unordered)) { return; } - m_session->stepOver(); + m_session->runUntil({}, 43); WAIT_FOR_STATE_AND_IDLE(m_session, DebugSession::PausedState); + QCOMPARE(m_session->currentLine(), 42); // line 43: structList << A(); variableCollection()->expanded(watchVariableIndexAt(0)); // expand this node for correct update. WAIT_FOR_A_WHILE_AND_IDLE(m_session, 50); @@ -518,6 +529,7 @@ m_session->stepOver(); WAIT_FOR_STATE_AND_IDLE(m_session, DebugSession::PausedState); + QCOMPARE(m_session->currentLine(), 44); // line 45: Container pointerList; if (!verifyVariable(0, QStringLiteral("structList"), QStringLiteral(""), QStringList{"{...}", "{...}"}, __FILE__, __LINE__, false, false, unordered)) { @@ -528,6 +540,8 @@ // m_session->stepOver(); WAIT_FOR_STATE_AND_IDLE(m_session, DebugSession::PausedState); + QCOMPARE(m_session->currentLine(), 45); // line 46: pointerList << new int(1) << new int(2); + var = variableCollection()->watches()->add(QStringLiteral("pointerList")); WAIT_FOR_A_WHILE_AND_IDLE(m_session, 50); @@ -538,6 +552,7 @@ m_session->stepOver(); WAIT_FOR_STATE_AND_IDLE(m_session, DebugSession::PausedState); + QCOMPARE(m_session->currentLine(), 46); // line 47: pointerList << new int(3); variableCollection()->expanded(watchVariableIndexAt(0)); // expand this node for correct update. WAIT_FOR_A_WHILE_AND_IDLE(m_session, 50); @@ -549,6 +564,7 @@ m_session->stepOver(); WAIT_FOR_STATE_AND_IDLE(m_session, DebugSession::PausedState); + QCOMPARE(m_session->currentLine(), 47); // line 48: qDeleteAll(pointerList); if (!verifyVariable(0, QStringLiteral("pointerList"), QStringLiteral(""), QStringList{"^0x[0-9A-Fa-f]+$", "^0x[0-9A-Fa-f]+$", "^0x[0-9A-Fa-f]+$"}, @@ -561,13 +577,16 @@ // > m_session->stepOver(); WAIT_FOR_STATE_AND_IDLE(m_session, DebugSession::PausedState); + QCOMPARE(m_session->currentLine(), 50); // line 51: pairList << QPair(1, 2) << qMakePair(2, 3); + var = variableCollection()->watches()->add(QStringLiteral("pairList")); WAIT_FOR_A_WHILE_AND_IDLE(m_session, 50); VERIFY_WATCH(0, "pairList", "", QStringList{}); m_session->stepOver(); WAIT_FOR_STATE_AND_IDLE(m_session, DebugSession::PausedState); + QCOMPARE(m_session->currentLine(), 51); // line 52: pairList << qMakePair(4, 5); variableCollection()->expanded(watchVariableIndexAt(0)); // expand this node for correct update. WAIT_FOR_A_WHILE_AND_IDLE(m_session, 50); @@ -579,6 +598,7 @@ m_session->stepOver(); WAIT_FOR_STATE_AND_IDLE(m_session, DebugSession::PausedState); + QCOMPARE(m_session->currentLine(), 54); // line 55: int i = 0; if (!verifyVariable(0, QStringLiteral("pairList"), QStringLiteral(""), QStringList{"{...}", "{...}", "{...}"}, __FILE__, __LINE__, false, false, unordered)) { @@ -668,6 +688,7 @@ QVERIFY(m_session->startDebugging(&cfg, m_iface)); WAIT_FOR_STATE_AND_IDLE(m_session, DebugSession::PausedState); + QCOMPARE(m_session->currentLine(), 7); // line 8: m[QStringLiteral("30")] = QStringLiteral("300"); // Should be two rows ('auto', 'local') QCOMPARE(variableCollection()->rowCount(), 2); @@ -679,7 +700,7 @@ m_session->stepOver(); WAIT_FOR_STATE_AND_IDLE(m_session, DebugSession::PausedState); - QCOMPARE(m_session->currentLine(), 8); + QCOMPARE(m_session->currentLine(), 8); // line 9: return 0; VERIFY_LOCAL(0, "m", "", (QStringList{"(\"10\", \"100\")", "(\"20\", \"200\")", "(\"30\", \"300\")"}));