Debugger: Start making auto tests work using cmake

Change-Id: Ibe6c9bdfb52a16171e6f6acb841f185d936878f3
Reviewed-by: hjk <hjk@qt.io>
Reviewed-by: Christian Stenger <christian.stenger@qt.io>
This commit is contained in:
hjk
2020-06-12 10:55:13 +02:00
parent fb13a124c1
commit 5a7256b4bf
2 changed files with 192 additions and 54 deletions

View File

@@ -24,6 +24,8 @@ conditions by using environment variables as follows:
(QTC_CDBEXT_PATH (optional) - path to the cdbextension (QTC_CDBEXT_PATH (optional) - path to the cdbextension
defaults to IDE_BUILD_TREE/IDE_LIBRARY_BASENAME/qtcreatorcdbext64) defaults to IDE_BUILD_TREE/IDE_LIBRARY_BASENAME/qtcreatorcdbext64)
QTC_USE_CMAKE_FOR_TEST - Use cmake to build test cases (incomplete)
The tests should be used for automated testing, but can also The tests should be used for automated testing, but can also
be used for dumper development and fixing. be used for dumper development and fixing.

View File

@@ -45,6 +45,22 @@
using namespace Debugger; using namespace Debugger;
using namespace Internal; using namespace Internal;
enum class BuildSystem
{
Qmake,
CMake,
Nim
};
enum class Language
{
Cxx,
C,
ObjectiveCxx,
Nim,
Fortran90
};
#ifdef Q_CC_MSVC #ifdef Q_CC_MSVC
// Copied from msvctoolchain.cpp to avoid plugin dependency. // Copied from msvctoolchain.cpp to avoid plugin dependency.
@@ -703,6 +719,7 @@ struct NetworkProfile {};
struct QmlProfile {}; struct QmlProfile {};
struct QmlPrivateProfile {}; struct QmlPrivateProfile {};
struct SqlProfile {}; struct SqlProfile {};
struct XmlProfile {};
struct NimProfile {}; struct NimProfile {};
@@ -844,6 +861,10 @@ public:
{ {
profileExtra += "QT += core\n"; profileExtra += "QT += core\n";
cmakelistsExtra +=
"find_package(Qt5 COMPONENTS Core REQUIRED)\n"
"target_link_libraries(doit PRIVATE Qt5::Core)\n";
useQt = true; useQt = true;
useQHash = true; useQHash = true;
@@ -854,6 +875,10 @@ public:
{ {
profileExtra += "QT += core network\n"; profileExtra += "QT += core network\n";
cmakelistsExtra +=
"find_package(Qt5 COMPONENTS Core Network REQUIRED)\n"
"target_link_libraries(doit PRIVATE Qt5::Core Qt::Network)\n";
useQt = true; useQt = true;
useQHash = true; useQHash = true;
@@ -882,6 +907,10 @@ public:
"QT += gui\n" "QT += gui\n"
"greaterThan(QT_MAJOR_VERSION, 4):QT *= widgets\n"; "greaterThan(QT_MAJOR_VERSION, 4):QT *= widgets\n";
cmakelistsExtra +=
"find_package(Qt5 COMPONENTS Core Gui Widgets REQUIRED)\n"
"target_link_libraries(doit PRIVATE Qt5::Core Qt5::Gui Qt::Widgets)\n";
return *this; return *this;
} }
@@ -906,6 +935,10 @@ public:
" CONFIG += no_private_qt_headers_warning\n" " CONFIG += no_private_qt_headers_warning\n"
"}"; "}";
cmakelistsExtra +=
//"find_package(Qt5 COMPONENTS Core Gui GuiPrivate REQUIRED)\n"
"target_link_libraries(doit PRIVATE Qt5::Core Qt5::Gui Qt5::GuiPrivate)\n";
return *this; return *this;
} }
@@ -929,6 +962,23 @@ public:
" CONFIG += no_private_qt_headers_warning\n" " CONFIG += no_private_qt_headers_warning\n"
"}"; "}";
cmakelistsExtra +=
"find_package(Qt5 COMPONENTS Core Gui Qml REQUIRED)\n"
"target_link_libraries(doit PRIVATE Qt5::Core Qt5::Qml Qt5::QmlPrivate)\n";
return *this;
}
const Data &operator+(const XmlProfile &) const
{
this->operator+(CoreProfile());
profileExtra +=
" QT += xml\n";
cmakelistsExtra +=
"find_package(Qt5 COMPONENTS Core Xml REQUIRED)\n"
"target_link_libraries(doit PRIVATE Qt5::Core Qt5::Xml)\n";
return *this; return *this;
} }
@@ -941,13 +991,13 @@ public:
useQt = false; useQt = false;
useQHash = false; useQHash = false;
mainFile = "main.mm"; language = Language::ObjectiveCxx;
return *this; return *this;
} }
const Data &operator+(const ForceC &) const const Data &operator+(const ForceC &) const
{ {
mainFile = "main.c"; language = Language::C;
return *this; return *this;
} }
@@ -973,11 +1023,10 @@ public:
mutable QString allProfile; // Overrides anything below if not empty. mutable QString allProfile; // Overrides anything below if not empty.
mutable QString allCode; // Overrides anything below if not empty. mutable QString allCode; // Overrides anything below if not empty.
mutable QString mainFile = "main.cpp"; mutable Language language = Language::Cxx;
mutable QString projectFile = "doit.pro";
mutable QString dumperOptions; mutable QString dumperOptions;
mutable QString profileExtra; mutable QString profileExtra;
mutable QString cmakelistsExtra;
mutable QString includes; mutable QString includes;
mutable QString code; mutable QString code;
mutable QString unused; mutable QString unused;
@@ -1021,9 +1070,11 @@ private slots:
private: private:
void disarm() { t->buildTemp.setAutoRemove(!keepTemp()); } void disarm() { t->buildTemp.setAutoRemove(!keepTemp()); }
bool keepTemp() const { return m_keepTemp || m_forceKeepTemp; } bool keepTemp() const { return m_keepTemp || m_forceKeepTemp; }
TempStuff *t = 0; TempStuff *t = nullptr;
BuildSystem m_buildSystem = BuildSystem::Qmake;
QString m_debuggerBinary; QString m_debuggerBinary;
QString m_qmakeBinary; QString m_qmakeBinary;
QString m_cmakeBinary{"cmake"};
QProcessEnvironment m_env; QProcessEnvironment m_env;
DebuggerEngine m_debuggerEngine; DebuggerEngine m_debuggerEngine;
QString m_makeBinary; QString m_makeBinary;
@@ -1062,7 +1113,11 @@ void tst_Dumpers::initTestCase()
m_qmakeBinary = QDir::fromNativeSeparators(QString::fromLocal8Bit(qgetenv("QTC_QMAKE_PATH_FOR_TEST"))); m_qmakeBinary = QDir::fromNativeSeparators(QString::fromLocal8Bit(qgetenv("QTC_QMAKE_PATH_FOR_TEST")));
if (m_qmakeBinary.isEmpty()) if (m_qmakeBinary.isEmpty())
m_qmakeBinary = "qmake"; m_qmakeBinary = "qmake";
if (qEnvironmentVariableIntValue("QTC_USE_CMAKE_FOR_TEST"))
m_buildSystem = BuildSystem::CMake;
qDebug() << "QMake : " << m_qmakeBinary; qDebug() << "QMake : " << m_qmakeBinary;
qDebug() << "Use CMake : " << (m_buildSystem == BuildSystem::CMake) << int(m_buildSystem);
m_useGLibCxxDebug = qgetenv("QTC_USE_GLIBCXXDEBUG_FOR_TEST").toInt(); m_useGLibCxxDebug = qgetenv("QTC_USE_GLIBCXXDEBUG_FOR_TEST").toInt();
qDebug() << "Use _GLIBCXX_DEBUG : " << m_useGLibCxxDebug; qDebug() << "Use _GLIBCXX_DEBUG : " << m_useGLibCxxDebug;
@@ -1309,32 +1364,94 @@ void tst_Dumpers::dumper()
} }
} }
QFile proFile(t->buildPath + '/' + data.projectFile); QString mainFile;
QVERIFY(proFile.open(QIODevice::ReadWrite)); QByteArray cmakeLanguage;
if (data.allProfile.isEmpty()) { if (data.language == Language::C) {
proFile.write("SOURCES = "); mainFile = "main.c";
proFile.write(data.mainFile.toUtf8()); cmakeLanguage = "C";
proFile.write("\nTARGET = doit\n"); } else if (data.language == Language::ObjectiveCxx) {
proFile.write("\nCONFIG -= app_bundle\n"); mainFile = "main.mm";
proFile.write("\nmacos: CONFIG += sdk_no_version_check\n"); cmakeLanguage = "CXX";
proFile.write("\nCONFIG -= release\n"); } else if (data.language == Language::Nim) {
proFile.write("\nCONFIG += debug\n"); mainFile = "main.nim";
proFile.write("\nCONFIG += console\n"); cmakeLanguage = "CXX";
if (data.useQt) } else if (data.language == Language::Fortran90) {
proFile.write("QT -= widgets gui\n"); mainFile = "main.f90";
else cmakeLanguage = "Fortran";
proFile.write("CONFIG -= qt\n");
if (m_useGLibCxxDebug)
proFile.write("DEFINES += _GLIBCXX_DEBUG\n");
if (m_debuggerEngine == GdbEngine && m_debuggerVersion < 70500)
proFile.write("QMAKE_CXXFLAGS += -gdwarf-3\n");
proFile.write(data.profileExtra.toUtf8());
} else { } else {
proFile.write(data.allProfile.toUtf8()); mainFile = "main.cpp";
cmakeLanguage = "CXX";
} }
proFile.close();
QFile source(t->buildPath + '/' + data.mainFile); QFile projectFile;
if (m_buildSystem == BuildSystem::CMake) {
projectFile.setFileName(t->buildPath + "/CMakeLists.txt");
QVERIFY(projectFile.open(QIODevice::ReadWrite));
if (data.allProfile.isEmpty()) {
projectFile.write("cmake_minimum_required(VERSION 3.5)\n\n");
projectFile.write("project(doit LANGUAGES " + cmakeLanguage + ")\n\n");
projectFile.write("set(CMAKE_INCLUDE_CURRENT_DIR ON)\n\n");
if (data.useQt) {
projectFile.write("set(CMAKE_AUTOUIC ON)\n");
projectFile.write("set(CMAKE_AUTOMOC ON)\n");
projectFile.write("set(CMAKE_AUTORCC ON)\n");
}
projectFile.write("set(CMAKE_CXX_STANDARD 11)\n");
projectFile.write("set(CMAKE_CXX_STANDARD_REQUIRED ON)\n");
projectFile.write("add_executable(doit\n");
projectFile.write(" " + mainFile.toUtf8() + "\n");
projectFile.write(")\n\n");
//projectFile.write("target_link_libraries(doit PRIVATE Qt5::Widgets)\n");
//projectFile.write("\nmacos: CONFIG += sdk_no_version_check\n");
//projectFile.write("\nCONFIG -= release\n");
//projectFile.write("\nCONFIG += debug\n");
//projectFile.write("\nCONFIG += console\n");
//if (m_useGLibCxxDebug)
// projectFile.write("DEFINES += _GLIBCXX_DEBUG\n");
//if (m_debuggerEngine == GdbEngine && m_debuggerVersion < 70500)
// projectFile.write("QMAKE_CXXFLAGS += -gdwarf-3\n");
projectFile.write(data.cmakelistsExtra.toUtf8());
} else {
projectFile.write(data.allProfile.toUtf8());
}
projectFile.close();
} else {
projectFile.setFileName(t->buildPath + "/doit.pro");
QVERIFY(projectFile.open(QIODevice::ReadWrite));
if (data.allProfile.isEmpty()) {
projectFile.write("SOURCES = ");
projectFile.write(mainFile.toUtf8());
projectFile.write("\nTARGET = doit\n");
projectFile.write("\nCONFIG -= app_bundle\n");
projectFile.write("\nmacos: CONFIG += sdk_no_version_check\n");
projectFile.write("\nCONFIG -= release\n");
projectFile.write("\nCONFIG += debug\n");
projectFile.write("\nCONFIG += console\n");
if (data.useQt)
projectFile.write("QT -= widgets gui\n");
else
projectFile.write("CONFIG -= qt\n");
if (m_useGLibCxxDebug)
projectFile.write("DEFINES += _GLIBCXX_DEBUG\n");
if (m_debuggerEngine == GdbEngine && m_debuggerVersion < 70500)
projectFile.write("QMAKE_CXXFLAGS += -gdwarf-3\n");
projectFile.write(data.profileExtra.toUtf8());
} else {
projectFile.write(data.allProfile.toUtf8());
}
#ifdef Q_OS_WIN
projectFile.write("TARGET = ../doit\n"); // avoid handling debug / release folder
#endif
projectFile.close();
}
QFile source(t->buildPath + '/' + mainFile);
QVERIFY(source.open(QIODevice::ReadWrite)); QVERIFY(source.open(QIODevice::ReadWrite));
QString unused; QString unused;
@@ -1420,23 +1537,47 @@ void tst_Dumpers::dumper()
source.write(fullCode.toUtf8()); source.write(fullCode.toUtf8());
source.close(); source.close();
QProcess qmake; if (m_buildSystem == BuildSystem::CMake) {
qmake.setWorkingDirectory(t->buildPath); QProcess cmake;
//qDebug() << "Starting qmake: " << m_qmakeBinary; cmake.setWorkingDirectory(t->buildPath);
QStringList options; QDir dir = QFileInfo(m_qmakeBinary).dir(); // {Qt:QT_INSTALL_PREFIX}
#ifdef Q_OS_MAC dir.cdUp();
if (m_qtVersion && m_qtVersion < 0x050000) QStringList options = {
options << "-spec" << "unsupported/macx-clang"; "-DCMAKE_BUILD_TYPE=Debug",
#endif "-DCMAKE_PREFIX_PATH=" + dir.absolutePath(),
qmake.start(m_qmakeBinary, options); "."
QVERIFY(qmake.waitForFinished()); };
output = qmake.readAllStandardOutput(); //qDebug() << "Starting cmake: " << m_cmakeBinary << ' ' << qPrintable(options.join(' '));
error = qmake.readAllStandardError(); cmake.start(m_cmakeBinary, options);
//qDebug() << "stdout: " << output; QVERIFY(cmake.waitForFinished());
output = cmake.readAllStandardOutput();
error = cmake.readAllStandardError();
//qDebug() << "stdout: " << output;
if (data.allProfile.isEmpty()) { // Nim... if (data.allProfile.isEmpty()) { // Nim...
if (!error.isEmpty()) { if (!error.isEmpty()) {
qDebug() << error; QVERIFY(false); qDebug() << error; QVERIFY(false);
}
}
} else {
QProcess qmake;
qmake.setWorkingDirectory(t->buildPath);
//qDebug() << "Starting qmake: " << m_qmakeBinary;
QStringList options;
#ifdef Q_OS_MACOS
if (m_qtVersion && m_qtVersion < 0x050000)
options << "-spec" << "unsupported/macx-clang";
#endif
qmake.start(m_qmakeBinary, options);
QVERIFY(qmake.waitForFinished());
output = qmake.readAllStandardOutput();
error = qmake.readAllStandardError();
//qDebug() << "stdout: " << output;
if (data.allProfile.isEmpty()) { // Nim...
if (!error.isEmpty()) {
qDebug() << error; QVERIFY(false);
}
} }
} }
@@ -1454,7 +1595,7 @@ void tst_Dumpers::dumper()
qDebug() << "\n------------------ CODE --------------------"; qDebug() << "\n------------------ CODE --------------------";
qDebug().noquote() << fullCode; qDebug().noquote() << fullCode;
qDebug() << "\n------------------ CODE --------------------"; qDebug() << "\n------------------ CODE --------------------";
qDebug().noquote() << "Project file: " << proFile.fileName(); qDebug().noquote() << "Project file: " << projectFile.fileName();
QCOMPARE(make.exitCode(), 0); QCOMPARE(make.exitCode(), 0);
} }
@@ -1527,11 +1668,7 @@ void tst_Dumpers::dumper()
QByteArray nograb = "-nograb"; QByteArray nograb = "-nograb";
cmds = "set confirm off\n" cmds = "set confirm off\n"
#ifdef Q_OS_WIN
"file debug/doit\n"
#else
"file doit\n" "file doit\n"
#endif
"set auto-load python-scripts off\n"; "set auto-load python-scripts off\n";
cmds += "python sys.path.insert(1, '" + dumperDir + "')\n" cmds += "python sys.path.insert(1, '" + dumperDir + "')\n"
@@ -1555,7 +1692,7 @@ void tst_Dumpers::dumper()
<< "0x4000001f" << "0x4000001f"
<< "-c" << "-c"
<< "bm doit!qtcDebugBreakFunction;g" << "bm doit!qtcDebugBreakFunction;g"
<< "debug\\doit.exe"; << "doit.exe";
cmds += ".symopt+0x8000\n" cmds += ".symopt+0x8000\n"
"!qtcreatorcdbext.script sys.path.insert(1, '" + dumperDir + "')\n" "!qtcreatorcdbext.script sys.path.insert(1, '" + dumperDir + "')\n"
"!qtcreatorcdbext.script from cdbbridge import *\n" "!qtcreatorcdbext.script from cdbbridge import *\n"
@@ -4275,8 +4412,7 @@ void tst_Dumpers::dumper_data()
"atts.append(\"name3\", \"uri3\", \"localPart3\", \"value3\");", "atts.append(\"name3\", \"uri3\", \"localPart3\", \"value3\");",
"&atts") "&atts")
+ CoreProfile() + XmlProfile()
+ Profile("QT += xml\n")
+ Check("atts", "<3 items>", "@QXmlAttributes") + Check("atts", "<3 items>", "@QXmlAttributes")
+ Check("atts.0", "[0]", "", "@QXmlAttributes::Attribute") + Check("atts.0", "[0]", "", "@QXmlAttributes::Attribute")
@@ -7827,7 +7963,7 @@ void tst_Dumpers::dumper_data()
" i8 = i8 / 0\n" " i8 = i8 / 0\n"
"end program\n"; "end program\n";
f90data.mainFile = "main.f90"; f90data.language = Language::Fortran90;
QTest::newRow("F90") QTest::newRow("F90")
<< f90data << f90data