File indexing completed on 2024-05-12 04:40:08
0001 /* 0002 SPDX-FileCopyrightText: 2009 Niko Sams <niko.sams@gmail.com> 0003 SPDX-FileCopyrightText: 2013 Vlas Puhov <vlas.puhov@mail.ru> 0004 SPDX-FileCopyrightText: 2016 Aetf <aetf@unlimitedcodeworks.xyz> 0005 0006 SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL 0007 */ 0008 0009 #include "test_lldb.h" 0010 0011 #include "controllers/framestackmodel.h" 0012 #include "debugsession.h" 0013 #include "tests/debuggers-tests-config.h" 0014 #include "tests/testhelper.h" 0015 0016 #include <execute/iexecuteplugin.h> 0017 #include <debugger/breakpoint/breakpointmodel.h> 0018 #include <debugger/variable/variablecollection.h> 0019 #include <interfaces/idebugcontroller.h> 0020 #include <interfaces/iplugincontroller.h> 0021 #include <tests/autotestshell.h> 0022 #include <tests/testcore.h> 0023 0024 #include <KConfigGroup> 0025 #include <KIO/Global> 0026 #include <KSharedConfig> 0027 0028 #include <QFileInfo> 0029 #include <QSignalSpy> 0030 #include <QString> 0031 #include <QStringList> 0032 #include <QTest> 0033 #include <QTemporaryFile> 0034 #include <QUrl> 0035 #include <QDir> 0036 0037 #define WAIT_FOR_A_WHILE(session, ms) \ 0038 do { if (!KDevMI::waitForAWhile((session), (ms), __FILE__, __LINE__)) return; } while (0) 0039 0040 using namespace KDevelop; 0041 using namespace KDevMI::LLDB; 0042 using KDevMI::findExecutable; 0043 using KDevMI::findFile; 0044 using KDevMI::findSourceFile; 0045 0046 namespace { 0047 0048 class TestFrameStackModel : public LldbFrameStackModel 0049 { 0050 Q_OBJECT 0051 0052 public: 0053 0054 explicit TestFrameStackModel(DebugSession* session) 0055 : LldbFrameStackModel(session), fetchFramesCalled(0), fetchThreadsCalled(0) {} 0056 0057 void fetchFrames(int threadNumber, int from, int to) override 0058 { 0059 fetchFramesCalled++; 0060 LldbFrameStackModel::fetchFrames(threadNumber, from, to); 0061 } 0062 0063 void fetchThreads() override 0064 { 0065 fetchThreadsCalled++; 0066 LldbFrameStackModel::fetchThreads(); 0067 } 0068 0069 int fetchFramesCalled; 0070 int fetchThreadsCalled; 0071 }; 0072 0073 class TestDebugSession : public DebugSession 0074 { 0075 Q_OBJECT 0076 public: 0077 TestDebugSession() : DebugSession() 0078 { 0079 // explicit set formatter path to force use in-tree formatters, not the one installed in system. 0080 auto formatter = findFile(LLDB_SRC_DIR, "formatters/all.py"); 0081 setFormatterPath(formatter); 0082 0083 setSourceInitFile(false); 0084 m_frameStackModel = new TestFrameStackModel(this); 0085 0086 KDevelop::ICore::self()->debugController()->addSession(this); 0087 } 0088 0089 TestFrameStackModel* frameStackModel() const override 0090 { 0091 return m_frameStackModel; 0092 } 0093 0094 private: 0095 TestFrameStackModel* m_frameStackModel; 0096 }; 0097 0098 } // end of anonymous namespace 0099 0100 0101 BreakpointModel* LldbTest::breakpoints() 0102 { 0103 return m_core->debugController()->breakpointModel(); 0104 } 0105 0106 VariableCollection *LldbTest::variableCollection() 0107 { 0108 return m_core->debugController()->variableCollection(); 0109 } 0110 0111 Variable *LldbTest::watchVariableAt(int i) 0112 { 0113 auto watchRoot = variableCollection()->indexForItem(variableCollection()->watches(), 0); 0114 auto idx = variableCollection()->index(i, 0, watchRoot); 0115 return qobject_cast<Variable*>(variableCollection()->itemForIndex(idx)); 0116 } 0117 0118 QModelIndex LldbTest::localVariableIndexAt(int i, int col) 0119 { 0120 auto localRoot = variableCollection()->indexForItem(variableCollection()->locals(), 0); 0121 return variableCollection()->index(i, col, localRoot); 0122 } 0123 0124 // Called before the first testfunction is executed 0125 void LldbTest::initTestCase() 0126 { 0127 AutoTestShell::init(); 0128 m_core = TestCore::initialize(Core::NoUi); 0129 0130 m_iface = m_core->pluginController() 0131 ->pluginForExtension(QStringLiteral("org.kdevelop.IExecutePlugin"), QStringLiteral("kdevexecute")) 0132 ->extension<IExecutePlugin>(); 0133 Q_ASSERT(m_iface); 0134 0135 m_debugeeFileName = findSourceFile("debugee.cpp"); 0136 0137 const QString lldbMiExecutable = QStandardPaths::findExecutable(QStringLiteral("lldb-mi")); 0138 if (lldbMiExecutable.isEmpty()) { 0139 QSKIP("Skipping, lldb-mi not available"); 0140 } 0141 } 0142 0143 // Called after the last testfunction was executed 0144 void LldbTest::cleanupTestCase() 0145 { 0146 TestCore::shutdown(); 0147 } 0148 0149 // Called before each testfunction is executed 0150 void LldbTest::init() 0151 { 0152 //remove all breakpoints - so we can set our own in the test 0153 KConfigGroup bpCfg = KSharedConfig::openConfig()->group("breakpoints"); 0154 bpCfg.writeEntry("number", 0); 0155 bpCfg.sync(); 0156 0157 breakpoints()->removeRows(0, breakpoints()->rowCount()); 0158 0159 while (variableCollection()->watches()->childCount() > 0) { 0160 auto var = watchVariableAt(0); 0161 if (!var) break; 0162 var->die(); 0163 } 0164 } 0165 0166 void LldbTest::cleanup() 0167 { 0168 // Called after every testfunction 0169 } 0170 0171 void LldbTest::testStdout() 0172 { 0173 auto *session = new TestDebugSession; 0174 0175 QSignalSpy outputSpy(session, &TestDebugSession::inferiorStdoutLines); 0176 0177 TestLaunchConfiguration cfg; 0178 QVERIFY(session->startDebugging(&cfg, m_iface)); 0179 WAIT_FOR_STATE(session, KDevelop::IDebugSession::EndedState); 0180 0181 QVERIFY(outputSpy.count() > 0); 0182 0183 QStringList outputLines; 0184 while (outputSpy.count() > 0) { 0185 const QList<QVariant> arguments = outputSpy.takeFirst(); 0186 for (const auto &item : arguments) { 0187 outputLines.append(item.toStringList()); 0188 } 0189 } 0190 QCOMPARE(outputLines, QStringList() << "Hello, world!" 0191 << "Hello"); 0192 } 0193 0194 void LldbTest::testEnvironmentSet() 0195 { 0196 KDevMI::testEnvironmentSet(new TestDebugSession, QStringLiteral("LldbTestGroup"), m_iface); 0197 } 0198 0199 void LldbTest::testBreakpoint() 0200 { 0201 auto *session = new TestDebugSession; 0202 0203 TestLaunchConfiguration cfg; 0204 0205 KDevelop::Breakpoint * b = breakpoints()->addCodeBreakpoint(QUrl::fromLocalFile(m_debugeeFileName), 29); 0206 QCOMPARE(b->state(), KDevelop::Breakpoint::NotStartedState); 0207 0208 QVERIFY(session->startDebugging(&cfg, m_iface)); 0209 WAIT_FOR_STATE_AND_IDLE(session, DebugSession::PausedState); 0210 QCOMPARE(b->state(), KDevelop::Breakpoint::CleanState); 0211 QCOMPARE(session->currentLine(), 29); 0212 0213 session->stepInto(); 0214 WAIT_FOR_STATE_AND_IDLE(session, DebugSession::PausedState); 0215 0216 session->stepInto(); 0217 WAIT_FOR_STATE_AND_IDLE(session, DebugSession::PausedState); 0218 0219 session->run(); 0220 WAIT_FOR_STATE(session, DebugSession::EndedState); 0221 QCOMPARE(b->state(), KDevelop::Breakpoint::NotStartedState); 0222 } 0223 0224 void LldbTest::testBreakOnStart() 0225 { 0226 auto *session = new TestDebugSession; 0227 0228 TestLaunchConfiguration cfg; 0229 cfg.config().writeEntry(KDevMI::Config::BreakOnStartEntry, true); 0230 0231 QVERIFY(session->startDebugging(&cfg, m_iface)); 0232 WAIT_FOR_STATE(session, DebugSession::PausedState); 0233 // line 28 is the start of main function in debugee.cpp 0234 QCOMPARE(session->currentLine(), 27); // currentLine is zero-based 0235 0236 session->run(); 0237 WAIT_FOR_STATE(session, DebugSession::EndedState); 0238 } 0239 0240 void LldbTest::testDisableBreakpoint() 0241 { 0242 QSKIP("Skipping... In lldb-mi -d flag has no effect when mixed with -f"); 0243 //Description: We must stop only on the third breakpoint 0244 0245 int firstBreakLine=28; 0246 int secondBreakLine=23; 0247 int thirdBreakLine=24; 0248 int fourthBreakLine=31; 0249 0250 auto *session = new TestDebugSession; 0251 0252 TestLaunchConfiguration cfg; 0253 0254 KDevelop::Breakpoint *b; 0255 0256 b = breakpoints()->addCodeBreakpoint(QUrl::fromLocalFile(m_debugeeFileName), firstBreakLine); 0257 b->setData(KDevelop::Breakpoint::EnableColumn, Qt::Unchecked); 0258 0259 0260 //this is needed to emulate debug from GUI. If we are in edit mode, the debugSession doesn't exist. 0261 m_core->debugController()->breakpointModel()->blockSignals(true); 0262 b = breakpoints()->addCodeBreakpoint(QUrl::fromLocalFile(m_debugeeFileName), secondBreakLine); 0263 b->setData(KDevelop::Breakpoint::EnableColumn, Qt::Unchecked); 0264 //all disabled breakpoints were added 0265 0266 auto *thirdBreak = breakpoints()->addCodeBreakpoint(QUrl::fromLocalFile(m_debugeeFileName), 0267 thirdBreakLine); 0268 m_core->debugController()->breakpointModel()->blockSignals(false); 0269 0270 0271 QVERIFY(session->startDebugging(&cfg, m_iface)); 0272 WAIT_FOR_STATE_AND_IDLE(session, DebugSession::PausedState); 0273 QCOMPARE(session->currentLine(), thirdBreak->line()); 0274 0275 //disable existing breakpoint 0276 thirdBreak->setData(KDevelop::Breakpoint::EnableColumn, Qt::Unchecked); 0277 0278 //add another disabled breakpoint 0279 b = breakpoints()->addCodeBreakpoint(QUrl::fromLocalFile(m_debugeeFileName), fourthBreakLine); 0280 WAIT_FOR_A_WHILE(session, 300); 0281 b->setData(KDevelop::Breakpoint::EnableColumn, Qt::Unchecked); 0282 0283 WAIT_FOR_A_WHILE(session, 300); 0284 session->run(); 0285 WAIT_FOR_STATE(session, DebugSession::EndedState); 0286 } 0287 0288 void LldbTest::testChangeLocationBreakpoint() 0289 { 0290 auto *session = new TestDebugSession; 0291 0292 TestLaunchConfiguration cfg; 0293 0294 auto *b = breakpoints()->addCodeBreakpoint(QUrl::fromLocalFile(m_debugeeFileName), 27); 0295 0296 QVERIFY(session->startDebugging(&cfg, m_iface)); 0297 WAIT_FOR_STATE_AND_IDLE(session, DebugSession::PausedState); 0298 QCOMPARE(session->currentLine(), 27); 0299 0300 WAIT_FOR_A_WHILE(session, 100); 0301 b->setLine(28); 0302 WAIT_FOR_A_WHILE(session, 100); 0303 session->run(); 0304 0305 WAIT_FOR_A_WHILE(session, 100); 0306 WAIT_FOR_STATE(session, DebugSession::PausedState); 0307 QCOMPARE(session->currentLine(), 28); 0308 WAIT_FOR_A_WHILE(session, 500); 0309 breakpoints()->setData(breakpoints()->index(0, KDevelop::Breakpoint::LocationColumn), QString(m_debugeeFileName+":30")); 0310 QCOMPARE(b->line(), 29); 0311 WAIT_FOR_A_WHILE(session, 100); 0312 QCOMPARE(b->line(), 29); 0313 session->run(); 0314 WAIT_FOR_A_WHILE(session, 100); 0315 WAIT_FOR_STATE(session, DebugSession::PausedState); 0316 QCOMPARE(session->currentLine(), 29); 0317 session->run(); 0318 0319 WAIT_FOR_STATE(session, DebugSession::EndedState); 0320 } 0321 0322 void LldbTest::testDeleteBreakpoint() 0323 { 0324 auto *session = new TestDebugSession; 0325 0326 TestLaunchConfiguration cfg; 0327 0328 QCOMPARE(breakpoints()->rowCount(), 0); 0329 //add breakpoint before startDebugging 0330 breakpoints()->addCodeBreakpoint(QUrl::fromLocalFile(m_debugeeFileName), 21); 0331 QCOMPARE(breakpoints()->rowCount(), 1); 0332 breakpoints()->removeRow(0); 0333 QCOMPARE(breakpoints()->rowCount(), 0); 0334 0335 breakpoints()->addCodeBreakpoint(QUrl::fromLocalFile(m_debugeeFileName), 22); 0336 0337 QVERIFY(session->startDebugging(&cfg, m_iface)); 0338 WAIT_FOR_STATE_AND_IDLE(session, DebugSession::PausedState); 0339 breakpoints()->removeRow(0); 0340 session->run(); 0341 0342 WAIT_FOR_STATE(session, DebugSession::EndedState); 0343 } 0344 0345 void LldbTest::testPendingBreakpoint() 0346 { 0347 QSKIP("Skipping... Pending breakpoint not work on lldb-mi"); 0348 auto *session = new TestDebugSession; 0349 TestLaunchConfiguration cfg; 0350 0351 breakpoints()->addCodeBreakpoint(QUrl::fromLocalFile(m_debugeeFileName), 28); 0352 0353 auto * b = breakpoints()->addCodeBreakpoint(QUrl::fromLocalFile(findSourceFile("test_lldb.cpp")), 10); 0354 QCOMPARE(b->state(), Breakpoint::NotStartedState); 0355 0356 QVERIFY(session->startDebugging(&cfg, m_iface)); 0357 WAIT_FOR_STATE(session, DebugSession::PausedState); 0358 QCOMPARE(b->state(), Breakpoint::PendingState); 0359 session->run(); 0360 WAIT_FOR_STATE(session, DebugSession::EndedState); 0361 } 0362 0363 void LldbTest::testUpdateBreakpoint() 0364 { 0365 // Description: user might insert breakpoints using lldb console. model should 0366 // pick up the manually set breakpoint 0367 auto *session = new TestDebugSession; 0368 TestLaunchConfiguration cfg; 0369 0370 // break at line 29 0371 auto b = breakpoints()->addCodeBreakpoint(QUrl::fromLocalFile(m_debugeeFileName), 28); 0372 QCOMPARE(breakpoints()->rowCount(), 1); 0373 0374 QVERIFY(session->startDebugging(&cfg, m_iface)); 0375 0376 WAIT_FOR_STATE_AND_IDLE(session, DebugSession::PausedState); // stop at line 29 0377 0378 session->stepInto(); 0379 WAIT_FOR_STATE_AND_IDLE(session, DebugSession::PausedState); // stop after step 0380 0381 QCOMPARE(session->currentLine(), 23-1); // at the beginning of foo():23: ++i; 0382 0383 session->addUserCommand(QStringLiteral("break set --file %1 --line %2").arg(m_debugeeFileName).arg(33)); 0384 WAIT_FOR_A_WHILE(session, 20); 0385 0386 QCOMPARE(breakpoints()->rowCount(), 2); 0387 b = breakpoints()->breakpoint(1); 0388 QCOMPARE(b->url(), QUrl::fromLocalFile(m_debugeeFileName)); 0389 QCOMPARE(b->line(), 33-1); 0390 0391 session->run(); 0392 WAIT_FOR_STATE_AND_IDLE(session, DebugSession::PausedState); // stop at line 25 0393 0394 QCOMPARE(session->currentLine(), 33-1); 0395 0396 session->run(); 0397 WAIT_FOR_STATE(session, DebugSession::EndedState); 0398 } 0399 0400 void LldbTest::testIgnoreHitsBreakpoint() 0401 { 0402 QSKIP("Skipping... lldb-mi doesn't provide breakpoint hit count update"); 0403 auto *session = new TestDebugSession; 0404 TestLaunchConfiguration cfg; 0405 0406 KDevelop::Breakpoint * b1 = breakpoints()->addCodeBreakpoint(QUrl::fromLocalFile(m_debugeeFileName), 21); 0407 b1->setIgnoreHits(1); 0408 0409 KDevelop::Breakpoint * b2 = breakpoints()->addCodeBreakpoint(QUrl::fromLocalFile(m_debugeeFileName), 22); 0410 0411 QVERIFY(session->startDebugging(&cfg, m_iface)); 0412 0413 //WAIT_FOR_STATE(session, DebugSession::PausedState); 0414 WAIT_FOR(session, session->state() == DebugSession::PausedState && b2->hitCount() == 1); 0415 b2->setIgnoreHits(1); 0416 session->run(); 0417 //WAIT_FOR_STATE(session, DebugSession::PausedState); 0418 WAIT_FOR(session, session->state() == DebugSession::PausedState && b1->hitCount() == 1); 0419 session->run(); 0420 WAIT_FOR_STATE(session, DebugSession::EndedState); 0421 } 0422 0423 void LldbTest::testConditionBreakpoint() 0424 { 0425 auto *session = new TestDebugSession; 0426 TestLaunchConfiguration cfg; 0427 0428 auto b = breakpoints()->addCodeBreakpoint(QUrl::fromLocalFile(m_debugeeFileName), 39); 0429 b->setCondition(QStringLiteral("x[0] == 'H'")); 0430 0431 b = breakpoints()->addCodeBreakpoint(QUrl::fromLocalFile(m_debugeeFileName), 23); 0432 b->setCondition(QStringLiteral("i==2")); 0433 0434 b = breakpoints()->addCodeBreakpoint(QUrl::fromLocalFile(m_debugeeFileName), 24); 0435 0436 QVERIFY(session->startDebugging(&cfg, m_iface)); 0437 0438 WAIT_FOR(session, session->state() == DebugSession::PausedState && session->currentLine() == 24); 0439 b->setCondition(QStringLiteral("i == 0")); 0440 WAIT_FOR_A_WHILE(session, 100); 0441 session->run(); 0442 WAIT_FOR_STATE_AND_IDLE(session, DebugSession::PausedState); 0443 0444 QCOMPARE(session->currentLine(), 23); 0445 0446 session->run(); 0447 WAIT_FOR_STATE_AND_IDLE(session, DebugSession::PausedState); 0448 0449 QCOMPARE(session->currentLine(), 39); 0450 0451 session->run(); 0452 WAIT_FOR_STATE(session, DebugSession::EndedState); 0453 } 0454 0455 void LldbTest::testBreakOnWriteBreakpoint() 0456 { 0457 QSKIP("Skipping... lldb-mi doesn't have proper watchpoint support"); 0458 auto *session = new TestDebugSession; 0459 TestLaunchConfiguration cfg; 0460 0461 breakpoints()->addCodeBreakpoint(QUrl::fromLocalFile(m_debugeeFileName), 24); 0462 0463 QVERIFY(session->startDebugging(&cfg, m_iface)); 0464 0465 WAIT_FOR_STATE_AND_IDLE(session, DebugSession::PausedState); 0466 QCOMPARE(session->currentLine(), 24); 0467 0468 breakpoints()->addWatchpoint(QStringLiteral("i")); 0469 WAIT_FOR_A_WHILE(session, 100); 0470 0471 session->run(); 0472 WAIT_FOR_STATE_AND_IDLE(session, DebugSession::PausedState); 0473 QCOMPARE(session->currentLine(), 23); 0474 session->run(); 0475 WAIT_FOR_STATE_AND_IDLE(session, DebugSession::PausedState); 0476 QCOMPARE(session->currentLine(), 24); 0477 session->run(); 0478 WAIT_FOR_STATE(session, DebugSession::EndedState); 0479 } 0480 0481 void LldbTest::testBreakOnWriteWithConditionBreakpoint() 0482 { 0483 QSKIP("Skipping... lldb-mi doesn't have proper watchpoint support"); 0484 auto *session = new TestDebugSession; 0485 TestLaunchConfiguration cfg; 0486 0487 breakpoints()->addCodeBreakpoint(QUrl::fromLocalFile(m_debugeeFileName), 24); 0488 0489 QVERIFY(session->startDebugging(&cfg, m_iface)); 0490 0491 WAIT_FOR_STATE_AND_IDLE(session, DebugSession::PausedState); 0492 QCOMPARE(session->currentLine(), 24); 0493 0494 KDevelop::Breakpoint *b = breakpoints()->addWatchpoint(QStringLiteral("i")); 0495 b->setCondition(QStringLiteral("i==2")); 0496 QTest::qWait(100); 0497 0498 session->run(); 0499 WAIT_FOR_STATE_AND_IDLE(session, DebugSession::PausedState); 0500 QCOMPARE(session->currentLine(), 23); 0501 session->run(); 0502 WAIT_FOR_STATE_AND_IDLE(session, DebugSession::PausedState); 0503 QCOMPARE(session->currentLine(), 24); 0504 session->run(); 0505 WAIT_FOR_STATE(session, DebugSession::EndedState); 0506 } 0507 0508 void LldbTest::testBreakOnReadBreakpoint() 0509 { 0510 QSKIP("Skipping... lldb-mi doesn't have proper watchpoint support"); 0511 auto *session = new TestDebugSession; 0512 TestLaunchConfiguration cfg; 0513 0514 breakpoints()->addReadWatchpoint(QStringLiteral("foo::i")); 0515 0516 QVERIFY(session->startDebugging(&cfg, m_iface)); 0517 0518 WAIT_FOR_STATE_AND_IDLE(session, DebugSession::PausedState); 0519 QCOMPARE(session->currentLine(), 23); 0520 session->run(); 0521 WAIT_FOR_STATE(session, DebugSession::EndedState); 0522 } 0523 0524 void LldbTest::testBreakOnReadBreakpoint2() 0525 { 0526 QSKIP("Skipping... lldb-mi doesn't have proper watchpoint support"); 0527 auto *session = new TestDebugSession; 0528 TestLaunchConfiguration cfg; 0529 0530 breakpoints()->addCodeBreakpoint(QUrl::fromLocalFile(m_debugeeFileName), 24); 0531 0532 QVERIFY(session->startDebugging(&cfg, m_iface)); 0533 0534 WAIT_FOR_STATE_AND_IDLE(session, DebugSession::PausedState); 0535 QCOMPARE(session->currentLine(), 24); 0536 0537 breakpoints()->addReadWatchpoint(QStringLiteral("i")); 0538 0539 session->run(); 0540 WAIT_FOR_STATE_AND_IDLE(session, DebugSession::PausedState); 0541 QCOMPARE(session->currentLine(), 22); 0542 0543 session->run(); 0544 WAIT_FOR_STATE_AND_IDLE(session, DebugSession::PausedState); 0545 QCOMPARE(session->currentLine(), 24); 0546 0547 session->run(); 0548 WAIT_FOR_STATE(session, DebugSession::EndedState); 0549 } 0550 0551 void LldbTest::testBreakOnAccessBreakpoint() 0552 { 0553 QSKIP("Skipping... lldb-mi doesn't have proper watchpoint support"); 0554 auto *session = new TestDebugSession; 0555 TestLaunchConfiguration cfg; 0556 0557 breakpoints()->addCodeBreakpoint(QUrl::fromLocalFile(m_debugeeFileName), 24); 0558 0559 QVERIFY(session->startDebugging(&cfg, m_iface)); 0560 0561 WAIT_FOR_STATE_AND_IDLE(session, DebugSession::PausedState); 0562 QCOMPARE(session->currentLine(), 24); 0563 0564 breakpoints()->addAccessWatchpoint(QStringLiteral("i")); 0565 0566 session->run(); 0567 WAIT_FOR_STATE_AND_IDLE(session, DebugSession::PausedState); 0568 QCOMPARE(session->currentLine(), 22); 0569 0570 session->run(); 0571 WAIT_FOR_STATE_AND_IDLE(session, DebugSession::PausedState); 0572 QCOMPARE(session->currentLine(), 23); 0573 0574 0575 session->run(); 0576 WAIT_FOR_STATE_AND_IDLE(session, DebugSession::PausedState); 0577 QCOMPARE(session->currentLine(), 24); 0578 0579 session->run(); 0580 WAIT_FOR_STATE(session, DebugSession::EndedState); 0581 } 0582 0583 void LldbTest::testInsertBreakpointWhileRunning() 0584 { 0585 #ifdef Q_OS_FREEBSD 0586 QSKIP("apparently this test doesn't work on FreeBSD"); 0587 #endif 0588 0589 auto *session = new TestDebugSession; 0590 TestLaunchConfiguration cfg(QStringLiteral("debuggee_debugeeslow")); 0591 QString fileName = findSourceFile("debugeeslow.cpp"); 0592 0593 QVERIFY(session->startDebugging(&cfg, m_iface)); 0594 0595 WAIT_FOR_STATE(session, DebugSession::ActiveState); 0596 WAIT_FOR_A_WHILE(session, 2000); 0597 0598 qDebug() << "adding breakpoint"; 0599 KDevelop::Breakpoint *b = breakpoints()->addCodeBreakpoint(QUrl::fromLocalFile(fileName), 25); 0600 WAIT_FOR_A_WHILE(session, 500); 0601 0602 WAIT_FOR_STATE_AND_IDLE(session, DebugSession::PausedState); 0603 WAIT_FOR_A_WHILE(session, 500); 0604 0605 QCOMPARE(session->currentLine(), 25); 0606 breakpoints()->removeBreakpoint(b); 0607 session->run(); 0608 WAIT_FOR_STATE(session, DebugSession::EndedState); 0609 } 0610 0611 void LldbTest::testInsertBreakpointWhileRunningMultiple() 0612 { 0613 #ifdef Q_OS_FREEBSD 0614 QSKIP("apparently this test doesn't work on FreeBSD"); 0615 #endif 0616 0617 auto *session = new TestDebugSession; 0618 TestLaunchConfiguration cfg(QStringLiteral("debuggee_debugeeslow")); 0619 QString fileName = findSourceFile("debugeeslow.cpp"); 0620 0621 QVERIFY(session->startDebugging(&cfg, m_iface)); 0622 0623 WAIT_FOR_STATE(session, DebugSession::ActiveState); 0624 WAIT_FOR_A_WHILE(session, 2000); 0625 0626 qDebug() << "adding breakpoint"; 0627 auto b1 = breakpoints()->addCodeBreakpoint(QUrl::fromLocalFile(fileName), 24); 0628 auto b2 = breakpoints()->addCodeBreakpoint(QUrl::fromLocalFile(fileName), 25); 0629 0630 WAIT_FOR_A_WHILE(session, 500); 0631 WAIT_FOR_STATE_AND_IDLE(session, DebugSession::PausedState); 0632 0633 WAIT_FOR_A_WHILE(session, 500); 0634 QCOMPARE(session->currentLine(), 24); 0635 0636 session->run(); 0637 WAIT_FOR_STATE_AND_IDLE(session, DebugSession::PausedState); 0638 0639 WAIT_FOR_A_WHILE(session, 500); 0640 QCOMPARE(session->currentLine(), 25); 0641 breakpoints()->removeBreakpoint(b1); 0642 breakpoints()->removeBreakpoint(b2); 0643 0644 session->run(); 0645 WAIT_FOR_STATE(session, DebugSession::EndedState); 0646 } 0647 0648 void LldbTest::testInsertBreakpointFunctionName() 0649 { 0650 auto *session = new TestDebugSession; 0651 TestLaunchConfiguration cfg; 0652 0653 breakpoints()->addCodeBreakpoint(QStringLiteral("main")); 0654 0655 QVERIFY(session->startDebugging(&cfg, m_iface)); 0656 WAIT_FOR_STATE_AND_IDLE(session, DebugSession::PausedState); 0657 QCOMPARE(session->currentLine(), 27); 0658 0659 session->run(); 0660 WAIT_FOR_STATE(session, DebugSession::EndedState); 0661 } 0662 0663 void LldbTest::testManualBreakpoint() 0664 { 0665 auto *session = new TestDebugSession; 0666 TestLaunchConfiguration cfg; 0667 0668 breakpoints()->addCodeBreakpoint(QStringLiteral("main")); 0669 0670 QVERIFY(session->startDebugging(&cfg, m_iface)); 0671 WAIT_FOR_STATE_AND_IDLE(session, DebugSession::PausedState); 0672 QCOMPARE(session->currentLine(), 27); 0673 0674 breakpoints()->removeRows(0, 1); 0675 WAIT_FOR_A_WHILE(session, 100); 0676 QCOMPARE(breakpoints()->rowCount(), 0); 0677 0678 session->addCommand(MI::NonMI, QStringLiteral("break set --file debugee.cpp --line 23")); 0679 WAIT_FOR_A_WHILE(session, 100); 0680 QCOMPARE(breakpoints()->rowCount(), 1); 0681 0682 auto b = breakpoints()->breakpoint(0); 0683 QCOMPARE(b->line(), 22); 0684 0685 session->addCommand(MI::NonMI, QStringLiteral("break disable 2")); 0686 session->addCommand(MI::NonMI, QStringLiteral("break modify -c 'i == 1' 2")); 0687 session->addCommand(MI::NonMI, QStringLiteral("break modify -i 1 2")); 0688 WAIT_FOR_A_WHILE(session, 1000); 0689 QCOMPARE(b->enabled(), false); 0690 QEXPECT_FAIL("", "LLDB 4.0 does not report condition in mi response", Continue); 0691 QCOMPARE(b->condition(), QString("i == 1")); 0692 QEXPECT_FAIL("", "LLDB 4.0 does not report ignore hits in mi response", Continue); 0693 QCOMPARE(b->ignoreHits(), 1); 0694 0695 session->addCommand(MI::NonMI, QStringLiteral("break delete 2")); 0696 WAIT_FOR_A_WHILE(session, 100); 0697 QEXPECT_FAIL("", "LLDB 4.0 does not report breakpoint deletion as mi notification", Continue); 0698 QCOMPARE(breakpoints()->rowCount(), 0); 0699 0700 session->run(); 0701 WAIT_FOR_STATE(session, DebugSession::EndedState); 0702 } 0703 0704 //Bug 201771 0705 void LldbTest::testInsertAndRemoveBreakpointWhileRunning() 0706 { 0707 #ifdef Q_OS_FREEBSD 0708 QSKIP("apparently this test doesn't work on FreeBSD"); 0709 #endif 0710 0711 auto *session = new TestDebugSession; 0712 TestLaunchConfiguration cfg(QStringLiteral("debuggee_debugeeslow")); 0713 0714 QString fileName = findSourceFile("debugeeslow.cpp"); 0715 0716 QVERIFY(session->startDebugging(&cfg, m_iface)); 0717 WAIT_FOR_STATE(session, DebugSession::ActiveState); 0718 WAIT_FOR_A_WHILE(session, 1000); 0719 0720 KDevelop::Breakpoint *b = breakpoints()->addCodeBreakpoint(QUrl::fromLocalFile(fileName), 25); 0721 WAIT_FOR_A_WHILE(session, 200); // wait for feedback notification from lldb-mi 0722 breakpoints()->removeBreakpoint(b); 0723 0724 WAIT_FOR_A_WHILE(session, 3000); // give slow debugee extra time to run 0725 WAIT_FOR_STATE(session, DebugSession::EndedState); 0726 } 0727 0728 void LldbTest::testPickupManuallyInsertedBreakpoint() 0729 { 0730 auto *session = new TestDebugSession; 0731 TestLaunchConfiguration cfg; 0732 0733 breakpoints()->addCodeBreakpoint(QStringLiteral("main")); 0734 QVERIFY(session->startDebugging(&cfg, m_iface)); 0735 0736 WAIT_FOR_STATE_AND_IDLE(session, DebugSession::PausedState); 0737 0738 session->addCommand(MI::NonMI, QStringLiteral("break set --file debugee.cpp --line 32")); 0739 session->stepInto(); 0740 WAIT_FOR_STATE_AND_IDLE(session, DebugSession::PausedState); 0741 QCOMPARE(breakpoints()->breakpoints().count(), 2); 0742 QCOMPARE(breakpoints()->rowCount(), 2); 0743 KDevelop::Breakpoint *b = breakpoints()->breakpoint(1); 0744 QVERIFY(b); 0745 QCOMPARE(b->line(), 31); //we start with 0, gdb with 1 0746 QCOMPARE(b->url().fileName(), QString("debugee.cpp")); 0747 } 0748 0749 //Bug 270970 0750 void LldbTest::testPickupManuallyInsertedBreakpointOnlyOnce() 0751 { 0752 auto *session = new TestDebugSession; 0753 0754 QString sourceFile = findSourceFile("debugee.cpp"); 0755 //inject here, so it behaves similar like a command from .lldbinit 0756 QTemporaryFile configScript; 0757 configScript.open(); 0758 configScript.write(QStringLiteral("break set --file %0 --line 32\n").arg(sourceFile).toLocal8Bit()); 0759 configScript.close(); 0760 0761 TestLaunchConfiguration cfg; 0762 KConfigGroup grp = cfg.config(); 0763 grp.writeEntry(Config::LldbConfigScriptEntry, QUrl::fromLocalFile(configScript.fileName())); 0764 0765 breakpoints()->addCodeBreakpoint(QUrl::fromLocalFile(QStringLiteral("debugee.cpp")), 31); 0766 0767 QVERIFY(session->startDebugging(&cfg, m_iface)); 0768 WAIT_FOR_STATE_AND_IDLE(session, DebugSession::PausedState); 0769 0770 QCOMPARE(breakpoints()->breakpoints().count(), 1); 0771 0772 session->run(); 0773 WAIT_FOR_STATE(session, DebugSession::EndedState); 0774 } 0775 0776 void LldbTest::testBreakpointWithSpaceInPath() 0777 { 0778 auto *session = new TestDebugSession; 0779 TestLaunchConfiguration cfg(QStringLiteral("debuggee_debugeespace")); 0780 0781 KConfigGroup grp = cfg.config(); 0782 QString fileName = findSourceFile("debugee space.cpp"); 0783 0784 KDevelop::Breakpoint * b = breakpoints()->addCodeBreakpoint(QUrl::fromLocalFile(fileName), 20); 0785 QCOMPARE(b->state(), KDevelop::Breakpoint::NotStartedState); 0786 0787 QVERIFY(session->startDebugging(&cfg, m_iface)); 0788 WAIT_FOR_STATE_AND_IDLE(session, DebugSession::PausedState); 0789 0790 QCOMPARE(session->currentLine(), 20); 0791 session->run(); 0792 WAIT_FOR_STATE(session, DebugSession::EndedState); 0793 } 0794 0795 void LldbTest::testBreakpointDisabledOnStart() 0796 { 0797 auto *session = new TestDebugSession; 0798 TestLaunchConfiguration cfg; 0799 0800 auto b = breakpoints()->addCodeBreakpoint(QUrl::fromLocalFile(m_debugeeFileName), 23); 0801 b->setData(KDevelop::Breakpoint::EnableColumn, Qt::Unchecked); 0802 breakpoints()->addCodeBreakpoint(QUrl::fromLocalFile(m_debugeeFileName), 29); 0803 b = breakpoints()->addCodeBreakpoint(QUrl::fromLocalFile(m_debugeeFileName), 34); 0804 b->setData(KDevelop::Breakpoint::EnableColumn, Qt::Unchecked); 0805 0806 QVERIFY(session->startDebugging(&cfg, m_iface)); 0807 WAIT_FOR_STATE_AND_IDLE(session, DebugSession::PausedState); 0808 0809 QEXPECT_FAIL("", "See LLDB bug 28703: -d flag has no effect", Abort); 0810 QCOMPARE(session->currentLine(), 29); 0811 b->setData(KDevelop::Breakpoint::EnableColumn, Qt::Checked); 0812 0813 session->run(); 0814 WAIT_FOR_STATE_AND_IDLE(session, DebugSession::PausedState); 0815 QCOMPARE(session->currentLine(), 34); 0816 0817 session->run(); 0818 WAIT_FOR_STATE(session, DebugSession::EndedState); 0819 } 0820 0821 void LldbTest::testMultipleLocationsBreakpoint() 0822 { 0823 auto *session = new TestDebugSession; 0824 TestLaunchConfiguration cfg(QStringLiteral("debuggee_debugeemultilocbreakpoint")); 0825 0826 breakpoints()->addCodeBreakpoint(QStringLiteral("aPlusB")); 0827 0828 //TODO check if the additional location breakpoint is added 0829 0830 QVERIFY(session->startDebugging(&cfg, m_iface)); 0831 WAIT_FOR_STATE_AND_IDLE(session, DebugSession::PausedState); 0832 QCOMPARE(session->currentLine(), 19); 0833 0834 session->run(); 0835 WAIT_FOR_STATE_AND_IDLE(session, DebugSession::PausedState); 0836 QCOMPARE(session->currentLine(), 23); 0837 0838 session->run(); 0839 WAIT_FOR_STATE(session, DebugSession::EndedState); 0840 } 0841 0842 void LldbTest::testMultipleBreakpoint() 0843 { 0844 auto *session = new TestDebugSession; 0845 0846 //there'll be about 3-4 breakpoints, but we treat it like one. 0847 TestLaunchConfiguration c(QStringLiteral("debuggee_debugeemultiplebreakpoint")); 0848 auto b = breakpoints()->addCodeBreakpoint(QStringLiteral("debugeemultiplebreakpoint.cpp:52")); 0849 0850 QVERIFY(session->startDebugging(&c, m_iface)); 0851 WAIT_FOR_STATE_AND_IDLE(session, DebugSession::PausedState); 0852 0853 QCOMPARE(breakpoints()->breakpoints().count(), 1); 0854 0855 b->setData(KDevelop::Breakpoint::EnableColumn, Qt::Unchecked); 0856 session->run(); 0857 WAIT_FOR_STATE(session, DebugSession::EndedState); 0858 } 0859 0860 void LldbTest::testRegularExpressionBreakpoint() 0861 { 0862 QSKIP("Skipping... lldb has only one breakpoint for multiple locations" 0863 " (and lldb-mi returns the first one), not support this yet"); 0864 auto *session = new TestDebugSession; 0865 TestLaunchConfiguration c(QStringLiteral("debuggee_debugeemultilocbreakpoint")); 0866 0867 breakpoints()->addCodeBreakpoint(QStringLiteral("main")); 0868 QVERIFY(session->startDebugging(&c, m_iface)); 0869 0870 WAIT_FOR_STATE_AND_IDLE(session, DebugSession::PausedState); 0871 0872 session->addCommand(MI::NonMI, QStringLiteral("break set --func-regex .*aPl.*B")); 0873 session->run(); 0874 WAIT_FOR_STATE_AND_IDLE(session, DebugSession::PausedState); 0875 0876 QCOMPARE(breakpoints()->breakpoints().count(), 3); 0877 0878 session->addCommand(MI::BreakDelete, QString()); 0879 session->run(); 0880 WAIT_FOR_STATE(session, DebugSession::EndedState); 0881 } 0882 0883 void LldbTest::testChangeBreakpointWhileRunning() 0884 { 0885 QSKIP("Skipping... lldb-mi command -break-enable doesn't enable breakpoint"); 0886 auto *session = new TestDebugSession; 0887 TestLaunchConfiguration c(QStringLiteral("debuggee_debugeeslow")); 0888 0889 KDevelop::Breakpoint* b = breakpoints()->addCodeBreakpoint(QStringLiteral("debugeeslow.cpp:25")); 0890 QVERIFY(session->startDebugging(&c, m_iface)); 0891 WAIT_FOR_STATE_AND_IDLE(session, DebugSession::PausedState); 0892 0893 QVERIFY(session->currentLine() >= 24 && session->currentLine() <= 26 ); 0894 0895 session->run(); 0896 WAIT_FOR_STATE(session, DebugSession::ActiveState); 0897 qDebug() << "Disabling breakpoint"; 0898 b->setData(KDevelop::Breakpoint::EnableColumn, Qt::Unchecked); 0899 //to make one loop 0900 WAIT_FOR_A_WHILE(session, 2500); 0901 qDebug() << "Waiting for active"; 0902 WAIT_FOR_STATE(session, DebugSession::ActiveState); 0903 qDebug() << "Enabling breakpoint"; 0904 0905 // Use native user command works, but not through -break-enable, which is triggered by setData 0906 session->addCommand(MI::NonMI, QStringLiteral("break enable")); 0907 //b->setData(KDevelop::Breakpoint::EnableColumn, Qt::Checked); 0908 0909 WAIT_FOR_STATE_AND_IDLE(session, DebugSession::PausedState); 0910 0911 b->setData(KDevelop::Breakpoint::EnableColumn, Qt::Unchecked); 0912 0913 session->run(); 0914 WAIT_FOR_STATE(session, DebugSession::EndedState); 0915 } 0916 0917 void LldbTest::testCatchpoint() 0918 { 0919 auto *session = new TestDebugSession; 0920 TestLaunchConfiguration cfg(QStringLiteral("debuggee_debugeeexception")); 0921 0922 session->variableController()->setAutoUpdate(KDevelop::IVariableController::UpdateLocals); 0923 TestFrameStackModel* fsModel = session->frameStackModel(); 0924 0925 breakpoints()->addCodeBreakpoint(QUrl::fromLocalFile(findSourceFile("debugeeexception.cpp")), 29); 0926 0927 QVERIFY(session->startDebugging(&cfg, m_iface)); 0928 WAIT_FOR_STATE_AND_IDLE(session, DebugSession::PausedState); 0929 0930 QCOMPARE(fsModel->currentFrame(), 0); 0931 QCOMPARE(session->currentLine(), 29); 0932 0933 session->addCommand(MI::NonMI, QStringLiteral("break set -E c++")); 0934 session->run(); 0935 WAIT_FOR_STATE_AND_IDLE(session, DebugSession::PausedState); 0936 0937 const auto frames = fsModel->frames(fsModel->currentThread()); 0938 QVERIFY(frames.size() >= 2); 0939 // frame 0 is somewhere inside libstdc++ 0940 QCOMPARE(frames[1].file, QUrl::fromLocalFile(findSourceFile("debugeeexception.cpp"))); 0941 QCOMPARE(frames[1].line, 22); 0942 0943 QCOMPARE(breakpoints()->rowCount(),2); 0944 QVERIFY(!breakpoints()->breakpoint(0)->location().isEmpty()); 0945 QVERIFY(!breakpoints()->breakpoint(1)->location().isEmpty()); 0946 0947 session->run(); 0948 WAIT_FOR_STATE(session, DebugSession::EndedState); 0949 } 0950 0951 void LldbTest::testShowStepInSource() 0952 { 0953 auto *session = new TestDebugSession; 0954 TestLaunchConfiguration cfg; 0955 0956 QSignalSpy showStepInSourceSpy(session, &TestDebugSession::showStepInSource); 0957 0958 breakpoints()->addCodeBreakpoint(QUrl::fromLocalFile(m_debugeeFileName), 29); 0959 0960 QVERIFY(session->startDebugging(&cfg, m_iface)); 0961 WAIT_FOR_STATE_AND_IDLE(session, DebugSession::PausedState); 0962 0963 session->stepInto(); 0964 WAIT_FOR_STATE_AND_IDLE(session, DebugSession::PausedState); 0965 0966 session->stepInto(); 0967 WAIT_FOR_STATE_AND_IDLE(session, DebugSession::PausedState); 0968 session->run(); 0969 WAIT_FOR_STATE(session, DebugSession::EndedState); 0970 0971 { 0972 QCOMPARE(showStepInSourceSpy.count(), 3); 0973 QList<QVariant> arguments = showStepInSourceSpy.takeFirst(); 0974 QCOMPARE(arguments.first().toUrl(), QUrl::fromLocalFile(m_debugeeFileName)); 0975 QCOMPARE(arguments.at(1).toInt(), 29); 0976 0977 arguments = showStepInSourceSpy.takeFirst(); 0978 QCOMPARE(arguments.first().toUrl(), QUrl::fromLocalFile(m_debugeeFileName)); 0979 QCOMPARE(arguments.at(1).toInt(), 22); 0980 0981 arguments = showStepInSourceSpy.takeFirst(); 0982 QCOMPARE(arguments.first().toUrl(), QUrl::fromLocalFile(m_debugeeFileName)); 0983 QCOMPARE(arguments.at(1).toInt(), 23); 0984 } 0985 } 0986 0987 void LldbTest::testStack() 0988 { 0989 auto *session = new TestDebugSession; 0990 TestLaunchConfiguration cfg; 0991 0992 TestFrameStackModel *stackModel = session->frameStackModel(); 0993 0994 breakpoints()->addCodeBreakpoint(QUrl::fromLocalFile(m_debugeeFileName), 21); 0995 0996 QVERIFY(session->startDebugging(&cfg, m_iface)); 0997 WAIT_FOR_STATE_AND_IDLE(session, DebugSession::PausedState); 0998 0999 QModelIndex tIdx = stackModel->index(0,0); 1000 QCOMPARE(stackModel->rowCount(QModelIndex()), 1); 1001 QCOMPARE(stackModel->columnCount(QModelIndex()), 3); 1002 COMPARE_DATA(tIdx, "#1 at foo()"); 1003 1004 QCOMPARE(stackModel->rowCount(tIdx), 4); 1005 QCOMPARE(stackModel->columnCount(tIdx), 3); 1006 COMPARE_DATA(stackModel->index(0, 0, tIdx), "0"); 1007 COMPARE_DATA(stackModel->index(0, 1, tIdx), "foo()"); 1008 COMPARE_DATA(stackModel->index(0, 2, tIdx), m_debugeeFileName+":23"); 1009 COMPARE_DATA(stackModel->index(1, 0, tIdx), "1"); 1010 COMPARE_DATA(stackModel->index(1, 1, tIdx), "main"); 1011 COMPARE_DATA(stackModel->index(1, 2, tIdx), m_debugeeFileName+":29"); 1012 COMPARE_DATA(stackModel->index(2, 0, tIdx), "2"); 1013 COMPARE_DATA(stackModel->index(2, 1, tIdx), "__libc_start_main"); 1014 COMPARE_DATA(stackModel->index(3, 0, tIdx), "3"); 1015 COMPARE_DATA(stackModel->index(3, 1, tIdx), "_start"); 1016 1017 1018 session->stepOut(); 1019 WAIT_FOR_STATE_AND_IDLE(session, DebugSession::PausedState); 1020 COMPARE_DATA(tIdx, "#1 at main"); 1021 QCOMPARE(stackModel->rowCount(tIdx), 3); 1022 COMPARE_DATA(stackModel->index(0, 0, tIdx), "0"); 1023 COMPARE_DATA(stackModel->index(0, 1, tIdx), "main"); 1024 COMPARE_DATA(stackModel->index(0, 2, tIdx), m_debugeeFileName+":30"); 1025 COMPARE_DATA(stackModel->index(1, 0, tIdx), "1"); 1026 COMPARE_DATA(stackModel->index(1, 1, tIdx), "__libc_start_main"); 1027 COMPARE_DATA(stackModel->index(2, 0, tIdx), "2"); 1028 COMPARE_DATA(stackModel->index(2, 1, tIdx), "_start"); 1029 1030 session->run(); 1031 WAIT_FOR_STATE_AND_IDLE(session, DebugSession::PausedState); 1032 1033 session->run(); 1034 WAIT_FOR_STATE(session, DebugSession::EndedState); 1035 } 1036 1037 void LldbTest::testStackFetchMore() 1038 { 1039 auto *session = new TestDebugSession; 1040 TestLaunchConfiguration cfg(QStringLiteral("debuggee_debugeerecursion")); 1041 QString fileName = findSourceFile("debugeerecursion.cpp"); 1042 1043 TestFrameStackModel *stackModel = session->frameStackModel(); 1044 1045 breakpoints()->addCodeBreakpoint(QUrl::fromLocalFile(fileName), 25); 1046 1047 QVERIFY(session->startDebugging(&cfg, m_iface)); 1048 WAIT_FOR_STATE_AND_IDLE(session, DebugSession::PausedState); 1049 QCOMPARE(session->frameStackModel()->fetchFramesCalled, 1); 1050 1051 QModelIndex tIdx = stackModel->index(0,0); 1052 QCOMPARE(stackModel->rowCount(QModelIndex()), 1); 1053 QCOMPARE(stackModel->columnCount(QModelIndex()), 3); 1054 COMPARE_DATA(tIdx, "#1 at foo()"); 1055 1056 QCOMPARE(stackModel->rowCount(tIdx), 21); 1057 COMPARE_DATA(stackModel->index(0, 0, tIdx), "0"); 1058 COMPARE_DATA(stackModel->index(0, 1, tIdx), "foo()"); 1059 COMPARE_DATA(stackModel->index(0, 2, tIdx), fileName+":26"); 1060 COMPARE_DATA(stackModel->index(1, 0, tIdx), "1"); 1061 COMPARE_DATA(stackModel->index(1, 1, tIdx), "foo()"); 1062 COMPARE_DATA(stackModel->index(1, 2, tIdx), fileName+":24"); 1063 COMPARE_DATA(stackModel->index(2, 0, tIdx), "2"); 1064 COMPARE_DATA(stackModel->index(2, 1, tIdx), "foo()"); 1065 COMPARE_DATA(stackModel->index(2, 2, tIdx), fileName+":24"); 1066 COMPARE_DATA(stackModel->index(19, 0, tIdx), "19"); 1067 COMPARE_DATA(stackModel->index(20, 0, tIdx), "20"); 1068 1069 stackModel->fetchMoreFrames(); 1070 WAIT_FOR_A_WHILE(session, 200); 1071 QCOMPARE(stackModel->fetchFramesCalled, 2); 1072 QCOMPARE(stackModel->rowCount(tIdx), 41); 1073 COMPARE_DATA(stackModel->index(20, 0, tIdx), "20"); 1074 COMPARE_DATA(stackModel->index(21, 0, tIdx), "21"); 1075 COMPARE_DATA(stackModel->index(22, 0, tIdx), "22"); 1076 COMPARE_DATA(stackModel->index(39, 0, tIdx), "39"); 1077 COMPARE_DATA(stackModel->index(40, 0, tIdx), "40"); 1078 1079 stackModel->fetchMoreFrames(); 1080 WAIT_FOR_A_WHILE(session, 200); 1081 QCOMPARE(stackModel->fetchFramesCalled, 3); 1082 QCOMPARE(stackModel->rowCount(tIdx), 121); 1083 COMPARE_DATA(stackModel->index(40, 0, tIdx), "40"); 1084 COMPARE_DATA(stackModel->index(41, 0, tIdx), "41"); 1085 COMPARE_DATA(stackModel->index(42, 0, tIdx), "42"); 1086 COMPARE_DATA(stackModel->index(119, 0, tIdx), "119"); 1087 COMPARE_DATA(stackModel->index(120, 0, tIdx), "120"); 1088 1089 stackModel->fetchMoreFrames(); 1090 WAIT_FOR_A_WHILE(session, 200); 1091 QCOMPARE(stackModel->fetchFramesCalled, 4); 1092 QCOMPARE(stackModel->rowCount(tIdx), 301); 1093 COMPARE_DATA(stackModel->index(120, 0, tIdx), "120"); 1094 COMPARE_DATA(stackModel->index(121, 0, tIdx), "121"); 1095 COMPARE_DATA(stackModel->index(122, 0, tIdx), "122"); 1096 COMPARE_DATA(stackModel->index(298, 0, tIdx), "298"); 1097 COMPARE_DATA(stackModel->index(298, 1, tIdx), "main"); 1098 COMPARE_DATA(stackModel->index(298, 2, tIdx), fileName+":30"); 1099 COMPARE_DATA(stackModel->index(299, 0, tIdx), "299"); 1100 COMPARE_DATA(stackModel->index(299, 1, tIdx), "__libc_start_main"); 1101 COMPARE_DATA(stackModel->index(300, 0, tIdx), "300"); 1102 COMPARE_DATA(stackModel->index(300, 1, tIdx), "_start"); 1103 1104 stackModel->fetchMoreFrames(); //nothing to fetch, we are at the end 1105 WAIT_FOR_A_WHILE(session, 200); 1106 QCOMPARE(stackModel->fetchFramesCalled, 4); 1107 QCOMPARE(stackModel->rowCount(tIdx), 301); 1108 1109 session->run(); 1110 WAIT_FOR_STATE(session, DebugSession::EndedState); 1111 } 1112 1113 void LldbTest::testStackDeactivateAndActive() 1114 { 1115 auto *session = new TestDebugSession; 1116 TestLaunchConfiguration cfg; 1117 1118 TestFrameStackModel *stackModel = session->frameStackModel(); 1119 1120 breakpoints()->addCodeBreakpoint(QUrl::fromLocalFile(m_debugeeFileName), 21); 1121 QVERIFY(session->startDebugging(&cfg, m_iface)); 1122 WAIT_FOR_STATE(session, DebugSession::PausedState); 1123 1124 QModelIndex tIdx = stackModel->index(0,0); 1125 1126 session->stepOut(); 1127 WAIT_FOR_STATE_AND_IDLE(session, DebugSession::PausedState); 1128 COMPARE_DATA(tIdx, "#1 at main"); 1129 QCOMPARE(stackModel->rowCount(tIdx), 3); 1130 COMPARE_DATA(stackModel->index(0, 0, tIdx), "0"); 1131 COMPARE_DATA(stackModel->index(0, 1, tIdx), "main"); 1132 COMPARE_DATA(stackModel->index(0, 2, tIdx), m_debugeeFileName+":30"); 1133 COMPARE_DATA(stackModel->index(1, 0, tIdx), "1"); 1134 COMPARE_DATA(stackModel->index(1, 1, tIdx), "__libc_start_main"); 1135 COMPARE_DATA(stackModel->index(2, 0, tIdx), "2"); 1136 COMPARE_DATA(stackModel->index(2, 1, tIdx), "_start"); 1137 1138 session->run(); 1139 WAIT_FOR_STATE_AND_IDLE(session, DebugSession::PausedState); 1140 1141 session->run(); 1142 WAIT_FOR_STATE(session, DebugSession::EndedState); 1143 } 1144 1145 void LldbTest::testStackSwitchThread() 1146 { 1147 QSKIP("Skipping... lldb-mi crashes when break at a location with multiple threads running"); 1148 auto *session = new TestDebugSession; 1149 TestLaunchConfiguration cfg(QStringLiteral("debuggee_debugeethreads")); 1150 QString fileName = findSourceFile("debugeethreads.cpp"); 1151 1152 TestFrameStackModel *stackModel = session->frameStackModel(); 1153 1154 breakpoints()->addCodeBreakpoint(QUrl::fromLocalFile(fileName), 38); 1155 QVERIFY(session->startDebugging(&cfg, m_iface)); 1156 WAIT_FOR_STATE_AND_IDLE(session, DebugSession::PausedState); 1157 1158 QCOMPARE(stackModel->rowCount(), 4); 1159 1160 QModelIndex tIdx = stackModel->index(0,0); 1161 COMPARE_DATA(tIdx, "#1 at main"); 1162 QCOMPARE(stackModel->rowCount(tIdx), 1); 1163 COMPARE_DATA(stackModel->index(0, 0, tIdx), "0"); 1164 COMPARE_DATA(stackModel->index(0, 1, tIdx), "main"); 1165 COMPARE_DATA(stackModel->index(0, 2, tIdx), fileName+":39"); 1166 1167 tIdx = stackModel->index(1,0); 1168 QVERIFY(stackModel->data(tIdx).toString().startsWith("#2 at ")); 1169 stackModel->setCurrentThread(2); 1170 WAIT_FOR_A_WHILE(session, 200); 1171 int rows = stackModel->rowCount(tIdx); 1172 QVERIFY(rows > 3); 1173 1174 session->run(); 1175 WAIT_FOR_STATE(session, DebugSession::EndedState); 1176 } 1177 1178 void LldbTest::testAttach() 1179 { 1180 #ifdef Q_OS_FREEBSD 1181 QSKIP("apparently this test doesn't work on FreeBSD"); 1182 #endif 1183 1184 SKIP_IF_ATTACH_FORBIDDEN(); 1185 1186 QString fileName = findSourceFile("debugeeslow.cpp"); 1187 1188 KProcess debugeeProcess; 1189 debugeeProcess << QStringLiteral("nice") << findExecutable(QStringLiteral("debuggee_debugeeslow")).toLocalFile(); 1190 debugeeProcess.start(); 1191 QVERIFY(debugeeProcess.waitForStarted()); 1192 QTest::qWait(100); 1193 1194 auto *session = new TestDebugSession; 1195 session->attachToProcess(debugeeProcess.processId()); 1196 1197 WAIT_FOR_A_WHILE(session, 100); 1198 1199 breakpoints()->addCodeBreakpoint(QUrl::fromLocalFile(fileName), 35); 1200 1201 // lldb-mi silently stops when attaching to a process. Force it continue to run. 1202 session->addCommand(MI::ExecContinue, QString(), MI::CmdMaybeStartsRunning); 1203 WAIT_FOR_A_WHILE(session, 2000); 1204 WAIT_FOR_STATE_AND_IDLE(session, DebugSession::PausedState); 1205 1206 QCOMPARE(session->currentLine(), 35); 1207 1208 session->run(); 1209 WAIT_FOR_STATE(session, DebugSession::EndedState); 1210 } 1211 1212 void LldbTest::testRemoteDebugging() 1213 { 1214 KProcess gdbServer; 1215 gdbServer << QStringLiteral("lldb-server") << QStringLiteral("gdbserver") << QStringLiteral("*:1234"); 1216 gdbServer.start(); 1217 QVERIFY(gdbServer.waitForStarted()); 1218 1219 auto *session = new TestDebugSession; 1220 TestLaunchConfiguration cfg; 1221 1222 cfg.config().writeEntry(Config::LldbRemoteDebuggingEntry, true); 1223 cfg.config().writeEntry(Config::LldbRemoteServerEntry, "localhost:1234"); 1224 cfg.config().writeEntry(Config::LldbRemotePathEntry, "/tmp"); 1225 1226 breakpoints()->addCodeBreakpoint(QUrl::fromLocalFile(m_debugeeFileName), 34); 1227 1228 QVERIFY(session->startDebugging(&cfg, m_iface)); 1229 WAIT_FOR_STATE_AND_IDLE(session, DebugSession::PausedState); 1230 1231 session->run(); 1232 WAIT_FOR_STATE(session, DebugSession::EndedState); 1233 } 1234 1235 void LldbTest::testCoreFile() 1236 { 1237 QFileInfo f(QStringLiteral("core")); 1238 f.setCaching(false); // don't cache information 1239 if (f.exists()) { 1240 QVERIFY(QFile::remove(f.canonicalFilePath())); 1241 } 1242 1243 KProcess debugeeProcess; 1244 debugeeProcess.setOutputChannelMode(KProcess::MergedChannels); 1245 debugeeProcess << QStringLiteral("bash") << QStringLiteral("-c") 1246 << "ulimit -c unlimited; " 1247 + findExecutable(QStringLiteral("debuggee_crash")).toLocalFile(); 1248 debugeeProcess.start(); 1249 debugeeProcess.waitForFinished(); 1250 qDebug() << debugeeProcess.readAll(); 1251 1252 bool coreFileFound = f.exists(); 1253 if (!coreFileFound) { 1254 // Try to use coredumpctl 1255 qDebug() << "try to use coredumpctl"; 1256 auto coredumpctl = QStandardPaths::findExecutable(QStringLiteral("coredumpctl")); 1257 if (!coredumpctl.isEmpty()) { 1258 KProcess::execute(coredumpctl, {"-1", "-o", f.absoluteFilePath(), "dump", "debuggee_crash"}); 1259 // coredumpctl seems to create an empty file "core" even if no cores can be delivered 1260 // (like when run inside docker containers as on KDE CI or with kernel.core_pattern=|/dev/null) 1261 // so also check for size != 0 1262 coreFileFound = f.exists() && (f.size() > 0); 1263 } 1264 } 1265 if (!coreFileFound) 1266 QSKIP("no core dump found, check your system configuration (see /proc/sys/kernel/core_pattern)."); 1267 1268 auto *session = new TestDebugSession; 1269 session->examineCoreFile(findExecutable(QStringLiteral("debuggee_crash")), 1270 QUrl::fromLocalFile(f.canonicalFilePath())); 1271 1272 TestFrameStackModel *stackModel = session->frameStackModel(); 1273 1274 WAIT_FOR_STATE(session, DebugSession::StoppedState); 1275 1276 QModelIndex tIdx = stackModel->index(0,0); 1277 QCOMPARE(stackModel->rowCount(QModelIndex()), 1); 1278 QCOMPARE(stackModel->columnCount(QModelIndex()), 3); 1279 COMPARE_DATA(tIdx, "#1 at foo()"); 1280 1281 session->stopDebugger(); 1282 WAIT_FOR_STATE(session, DebugSession::EndedState); 1283 } 1284 1285 void LldbTest::testVariablesLocals() 1286 { 1287 auto *session = new TestDebugSession; 1288 TestLaunchConfiguration cfg; 1289 1290 session->variableController()->setAutoUpdate(IVariableController::UpdateLocals); 1291 1292 breakpoints()->addCodeBreakpoint(QUrl::fromLocalFile(m_debugeeFileName), 24); 1293 1294 QVERIFY(session->startDebugging(&cfg, m_iface)); 1295 WAIT_FOR_STATE_AND_IDLE(session, DebugSession::PausedState); 1296 1297 QCOMPARE(variableCollection()->rowCount(), 2); 1298 QModelIndex i = variableCollection()->index(1, 0); 1299 COMPARE_DATA(i, "Locals"); 1300 1301 QCOMPARE(variableCollection()->rowCount(i), 1); 1302 COMPARE_DATA(variableCollection()->index(0, 0, i), "j"); 1303 COMPARE_DATA(variableCollection()->index(0, 1, i), "1"); 1304 1305 session->run(); 1306 WAIT_FOR_STATE_AND_IDLE(session, DebugSession::PausedState); 1307 1308 COMPARE_DATA(variableCollection()->index(0, 0, i), "j"); 1309 COMPARE_DATA(variableCollection()->index(0, 1, i), "2"); 1310 1311 session->run(); 1312 WAIT_FOR_STATE(session, DebugSession::EndedState); 1313 } 1314 1315 void LldbTest::testVariablesLocalsStruct() 1316 { 1317 auto *session = new TestDebugSession; 1318 session->variableController()->setAutoUpdate(KDevelop::IVariableController::UpdateLocals); 1319 1320 TestLaunchConfiguration cfg; 1321 1322 breakpoints()->addCodeBreakpoint(QUrl::fromLocalFile(m_debugeeFileName), 38); 1323 QVERIFY(session->startDebugging(&cfg, m_iface)); 1324 WAIT_FOR_STATE(session, DebugSession::PausedState); 1325 WAIT_FOR_A_WHILE(session, 1000); 1326 1327 QModelIndex i = variableCollection()->index(1, 0); 1328 QCOMPARE(variableCollection()->rowCount(i), 4); 1329 1330 int structIndex = 0; 1331 for(int j=0; j<3; ++j) { 1332 if (variableCollection()->index(j, 0, i).data().toString() == QLatin1String("ts")) { 1333 structIndex = j; 1334 } 1335 } 1336 1337 COMPARE_DATA(variableCollection()->index(structIndex, 0, i), "ts"); 1338 COMPARE_DATA(variableCollection()->index(structIndex, 1, i), "{...}"); 1339 QModelIndex ts = variableCollection()->index(structIndex, 0, i); 1340 COMPARE_DATA(variableCollection()->index(0, 0, ts), "..."); 1341 variableCollection()->expanded(ts); 1342 WAIT_FOR_A_WHILE(session, 100); 1343 COMPARE_DATA(variableCollection()->index(0, 0, ts), "a"); 1344 COMPARE_DATA(variableCollection()->index(0, 1, ts), "0"); 1345 COMPARE_DATA(variableCollection()->index(1, 0, ts), "b"); 1346 COMPARE_DATA(variableCollection()->index(1, 1, ts), "1"); 1347 COMPARE_DATA(variableCollection()->index(2, 0, ts), "c"); 1348 COMPARE_DATA(variableCollection()->index(2, 1, ts), "2"); 1349 1350 session->stepInto(); 1351 WAIT_FOR_STATE(session, DebugSession::PausedState); 1352 WAIT_FOR_A_WHILE(session, 1000); 1353 COMPARE_DATA(variableCollection()->index(structIndex, 0, i), "ts"); 1354 COMPARE_DATA(variableCollection()->index(structIndex, 1, i), "{...}"); 1355 COMPARE_DATA(variableCollection()->index(0, 1, ts), "1"); 1356 1357 session->run(); 1358 WAIT_FOR_STATE(session, DebugSession::EndedState); 1359 } 1360 1361 void LldbTest::testVariablesWatches() 1362 { 1363 auto *session = new TestDebugSession; 1364 TestLaunchConfiguration cfg; 1365 1366 m_core->debugController()->variableCollection()->variableWidgetShown(); 1367 1368 breakpoints()->addCodeBreakpoint(QUrl::fromLocalFile(m_debugeeFileName), 38); 1369 QVERIFY(session->startDebugging(&cfg, m_iface)); 1370 WAIT_FOR_STATE(session, DebugSession::PausedState); 1371 1372 variableCollection()->watches()->add(QStringLiteral("ts")); 1373 WAIT_FOR_A_WHILE(session, 300); 1374 1375 QModelIndex i = variableCollection()->index(0, 0); 1376 QCOMPARE(variableCollection()->rowCount(i), 1); 1377 COMPARE_DATA(variableCollection()->index(0, 0, i), "ts"); 1378 COMPARE_DATA(variableCollection()->index(0, 1, i), "{...}"); 1379 QModelIndex ts = variableCollection()->index(0, 0, i); 1380 COMPARE_DATA(variableCollection()->index(0, 0, ts), "..."); 1381 variableCollection()->expanded(ts); 1382 WAIT_FOR_A_WHILE(session, 100); 1383 COMPARE_DATA(variableCollection()->index(0, 0, ts), "a"); 1384 COMPARE_DATA(variableCollection()->index(0, 1, ts), "0"); 1385 COMPARE_DATA(variableCollection()->index(1, 0, ts), "b"); 1386 COMPARE_DATA(variableCollection()->index(1, 1, ts), "1"); 1387 COMPARE_DATA(variableCollection()->index(2, 0, ts), "c"); 1388 COMPARE_DATA(variableCollection()->index(2, 1, ts), "2"); 1389 1390 session->stepInto(); 1391 WAIT_FOR_STATE(session, DebugSession::PausedState); 1392 WAIT_FOR_A_WHILE(session, 100); 1393 COMPARE_DATA(variableCollection()->index(0, 0, i), "ts"); 1394 COMPARE_DATA(variableCollection()->index(0, 1, i), "{...}"); 1395 COMPARE_DATA(variableCollection()->index(0, 1, ts), "1"); 1396 1397 session->run(); 1398 WAIT_FOR_STATE(session, DebugSession::EndedState); 1399 } 1400 1401 void LldbTest::testVariablesWatchesQuotes() 1402 { 1403 auto *session = new TestDebugSession; 1404 TestLaunchConfiguration cfg; 1405 1406 session->variableController()->setAutoUpdate(KDevelop::IVariableController::UpdateWatches); 1407 1408 // the unquoted string (the actual content): t\"t 1409 // quoted string (what we would write as a c string): "t\\\"t" 1410 // written in source file: R"("t\\\"t")" 1411 const QString testString(QStringLiteral("t\\\"t")); // the actual content 1412 const QString quotedTestString(QStringLiteral(R"("t\\\"t")")); 1413 1414 breakpoints()->addCodeBreakpoint(QUrl::fromLocalFile(m_debugeeFileName), 38); 1415 QVERIFY(session->startDebugging(&cfg, m_iface)); 1416 WAIT_FOR_STATE(session, DebugSession::PausedState); 1417 1418 variableCollection()->watches()->add(quotedTestString); //just a constant string 1419 WAIT_FOR_A_WHILE(session, 3000); 1420 1421 QModelIndex i = variableCollection()->index(0, 0); 1422 QCOMPARE(variableCollection()->rowCount(i), 1); 1423 COMPARE_DATA(variableCollection()->index(0, 0, i), quotedTestString); 1424 1425 QEXPECT_FAIL("", 1426 "LLDB 4.0 cannot deal with string literal in expression when debugging, causing memory access error", 1427 Abort); 1428 COMPARE_DATA(variableCollection()->index(0, 1, i), quotedTestString); 1429 1430 QModelIndex testStr = variableCollection()->index(0, 0, i); 1431 COMPARE_DATA(variableCollection()->index(0, 0, testStr), "..."); 1432 variableCollection()->expanded(testStr); 1433 WAIT_FOR_A_WHILE(session, 100); 1434 int len = testString.length(); 1435 for (int ind = 0; ind < len; ind++) 1436 { 1437 COMPARE_DATA(variableCollection()->index(ind, 0, testStr), QStringLiteral("[%0]").arg(ind)); 1438 QChar c = testString.at(ind); 1439 QString value = QString::number(c.toLatin1()) + " '" + c + "'"; 1440 COMPARE_DATA(variableCollection()->index(ind, 1, testStr), value); 1441 } 1442 COMPARE_DATA(variableCollection()->index(len, 0, testStr), QStringLiteral("[%0]").arg(len)); 1443 COMPARE_DATA(variableCollection()->index(len, 1, testStr), "0 '\\0'"); 1444 1445 session->run(); 1446 WAIT_FOR_STATE(session, DebugSession::EndedState); 1447 } 1448 1449 void LldbTest::testVariablesWatchesTwoSessions() 1450 { 1451 auto *session = new TestDebugSession; 1452 TestLaunchConfiguration cfg; 1453 1454 session->variableController()->setAutoUpdate(KDevelop::IVariableController::UpdateWatches); 1455 1456 breakpoints()->addCodeBreakpoint(QUrl::fromLocalFile(m_debugeeFileName), 38); 1457 QVERIFY(session->startDebugging(&cfg, m_iface)); 1458 WAIT_FOR_STATE_AND_IDLE(session, DebugSession::PausedState); 1459 1460 variableCollection()->watches()->add(QStringLiteral("ts")); 1461 WAIT_FOR_A_WHILE(session, 300); 1462 1463 QModelIndex ts = variableCollection()->index(0, 0, variableCollection()->index(0, 0)); 1464 variableCollection()->expanded(ts); 1465 WAIT_FOR_A_WHILE(session, 100); 1466 session->run(); 1467 WAIT_FOR_STATE(session, DebugSession::EndedState); 1468 1469 //check if variable is marked as out-of-scope 1470 QCOMPARE(variableCollection()->watches()->childCount(), 1); 1471 auto v = qobject_cast<LldbVariable*>(watchVariableAt(0)); 1472 QVERIFY(v); 1473 QVERIFY(!v->inScope()); 1474 QCOMPARE(v->childCount(), 3); 1475 v = qobject_cast<LldbVariable*>(v->child(0)); 1476 QVERIFY(!v->inScope()); 1477 1478 //start a second debug session 1479 session = new TestDebugSession; 1480 session->variableController()->setAutoUpdate(KDevelop::IVariableController::UpdateWatches); 1481 QVERIFY(session->startDebugging(&cfg, m_iface)); 1482 WAIT_FOR_STATE_AND_IDLE(session, DebugSession::PausedState); 1483 1484 QCOMPARE(variableCollection()->watches()->childCount(), 1); 1485 ts = variableCollection()->index(0, 0, variableCollection()->index(0, 0)); 1486 v = qobject_cast<LldbVariable*>(watchVariableAt(0)); 1487 QVERIFY(v); 1488 QVERIFY(v->inScope()); 1489 QCOMPARE(v->childCount(), 3); 1490 v = qobject_cast<LldbVariable*>(v->child(0)); 1491 QVERIFY(v->inScope()); 1492 COMPARE_DATA(variableCollection()->indexForItem(v, 1), QString::number(0)); 1493 1494 session->run(); 1495 WAIT_FOR_STATE(session, DebugSession::EndedState); 1496 1497 //check if variable is marked as out-of-scope 1498 v = qobject_cast<LldbVariable*>(watchVariableAt(0)); 1499 QVERIFY(!v->inScope()); 1500 QVERIFY(!qobject_cast<KDevelop::Variable*>(v->child(0))->inScope()); 1501 } 1502 1503 void LldbTest::testVariablesStopDebugger() 1504 { 1505 auto *session = new TestDebugSession; 1506 TestLaunchConfiguration cfg; 1507 1508 session->variableController()->setAutoUpdate(KDevelop::IVariableController::UpdateLocals); 1509 1510 breakpoints()->addCodeBreakpoint(QUrl::fromLocalFile(m_debugeeFileName), 38); 1511 QVERIFY(session->startDebugging(&cfg, m_iface)); 1512 WAIT_FOR_STATE_AND_IDLE(session, DebugSession::PausedState); 1513 1514 session->stopDebugger(); 1515 WAIT_FOR_STATE(session, DebugSession::EndedState); 1516 } 1517 1518 void LldbTest::testVariablesStartSecondSession() 1519 { 1520 auto *session = new TestDebugSession; 1521 TestLaunchConfiguration cfg; 1522 1523 session->variableController()->setAutoUpdate(KDevelop::IVariableController::UpdateLocals); 1524 1525 breakpoints()->addCodeBreakpoint(QUrl::fromLocalFile(m_debugeeFileName), 38); 1526 QVERIFY(session->startDebugging(&cfg, m_iface)); 1527 WAIT_FOR_STATE_AND_IDLE(session, DebugSession::PausedState); 1528 1529 session = new TestDebugSession; 1530 session->variableController()->setAutoUpdate(KDevelop::IVariableController::UpdateLocals); 1531 1532 breakpoints()->addCodeBreakpoint(QUrl::fromLocalFile(m_debugeeFileName), 38); 1533 QVERIFY(session->startDebugging(&cfg, m_iface)); 1534 WAIT_FOR_STATE_AND_IDLE(session, DebugSession::PausedState); 1535 1536 session->run(); 1537 WAIT_FOR_STATE(session, DebugSession::EndedState); 1538 } 1539 1540 void LldbTest::testVariablesSwitchFrame() 1541 { 1542 auto *session = new TestDebugSession; 1543 TestLaunchConfiguration cfg; 1544 1545 session->variableController()->setAutoUpdate(KDevelop::IVariableController::UpdateLocals); 1546 1547 TestFrameStackModel *stackModel = session->frameStackModel(); 1548 1549 breakpoints()->addCodeBreakpoint(QUrl::fromLocalFile(m_debugeeFileName), 24); 1550 QVERIFY(session->startDebugging(&cfg, m_iface)); 1551 WAIT_FOR_STATE_AND_IDLE(session, DebugSession::PausedState); 1552 1553 QModelIndex i = variableCollection()->index(1, 0); 1554 COMPARE_DATA(i, "Locals"); 1555 QCOMPARE(variableCollection()->rowCount(i), 1); 1556 COMPARE_DATA(variableCollection()->index(0, 0, i), "j"); // only non-static variable works 1557 COMPARE_DATA(variableCollection()->index(0, 1, i), "1"); 1558 1559 stackModel->setCurrentFrame(1); 1560 WAIT_FOR_A_WHILE(session, 200); 1561 1562 i = variableCollection()->index(1, 0); 1563 QCOMPARE(variableCollection()->rowCount(i), 4); 1564 COMPARE_DATA(variableCollection()->index(2, 0, i), "argc"); 1565 COMPARE_DATA(variableCollection()->index(2, 1, i), "1"); 1566 COMPARE_DATA(variableCollection()->index(3, 0, i), "argv"); 1567 1568 breakpoints()->removeRow(0); 1569 1570 session->run(); 1571 WAIT_FOR_STATE(session, DebugSession::EndedState); 1572 } 1573 1574 void LldbTest::testVariablesQuicklySwitchFrame() 1575 { 1576 auto *session = new TestDebugSession; 1577 TestLaunchConfiguration cfg; 1578 1579 session->variableController()->setAutoUpdate(KDevelop::IVariableController::UpdateLocals); 1580 1581 TestFrameStackModel *stackModel = session->frameStackModel(); 1582 1583 breakpoints()->addCodeBreakpoint(QUrl::fromLocalFile(m_debugeeFileName), 24); 1584 QVERIFY(session->startDebugging(&cfg, m_iface)); 1585 WAIT_FOR_STATE_AND_IDLE(session, DebugSession::PausedState); 1586 1587 QModelIndex i = variableCollection()->index(1, 0); 1588 COMPARE_DATA(i, "Locals"); 1589 QCOMPARE(variableCollection()->rowCount(i), 1); 1590 COMPARE_DATA(variableCollection()->index(0, 0, i), "j"); // only non-static variable works 1591 COMPARE_DATA(variableCollection()->index(0, 1, i), "1"); 1592 1593 stackModel->setCurrentFrame(1); 1594 WAIT_FOR_A_WHILE(session, 300); 1595 stackModel->setCurrentFrame(0); 1596 WAIT_FOR_A_WHILE(session, 1); 1597 stackModel->setCurrentFrame(1); 1598 WAIT_FOR_A_WHILE(session, 1); 1599 stackModel->setCurrentFrame(0); 1600 WAIT_FOR_A_WHILE(session, 1); 1601 stackModel->setCurrentFrame(1); 1602 WAIT_FOR_A_WHILE(session, 500); 1603 1604 i = variableCollection()->index(1, 0); 1605 QCOMPARE(variableCollection()->rowCount(i), 4); 1606 QStringList locs; 1607 for (int j = 0; j < variableCollection()->rowCount(i); ++j) { 1608 locs << variableCollection()->index(j, 0, i).data().toString(); 1609 } 1610 QVERIFY(locs.contains("argc")); 1611 QVERIFY(locs.contains("argv")); 1612 QVERIFY(locs.contains("x")); 1613 1614 breakpoints()->removeRow(0); 1615 session->run(); 1616 WAIT_FOR_STATE(session, DebugSession::EndedState); 1617 } 1618 1619 void LldbTest::testSwitchFrameLldbConsole() 1620 { 1621 auto *session = new TestDebugSession; 1622 TestLaunchConfiguration cfg; 1623 1624 TestFrameStackModel *stackModel = session->frameStackModel(); 1625 1626 breakpoints()->addCodeBreakpoint(QUrl::fromLocalFile(m_debugeeFileName), 24); 1627 QVERIFY(session->startDebugging(&cfg, m_iface)); 1628 WAIT_FOR_STATE_AND_IDLE(session, DebugSession::PausedState); 1629 1630 QCOMPARE(stackModel->currentFrame(), 0); 1631 stackModel->setCurrentFrame(1); 1632 QCOMPARE(stackModel->currentFrame(), 1); 1633 WAIT_FOR_A_WHILE(session, 500); 1634 QCOMPARE(stackModel->currentFrame(), 1); 1635 1636 session->addUserCommand(QStringLiteral("print i")); 1637 WAIT_FOR_A_WHILE(session, 500); 1638 //currentFrame must not reset to 0; Bug 222882 1639 QCOMPARE(stackModel->currentFrame(), 1); 1640 } 1641 1642 void LldbTest::testSegfaultDebugee() 1643 { 1644 auto *session = new TestDebugSession; 1645 TestLaunchConfiguration cfg(QStringLiteral("debuggee_crash")); 1646 1647 session->variableController()->setAutoUpdate(KDevelop::IVariableController::UpdateLocals); 1648 1649 QString fileName = findSourceFile("debugeecrash.cpp"); 1650 breakpoints()->addCodeBreakpoint(QUrl::fromLocalFile(fileName), 23); 1651 1652 QVERIFY(session->startDebugging(&cfg, m_iface)); 1653 1654 WAIT_FOR_STATE_AND_IDLE(session, DebugSession::PausedState); 1655 QCOMPARE(session->currentLine(), 23); 1656 session->run(); 1657 1658 WAIT_FOR_STATE_AND_IDLE(session, DebugSession::PausedState); 1659 QCOMPARE(session->currentLine(), 24); 1660 1661 session->stopDebugger(); 1662 WAIT_FOR_STATE(session, DebugSession::EndedState); 1663 } 1664 1665 //Bug 274390 1666 void LldbTest::testCommandOrderFastStepping() 1667 { 1668 auto *session = new TestDebugSession; 1669 TestLaunchConfiguration cfg(QStringLiteral("debuggee_debugeeqt")); 1670 1671 breakpoints()->addCodeBreakpoint(QStringLiteral("main")); 1672 QVERIFY(session->startDebugging(&cfg, m_iface)); 1673 for(int i=0; i<20; i++) { 1674 session->stepInto(); 1675 } 1676 WAIT_FOR_STATE_AND_IDLE(session, DebugSession::PausedState); 1677 session->run(); 1678 WAIT_FOR_STATE(session, DebugSession::EndedState); 1679 } 1680 1681 void LldbTest::testRunLldbScript() 1682 { 1683 auto *session = new TestDebugSession; 1684 1685 QTemporaryFile runScript; 1686 runScript.open(); 1687 1688 runScript.write(QStringLiteral("break set --file %1 --line 35\n").arg(findSourceFile("debugee.cpp")).toUtf8()); 1689 runScript.close(); 1690 1691 TestLaunchConfiguration cfg; 1692 KConfigGroup grp = cfg.config(); 1693 grp.writeEntry(Config::LldbConfigScriptEntry, QUrl::fromLocalFile(runScript.fileName())); 1694 1695 QVERIFY(session->startDebugging(&cfg, m_iface)); 1696 1697 WAIT_FOR_STATE_AND_IDLE(session, DebugSession::PausedState); 1698 1699 QCOMPARE(session->currentLine(), 35); 1700 1701 session->run(); 1702 WAIT_FOR_STATE(session, DebugSession::EndedState); 1703 } 1704 1705 void LldbTest::testBug301287() 1706 { 1707 auto *session = new TestDebugSession; 1708 TestLaunchConfiguration cfg; 1709 1710 session->variableController()->setAutoUpdate(KDevelop::IVariableController::UpdateWatches); 1711 1712 breakpoints()->addCodeBreakpoint(QUrl::fromLocalFile(m_debugeeFileName), 28); 1713 1714 QVERIFY(session->startDebugging(&cfg, m_iface)); 1715 WAIT_FOR_STATE_AND_IDLE(session, DebugSession::PausedState); 1716 1717 variableCollection()->watches()->add(QStringLiteral("argc")); 1718 WAIT_FOR_A_WHILE(session, 300); 1719 1720 QModelIndex i = variableCollection()->index(0, 0); 1721 QCOMPARE(variableCollection()->rowCount(i), 1); 1722 COMPARE_DATA(variableCollection()->index(0, 0, i), "argc"); 1723 COMPARE_DATA(variableCollection()->index(0, 1, i), "1"); 1724 1725 session->run(); 1726 WAIT_FOR_STATE(session, DebugSession::EndedState); 1727 1728 //start second debug session (same cfg) 1729 session = new TestDebugSession; 1730 session->variableController()->setAutoUpdate(KDevelop::IVariableController::UpdateWatches); 1731 1732 QVERIFY(session->startDebugging(&cfg, m_iface)); 1733 WAIT_FOR_STATE_AND_IDLE(session, DebugSession::PausedState); 1734 1735 i = variableCollection()->index(0, 0); 1736 QCOMPARE(variableCollection()->rowCount(i), 1); 1737 COMPARE_DATA(variableCollection()->index(0, 0, i), "argc"); 1738 COMPARE_DATA(variableCollection()->index(0, 1, i), "1"); 1739 1740 session->run(); 1741 WAIT_FOR_STATE(session, DebugSession::EndedState); 1742 } 1743 1744 void LldbTest::testDebugInExternalTerminal() 1745 { 1746 TestLaunchConfiguration cfg; 1747 1748 const QStringList consoles { "konsole", "xterm", "xfce4-terminal", "gnome-terminal" }; 1749 for (const QString& console : consoles) { 1750 1751 if (QStandardPaths::findExecutable(console).isEmpty()) { 1752 continue; 1753 } 1754 1755 auto* session = new TestDebugSession(); 1756 1757 cfg.config().writeEntry(IExecutePlugin::useTerminalEntry, true); 1758 cfg.config().writeEntry(IExecutePlugin::terminalEntry, console); 1759 1760 KDevelop::Breakpoint* b = breakpoints()->addCodeBreakpoint(QUrl::fromLocalFile(m_debugeeFileName), 28); 1761 1762 QVERIFY(session->startDebugging(&cfg, m_iface)); 1763 WAIT_FOR_STATE_AND_IDLE(session, DebugSession::PausedState); 1764 1765 QCOMPARE(b->state(), KDevelop::Breakpoint::CleanState); 1766 1767 session->stepInto(); 1768 WAIT_FOR_STATE_AND_IDLE(session, DebugSession::PausedState); 1769 1770 session->run(); 1771 WAIT_FOR_STATE(session, DebugSession::EndedState); 1772 } 1773 } 1774 1775 void LldbTest::testSpecialPath() 1776 { 1777 QSKIP("Skipping... lldb-mi itself can't handle path with space in application dir"); 1778 1779 auto* session = new TestDebugSession; 1780 1781 auto debugee = findExecutable(QStringLiteral("path with space/debuggee_spacedebugee")); 1782 TestLaunchConfiguration c(debugee, KIO::upUrl(debugee)); 1783 KDevelop::Breakpoint* b = breakpoints()->addCodeBreakpoint(QStringLiteral("spacedebugee.cpp:30")); 1784 QCOMPARE(b->state(), KDevelop::Breakpoint::NotStartedState); 1785 1786 QVERIFY(session->startDebugging(&c, m_iface)); 1787 1788 WAIT_FOR_STATE_AND_IDLE(session, DebugSession::PausedState); 1789 QCOMPARE(b->state(), KDevelop::Breakpoint::CleanState); 1790 1791 session->run(); 1792 WAIT_FOR_STATE(session, DebugSession::EndedState); 1793 } 1794 1795 void KDevMI::LLDB::LldbTest::testEnvironmentCd() 1796 { 1797 auto *session = new TestDebugSession; 1798 1799 QSignalSpy outputSpy(session, &TestDebugSession::inferiorStdoutLines); 1800 1801 auto path = KIO::upUrl(findExecutable(QStringLiteral("path with space/debuggee_spacedebugee"))); 1802 TestLaunchConfiguration cfg(QStringLiteral("debuggee_debugeepath"), path); 1803 1804 QVERIFY(session->startDebugging(&cfg, m_iface)); 1805 WAIT_FOR_STATE(session, KDevelop::IDebugSession::EndedState); 1806 1807 QVERIFY(outputSpy.count() > 0); 1808 1809 QStringList outputLines; 1810 while (outputSpy.count() > 0) { 1811 const QList<QVariant> arguments = outputSpy.takeFirst(); 1812 for (const auto &item : arguments) { 1813 outputLines.append(item.toStringList()); 1814 } 1815 } 1816 QCOMPARE(outputLines, QStringList() << path.toLocalFile()); 1817 } 1818 1819 QTEST_MAIN(KDevMI::LLDB::LldbTest) 1820 1821 #include "test_lldb.moc" 1822 #include "moc_test_lldb.cpp"