| 1540 | } |
| 1541 | |
| 1542 | void DebuggerTestBase::testCoreFile() |
| 1543 | { |
| 1544 | QFETCH(const FileKind, executableFileKind); |
| 1545 | QFETCH(const FileKind, coreFileKind); |
| 1546 | |
| 1547 | const auto findDebuggeeExecutable = [] { |
| 1548 | return findExecutable("debuggee_crash"); |
| 1549 | }; |
| 1550 | const auto generateCoreFile = [this] { |
| 1551 | // If a core file was just generated for another data row, it is up-to-date and can be reused. |
| 1552 | // Otherwise, generate a new core file in place of a possibly incompatible existing one. |
| 1553 | const auto reuseExisting = m_generatedCoreFile; |
| 1554 | const auto fileName = ::generateCoreFile(reuseExisting); |
| 1555 | m_generatedCoreFile = !fileName.isEmpty(); |
| 1556 | return QUrl::fromLocalFile(fileName); |
| 1557 | }; |
| 1558 | |
| 1559 | const auto executable = urlForFileKind(executableFileKind, findDebuggeeExecutable); |
| 1560 | RETURN_IF_TEST_RESOLVED(); |
| 1561 | const auto core = urlForFileKind(coreFileKind, generateCoreFile); |
| 1562 | RETURN_IF_TEST_RESOLVED(); |
| 1563 | |
| 1564 | auto* const session = createTestDebugSession(); |
| 1565 | VERIFY_INVALID_CURRENT_LOCATION(session); |
| 1566 | QVERIFY(session->examineCoreFile(executable, core)); |
| 1567 | |
| 1568 | const auto isExecutableAcceptable = isAcceptableExecutableFileKindForCore(executableFileKind); |
| 1569 | if (isExecutableAcceptable && coreFileKind == acceptableCoreFileKind) { |
| 1570 | const auto* const stackModel = session->frameStackModel(); |
| 1571 | |
| 1572 | WAIT_FOR_STATE(session, IDebugSession::StoppedState); |
| 1573 | |
| 1574 | const auto missingCurrentLocation = |
| 1575 | executableFileKind == FileKind::EmptyName && !isLldb() && session->currentUrl().isEmpty(); |
| 1576 | if (missingCurrentLocation) { |
| 1577 | // No idea why one day GDB loads the current location from the core file, then 10 days later it does not... |
| 1578 | qWarning() << "GDB failed to load current location from the core file"; |
| 1579 | } else { |
| 1580 | VERIFY_VALID_CURRENT_LOCATION(session, QUrl::fromLocalFile(findSourceFile("debugeecrash.cpp")), 25); |
| 1581 | } |
| 1582 | |
| 1583 | const auto threadIndex = stackModel->index(0, 0); |
| 1584 | VALIDATE_COLUMN_COUNTS_THREAD_COUNT_AND_STACK_FRAME_NUMBERS(threadIndex, 1); |
| 1585 | if (!missingCurrentLocation) { |
| 1586 | COMPARE_DATA(threadIndex, adjustedStackModelFrameName("#1 at foo")); |
| 1587 | } |
| 1588 | |
| 1589 | session->stopDebugger(); |
| 1590 | } else if (isExecutableAcceptable && coreFileKind == FileKind::EmptyName && !isLldb()) { |
| 1591 | // If the core filename is empty, KDevelop sends a non-MI command `core` without argument, GDB |
| 1592 | // outputs a message "No core file now." and replies with "done". Consequently, the debug session |
| 1593 | // is stuck in the starting state instead of ending with an error. This is not a problem in |
| 1594 | // practice, because the Select Core File dialog cannot be accepted if the core filename is empty. |
| 1595 | WAIT_FOR_A_WHILE(session, 1000); |
| 1596 | QEXPECT_FAIL("", "Debug session is stuck in the starting state", Continue); |
| 1597 | QCOMPARE(session->state(), IDebugSession::EndedState); |
| 1598 | QCOMPARE(session->state(), IDebugSession::StartingState); |
| 1599 | session->stopDebugger(); |
nothing calls this directly
no test coverage detected