diff options
Diffstat (limited to 'tests')
176 files changed, 8008 insertions, 1530 deletions
diff --git a/tests/auto/algorithm/tst_algorithm.cpp b/tests/auto/algorithm/tst_algorithm.cpp index 614cf3fa12..47e05b4636 100644 --- a/tests/auto/algorithm/tst_algorithm.cpp +++ b/tests/auto/algorithm/tst_algorithm.cpp @@ -42,6 +42,16 @@ int stringToInt(const QString &s) return s.toInt(); } +namespace { +struct Struct +{ + Struct(int m) : member(m) {} + bool operator==(const Struct &other) const { return member == other.member; } + + int member; +}; +} + void tst_Algorithm::transform() { // same container type @@ -110,16 +120,11 @@ void tst_Algorithm::transform() Utils::sort(i3); QCOMPARE(i3, QList<int>({1, 1, 3})); } -} - -namespace { -struct Struct -{ - Struct(int m) : member(m) {} - bool operator==(const Struct &other) const { return member == other.member; } - - int member; -}; + { + const QList<Struct> list({4, 3, 2, 1, 2}); + const QList<int> trans = Utils::transform(list, &Struct::member); + QCOMPARE(trans, QList<int>({4, 3, 2, 1, 2})); + } } void tst_Algorithm::sort() diff --git a/tests/auto/clangstaticanalyzer/clangstaticanalyzerautotest.qbs b/tests/auto/clangstaticanalyzer/clangstaticanalyzerautotest.qbs index 7ae782956f..5ec34efb84 100644 --- a/tests/auto/clangstaticanalyzer/clangstaticanalyzerautotest.qbs +++ b/tests/auto/clangstaticanalyzer/clangstaticanalyzerautotest.qbs @@ -6,6 +6,5 @@ QtcAutotest { Depends { name: "Utils" } property path pluginDir: project.ide_source_tree + "/src/plugins/clangstaticanalyzer" - cpp.defines: base.concat('SRCDIR="' + sourceDirectory + '"') cpp.includePaths: base.concat(pluginDir + "/..") } diff --git a/tests/auto/clangstaticanalyzer/clangstaticanalyzerlogfilereader/clangstaticanalyzerlogfilereader.qbs b/tests/auto/clangstaticanalyzer/clangstaticanalyzerlogfilereader/clangstaticanalyzerlogfilereader.qbs index a1ac819f5f..5fc992aa06 100644 --- a/tests/auto/clangstaticanalyzer/clangstaticanalyzerlogfilereader/clangstaticanalyzerlogfilereader.qbs +++ b/tests/auto/clangstaticanalyzer/clangstaticanalyzerlogfilereader/clangstaticanalyzerlogfilereader.qbs @@ -3,6 +3,7 @@ import "../clangstaticanalyzerautotest.qbs" as ClangStaticAnalyzerAutotest ClangStaticAnalyzerAutotest { name: "ClangStaticAnalyzerLogFileReader Autotest" + cpp.defines: base.concat('SRCDIR="' + sourceDirectory + '"') Group { name: "sources from plugin" diff --git a/tests/auto/clangstaticanalyzer/clangstaticanalyzerrunner/clangstaticanalyzerrunner.pro b/tests/auto/clangstaticanalyzer/clangstaticanalyzerrunner/clangstaticanalyzerrunner.pro index 1331b22103..7893e8761a 100644 --- a/tests/auto/clangstaticanalyzer/clangstaticanalyzerrunner/clangstaticanalyzerrunner.pro +++ b/tests/auto/clangstaticanalyzer/clangstaticanalyzerrunner/clangstaticanalyzerrunner.pro @@ -2,8 +2,6 @@ include(../clangstaticanalyzertest.pri) TARGET = tst_clangstaticanalyzerrunnertest -DEFINES += SRCDIR=\\\"$$PWD/\\\" - SOURCES += \ tst_clangstaticanalyzerrunner.cpp \ $$PLUGINDIR/clangstaticanalyzerrunner.cpp diff --git a/tests/auto/clangstaticanalyzer/clangstaticanalyzerrunner/tst_clangstaticanalyzerrunner.cpp b/tests/auto/clangstaticanalyzer/clangstaticanalyzerrunner/tst_clangstaticanalyzerrunner.cpp index 76aa68e30d..9c71b800ec 100644 --- a/tests/auto/clangstaticanalyzer/clangstaticanalyzerrunner/tst_clangstaticanalyzerrunner.cpp +++ b/tests/auto/clangstaticanalyzer/clangstaticanalyzerrunner/tst_clangstaticanalyzerrunner.cpp @@ -27,6 +27,7 @@ #include <clangstaticanalyzer/clangstaticanalyzerrunner.h> #include <utils/hostosinfo.h> +#include <utils/temporarydirectory.h> #include <QtTest> @@ -168,8 +169,7 @@ void ClangStaticAnalyzerRunnerTest::runWithTestCodeGeneratedOneIssue() "}\n"; QVERIFY(writeFile(testFilePath, source)); - QTemporaryDir temporaryDir(QDir::tempPath() + QLatin1String("/qtc-clangstaticanalyzer-XXXXXX")); - QVERIFY(temporaryDir.isValid()); + Utils::TemporaryDirectory temporaryDir("runWithTestCodeGeneratedOneIssue"); ClangStaticAnalyzerRunner runner(m_clangExecutable, temporaryDir.path(), Utils::Environment::systemEnvironment()); @@ -185,8 +185,7 @@ void ClangStaticAnalyzerRunnerTest::runWithNonExistentFileToAnalyze() if (m_clangExecutable.isEmpty()) QSKIP("Clang executable in PATH required."); - QTemporaryDir temporaryDir(QDir::tempPath() + QLatin1String("/qtc-clangstaticanalyzer-XXXXXX")); - QVERIFY(temporaryDir.isValid()); + Utils::TemporaryDirectory temporaryDir("runWithNonExistentFileToAnalyze"); ClangStaticAnalyzerRunner runner(m_clangExecutable, temporaryDir.path(), Utils::Environment::systemEnvironment()); @@ -197,6 +196,14 @@ void ClangStaticAnalyzerRunnerTest::runWithNonExistentFileToAnalyze() QVERIFY(st.expectFinishWithFailureSignal(finishedWithBadExitCode(1))); } -QTEST_MAIN(ClangStaticAnalyzerRunnerTest) +int main(int argc, char *argv[]) +{ + Utils::TemporaryDirectory::setMasterTemporaryDirectory( + QDir::tempPath() + "/qtc-clangstaticanalyzer-test-XXXXXX"); + + QCoreApplication app(argc, argv); + ClangStaticAnalyzerRunnerTest test; + return QTest::qExec(&test, argc, argv); +} #include "tst_clangstaticanalyzerrunner.moc" diff --git a/tests/auto/cplusplus/c99/tst_c99.cpp b/tests/auto/cplusplus/c99/tst_c99.cpp index 1321b6e045..df33671907 100644 --- a/tests/auto/cplusplus/c99/tst_c99.cpp +++ b/tests/auto/cplusplus/c99/tst_c99.cpp @@ -81,7 +81,7 @@ class tst_c99: public QObject if (! errors) return; - static const char *const pretty[] = { "warning", "error", "fatal" }; + static const char *const pretty[] = {"warning", "error", "fatal"}; QString str; str.sprintf("%s:%d:%d: %s: ", fileName->chars(), line, column, pretty[level]); diff --git a/tests/auto/cplusplus/cxx11/tst_cxx11.cpp b/tests/auto/cplusplus/cxx11/tst_cxx11.cpp index ef81d41235..a39f367473 100644 --- a/tests/auto/cplusplus/cxx11/tst_cxx11.cpp +++ b/tests/auto/cplusplus/cxx11/tst_cxx11.cpp @@ -83,7 +83,7 @@ class tst_cxx11: public QObject if (! errors) return; - static const char *const pretty[] = { "warning", "error", "fatal" }; + static const char *const pretty[] = {"warning", "error", "fatal"}; QString str; str.sprintf("%s:%d:%d: %s: ", fileName->chars(), line, column, pretty[level]); diff --git a/tests/auto/cplusplus/misc/tst_misc.cpp b/tests/auto/cplusplus/misc/tst_misc.cpp index 984245c96b..aff5a12ce0 100644 --- a/tests/auto/cplusplus/misc/tst_misc.cpp +++ b/tests/auto/cplusplus/misc/tst_misc.cpp @@ -233,7 +233,7 @@ void tst_Misc::astPathOnGeneratedTokens() QVERIFY(paths.at(4)->asSimpleName()); // Check end - for (auto i : { 7, 8, 9 }) { + for (auto i : {7, 8, 9}) { paths = astPath(3, i); QCOMPARE(paths.size(), 2); QVERIFY(paths.at(0)->asTranslationUnit()); diff --git a/tests/auto/cplusplus/semantic/tst_semantic.cpp b/tests/auto/cplusplus/semantic/tst_semantic.cpp index bfa85b38a3..3904558efc 100644 --- a/tests/auto/cplusplus/semantic/tst_semantic.cpp +++ b/tests/auto/cplusplus/semantic/tst_semantic.cpp @@ -612,7 +612,7 @@ void tst_Semantic::template_instance_1() Declaration *decl = templ->memberAt(1)->asClass()->memberAt(0)->asDeclaration(); QVERIFY(decl); - FullySpecifiedType templArgs[] = { control->integerType(IntegerType::Int) }; + FullySpecifiedType templArgs[] = {control->integerType(IntegerType::Int)}; const Name *templId = control->templateNameId(control->identifier("QList"), false, templArgs, 1); FullySpecifiedType genTy = DeprecatedGenTemplateInstance::instantiate(templId, decl, control); diff --git a/tests/auto/debugger/README.txt b/tests/auto/debugger/README.txt index 13396b9bb7..e3b550e8cc 100644 --- a/tests/auto/debugger/README.txt +++ b/tests/auto/debugger/README.txt @@ -21,6 +21,8 @@ conditions by using environment variables as follows: paths installed or if a non-standard path has been used (QTC_MSVC_ENV_BAT - to set up MSVC) + (QTC_CDBEXT_PATH (optional) - path to the cdbextension + defaults to IDE_BUILD_TREE/IDE_LIBRARY_BASENAME/qtcreatorcdbext64) The tests should be used for automated testing, but can also be used for dumper development and fixing. diff --git a/tests/auto/debugger/disassembler.pro b/tests/auto/debugger/disassembler.pro index c42b8e047d..2a145964ea 100644 --- a/tests/auto/debugger/disassembler.pro +++ b/tests/auto/debugger/disassembler.pro @@ -1,4 +1,3 @@ -QTC_LIB_DEPENDS += utils QT = core network widgets include(../qttest.pri) diff --git a/tests/auto/debugger/disassembler.qbs b/tests/auto/debugger/disassembler.qbs index 35a5aadd59..4d23156527 100644 --- a/tests/auto/debugger/disassembler.qbs +++ b/tests/auto/debugger/disassembler.qbs @@ -2,8 +2,6 @@ import qbs QtcAutotest { name: "disassembler autotest" - Depends { name: "ProjectExplorer" } - Depends { name: "QtcSsh" } Group { name: "Sources from Debugger plugin" prefix: project.debuggerDir diff --git a/tests/auto/debugger/dumpers.pro b/tests/auto/debugger/dumpers.pro index 6385f42bbd..0eec400a89 100644 --- a/tests/auto/debugger/dumpers.pro +++ b/tests/auto/debugger/dumpers.pro @@ -1,16 +1,30 @@ QT = core network -QTC_LIB_DEPENDS += utils +msvc: QTC_LIB_DEPENDS += utils include(../qttest.pri) msvc { + LIBS *= -L$$IDE_PLUGIN_PATH DEFINES += Q_PLUGIN_PATH=\"\\\"$$IDE_PLUGIN_PATH\\\"\" CDBEXT_PATH = $$IDE_BUILD_TREE\\$$IDE_LIBRARY_BASENAME # replace '\' with '\\' DEFINES += CDBEXT_PATH=\"\\\"$$replace(CDBEXT_PATH, \\\\, \\\\)\\\"\" + +} else { + + SOURCES += \ + $$IDE_SOURCE_TREE/src/libs/utils/treemodel.cpp \ + $$IDE_SOURCE_TREE/src/libs/utils/qtcassert.cpp \ + $$IDE_SOURCE_TREE/src/libs/utils/processhandle.cpp + + HEADERS += \ + $$IDE_SOURCE_TREE/src/libs/utils/treemodel.h \ + $$IDE_SOURCE_TREE/src/libs/utils/qtcassert.h \ + $$IDE_SOURCE_TREE/src/libs/utils/processhandle.h + } DEBUGGERDIR = $$IDE_SOURCE_TREE/src/plugins/debugger diff --git a/tests/auto/debugger/gdb.pro b/tests/auto/debugger/gdb.pro index 9cd6e1c475..5b1b3627bf 100644 --- a/tests/auto/debugger/gdb.pro +++ b/tests/auto/debugger/gdb.pro @@ -1,12 +1,13 @@ -QTC_LIB_DEPENDS += utils QT = core network include(../qttest.pri) DEBUGGERDIR = $$IDE_SOURCE_TREE/src/plugins/debugger +UTILSDIR = $$IDE_SOURCE_TREE/src/libs/utils INCLUDEPATH += $$DEBUGGERDIR SOURCES += \ tst_gdb.cpp \ $$DEBUGGERDIR/debuggerprotocol.cpp \ + $$UTILSDIR/processhandle.cpp diff --git a/tests/auto/debugger/gdb.qbs b/tests/auto/debugger/gdb.qbs index b7ea870325..6618bd59dd 100644 --- a/tests/auto/debugger/gdb.qbs +++ b/tests/auto/debugger/gdb.qbs @@ -2,6 +2,7 @@ import qbs QtcAutotest { name: "gdb autotest" + Depends { name: "Utils" } Depends { name: "Qt.network" } // For QHostAddress Group { name: "Sources from Debugger plugin" diff --git a/tests/auto/debugger/namedemangler.pro b/tests/auto/debugger/namedemangler.pro index ec021e6eb8..241e1e2759 100644 --- a/tests/auto/debugger/namedemangler.pro +++ b/tests/auto/debugger/namedemangler.pro @@ -1,4 +1,3 @@ -QTC_LIB_DEPENDS += utils QT -= gui include(../qttest.pri) diff --git a/tests/auto/debugger/simplifytypes.pro b/tests/auto/debugger/simplifytypes.pro index df645f1513..7e15fecad3 100644 --- a/tests/auto/debugger/simplifytypes.pro +++ b/tests/auto/debugger/simplifytypes.pro @@ -1,4 +1,3 @@ -QTC_LIB_DEPENDS += utils include(../qttest.pri) QT += network QT -= gui widgets diff --git a/tests/auto/debugger/tst_dumpers.cpp b/tests/auto/debugger/tst_dumpers.cpp index 919a58ce0e..00d2bc05f4 100644 --- a/tests/auto/debugger/tst_dumpers.cpp +++ b/tests/auto/debugger/tst_dumpers.cpp @@ -143,28 +143,8 @@ static bool generateEnvironmentSettings(Utils::Environment &env, #define CDBEXT_PATH "" #endif -static void setupCdb(QString *makeBinary, QProcessEnvironment *environment) -{ - QByteArray envBat = qgetenv("QTC_MSVC_ENV_BAT"); - QMap <QString, QString> envPairs; - Utils::Environment env = Utils::Environment::systemEnvironment(); - QVERIFY(generateEnvironmentSettings(env, QString::fromLatin1(envBat), QString(), envPairs)); - for (QMap<QString,QString>::const_iterator envIt = envPairs.begin(); envIt != envPairs.end(); ++envIt) - env.set(envIt.key(), envIt.value()); - const QByteArray cdbextPath = CDBEXT_PATH "\\qtcreatorcdbext64"; - QVERIFY(QFile::exists(QString::fromLatin1(cdbextPath + QByteArray("\\qtcreatorcdbext.dll")))); - env.set(QLatin1String("_NT_DEBUGGER_EXTENSION_PATH"), QString::fromLatin1(cdbextPath)); - *makeBinary = env.searchInPath(QLatin1String("nmake.exe")).toString(); - *environment = env.toProcessEnvironment(); -} - -#else - -static void setupCdb(QString *, QProcessEnvironment *) {} - #endif // Q_CC_MSVC - struct VersionBase { // Minimum and maximum are inclusive. @@ -213,6 +193,13 @@ struct ClangVersion : VersionBase {} }; +struct MsvcVersion : VersionBase +{ + explicit MsvcVersion(int minimum = 0, int maximum = INT_MAX) + : VersionBase(minimum, maximum) + {} +}; + struct GdbVersion : VersionBase { explicit GdbVersion(int minimum = 0, int maximum = INT_MAX) @@ -236,13 +223,31 @@ struct BoostVersion : VersionBase static QString noValue = "\001"; +enum DebuggerEngine +{ + NoEngine = 0x00, + + GdbEngine = 0x01, + CdbEngine = 0x02, + LldbEngine = 0x04, + + AllEngines = GdbEngine | CdbEngine | LldbEngine, + + NoCdbEngine = AllEngines & (~CdbEngine), + NoLldbEngine = AllEngines & (~LldbEngine), + NoGdbEngine = AllEngines & (~GdbEngine) +}; + struct Context { + Context(DebuggerEngine engine) : engine(engine) {} QString nameSpace; int qtVersion = 0; int gccVersion = 0; int clangVersion = 0; + int msvcVersion = 0; int boostVersion = 0; + DebuggerEngine engine; }; struct Name @@ -400,7 +405,11 @@ struct Type QString actualType = simplifyType(actualType0); actualType.replace(' ', ""); actualType.replace("const", ""); - QString expectedType = type; + QString expectedType; + if (aliasName.isEmpty() || context.engine == CdbEngine) + expectedType = type; + else + expectedType = aliasName; expectedType.replace(' ', ""); expectedType.replace("const", ""); expectedType.replace('@', context.nameSpace); @@ -427,6 +436,7 @@ struct Type } QString type; + QString aliasName; int qtVersion = 0; bool isPattern = false; }; @@ -446,17 +456,21 @@ struct TypePattern : Type TypePattern(const QString &ba) : Type(ba) { isPattern = true; } }; -enum DebuggerEngine +struct TypeDef : Type { - GdbEngine = 0x01, - CdbEngine = 0x02, - LldbEngine = 0x04, + TypeDef(const QString &typeName, const QString &aliasName) : Type(typeName) + { + this->aliasName = aliasName; + } +}; - AllEngines = GdbEngine | CdbEngine | LldbEngine, +struct RequiredMessage +{ + RequiredMessage() {} - NoCdbEngine = AllEngines & (~CdbEngine), - NoLldbEngine = AllEngines & (~LldbEngine), - NoGdbEngine = AllEngines & (~GdbEngine) + RequiredMessage(const QString &message) : message(message) {} + + QString message; }; struct Check @@ -480,6 +494,7 @@ struct Check && debuggerVersionForCheck.covers(debuggerVersion) && gccVersionForCheck.covers(context.gccVersion) && clangVersionForCheck.covers(context.clangVersion) + && msvcVersionForCheck.covers(context.msvcVersion) && qtVersionForCheck.covers(context.qtVersion); } @@ -523,6 +538,13 @@ struct Check return *this; } + const Check &operator%(MsvcVersion version) const + { + enginesForCheck = CdbEngine; + msvcVersionForCheck = version; + return *this; + } + const Check &operator%(BoostVersion version) const { boostVersionForCheck = version; @@ -544,6 +566,7 @@ struct Check mutable VersionBase debuggerVersionForCheck; mutable VersionBase gccVersionForCheck; mutable VersionBase clangVersionForCheck; + mutable VersionBase msvcVersionForCheck; mutable QtVersion qtVersionForCheck; mutable BoostVersion boostVersionForCheck; mutable bool optionallyPresent = false; @@ -610,6 +633,9 @@ struct BoostProfile : public Profile contents = QByteArray("INCLUDEPATH += ") + boostIncPath.constData(); else contents = "macx:INCLUDEPATH += /usr/local/include"; + const QByteArray &boostLibPath = qgetenv("QTC_BOOST_LIBRARY_PATH_FOR_TEST"); + if (!boostLibPath.isEmpty()) + contents += QByteArray("\nLIBS += \"-L") + boostLibPath.constData() + QByteArray("\""); includes = "#include <boost/version.hpp>\n"; } }; @@ -646,6 +672,7 @@ struct GuiPrivateProfile {}; struct NetworkProfile {}; struct QmlProfile {}; struct QmlPrivateProfile {}; +struct SqlProfile {}; struct NimProfile {}; @@ -655,7 +682,6 @@ class Data { public: Data() {} - Data(const QString &code) : code(code) {} Data(const QString &includes, const QString &code) : includes(includes), code(code) @@ -667,6 +693,12 @@ public: return *this; } + const Data &operator+(const RequiredMessage &check) const + { + requiredMessages.append(check); + return *this; + } + const Data &operator+(const Profile &profile) const { profileExtra += profile.contents; @@ -692,6 +724,12 @@ public: return *this; } + const Data &operator+(const MsvcVersion &msvcVersion) const + { + neededMsvcVersion = msvcVersion; + return *this; + } + const Data &operator+(const GdbVersion &gdbVersion) const { neededGdbVersion = gdbVersion; @@ -762,9 +800,7 @@ public: const Data &operator+(const CoreProfile &) const { - profileExtra += - "CONFIG += QT\n" - "QT += core\n"; + profileExtra += "QT += core\n"; useQt = true; useQHash = true; @@ -774,9 +810,7 @@ public: const Data &operator+(const NetworkProfile &) const { - profileExtra += - "CONFIG += QT\n" - "QT += core network\n"; + profileExtra += "QT += core network\n"; useQt = true; useQHash = true; @@ -784,6 +818,15 @@ public: return *this; } + const Data &operator+(const SqlProfile &) const + { + profileExtra += "QT += core sql\n"; + + useQt = true; + + return *this; + } + const Data &operator+(const BigArrayProfile &) const { this->bigArray = true; @@ -826,6 +869,7 @@ public: const Data &operator+(const QmlProfile &) const { + this->operator+(CoreProfile()); profileExtra += "greaterThan(QT_MAJOR_VERSION, 4) {\n" " QT += qml\n" @@ -865,6 +909,7 @@ public: mutable QtVersion neededQtVersion; // HEX! 0x50300 mutable GccVersion neededGccVersion; // DEC. 40702 for 4.7.2 mutable ClangVersion neededClangVersion; // DEC. + mutable MsvcVersion neededMsvcVersion; // DEC. mutable BoostVersion neededBoostVersion; // DEC. 105400 for 1.54.0 mutable DwarfVersion neededDwarfVersion; // DEC. 105400 for 1.54.0 @@ -881,6 +926,7 @@ public: mutable QString code; mutable QList<Check> checks; + mutable QList<RequiredMessage> requiredMessages; }; struct TempStuff @@ -930,6 +976,7 @@ private: int m_gdbBuildVersion = 0; int m_qtVersion = 0; // 5.2.0 -> 50200 int m_gccVersion = 0; + int m_msvcVersion = 0; bool m_isMacGdb = false; bool m_isQnxGdb = false; bool m_useGLibCxxDebug = false; @@ -1008,7 +1055,35 @@ void tst_Dumpers::initTestCase() qDebug() << "Make path : " << m_makeBinary; qDebug() << "Gdb version : " << m_debuggerVersion; } else if (m_debuggerEngine == CdbEngine) { - setupCdb(&m_makeBinary, &m_env); +#ifdef Q_CC_MSVC + QByteArray envBat = qgetenv("QTC_MSVC_ENV_BAT"); + QMap <QString, QString> envPairs; + Utils::Environment env = Utils::Environment::systemEnvironment(); + QVERIFY(generateEnvironmentSettings(env, QString::fromLatin1(envBat), QString(), envPairs)); + for (auto envIt = envPairs.begin(); envIt != envPairs.end(); ++envIt) + env.set(envIt.key(), envIt.value()); + QByteArray cdbextPath = qgetenv("QTC_CDBEXT_PATH"); + if (cdbextPath.isEmpty()) + cdbextPath = CDBEXT_PATH "\\qtcreatorcdbext64"; + QVERIFY(QFile::exists(QString::fromLatin1(cdbextPath + QByteArray("\\qtcreatorcdbext.dll")))); + env.set(QLatin1String("_NT_DEBUGGER_EXTENSION_PATH"), QString::fromLatin1(cdbextPath)); + env.prependOrSetPath(QDir::toNativeSeparators(QFileInfo(m_qmakeBinary).absolutePath())); + m_makeBinary = env.searchInPath(QLatin1String("nmake.exe")).toString(); + m_env = env.toProcessEnvironment(); + + QProcess cl; + cl.start(env.searchInPath(QLatin1String("cl.exe")).toString(), QStringList()); + QVERIFY(cl.waitForFinished()); + QString output = cl.readAllStandardError(); + int pos = output.indexOf('\n'); + if (pos != -1) + output = output.left(pos); + qDebug() << "Extracting MSVC version from: " << output; + QRegularExpression reg(" (\\d\\d)\\.(\\d\\d)\\."); + QRegularExpressionMatch match = reg.match(output); + if (match.matchType() != QRegularExpression::NoMatch) + m_msvcVersion = QString(match.captured(1) + match.captured(2)).toInt(); +#endif //Q_CC_MSVC } else if (m_debuggerEngine == LldbEngine) { qDebug() << "Dumper dir : " << DUMPERDIR; QProcess debugger; @@ -1156,6 +1231,15 @@ void tst_Dumpers::dumper() + QByteArray::number(data.neededGccVersion.max)); } + if (data.neededMsvcVersion.isRestricted && m_debuggerEngine == CdbEngine) { + if (data.neededMsvcVersion.min > m_msvcVersion) + MSKIP_SINGLE("Need minimum Msvc version " + + QByteArray::number(data.neededMsvcVersion.min)); + if (data.neededMsvcVersion.max < m_msvcVersion) + MSKIP_SINGLE("Need maximum Msvc version " + + QByteArray::number(data.neededMsvcVersion.max)); + } + if (!data.configTest.isEmpty()) { QProcess configTest; configTest.start(data.configTest); @@ -1177,10 +1261,11 @@ void tst_Dumpers::dumper() proFile.write("\nCONFIG -= app_bundle\n"); proFile.write("\nCONFIG -= release\n"); proFile.write("\nCONFIG += debug\n"); + proFile.write("\nCONFIG += console\n"); if (data.useQt) proFile.write("QT -= widgets gui\n"); else - proFile.write("CONFIG -= QT\n"); + proFile.write("CONFIG -= qt\n"); if (m_useGLibCxxDebug) proFile.write("DEFINES += _GLIBCXX_DEBUG\n"); if (m_debuggerEngine == GdbEngine && m_debuggerVersion < 70500) @@ -1196,7 +1281,7 @@ void tst_Dumpers::dumper() QString fullCode = QString() + "\n\n#if defined(_MSC_VER)" + (data.useQt ? "\n#include <qt_windows.h>" : - "\n#include <Windows.h>") + + "\n#define NOMINMAX\n#include <Windows.h>") + "\n#define BREAK [](){ DebugBreak(); }();" "\n\nvoid unused(const void *first,...) { (void) first; }" "\n#else" @@ -1304,7 +1389,7 @@ void tst_Dumpers::dumper() if (data.neededDwarfVersion.isRestricted) { QProcess readelf; readelf.setWorkingDirectory(t->buildPath); - readelf.start("readelf", { "-wi", "doit" }); + readelf.start("readelf", {"-wi", "doit"}); QVERIFY(readelf.waitForFinished()); output = readelf.readAllStandardOutput(); error = readelf.readAllStandardError(); @@ -1456,7 +1541,7 @@ void tst_Dumpers::dumper() logger.write(error); } - Context context; + Context context(m_debuggerEngine); QByteArray contents; if (m_debuggerEngine == GdbEngine) { int posDataStart = output.indexOf("data="); @@ -1607,6 +1692,15 @@ void tst_Dumpers::dumper() qDebug() << "SEEN INAMES " << seenINames; qDebug() << "EXPANDED : " << expanded; } + + for (int i = data.requiredMessages.size(); --i >= 0; ) { + RequiredMessage check = data.requiredMessages.at(i); + if (fullOutput.contains(check.message.toLatin1())) { + qDebug() << " EXPECTED MESSAGE TO BE MISSING, BUT FOUND: " << check.message; + ok = false; + } + } + if (ok) { m_keepTemp = false; } else { @@ -1624,7 +1718,7 @@ void tst_Dumpers::dumper() qDebug() << "MSG: " << fullOutput.mid(pos1, pos2 - pos1 - 1); } qDebug() << "CONTENTS : " << contents; - qDebug() << "FULL OUTPUT : " << fullOutput; + qDebug() << "FULL OUTPUT : " << fullOutput.data(); qDebug() << "Qt VERSION : " << QString::number(context.qtVersion, 16); if (m_debuggerEngine != CdbEngine) qDebug() << "GCC VERSION : " << context.gccVersion; @@ -1874,6 +1968,7 @@ void tst_Dumpers::dumper_data() "file.setObjectName(\"A QFile instance\");\n" "QFileInfo fi(\"C:\\\\Program Files\\\\tt\");\n" "QString s = fi.absoluteFilePath();\n") + + CoreProfile() + Check("fi", "\"C:/Program Files/tt\"", "QFileInfo") + Check("file", "\"C:\\Program Files\\t\"", "QFile") + Check("s", "\"C:/Program Files/tt\"", "QString"); @@ -1894,6 +1989,7 @@ void tst_Dumpers::dumper_data() QTest::newRow("QFixed") << Data("#include <private/qfixed_p.h>\n", "QFixed f(1234);\n") + + Qt5 + GuiPrivateProfile() + Check("f", "78976/64 = 1234.0", "@QFixed"); @@ -1989,8 +2085,7 @@ void tst_Dumpers::dumper_data() + Check("h7.2.key", "\".\"", "@QString") + CheckType("h7.2.value", "@QPointer<@QObject>") - + Check("h8", "<3 items>", "Hash") % NoCdbEngine - + Check("h8", "<3 items>", "QHash<int,float>") % CdbEngine + + Check("h8", "<3 items>", TypeDef("QHash<int,float>", "Hash")) + Check("h8.0", "[0] 22", FloatValue("22"), "") + Check("it1.key", "22", "int") + Check("it1.value", FloatValue("22"), "float") @@ -2026,7 +2121,7 @@ void tst_Dumpers::dumper_data() + NetworkProfile() + Check("ha1", "129.0.0.130", "@QHostAddress") - + Check("ha2", "\"127.0.0.1\"", "@QHostAddress") + + Check("ha2", ValuePattern(".*127.0.0.1.*"), "@QHostAddress") + Check("addr", "1:203:506:0:809:a0b:0:0", "@QIPv6Address") + Check("addr.3", "[3]", "3", "unsigned char"); @@ -2111,12 +2206,10 @@ void tst_Dumpers::dumper_data() + CheckType("l3.2", "[2]", "Foo") + Check("l3.2.a", "3", "int") - + Check("l4", "<2 items>", "@QLinkedList<unsigned long long>") % NoCdbEngine - + Check("l4.0", "[0]", "42", "unsigned long long") % NoCdbEngine - + Check("l4.1", "[1]", "43", "unsigned long long") % NoCdbEngine - + Check("l4", "<2 items>", "@QLinkedList<unsigned __int64>") % CdbEngine - + Check("l4.0", "[0]", "42", "unsigned int64") % CdbEngine - + Check("l4.1", "[1]", "43", "unsigned int64") % CdbEngine + + Check("l4", "<2 items>", TypeDef("@QLinkedList<unsigned __int64>", + "@QLinkedList<unsigned long long>")) + + Check("l4.0", "[0]", "42", TypeDef("unsigned int64", "unsigned long long")) + + Check("l4.1", "[1]", "43", TypeDef("unsigned int64", "unsigned long long")) + Check("l5", "<2 items>", "@QLinkedList<Foo>") @@ -2255,12 +2348,10 @@ void tst_Dumpers::dumper_data() + Check("l10.0", "[0]", "97", "@QChar") + Check("l10.2", "[2]", "99", "@QChar") - + Check("l11", "<3 items>", "@QList<unsigned long long>") % NoCdbEngine - + Check("l11.0", "[0]", "100", "unsigned long long") % NoCdbEngine - + Check("l11.2", "[2]", "102", "unsigned long long") % NoCdbEngine - + Check("l11", "<3 items>", "@QList<unsigned __int64>") % CdbEngine - + Check("l11.0", "[0]", "100", "unsigned int64") % CdbEngine - + Check("l11.2", "[2]", "102", "unsigned int64") % CdbEngine + + Check("l11", "<3 items>", TypeDef("@QList<unsigned __int64>", + "@QList<unsigned long long>")) + + Check("l11.0", "[0]", "100", TypeDef("unsigned int64", "unsigned long long")) + + Check("l11.2", "[2]", "102", TypeDef("unsigned int64", "unsigned long long")) + Check("l12", "<0 items>", "@QList<std::string>") + Check("l13", "<4 items>", "@QList<std::string>") @@ -2298,10 +2389,8 @@ void tst_Dumpers::dumper_data() + Check("r.0", "[0]", "3", "int") + Check("r.1", "[1]", "2", "int") + Check("r.2", "[2]", "1", "int") - + Check("rend", "", "Reverse") % NoCdbEngine - + Check("rend", "", "std::reverse_iterator<QList<int>::iterator>") % CdbEngine - + Check("rit", "", "Reverse") % NoCdbEngine - + Check("rit", "", "std::reverse_iterator<QList<int>::iterator>") % CdbEngine; + + Check("rend", "", TypeDef("std::reverse_iterator<QList<int>::iterator>", "Reverse")) + + Check("rit", "", TypeDef("std::reverse_iterator<QList<int>::iterator>", "Reverse")); QTest::newRow("QLocale") @@ -2313,6 +2402,7 @@ void tst_Dumpers::dumper_data() "QLocale::MeasurementSystem m1 = loc1.measurementSystem();\n" "unused(&loc0, &loc, &m, &loc1, &m1);\n") + CoreProfile() + + NoCdbEngine + CheckType("loc", "@QLocale") + CheckType("m", "@QLocale::MeasurementSystem") + Check("loc1", "\"en_US\"", "@QLocale") @@ -2395,8 +2485,7 @@ void tst_Dumpers::dumper_data() + Check("m2.0", "[0] 11", FloatValue("31.0"), "") + Check("m2.1", "[1] 22", FloatValue("32.0"), "") - + Check("m3", "<2 items>", "T") % NoCdbEngine - + Check("m3", "<2 items>", "QMap<unsigned int,QStringList>") % CdbEngine + + Check("m3", "<2 items>", TypeDef("QMap<unsigned int,QStringList>", "T")) + Check("m4", "<1 items>", "@QMap<@QString, float>") + Check("m4.0.key", "\"22.0\"", "@QString") @@ -2589,19 +2678,18 @@ void tst_Dumpers::dumper_data() + Check("test", "\"Name\"", "Bar::TestObject") + Check("test.[properties]", "<6 items>", "") + Check("test.[properties].myProp1", - "\"Hello\"", "@QVariant (QString)") + "\"Hello\"", "@QVariant (QString)") % NoCdbEngine + Check("test.[properties].myProp2", - "\"World\"", "@QVariant (QByteArray)") - + Check("test.[properties].myProp3", "54", "@QVariant (long)") - + Check("test.[properties].myProp4", "44", "@QVariant (int)") + "\"World\"", "@QVariant (QByteArray)") % NoCdbEngine + + Check("test.[properties].myProp3", "54", "@QVariant (long)") % NoCdbEngine + + Check("test.[properties].myProp4", "44", "@QVariant (int)") % NoCdbEngine + Check("test.[properties].4", "\"New\"", "\"Stuff\"", "@QVariant (QByteArray)") + Check("test.[properties].5", "\"Old\"", "\"Cruft\"", "@QVariant (QString)") + Check5("mm", "destroyed", "@QMetaMethod") + Check4("mm", "destroyed(QObject*)", "@QMetaMethod") - + Check("mm.handle", "14", "uint") % NoCdbEngine - + Check("mm.handle", "14", "unsigned int") % CdbEngine + + Check("mm.handle", "14", TypeDef("unsigned int", "uint")) + Check("mp", "objectName", "@QMetaProperty"); QTest::newRow("QObject3") @@ -2960,7 +3048,9 @@ void tst_Dumpers::dumper_data() "SomeStructPointer p(s); unused(p);\n" "Pointer<SomeStruct> pp(s); unused(pp);\n" "QAtomicPointer<SomeStruct> ppp(s); unused(ppp);\n") + + CoreProfile() + Cxx11Profile() + + MsvcVersion(1900) + Check("p.@1.a", "1", "int") + Check("p.@1.e", "<2 items>", "@QList<@QString>") + Check("pp.@1.a", "1", "int") @@ -3256,7 +3346,7 @@ void tst_Dumpers::dumper_data() expected1.append(QChar(1)); expected1.append("BBB\""); - QChar oUmlaut = QLatin1Char((char)0xf6); + QChar oUmlaut = QLatin1Char(char(0xf6)); QTest::newRow("QString") << Data("#include <QByteArray>\n" @@ -3324,7 +3414,7 @@ void tst_Dumpers::dumper_data() "#endif\n") + CoreProfile() - + + MsvcVersion(1900) + Check("s0", "\"Prefix: Hello\"", "@QByteArray") + Check("s1", expected1, "@QByteArray") + Check("s2", "\"Hell\"", "@QString") @@ -3350,8 +3440,8 @@ void tst_Dumpers::dumper_data() + Check("str4", "\"Hello\tQt\"", "@QString") + Check("holder", "", "@QStringDataPtr") % Qt5 - + Check("holder.ptr", "\"ABC\"", "@QStringData") % NoCdbEngine % Qt5 - + Check("holder.ptr", "\"ABC\"", "@QTypedArrayData<unsigned short>") % CdbEngine % Qt5 + + Check("holder.ptr", "\"ABC\"", TypeDef("@QTypedArrayData<unsigned short>", + "@QStringData")) % Qt5 + Check("sd", "\"Q\"", "@QStaticStringData<1>") % Qt5; @@ -3467,8 +3557,7 @@ void tst_Dumpers::dumper_data() //+ Check("v1", "\"Some string\"", "@QVariant (QString)") + CheckType("v1", "@QVariant (QString)") - + Check("my", "<2 items>", "MyType") % NoCdbEngine - + Check("my", "<2 items>", "QMap<unsigned int,QStringList>") % CdbEngine + + Check("my", "<2 items>", TypeDef("QMap<unsigned int,QStringList>", "MyType")) + Check("my.0.key", "1", "unsigned int") + Check("my.0.value", "<1 items>", "@QStringList") + Check("my.0.value.0", "[0]", "\"Hello\"", "@QString") @@ -3476,24 +3565,23 @@ void tst_Dumpers::dumper_data() + Check("my.1.value", "<1 items>", "@QStringList") + Check("my.1.value.0", "[0]", "\"World\"", "@QString") //+ CheckType("v2", "@QVariant (MyType)") - + Check("v2.data", "<2 items>", "MyType") % NoCdbEngine - + Check("v2.data", "<2 items>", "QMap<unsigned int,QStringList>") % CdbEngine - + Check("v2.data.0.key", "1", "unsigned int") - + Check("v2.data.0.value", "<1 items>", "@QStringList") - + Check("v2.data.0.value.0", "[0]", "\"Hello\"", "@QString") - + Check("v2.data.1.key", "3", "unsigned int") - + Check("v2.data.1.value", "<1 items>", "@QStringList") - + Check("v2.data.1.value.0", "[0]", "\"World\"", "@QString") + + Check("my", "<2 items>", TypeDef("QMap<unsigned int,QStringList>", "MyType")) + + Check("v2.data.0.key", "1", "unsigned int") % NoCdbEngine + + Check("v2.data.0.value", "<1 items>", "@QStringList") % NoCdbEngine + + Check("v2.data.0.value.0", "[0]", "\"Hello\"", "@QString") % NoCdbEngine + + Check("v2.data.1.key", "3", "unsigned int") % NoCdbEngine + + Check("v2.data.1.value", "<1 items>", "@QStringList") % NoCdbEngine + + Check("v2.data.1.value.0", "[0]", "\"World\"", "@QString") % NoCdbEngine + Check("list", "<3 items>", "@QList<int>") + Check("list.0", "[0]", "1", "int") + Check("list.1", "[1]", "2", "int") + Check("list.2", "[2]", "3", "int") //+ Check("v3", "", "@QVariant (@QList<int>)") - + Check("v3.data", "<3 items>", TypePattern(".*QList<int>")) - + Check("v3.data.0", "[0]", "1", "int") - + Check("v3.data.1", "[1]", "2", "int") - + Check("v3.data.2", "[2]", "3", "int"); + + Check("v3.data", "<3 items>", TypePattern(".*QList<int>")) % NoCdbEngine + + Check("v3.data.0", "[0]", "1", "int") % NoCdbEngine + + Check("v3.data.1", "[1]", "2", "int") % NoCdbEngine + + Check("v3.data.2", "[2]", "3", "int") % NoCdbEngine; QTest::newRow("QVariant2") @@ -3684,28 +3772,26 @@ void tst_Dumpers::dumper_data() + NetworkProfile() - + Check("ha", "\"127.0.0.1\"", "@QHostAddress") - + Check("ha.a", "2130706433", "@quint32") % NoCdbEngine - + Check("ha.a", "2130706433", "unsigned int") % CdbEngine - + Check("ha.ipString", "\"127.0.0.1\"", "@QString") - + Check("ha.isParsed", "1", "bool") + + Check("ha", ValuePattern(".*127.0.0.1.*"), "@QHostAddress") + + Check("ha.a", "2130706433", TypeDef("unsigned int", "@quint32")) + + Check("ha.ipString", ValuePattern(".*127.0.0.1.*"), "@QString") + % QtVersion(0, 0x50800) //+ Check("ha.protocol", "@QAbstractSocket::IPv4Protocol (0)", // "@QAbstractSocket::NetworkLayerProtocol") % GdbEngine //+ Check("ha.protocol", "IPv4Protocol", // "@QAbstractSocket::NetworkLayerProtocol") % LldbEngine + Check("ha.scopeId", "\"\"", "@QString") - + Check("ha1", "\"127.0.0.1\"", "@QHostAddress") - + Check("ha1.a", "2130706433", "@quint32") % NoCdbEngine - + Check("ha1.a", "2130706433", "unsigned int") % CdbEngine + + Check("ha1", ValuePattern(".*127.0.0.1.*"), "@QHostAddress") + + Check("ha1.a", "2130706433", TypeDef("unsigned int", "@quint32")) + Check("ha1.ipString", "\"127.0.0.1\"", "@QString") - + Check("ha1.isParsed", "1", "bool") + % QtVersion(0, 0x50800) //+ Check("ha1.protocol", "@QAbstractSocket::IPv4Protocol (0)", // "@QAbstractSocket::NetworkLayerProtocol") % GdbEngine //+ Check("ha1.protocol", "IPv4Protocol", // "@QAbstractSocket::NetworkLayerProtocol") % LldbEngine + Check("ha1.scopeId", "\"\"", "@QString") - + Check("var", "", "@QVariant (@QHostAddress)") - + Check("var.data", "\"127.0.0.1\"", "@QHostAddress"); + + Check("var", "", "@QVariant (@QHostAddress)") % NoCdbEngine + + Check("var.data", ValuePattern(".*127.0.0.1.*"), "@QHostAddress") % NoCdbEngine; QTest::newRow("QVariantList") @@ -3730,9 +3816,9 @@ void tst_Dumpers::dumper_data() + CoreProfile() - + Check("vl0", "<0 items>", "@QVariantList") + + Check("vl0", "<0 items>", TypeDef("@QList<@QVariant>", "@QVariantList")) - + Check("vl1", "<6 items>", "@QVariantList") + + Check("vl1", "<6 items>", TypeDef("@QList<@QVariant>", "@QVariantList")) + CheckType("vl1.0", "[0]", "@QVariant (int)") + CheckType("vl1.2", "[2]", "@QVariant (QString)") @@ -3760,9 +3846,9 @@ void tst_Dumpers::dumper_data() + CoreProfile() - + Check("vm0", "<0 items>", "@QVariantMap") + + Check("vm0", "<0 items>", TypeDef("@QMap<@QString,@QVariant>", "@QVariantMap")) - + Check("vm1", "<6 items>", "@QVariantMap") + + Check("vm1", "<6 items>", TypeDef("@QMap<@QString,@QVariant>", "@QVariantMap")) + Check("vm1.0.key", "\"a\"", "@QString") + Check("vm1.0.value", "1", "@QVariant (int)") + Check("vm1.5.key", "\"f\"", "@QString") @@ -3787,9 +3873,9 @@ void tst_Dumpers::dumper_data() + CoreProfile() - + Check("h0", "<0 items>", "@QVariantHash") + + Check("h0", "<0 items>", TypeDef("@QHash<@QString,@QVariant>", "@QVariantHash")) - + Check("h1", "<1 items>", "@QVariantHash") + + Check("h1", "<1 items>", TypeDef("@QHash<@QString,@QVariant>", "@QVariantHash")) + Check("h1.0.key", "\"one\"", "@QString") + Check("h1.0.value", "\"vone\"", "@QVariant (QString)") @@ -3847,8 +3933,7 @@ void tst_Dumpers::dumper_data() + Check("v2.1", "[1]", "", "Foo") + Check("v2.1.a", "2", "int") - + Check("v3", "<2 items>", "FooVector") % NoCdbEngine - + Check("v3", "<2 items>", "QVector<Foo>") % CdbEngine + + Check("v3", "<2 items>", TypeDef("QVector<Foo>", "FooVector")) + Check("v3.0", "[0]", "", "Foo") + Check("v3.0.a", "1", "int") + Check("v3.1", "[1]", "", "Foo") @@ -3928,8 +4013,7 @@ void tst_Dumpers::dumper_data() + Check("v2.1", "[1]", "", "Foo") + Check("v2.1.a", "2", "int") - + Check("v3", "<2 items>", "FooVector") % NoCdbEngine - + Check("v3", "<2 items>", "@QVarLengthArray<Foo,256>") % CdbEngine + + Check("v3", "<2 items>", TypeDef("@QVarLengthArray<Foo,256>", "FooVector")) + Check("v3.0", "[0]", "", "Foo") + Check("v3.0.a", "1", "int") + Check("v3.1", "[1]", "", "Foo") @@ -4023,6 +4107,7 @@ void tst_Dumpers::dumper_data() + ForceC() + GdbVersion(70500) + + NoCdbEngine + Check("a", "0 + 0 * I", "complex double") % GdbEngine + Check("b", "0 + 0 * I", "complex double") % GdbEngine @@ -4190,6 +4275,7 @@ void tst_Dumpers::dumper_data() "l2.push_back(new Foo(2));\n" "unused(&l2);\n") + + CoreProfile() + Check("l1", "<2 items>", "std::list<Foo>") + Check("l1.0", "[0]", "", "Foo") + Check("l1.0.a", "15", "int") @@ -4205,7 +4291,8 @@ void tst_Dumpers::dumper_data() QTest::newRow("StdMap") - << Data("#include <map>\n", + << Data("#include <map>\n" + "#include <string>\n", "std::map<unsigned int, unsigned int> map1;\n" "map1[11] = 1;\n" @@ -4237,7 +4324,13 @@ void tst_Dumpers::dumper_data() "map4.insert(std::pair<unsigned int, float>(22, 22.0));\n" "map4.insert(std::pair<unsigned int, float>(22, 23.0));\n" "map4.insert(std::pair<unsigned int, float>(22, 24.0));\n" - "map4.insert(std::pair<unsigned int, float>(22, 25.0));\n") + "map4.insert(std::pair<unsigned int, float>(22, 25.0));\n" + + "std::map<short, long long> map5;\n" + "map5[12] = 42;\n" + + "std::map<short, std::string> map6;\n" + "map6[12] = \"42\";\n") + Check("map1", "<2 items>", "std::map<unsigned int, unsigned int>") + Check("map1.0", "[0] 11", "1", "") @@ -4247,16 +4340,25 @@ void tst_Dumpers::dumper_data() + Check("map2.0", "[0] 11", FloatValue("11"), "") + Check("map2.1", "[1] 22", FloatValue("22"), "") - + Check("map3", "<6 items>", "Map") + + Check("map3", "<6 items>", TypeDef("std::map<int, float>", "Map")) + Check("map3.0", "[0] 11", FloatValue("11"), "") - + Check("it1.first", "11", "int") - + Check("it1.second", FloatValue("11"), "float") - + Check("it6.first", "66", "int") - + Check("it6.second", FloatValue("66"), "float") + + Check("it1.first", "11", "int") % NoCdbEngine + + Check("it1.second", FloatValue("11"), "float") % NoCdbEngine + + Check("it6.first", "66", "int") % NoCdbEngine + + Check("it6.second", FloatValue("66"), "float") % NoCdbEngine + + Check("it1.0", "11", FloatValue("11"), "") % CdbEngine + + Check("it6.0", "66", FloatValue("66"), "") % CdbEngine + Check("map4", "<5 items>", "std::multimap<unsigned int, float>") + Check("map4.0", "[0] 11", FloatValue("11"), "") - + Check("map4.4", "[4] 22", FloatValue("25"), ""); + + Check("map4.4", "[4] 22", FloatValue("25"), "") + + + Check("map5", "<1 items>", TypeDef("std::map<short, __int64>", + "std::map<short, long long>")) + + Check("map5.0", "[0] 12", "42", "") + + + Check("map6", "<1 items>", "std::map<short, std::string>") + + Check("map6.0", "[0] 12", "\"42\"", ""); QTest::newRow("StdMapQt") @@ -4372,6 +4474,7 @@ void tst_Dumpers::dumper_data() "std::unique_ptr<Foo> p2(new Foo); unused(&p2);\n\n" "std::unique_ptr<std::string> p3(new std::string(\"ABC\")); unused(&p3);\n\n") + + CoreProfile() + Cxx11Profile() + MacLibCppProfile() @@ -4399,6 +4502,7 @@ void tst_Dumpers::dumper_data() "std::weak_ptr<Foo> wf = pf; unused(&wf);\n" "std::weak_ptr<std::string> ws = ps; unused(&ws);\n") + + CoreProfile() + Cxx11Profile() + MacLibCppProfile() @@ -4465,7 +4569,7 @@ void tst_Dumpers::dumper_data() + Check("s1", "<3 items>", "std::set<int>") - + Check("s2", "<3 items>", "Set") + + Check("s2", "<3 items>", TypeDef("std::set<int>", "Set")) + Check("it1.value", "11", "int") + Check("it3.value", "33", "int") @@ -4490,6 +4594,7 @@ void tst_Dumpers::dumper_data() "unused(&ptr, &ob, &set1, &set2);\n") + + CoreProfile() + Check("set1", "<1 items>", "std::set<@QString>") + Check("set1.0", "[0]", "\"22.0\"", "@QString") @@ -4799,21 +4904,42 @@ void tst_Dumpers::dumper_data() "std::unordered_map<std::string, float> map2;\n" "map2[\"11.0\"] = 11.0;\n" "map2[\"22.0\"] = 22.0;\n" - "unused(&map2);\n") + "unused(&map2);\n" + + "std::unordered_multimap<int, std::string> map3;\n" + "map3.insert({1, \"Foo\"});\n" + "map3.insert({1, \"Bar\"});\n" + "unused(&map3);\n" ) + Cxx11Profile() + Check("map1", "<2 items>", "std::unordered_map<unsigned int, unsigned int>") - + Check("map1.0", "[0] 22", "2", "") - + Check("map1.1", "[1] 11", "1", "") + + Check("map1.0", "[0] 22", "2", "") % NoCdbEngine + + Check("map1.1", "[1] 11", "1", "") % NoCdbEngine + + Check("map1.0", "11", "1", "std::pair<unsigned int const ,unsigned int>") % CdbEngine + + Check("map1.1", "22", "2", "std::pair<unsigned int const ,unsigned int>") % CdbEngine + Check("map2", "<2 items>", "std::unordered_map<std::string, float>") - + Check("map2.0", "[0] \"22.0\"", FloatValue("22.0"), "") - + Check("map2.0.first", "\"22.0\"", "std::string") - + Check("map2.0.second", FloatValue("22"), "float") - + Check("map2.1", "[1] \"11.0\"", FloatValue("11.0"), "") - + Check("map2.1.first", "\"11.0\"", "std::string") - + Check("map2.1.second", FloatValue("11"), "float"); + + Check("map2.0", "[0] \"22.0\"", FloatValue("22.0"), "") % NoCdbEngine + + Check("map2.0.first", "\"22.0\"", "std::string") % NoCdbEngine + + Check("map2.0.second", FloatValue("22"), "float") % NoCdbEngine + + Check("map2.1", "[1] \"11.0\"", FloatValue("11.0"), "") % NoCdbEngine + + Check("map2.1.first", "\"11.0\"", "std::string") % NoCdbEngine + + Check("map2.1.second", FloatValue("11"), "float") % NoCdbEngine + + Check("map2.0", "\"11.0\"", FloatValue("11.0"), + "std::pair<std::string, float>") % CdbEngine + + Check("map2.0.first", "\"11.0\"", "std::string") % CdbEngine + + Check("map2.0.second", FloatValue("11"), "float") % CdbEngine + + Check("map2.1", "\"22.0\"", FloatValue("22.0"), + "std::pair<std::string, float>") % CdbEngine + + Check("map2.1.first", "\"22.0\"", "std::string") % CdbEngine + + Check("map2.1.second", FloatValue("22"), "float") % CdbEngine + + + Check("map3", "<2 items>", "std::unordered_multimap<int, std::string>") + + Check("map3.0", "[0] 1", "\"Bar\"", "") % NoCdbEngine + + Check("map3.1", "[1] 1", "\"Foo\"", "") % NoCdbEngine + + Check("map3.0", "1", "\"Foo\"", "std::pair<int const ,std::string>") % CdbEngine + + Check("map3.1", "1", "\"Bar\"", "std::pair<int const ,std::string>") % CdbEngine; QTest::newRow("StdUnorderedSet") @@ -4822,14 +4948,25 @@ void tst_Dumpers::dumper_data() "set1.insert(11);\n" "set1.insert(22);\n" "set1.insert(33);\n" - "unused(&set1);\n") + "unused(&set1);\n" + + "std::unordered_multiset<int> set2;\n" + "set2.insert(42);\n" + "set2.insert(42);\n" + "unused(&set2);\n") + Cxx11Profile() + Check("set1", "<3 items>", "std::unordered_set<int>") - + Check("set1.0", "[0]", "33", "int") + + Check("set1.0", "[0]", "33", "int") % NoCdbEngine + + Check("set1.0", "[0]", "11", "int") % CdbEngine + Check("set1.1", "[1]", "22", "int") - + Check("set1.2", "[2]", "11", "int"); + + Check("set1.2", "[2]", "11", "int") % NoCdbEngine + + Check("set1.2", "[2]", "33", "int") % CdbEngine + + + Check("set2", "<2 items>", "std::unordered_multiset<int>") + + Check("set2.0", "[0]", "42", "int") + + Check("set2.1", "[1]", "42", "int"); // class Goo @@ -4975,7 +5112,8 @@ void tst_Dumpers::dumper_data() const FloatValue ff("5.88545355e-44"); QTest::newRow("AnonymousStruct") - << Data("union {\n" + << Data("", + "union {\n" " struct { int i; int b; };\n" " struct { float f; };\n" " double d;\n" @@ -4987,9 +5125,13 @@ void tst_Dumpers::dumper_data() //+ Check("a.i", "42", "int") % GdbVersion(0, 70699) //+ Check("a.f", ff, "float") % GdbVersion(0, 70699) - + Check("a.#1.b", "43", "int") - + Check("a.#1.i", "42", "int") - + Check("a.#2.f", ff, "float"); + + Check("a.#1.b", "43", "int") % NoCdbEngine + + Check("a.#1.i", "42", "int") % NoCdbEngine + + Check("a.#2.f", ff, "float") % NoCdbEngine + + Check("a.b", "43", "int") % CdbEngine + + Check("a.i", "42", "int") % CdbEngine + + Check("a.f", ff, "float") % CdbEngine; + QTest::newRow("Chars") << Data("#include <qglobal.h>\n", @@ -5000,28 +5142,33 @@ void tst_Dumpers::dumper_data() "quint8 qu = -12;\n" "unused(&c, &sc, &uc, &qs, &qu);\n") + + CoreProfile() + Check("c", "-12", "char") // on all our platforms char is signed. - + Check("sc", "-12", "signed char") + + Check("sc", "-12", TypeDef("char", "signed char")) + Check("uc", "244", "unsigned char") - + Check("qs", "-12", "@qint8") - + Check("qu", "244", "@quint8"); + + Check("qs", "-12", TypeDef("char", "@qint8")) + + Check("qu", "244", TypeDef("unsigned char", "@quint8")); QTest::newRow("CharArrays") - << Data("char s[] = \"aöa\";\n" + << Data("", + "char s[] = \"aöa\";\n" "char t[] = \"aöax\";\n" "wchar_t w[] = L\"aöa\";\n" "unused(&s, &t, &w);\n") - + CheckType("s", "char [5]") + + CheckType("s", "char [5]") % NoCdbEngine + + CheckType("s", "char [4]") % CdbEngine + Check("s.0", "[0]", "97", "char") - + CheckType("t", "char [6]") + + CheckType("t", "char [6]") % NoCdbEngine + + CheckType("t", "char [5]") % CdbEngine + Check("t.0", "[0]", "97", "char") + CheckType("w", "wchar_t [4]"); QTest::newRow("CharPointers") - << Data("const char *s = \"aöa\";\n" + << Data("", + "const char *s = \"aöa\";\n" "const char *t = \"a\\xc3\\xb6\";\n" "unsigned char uu[] = { 'a', 153 /* ö Latin1 */, 'a' };\n" "const unsigned char *u = uu;\n" @@ -5040,12 +5187,13 @@ void tst_Dumpers::dumper_data() QTest::newRow("GccExtensions") - << Data( + << Data("", "char v[8] = { 1, 2 };\n" "char w __attribute__ ((vector_size (8))) = { 1, 2 };\n" "int y[2] = { 1, 2 };\n" "int z __attribute__ ((vector_size (8))) = { 1, 2 };\n" "unused(&v, &w, &y, &z);\n") + + NoCdbEngine + Check("v.0", "[0]", "1", "char") + Check("v.1", "[1]", "2", "char") + Check("w.0", "[0]", "1", "char") @@ -5071,14 +5219,15 @@ void tst_Dumpers::dumper_data() "QString dummy; // needed to get namespace\n" "unused(&u64, &s64, &u32, &s32, &u64s, &s64s, &u32s, &s32s, &dummy);\n") + CoreProfile() - + Check("u64", "18446744073709551615", "@quint64") - + Check("s64", "9223372036854775807", "@qint64") - + Check("u32", "4294967295", "@quint32") - + Check("s32", "2147483647", "@qint32") - + Check("u64s", "0", "@quint64") - + Check("s64s", "-9223372036854775808", "@qint64") - + Check("u32s", "0", "@quint32") - + Check("s32s", "-2147483648", "@qint32"); + + Check("u64", "18446744073709551615", TypeDef("unsigned int64", "@quint64")) + + Check("s64", "9223372036854775807", TypeDef("int64", "@qint64")) + + Check("u32", "4294967295", TypeDef("unsigned int", "@quint32")) + + Check("s32", "2147483647", TypeDef("int", "@qint32")) + + Check("u64s", "0", TypeDef("unsigned int64", "@quint64")) + + Check("s64s", "-9223372036854775808", TypeDef("int64", "@qint64")) + + Check("u32s", "0", TypeDef("unsigned int", "@quint32")) + + Check("s32s", "-2147483648", TypeDef("int", "@qint32")); + QTest::newRow("Enum") @@ -5109,7 +5258,8 @@ void tst_Dumpers::dumper_data() QTest::newRow("Array") - << Data("double a1[3][3];\n" + << Data("", + "double a1[3][3];\n" "for (int i = 0; i != 3; ++i)\n" " for (int j = 0; j != 3; ++j)\n" " a1[i][j] = i + j;\n" @@ -5154,6 +5304,7 @@ void tst_Dumpers::dumper_data() "for (int i = 0; i < 5; ++i)\n" " a3[i].a = i;\n") + + CoreProfile() + CheckType("a1", "@QString [20]") + Check("a1.0", "[0]", "\"a\"", "@QString") + Check("a1.3", "[3]", "\"d\"", "@QString") @@ -5172,7 +5323,8 @@ void tst_Dumpers::dumper_data() QTest::newRow("Bitfields") - << Data("struct S\n" + << Data("", + "struct S\n" "{\n" " S() : x(2), y(3), z(39), c(1), b(0), f(5), d(6), i(7) {}\n" " unsigned int x : 3;\n" @@ -5186,15 +5338,19 @@ void tst_Dumpers::dumper_data() "} s;\n" "unused(&s);\n") - + Check("s", "", "S") + + Check("s", "", "S") % NoCdbEngine + Check("s.b", "0", "bool") - + Check("s.c", "1", "bool : 1") + + Check("s.c", "1", "bool : 1") % NoCdbEngine + + Check("s.c", "1", "bool") % CdbEngine + Check("s.f", FloatValue("5"), "float") + Check("s.d", FloatValue("6"), "double") + Check("s.i", "7", "int") - + Check("s.x", "2", "unsigned int : 3") - + Check("s.y", "3", "unsigned int : 4") - + Check("s.z", "39", "unsigned int : 18"); + + Check("s.x", "2", "unsigned int : 3") % NoCdbEngine + + Check("s.y", "3", "unsigned int : 4") % NoCdbEngine + + Check("s.z", "39", "unsigned int : 18") % NoCdbEngine + + Check("s.x", "2", "unsigned int") % CdbEngine + + Check("s.y", "3", "unsigned int") % CdbEngine + + Check("s.z", "39", "unsigned int") % CdbEngine; QTest::newRow("Function") @@ -5277,6 +5433,7 @@ void tst_Dumpers::dumper_data() "Foo *p = new Foo();\n" "unused(&p);\n") + + CoreProfile() + Check("f", "", "Foo") + Check("f.a", "3", "int") + Check("f.b", "2", "int") @@ -5335,8 +5492,8 @@ void tst_Dumpers::dumper_data() "CVoidPtr cp = &a;\n" "unused(&a, &p, &cp);\n") + Check("a", "", "A") - + Check("cp", Pointer(), "CVoidPtr") - + Check("p", Pointer(), "VoidPtr"); + + Check("cp", Pointer(), TypeDef("void*", "CVoidPtr")) + + Check("p", Pointer(), TypeDef("void*", "VoidPtr")); QTest::newRow("Reference") @@ -5374,6 +5531,7 @@ void tst_Dumpers::dumper_data() "unused(&a4, &b4, &d4);\n") + CoreProfile() + + NoCdbEngine // The Cdb has no information about references + Check("a1", "43", "int") + Check("b1", "43", "int &") @@ -5403,6 +5561,7 @@ void tst_Dumpers::dumper_data() "BaseClass *b1 = &d;\n" "BaseClass &b2 = d;\n" "unused(&d, &b1, &b2);\n") + + NoCdbEngine // The Cdb has no information about references + CheckType("b1", "DerivedClass") // autoderef + CheckType("b2", "DerivedClass &"); @@ -5426,7 +5585,8 @@ void tst_Dumpers::dumper_data() */ QTest::newRow("LongEvaluation2") - << Data("const int N = 10000;\n" + << Data("", + "const int N = 10000;\n" "int bigv[N];\n" "for (int i = 0; i < N; ++i)\n" " bigv[i] = i;\n" @@ -5467,8 +5627,8 @@ void tst_Dumpers::dumper_data() "int a2 = x.*m;\n" "unused(&a2);\n") - + CheckType("f", "func_t") - + CheckType("m", "member_t"); + + CheckType("f", TypeDef("<function>", "func_t")) + + CheckType("m", TypeDef("int*", "member_t")); QTest::newRow("PassByReference") @@ -5480,6 +5640,8 @@ void tst_Dumpers::dumper_data() "}\n", "Foo f(12);\n" "testPassByReference(f);\n") + + CoreProfile() + + NoCdbEngine // The Cdb has no information about references + CheckType("f", "Foo &") + Check("f.a", "12", "int"); @@ -5494,10 +5656,10 @@ void tst_Dumpers::dumper_data() "QString dummy;\n" "unused(&a, &b, &c, &d, &dummy);\n") + CoreProfile() - + Check("a", "-1143861252567568256", "@qint64") - + Check("b", "17302882821141983360", "@quint64") - + Check("c", "18446744073709551614", "@quint64") - + Check("d", "-2", "@qint64"); + + Check("a", "-1143861252567568256", TypeDef("int64", "@qint64")) + + Check("b", "17302882821141983360", TypeDef("unsigned int64", "@quint64")) + + Check("c", "18446744073709551614", TypeDef("unsigned int64", "@quint64")) + + Check("d", "-2", TypeDef("int64", "@qint64")); QTest::newRow("Hidden") @@ -5539,6 +5701,7 @@ void tst_Dumpers::dumper_data() QTest::newRow("RValueReference2") << Data(rvalueData) + DwarfProfile(2) + + NoCdbEngine // The Cdb has no information about references + Check("x1", "", "X &") + Check("x2", "", "X &") + Check("x3", "", "X &"); @@ -5608,6 +5771,7 @@ void tst_Dumpers::dumper_data() "boost::shared_ptr<QStringList> sl(new QStringList(QStringList() << \"HUH!\"));\n" "unused(&s, &i, &j, &sl);\n") + + CoreProfile() + BoostProfile() + Check("s", "(null)", "boost::shared_ptr<int>") @@ -5668,7 +5832,8 @@ void tst_Dumpers::dumper_data() "int r = it->second;\n" "unused(&l, &r);\n") + BoostProfile() - + Check("b", "<1 items>", "B"); + + Check("b", "<1 items>", TypeDef("boost::bimaps::bimap<int,int,boost::mpl::na," + "boost::mpl::na,boost::mpl::na>", "B")); QTest::newRow("BoostPosixTimePtime") @@ -5688,6 +5853,9 @@ void tst_Dumpers::dumper_data() + Check("p3", "Thu Jan 1 00:00:00 1970", "boost::posix_time::ptime"); +/* + FIXME + QTest::newRow("BoostList") << Data("#include <boost/container/list.hpp>\n", "typedef std::pair<int, double> p;\n" @@ -5699,6 +5867,7 @@ void tst_Dumpers::dumper_data() + BoostProfile() + Check("l", "<4 items>", TypePattern("boost::container::list<std::pair<int,double>.*>")) + Check("l.2.second", FloatValue("65"), "double"); +*/ QTest::newRow("BoostUnorderedSet") @@ -5777,10 +5946,11 @@ void tst_Dumpers::dumper_data() // https://bugreports.qt.io/browse/QTCREATORBUG-3611 QTest::newRow("Bug3611") - << Data("typedef unsigned char byte;\n" + << Data("", + "typedef unsigned char byte;\n" "byte f = '2';\n" "int *x = (int*)&f;\n") - + Check("f", "50", "byte"); + + Check("f", "50", TypeDef("unsigned char", "byte")); // https://bugreports.qt.io/browse/QTCREATORBUG-4904 @@ -5850,7 +6020,8 @@ void tst_Dumpers::dumper_data() + NetworkProfile() + Check("raw", "<0 items>", "@QList<@QByteArray>") + CheckType("request", "@QNetworkRequest") - + Check("url", "\"http://127.0.0.1/\"", "@QUrl &"); + + Check("url", "\"http://127.0.0.1/\"", "@QUrl &") % NoCdbEngine + + Check("url", "\"http://127.0.0.1/\"", "@QUrl") % CdbEngine; // https://bugreports.qt.io/browse/QTCREATORBUG-5799 @@ -5868,7 +6039,7 @@ void tst_Dumpers::dumper_data() "Array a2;\n" "unused(&s2, &s4, &a1, &a2);\n") + CheckType("a1", "S1 [10]") - + CheckType("a2", "Array") + + CheckType("a2", TypeDef("S1 [10]", "Array")) + CheckType("s2", "S2") + CheckType("s2.@1", "[S1]", "S1") + Check("s2.@1.m1", "5", "int") @@ -5881,7 +6052,8 @@ void tst_Dumpers::dumper_data() // https://bugreports.qt.io/browse/QTCREATORBUG-6465 QTest::newRow("Bug6465") - << Data("typedef char Foo[20];\n" + << Data("", + "typedef char Foo[20];\n" "Foo foo = \"foo\";\n" "char bar[20] = \"baz\";\n") + CheckType("bar", "char[20]"); @@ -5973,11 +6145,51 @@ void tst_Dumpers::dumper_data() "Derived d;\n" "Base *b = &d;\n" "unused(&d, &b);\n") + + NoCdbEngine // FIXME + Check("b.@1.a", "a", "21", "int") + Check("b.b", "b", "42", "int"); + // https://bugreports.qt.io/browse/QTCREATORBUG-17823 + QTest::newRow("Bug17823") + << Data("struct Base1\n" + "{\n" + " virtual ~Base1() {}\n" + " int foo = 42;\n" + "};\n\n" + "struct Base2\n" + "{\n" + " virtual ~Base2() {}\n" + " int bar = 43;\n" + "};\n\n" + "struct Derived : Base1, Base2\n" + "{\n" + " int baz = 84;\n" + "};\n\n" + "struct Container\n" + "{\n" + " Container(Base2 *b) : b2(b) {}\n" + " Base2 *b2;\n" + "};\n", + + "Derived d;\n" + "Container c(&d); // c.b2 has wrong address\n" + "unused(&c);\n" + "Base2 *b2 = &d; // This has the right address\n" + "unused(&b2);\n") + + NoCdbEngine // FIXME + + + Check("c.b2.@1.foo", "42", "int") + + Check("c.b2.@2.bar", "43", "int") + + Check("c.b2.baz", "84", "int") + + + Check("d.@1.foo", "42", "int") + + Check("d.@2.bar", "43", "int") + + Check("d.baz", "84", "int"); + + + // http://www.qtcentre.org/threads/42170-How-to-watch-data-of-actual-type-in-debugger QTest::newRow("QC42170") << Data("struct Object {\n" @@ -6004,6 +6216,7 @@ void tst_Dumpers::dumper_data() "Object *obj = circle;\n" "helper(circle);\n" "helper(obj);\n") + + NoCdbEngine + CheckType("obj", "Circle"); @@ -6023,7 +6236,7 @@ void tst_Dumpers::dumper_data() "m[\"two\"].push_back(\"2\");\n" "m[\"two\"].push_back(\"3\");\n" "map_t::const_iterator it = m.begin();\n") - + Check("m", "<2 items>", "map_t") + + Check("m", "<2 items>", TypeDef("std::map<std::string, std::list<std::string>>","map_t")) + Check("m.0.first", "\"one\"", "std::string") + Check("m.0.second", "<3 items>", "std::list<std::string>") + Check("m.0.second.0", "[0]", "\"a\"", "std::string") @@ -6034,10 +6247,14 @@ void tst_Dumpers::dumper_data() + Check("m.1.second.0", "[0]", "\"1\"", "std::string") + Check("m.1.second.1", "[1]", "\"2\"", "std::string") + Check("m.1.second.2", "[2]", "\"3\"", "std::string") - + CheckType("it", "std::map<std::string, std::list<std::string> >::const_iterator") - + Check("it.first", "\"one\"", "std::string") - + Check("it.second", "<3 items>", "std::list<std::string>"); - + + CheckType("it", TypeDef("std::_Tree_const_iterator<std::_Tree_val<" + "std::_Tree_simple_types<std::pair<" + "std::string const ,std::list<std::string>>>>>", + "std::map<std::string, std::list<std::string> >::const_iterator")) + + Check("it.first", "\"one\"", "std::string") % NoCdbEngine + + Check("it.second", "<3 items>", "std::list<std::string>") % NoCdbEngine + + Check("it.0.first", "\"one\"", "std::string") % CdbEngine + + Check("it.0.second", "<3 items>", "std::list<std::string>") % CdbEngine; QTest::newRow("Varargs") << Data("#include <stdarg.h>\n" @@ -6202,32 +6419,40 @@ void tst_Dumpers::dumper_data() // The proposed fix has been reported to crash gdb steered from eclipse"); // http://sourceware.org/ml/gdb-patches/2011-12/msg00420.html QTest::newRow("Gdb10586") - << Data("struct Test {\n" + << Data("", + "struct Test {\n" " struct { int a; float b; };\n" " struct { int c; float d; };\n" "} v = {{1, 2}, {3, 4}};\n" "unused(&v);\n") - + Check("v", "", "Test") + + Check("v", "", "Test") % NoCdbEngine + + Check("v", "", TypePattern("main::.*::Test")) % CdbEngine //+ Check("v.a", "1", "int") % GdbVersion(0, 70699) //+ Check("v.0.a", "1", "int") % GdbVersion(70700) - + Check("v.#1.a", "1", "int"); + + Check("v.#1.a", "1", "int") % NoCdbEngine + + Check("v.a", "1", "int") % CdbEngine; QTest::newRow("Gdb10586eclipse") - << Data("struct { int x; struct { int a; }; struct { int b; }; } " + << Data("", + "struct { int x; struct { int a; }; struct { int b; }; } " " v = {1, {2}, {3}};\n" "struct S { int x, y; } n = {10, 20};\n" "unused(&v, &n);\n") + Check("v", "", "{...}") % GdbEngine + Check("v", "", TypePattern(".*anonymous .*")) % LldbEngine - + Check("n", "", "S") + + Check("v", "", TypePattern(".*<unnamed-type-.*")) % CdbEngine + + Check("n", "", "S") % NoCdbEngine + + Check("n", "", TypePattern("main::.*::S")) % CdbEngine //+ Check("v.a", "2", "int") % GdbVersion(0, 70699) //+ Check("v.0.a", "2", "int") % GdbVersion(70700) - + Check("v.#1.a", "2", "int") + + Check("v.#1.a", "2", "int") % NoCdbEngine + + Check("v.a", "2", "int") % CdbEngine //+ Check("v.b", "3", "int") % GdbVersion(0, 70699) //+ Check("v.1.b", "3", "int") % GdbVersion(70700) - + Check("v.#2.b", "3", "int") + + Check("v.#2.b", "3", "int") % NoCdbEngine + + Check("v.b", "3", "int") % CdbEngine + Check("v.x", "1", "int") + Check("n.x", "10", "int") + Check("n.y", "20", "int"); @@ -6242,12 +6467,12 @@ void tst_Dumpers::dumper_data() "uint32_t u32 = 68;\n" "int32_t s32 = 69;\n" "unused(&u8, &s8, &u16, &s16, &u32, &s32);\n") - + Check("u8", "64", "uint8_t") - + Check("s8", "65", "int8_t") - + Check("u16", "66", "uint16_t") - + Check("s16", "67", "int16_t") - + Check("u32", "68", "uint32_t") - + Check("s32", "69", "int32_t"); + + Check("u8", "64", TypeDef("unsigned char", "uint8_t")) + + Check("s8", "65", TypeDef("char", "int8_t")) + + Check("u16", "66", TypeDef("unsigned short", "uint16_t")) + + Check("s16", "67", TypeDef("short", "int16_t")) + + Check("u32", "68", TypeDef("unsigned int", "uint32_t")) + + Check("s32", "69", TypeDef("int", "int32_t")); QTest::newRow("QPolygon") << Data("#include <QGraphicsScene>\n" @@ -6312,7 +6537,9 @@ void tst_Dumpers::dumper_data() "unused(&ob,&b,&a);\n" "#endif\n") + Cxx11Profile() + + CoreProfile() + QtVersion(0x50000) + + MsvcVersion(1900) + Check("a", "<6 items>", "@QJsonArray") + Check("a.0", "[0]", "1", "QJsonValue (Number)") + Check("a.1", "[1]", "\"asd\"", "QJsonValue (String)") @@ -6356,9 +6583,9 @@ void tst_Dumpers::dumper_data() QTest::newRow("QV4") << Data("#include <private/qv4value_p.h>\n" "#include <private/qjsvalue_p.h>\n" - "#include <QGuiApplication>\n" + "#include <QCoreApplication>\n" "#include <QJSEngine>\n", - "QGuiApplication app(argc, argv);\n" + "QCoreApplication app(argc, argv);\n" "QJSEngine eng;\n\n" "//QV4::Value q0; unused(&q0); // Uninitialized data.\n\n" "//QV4::Value q1; unused(&q1); // Upper 32 bit uninitialized.\n" @@ -6416,6 +6643,7 @@ void tst_Dumpers::dumper_data() QTest::newRow("Internal1") << Data("struct QtcDumperTest_FieldAccessByIndex { int d[3] = { 10, 11, 12 }; };\n", "QtcDumperTest_FieldAccessByIndex d; unused(&d);\n") + + MsvcVersion(1900) + Check("d", "12", "QtcDumperTest_FieldAccessByIndex"); @@ -6429,6 +6657,38 @@ void tst_Dumpers::dumper_data() + Check("tc.1.bar", "15", "int") + Check("tc.2.bar", "15", "int") + Check("tc.3.bar", "15", "int"); + + QTest::newRow("ArrayOfFunctionPointers") + << Data("typedef int (*FP)(int *); \n" + "int func(int *param) { unused(param); return 0; } \n", + "FP fps[5]; fps[0] = func; fps[0](0); unused(&fps);\n") + + RequiredMessage("Searching for type int (*)(int *) across all target modules, this could be very slow") + + LldbEngine; + + QTest::newRow("Sql") + << Data("#include <QSqlField>\n" + "#include <QSqlDatabase>\n" + "#include <QSqlQuery>\n" + "#include <QSqlRecord>\n", + "QSqlDatabase db = QSqlDatabase::addDatabase(\"QSQLITE\");\n" + "db.setDatabaseName(\":memory:\");\n" + "Q_ASSERT(db.open());\n" + "QSqlQuery query;\n" + "query.exec(\"create table images (itemid int, file varchar(20))\");\n" + "query.exec(\"insert into images values(1, 'qt-logo.png')\");\n" + "query.exec(\"insert into images values(2, 'qt-creator.png')\");\n" + "query.exec(\"insert into images values(3, 'qt-project.png')\");\n" + "query.exec(\"select * from images\");\n" + "query.next();\n" + "QSqlRecord rec = query.record();\n" + "QSqlField f1 = rec.field(0);\n" + "QSqlField f2 = rec.field(1);\n" + "QSqlField f3 = rec.field(2);\n" + "unused(&f1, &f2, &f3);\n") + + SqlProfile() + + Check("f1", "1", "@QSqlField (qlonglong)") + + Check("f2", "\"qt-logo.png\"", "@QSqlField (QString)") + + Check("f3", "(invalid)", "@QSqlField (invalid)"); #if 0 #ifdef Q_OS_LINUX // Hint: To open a failing test in Creator, do: diff --git a/tests/auto/debugger/tst_offsets.cpp b/tests/auto/debugger/tst_offsets.cpp index b8513f959c..ee39d08a76 100644 --- a/tests/auto/debugger/tst_offsets.cpp +++ b/tests/auto/debugger/tst_offsets.cpp @@ -149,7 +149,7 @@ void tst_offsets::offsets_data() if (qtVersion >= 0x50600) #ifdef Q_OS_WIN # ifdef Q_CC_MSVC - OFFSET_TEST(QFilePrivate, fileName) << 176 << 248; + OFFSET_TEST(QFilePrivate, fileName) << 184 << 248; # else // MinGW OFFSET_TEST(QFilePrivate, fileName) << 164 << 248; # endif diff --git a/tests/auto/debugger/tst_simplifytypes.cpp b/tests/auto/debugger/tst_simplifytypes.cpp index 94693e92b4..2d5444d386 100644 --- a/tests/auto/debugger/tst_simplifytypes.cpp +++ b/tests/auto/debugger/tst_simplifytypes.cpp @@ -44,7 +44,9 @@ const char *description[] = "g++_stringvector", "g++_wstringvector", "g++_unordered_set", + "g++_unordered_multiset", "g++_unordered_map", + "g++_unordered_multimap", "g++_stdvector_int_ptr", "g++_stdmap_char_ptr", @@ -82,7 +84,9 @@ const char *input[] = "std::vector<std::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> >, std::allocator<std::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> > > >", "std::unordered_set<int, std::hash<int>, std::equal_to<int>, std::allocator<int> >", +"std::unordered_multiset<int, std::hash<int>, std::equal_to<int>, std::allocator<int> >", "std::unordered_map<int, int, std::hash<int>, std::equal_to<int>, std::allocator<std::pair<int const, int> > >", +"std::unordered_multimap<int, int, std::hash<int>, std::equal_to<int>, std::allocator<std::pair<int const, int> > >", "std::vector<int *, std::allocator<int*> >", "std::map<const char *, Foo, std::less<const char *>, std::allocator<std::pair<char const* const, Foo> > >", @@ -124,7 +128,9 @@ const char *output[] = "std::vector<std::string>", "std::vector<std::wstring>", "std::unordered_set<int>", + "std::unordered_multiset<int>", "std::unordered_map<int, int>", + "std::unordered_multimap<int, int>", "std::vector<int *>", "std::map<const char *, Foo>", // libc++ diff --git a/tests/auto/environment/tst_environment.cpp b/tests/auto/environment/tst_environment.cpp index feb9831139..48fb26c92d 100644 --- a/tests/auto/environment/tst_environment.cpp +++ b/tests/auto/environment/tst_environment.cpp @@ -57,31 +57,31 @@ void tst_Environment::environment_data() const char * const out; } vals[] = { #ifdef Q_OS_WIN - { "", "" }, - { "hi", "hi" }, - { "hi%", "hi%" }, - { "hi% ho", "hi% ho" }, - { "hi%here ho", "hi%here ho" }, - { "hi%here%ho", "hi%here%ho" }, - { "hi%word%", "hihi" }, - { "hi%foo%word%", "hi%foohi" }, - { "%word%word%ho", "hiword%ho" }, - { "hi%word%x%word%ho", "hihixhiho" }, - { "hi%word%xx%word%ho", "hihixxhiho" }, - { "hi%word%%word%ho", "hihihiho" }, + {"", ""}, + {"hi", "hi"}, + {"hi%", "hi%"}, + {"hi% ho", "hi% ho"}, + {"hi%here ho", "hi%here ho"}, + {"hi%here%ho", "hi%here%ho"}, + {"hi%word%", "hihi"}, + {"hi%foo%word%", "hi%foohi"}, + {"%word%word%ho", "hiword%ho"}, + {"hi%word%x%word%ho", "hihixhiho"}, + {"hi%word%xx%word%ho", "hihixxhiho"}, + {"hi%word%%word%ho", "hihihiho"}, #else - { "", "" }, - { "hi", "hi" }, - { "hi$", "hi$" }, - { "hi${", "hi${" }, - { "hi${word", "hi${word" }, - { "hi${word}", "hihi" }, - { "hi${word}ho", "hihiho" }, - { "hi$wo", "hi$wo" }, - { "hi$word", "hihi" }, - { "hi$word ho", "hihi ho" }, - { "$word", "hi" }, - { "hi${word}$word", "hihihi" }, + {"", ""}, + {"hi", "hi"}, + {"hi$", "hi$"}, + {"hi${", "hi${"}, + {"hi${word", "hi${word"}, + {"hi${word}", "hihi"}, + {"hi${word}ho", "hihiho"}, + {"hi$wo", "hi$wo"}, + {"hi$word", "hihi"}, + {"hi$word ho", "hihi ho"}, + {"$word", "hi"}, + {"hi${word}$word", "hihihi"}, #endif }; diff --git a/tests/auto/json/tst_json.cpp b/tests/auto/json/tst_json.cpp index 67c77b64d4..1253f00806 100644 --- a/tests/auto/json/tst_json.cpp +++ b/tests/auto/json/tst_json.cpp @@ -1598,12 +1598,12 @@ void tst_Json::parseNumbers() int n; }; Numbers numbers [] = { - { "0", 0 }, - { "1", 1 }, - { "10", 10 }, - { "-1", -1 }, - { "100000", 100000 }, - { "-999", -999 } + {"0", 0}, + {"1", 1}, + {"10", 10}, + {"-1", -1}, + {"100000", 100000}, + {"-999", -999} }; int size = sizeof(numbers)/sizeof(Numbers); for (int i = 0; i < size; ++i) { @@ -1628,26 +1628,26 @@ void tst_Json::parseNumbers() double n; }; Numbers numbers [] = { - { "0", 0 }, - { "1", 1 }, - { "10", 10 }, - { "-1", -1 }, - { "100000", 100000 }, - { "-999", -999 }, - { "1.1", 1.1 }, - { "1e10", 1e10 }, - { "-1.1", -1.1 }, - { "-1e10", -1e10 }, - { "-1E10", -1e10 }, - { "1.1e10", 1.1e10 }, - { "1.1e308", 1.1e308 }, - { "-1.1e308", -1.1e308 }, - { "1.1e-308", 1.1e-308 }, - { "-1.1e-308", -1.1e-308 }, - { "1.1e+308", 1.1e+308 }, - { "-1.1e+308", -1.1e+308 }, - { "1.e+308", 1.e+308 }, - { "-1.e+308", -1.e+308 } + {"0", 0}, + {"1", 1}, + {"10", 10}, + {"-1", -1}, + {"100000", 100000}, + {"-999", -999}, + {"1.1", 1.1}, + {"1e10", 1e10}, + {"-1.1", -1.1}, + {"-1e10", -1e10}, + {"-1E10", -1e10}, + {"1.1e10", 1.1e10}, + {"1.1e308", 1.1e308}, + {"-1.1e308", -1.1e308}, + {"1.1e-308", 1.1e-308}, + {"-1.1e-308", -1.1e-308}, + {"1.1e+308", 1.1e+308}, + {"-1.1e+308", -1.1e+308}, + {"1.e+308", 1.e+308}, + {"-1.e+308", -1.e+308} }; int size = sizeof(numbers)/sizeof(Numbers); for (int i = 0; i < size; ++i) { @@ -1710,10 +1710,10 @@ void tst_Json::parseStrings() const char *out; }; Pairs pairs [] = { - { "abc\\/abc", "abc/abc" }, - { "abc\\u0402abc", "abc" UNICODE_DJE "abc" }, - { "abc\\u0065abc", "abceabc" }, - { "abc\\uFFFFabc", "abc" UNICODE_NON_CHARACTER "abc" } + {"abc\\/abc", "abc/abc"}, + {"abc\\u0402abc", "abc" UNICODE_DJE "abc"}, + {"abc\\u0065abc", "abceabc"}, + {"abc\\uFFFFabc", "abc" UNICODE_NON_CHARACTER "abc"} }; size = sizeof(pairs)/sizeof(Pairs); @@ -2024,7 +2024,7 @@ void tst_Json::assignArrays() void tst_Json::testTrailingComma() { - const char *jsons[] = { "{ \"Key\": 1, }", "[ { \"Key\": 1 }, ]" }; + const char *jsons[] = {"{ \"Key\": 1, }", "[ { \"Key\": 1 }, ]"}; for (unsigned i = 0; i < sizeof(jsons)/sizeof(jsons[0]); ++i) { JsonParseError error; @@ -2390,21 +2390,21 @@ void tst_Json::arrayInitializerList() { JsonObject o; o["property"] = 1; - JsonArray a1 {o}; + JsonArray a1{o}; QCOMPARE(a1.count(), 1); QCOMPARE(a1[0].toObject(), o); - JsonArray a2 {o, 23}; + JsonArray a2{o, 23}; QCOMPARE(a2.count(), 2); QCOMPARE(a2[0].toObject(), o); QCOMPARE(JsonValue(a2[1]), JsonValue(23)); - JsonArray a3 { a1, o, a2 }; + JsonArray a3{a1, o, a2}; QCOMPARE(JsonValue(a3[0]), JsonValue(a1)); QCOMPARE(JsonValue(a3[1]), JsonValue(o)); QCOMPARE(JsonValue(a3[2]), JsonValue(a2)); - JsonArray a4 { 1, JsonArray{1,2,3}, JsonArray{"hello", 2}, JsonObject{{"one", 1}} }; + JsonArray a4{1, JsonArray{1,2,3}, JsonArray{"hello", 2}, JsonObject{{"one", 1}}}; QCOMPARE(a4.count(), 4); QCOMPARE(JsonValue(a4[0]), JsonValue(1)); @@ -2439,9 +2439,9 @@ void tst_Json::objectInitializerList() } { // two properties JsonObject two { - {"one", 1}, - {"two", 2} - }; + {"one", 1}, + {"two", 2} + }; QCOMPARE(two.count(), 2); QVERIFY(two.contains("one")); QVERIFY(two.contains("two")); diff --git a/tests/auto/profilewriter/tst_profilewriter.cpp b/tests/auto/profilewriter/tst_profilewriter.cpp index f60c5aa810..999ac0ae41 100644 --- a/tests/auto/profilewriter/tst_profilewriter.cpp +++ b/tests/auto/profilewriter/tst_profilewriter.cpp @@ -94,8 +94,8 @@ void tst_ProFileWriter::adds_data() const char *output; }; - static const char *f_foo[] = { "foo", 0 }; - static const char *f_foo_bar[] = { "foo", "bar", 0 }; + static const char *f_foo[] = {"foo", 0}; + static const char *f_foo_bar[] = {"foo", "bar", 0}; static const Case cases[] = { { PW::AppendValues|PW::AppendOperator|PW::MultiLine, @@ -469,8 +469,8 @@ void tst_ProFileWriter::removes_data() const char *output; }; - static const char *f_foo[] = { "foo", 0 }; - static const char *f_foo_bar[] = { "foo", "bar", 0 }; + static const char *f_foo[] = {"foo", 0}; + static const char *f_foo_bar[] = {"foo", "bar", 0}; static const Case cases[] = { { "remove fail", f_foo, diff --git a/tests/auto/qml/codemodel/importscheck/importscheck.pro b/tests/auto/qml/codemodel/importscheck/importscheck.pro index 56302a5786..d5e9ba7781 100644 --- a/tests/auto/qml/codemodel/importscheck/importscheck.pro +++ b/tests/auto/qml/codemodel/importscheck/importscheck.pro @@ -1,7 +1,7 @@ QTC_LIB_DEPENDS += cplusplus utils extensionsystem include(../../../qttest.pri) include($$IDE_SOURCE_TREE/src/rpath.pri) -DEFINES += QMLJS_BUILD_DIR +DEFINES += QMLJS_LIBRARY QT += qml xml # direct dependency on qmljs for quicker turnaround when editing them diff --git a/tests/auto/qml/codemodel/importscheck/tst_importscheck.cpp b/tests/auto/qml/codemodel/importscheck/tst_importscheck.cpp index cdbeb745cf..f362c2cdf9 100644 --- a/tests/auto/qml/codemodel/importscheck/tst_importscheck.cpp +++ b/tests/auto/qml/codemodel/importscheck/tst_importscheck.cpp @@ -118,69 +118,57 @@ void tst_ImportCheck::test_data() QTest::addColumn<QStringList>("paths"); QTest::addColumn<QStringList>("expectedLibraries"); QTest::addColumn<QStringList>("expectedFiles"); - QTest::newRow("base") << QStringList(QLatin1String(TESTSRCDIR "/base")) - << (QStringList() << QLatin1String("QML 1.0") - << QLatin1String("QtQml 2.2") - << QLatin1String("QtQml 2.1") - << QLatin1String("QtQuick 2.0") - << QLatin1String("QtQml 2.0") - << QLatin1String("QtQuick 2.-1") - << QLatin1String("QtQuick 2.1") - << QLatin1String("QtQuick 2.2") - << QLatin1String("<cpp>")) + QTest::newRow("base") << QStringList(QString(TESTSRCDIR "/base")) + << QStringList({"QML 1.0", "QtQml 2.2", "QtQml 2.1", "QtQuick 2.0", + "QtQml 2.0", "QtQuick 2.-1", "QtQuick 2.1", + "QtQuick 2.2", "<cpp>"}) << QStringList(); - QTest::newRow("001_flatQmlOnly") << QStringList(QLatin1String(TESTSRCDIR "/001_flatQmlOnly")) + QTest::newRow("001_flatQmlOnly") << QStringList(QString(TESTSRCDIR "/001_flatQmlOnly")) << QStringList() << QStringList(); - QTest::newRow("002_nestedQmlOnly") << QStringList(QLatin1String(TESTSRCDIR "/002_nestedQmlOnly")) + QTest::newRow("002_nestedQmlOnly") << QStringList(QString(TESTSRCDIR "/002_nestedQmlOnly")) << QStringList() << QStringList(); - /*QTest::newRow("003_packageQmlOnly") << QStringList(QLatin1String(TESTSRCDIR "/003_packageQmlOnly")) - << (QStringList() << QLatin1String("QtGraphicalEffects")) - << (QStringList() - << QLatin1String(TESTSRCDIR "/003_packageQmlOnly/QtGraphicalEffects/ZoomBlur.qml") - << QLatin1String(TESTSRCDIR "/003_packageQmlOnly/QtGraphicalEffects/private/FastGlow.qml") - << QLatin1String(TESTSRCDIR "/003_packageQmlOnly/QtGraphicalEffects/private/GaussianInnerShadow.qml") - << QLatin1String(TESTSRCDIR "/003_packageQmlOnly/QtGraphicalEffects/private/SourceProxy.qml") - << QLatin1String(TESTSRCDIR "/003_packageQmlOnly/QtGraphicalEffects/GammaAdjust.qml") - << QLatin1String(TESTSRCDIR "/003_packageQmlOnly/QtGraphicalEffects/HueSaturation.qml") - << QLatin1String(TESTSRCDIR "/003_packageQmlOnly/QtGraphicalEffects/Colorize.qml") - << QLatin1String(TESTSRCDIR "/003_packageQmlOnly/QtGraphicalEffects/RadialBlur.qml") - << QLatin1String(TESTSRCDIR "/003_packageQmlOnly/QtGraphicalEffects/ColorOverlay.qml") - << QLatin1String(TESTSRCDIR "/003_packageQmlOnly/QtGraphicalEffects/MaskedBlur.qml") - << QLatin1String(TESTSRCDIR "/003_packageQmlOnly/QtGraphicalEffects/RectangularGlow.qml") - << QLatin1String(TESTSRCDIR "/003_packageQmlOnly/QtGraphicalEffects/Displace.qml") - << QLatin1String(TESTSRCDIR "/003_packageQmlOnly/QtGraphicalEffects/private/FastMaskedBlur.qml") - << QLatin1String(TESTSRCDIR "/003_packageQmlOnly/QtGraphicalEffects/Desaturate.qml") - << QLatin1String(TESTSRCDIR "/003_packageQmlOnly/QtGraphicalEffects/private/GaussianDirectionalBlur.qml") - << QLatin1String(TESTSRCDIR "/003_packageQmlOnly/QtGraphicalEffects/GaussianBlur.qml") - << QLatin1String(TESTSRCDIR "/003_packageQmlOnly/QtGraphicalEffects/InnerShadow.qml") - << QLatin1String(TESTSRCDIR "/003_packageQmlOnly/QtGraphicalEffects/LinearGradient.qml") - << QLatin1String(TESTSRCDIR "/003_packageQmlOnly/QtGraphicalEffects/Blend.qml") - << QLatin1String(TESTSRCDIR "/003_packageQmlOnly/QtGraphicalEffects/Glow.qml") - << QLatin1String(TESTSRCDIR "/003_packageQmlOnly/QtGraphicalEffects/RecursiveBlur.qml") - << QLatin1String(TESTSRCDIR "/003_packageQmlOnly/QtGraphicalEffects/private/GaussianMaskedBlur.qml") - << QLatin1String(TESTSRCDIR "/003_packageQmlOnly/QtGraphicalEffects/DropShadow.qml") - << QLatin1String(TESTSRCDIR "/003_packageQmlOnly/QtGraphicalEffects/DirectionalBlur.qml") - << QLatin1String(TESTSRCDIR "/003_packageQmlOnly/QtGraphicalEffects/OpacityMask.qml") - << QLatin1String(TESTSRCDIR "/003_packageQmlOnly/QtGraphicalEffects/BrightnessContrast.qml") - << QLatin1String(TESTSRCDIR "/003_packageQmlOnly/QtGraphicalEffects/private/GaussianGlow.qml") - << QLatin1String(TESTSRCDIR "/003_packageQmlOnly/QtGraphicalEffects/RadialGradient.qml") - << QLatin1String(TESTSRCDIR "/003_packageQmlOnly/QtGraphicalEffects/private/FastInnerShadow.qml") - << QLatin1String(TESTSRCDIR "/003_packageQmlOnly/QtGraphicalEffects/ConicalGradient.qml") - << QLatin1String(TESTSRCDIR "/003_packageQmlOnly/QtGraphicalEffects/ThresholdMask.qml") - << QLatin1String(TESTSRCDIR "/003_packageQmlOnly/QtGraphicalEffects/LevelAdjust.qml") - << QLatin1String(TESTSRCDIR "/003_packageQmlOnly/QtGraphicalEffects/FastBlur.qml")); - QTest::newRow("004_cppOnly copy") << QStringList(QLatin1String(TESTSRCDIR "004_cppOnly copy")) - << (QStringList() << QLatin1String("QML 1.0") - << QLatin1String("QtQml 2.2") - << QLatin1String("QtQml 2.1") - << QLatin1String("QtQuick 2.0") - << QLatin1String("QtQml 2.0") - << QLatin1String("QtQuick 2.-1") - << QLatin1String("QtQuick 2.1") - << QLatin1String("QtQuick 2.2") - << QLatin1String("<cpp>")) + /*QTest::newRow("003_packageQmlOnly") << QStringList(QString(TESTSRCDIR "/003_packageQmlOnly")) + << QStringList("QtGraphicalEffects") + << QStringList() + << QString(TESTSRCDIR "/003_packageQmlOnly/QtGraphicalEffects/ZoomBlur.qml") + << QString(TESTSRCDIR "/003_packageQmlOnly/QtGraphicalEffects/private/FastGlow.qml") + << QString(TESTSRCDIR "/003_packageQmlOnly/QtGraphicalEffects/private/GaussianInnerShadow.qml") + << QString(TESTSRCDIR "/003_packageQmlOnly/QtGraphicalEffects/private/SourceProxy.qml") + << QString(TESTSRCDIR "/003_packageQmlOnly/QtGraphicalEffects/GammaAdjust.qml") + << QString(TESTSRCDIR "/003_packageQmlOnly/QtGraphicalEffects/HueSaturation.qml") + << QString(TESTSRCDIR "/003_packageQmlOnly/QtGraphicalEffects/Colorize.qml") + << QString(TESTSRCDIR "/003_packageQmlOnly/QtGraphicalEffects/RadialBlur.qml") + << QString(TESTSRCDIR "/003_packageQmlOnly/QtGraphicalEffects/ColorOverlay.qml") + << QString(TESTSRCDIR "/003_packageQmlOnly/QtGraphicalEffects/MaskedBlur.qml") + << QString(TESTSRCDIR "/003_packageQmlOnly/QtGraphicalEffects/RectangularGlow.qml") + << QString(TESTSRCDIR "/003_packageQmlOnly/QtGraphicalEffects/Displace.qml") + << QString(TESTSRCDIR "/003_packageQmlOnly/QtGraphicalEffects/private/FastMaskedBlur.qml") + << QString(TESTSRCDIR "/003_packageQmlOnly/QtGraphicalEffects/Desaturate.qml") + << QString(TESTSRCDIR "/003_packageQmlOnly/QtGraphicalEffects/private/GaussianDirectionalBlur.qml") + << QString(TESTSRCDIR "/003_packageQmlOnly/QtGraphicalEffects/GaussianBlur.qml") + << QString(TESTSRCDIR "/003_packageQmlOnly/QtGraphicalEffects/InnerShadow.qml") + << QString(TESTSRCDIR "/003_packageQmlOnly/QtGraphicalEffects/LinearGradient.qml") + << QString(TESTSRCDIR "/003_packageQmlOnly/QtGraphicalEffects/Blend.qml") + << QString(TESTSRCDIR "/003_packageQmlOnly/QtGraphicalEffects/Glow.qml") + << QString(TESTSRCDIR "/003_packageQmlOnly/QtGraphicalEffects/RecursiveBlur.qml") + << QString(TESTSRCDIR "/003_packageQmlOnly/QtGraphicalEffects/private/GaussianMaskedBlur.qml") + << QString(TESTSRCDIR "/003_packageQmlOnly/QtGraphicalEffects/DropShadow.qml") + << QString(TESTSRCDIR "/003_packageQmlOnly/QtGraphicalEffects/DirectionalBlur.qml") + << QString(TESTSRCDIR "/003_packageQmlOnly/QtGraphicalEffects/OpacityMask.qml") + << QString(TESTSRCDIR "/003_packageQmlOnly/QtGraphicalEffects/BrightnessContrast.qml") + << QString(TESTSRCDIR "/003_packageQmlOnly/QtGraphicalEffects/private/GaussianGlow.qml") + << QString(TESTSRCDIR "/003_packageQmlOnly/QtGraphicalEffects/RadialGradient.qml") + << QString(TESTSRCDIR "/003_packageQmlOnly/QtGraphicalEffects/private/FastInnerShadow.qml") + << QString(TESTSRCDIR "/003_packageQmlOnly/QtGraphicalEffects/ConicalGradient.qml") + << QString(TESTSRCDIR "/003_packageQmlOnly/QtGraphicalEffects/ThresholdMask.qml") + << QString(TESTSRCDIR "/003_packageQmlOnly/QtGraphicalEffects/LevelAdjust.qml") + << QString(TESTSRCDIR "/003_packageQmlOnly/QtGraphicalEffects/FastBlur.qml")); + QTest::newRow("004_cppOnly copy") << QStringList(QString(TESTSRCDIR "004_cppOnly copy")) + << QStringList({ "QML 1.0", "QtQml 2.2", "QtQml 2.1", "QtQuick 2.0", + "QtQml 2.0", "QtQuick 2.-1", "QtQuick 2.1", + "QtQuick 2.2", "<cpp>" }) << QStringList();*/ } diff --git a/tests/auto/qml/persistenttrie/persistenttrie.pro b/tests/auto/qml/persistenttrie/persistenttrie.pro index ccaa5da46a..5e3c7169ac 100644 --- a/tests/auto/qml/persistenttrie/persistenttrie.pro +++ b/tests/auto/qml/persistenttrie/persistenttrie.pro @@ -12,7 +12,7 @@ SOURCES += \ tst_testtrie.cpp TEMPLATE = app -DEFINES += QMLJS_BUILD_DIR +DEFINES += QMLJS_LIBRARY DISTFILES += \ listAll.data \ diff --git a/tests/auto/qml/persistenttrie/persistenttrie.qbs b/tests/auto/qml/persistenttrie/persistenttrie.qbs index 0e07e49423..9f03227ee7 100644 --- a/tests/auto/qml/persistenttrie/persistenttrie.qbs +++ b/tests/auto/qml/persistenttrie/persistenttrie.qbs @@ -5,7 +5,7 @@ QtcAutotest { Depends { name: "QmlJS" } files: [ "tst_testtrie.h", "tst_testtrie.cpp" ] cpp.defines: base.concat([ - 'QMLJS_BUILD_DIR', + 'QMLJS_LIBRARY', 'QTCREATORDIR="' + project.ide_source_tree + '"', 'TESTSRCDIR="' + path + '"' ]) diff --git a/tests/auto/qml/qmldesigner/coretests/coretests.pro b/tests/auto/qml/qmldesigner/coretests/coretests.pro index 2dfb141852..bdf97a1ce0 100644 --- a/tests/auto/qml/qmldesigner/coretests/coretests.pro +++ b/tests/auto/qml/qmldesigner/coretests/coretests.pro @@ -1,6 +1,11 @@ QTC_LIB_DEPENDS += \ utils \ qmljs \ + qmleditorwidgets + +QTC_LIB_DEPENDS += \ + utils \ + qmljs \ qmleditorwidgets \ cplusplus diff --git a/tests/auto/qml/qmldesigner/coretests/tst_testcore.cpp b/tests/auto/qml/qmldesigner/coretests/tst_testcore.cpp index 5700ea6ddc..177df3a4f3 100644 --- a/tests/auto/qml/qmldesigner/coretests/tst_testcore.cpp +++ b/tests/auto/qml/qmldesigner/coretests/tst_testcore.cpp @@ -380,11 +380,6 @@ void tst_TestCore::saveEmptyCoreModel() testRewriterView1->setTextModifier(&modifier1); model1->attachView(testRewriterView1.data()); - - QBuffer buffer; - buffer.open(QIODevice::ReadWrite | QIODevice::Text); - modifier1.save(&buffer); - QPlainTextEdit textEdit2; textEdit2.setPlainText("import QtQuick 1.1; Item{}"); NotIndentingTextEditModifier modifier2(&textEdit2); @@ -396,7 +391,6 @@ void tst_TestCore::saveEmptyCoreModel() model2->attachView(testRewriterView2.data()); QVERIFY(compareTree(testRewriterView1->rootModelNode(), testRewriterView2->rootModelNode())); - } void tst_TestCore::loadAttributesInCoreModel() @@ -453,7 +447,7 @@ void tst_TestCore::saveAttributesInCoreModel() QBuffer buffer; buffer.open(QIODevice::ReadWrite | QIODevice::Text); - modifier1.save(&buffer); + buffer.write(modifier1.textDocument()->toPlainText().toUtf8()); QPlainTextEdit textEdit2; textEdit2.setPlainText(QString::fromUtf8(buffer.data())); @@ -999,6 +993,37 @@ void tst_TestCore::testRewriterChangeImports() QCOMPARE(model->imports().first(), Import::createLibraryImport("QtQuick", "1.1")); } +void tst_TestCore::testRewriterUnicodeChars() +{ + const QLatin1String qmlString("\n" + "import QtQuick 2.1\n" + "\n" + "Text {\n" + " text: \"test\"" + "}\n"); + + QPlainTextEdit textEdit; + textEdit.setPlainText(qmlString); + NotIndentingTextEditModifier modifier(&textEdit); + + QScopedPointer<Model> model(Model::create("QtQuick.Rectangle")); + + QScopedPointer<TestRewriterView> testRewriterView(new TestRewriterView(0, RewriterView::Amend)); + testRewriterView->setTextModifier(&modifier); + model->attachView(testRewriterView.data()); + + QVERIFY(testRewriterView->errors().isEmpty()); + + ModelNode rootModelNode = testRewriterView->rootModelNode(); + QVERIFY(rootModelNode.isValid()); + + rootModelNode.variantProperty("text").setValue("\\u2795"); + + const QLatin1String unicodeChar("\nimport QtQuick 2.1\n\nText {\n text: \"\\u2795\"}\n"); + + QCOMPARE(textEdit.toPlainText(), unicodeChar); +} + void tst_TestCore::testRewriterForGradientMagic() { const QLatin1String qmlString("\n" @@ -1099,11 +1124,12 @@ void tst_TestCore::loadSubItems() void tst_TestCore::createInvalidCoreModel() { + QSKIP("no direct type checking in model atm", SkipAll); QScopedPointer<Model> invalidModel(createModel("ItemSUX")); - //QVERIFY(!invalidModel.data()); //#no direct ype checking in model atm + QVERIFY(!invalidModel.data()); QScopedPointer<Model> invalidModel2(createModel("InvalidNode")); - //QVERIFY(!invalidModel2.data()); + QVERIFY(!invalidModel2.data()); } void tst_TestCore::testModelCreateSubNode() @@ -3928,7 +3954,7 @@ char qmlString[] = "import QtQuick 2.1\n" "text: \"Hello World\"\n" "anchors.centerIn: parent\n" "Item {\n" - "id: item\n" + "id: item01\n" "}\n" "}\n" "Rectangle {\n" @@ -3995,7 +4021,7 @@ char qmlString[] = "import QtQuick 2.1\n" QVERIFY(!textNode1.nodeListProperty("data").toModelNodeList().isEmpty()); ModelNode itemNode = textNode1.nodeListProperty("data").toModelNodeList().first(); QVERIFY(itemNode.isValid()); - QCOMPARE(itemNode.id(), QString("item")); + QCOMPARE(itemNode.id(), QString("item01")); QVERIFY(!itemNode.hasProperty("data")); ModelNode rectNode = rootModelNode.nodeListProperty("data").toModelNodeList().at(1); @@ -4184,7 +4210,7 @@ void tst_TestCore::testMetaInfoQtQuick1Vs2() "text: \"Hello World\"\n" "anchors.centerIn: parent\n" "Item {\n" - "id: item\n" + "id: item01\n" "}\n" "}\n" "Rectangle {\n" @@ -6148,6 +6174,95 @@ void tst_TestCore::testModelNodeIsAncestorOf() QVERIFY(item3.isAncestorOf(item4)); } +void tst_TestCore::testModelChangeType() +{ + const QLatin1String qmlString("\n" + "import QtQuick 2.1\n" + "\n" + "Rectangle {\n" + " id: rootItem\n" + " Item {\n" + " id: firstItem\n" + " x: 10\n" + " }\n" + " Item {\n" + " id: secondItem\n" + " x: 20\n" + " }\n" + "}"); + QPlainTextEdit textEdit; + textEdit.setPlainText(qmlString); + NotIndentingTextEditModifier textModifier(&textEdit); + + QScopedPointer<Model> model(Model::create("QtQuick.Item", 2, 1)); + QVERIFY(model.data()); + + QScopedPointer<TestView> view(new TestView(model.data())); + model->attachView(view.data()); + + // read in + QScopedPointer<TestRewriterView> testRewriterView(new TestRewriterView()); + testRewriterView->setTextModifier(&textModifier); + model->attachView(testRewriterView.data()); + + ModelNode rootNode = view->rootModelNode(); + QVERIFY(rootNode.isValid()); + QCOMPARE(rootNode.type(), QmlDesigner::TypeName("QtQuick.Rectangle")); + QCOMPARE(rootNode.id(), QLatin1String("rootItem")); + + ModelNode childNode = rootNode.nodeListProperty(("data")).toModelNodeList().at(0); + QVERIFY(childNode.isValid()); + QCOMPARE(childNode.type(), QmlDesigner::TypeName("QtQuick.Item")); + QCOMPARE(childNode.id(), QLatin1String("firstItem")); + + childNode.changeType("QtQuick.Rectangle", 2, 0); + + QCOMPARE(childNode.type(), QmlDesigner::TypeName("QtQuick.Rectangle")); + + const QLatin1String expectedQmlCode1("\n" + "import QtQuick 2.1\n" + "\n" + "Rectangle {\n" + " id: rootItem\n" + " Rectangle {\n" + " id: firstItem\n" + " x: 10\n" + " }\n" + " Item {\n" + " id: secondItem\n" + " x: 20\n" + " }\n" + "}"); + + QCOMPARE(textEdit.toPlainText(), expectedQmlCode1); + + childNode = rootNode.nodeListProperty(("data")).toModelNodeList().at(1); + QVERIFY(childNode.isValid()); + QCOMPARE(childNode.type(), QmlDesigner::TypeName("QtQuick.Item")); + QCOMPARE(childNode.id(), QLatin1String("secondItem")); + + childNode.changeType("QtQuick.Rectangle", 2, 0); + + QCOMPARE(childNode.type(), QmlDesigner::TypeName("QtQuick.Rectangle")); + + const QLatin1String expectedQmlCode2("\n" + "import QtQuick 2.1\n" + "\n" + "Rectangle {\n" + " id: rootItem\n" + " Rectangle {\n" + " id: firstItem\n" + " x: 10\n" + " }\n" + " Rectangle {\n" + " id: secondItem\n" + " x: 20\n" + " }\n" + "}"); + + QCOMPARE(textEdit.toPlainText(), expectedQmlCode2); +} + void tst_TestCore::testModelDefaultProperties() { QScopedPointer<Model> model(createModel("QtQuick.Rectangle", 2, 0)); @@ -7878,7 +7993,7 @@ void tst_TestCore::loadTestFiles() ModelNode textNode(rootModelNode.nodeListProperty("data").toModelNodeList().first()); QVERIFY(textNode.isValid()); - QCOMPARE(textNode.id(), QLatin1String("text")); + QCOMPARE(textNode.id(), QLatin1String("textElement")); QCOMPARE(textNode.type(), QmlDesigner::TypeName("QtQuick.Text")); QCOMPARE(textNode.variantProperty("x").value().toInt(), 66); QCOMPARE(textNode.variantProperty("y").value().toInt(), 93); diff --git a/tests/auto/qml/qmldesigner/coretests/tst_testcore.h b/tests/auto/qml/qmldesigner/coretests/tst_testcore.h index f846c1963e..b3d47fbb72 100644 --- a/tests/auto/qml/qmldesigner/coretests/tst_testcore.h +++ b/tests/auto/qml/qmldesigner/coretests/tst_testcore.h @@ -87,6 +87,7 @@ private slots: void testModelPropertyValueTypes(); void testModelNodeInHierarchy(); void testModelNodeIsAncestorOf(); + void testModelChangeType(); // // unit tests Rewriter @@ -138,6 +139,7 @@ private slots: void testRewriterActionCompression(); void testRewriterImports(); void testRewriterChangeImports(); + void testRewriterUnicodeChars(); // // unit tests QmlModelNodeFacade/QmlModelState diff --git a/tests/auto/qml/qmldesigner/data/fx/states.qml b/tests/auto/qml/qmldesigner/data/fx/states.qml index 3ad8dc1be0..91e7348d24 100644 --- a/tests/auto/qml/qmldesigner/data/fx/states.qml +++ b/tests/auto/qml/qmldesigner/data/fx/states.qml @@ -30,7 +30,7 @@ Rectangle { width: 200 height: 200 Text { - id: text + id: textElement x: 66 y: 93 text: "Base State" diff --git a/tests/auto/qml/qmldesigner/testview.cpp b/tests/auto/qml/qmldesigner/testview.cpp index b7a3023307..23c50599c7 100644 --- a/tests/auto/qml/qmldesigner/testview.cpp +++ b/tests/auto/qml/qmldesigner/testview.cpp @@ -167,7 +167,7 @@ void TestView::nodeOrderChanged(const QmlDesigner::NodeListProperty &listPropert m_methodCalls += MethodCall("nodeOrderChanged", QStringList() << QString::fromUtf8(listProperty.name()) << movedNode.id() << QString::number(oldIndex)); } -void TestView::instancePropertyChange(const QList<QPair<QmlDesigner::ModelNode, QmlDesigner::PropertyName> > &) +void TestView::instancePropertyChanged(const QList<QPair<QmlDesigner::ModelNode, QmlDesigner::PropertyName> > &) { } @@ -177,7 +177,7 @@ void TestView::instancesCompleted(const QVector<QmlDesigner::ModelNode> &) } -void TestView::instanceInformationsChange(const QMultiHash<QmlDesigner::ModelNode, QmlDesigner::InformationName> &) +void TestView::instanceInformationsChanged(const QMultiHash<QmlDesigner::ModelNode, QmlDesigner::InformationName> &) { } diff --git a/tests/auto/qml/qmldesigner/testview.h b/tests/auto/qml/qmldesigner/testview.h index dba423a63b..9a78611488 100644 --- a/tests/auto/qml/qmldesigner/testview.h +++ b/tests/auto/qml/qmldesigner/testview.h @@ -76,9 +76,9 @@ public: void nodeOrderChanged(const QmlDesigner::NodeListProperty &listProperty, const QmlDesigner::ModelNode &movedNode, int oldIndex); - virtual void instancePropertyChange(const QList<QPair<QmlDesigner::ModelNode, QmlDesigner::PropertyName> > &propertyList); + virtual void instancePropertyChanged(const QList<QPair<QmlDesigner::ModelNode, QmlDesigner::PropertyName> > &propertyList); virtual void instancesCompleted(const QVector<QmlDesigner::ModelNode> &completedNodeList); - virtual void instanceInformationsChange(const QMultiHash<QmlDesigner::ModelNode, QmlDesigner::InformationName> &informationChangeHash); + virtual void instanceInformationsChanged(const QMultiHash<QmlDesigner::ModelNode, QmlDesigner::InformationName> &informationChangeHash); virtual void instancesRenderImageChanged(const QVector<QmlDesigner::ModelNode> &nodeList); virtual void instancesPreviewImageChanged(const QVector<QmlDesigner::ModelNode> &nodeList); virtual void instancesChildrenChanged(const QVector<QmlDesigner::ModelNode> &nodeList); diff --git a/tests/auto/qml/qrcparser/tst_qrcparser.cpp b/tests/auto/qml/qrcparser/tst_qrcparser.cpp index 72d425a4e8..d8c3f03c36 100644 --- a/tests/auto/qml/qrcparser/tst_qrcparser.cpp +++ b/tests/auto/qml/qrcparser/tst_qrcparser.cpp @@ -162,18 +162,10 @@ void tst_QrcParser::simpleTest() QrcParser::Ptr p = QrcParser::parseQrcFile(QString::fromLatin1(TESTSRCDIR).append(QLatin1String("/simple.qrc")), QString()); QStringList paths = allPaths(p); paths.sort(); - QVERIFY(paths == QStringList() - << QLatin1String("/") - << QLatin1String("/cut.jpg") - << QLatin1String("/images/") - << QLatin1String("/images/copy.png") - << QLatin1String("/images/cut.png") - << QLatin1String("/images/new.png") - << QLatin1String("/images/open.png") - << QLatin1String("/images/paste.png") - << QLatin1String("/images/save.png") - << QLatin1String("/myresources/") - << QLatin1String("/myresources/cut-img.png")); + QVERIFY(paths == QStringList({ "/", "/cut.jpg", "/images/", "/images/copy.png", + "/images/cut.png", "/images/new.png", "/images/open.png", + "/images/paste.png", "/images/save.png", "/myresources/", + "/myresources/cut-img.png" })); QString frPath = p->firstFileAtPath(QLatin1String("/cut.jpg"), QLocale(QLatin1String("fr_FR"))); QString refFrPath = QString::fromLatin1(TESTSRCDIR).append(QLatin1String("/cut_fr.jpg")); QCOMPARE(frPath, refFrPath); diff --git a/tests/auto/qml/reformatter/comments.qml b/tests/auto/qml/reformatter/comments.qml new file mode 100644 index 0000000000..61889ea007 --- /dev/null +++ b/tests/auto/qml/reformatter/comments.qml @@ -0,0 +1,16 @@ +import QtQuick 2.0 + + +/* Comment 1 + This is a multiline comment. */ + +/* + Another multiline comment. + + A slightly different formatting. +*/ +Item { + /* + Indented multiline comment. + */ +} diff --git a/tests/auto/qml/reformatter/reformatter.pro b/tests/auto/qml/reformatter/reformatter.pro index f4eb2fc3ee..ba3a673b71 100644 --- a/tests/auto/qml/reformatter/reformatter.pro +++ b/tests/auto/qml/reformatter/reformatter.pro @@ -8,3 +8,11 @@ TARGET = tst_reformatter SOURCES += \ tst_reformatter.cpp + +DISTFILES += \ + jssyntax.js \ + objectliteral.js \ + qmlreadonly.qml \ + qmlsingleton.qml \ + qmlsyntax.qml \ + comments.qml diff --git a/tests/auto/qtcprocess/tst_qtcprocess.cpp b/tests/auto/qtcprocess/tst_qtcprocess.cpp index d5fbb42a18..e789203fbc 100644 --- a/tests/auto/qtcprocess/tst_qtcprocess.cpp +++ b/tests/auto/qtcprocess/tst_qtcprocess.cpp @@ -140,39 +140,39 @@ void tst_QtcProcess::splitArgs_data() const QtcProcess::SplitError err; const OsType os; } vals[] = { - { "", "", QtcProcess::SplitOk, OsTypeWindows }, - { " ", "", QtcProcess::SplitOk, OsTypeWindows }, - { "hi", "hi", QtcProcess::SplitOk, OsTypeWindows }, - { "hi ho", "hi ho", QtcProcess::SplitOk, OsTypeWindows }, - { " hi ho ", "hi ho", QtcProcess::SplitOk, OsTypeWindows }, - { "\"hi ho\" \"hi\" ho ", "\"hi ho\" hi ho", QtcProcess::SplitOk, OsTypeWindows }, - { "\\", "\\", QtcProcess::SplitOk, OsTypeWindows }, - { "\\\"", "\"\"\\^\"\"\"", QtcProcess::SplitOk, OsTypeWindows }, - { "\"hi\"\"\"ho\"", "\"hi\"\\^\"\"ho\"", QtcProcess::SplitOk, OsTypeWindows }, - { "\\\\\\\"", "\"\"\\\\\\^\"\"\"", QtcProcess::SplitOk, OsTypeWindows }, - { " ^^ ", "\"^^\"", QtcProcess::SplitOk, OsTypeWindows }, - { "hi\"", "", QtcProcess::BadQuoting, OsTypeWindows }, - { "hi\"dood", "", QtcProcess::BadQuoting, OsTypeWindows }, - { "%var%", "%var%", QtcProcess::SplitOk, OsTypeWindows }, - - { "", "", QtcProcess::SplitOk, OsTypeLinux }, - { " ", "", QtcProcess::SplitOk, OsTypeLinux }, - { "hi", "hi", QtcProcess::SplitOk, OsTypeLinux }, - { "hi ho", "hi ho", QtcProcess::SplitOk, OsTypeLinux }, - { " hi ho ", "hi ho", QtcProcess::SplitOk, OsTypeLinux }, - { "'hi ho' \"hi\" ho ", "'hi ho' hi ho", QtcProcess::SplitOk, OsTypeLinux }, - { " \\ ", "' '", QtcProcess::SplitOk, OsTypeLinux }, - { " \\\" ", "'\"'", QtcProcess::SplitOk, OsTypeLinux }, - { " '\"' ", "'\"'", QtcProcess::SplitOk, OsTypeLinux }, - { " \"\\\"\" ", "'\"'", QtcProcess::SplitOk, OsTypeLinux }, - { "hi'", "", QtcProcess::BadQuoting, OsTypeLinux }, - { "hi\"dood", "", QtcProcess::BadQuoting, OsTypeLinux }, - { "$var", "'$var'", QtcProcess::SplitOk, OsTypeLinux }, - { "~", "@HOME@", QtcProcess::SplitOk, OsTypeLinux }, - { "~ foo", "@HOME@ foo", QtcProcess::SplitOk, OsTypeLinux }, - { "foo ~", "foo @HOME@", QtcProcess::SplitOk, OsTypeLinux }, - { "~/foo", "@HOME@/foo", QtcProcess::SplitOk, OsTypeLinux }, - { "~foo", "'~foo'", QtcProcess::SplitOk, OsTypeLinux } + {"", "", QtcProcess::SplitOk, OsTypeWindows}, + {" ", "", QtcProcess::SplitOk, OsTypeWindows}, + {"hi", "hi", QtcProcess::SplitOk, OsTypeWindows}, + {"hi ho", "hi ho", QtcProcess::SplitOk, OsTypeWindows}, + {" hi ho ", "hi ho", QtcProcess::SplitOk, OsTypeWindows}, + {"\"hi ho\" \"hi\" ho ", "\"hi ho\" hi ho", QtcProcess::SplitOk, OsTypeWindows}, + {"\\", "\\", QtcProcess::SplitOk, OsTypeWindows}, + {"\\\"", "\"\"\\^\"\"\"", QtcProcess::SplitOk, OsTypeWindows}, + {"\"hi\"\"\"ho\"", "\"hi\"\\^\"\"ho\"", QtcProcess::SplitOk, OsTypeWindows}, + {"\\\\\\\"", "\"\"\\\\\\^\"\"\"", QtcProcess::SplitOk, OsTypeWindows}, + {" ^^ ", "\"^^\"", QtcProcess::SplitOk, OsTypeWindows}, + {"hi\"", "", QtcProcess::BadQuoting, OsTypeWindows}, + {"hi\"dood", "", QtcProcess::BadQuoting, OsTypeWindows}, + {"%var%", "%var%", QtcProcess::SplitOk, OsTypeWindows}, + + {"", "", QtcProcess::SplitOk, OsTypeLinux}, + {" ", "", QtcProcess::SplitOk, OsTypeLinux}, + {"hi", "hi", QtcProcess::SplitOk, OsTypeLinux}, + {"hi ho", "hi ho", QtcProcess::SplitOk, OsTypeLinux}, + {" hi ho ", "hi ho", QtcProcess::SplitOk, OsTypeLinux}, + {"'hi ho' \"hi\" ho ", "'hi ho' hi ho", QtcProcess::SplitOk, OsTypeLinux}, + {" \\ ", "' '", QtcProcess::SplitOk, OsTypeLinux}, + {" \\\" ", "'\"'", QtcProcess::SplitOk, OsTypeLinux}, + {" '\"' ", "'\"'", QtcProcess::SplitOk, OsTypeLinux}, + {" \"\\\"\" ", "'\"'", QtcProcess::SplitOk, OsTypeLinux}, + {"hi'", "", QtcProcess::BadQuoting, OsTypeLinux}, + {"hi\"dood", "", QtcProcess::BadQuoting, OsTypeLinux}, + {"$var", "'$var'", QtcProcess::SplitOk, OsTypeLinux}, + {"~", "@HOME@", QtcProcess::SplitOk, OsTypeLinux}, + {"~ foo", "@HOME@ foo", QtcProcess::SplitOk, OsTypeLinux}, + {"foo ~", "foo @HOME@", QtcProcess::SplitOk, OsTypeLinux}, + {"~/foo", "@HOME@/foo", QtcProcess::SplitOk, OsTypeLinux}, + {"~foo", "'~foo'", QtcProcess::SplitOk, OsTypeLinux} }; for (unsigned i = 0; i < sizeof(vals)/sizeof(vals[0]); i++) { @@ -211,36 +211,36 @@ void tst_QtcProcess::prepareArgs_data() const QtcProcess::SplitError err; const OsType os; } vals[] = { - { " ", " ", QtcProcess::SplitOk, OsTypeWindows }, - { "", "", QtcProcess::SplitOk, OsTypeWindows }, - { "hi", "hi", QtcProcess::SplitOk, OsTypeWindows }, - { "hi ho", "hi ho", QtcProcess::SplitOk, OsTypeWindows }, - { " hi ho ", " hi ho ", QtcProcess::SplitOk, OsTypeWindows }, - { "\"hi ho\" \"hi\" ho ", "\"hi ho\" \"hi\" ho ", QtcProcess::SplitOk, OsTypeWindows }, - { "\\", "\\", QtcProcess::SplitOk, OsTypeWindows }, - { "\\\"", "\\\"", QtcProcess::SplitOk, OsTypeWindows }, - { "\"hi\"\"ho\"", "\"hi\"\"ho\"", QtcProcess::SplitOk, OsTypeWindows }, - { "\\\\\\\"", "\\\\\\\"", QtcProcess::SplitOk, OsTypeWindows }, - { "^^", "^", QtcProcess::SplitOk, OsTypeWindows }, - { "hi\"", "hi\"", QtcProcess::SplitOk, OsTypeWindows }, - { "hi\"dood", "hi\"dood", QtcProcess::SplitOk, OsTypeWindows }, - { "%var%", "", QtcProcess::FoundMeta, OsTypeWindows }, - { "echo hi > file", "", QtcProcess::FoundMeta, OsTypeWindows }, - - { "", "", QtcProcess::SplitOk, OsTypeLinux }, - { " ", "", QtcProcess::SplitOk, OsTypeLinux }, - { "hi", "hi", QtcProcess::SplitOk, OsTypeLinux }, - { "hi ho", "hi ho", QtcProcess::SplitOk, OsTypeLinux }, - { " hi ho ", "hi ho", QtcProcess::SplitOk, OsTypeLinux }, - { "'hi ho' \"hi\" ho ", "'hi ho' hi ho", QtcProcess::SplitOk, OsTypeLinux }, - { " \\ ", "' '", QtcProcess::SplitOk, OsTypeLinux }, - { "hi'", "", QtcProcess::BadQuoting, OsTypeLinux }, - { "hi\"dood", "", QtcProcess::BadQuoting, OsTypeLinux }, - { "$var", "", QtcProcess::FoundMeta, OsTypeLinux }, - { "~", "@HOME@", QtcProcess::SplitOk, OsTypeLinux }, - { "~ foo", "@HOME@ foo", QtcProcess::SplitOk, OsTypeLinux }, - { "~/foo", "@HOME@/foo", QtcProcess::SplitOk, OsTypeLinux }, - { "~foo", "", QtcProcess::FoundMeta, OsTypeLinux } + {" ", " ", QtcProcess::SplitOk, OsTypeWindows}, + {"", "", QtcProcess::SplitOk, OsTypeWindows}, + {"hi", "hi", QtcProcess::SplitOk, OsTypeWindows}, + {"hi ho", "hi ho", QtcProcess::SplitOk, OsTypeWindows}, + {" hi ho ", " hi ho ", QtcProcess::SplitOk, OsTypeWindows}, + {"\"hi ho\" \"hi\" ho ", "\"hi ho\" \"hi\" ho ", QtcProcess::SplitOk, OsTypeWindows}, + {"\\", "\\", QtcProcess::SplitOk, OsTypeWindows}, + {"\\\"", "\\\"", QtcProcess::SplitOk, OsTypeWindows}, + {"\"hi\"\"ho\"", "\"hi\"\"ho\"", QtcProcess::SplitOk, OsTypeWindows}, + {"\\\\\\\"", "\\\\\\\"", QtcProcess::SplitOk, OsTypeWindows}, + {"^^", "^", QtcProcess::SplitOk, OsTypeWindows}, + {"hi\"", "hi\"", QtcProcess::SplitOk, OsTypeWindows}, + {"hi\"dood", "hi\"dood", QtcProcess::SplitOk, OsTypeWindows}, + {"%var%", "", QtcProcess::FoundMeta, OsTypeWindows}, + {"echo hi > file", "", QtcProcess::FoundMeta, OsTypeWindows}, + + {"", "", QtcProcess::SplitOk, OsTypeLinux}, + {" ", "", QtcProcess::SplitOk, OsTypeLinux}, + {"hi", "hi", QtcProcess::SplitOk, OsTypeLinux}, + {"hi ho", "hi ho", QtcProcess::SplitOk, OsTypeLinux}, + {" hi ho ", "hi ho", QtcProcess::SplitOk, OsTypeLinux}, + {"'hi ho' \"hi\" ho ", "'hi ho' hi ho", QtcProcess::SplitOk, OsTypeLinux}, + {" \\ ", "' '", QtcProcess::SplitOk, OsTypeLinux}, + {"hi'", "", QtcProcess::BadQuoting, OsTypeLinux}, + {"hi\"dood", "", QtcProcess::BadQuoting, OsTypeLinux}, + {"$var", "", QtcProcess::FoundMeta, OsTypeLinux}, + {"~", "@HOME@", QtcProcess::SplitOk, OsTypeLinux}, + {"~ foo", "@HOME@ foo", QtcProcess::SplitOk, OsTypeLinux}, + {"~/foo", "@HOME@/foo", QtcProcess::SplitOk, OsTypeLinux}, + {"~foo", "", QtcProcess::FoundMeta, OsTypeLinux} }; for (unsigned i = 0; i < sizeof(vals)/sizeof(vals[0]); i++) { @@ -281,56 +281,56 @@ void tst_QtcProcess::prepareArgsEnv_data() const QtcProcess::SplitError err; const OsType os; } vals[] = { - { " ", " ", QtcProcess::SplitOk, OsTypeWindows }, - { "", "", QtcProcess::SplitOk, OsTypeWindows }, - { "hi", "hi", QtcProcess::SplitOk, OsTypeWindows }, - { "hi ho", "hi ho", QtcProcess::SplitOk, OsTypeWindows }, - { " hi ho ", " hi ho ", QtcProcess::SplitOk, OsTypeWindows }, - { "\"hi ho\" \"hi\" ho ", "\"hi ho\" \"hi\" ho ", QtcProcess::SplitOk, OsTypeWindows }, - { "\\", "\\", QtcProcess::SplitOk, OsTypeWindows }, - { "\\\"", "\\\"", QtcProcess::SplitOk, OsTypeWindows }, - { "\"hi\"\"ho\"", "\"hi\"\"ho\"", QtcProcess::SplitOk, OsTypeWindows }, - { "\\\\\\\"", "\\\\\\\"", QtcProcess::SplitOk, OsTypeWindows }, - { "^^", "^", QtcProcess::SplitOk, OsTypeWindows }, - { "hi\"", "hi\"", QtcProcess::SplitOk, OsTypeWindows }, - { "hi\"dood", "hi\"dood", QtcProcess::SplitOk, OsTypeWindows }, - { "%empty%", "%empty%", QtcProcess::SplitOk, OsTypeWindows }, // Yep, no empty variables on Windows. - { "%word%", "hi", QtcProcess::SplitOk, OsTypeWindows }, - { " %word% ", " hi ", QtcProcess::SplitOk, OsTypeWindows }, - { "%words%", "hi ho", QtcProcess::SplitOk, OsTypeWindows }, - { "%nonsense%words%", "%nonsensehi ho", QtcProcess::SplitOk, OsTypeWindows }, - { "fail%nonsense%words%", "fail%nonsensehi ho", QtcProcess::SplitOk, OsTypeWindows }, - { "%words%words%", "hi howords%", QtcProcess::SplitOk, OsTypeWindows }, - { "%words%%words%", "hi hohi ho", QtcProcess::SplitOk, OsTypeWindows }, - { "echo hi > file", "", QtcProcess::FoundMeta, OsTypeWindows }, - - { "", "", QtcProcess::SplitOk, OsTypeLinux }, - { " ", "", QtcProcess::SplitOk, OsTypeLinux }, - { "hi", "hi", QtcProcess::SplitOk, OsTypeLinux }, - { "hi ho", "hi ho", QtcProcess::SplitOk, OsTypeLinux }, - { " hi ho ", "hi ho", QtcProcess::SplitOk, OsTypeLinux }, - { "'hi ho' \"hi\" ho ", "'hi ho' hi ho", QtcProcess::SplitOk, OsTypeLinux }, - { " \\ ", "' '", QtcProcess::SplitOk, OsTypeLinux }, - { "hi'", "", QtcProcess::BadQuoting, OsTypeLinux }, - { "hi\"dood", "", QtcProcess::BadQuoting, OsTypeLinux }, - { "$empty", "", QtcProcess::SplitOk, OsTypeLinux }, - { "$word", "hi", QtcProcess::SplitOk, OsTypeLinux }, - { " $word ", "hi", QtcProcess::SplitOk, OsTypeLinux }, - { "${word}", "hi", QtcProcess::SplitOk, OsTypeLinux }, - { " ${word} ", "hi", QtcProcess::SplitOk, OsTypeLinux }, - { "$words", "hi ho", QtcProcess::SplitOk, OsTypeLinux }, - { "$spacedwords", "hi ho sucker", QtcProcess::SplitOk, OsTypeLinux }, - { "hi${empty}ho", "hiho", QtcProcess::SplitOk, OsTypeLinux }, - { "hi${words}ho", "hihi hoho", QtcProcess::SplitOk, OsTypeLinux }, - { "hi${spacedwords}ho", "hi hi ho sucker ho", QtcProcess::SplitOk, OsTypeLinux }, - { "${", "", QtcProcess::BadQuoting, OsTypeLinux }, - { "${var", "", QtcProcess::BadQuoting, OsTypeLinux }, - { "${var ", "", QtcProcess::FoundMeta, OsTypeLinux }, - { "\"hi${words}ho\"", "'hihi hoho'", QtcProcess::SplitOk, OsTypeLinux }, - { "\"hi${spacedwords}ho\"", "'hi hi ho sucker ho'", QtcProcess::SplitOk, OsTypeLinux }, - { "\"${", "", QtcProcess::BadQuoting, OsTypeLinux }, - { "\"${var", "", QtcProcess::BadQuoting, OsTypeLinux }, - { "\"${var ", "", QtcProcess::FoundMeta, OsTypeLinux }, + {" ", " ", QtcProcess::SplitOk, OsTypeWindows}, + {"", "", QtcProcess::SplitOk, OsTypeWindows}, + {"hi", "hi", QtcProcess::SplitOk, OsTypeWindows}, + {"hi ho", "hi ho", QtcProcess::SplitOk, OsTypeWindows}, + {" hi ho ", " hi ho ", QtcProcess::SplitOk, OsTypeWindows}, + {"\"hi ho\" \"hi\" ho ", "\"hi ho\" \"hi\" ho ", QtcProcess::SplitOk, OsTypeWindows}, + {"\\", "\\", QtcProcess::SplitOk, OsTypeWindows}, + {"\\\"", "\\\"", QtcProcess::SplitOk, OsTypeWindows}, + {"\"hi\"\"ho\"", "\"hi\"\"ho\"", QtcProcess::SplitOk, OsTypeWindows}, + {"\\\\\\\"", "\\\\\\\"", QtcProcess::SplitOk, OsTypeWindows}, + {"^^", "^", QtcProcess::SplitOk, OsTypeWindows}, + {"hi\"", "hi\"", QtcProcess::SplitOk, OsTypeWindows}, + {"hi\"dood", "hi\"dood", QtcProcess::SplitOk, OsTypeWindows}, + {"%empty%", "%empty%", QtcProcess::SplitOk, OsTypeWindows}, // Yep, no empty variables on Windows. + {"%word%", "hi", QtcProcess::SplitOk, OsTypeWindows}, + {" %word% ", " hi ", QtcProcess::SplitOk, OsTypeWindows}, + {"%words%", "hi ho", QtcProcess::SplitOk, OsTypeWindows}, + {"%nonsense%words%", "%nonsensehi ho", QtcProcess::SplitOk, OsTypeWindows}, + {"fail%nonsense%words%", "fail%nonsensehi ho", QtcProcess::SplitOk, OsTypeWindows}, + {"%words%words%", "hi howords%", QtcProcess::SplitOk, OsTypeWindows}, + {"%words%%words%", "hi hohi ho", QtcProcess::SplitOk, OsTypeWindows}, + {"echo hi > file", "", QtcProcess::FoundMeta, OsTypeWindows}, + + {"", "", QtcProcess::SplitOk, OsTypeLinux}, + {" ", "", QtcProcess::SplitOk, OsTypeLinux}, + {"hi", "hi", QtcProcess::SplitOk, OsTypeLinux}, + {"hi ho", "hi ho", QtcProcess::SplitOk, OsTypeLinux}, + {" hi ho ", "hi ho", QtcProcess::SplitOk, OsTypeLinux}, + {"'hi ho' \"hi\" ho ", "'hi ho' hi ho", QtcProcess::SplitOk, OsTypeLinux}, + {" \\ ", "' '", QtcProcess::SplitOk, OsTypeLinux}, + {"hi'", "", QtcProcess::BadQuoting, OsTypeLinux}, + {"hi\"dood", "", QtcProcess::BadQuoting, OsTypeLinux}, + {"$empty", "", QtcProcess::SplitOk, OsTypeLinux}, + {"$word", "hi", QtcProcess::SplitOk, OsTypeLinux}, + {" $word ", "hi", QtcProcess::SplitOk, OsTypeLinux}, + {"${word}", "hi", QtcProcess::SplitOk, OsTypeLinux}, + {" ${word} ", "hi", QtcProcess::SplitOk, OsTypeLinux}, + {"$words", "hi ho", QtcProcess::SplitOk, OsTypeLinux}, + {"$spacedwords", "hi ho sucker", QtcProcess::SplitOk, OsTypeLinux}, + {"hi${empty}ho", "hiho", QtcProcess::SplitOk, OsTypeLinux}, + {"hi${words}ho", "hihi hoho", QtcProcess::SplitOk, OsTypeLinux}, + {"hi${spacedwords}ho", "hi hi ho sucker ho", QtcProcess::SplitOk, OsTypeLinux}, + {"${", "", QtcProcess::BadQuoting, OsTypeLinux}, + {"${var", "", QtcProcess::BadQuoting, OsTypeLinux}, + {"${var ", "", QtcProcess::FoundMeta, OsTypeLinux}, + {"\"hi${words}ho\"", "'hihi hoho'", QtcProcess::SplitOk, OsTypeLinux}, + {"\"hi${spacedwords}ho\"", "'hi hi ho sucker ho'", QtcProcess::SplitOk, OsTypeLinux}, + {"\"${", "", QtcProcess::BadQuoting, OsTypeLinux}, + {"\"${var", "", QtcProcess::BadQuoting, OsTypeLinux}, + {"\"${var ", "", QtcProcess::FoundMeta, OsTypeLinux}, }; for (unsigned i = 0; i < sizeof(vals)/sizeof(vals[0]); i++) { @@ -371,207 +371,207 @@ void tst_QtcProcess::expandMacros_data() const char * const out; OsType os; } vals[] = { - { "plain", 0, OsTypeWindows }, - { "%{a}", "hi", OsTypeWindows }, - { "%{aa}", "\"hi ho\"", OsTypeWindows }, - { "%{b}", "h\\i", OsTypeWindows }, - { "%{c}", "\\hi", OsTypeWindows }, - { "%{d}", "hi\\", OsTypeWindows }, - { "%{ba}", "\"h\\i ho\"", OsTypeWindows }, - { "%{ca}", "\"\\hi ho\"", OsTypeWindows }, - { "%{da}", "\"hi ho\\\\\"", OsTypeWindows }, // or "\"hi ho\"\\" - { "%{e}", "\"h\"\\^\"\"i\"", OsTypeWindows }, - { "%{f}", "\"\"\\^\"\"hi\"", OsTypeWindows }, - { "%{g}", "\"hi\"\\^\"\"\"", OsTypeWindows }, - { "%{h}", "\"h\\\\\"\\^\"\"i\"", OsTypeWindows }, - { "%{i}", "\"\\\\\"\\^\"\"hi\"", OsTypeWindows }, - { "%{j}", "\"hi\\\\\"\\^\"\"\"", OsTypeWindows }, - { "%{k}", "\"&special;\"", OsTypeWindows }, - { "%{x}", "\\", OsTypeWindows }, - { "%{y}", "\"\"\\^\"\"\"", OsTypeWindows }, - { "%{z}", "\"\"", OsTypeWindows }, - { "^%{z}%{z}", "^%{z}%{z}", OsTypeWindows }, // stupid user check - - { "quoted", 0, OsTypeWindows }, - { "\"%{a}\"", "\"hi\"", OsTypeWindows }, - { "\"%{aa}\"", "\"hi ho\"", OsTypeWindows }, - { "\"%{b}\"", "\"h\\i\"", OsTypeWindows }, - { "\"%{c}\"", "\"\\hi\"", OsTypeWindows }, - { "\"%{d}\"", "\"hi\\\\\"", OsTypeWindows }, - { "\"%{ba}\"", "\"h\\i ho\"", OsTypeWindows }, - { "\"%{ca}\"", "\"\\hi ho\"", OsTypeWindows }, - { "\"%{da}\"", "\"hi ho\\\\\"", OsTypeWindows }, - { "\"%{e}\"", "\"h\"\\^\"\"i\"", OsTypeWindows }, - { "\"%{f}\"", "\"\"\\^\"\"hi\"", OsTypeWindows }, - { "\"%{g}\"", "\"hi\"\\^\"\"\"", OsTypeWindows }, - { "\"%{h}\"", "\"h\\\\\"\\^\"\"i\"", OsTypeWindows }, - { "\"%{i}\"", "\"\\\\\"\\^\"\"hi\"", OsTypeWindows }, - { "\"%{j}\"", "\"hi\\\\\"\\^\"\"\"", OsTypeWindows }, - { "\"%{k}\"", "\"&special;\"", OsTypeWindows }, - { "\"%{x}\"", "\"\\\\\"", OsTypeWindows }, - { "\"%{y}\"", "\"\"\\^\"\"\"", OsTypeWindows }, - { "\"%{z}\"", "\"\"", OsTypeWindows }, - - { "leading bs", 0, OsTypeWindows }, - { "\\%{a}", "\\hi", OsTypeWindows }, - { "\\%{aa}", "\\\\\"hi ho\"", OsTypeWindows }, - { "\\%{b}", "\\h\\i", OsTypeWindows }, - { "\\%{c}", "\\\\hi", OsTypeWindows }, - { "\\%{d}", "\\hi\\", OsTypeWindows }, - { "\\%{ba}", "\\\\\"h\\i ho\"", OsTypeWindows }, - { "\\%{ca}", "\\\\\"\\hi ho\"", OsTypeWindows }, - { "\\%{da}", "\\\\\"hi ho\\\\\"", OsTypeWindows }, - { "\\%{e}", "\\\\\"h\"\\^\"\"i\"", OsTypeWindows }, - { "\\%{f}", "\\\\\"\"\\^\"\"hi\"", OsTypeWindows }, - { "\\%{g}", "\\\\\"hi\"\\^\"\"\"", OsTypeWindows }, - { "\\%{h}", "\\\\\"h\\\\\"\\^\"\"i\"", OsTypeWindows }, - { "\\%{i}", "\\\\\"\\\\\"\\^\"\"hi\"", OsTypeWindows }, - { "\\%{j}", "\\\\\"hi\\\\\"\\^\"\"\"", OsTypeWindows }, - { "\\%{x}", "\\\\", OsTypeWindows }, - { "\\%{y}", "\\\\\"\"\\^\"\"\"", OsTypeWindows }, - { "\\%{z}", "\\", OsTypeWindows }, - - { "trailing bs", 0, OsTypeWindows }, - { "%{a}\\", "hi\\", OsTypeWindows }, - { "%{aa}\\", "\"hi ho\"\\", OsTypeWindows }, - { "%{b}\\", "h\\i\\", OsTypeWindows }, - { "%{c}\\", "\\hi\\", OsTypeWindows }, - { "%{d}\\", "hi\\\\", OsTypeWindows }, - { "%{ba}\\", "\"h\\i ho\"\\", OsTypeWindows }, - { "%{ca}\\", "\"\\hi ho\"\\", OsTypeWindows }, - { "%{da}\\", "\"hi ho\\\\\"\\", OsTypeWindows }, - { "%{e}\\", "\"h\"\\^\"\"i\"\\", OsTypeWindows }, - { "%{f}\\", "\"\"\\^\"\"hi\"\\", OsTypeWindows }, - { "%{g}\\", "\"hi\"\\^\"\"\"\\", OsTypeWindows }, - { "%{h}\\", "\"h\\\\\"\\^\"\"i\"\\", OsTypeWindows }, - { "%{i}\\", "\"\\\\\"\\^\"\"hi\"\\", OsTypeWindows }, - { "%{j}\\", "\"hi\\\\\"\\^\"\"\"\\", OsTypeWindows }, - { "%{x}\\", "\\\\", OsTypeWindows }, - { "%{y}\\", "\"\"\\^\"\"\"\\", OsTypeWindows }, - { "%{z}\\", "\\", OsTypeWindows }, - - { "bs-enclosed", 0, OsTypeWindows }, - { "\\%{a}\\", "\\hi\\", OsTypeWindows }, - { "\\%{aa}\\", "\\\\\"hi ho\"\\", OsTypeWindows }, - { "\\%{b}\\", "\\h\\i\\", OsTypeWindows }, - { "\\%{c}\\", "\\\\hi\\", OsTypeWindows }, - { "\\%{d}\\", "\\hi\\\\", OsTypeWindows }, - { "\\%{ba}\\", "\\\\\"h\\i ho\"\\", OsTypeWindows }, - { "\\%{ca}\\", "\\\\\"\\hi ho\"\\", OsTypeWindows }, - { "\\%{da}\\", "\\\\\"hi ho\\\\\"\\", OsTypeWindows }, - { "\\%{e}\\", "\\\\\"h\"\\^\"\"i\"\\", OsTypeWindows }, - { "\\%{f}\\", "\\\\\"\"\\^\"\"hi\"\\", OsTypeWindows }, - { "\\%{g}\\", "\\\\\"hi\"\\^\"\"\"\\", OsTypeWindows }, - { "\\%{h}\\", "\\\\\"h\\\\\"\\^\"\"i\"\\", OsTypeWindows }, - { "\\%{i}\\", "\\\\\"\\\\\"\\^\"\"hi\"\\", OsTypeWindows }, - { "\\%{j}\\", "\\\\\"hi\\\\\"\\^\"\"\"\\", OsTypeWindows }, - { "\\%{x}\\", "\\\\\\", OsTypeWindows }, - { "\\%{y}\\", "\\\\\"\"\\^\"\"\"\\", OsTypeWindows }, - { "\\%{z}\\", "\\\\", OsTypeWindows }, - - { "bs-enclosed and trailing literal quote", 0, OsTypeWindows }, - { "\\%{a}\\\\\\^\"", "\\hi\\\\\\^\"", OsTypeWindows }, - { "\\%{aa}\\\\\\^\"", "\\\\\"hi ho\"\\\\\\^\"", OsTypeWindows }, - { "\\%{b}\\\\\\^\"", "\\h\\i\\\\\\^\"", OsTypeWindows }, - { "\\%{c}\\\\\\^\"", "\\\\hi\\\\\\^\"", OsTypeWindows }, - { "\\%{d}\\\\\\^\"", "\\hi\\\\\\\\\\^\"", OsTypeWindows }, - { "\\%{ba}\\\\\\^\"", "\\\\\"h\\i ho\"\\\\\\^\"", OsTypeWindows }, - { "\\%{ca}\\\\\\^\"", "\\\\\"\\hi ho\"\\\\\\^\"", OsTypeWindows }, - { "\\%{da}\\\\\\^\"", "\\\\\"hi ho\\\\\"\\\\\\^\"", OsTypeWindows }, - { "\\%{e}\\\\\\^\"", "\\\\\"h\"\\^\"\"i\"\\\\\\^\"", OsTypeWindows }, - { "\\%{f}\\\\\\^\"", "\\\\\"\"\\^\"\"hi\"\\\\\\^\"", OsTypeWindows }, - { "\\%{g}\\\\\\^\"", "\\\\\"hi\"\\^\"\"\"\\\\\\^\"", OsTypeWindows }, - { "\\%{h}\\\\\\^\"", "\\\\\"h\\\\\"\\^\"\"i\"\\\\\\^\"", OsTypeWindows }, - { "\\%{i}\\\\\\^\"", "\\\\\"\\\\\"\\^\"\"hi\"\\\\\\^\"", OsTypeWindows }, - { "\\%{j}\\\\\\^\"", "\\\\\"hi\\\\\"\\^\"\"\"\\\\\\^\"", OsTypeWindows }, - { "\\%{x}\\\\\\^\"", "\\\\\\\\\\\\\\^\"", OsTypeWindows }, - { "\\%{y}\\\\\\^\"", "\\\\\"\"\\^\"\"\"\\\\\\^\"", OsTypeWindows }, - { "\\%{z}\\\\\\^\"", "\\\\\\\\\\^\"", OsTypeWindows }, - - { "bs-enclosed and trailing unclosed quote", 0, OsTypeWindows }, - { "\\%{a}\\\\\"", "\\hi\\\\\"", OsTypeWindows }, - { "\\%{aa}\\\\\"", "\\\\\"hi ho\"\\\\\"", OsTypeWindows }, - { "\\%{b}\\\\\"", "\\h\\i\\\\\"", OsTypeWindows }, - { "\\%{c}\\\\\"", "\\\\hi\\\\\"", OsTypeWindows }, - { "\\%{d}\\\\\"", "\\hi\\\\\\\\\"", OsTypeWindows }, - { "\\%{ba}\\\\\"", "\\\\\"h\\i ho\"\\\\\"", OsTypeWindows }, - { "\\%{ca}\\\\\"", "\\\\\"\\hi ho\"\\\\\"", OsTypeWindows }, - { "\\%{da}\\\\\"", "\\\\\"hi ho\\\\\"\\\\\"", OsTypeWindows }, - { "\\%{e}\\\\\"", "\\\\\"h\"\\^\"\"i\"\\\\\"", OsTypeWindows }, - { "\\%{f}\\\\\"", "\\\\\"\"\\^\"\"hi\"\\\\\"", OsTypeWindows }, - { "\\%{g}\\\\\"", "\\\\\"hi\"\\^\"\"\"\\\\\"", OsTypeWindows }, - { "\\%{h}\\\\\"", "\\\\\"h\\\\\"\\^\"\"i\"\\\\\"", OsTypeWindows }, - { "\\%{i}\\\\\"", "\\\\\"\\\\\"\\^\"\"hi\"\\\\\"", OsTypeWindows }, - { "\\%{j}\\\\\"", "\\\\\"hi\\\\\"\\^\"\"\"\\\\\"", OsTypeWindows }, - { "\\%{x}\\\\\"", "\\\\\\\\\\\\\"", OsTypeWindows }, - { "\\%{y}\\\\\"", "\\\\\"\"\\^\"\"\"\\\\\"", OsTypeWindows }, - { "\\%{z}\\\\\"", "\\\\\\\\\"", OsTypeWindows }, - - { "multi-var", 0, OsTypeWindows }, - { "%{x}%{y}%{z}", "\\\\\"\"\\^\"\"\"", OsTypeWindows }, - { "%{x}%{z}%{y}%{z}", "\\\\\"\"\\^\"\"\"", OsTypeWindows }, - { "%{x}%{z}%{y}", "\\\\\"\"\\^\"\"\"", OsTypeWindows }, - { "%{x}\\^\"%{z}", "\\\\\\^\"", OsTypeWindows }, - { "%{x}%{z}\\^\"%{z}", "\\\\\\^\"", OsTypeWindows }, - { "%{x}%{z}\\^\"", "\\\\\\^\"", OsTypeWindows }, - { "%{x}\\%{z}", "\\\\", OsTypeWindows }, - { "%{x}%{z}\\%{z}", "\\\\", OsTypeWindows }, - { "%{x}%{z}\\", "\\\\", OsTypeWindows }, - { "%{aa}%{a}", "\"hi hohi\"", OsTypeWindows }, - { "%{aa}%{aa}", "\"hi hohi ho\"", OsTypeWindows }, - { "%{aa}:%{aa}", "\"hi ho\":\"hi ho\"", OsTypeWindows }, - { "hallo ^|%{aa}^|", "hallo ^|\"hi ho\"^|", OsTypeWindows }, - - { "quoted multi-var", 0, OsTypeWindows }, - { "\"%{x}%{y}%{z}\"", "\"\\\\\"\\^\"\"\"", OsTypeWindows }, - { "\"%{x}%{z}%{y}%{z}\"", "\"\\\\\"\\^\"\"\"", OsTypeWindows }, - { "\"%{x}%{z}%{y}\"", "\"\\\\\"\\^\"\"\"", OsTypeWindows }, - { "\"%{x}\"^\"\"%{z}\"", "\"\\\\\"^\"\"\"", OsTypeWindows }, - { "\"%{x}%{z}\"^\"\"%{z}\"", "\"\\\\\"^\"\"\"", OsTypeWindows }, - { "\"%{x}%{z}\"^\"\"\"", "\"\\\\\"^\"\"\"", OsTypeWindows }, - { "\"%{x}\\%{z}\"", "\"\\\\\\\\\"", OsTypeWindows }, - { "\"%{x}%{z}\\%{z}\"", "\"\\\\\\\\\"", OsTypeWindows }, - { "\"%{x}%{z}\\\\\"", "\"\\\\\\\\\"", OsTypeWindows }, - { "\"%{aa}%{a}\"", "\"hi hohi\"", OsTypeWindows }, - { "\"%{aa}%{aa}\"", "\"hi hohi ho\"", OsTypeWindows }, - { "\"%{aa}:%{aa}\"", "\"hi ho:hi ho\"", OsTypeWindows }, - - { "plain", 0, OsTypeLinux }, - { "%{a}", "hi", OsTypeLinux }, - { "%{b}", "'hi ho'", OsTypeLinux }, - { "%{c}", "'&special;'", OsTypeLinux }, - { "%{d}", "'h\\i'", OsTypeLinux }, - { "%{e}", "'h\"i'", OsTypeLinux }, - { "%{f}", "'h'\\''i'", OsTypeLinux }, - { "%{z}", "''", OsTypeLinux }, - { "\\%{z}%{z}", "\\%{z}%{z}", OsTypeLinux }, // stupid user check - - { "single-quoted", 0, OsTypeLinux }, - { "'%{a}'", "'hi'", OsTypeLinux }, - { "'%{b}'", "'hi ho'", OsTypeLinux }, - { "'%{c}'", "'&special;'", OsTypeLinux }, - { "'%{d}'", "'h\\i'", OsTypeLinux }, - { "'%{e}'", "'h\"i'", OsTypeLinux }, - { "'%{f}'", "'h'\\''i'", OsTypeLinux }, - { "'%{z}'", "''", OsTypeLinux }, - - { "double-quoted", 0, OsTypeLinux }, - { "\"%{a}\"", "\"hi\"", OsTypeLinux }, - { "\"%{b}\"", "\"hi ho\"", OsTypeLinux }, - { "\"%{c}\"", "\"&special;\"", OsTypeLinux }, - { "\"%{d}\"", "\"h\\\\i\"", OsTypeLinux }, - { "\"%{e}\"", "\"h\\\"i\"", OsTypeLinux }, - { "\"%{f}\"", "\"h'i\"", OsTypeLinux }, - { "\"%{z}\"", "\"\"", OsTypeLinux }, - - { "complex", 0, OsTypeLinux }, - { "echo \"$(echo %{a})\"", "echo \"$(echo hi)\"", OsTypeLinux }, - { "echo \"$(echo %{b})\"", "echo \"$(echo 'hi ho')\"", OsTypeLinux }, - { "echo \"$(echo \"%{a}\")\"", "echo \"$(echo \"hi\")\"", OsTypeLinux }, + {"plain", 0, OsTypeWindows}, + {"%{a}", "hi", OsTypeWindows}, + {"%{aa}", "\"hi ho\"", OsTypeWindows}, + {"%{b}", "h\\i", OsTypeWindows}, + {"%{c}", "\\hi", OsTypeWindows}, + {"%{d}", "hi\\", OsTypeWindows}, + {"%{ba}", "\"h\\i ho\"", OsTypeWindows}, + {"%{ca}", "\"\\hi ho\"", OsTypeWindows}, + {"%{da}", "\"hi ho\\\\\"", OsTypeWindows}, // or "\"hi ho\"\\" + {"%{e}", "\"h\"\\^\"\"i\"", OsTypeWindows}, + {"%{f}", "\"\"\\^\"\"hi\"", OsTypeWindows}, + {"%{g}", "\"hi\"\\^\"\"\"", OsTypeWindows}, + {"%{h}", "\"h\\\\\"\\^\"\"i\"", OsTypeWindows}, + {"%{i}", "\"\\\\\"\\^\"\"hi\"", OsTypeWindows}, + {"%{j}", "\"hi\\\\\"\\^\"\"\"", OsTypeWindows}, + {"%{k}", "\"&special;\"", OsTypeWindows}, + {"%{x}", "\\", OsTypeWindows}, + {"%{y}", "\"\"\\^\"\"\"", OsTypeWindows}, + {"%{z}", "\"\"", OsTypeWindows}, + {"^%{z}%{z}", "^%{z}%{z}", OsTypeWindows}, // stupid user check + + {"quoted", 0, OsTypeWindows}, + {"\"%{a}\"", "\"hi\"", OsTypeWindows}, + {"\"%{aa}\"", "\"hi ho\"", OsTypeWindows}, + {"\"%{b}\"", "\"h\\i\"", OsTypeWindows}, + {"\"%{c}\"", "\"\\hi\"", OsTypeWindows}, + {"\"%{d}\"", "\"hi\\\\\"", OsTypeWindows}, + {"\"%{ba}\"", "\"h\\i ho\"", OsTypeWindows}, + {"\"%{ca}\"", "\"\\hi ho\"", OsTypeWindows}, + {"\"%{da}\"", "\"hi ho\\\\\"", OsTypeWindows}, + {"\"%{e}\"", "\"h\"\\^\"\"i\"", OsTypeWindows}, + {"\"%{f}\"", "\"\"\\^\"\"hi\"", OsTypeWindows}, + {"\"%{g}\"", "\"hi\"\\^\"\"\"", OsTypeWindows}, + {"\"%{h}\"", "\"h\\\\\"\\^\"\"i\"", OsTypeWindows}, + {"\"%{i}\"", "\"\\\\\"\\^\"\"hi\"", OsTypeWindows}, + {"\"%{j}\"", "\"hi\\\\\"\\^\"\"\"", OsTypeWindows}, + {"\"%{k}\"", "\"&special;\"", OsTypeWindows}, + {"\"%{x}\"", "\"\\\\\"", OsTypeWindows}, + {"\"%{y}\"", "\"\"\\^\"\"\"", OsTypeWindows}, + {"\"%{z}\"", "\"\"", OsTypeWindows}, + + {"leading bs", 0, OsTypeWindows}, + {"\\%{a}", "\\hi", OsTypeWindows}, + {"\\%{aa}", "\\\\\"hi ho\"", OsTypeWindows}, + {"\\%{b}", "\\h\\i", OsTypeWindows}, + {"\\%{c}", "\\\\hi", OsTypeWindows}, + {"\\%{d}", "\\hi\\", OsTypeWindows}, + {"\\%{ba}", "\\\\\"h\\i ho\"", OsTypeWindows}, + {"\\%{ca}", "\\\\\"\\hi ho\"", OsTypeWindows}, + {"\\%{da}", "\\\\\"hi ho\\\\\"", OsTypeWindows}, + {"\\%{e}", "\\\\\"h\"\\^\"\"i\"", OsTypeWindows}, + {"\\%{f}", "\\\\\"\"\\^\"\"hi\"", OsTypeWindows}, + {"\\%{g}", "\\\\\"hi\"\\^\"\"\"", OsTypeWindows}, + {"\\%{h}", "\\\\\"h\\\\\"\\^\"\"i\"", OsTypeWindows}, + {"\\%{i}", "\\\\\"\\\\\"\\^\"\"hi\"", OsTypeWindows}, + {"\\%{j}", "\\\\\"hi\\\\\"\\^\"\"\"", OsTypeWindows}, + {"\\%{x}", "\\\\", OsTypeWindows}, + {"\\%{y}", "\\\\\"\"\\^\"\"\"", OsTypeWindows}, + {"\\%{z}", "\\", OsTypeWindows}, + + {"trailing bs", 0, OsTypeWindows}, + {"%{a}\\", "hi\\", OsTypeWindows}, + {"%{aa}\\", "\"hi ho\"\\", OsTypeWindows}, + {"%{b}\\", "h\\i\\", OsTypeWindows}, + {"%{c}\\", "\\hi\\", OsTypeWindows}, + {"%{d}\\", "hi\\\\", OsTypeWindows}, + {"%{ba}\\", "\"h\\i ho\"\\", OsTypeWindows}, + {"%{ca}\\", "\"\\hi ho\"\\", OsTypeWindows}, + {"%{da}\\", "\"hi ho\\\\\"\\", OsTypeWindows}, + {"%{e}\\", "\"h\"\\^\"\"i\"\\", OsTypeWindows}, + {"%{f}\\", "\"\"\\^\"\"hi\"\\", OsTypeWindows}, + {"%{g}\\", "\"hi\"\\^\"\"\"\\", OsTypeWindows}, + {"%{h}\\", "\"h\\\\\"\\^\"\"i\"\\", OsTypeWindows}, + {"%{i}\\", "\"\\\\\"\\^\"\"hi\"\\", OsTypeWindows}, + {"%{j}\\", "\"hi\\\\\"\\^\"\"\"\\", OsTypeWindows}, + {"%{x}\\", "\\\\", OsTypeWindows}, + {"%{y}\\", "\"\"\\^\"\"\"\\", OsTypeWindows}, + {"%{z}\\", "\\", OsTypeWindows}, + + {"bs-enclosed", 0, OsTypeWindows}, + {"\\%{a}\\", "\\hi\\", OsTypeWindows}, + {"\\%{aa}\\", "\\\\\"hi ho\"\\", OsTypeWindows}, + {"\\%{b}\\", "\\h\\i\\", OsTypeWindows}, + {"\\%{c}\\", "\\\\hi\\", OsTypeWindows}, + {"\\%{d}\\", "\\hi\\\\", OsTypeWindows}, + {"\\%{ba}\\", "\\\\\"h\\i ho\"\\", OsTypeWindows}, + {"\\%{ca}\\", "\\\\\"\\hi ho\"\\", OsTypeWindows}, + {"\\%{da}\\", "\\\\\"hi ho\\\\\"\\", OsTypeWindows}, + {"\\%{e}\\", "\\\\\"h\"\\^\"\"i\"\\", OsTypeWindows}, + {"\\%{f}\\", "\\\\\"\"\\^\"\"hi\"\\", OsTypeWindows}, + {"\\%{g}\\", "\\\\\"hi\"\\^\"\"\"\\", OsTypeWindows}, + {"\\%{h}\\", "\\\\\"h\\\\\"\\^\"\"i\"\\", OsTypeWindows}, + {"\\%{i}\\", "\\\\\"\\\\\"\\^\"\"hi\"\\", OsTypeWindows}, + {"\\%{j}\\", "\\\\\"hi\\\\\"\\^\"\"\"\\", OsTypeWindows}, + {"\\%{x}\\", "\\\\\\", OsTypeWindows}, + {"\\%{y}\\", "\\\\\"\"\\^\"\"\"\\", OsTypeWindows}, + {"\\%{z}\\", "\\\\", OsTypeWindows}, + + {"bs-enclosed and trailing literal quote", 0, OsTypeWindows}, + {"\\%{a}\\\\\\^\"", "\\hi\\\\\\^\"", OsTypeWindows}, + {"\\%{aa}\\\\\\^\"", "\\\\\"hi ho\"\\\\\\^\"", OsTypeWindows}, + {"\\%{b}\\\\\\^\"", "\\h\\i\\\\\\^\"", OsTypeWindows}, + {"\\%{c}\\\\\\^\"", "\\\\hi\\\\\\^\"", OsTypeWindows}, + {"\\%{d}\\\\\\^\"", "\\hi\\\\\\\\\\^\"", OsTypeWindows}, + {"\\%{ba}\\\\\\^\"", "\\\\\"h\\i ho\"\\\\\\^\"", OsTypeWindows}, + {"\\%{ca}\\\\\\^\"", "\\\\\"\\hi ho\"\\\\\\^\"", OsTypeWindows}, + {"\\%{da}\\\\\\^\"", "\\\\\"hi ho\\\\\"\\\\\\^\"", OsTypeWindows}, + {"\\%{e}\\\\\\^\"", "\\\\\"h\"\\^\"\"i\"\\\\\\^\"", OsTypeWindows}, + {"\\%{f}\\\\\\^\"", "\\\\\"\"\\^\"\"hi\"\\\\\\^\"", OsTypeWindows}, + {"\\%{g}\\\\\\^\"", "\\\\\"hi\"\\^\"\"\"\\\\\\^\"", OsTypeWindows}, + {"\\%{h}\\\\\\^\"", "\\\\\"h\\\\\"\\^\"\"i\"\\\\\\^\"", OsTypeWindows}, + {"\\%{i}\\\\\\^\"", "\\\\\"\\\\\"\\^\"\"hi\"\\\\\\^\"", OsTypeWindows}, + {"\\%{j}\\\\\\^\"", "\\\\\"hi\\\\\"\\^\"\"\"\\\\\\^\"", OsTypeWindows}, + {"\\%{x}\\\\\\^\"", "\\\\\\\\\\\\\\^\"", OsTypeWindows}, + {"\\%{y}\\\\\\^\"", "\\\\\"\"\\^\"\"\"\\\\\\^\"", OsTypeWindows}, + {"\\%{z}\\\\\\^\"", "\\\\\\\\\\^\"", OsTypeWindows}, + + {"bs-enclosed and trailing unclosed quote", 0, OsTypeWindows}, + {"\\%{a}\\\\\"", "\\hi\\\\\"", OsTypeWindows}, + {"\\%{aa}\\\\\"", "\\\\\"hi ho\"\\\\\"", OsTypeWindows}, + {"\\%{b}\\\\\"", "\\h\\i\\\\\"", OsTypeWindows}, + {"\\%{c}\\\\\"", "\\\\hi\\\\\"", OsTypeWindows}, + {"\\%{d}\\\\\"", "\\hi\\\\\\\\\"", OsTypeWindows}, + {"\\%{ba}\\\\\"", "\\\\\"h\\i ho\"\\\\\"", OsTypeWindows}, + {"\\%{ca}\\\\\"", "\\\\\"\\hi ho\"\\\\\"", OsTypeWindows}, + {"\\%{da}\\\\\"", "\\\\\"hi ho\\\\\"\\\\\"", OsTypeWindows}, + {"\\%{e}\\\\\"", "\\\\\"h\"\\^\"\"i\"\\\\\"", OsTypeWindows}, + {"\\%{f}\\\\\"", "\\\\\"\"\\^\"\"hi\"\\\\\"", OsTypeWindows}, + {"\\%{g}\\\\\"", "\\\\\"hi\"\\^\"\"\"\\\\\"", OsTypeWindows}, + {"\\%{h}\\\\\"", "\\\\\"h\\\\\"\\^\"\"i\"\\\\\"", OsTypeWindows}, + {"\\%{i}\\\\\"", "\\\\\"\\\\\"\\^\"\"hi\"\\\\\"", OsTypeWindows}, + {"\\%{j}\\\\\"", "\\\\\"hi\\\\\"\\^\"\"\"\\\\\"", OsTypeWindows}, + {"\\%{x}\\\\\"", "\\\\\\\\\\\\\"", OsTypeWindows}, + {"\\%{y}\\\\\"", "\\\\\"\"\\^\"\"\"\\\\\"", OsTypeWindows}, + {"\\%{z}\\\\\"", "\\\\\\\\\"", OsTypeWindows}, + + {"multi-var", 0, OsTypeWindows}, + {"%{x}%{y}%{z}", "\\\\\"\"\\^\"\"\"", OsTypeWindows}, + {"%{x}%{z}%{y}%{z}", "\\\\\"\"\\^\"\"\"", OsTypeWindows}, + {"%{x}%{z}%{y}", "\\\\\"\"\\^\"\"\"", OsTypeWindows}, + {"%{x}\\^\"%{z}", "\\\\\\^\"", OsTypeWindows}, + {"%{x}%{z}\\^\"%{z}", "\\\\\\^\"", OsTypeWindows}, + {"%{x}%{z}\\^\"", "\\\\\\^\"", OsTypeWindows}, + {"%{x}\\%{z}", "\\\\", OsTypeWindows}, + {"%{x}%{z}\\%{z}", "\\\\", OsTypeWindows}, + {"%{x}%{z}\\", "\\\\", OsTypeWindows}, + {"%{aa}%{a}", "\"hi hohi\"", OsTypeWindows}, + {"%{aa}%{aa}", "\"hi hohi ho\"", OsTypeWindows}, + {"%{aa}:%{aa}", "\"hi ho\":\"hi ho\"", OsTypeWindows}, + {"hallo ^|%{aa}^|", "hallo ^|\"hi ho\"^|", OsTypeWindows}, + + {"quoted multi-var", 0, OsTypeWindows}, + {"\"%{x}%{y}%{z}\"", "\"\\\\\"\\^\"\"\"", OsTypeWindows}, + {"\"%{x}%{z}%{y}%{z}\"", "\"\\\\\"\\^\"\"\"", OsTypeWindows}, + {"\"%{x}%{z}%{y}\"", "\"\\\\\"\\^\"\"\"", OsTypeWindows}, + {"\"%{x}\"^\"\"%{z}\"", "\"\\\\\"^\"\"\"", OsTypeWindows}, + {"\"%{x}%{z}\"^\"\"%{z}\"", "\"\\\\\"^\"\"\"", OsTypeWindows}, + {"\"%{x}%{z}\"^\"\"\"", "\"\\\\\"^\"\"\"", OsTypeWindows}, + {"\"%{x}\\%{z}\"", "\"\\\\\\\\\"", OsTypeWindows}, + {"\"%{x}%{z}\\%{z}\"", "\"\\\\\\\\\"", OsTypeWindows}, + {"\"%{x}%{z}\\\\\"", "\"\\\\\\\\\"", OsTypeWindows}, + {"\"%{aa}%{a}\"", "\"hi hohi\"", OsTypeWindows}, + {"\"%{aa}%{aa}\"", "\"hi hohi ho\"", OsTypeWindows}, + {"\"%{aa}:%{aa}\"", "\"hi ho:hi ho\"", OsTypeWindows}, + + {"plain", 0, OsTypeLinux}, + {"%{a}", "hi", OsTypeLinux}, + {"%{b}", "'hi ho'", OsTypeLinux}, + {"%{c}", "'&special;'", OsTypeLinux}, + {"%{d}", "'h\\i'", OsTypeLinux}, + {"%{e}", "'h\"i'", OsTypeLinux}, + {"%{f}", "'h'\\''i'", OsTypeLinux}, + {"%{z}", "''", OsTypeLinux}, + {"\\%{z}%{z}", "\\%{z}%{z}", OsTypeLinux}, // stupid user check + + {"single-quoted", 0, OsTypeLinux}, + {"'%{a}'", "'hi'", OsTypeLinux}, + {"'%{b}'", "'hi ho'", OsTypeLinux}, + {"'%{c}'", "'&special;'", OsTypeLinux}, + {"'%{d}'", "'h\\i'", OsTypeLinux}, + {"'%{e}'", "'h\"i'", OsTypeLinux}, + {"'%{f}'", "'h'\\''i'", OsTypeLinux}, + {"'%{z}'", "''", OsTypeLinux}, + + {"double-quoted", 0, OsTypeLinux}, + {"\"%{a}\"", "\"hi\"", OsTypeLinux}, + {"\"%{b}\"", "\"hi ho\"", OsTypeLinux}, + {"\"%{c}\"", "\"&special;\"", OsTypeLinux}, + {"\"%{d}\"", "\"h\\\\i\"", OsTypeLinux}, + {"\"%{e}\"", "\"h\\\"i\"", OsTypeLinux}, + {"\"%{f}\"", "\"h'i\"", OsTypeLinux}, + {"\"%{z}\"", "\"\"", OsTypeLinux}, + + {"complex", 0, OsTypeLinux}, + {"echo \"$(echo %{a})\"", "echo \"$(echo hi)\"", OsTypeLinux}, + {"echo \"$(echo %{b})\"", "echo \"$(echo 'hi ho')\"", OsTypeLinux}, + {"echo \"$(echo \"%{a}\")\"", "echo \"$(echo \"hi\")\"", OsTypeLinux}, // These make no sense shell-wise, but they test expando nesting - { "echo \"%{echo %{a}}\"", "echo \"%{echo hi}\"", OsTypeLinux }, - { "echo \"%{echo %{b}}\"", "echo \"%{echo hi ho}\"", OsTypeLinux }, - { "echo \"%{echo \"%{a}\"}\"", "echo \"%{echo \"hi\"}\"", OsTypeLinux }, + {"echo \"%{echo %{a}}\"", "echo \"%{echo hi}\"", OsTypeLinux}, + {"echo \"%{echo %{b}}\"", "echo \"%{echo hi ho}\"", OsTypeLinux}, + {"echo \"%{echo \"%{a}\"}\"", "echo \"%{echo \"hi\"}\"", OsTypeLinux }, }; const char *title = 0; @@ -616,42 +616,42 @@ void tst_QtcProcess::iterations_data() const char * const out; OsType os; } vals[] = { - { "", "", OsTypeWindows }, - { "hi", "hi", OsTypeWindows }, - { " hi ", "hi", OsTypeWindows }, - { "hi ho", "hi ho", OsTypeWindows }, - { "\"hi ho\" sucker", "\"hi ho\" sucker", OsTypeWindows }, - { "\"hi\"^\"\"ho\" sucker", "\"hi\"\\^\"\"ho\" sucker", OsTypeWindows }, - { "\"hi\"\\^\"\"ho\" sucker", "\"hi\"\\^\"\"ho\" sucker", OsTypeWindows }, - { "hi^|ho", "\"hi|ho\"", OsTypeWindows }, - { "c:\\", "c:\\", OsTypeWindows }, - { "\"c:\\\\\"", "c:\\", OsTypeWindows }, - { "\\hi\\ho", "\\hi\\ho", OsTypeWindows }, - { "hi null%", "hi null%", OsTypeWindows }, - { "hi null% ho", "hi null% ho", OsTypeWindows }, - { "hi null%here ho", "hi null%here ho", OsTypeWindows }, - { "hi null%here%too ho", "hi {} ho", OsTypeWindows }, - { "echo hello | more", "echo hello", OsTypeWindows }, - { "echo hello| more", "echo hello", OsTypeWindows }, - - { "", "", OsTypeLinux }, - { " ", "", OsTypeLinux }, - { "hi", "hi", OsTypeLinux }, - { " hi ", "hi", OsTypeLinux }, - { "'hi'", "hi", OsTypeLinux }, - { "hi ho", "hi ho", OsTypeLinux }, - { "\"hi ho\" sucker", "'hi ho' sucker", OsTypeLinux }, - { "\"hi\\\"ho\" sucker", "'hi\"ho' sucker", OsTypeLinux }, - { "\"hi'ho\" sucker", "'hi'\\''ho' sucker", OsTypeLinux }, - { "'hi ho' sucker", "'hi ho' sucker", OsTypeLinux }, - { "\\\\", "'\\'", OsTypeLinux }, - { "'\\'", "'\\'", OsTypeLinux }, - { "hi 'null${here}too' ho", "hi 'null${here}too' ho", OsTypeLinux }, - { "hi null${here}too ho", "hi {} ho", OsTypeLinux }, - { "hi $(echo $dollar cent) ho", "hi {} ho", OsTypeLinux }, - { "hi `echo $dollar \\`echo cent\\` | cat` ho", "hi {} ho", OsTypeLinux }, - { "echo hello | more", "echo hello", OsTypeLinux }, - { "echo hello| more", "echo hello", OsTypeLinux }, + {"", "", OsTypeWindows}, + {"hi", "hi", OsTypeWindows}, + {" hi ", "hi", OsTypeWindows}, + {"hi ho", "hi ho", OsTypeWindows}, + {"\"hi ho\" sucker", "\"hi ho\" sucker", OsTypeWindows}, + {"\"hi\"^\"\"ho\" sucker", "\"hi\"\\^\"\"ho\" sucker", OsTypeWindows}, + {"\"hi\"\\^\"\"ho\" sucker", "\"hi\"\\^\"\"ho\" sucker", OsTypeWindows}, + {"hi^|ho", "\"hi|ho\"", OsTypeWindows}, + {"c:\\", "c:\\", OsTypeWindows}, + {"\"c:\\\\\"", "c:\\", OsTypeWindows}, + {"\\hi\\ho", "\\hi\\ho", OsTypeWindows}, + {"hi null%", "hi null%", OsTypeWindows}, + {"hi null% ho", "hi null% ho", OsTypeWindows}, + {"hi null%here ho", "hi null%here ho", OsTypeWindows}, + {"hi null%here%too ho", "hi {} ho", OsTypeWindows}, + {"echo hello | more", "echo hello", OsTypeWindows}, + {"echo hello| more", "echo hello", OsTypeWindows}, + + {"", "", OsTypeLinux}, + {" ", "", OsTypeLinux}, + {"hi", "hi", OsTypeLinux}, + {" hi ", "hi", OsTypeLinux}, + {"'hi'", "hi", OsTypeLinux}, + {"hi ho", "hi ho", OsTypeLinux}, + {"\"hi ho\" sucker", "'hi ho' sucker", OsTypeLinux}, + {"\"hi\\\"ho\" sucker", "'hi\"ho' sucker", OsTypeLinux}, + {"\"hi'ho\" sucker", "'hi'\\''ho' sucker", OsTypeLinux}, + {"'hi ho' sucker", "'hi ho' sucker", OsTypeLinux}, + {"\\\\", "'\\'", OsTypeLinux}, + {"'\\'", "'\\'", OsTypeLinux}, + {"hi 'null${here}too' ho", "hi 'null${here}too' ho", OsTypeLinux}, + {"hi null${here}too ho", "hi {} ho", OsTypeLinux}, + {"hi $(echo $dollar cent) ho", "hi {} ho", OsTypeLinux}, + {"hi `echo $dollar \\`echo cent\\` | cat` ho", "hi {} ho", OsTypeLinux}, + {"echo hello | more", "echo hello", OsTypeLinux}, + {"echo hello| more", "echo hello", OsTypeLinux}, }; for (unsigned i = 0; i < sizeof(vals)/sizeof(vals[0]); i++) diff --git a/tests/auto/timeline/timelinemodel/tst_timelinemodel.cpp b/tests/auto/timeline/timelinemodel/tst_timelinemodel.cpp index 3888350d5b..eb24474bd4 100644 --- a/tests/auto/timeline/timelinemodel/tst_timelinemodel.cpp +++ b/tests/auto/timeline/timelinemodel/tst_timelinemodel.cpp @@ -368,7 +368,7 @@ void tst_TimelineModel::defaultValues() QCOMPARE(dummy.rowMinValue(0), 0); QCOMPARE(dummy.rowMaxValue(0), 0); QCOMPARE(dummy.typeId(0), -1); - QCOMPARE(dummy.color(0), QColor()); + QCOMPARE(dummy.color(0), QRgb()); QCOMPARE(dummy.labels(), QVariantList()); QCOMPARE(dummy.details(0), QVariantMap()); QCOMPARE(dummy.collapsedRow(0), 0); @@ -387,21 +387,21 @@ void tst_TimelineModel::row() void tst_TimelineModel::colorByHue() { DummyModel dummy; - QCOMPARE(dummy.colorByHue(10), QColor::fromHsl(10, 150, 166)); - QCOMPARE(dummy.colorByHue(500), QColor::fromHsl(140, 150, 166)); + QCOMPARE(dummy.colorByHue(10), QColor::fromHsl(10, 150, 166).rgb()); + QCOMPARE(dummy.colorByHue(500), QColor::fromHsl(140, 150, 166).rgb()); } void tst_TimelineModel::colorBySelectionId() { DummyModel dummy; dummy.loadData(); - QCOMPARE(dummy.colorBySelectionId(5), QColor::fromHsl(6 * 25, 150, 166)); + QCOMPARE(dummy.colorBySelectionId(5), QColor::fromHsl(6 * 25, 150, 166).rgb()); } void tst_TimelineModel::colorByFraction() { DummyModel dummy; - QCOMPARE(dummy.colorByFraction(0.5), QColor::fromHsl(0.5 * 96 + 10, 150, 166)); + QCOMPARE(dummy.colorByFraction(0.5), QColor::fromHsl(0.5 * 96 + 10, 150, 166).rgb()); } void tst_TimelineModel::supportedRenderPasses() diff --git a/tests/auto/utils/objectpool/objectpool.pro b/tests/auto/utils/objectpool/objectpool.pro new file mode 100644 index 0000000000..4da02c45c5 --- /dev/null +++ b/tests/auto/utils/objectpool/objectpool.pro @@ -0,0 +1,4 @@ +QTC_LIB_DEPENDS += utils +include(../../qttest.pri) + +SOURCES += tst_objectpool.cpp diff --git a/tests/auto/utils/objectpool/objectpool.qbs b/tests/auto/utils/objectpool/objectpool.qbs new file mode 100644 index 0000000000..1fdd37c19a --- /dev/null +++ b/tests/auto/utils/objectpool/objectpool.qbs @@ -0,0 +1,7 @@ +import qbs + +QtcAutotest { + name: "ObjectPool autotest" + Depends { name: "Utils" } + files: "tst_objectpool.cpp" +} diff --git a/tests/auto/utils/objectpool/tst_objectpool.cpp b/tests/auto/utils/objectpool/tst_objectpool.cpp new file mode 100644 index 0000000000..40bf1eb47a --- /dev/null +++ b/tests/auto/utils/objectpool/tst_objectpool.cpp @@ -0,0 +1,96 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#include <utils/objectpool.h> + +#include <QtTest> + +//TESTED_COMPONENT=src/libs/utils + +using namespace Utils; + +class tst_ObjectPool : public QObject +{ + Q_OBJECT + +private slots: + void testSize(); +}; + +void tst_ObjectPool::testSize() +{ + QObject parent; + + QPointer<QObject> object1 = new QObject; + object1->setObjectName("object1"); + + QPointer<QObject> object2 = new QObject(&parent); + object2->setObjectName("object2"); + + QPointer<QObject> object3 = new QObject; + object3->setObjectName("object3"); + + QPointer<QObject> object4 = new QObject(&parent); + object4->setObjectName("object4"); + + { + ObjectPool<QObject> pool; + QCOMPARE(pool.size(), 0); + + pool.addObject(object1.data()); + QCOMPARE(pool.size(), 1); + + pool.addObject(object2.data()); + QCOMPARE(pool.size(), 2); + + pool.addObject(object3.data()); + QCOMPARE(pool.size(), 3); + + pool.addObject(object4.data()); + QCOMPARE(pool.size(), 4); + + delete object1; + QCOMPARE(pool.size(), 3); + QCOMPARE(parent.children().size(), 2); + + delete object2; + QCOMPARE(pool.size(), 2); + QCOMPARE(parent.children().size(), 1); + } + + QCOMPARE(parent.children().size(), 1); + QCOMPARE(object3.isNull(), true); + QCOMPARE(object4.isNull(), false); + + delete object4; + QCOMPARE(parent.children().size(), 0); + QCOMPARE(object3.isNull(), true); + QCOMPARE(object4.isNull(), true); +} + + +QTEST_MAIN(tst_ObjectPool) + +#include "tst_objectpool.moc" diff --git a/tests/auto/utils/stringutils/tst_stringutils.cpp b/tests/auto/utils/stringutils/tst_stringutils.cpp index 051baf3470..ae137b13e1 100644 --- a/tests/auto/utils/stringutils/tst_stringutils.cpp +++ b/tests/auto/utils/stringutils/tst_stringutils.cpp @@ -120,40 +120,40 @@ void tst_StringUtils::testMacroExpander_data() const char * const in; const char * const out; } vals[] = { - { "text", "text" }, - { "%{a}", "hi" }, - { "%%{a}", "%hi" }, - { "%%%{a}", "%%hi" }, - { "%{b}", "%{b}" }, - { "pre%{a}", "prehi" }, - { "%{a}post", "hipost" }, - { "pre%{a}post", "prehipost" }, - { "%{a}%{a}", "hihi" }, - { "%{a}text%{a}", "hitexthi" }, - { "%{foo}%{a}text%{a}", "ahitexthi" }, - { "%{}{a}", "%{a}" }, - { "%{}", "%" }, - { "test%{}", "test%" }, - { "%{}test", "%test" }, - { "%{abc", "%{abc" }, - { "%{%{a}", "%{hi" }, - { "%{%{a}}", "ho" }, - { "%{%{a}}}post", "ho}post" }, - { "%{hi%{a}}", "bar" }, - { "%{hi%{%{foo}}}", "bar" }, - { "%{hihi/b/c}", "car" }, - { "%{hihi/a/}", "br" }, // empty replacement - { "%{hihi/b}", "bar" }, // incomplete substitution - { "%{hihi/./c}", "car" }, - { "%{hihi//./c}", "ccc" }, - { "%{hihi/(.)(.)r/\\2\\1c}", "abc" }, // no escape for capture groups - { "%{hihi/b/c/d}", "c/dar" }, - { "%{hihi/a/e{\\}e}", "be{}er" }, // escape closing brace - { "%{slash/o\\/b/ol's c}", "fool's car" }, - { "%{sl\\/sh/(.)(a)(.)/\\2\\1\\3as}", "salsash" }, // escape in variable name - { "%{JS:foo/b/c}", "%{JS:foo/b/c}" }, // No replacement for JS (all considered varName) - { "%{%{a}%{a}/b/c}", "car" }, - { "%{nonsense:-sense}", "sense" }, + {"text", "text"}, + {"%{a}", "hi"}, + {"%%{a}", "%hi"}, + {"%%%{a}", "%%hi"}, + {"%{b}", "%{b}"}, + {"pre%{a}", "prehi"}, + {"%{a}post", "hipost"}, + {"pre%{a}post", "prehipost"}, + {"%{a}%{a}", "hihi"}, + {"%{a}text%{a}", "hitexthi"}, + {"%{foo}%{a}text%{a}", "ahitexthi"}, + {"%{}{a}", "%{a}"}, + {"%{}", "%"}, + {"test%{}", "test%"}, + {"%{}test", "%test"}, + {"%{abc", "%{abc"}, + {"%{%{a}", "%{hi"}, + {"%{%{a}}", "ho"}, + {"%{%{a}}}post", "ho}post"}, + {"%{hi%{a}}", "bar"}, + {"%{hi%{%{foo}}}", "bar"}, + {"%{hihi/b/c}", "car"}, + {"%{hihi/a/}", "br"}, // empty replacement + {"%{hihi/b}", "bar"}, // incomplete substitution + {"%{hihi/./c}", "car"}, + {"%{hihi//./c}", "ccc"}, + {"%{hihi/(.)(.)r/\\2\\1c}", "abc"}, // no escape for capture groups + {"%{hihi/b/c/d}", "c/dar"}, + {"%{hihi/a/e{\\}e}", "be{}er"}, // escape closing brace + {"%{slash/o\\/b/ol's c}", "fool's car"}, + {"%{sl\\/sh/(.)(a)(.)/\\2\\1\\3as}", "salsash"}, // escape in variable name + {"%{JS:foo/b/c}", "%{JS:foo/b/c}"}, // No replacement for JS (all considered varName) + {"%{%{a}%{a}/b/c}", "car"}, + {"%{nonsense:-sense}", "sense"}, }; for (unsigned i = 0; i < sizeof(vals)/sizeof(vals[0]); i++) diff --git a/tests/auto/utils/utils.pro b/tests/auto/utils/utils.pro index 884634641e..f5d9e94b00 100644 --- a/tests/auto/utils/utils.pro +++ b/tests/auto/utils/utils.pro @@ -3,6 +3,7 @@ TEMPLATE = subdirs SUBDIRS = \ fileutils \ ansiescapecodehandler \ + objectpool \ stringutils \ templateengine \ treemodel diff --git a/tests/auto/utils/utils.qbs b/tests/auto/utils/utils.qbs index 1917c51df2..4389b5b477 100644 --- a/tests/auto/utils/utils.qbs +++ b/tests/auto/utils/utils.qbs @@ -6,6 +6,7 @@ Project { "fileutils/fileutils.qbs", "ansiescapecodehandler/ansiescapecodehandler.qbs", "stringutils/stringutils.qbs", + "objectpool/objectpool.qbs", "templateengine/templateengine.qbs", "treemodel/treemodel.qbs", ] diff --git a/tests/auto/valgrind/memcheck/testapps/overlap/overlap.pro b/tests/auto/valgrind/memcheck/testapps/overlap/overlap.pro index 2614ae24a5..4ed187b29d 100644 --- a/tests/auto/valgrind/memcheck/testapps/overlap/overlap.pro +++ b/tests/auto/valgrind/memcheck/testapps/overlap/overlap.pro @@ -3,7 +3,7 @@ TARGET = overlap CONFIG += debug console CONFIG -= qt -!msvc: QMAKE_CXXFLAGS = -O0 -fno-builtin +!msvc: QMAKE_CXXFLAGS *= -O0 -fno-builtin macx:CONFIG -= app_bundle diff --git a/tests/manual/debugger/simple/simple_test_app.cpp b/tests/manual/debugger/simple/simple_test_app.cpp index b1fbf25706..7f72bba0fe 100644 --- a/tests/manual/debugger/simple/simple_test_app.cpp +++ b/tests/manual/debugger/simple/simple_test_app.cpp @@ -435,7 +435,7 @@ namespace peekandpoke { struct { int i; int b; }; struct { float f; }; double d; - } a = { { 42, 43 } }; + } a = {{42, 43}}; BREAK_HERE; // Expand a. // CheckType a union {...}. @@ -669,7 +669,7 @@ namespace qbytearray { void testQByteArray4() { - char data[] = { 'H', 'e', 'l', 'l', 'o' }; + char data[] = {'H', 'e', 'l', 'l', 'o'}; QByteArray ba1 = QByteArray::fromRawData(data, 4); QByteArray ba2 = QByteArray::fromRawData(data + 1, 4); BREAK_HERE; @@ -2279,10 +2279,10 @@ namespace qregion { BREAK_HERE; // Check region <4 items> QRegion. // Continue. - QVector<int> vv = { 1, 2, 3 }; + QVector<int> vv = {1, 2, 3}; dummyStatement(®ion, &vv); QRect x(12, 34, 66, 77); - QVector<QRect> rr = { {1, 2, 3, 4}, {5, 6, 7, 8} }; + QVector<QRect> rr = {{1, 2, 3, 4}, {5, 6, 7, 8}}; dummyStatement(®ion, &vv, &rr, &x); #endif } @@ -2650,8 +2650,8 @@ namespace stdarray { void testStdArray() { #if USE_CXX11LIB - std::array<int, 4> a = { { 1, 2, 3, 4} }; - std::array<QString, 4> b = { { "1", "2", "3", "4"} }; + std::array<int, 4> a = {{1, 2, 3, 4}}; + std::array<QString, 4> b = {{"1", "2", "3", "4"}}; BREAK_HERE; // Expand a. // Check a <4 items> std::array<int, 4u>. @@ -4063,7 +4063,7 @@ namespace qstring { void testQString2() { - QChar data[] = { 'H', 'e', 'l', 'l', 'o' }; + QChar data[] = {'H', 'e', 'l', 'l', 'o'}; QString str1 = QString::fromRawData(data, 4); QString str2 = QString::fromRawData(data + 1, 4); BREAK_HERE; @@ -4197,7 +4197,7 @@ namespace formats { // Windows: Select UTF-16 in "Change Format for Type" in L&W context menu. // Other: Select UCS-6 in "Change Format for Type" in L&W context menu. - const unsigned char uu[] = { 'a', 153 /* ö Latin1 */, 'a' }; + const unsigned char uu[] = {'a', 153 /* ö Latin1 */, 'a'}; const unsigned char *u = uu; BREAK_HERE; // CheckType u unsigned char *. @@ -4956,10 +4956,10 @@ namespace gccextensions { void testGccExtensions() { #ifdef __GNUC__ - char v[8] = { 1, 2 }; - char w __attribute__ ((vector_size (8))) = { 1, 2 }; - int y[2] = { 1, 2 }; - int z __attribute__ ((vector_size (8))) = { 1, 2 }; + char v[8] = {1, 2}; + char w __attribute__ ((vector_size (8))) = {1, 2}; + int y[2] = {1, 2}; + int z __attribute__ ((vector_size (8))) = {1, 2}; BREAK_HERE; // Expand v. // Check v.0 1 char. @@ -5193,7 +5193,7 @@ namespace basic { dummyStatement(&s); } - static char buf[20] = { 0 }; + static char buf[20] = {0}; void testCharStar() { diff --git a/tests/manual/fakevim/main.cpp b/tests/manual/fakevim/main.cpp index 4250676dea..7c364c09ad 100644 --- a/tests/manual/fakevim/main.cpp +++ b/tests/manual/fakevim/main.cpp @@ -36,8 +36,6 @@ using namespace FakeVim::Internal; -typedef QLatin1String _; - /** * Simple editor widget. * @tparam TextEdit QTextEdit or QPlainTextEdit as base class @@ -46,9 +44,10 @@ template <typename TextEdit> class Editor : public TextEdit { public: - Editor(QWidget *parent = 0) : TextEdit(parent) + Editor() { TextEdit::setCursorWidth(0); + TextEdit::setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); } void paintEvent(QPaintEvent *e) @@ -62,7 +61,7 @@ public: if ( TextEdit::overwriteMode() ) { QFontMetrics fm(TextEdit::font()); - rect.setWidth(fm.width(QLatin1Char('m'))); + rect.setWidth(fm.width('m')); painter.setPen(Qt::NoPen); painter.setBrush(TextEdit::palette().color(QPalette::Base)); painter.setCompositionMode(QPainter::CompositionMode_Difference); @@ -80,27 +79,29 @@ class Proxy : public QObject Q_OBJECT public: - Proxy(QWidget *widget, QMainWindow *mw, QObject *parent = 0) - : QObject(parent), m_widget(widget), m_mainWindow(mw) + Proxy(QMainWindow *mw) + : m_mainWindow(mw) {} - void changeSelection(const QList<QTextEdit::ExtraSelection> &s) + void changeSelection(FakeVimHandler *handler, const QList<QTextEdit::ExtraSelection> &s) { - if (QPlainTextEdit *ed = qobject_cast<QPlainTextEdit *>(m_widget)) + QWidget *widget = handler->widget(); + if (auto ed = qobject_cast<QPlainTextEdit *>(widget)) ed->setExtraSelections(s); - else if (QTextEdit *ed = qobject_cast<QTextEdit *>(m_widget)) + else if (auto ed = qobject_cast<QTextEdit *>(widget)) ed->setExtraSelections(s); } - void changeStatusData(const QString &info) + void changeStatusData(FakeVimHandler *, const QString &info) { m_statusData = info; updateStatusBar(); } - void highlightMatches(const QString &pattern) + void highlightMatches(FakeVimHandler *handler, const QString &pattern) { - QTextEdit *ed = qobject_cast<QTextEdit *>(m_widget); + QWidget *widget = handler->widget(); + auto ed = qobject_cast<QTextEdit *>(widget); if (!ed) return; @@ -136,39 +137,36 @@ public: } } - void changeStatusMessage(const QString &contents, int cursorPos) + void changeStatusMessage(FakeVimHandler *, const QString &contents, int cursorPos) { m_statusMessage = cursorPos == -1 ? contents : contents.left(cursorPos) + QChar(10073) + contents.mid(cursorPos); updateStatusBar(); } - void changeExtraInformation(const QString &info) + void changeExtraInformation(FakeVimHandler *handler, const QString &info) { - QMessageBox::information(m_widget, tr("Information"), info); + QMessageBox::information(handler->widget(), tr("Information"), info); } void updateStatusBar() { int slack = 80 - m_statusMessage.size() - m_statusData.size(); - QString msg = m_statusMessage + QString(slack, QLatin1Char(' ')) + m_statusData; + QString msg = m_statusMessage + QString(slack, ' ') + m_statusData; m_mainWindow->statusBar()->showMessage(msg); } - void handleExCommand(bool *handled, const ExCommand &cmd) + void handleExCommand(FakeVimHandler *, bool *handled, const ExCommand &cmd) { - if (cmd.matches(_("q"), _("quit")) || cmd.matches(_("qa"), _("qall"))) { + if (cmd.matches("q", "quit") || cmd.matches("qa", "qall")) { QApplication::quit(); + *handled = true; } else { *handled = false; - return; } - - *handled = true; } private: - QWidget *m_widget; QMainWindow *m_mainWindow; QString m_statusMessage; QString m_statusData; @@ -177,16 +175,11 @@ private: QWidget *createEditorWidget(bool usePlainTextEdit) { QWidget *editor = 0; - if (usePlainTextEdit) { - Editor<QPlainTextEdit> *w = new Editor<QPlainTextEdit>; - w->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); - editor = w; - } else { - Editor<QTextEdit> *w = new Editor<QTextEdit>; - w->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); - editor = w; - } - editor->setObjectName(_("Editor")); + if (usePlainTextEdit) + editor = new Editor<QPlainTextEdit>; + else + editor = new Editor<QTextEdit>; + editor->setObjectName("Editor"); editor->setFocus(); return editor; @@ -195,13 +188,13 @@ QWidget *createEditorWidget(bool usePlainTextEdit) void initHandler(FakeVimHandler &handler) { // Set some Vim options. - handler.handleCommand(_("set expandtab")); - handler.handleCommand(_("set shiftwidth=8")); - handler.handleCommand(_("set tabstop=16")); - handler.handleCommand(_("set autoindent")); + handler.handleCommand("set expandtab"); + handler.handleCommand("set shiftwidth=8"); + handler.handleCommand("set tabstop=16"); + handler.handleCommand("set autoindent"); // Try to source file "fakevimrc" from current directory. - handler.handleCommand(_("source fakevimrc")); + handler.handleCommand("source fakevimrc"); handler.installEventFilter(); handler.setupWidget(); @@ -209,7 +202,7 @@ void initHandler(FakeVimHandler &handler) void initMainWindow(QMainWindow &mainWindow, QWidget *centralWidget, const QString &title) { - mainWindow.setWindowTitle(QString(_("FakeVim (%1)")).arg(title)); + mainWindow.setWindowTitle(QString("FakeVim (%1)").arg(title)); mainWindow.setCentralWidget(centralWidget); mainWindow.resize(600, 650); mainWindow.move(0, 0); @@ -217,14 +210,14 @@ void initMainWindow(QMainWindow &mainWindow, QWidget *centralWidget, const QStri // Set monospace font for editor and status bar. QFont font = QApplication::font(); - font.setFamily(_("Monospace")); + font.setFamily("Monospace"); centralWidget->setFont(font); mainWindow.statusBar()->setFont(font); } void readFile(FakeVimHandler &handler, const QString &editFileName) { - handler.handleCommand(QString(_("r %1")).arg(editFileName)); + handler.handleCommand("r " + editFileName); } void connectSignals(FakeVimHandler &handler, Proxy &proxy) @@ -252,20 +245,20 @@ int main(int argc, char *argv[]) // If first argument is present use QPlainTextEdit instead on QTextEdit; bool usePlainTextEdit = args.size() > 1; // Second argument is path to file to edit. - const QString editFileName = args.value(2, QString(_("/usr/share/vim/vim73/tutor/tutor"))); + const QString editFileName = args.value(2, "/usr/share/vim/vim73/tutor/tutor"); // Create editor widget. QWidget *editor = createEditorWidget(usePlainTextEdit); // Create FakeVimHandler instance which will emulate Vim behavior in editor widget. - FakeVimHandler handler(editor, 0); + FakeVimHandler handler(editor, nullptr); // Create main window. QMainWindow mainWindow; - initMainWindow(mainWindow, editor, usePlainTextEdit ? _("QPlainTextEdit") : _("QTextEdit")); + initMainWindow(mainWindow, editor, usePlainTextEdit ? "QPlainTextEdit" : "QTextEdit"); // Connect slots to FakeVimHandler signals. - Proxy proxy(editor, &mainWindow); + Proxy proxy(&mainWindow); connectSignals(handler, proxy); // Initialize FakeVimHandler. diff --git a/tests/manual/ssh/sftpfsmodel/window.cpp b/tests/manual/ssh/sftpfsmodel/window.cpp index 79a05fad38..90e9906b14 100644 --- a/tests/manual/ssh/sftpfsmodel/window.cpp +++ b/tests/manual/ssh/sftpfsmodel/window.cpp @@ -82,7 +82,7 @@ void SftpFsWindow::downloadFile() const QModelIndexList selectedIndexes = m_ui->fsView->selectionModel()->selectedIndexes(); if (selectedIndexes.count() != 2) return; - const QString targetFilePath = QFileDialog::getSaveFileName(this, tr("Choose target file"), + const QString targetFilePath = QFileDialog::getSaveFileName(this, tr("Choose Target File"), QDir::tempPath()); if (targetFilePath.isEmpty()) return; diff --git a/tests/system/objects.map b/tests/system/objects.map index baf4e82e8a..edca350cec 100644 --- a/tests/system/objects.map +++ b/tests/system/objects.map @@ -136,7 +136,6 @@ :Qt Creator.Replace All_QToolButton {name='replaceAllButton' text='Replace All' type='QToolButton' visible='1' window=':Qt Creator_Core::Internal::MainWindow'} :Qt Creator.Replace_QToolButton {name='replaceButton' text='Replace' type='QToolButton' visible='1' window=':Qt Creator_Core::Internal::MainWindow'} :Qt Creator.Stop_QToolButton {text='Stop' type='QToolButton' unnamed='1' visible='1' window=':Qt Creator_Core::Internal::MainWindow'} -:Qt Creator.WelcomePage_QQuickWidget {name='WelcomePage' type='QQuickWidget' visible='1' window=':Qt Creator_Core::Internal::MainWindow'} :Qt Creator.replaceEdit_Utils::FilterLineEdit {name='replaceEdit' type='Utils::FancyLineEdit' visible='1' window=':Qt Creator_Core::Internal::MainWindow'} :Qt Creator.scrollArea_QScrollArea {type='ProjectExplorer::PanelsWidget' visible='1' window=':Qt Creator_Core::Internal::MainWindow'} :Qt Creator.splitter_QSplitter {name='splitter' type='QSplitter' visible='1' window=':Qt Creator_Core::Internal::MainWindow'} diff --git a/tests/system/shared/project.py b/tests/system/shared/project.py index 0e2bdd9e35..5caf3ee601 100644 --- a/tests/system/shared/project.py +++ b/tests/system/shared/project.py @@ -34,10 +34,11 @@ def openQbsProject(projectPath): def openQmakeProject(projectPath, targets=Targets.desktopTargetClasses(), fromWelcome=False): cleanUpUserFiles(projectPath) if fromWelcome: - welcomePage = ":Qt Creator.WelcomePage_QQuickWidget" - mouseClick(waitForObject("{clip='false' container='%s' enabled='true' text='Open Project' " - "type='Button' unnamed='1' visible='true'}" % welcomePage), - 5, 5, 0, Qt.LeftButton) + wsButtonFrame, wsButtonLabel = getWelcomeScreenMainButton('Open Project') + if not all((wsButtonFrame, wsButtonLabel)): + test.fatal("Could not find 'Open Project' button on Welcome Page.") + return [] + mouseClick(wsButtonLabel) else: invokeMenuItem("File", "Open File or Project...") selectFromFileDialog(projectPath) @@ -82,10 +83,11 @@ def openCmakeProject(projectPath, buildDir): # this list can be used in __chooseTargets__() def __createProjectOrFileSelectType__(category, template, fromWelcome = False, isProject=True): if fromWelcome: - welcomePage = ":Qt Creator.WelcomePage_QQuickWidget" - mouseClick(waitForObject("{clip='false' container='%s' enabled='true' text='New Project' " - "type='Button' unnamed='1' visible='true'}" % welcomePage), - 5, 5, 0, Qt.LeftButton) + wsButtonFrame, wsButtonLabel = getWelcomeScreenMainButton("New Project") + if not all((wsButtonFrame, wsButtonLabel)): + test.fatal("Could not find 'New Project' button on Welcome Page") + return [] + mouseClick(wsButtonLabel) else: invokeMenuItem("File", "New File or Project...") categoriesView = waitForObject(":New.templateCategoryView_QTreeView") @@ -122,6 +124,24 @@ def __createProjectSetNameAndPath__(path, projectName = None, checks = True, lib clickButton(waitForObject(":Next_QPushButton")) return str(projectName) +def __handleBuildSystem__(buildSystem): + combo = "{name='BuildSystem' type='Utils::TextFieldComboBox' visible='1'}" + try: + comboObj = waitForObject(combo, 2000) + except: + test.warning("No build system combo box found at all.") + return + try: + if buildSystem is None: + test.log("Keeping default build system '%s'" % str(comboObj.currentText)) + else: + test.log("Trying to select build system '%s'" % buildSystem) + selectFromCombo(combo, buildSystem) + except: + t, v = sys.exc_info()[:2] + test.warning("Exception while handling build system", "%s(%s)" % (str(t), str(v))) + clickButton(waitForObject(":Next_QPushButton")) + def __createProjectHandleQtQuickSelection__(minimumQtVersion): comboBox = waitForObject("{leftWidget=':Minimal required Qt version:_QLabel' name='QtVersion' " "type='Utils::TextFieldComboBox' visible='1'}") @@ -238,9 +258,10 @@ def createProject_Qt_GUI(path, projectName, checks = True, addToVersionControl = # param path specifies where to create the project # param projectName is the name for the new project # param checks turns tests in the function on if set to True -def createProject_Qt_Console(path, projectName, checks = True): +def createProject_Qt_Console(path, projectName, checks = True, buildSystem = None): available = __createProjectOrFileSelectType__(" Application", "Qt Console Application") __createProjectSetNameAndPath__(path, projectName, checks) + __handleBuildSystem__(buildSystem) checkedTargets = __selectQtVersionDesktop__(checks, available) expectedFiles = [] @@ -261,13 +282,14 @@ def createProject_Qt_Console(path, projectName, checks = True): def createNewQtQuickApplication(workingDir, projectName = None, targets=Targets.desktopTargetClasses(), minimumQtVersion="5.3", - withControls = False, fromWelcome=False): + withControls = False, fromWelcome = False, buildSystem = None): if withControls: template = "Qt Quick Controls Application" else: template = "Qt Quick Application" available = __createProjectOrFileSelectType__(" Application", template, fromWelcome) projectName = __createProjectSetNameAndPath__(workingDir, projectName) + __handleBuildSystem__(buildSystem) requiredQt = __createProjectHandleQtQuickSelection__(minimumQtVersion) __modifyAvailableTargets__(available, requiredQt) checkedTargets = __chooseTargets__(targets, available) @@ -281,12 +303,8 @@ def createNewQtQuickApplication(workingDir, projectName = None, return checkedTargets, projectName -def createNewQtQuickUI(workingDir, qtVersion = "5.3", withControls = False): - if withControls: - template = 'Qt Quick Controls UI' - else: - template = 'Qt Quick UI' - __createProjectOrFileSelectType__(" Other Project", template) +def createNewQtQuickUI(workingDir, qtVersion = "5.3"): + __createProjectOrFileSelectType__(" Other Project", 'Qt Quick UI Prototype') if workingDir == None: workingDir = tempDir() projectName = __createProjectSetNameAndPath__(workingDir) diff --git a/tests/system/shared/qtcreator.py b/tests/system/shared/qtcreator.py index 5e2ebeae64..afed6c118d 100644 --- a/tests/system/shared/qtcreator.py +++ b/tests/system/shared/qtcreator.py @@ -52,6 +52,7 @@ source("../../shared/project_explorer.py") source("../../shared/hook_utils.py") source("../../shared/debugger.py") source("../../shared/clang.py") +source("../../shared/welcome.py") source("../../shared/workarounds.py") # include this at last # ATTENTION: if a test case calls startApplication("qtcreator...") for several times this diff --git a/tests/system/shared/welcome.py b/tests/system/shared/welcome.py new file mode 100644 index 0000000000..e5a900ee1f --- /dev/null +++ b/tests/system/shared/welcome.py @@ -0,0 +1,63 @@ +############################################################################ +# +# Copyright (C) 2017 The Qt Company Ltd. +# Contact: https://www.qt.io/licensing/ +# +# This file is part of Qt Creator. +# +# Commercial License Usage +# Licensees holding valid commercial Qt licenses may use this file in +# accordance with the commercial license agreement provided with the +# Software or, alternatively, in accordance with the terms contained in +# a written agreement between you and The Qt Company. For licensing terms +# and conditions see https://www.qt.io/terms-conditions. For further +# information use the contact form at https://www.qt.io/contact-us. +# +# GNU General Public License Usage +# Alternatively, this file may be used under the terms of the GNU +# General Public License version 3 as published by the Free Software +# Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +# included in the packaging of this file. Please review the following +# information to ensure the GNU General Public License requirements will +# be met: https://www.gnu.org/licenses/gpl-3.0.html. +# +############################################################################ + +def __getWelcomeScreenButtonHelper__(buttonLabel, widgetWithQFrames): + frames = [child for child in object.children(widgetWithQFrames) if className(child) == 'QFrame'] + for frame in frames: + label = getChildByClass(frame, 'QLabel') + if str(label.text) == buttonLabel: + return frame, label + return None, None + +def getWelcomeScreenSideBarButton(buttonLabel): + sideBar = waitForObject("{type='Welcome::Internal::SideBar' unnamed='1' " + "window=':Qt Creator_Core::Internal::MainWindow'}") + return __getWelcomeScreenButtonHelper__(buttonLabel, sideBar) + +def getWelcomeScreenMainButton(buttonLabel): + stackedWidget = waitForObject("{type='QWidget' unnamed='1' visible='1' " + "leftWidget={type='QWidget' unnamed='1' visible='1' " + "leftWidget={type='Welcome::Internal::SideBar' unnamed='1' " + "window=':Qt Creator_Core::Internal::MainWindow'}}}") + currentStackWidget = stackedWidget.currentWidget() + return __getWelcomeScreenButtonHelper__(buttonLabel, currentStackWidget) + +def getWelcomeTreeView(treeViewLabel): + try: + return waitForObject("{aboveWidget={text='%s' type='QLabel' unnamed='1' visible='1' " + "window=':Qt Creator_Core::Internal::MainWindow'} " + "type='QTreeView' unnamed='1' visible='1'}" % treeViewLabel) + except: + return None + +def findExampleOrTutorial(tableView, regex, verbose=False): + model = tableView.model() + children = [ch for ch in object.children(tableView) if className(ch) == 'QModelIndex'] + for child in children: + if re.match(regex, str(child.text)): + if verbose: + test.log("Returning matching example/tutorial '%s'." % str(child.text), regex) + return child + return None diff --git a/tests/system/suite_WELP/tst_WELP01/test.py b/tests/system/suite_WELP/tst_WELP01/test.py index 00db463f3e..ffc16e087d 100755 --- a/tests/system/suite_WELP/tst_WELP01/test.py +++ b/tests/system/suite_WELP/tst_WELP01/test.py @@ -24,34 +24,56 @@ ############################################################################ source("../../shared/qtcreator.py") -source("../../shared/suites_qtta.py") -welcomePage = ":Qt Creator.WelcomePage_QQuickWidget" -gettingStartedText = getQmlItem("Button", welcomePage, False, - "text='Get Started Now' id='gettingStartedButton'") +getStarted = 'Get Started Now' -def clickItemVerifyHelpCombo(qmlItem, expectedHelpComboRegex, testDetails): - global gettingStartedText - mouseClick(waitForObject(qmlItem), 5, 5, 0, Qt.LeftButton) +def clickItemVerifyHelpCombo(button, expectedHelpComboRegex, testDetails): + global getStarted + mouseClick(button) helpCombo = waitForObject(":Qt Creator_HelpSelector_QComboBox") if not test.verify(waitFor('re.match(expectedHelpComboRegex, str(helpCombo.currentText))', 5000), testDetails): test.log("Found %s" % str(helpCombo.currentText)) # select "Welcome" page from left toolbar again switchViewTo(ViewConstants.WELCOME) - test.verify(checkIfObjectExists(gettingStartedText), - "Verifying: Get Started Now button is being displayed.") + wsButtonFrame, wsButtonLabel = getWelcomeScreenSideBarButton(getStarted) + return test.verify(all((wsButtonFrame, wsButtonLabel)), + "Verifying: '%s' button is being displayed." % getStarted) +def buttonActive(button): + # colors of the default theme for active button on Welcome page + (activeRed, activeGreen, activeBlue) = (64, 66, 68) + # QPalette::Window (used background color of Welcome page buttons) + enumQPaletteWindow = 10 + color = button.palette.color(enumQPaletteWindow) + return color.red == activeRed and color.green == activeGreen and color.blue == activeBlue -def waitForButtonsState(projectsChecked, examplesChecked, tutorialsChecked, timeout=5000): - projButton = waitForObject(getQmlItem("Button", welcomePage, False, "text='Projects'")) - exmpButton = waitForObject(getQmlItem("Button", welcomePage, False, "text='Examples'")) - tutoButton = waitForObject(getQmlItem("Button", welcomePage, False, "text='Tutorials'")) - return waitFor('projButton.checked == projectsChecked ' - 'and exmpButton.checked == examplesChecked ' - 'and tutoButton.checked == tutorialsChecked', timeout) +def waitForButtonsState(projectsActive, examplesActive, tutorialsActive, timeout=5000): + projButton = getWelcomeScreenSideBarButton('Projects')[0] + exmpButton = getWelcomeScreenSideBarButton('Examples')[0] + tutoButton = getWelcomeScreenSideBarButton('Tutorials')[0] + if not all((projButton, exmpButton, tutoButton)): + return False + return waitFor('buttonActive(projButton) == projectsActive ' + 'and buttonActive(exmpButton) == examplesActive ' + 'and buttonActive(tutoButton) == tutorialsActive', timeout) + +def checkTableViewForContent(tableViewStr, expectedRegExTitle, section, atLeastOneText): + try: + tableView = findObject(tableViewStr) # waitForObject does not work - visible is 0? + model = tableView.model() + + children = [ch for ch in object.children(tableView) if className(ch) == 'QModelIndex'] + for child in children: + match = re.match(expectedRegExTitle, str(model.data(child).toString())) + if match: + test.passes(atLeastOneText, "Found '%s'" % match.group()) + return + test.fail("No %s are displayed on Welcome page (%s)" % (section.lower(), section)) + except: + test.fail("Failed to get tableview to check content of Welcome page (%s)" % section) def main(): - global gettingStartedText + global getStarted # open Qt Creator startApplication("qtcreator" + SettingsPath) if not startedWithoutPluginError(): @@ -60,72 +82,84 @@ def main(): setAlwaysStartFullHelp() addCurrentCreatorDocumentation() - buttonsAndState = {'Projects':True, 'Examples':False, 'Tutorials':False, 'New Project':False, - 'Open Project':False} + buttonsAndState = {'Projects':True, 'Examples':False, 'Tutorials':False} for button, state in buttonsAndState.items(): - qmlItem = getQmlItem("Button", welcomePage, False, "text='%s'" % button) - if test.verify(checkIfObjectExists(qmlItem), - "Verifying whether '%s' button is shown." % button): - buttonObj = findObject(qmlItem) - test.compare(buttonObj.checked, state, "Verifying whether '%s' button is checked." - % button) + wsButtonFrame, wsButtonLabel = getWelcomeScreenSideBarButton(button) + if test.verify(all((wsButtonFrame, wsButtonLabel)), + "Verified whether '%s' button is shown." % button): + test.compare(buttonActive(wsButtonFrame), state, + "Verifying whether '%s' button is active (%s)." % (button, state)) + + for button in ['New Project', 'Open Project']: + wsButtonFrame, wsButtonLabel = getWelcomeScreenMainButton(button) + if test.verify(all((wsButtonFrame, wsButtonLabel)), + "Verified whether '%s' button is shown." % button): + test.verify(not buttonActive(wsButtonFrame), + "Verifying whether '%s' button is inactive." % button) - test.verify(checkIfObjectExists(gettingStartedText), - "Verifying: Qt Creator displays Welcome Page with 'Get Started Now' button.") - clickItemVerifyHelpCombo(gettingStartedText, "Qt Creator Manual", - "Verifying: Help with Creator Documentation is being opened.") - textUrls = {'Online Community':'http://forum.qt.io', - 'Blogs':'http://planet.qt.io', - 'Qt Account':'https://account.qt.io', - 'User Guide':'qthelp://org.qt-project.qtcreator/doc/index.html' - } - for text, url in textUrls.items(): - qmlItem = getQmlItem("Text", welcomePage, False, "text='%s'" % text) - if test.verify(checkIfObjectExists(qmlItem), - "Verifying: Link to %s exists." % text): - itemObj = findObject(qmlItem) - # some URLs might have varying parameters - limiting them to URL without a query - if url.startswith("qthelp"): - relevantUrlPart = str(itemObj.parent.openHelpUrl).split("?")[0] - else: - relevantUrlPart = str(itemObj.parent.openUrl).split("?")[0] - test.compare(relevantUrlPart, url, "Verifying link.") + wsButtonFrame, wsButtonLabel = getWelcomeScreenSideBarButton(getStarted) + if test.verify(all((wsButtonFrame, wsButtonLabel)), + "Verifying: Qt Creator displays Welcome Page with '%s' button." % getStarted): + if clickItemVerifyHelpCombo(wsButtonLabel, "Qt Creator Manual", + "Verifying: Help with Creator Documentation is being opened."): - mouseClick(gettingStartedText, 5, 5, 0, Qt.LeftButton) - qcManualQModelIndexStr = getQModelIndexStr("text~='Qt Creator Manual [0-9.]+'", - ":Qt Creator_QHelpContentWidget") - if str(waitForObject(":Qt Creator_HelpSelector_QComboBox").currentText) == "(Untitled)": - mouseClick(qcManualQModelIndexStr, 5, 5, 0, Qt.LeftButton) - test.warning("Clicking 'Get Started Now' the second time showed blank page (Untitled)") + textUrls = {'Online Community':'http://forum.qt.io', + 'Blogs':'http://planet.qt.io', + 'Qt Account':'https://account.qt.io', + 'User Guide':'qthelp://org.qt-project.qtcreator/doc/index.html' + } + for text, url in textUrls.items(): + test.verify(checkIfObjectExists("{type='QLabel' text='%s' unnamed='1' visible='1' " + "window=':Qt Creator_Core::Internal::MainWindow'}" + % text), + "Verifying whether link button (%s) exists." % text) + # TODO find way to verify URLs (or tweak source code of Welcome page to become able) + wsButtonFrame, wsButtonLabel = getWelcomeScreenSideBarButton(getStarted) + if wsButtonLabel is not None: + mouseClick(wsButtonLabel) + qcManualQModelIndexStr = getQModelIndexStr("text~='Qt Creator Manual [0-9.]+'", + ":Qt Creator_QHelpContentWidget") + if str(waitForObject(":Qt Creator_HelpSelector_QComboBox").currentText) == "(Untitled)": + mouseClick(qcManualQModelIndexStr) + test.warning("Clicking '%s' the second time showed blank page (Untitled)" % getStarted) + else: + test.fatal("Something's wrong - failed to find/click '%s' the second time." % getStarted) # select "Welcome" page from left toolbar again switchViewTo(ViewConstants.WELCOME) - test.verify(checkIfObjectExists(gettingStartedText), + wsButtonFrame, wsButtonLabel = getWelcomeScreenSideBarButton(getStarted) + test.verify(wsButtonFrame is not None and wsButtonLabel is not None, "Verifying: Getting Started topic is being displayed.") # select Examples and roughly check them - mouseClick(waitForObject(getQmlItem("Button", welcomePage, False, "text='Examples'")), - 5, 5, 0, Qt.LeftButton) - waitForButtonsState(False, True, False) - expect = (("Rectangle", "id='rectangle1' radius='0'", "examples rectangle"), - ("TextField", "id='lineEdit' placeholderText='Search in Examples...'", - "examples search line edit"), - ("ComboBox", "id='comboBox'", "Qt version combo box"), - ("Delegate", "id='delegate' radius='0' caption~='.*Example'", "at least one example") - ) + wsButtonFrame, wsButtonLabel = getWelcomeScreenSideBarButton('Examples') + if all((wsButtonFrame, wsButtonLabel)): + mouseClick(wsButtonLabel) + test.verify(waitForButtonsState(False, True, False), "Buttons' states have changed.") + + expect = (("QTableView", "unnamed='1' visible='1' window=':Qt Creator_Core::Internal::MainWindow'", + "examples list"), + ("QLineEdit", "placeholderText='Search in Examples...'", "examples search line edit"), + ("QComboBox", "text~='.*Qt.*'", "Qt version combo box")) + search = "{type='%s' %s}" for (qType, prop, info) in expect: - test.verify(checkIfObjectExists(getQmlItem(qType, welcomePage, None, prop)), + test.verify(checkIfObjectExists(search % (qType, prop)), "Verifying whether %s is shown" % info) + checkTableViewForContent(search % (expect[0][0], expect[0][1]), ".*Example", "Examples", + "Verifying that at least one example is displayed.") + # select Tutorials and roughly check them - mouseClick(waitForObject(getQmlItem("Button", welcomePage, False, "text='Tutorials'")), - 5, 5, 0, Qt.LeftButton) - waitForButtonsState(False, False, True) - expect = (("Rectangle", "id='rectangle1' radius='0'", "tutorials rectangle"), - ("TextField", "id='lineEdit' placeholderText='Search in Tutorials...'", - "tutorials search line edit"), - ("Delegate", "id='delegate' radius='0' caption~='Creating.*'", "at least one tutorial") - ) + wsButtonFrame, wsButtonLabel = getWelcomeScreenSideBarButton('Tutorials') + if all((wsButtonFrame, wsButtonLabel)): + mouseClick(wsButtonLabel) + test.verify(waitForButtonsState(False, False, True), "Buttons' states have changed.") + expect = (("QTableView", "unnamed='1' visible='1' window=':Qt Creator_Core::Internal::MainWindow'", + "tutorials list"), + ("QLineEdit", "placeholderText='Search in Tutorials...'", + "tutorials search line edit")) for (qType, prop, info) in expect: - test.verify(checkIfObjectExists(getQmlItem(qType, welcomePage, None, prop)), + test.verify(checkIfObjectExists(search % (qType, prop)), "Verifying whether %s is shown" % info) + checkTableViewForContent(search % (expect[0][0], expect[0][1]), "Creating.*", "Tutorials", + "Verifying that at least one tutorial is displayed.") # exit Qt Creator invokeMenuItem("File", "Exit") diff --git a/tests/system/suite_WELP/tst_WELP02/test.py b/tests/system/suite_WELP/tst_WELP02/test.py index 47baca1639..ae7b22e934 100644 --- a/tests/system/suite_WELP/tst_WELP02/test.py +++ b/tests/system/suite_WELP/tst_WELP02/test.py @@ -24,14 +24,44 @@ ############################################################################ source("../../shared/qtcreator.py") -source("../../shared/suites_qtta.py") - -welcomePage = ":Qt Creator.WelcomePage_QQuickWidget" def checkTypeAndProperties(typePropertiesDetails): for (qType, props, detail) in typePropertiesDetails: - test.verify(checkIfObjectExists(getQmlItem(qType, welcomePage, False, props)), - "Verifying: Qt Creator displays %s." % detail) + if qType == "QPushButton": + wsButtonFrame, wsButtonLabel = getWelcomeScreenSideBarButton(props) + test.verify(all((wsButtonFrame, wsButtonLabel)), + "Verifying: Qt Creator displays Welcome Page with %s." % detail) + elif qType == 'QTreeView': + treeView = getWelcomeTreeView(props) + test.verify(treeView is not None, + "Verifying: Qt Creator displays Welcome Page with %s." % detail) + elif qType == 'SessionModelIndex': + # for SessionModelIndex props must be a tuple with 2 elements, the first is just + # as for others (additional properties) while the second is either True or False and + # indicating whether to check the found index for being the default and current session + treeView = getWelcomeTreeView("Sessions") + if not treeView: + test.fatal("Failed to find Sessions tree view, cannot check for %s." % detail) + continue + indices = dumpIndices(treeView.model()) + found = False + for index in indices: + if props[0] == str(index.data()): + # 257 -> DefaultSessionRole, 259 -> ActiveSessionRole [sessionmodel.h] + isDefaultAndCurrent = index.data(257).toBool() and index.data(259).toBool() + if not props[1] or isDefaultAndCurrent: + found = True + break + test.verify(found, "Verifying: Qt Creator displays Welcome Page with %s." % detail) + elif qType == 'ProjectModelIndex': + treeView = getWelcomeTreeView("Recent Projects") + if not treeView: + test.fatal("Failed to find Projects tree view, cannot check for %s." % detail) + continue + test.verify(props in dumpItems(treeView.model()), + "Verifying: Qt Creator displays Welcome Page with %s." % detail) + else: + test.fatal("Unhandled qType '%s' found..." % qType) def main(): # prepare example project @@ -44,11 +74,10 @@ def main(): if not startedWithoutPluginError(): return - typePropDet = (("Button", "text='Get Started Now' id='gettingStartedButton'", - "Get Started Now button"), - ("Text", "text='Sessions' id='sessionsTitle'", "Sessions section"), - ("Text", "text='default'", "default session listed"), - ("Text", "text='Recent Projects' id='recentProjectsTitle'", "Projects section"), + typePropDet = (("QPushButton", "Get Started Now", "Get Started Now button"), + ("QTreeView", "Sessions", "Sessions section"), + ("SessionModelIndex", ("default", False), "default session listed"), + ("QTreeView", "Recent Projects", "Projects section") ) checkTypeAndProperties(typePropDet) @@ -59,12 +88,10 @@ def main(): "Verifying: The project is opened in 'Edit' mode after configuring.") # go to "Welcome page" again and verify updated information switchViewTo(ViewConstants.WELCOME) - typePropDet = (("Text", "text='Sessions' id='sessionsTitle'", "Sessions section"), - ("Text", "text='default (current session)'", - "default session as current listed"), - ("Text", "text='Recent Projects' id='recentProjectsTitle'", "Projects section"), - ("Text", "text='SampleApp'", - "current project listed in projects section") + typePropDet = (("QTreeView", "Sessions", "Sessions section"), + ("SessionModelIndex", ("default", True), "default session as current listed"), + ("QTreeView", "Recent Projects", "Projects section"), + ("ProjectModelIndex", "SampleApp", "current project listed in projects section") ) checkTypeAndProperties(typePropDet) @@ -77,11 +104,12 @@ def main(): "Verifying: The project is opened in 'Edit' mode after configuring.") # go to "Welcome page" again and check if there is an information about recent projects switchViewTo(ViewConstants.WELCOME) - test.verify(checkIfObjectExists(getQmlItem("Text", welcomePage, False, - "text='animation'")) and - checkIfObjectExists(getQmlItem("Text", welcomePage, False, - "text='SampleApp'")), - "Verifying: 'Welcome page' displays information about recently created and " - "opened projects.") + treeView = getWelcomeTreeView('Recent Projects') + if treeView is None: + test.fatal("Cannot verify Recent Projects on Welcome Page - failed to find tree view.") + else: + typePropDet = (("ProjectModelIndex", "animation", "one project"), + ("ProjectModelIndex", "SampleApp", "other project")) + checkTypeAndProperties(typePropDet) # exit Qt Creator invokeMenuItem("File", "Exit") diff --git a/tests/system/suite_WELP/tst_WELP03/test.py b/tests/system/suite_WELP/tst_WELP03/test.py index 8ba0263e0a..8b211d606d 100644 --- a/tests/system/suite_WELP/tst_WELP03/test.py +++ b/tests/system/suite_WELP/tst_WELP03/test.py @@ -40,8 +40,24 @@ def handlePackagingMessageBoxes(): except: break +def openExample(examplesLineEdit, input, exampleRegex, exampleName): + replaceEditorContent(examplesLineEdit, input) + tableView = waitForObject("{type='QTableView' unnamed='1' visible='1' " + "window=':Qt Creator_Core::Internal::MainWindow'}") + waitFor('findExampleOrTutorial(tableView, exampleRegex) is not None', 3000) + example = findExampleOrTutorial(tableView, exampleRegex, True) + if test.verify(example is not None, "Verifying: Example (%s) is shown." % exampleName): + mouseClick(example) + handlePackagingMessageBoxes() + helpWidget = waitForObject(":Help Widget_Help::Internal::HelpWidget") + test.verify(waitFor('exampleName in str(helpWidget.windowTitle)', 5000), + "Verifying: The example application is opened inside Help.") + sendEvent("QCloseEvent", helpWidget) + # assume the correct kit is selected, hit Configure Project + clickButton(waitForObject(":Qt Creator.Configure Project_QPushButton")) + return example + def main(): - welcomePage = ":Qt Creator.WelcomePage_QQuickWidget" # open Qt Creator startApplication("qtcreator" + SettingsPath) if not startedWithoutPluginError(): @@ -51,54 +67,50 @@ def main(): qchs.extend([os.path.join(p, "qtopengl.qch"), os.path.join(p, "qtwidgets.qch")]) addHelpDocumentation(qchs) setAlwaysStartFullHelp() - getStartedNow = getQmlItem("Button", welcomePage, False, - "text='Get Started Now' id='gettingStartedButton'") - if not test.verify(checkIfObjectExists(getStartedNow), + wsButtonFrame, wsButtonLabel = getWelcomeScreenSideBarButton('Get Started Now') + if not test.verify(all((wsButtonFrame, wsButtonLabel)), "Verifying: Qt Creator displays Welcome Page with Getting Started."): test.fatal("Something's wrong - leaving test.") invokeMenuItem("File", "Exit") return # select "Examples" topic - mouseClick(waitForObject(getQmlItem("Button", welcomePage, False, "text='Examples'")), - 5, 5, 0, Qt.LeftButton) - test.verify(checkIfObjectExists(getQmlItem("Text", welcomePage, False, "text='Examples'")), + wsButtonFrame, wsButtonLabel = getWelcomeScreenSideBarButton('Examples') + if all((wsButtonFrame, wsButtonLabel)): + mouseClick(wsButtonLabel) + expect = (("QTableView", "unnamed='1' visible='1' window=':Qt Creator_Core::Internal::MainWindow'", + "examples list"), + ("QLineEdit", "placeholderText='Search in Examples...'", "examples search line edit"), + ("QComboBox", "text~='.*Qt.*' visible='1'", "Qt version combo box")) + search = "{type='%s' %s}" + test.verify(all(map(checkIfObjectExists, (search % (exp[0], exp[1]) for exp in expect))), "Verifying: 'Examples' topic is opened and the examples are shown.") + + examplesLineEdit = waitForObject(search % (expect[1][0], expect[1][1])) + mouseClick(examplesLineEdit) + combo = waitForObject(search % (expect[2][0], expect[2][1])) + test.log("Using examples from Kit %s." % str(combo.currentText)) + replaceEditorContent(examplesLineEdit, "qwerty") + tableView = waitForObject(search % (expect[0][0], expect[0][1])) + waitFor('findExampleOrTutorial(tableView, ".*") is None', 3000) + example = findExampleOrTutorial(tableView, ".*", True) + test.verify(example is None, "Verifying: No example is shown.") + proFiles = map(lambda p: os.path.join(p, "opengl", "2dpainting", "2dpainting.pro"), Qt5Path.getPaths(Qt5Path.EXAMPLES)) cleanUpUserFiles(proFiles) for p in proFiles: removePackagingDirectory(os.path.dirname(p)) - examplesLineEdit = getQmlItem("TextField", welcomePage, - False, "id='lineEdit' placeholderText='Search in Examples...'") - mouseClick(waitForObject(examplesLineEdit), 5, 5, 0, Qt.LeftButton) - test.log("Using examples from Kit %s." - % (waitForObject(getQmlItem("ComboBox", welcomePage, - False, "id='comboBox'")).currentText)) - replaceEditorContent(waitForObject(examplesLineEdit), "qwerty") - test.verify(checkIfObjectExists(getQmlItem("Delegate", welcomePage, - False, "id='delegate' radius='0' caption~='.*'"), - False), "Verifying: No example is shown.") - replaceEditorContent(waitForObject(examplesLineEdit), "2d painting") - twoDPainting = getQmlItem("Delegate", welcomePage, - False, "id='delegate' radius='0' caption~='2D Painting.*'") - test.verify(checkIfObjectExists(twoDPainting), - "Verifying: Example (2D Painting) is shown.") - mouseClick(waitForObject(twoDPainting), 5, 5, 0, Qt.LeftButton) - handlePackagingMessageBoxes() - helpWidget = waitForObject(":Help Widget_Help::Internal::HelpWidget") - test.verify(waitFor('"2D Painting Example" in str(helpWidget.windowTitle)', 5000), - "Verifying: The example application is opened inside Help.") - sendEvent("QCloseEvent", helpWidget) - # assume the correct kit is selected, hit Configure Project - clickButton(waitForObject(":Qt Creator.Configure Project_QPushButton")) - test.verify(checkIfObjectExists("{column='0' container=':Qt Creator_Utils::NavigationTreeView'" - " text='2dpainting' type='QModelIndex'}"), - "Verifying: The project is shown in 'Edit' mode.") - invokeContextMenuOnProject('2dpainting', 'Close Project "2dpainting"') - navTree = waitForObject(":Qt Creator_Utils::NavigationTreeView") - res = waitFor("navTree.model().rowCount(navTree.rootIndex()) == 0", 2000) - test.verify(not checkIfObjectItemExists(":Qt Creator_Utils::NavigationTreeView", "2dpainting"), - "Verifying: The first example is closed.") + + example = openExample(examplesLineEdit, "2d painting", "2D Painting.*", "2D Painting Example") + if example is not None: + test.verify(checkIfObjectExists("{column='0' container=':Qt Creator_Utils::NavigationTreeView'" + " text='2dpainting' type='QModelIndex'}"), + "Verifying: The project is shown in 'Edit' mode.") + invokeContextMenuOnProject('2dpainting', 'Close Project "2dpainting"') + navTree = waitForObject(":Qt Creator_Utils::NavigationTreeView") + res = waitFor("navTree.model().rowCount(navTree.rootIndex()) == 0", 2000) + test.verify(not checkIfObjectItemExists(":Qt Creator_Utils::NavigationTreeView", "2dpainting"), + "Verifying: The first example is closed.") # clean up created packaging directories for p in proFiles: removePackagingDirectory(os.path.dirname(p)) @@ -110,31 +122,21 @@ def main(): cleanUpUserFiles(proFiles) for p in proFiles: removePackagingDirectory(os.path.dirname(p)) - examplesLineEditWidget = waitForObject(examplesLineEdit) - mouseClick(examplesLineEditWidget) - replaceEditorContent(examplesLineEditWidget, "address book") - addressBook = getQmlItem("Delegate", welcomePage, - False, "id='delegate' radius='0' caption~='Address Book.*'") - test.verify(checkIfObjectExists(addressBook), "Verifying: Example (address book) is shown.") - mouseClick(waitForObject(addressBook), 5, 5, 0, Qt.LeftButton) - handlePackagingMessageBoxes() - helpWidget = waitForObject(":Help Widget_Help::Internal::HelpWidget") - test.verify(waitFor('"Address Book Example" in str(helpWidget.windowTitle)', 5000), - "Verifying: The example application is opened inside Help.") - sendEvent("QCloseEvent", helpWidget) - # assume the correct kit is selected, hit Configure Project - clickButton(waitForObject(":Qt Creator.Configure Project_QPushButton")) - # close second example application - test.verify(checkIfObjectExists("{column='0' container=':Qt Creator_Utils::NavigationTreeView'" - " text='propertyanimation' type='QModelIndex'}", False) and - checkIfObjectExists("{column='0' container=':Qt Creator_Utils::NavigationTreeView'" - " text='addressbook' type='QModelIndex'}"), - "Verifying: The project is shown in 'Edit' mode while old project isn't.") - invokeContextMenuOnProject('addressbook', 'Close Project "addressbook"') - navTree = waitForObject(":Qt Creator_Utils::NavigationTreeView") - res = waitFor("navTree.model().rowCount(navTree.rootIndex()) == 0", 2000) - test.verify(not checkIfObjectItemExists(":Qt Creator_Utils::NavigationTreeView", "addressbook"), - "Verifying: The second example is closed.") + examplesLineEdit = waitForObject(search %(expect[1][0], expect[1][1])) + example = openExample(examplesLineEdit, "address book", "Address Book.*", + "Address Book Example") + if example is not None: + # close second example application + test.verify(checkIfObjectExists("{column='0' container=':Qt Creator_Utils::NavigationTreeView'" + " text='propertyanimation' type='QModelIndex'}", False) and + checkIfObjectExists("{column='0' container=':Qt Creator_Utils::NavigationTreeView'" + " text='addressbook' type='QModelIndex'}"), + "Verifying: The project is shown in 'Edit' mode while old project isn't.") + invokeContextMenuOnProject('addressbook', 'Close Project "addressbook"') + navTree = waitForObject(":Qt Creator_Utils::NavigationTreeView") + res = waitFor("navTree.model().rowCount(navTree.rootIndex()) == 0", 2000) + test.verify(not checkIfObjectItemExists(":Qt Creator_Utils::NavigationTreeView", "addressbook"), + "Verifying: The second example is closed.") # clean up created packaging directories for p in proFiles: removePackagingDirectory(os.path.dirname(p)) diff --git a/tests/system/suite_WELP/tst_WELP04/test.py b/tests/system/suite_WELP/tst_WELP04/test.py index ff735a2c73..3d1bff2f7f 100644 --- a/tests/system/suite_WELP/tst_WELP04/test.py +++ b/tests/system/suite_WELP/tst_WELP04/test.py @@ -24,53 +24,53 @@ ############################################################################ source("../../shared/qtcreator.py") -source("../../shared/suites_qtta.py") def main(): - welcomePage = ":Qt Creator.WelcomePage_QQuickWidget" # open Qt Creator startApplication("qtcreator" + SettingsPath) if not startedWithoutPluginError(): return - getStarted = getQmlItem("Button", welcomePage, False, - "text='Get Started Now' id='gettingStartedButton'") - if not test.verify(checkIfObjectExists(getStarted), - "Verifying: Qt Creator displays Welcome Page with Get Started Now button."): - test.fatal("Something's wrong here - leaving test.") + wsButtonFrame, wsButtonLabel = getWelcomeScreenSideBarButton('Get Started Now') + if not test.verify(all((wsButtonFrame, wsButtonLabel)), + "Verifying: Qt Creator displays Welcome Page with Getting Started."): + test.fatal("Something's wrong - leaving test.") invokeMenuItem("File", "Exit") return # select "Tutorials" - mouseClick(waitForObject(getQmlItem("Button", welcomePage, False, "text='Tutorials'")), - 5, 5, 0, Qt.LeftButton) - searchTut = getQmlItem("TextField", welcomePage, False, - "placeholderText='Search in Tutorials...' id='lineEdit'") - mouseClick(waitForObject(searchTut), 5, 5, 0, Qt.LeftButton) - replaceEditorContent(waitForObject(searchTut), "qwerty") - test.verify(checkIfObjectExists(getQmlItem("Text", welcomePage, - False, "text='Tutorials'")) and - checkIfObjectExists(getQmlItem("Delegate", welcomePage, - False, "id='delegate' radius='0' caption~='.*'"), - False), + wsButtonFrame, wsButtonLabel = getWelcomeScreenSideBarButton('Tutorials') + if all((wsButtonFrame, wsButtonLabel)): + mouseClick(wsButtonLabel) + else: + test.fatal("Could not find Tutorials button - leaving test") + invokeMenuItem("File", "Exit") + return + searchTutorials = waitForObject("{type='QLineEdit' placeholderText='Search in Tutorials...'}") + mouseClick(searchTutorials) + replaceEditorContent(searchTutorials, "qwerty") + tableView = waitForObject("{type='QTableView' unnamed='1' visible='1' " + "window=':Qt Creator_Core::Internal::MainWindow'}") + waitFor('findExampleOrTutorial(tableView, ".*") is None', 3000) + tutorial = findExampleOrTutorial(tableView, ".*", True) + test.verify(tutorial is None, "Verifying: 'Tutorials' topic is opened and nothing is shown.") - replaceEditorContent(waitForObject(searchTut), "building and running an example application") - bldRunExmpl = getQmlItem("Delegate", welcomePage, False, - "caption='Building and Running an Example Application' " - "id='delegate' radius='0'") - test.verify(checkIfObjectExists(bldRunExmpl), "Verifying: Expected Text tutorial is shown.") + bnr = "Building and Running an Example Application" + replaceEditorContent(searchTutorials, bnr.lower()) + waitFor('findExampleOrTutorial(tableView, "%s.*") is not None' % bnr, 3000) + tutorial = findExampleOrTutorial(tableView, "%s.*" % bnr, True) + test.verify(tutorial is not None, "Verifying: Expected Text tutorial is shown.") # select a text tutorial - mouseClick(waitForObject(bldRunExmpl), 5, 5, 0, Qt.LeftButton) + mouseClick(tutorial) test.verify("Building and Running an Example" in str(waitForObject(":Help Widget_Help::Internal::HelpWidget").windowTitle), "Verifying: The tutorial is opened inside Help.") # close help widget again to avoid focus issues sendEvent("QCloseEvent", waitForObject(":Help Widget_Help::Internal::HelpWidget")) # check a demonstration video link - searchTutWidget = waitForObject(searchTut) - mouseClick(searchTutWidget) - replaceEditorContent(searchTutWidget, "embedded device") - test.verify(checkIfObjectExists(getQmlItem("Delegate", welcomePage, - False, "id='delegate' radius='0' caption=" - "'Qt for Device Creation'")), + mouseClick(searchTutorials) + replaceEditorContent(searchTutorials, "embedded device") + waitFor('findExampleOrTutorial(tableView, "Qt for Device Creation.*") is not None', 3000) + tutorial = findExampleOrTutorial(tableView, "Qt for Device Creation.*", True) + test.verify(tutorial is not None, "Verifying: Link to the expected demonstration video exists.") # exit Qt Creator invokeMenuItem("File", "Exit") diff --git a/tests/system/suite_general/suite.conf b/tests/system/suite_general/suite.conf index 286bc162ef..f6429d5bb5 100644 --- a/tests/system/suite_general/suite.conf +++ b/tests/system/suite_general/suite.conf @@ -7,6 +7,6 @@ HOOK_SUB_PROCESSES=false IMPLICITAUTSTART=0 LANGUAGE=Python OBJECTMAP=../objects.map -TEST_CASES=tst_build_speedcrunch tst_cmake_speedcrunch tst_create_proj_wizard tst_default_settings tst_installed_languages tst_new_class tst_opencreator_qbs tst_openqt_creator tst_remove_kits tst_rename_file tst_save_before_build tst_session_handling tst_tasks_handling +TEST_CASES=tst_build_speedcrunch tst_cmake_speedcrunch tst_create_proj_wizard tst_custom_wizard_check tst_default_settings tst_installed_languages tst_new_class tst_opencreator_qbs tst_openqt_creator tst_remove_kits tst_rename_file tst_save_before_build tst_session_handling tst_tasks_handling VERSION=2 WRAPPERS=Qt diff --git a/tests/system/suite_general/tst_create_proj_wizard/test.py b/tests/system/suite_general/tst_create_proj_wizard/test.py index 126e1f3d7e..917f7d76a6 100644 --- a/tests/system/suite_general/tst_create_proj_wizard/test.py +++ b/tests/system/suite_general/tst_create_proj_wizard/test.py @@ -26,7 +26,7 @@ source("../../shared/qtcreator.py") def main(): - global tmpSettingsDir + global tmpSettingsDir, availableBuildSystems qtVersionsForQuick = ["5.3"] availableBuildSystems = ["qmake", "Qbs"] if platform.system() != 'Darwin': @@ -65,7 +65,8 @@ def main(): for template in dumpItems(templatesView.model(), templatesView.rootIndex()): template = template.replace(".", "\\.") # skip non-configurable - if not template in ["Qt Quick UI", "Qt Quick Controls UI", "Qt Canvas 3D Application"]: + if not template in ["Qt Quick UI Prototype", "Qt Canvas 3D Application", + "Auto Test Project"]: # FIXME availableProjectTypes.append({category:template}) safeClickButton("Cancel") for current in availableProjectTypes: @@ -74,34 +75,25 @@ def main(): displayedPlatforms = __createProject__(category, template) if template == "Qt Quick Application" or template == "Qt Quick Controls Application": for counter, qtVersion in enumerate(qtVersionsForQuick): - requiredQtVersion = __createProjectHandleQtQuickSelection__(qtVersion) - __modifyAvailableTargets__(displayedPlatforms, requiredQtVersion, True) - verifyKitCheckboxes(kits, displayedPlatforms) - # FIXME: if QTBUG-35203 is fixed replace by triggering the shortcut for Back - safeClickButton("Cancel") + def additionalFunc(displayedPlatforms, qtVersion): + requiredQtVersion = __createProjectHandleQtQuickSelection__(qtVersion) + __modifyAvailableTargets__(displayedPlatforms, requiredQtVersion, True) + handleBuildSystemVerifyKits(category, template, kits, displayedPlatforms, + additionalFunc, qtVersion) # are there more Quick combinations - then recreate this project if counter < len(qtVersionsForQuick) - 1: displayedPlatforms = __createProject__(category, template) continue elif template == "Qt Quick Controls 2 Application": # needs a Qt5.7 - clickButton(waitForObject(":Next_QPushButton")) # ignore this details page for now - verifyKitCheckboxes(kits, displayedPlatforms) - safeClickButton("Cancel") + def additionalFunc(displayedPlatforms): + clickButton(waitForObject(":Next_QPushButton")) # ignore this details page for now + handleBuildSystemVerifyKits(category, template, kits, displayedPlatforms, additionalFunc) continue elif template.startswith("Plain C"): - for counter, buildSystem in enumerate(availableBuildSystems): - combo = "{name='BuildSystem' type='Utils::TextFieldComboBox' visible='1'}" - selectFromCombo(combo, buildSystem) - clickButton(waitForObject(":Next_QPushButton")) - verifyKitCheckboxes(kits, displayedPlatforms) - # FIXME: if QTBUG-35203 is fixed replace by triggering the shortcut for Back - safeClickButton("Cancel") - if counter < len(availableBuildSystems) - 1: - displayedPlatforms = __createProject__(category, template) + handleBuildSystemVerifyKits(category, template, kits, displayedPlatforms) continue - verifyKitCheckboxes(kits, displayedPlatforms) - safeClickButton("Cancel") + handleBuildSystemVerifyKits(category, template, kits, displayedPlatforms) invokeMenuItem("File", "Exit") @@ -125,6 +117,35 @@ def verifyKitCheckboxes(kits, displayedPlatforms): test.fail("Found unexpected additional kit(s) %s on 'Kit Selection' page." % str(availableCheckboxes)) +def handleBuildSystemVerifyKits(category, template, kits, displayedPlatforms, + specialHandlingFunc = None, *args): + global availableBuildSystems + combo = "{name='BuildSystem' type='Utils::TextFieldComboBox' visible='1'}" + try: + waitForObject(combo, 2000) + skipBuildsystemChooser = False + except: + skipBuildsystemChooser = True + + if skipBuildsystemChooser: + test.log("Wizard without build system support.") + if specialHandlingFunc: + specialHandlingFunc(displayedPlatforms, *args) + verifyKitCheckboxes(kits, displayedPlatforms) + safeClickButton("Cancel") + return + + for counter, buildSystem in enumerate(availableBuildSystems): + test.log("Using build system '%s'" % buildSystem) + selectFromCombo(combo, buildSystem) + clickButton(waitForObject(":Next_QPushButton")) + if specialHandlingFunc: + specialHandlingFunc(displayedPlatforms, *args) + verifyKitCheckboxes(kits, displayedPlatforms) + safeClickButton("Cancel") + if counter < len(availableBuildSystems) - 1: + displayedPlatforms = __createProject__(category, template) + def __createProject__(category, template): def safeGetTextBrowserText(): try: diff --git a/tests/system/suite_general/tst_custom_wizard_check/test.py b/tests/system/suite_general/tst_custom_wizard_check/test.py new file mode 100644 index 0000000000..49e39d1554 --- /dev/null +++ b/tests/system/suite_general/tst_custom_wizard_check/test.py @@ -0,0 +1,52 @@ +############################################################################ +# +# Copyright (C) 2017 The Qt Company Ltd. +# Contact: https://www.qt.io/licensing/ +# +# This file is part of Qt Creator. +# +# Commercial License Usage +# Licensees holding valid commercial Qt licenses may use this file in +# accordance with the commercial license agreement provided with the +# Software or, alternatively, in accordance with the terms contained in +# a written agreement between you and The Qt Company. For licensing terms +# and conditions see https://www.qt.io/terms-conditions. For further +# information use the contact form at https://www.qt.io/contact-us. +# +# GNU General Public License Usage +# Alternatively, this file may be used under the terms of the GNU +# General Public License version 3 as published by the Free Software +# Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +# included in the packaging of this file. Please review the following +# information to ensure the GNU General Public License requirements will +# be met: https://www.gnu.org/licenses/gpl-3.0.html. +# +############################################################################ + +source("../../shared/qtcreator.py") + +def main(): + startApplication("qtcreator" + SettingsPath + " -customwizard-verbose") + if not startedWithoutPluginError(): + return + + openGeneralMessages() + messages = waitForObject(":Qt Creator_Core::OutputWindow") + output = str(messages.plainText) + test.log("General Messages Output:\n%s" % output) + if not len(output.strip()): + test.fatal("Failed to retrieve any output from General Messages pane.") + # check for parse errors, creation errors, no JSON object at all + for errMssg, description in (("Failed to parse", "Parse failures"), + ("Failed to create", "Creation failures"), + ("Did not find a JSON object", "Missing JSON objects")): + if not test.verify(errMssg not in output, "Checking for %s" % description): + test.log("%s\n%s" + % (description, "\n".join(l for l in output.splitlines() if errMssg in l))) + + # check for invalid version + invalidVersionRegex = "^\* Version .* not supported\." + if not test.verify(not re.search(invalidVersionRegex, output, re.MULTILINE), "Version check"): + test.log("Found unsupported version:\n%s" + % "\n".join(l for l in output.splitlines() if re.search(invalidVersionRegex, l))) + invokeMenuItem("File", "Exit") diff --git a/tests/system/suite_general/tst_session_handling/test.py b/tests/system/suite_general/tst_session_handling/test.py index 0247b6404f..19cbfbaa18 100644 --- a/tests/system/suite_general/tst_session_handling/test.py +++ b/tests/system/suite_general/tst_session_handling/test.py @@ -41,7 +41,7 @@ def main(): for project in projects: openQmakeProject(project, [Targets.DESKTOP_531_DEFAULT]) progressBarWait(20000) - checkNavigator(53, "Verifying whether all projects have been opened.") + checkNavigator(52, "Verifying whether all projects have been opened.") openDocument("animation.Resources.animation\\.qrc./animation.basics.animators\\.qml") openDocument("keyinteraction.Sources.main\\.cpp") checkOpenDocuments(2, "Verifying whether 2 files are open.") @@ -51,12 +51,12 @@ def main(): "Verifying window title is set to default.") checkWelcomePage(sessionName, False) switchViewTo(ViewConstants.EDIT) - checkNavigator(1, "Verifying that no more project is opened.") + checkNavigator(0, "Verifying that no more project is opened.") checkOpenDocuments(0, "Verifying whether all files have been closed.") switchSession(sessionName) test.verify(waitFor("sessionName in str(mainWindow.windowTitle)", 2000), "Verifying window title contains created session name.") - checkNavigator(53, "Verifying whether all projects have been re-opened.") + checkNavigator(52, "Verifying whether all projects have been re-opened.") checkOpenDocuments(2, "Verifying whether 2 files have been re-opened.") if test.verify("main.cpp" in str(mainWindow.windowTitle), "Verifying whether utility.h has been opened."): @@ -100,24 +100,32 @@ def createAndSwitchToSession(toSession): lineEdit = waitForObject("{type='QLineEdit' unnamed='1' visible='1' window=%s}" % sessionInputDialog) replaceEditorContent(lineEdit, toSession) - clickButton(waitForObject("{text='Switch To' type='QPushButton' unnamed='1' visible='1' " + clickButton(waitForObject("{text='Create and Open' type='QPushButton' unnamed='1' visible='1' " "window=%s}" % sessionInputDialog)) def checkWelcomePage(sessionName, isCurrent=False): - welcomePage = ":Qt Creator.WelcomePage_QQuickWidget" switchViewTo(ViewConstants.WELCOME) - mouseClick(waitForObject("{container='%s' text='Projects' type='Button' " - "unnamed='1' visible='true'}" % welcomePage)) - waitForObject("{container='%s' id='sessionsTitle' text='Sessions' type='Text' " - "unnamed='1' visible='true'}" % welcomePage) - if isCurrent: - sessions = ["default", "%s (current session)" % sessionName] - else: - sessions = ["default (current session)", sessionName] - for sessionName in sessions: - test.verify(object.exists("{container='%s' enabled='true' type='Text' unnamed='1' " - "visible='true' text='%s'}" % (welcomePage, sessionName)), - "Verifying session '%s' exists." % sessionName) + wsButtonFrame, wsButtonLabel = getWelcomeScreenSideBarButton('Projects') + if not all((wsButtonFrame, wsButtonLabel)): + test.fatal("Something's pretty wrong - leaving check for WelcomePage.") + return + mouseClick(wsButtonLabel) + treeView = getWelcomeTreeView("Sessions") + if not treeView: + test.fatal("Failed to find Sessions tree view - leaving check for WelcomePage.") + return + sessions = {"default":not isCurrent, sessionName:isCurrent} + indices = dumpIndices(treeView.model()) + for session, current in sessions.items(): + found = False + for index in indices: + if session == str(index.data()): + # 259 -> ActiveSessionRole [sessionmodel.h] + isCurrent = index.data(259).toBool() + if current == isCurrent: + found = True + break + test.verify(found, "Verifying: Qt Creator displays Welcome Page with %s." % session) def checkNavigator(expectedRows, message): navigatorModel = waitForObject(":Qt Creator_Utils::NavigationTreeView").model() diff --git a/tests/system/suite_qtquick/tst_qtquick_creation3/test.py b/tests/system/suite_qtquick/tst_qtquick_creation3/test.py index a19be52c58..c04b39de8a 100644 --- a/tests/system/suite_qtquick/tst_qtquick_creation3/test.py +++ b/tests/system/suite_qtquick/tst_qtquick_creation3/test.py @@ -29,14 +29,14 @@ def main(): startApplication("qtcreator" + SettingsPath) if not startedWithoutPluginError(): return - available = [("5.6", False), ("5.6", True)] + available = ["5.6"] if platform.system() != 'Darwin': - available.extend([("5.4", False), ("5.4", True)]) + available.extend(["5.4"]) - for qtVersion, controls in available: + for qtVersion in available: # using a temporary directory won't mess up a potentially existing workingDir = tempDir() - projectName = createNewQtQuickUI(workingDir, qtVersion, controls) + projectName = createNewQtQuickUI(workingDir, qtVersion) if qtVersion == "5.6": kit = Targets.getStringForTarget(Targets.DESKTOP_561_DEFAULT) if addAndActivateKit(Targets.DESKTOP_561_DEFAULT): @@ -53,10 +53,7 @@ def main(): else: test.fatal("Failed to activate kit %s" % kit) continue - additionalText = '' - if controls: - additionalText = ' Controls ' - test.log("Running project Qt Quick%sUI (%s)" % (additionalText, kit)) + test.log("Running project Qt Quick UI Prototype (%s)" % kit) qmlViewer = modifyRunSettingsForHookIntoQtQuickUI(2, 1, workingDir, projectName, 11223, quick) if qmlViewer!=None: qmlViewerPath = os.path.dirname(qmlViewer) diff --git a/tests/unit/echoserver/echoserver.pro b/tests/unit/echoserver/echoserver.pro index 38bf9b04ce..0f9ed76afa 100644 --- a/tests/unit/echoserver/echoserver.pro +++ b/tests/unit/echoserver/echoserver.pro @@ -1,7 +1,5 @@ QT += core network -QT -= gui - TARGET = echo CONFIG += console CONFIG -= app_bundle @@ -10,8 +8,13 @@ TEMPLATE = app unix:LIBS += -ldl -osx:QMAKE_CXXFLAGS = -stdlib=libc++ +# Set IDE_LIBEXEC_PATH and IDE_BIN_PATH to silence a warning about empty +# QTC_REL_TOOLS_PATH, which is not used by the tests. +IDE_LIBEXEC_PATH=$$PWD +IDE_BIN_PATH=$$PWD +include($$PWD/../../../src/libs/utils/utils-lib.pri) +include(../../../qtcreator.pri) include(../../../src/libs/clangbackendipc/clangbackendipc-lib.pri) include(../../../src/libs/sqlite/sqlite-lib.pri) diff --git a/tests/unit/mockup/cpptools/cpptoolsreuse.h b/tests/unit/mockup/cpptools/cpptoolsreuse.h index fec5388641..74db97df05 100644 --- a/tests/unit/mockup/cpptools/cpptoolsreuse.h +++ b/tests/unit/mockup/cpptools/cpptoolsreuse.h @@ -25,8 +25,10 @@ #pragma once +#include <cpptools/compileroptionsbuilder.h> + namespace CppTools { -CompilerOptionsBuilder::PchUsage getPchUsage() { return CompilerOptionsBuilder::PchUsage::None; } +inline CompilerOptionsBuilder::PchUsage getPchUsage() { return CompilerOptionsBuilder::PchUsage::None; } } // CppTools diff --git a/tests/unit/mockup/projectexplorer/kitinformation.h b/tests/unit/mockup/projectexplorer/kitinformation.h new file mode 100644 index 0000000000..fced31a50f --- /dev/null +++ b/tests/unit/mockup/projectexplorer/kitinformation.h @@ -0,0 +1,40 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#pragma once + +#include <utils/fileutils.h> + +namespace ProjectExplorer { + +class Kit; + +class SysRootKitInformation +{ +public: + static Utils::FileName sysRoot(const Kit *) { return Utils::FileName(); } +}; + +} // namespace ProjectExplorer diff --git a/tests/unit/mockup/projectexplorer/toolchain.h b/tests/unit/mockup/projectexplorer/toolchain.h new file mode 100644 index 0000000000..33bfa836df --- /dev/null +++ b/tests/unit/mockup/projectexplorer/toolchain.h @@ -0,0 +1,68 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#pragma once + +#include <projectexplorer/headerpath.h> +#include <projectexplorer/abi.h> +#include <coreplugin/id.h> + +#include <functional> + +namespace ProjectExplorer { + +class ToolChain +{ +public: + Core::Id typeId() const { return Core::Id(); } + + enum CompilerFlag { + NoFlags = 0, + StandardCxx11 = 0x1, + StandardC99 = 0x2, + StandardC11 = 0x4, + GnuExtensions = 0x8, + MicrosoftExtensions = 0x10, + BorlandExtensions = 0x20, + OpenMP = 0x40, + ObjectiveC = 0x80, + StandardCxx14 = 0x100, + StandardCxx17 = 0x200, + StandardCxx98 = 0x400, + }; + Q_DECLARE_FLAGS(CompilerFlags, CompilerFlag) + + Abi targetAbi() const { return Abi(); } + + using SystemHeaderPathsRunner = std::function<QList<HeaderPath>(const QStringList &cxxflags, const QString &sysRoot)>; + virtual SystemHeaderPathsRunner createSystemHeaderPathsRunner() const { return SystemHeaderPathsRunner(); } + + using PredefinedMacrosRunner = std::function<QByteArray(const QStringList &cxxflags)>; + virtual PredefinedMacrosRunner createPredefinedMacrosRunner() const { return PredefinedMacrosRunner(); } + + virtual QString originalTargetTriple() const { return QString(); } +}; + +} // namespace ProjectExplorer diff --git a/tests/unit/unittest/activationsequencecontextprocessor-test.cpp b/tests/unit/unittest/activationsequencecontextprocessor-test.cpp index 0f565aecd7..aca0ae4e97 100644 --- a/tests/unit/unittest/activationsequencecontextprocessor-test.cpp +++ b/tests/unit/unittest/activationsequencecontextprocessor-test.cpp @@ -40,7 +40,7 @@ using ContextProcessor = ClangCodeModel::Internal::ActivationSequenceContextPro using TextEditor::AssistInterface; using ClangCodeModel::Internal::ClangCompletionAssistInterface; -TEST(ActivationSequeneContextProcessor, TextCursorPosition) +TEST(ActivationSequenceContextProcessorSlowTest, TextCursorPosition) { ClangCompletionAssistInterface interface("foobar", 4); ContextProcessor processor{&interface}; @@ -48,7 +48,7 @@ TEST(ActivationSequeneContextProcessor, TextCursorPosition) ASSERT_THAT(processor.textCursor_forTestOnly().position(), 0); } -TEST(ActivationSequeneContextProcessor, StringLiteral) +TEST(ActivationSequenceContextProcessor, StringLiteral) { ClangCompletionAssistInterface interface("auto foo = \"bar\"", 12); ContextProcessor processor{&interface}; @@ -56,7 +56,7 @@ TEST(ActivationSequeneContextProcessor, StringLiteral) ASSERT_THAT(processor.completionKind(), CPlusPlus::T_EOF_SYMBOL); } -TEST(ActivationSequeneContextProcessor, EndOfStringLiteral) +TEST(ActivationSequenceContextProcessor, EndOfStringLiteral) { ClangCompletionAssistInterface interface("auto foo = \"bar\"", 16); ContextProcessor processor{&interface}; @@ -64,7 +64,7 @@ TEST(ActivationSequeneContextProcessor, EndOfStringLiteral) ASSERT_THAT(processor.completionKind(), CPlusPlus::T_EOF_SYMBOL); } -TEST(ActivationSequeneContextProcessor, FunctionCallComma) +TEST(ActivationSequenceContextProcessor, FunctionCallComma) { ClangCompletionAssistInterface interface("f(x, ", 4); ContextProcessor processor{&interface}; @@ -72,7 +72,7 @@ TEST(ActivationSequeneContextProcessor, FunctionCallComma) ASSERT_THAT(processor.completionKind(), CPlusPlus::T_COMMA); } -TEST(ActivationSequeneContextProcessor, NonFunctionCallComma) +TEST(ActivationSequenceContextProcessor, NonFunctionCallComma) { ClangCompletionAssistInterface interface("int x, ", 6); ContextProcessor processor{&interface}; @@ -80,7 +80,7 @@ TEST(ActivationSequeneContextProcessor, NonFunctionCallComma) ASSERT_THAT(processor.completionKind(), CPlusPlus::T_EOF_SYMBOL); } -TEST(ActivationSequeneContextProcessor, DoxygenComment) +TEST(ActivationSequenceContextProcessor, DoxygenComment) { ClangCompletionAssistInterface interface("//! @", 5); ContextProcessor processor{&interface}; @@ -88,7 +88,7 @@ TEST(ActivationSequeneContextProcessor, DoxygenComment) ASSERT_THAT(processor.completionKind(), CPlusPlus::T_DOXY_COMMENT); } -TEST(ActivationSequeneContextProcessor, NonDoxygenComment) +TEST(ActivationSequenceContextProcessor, NonDoxygenComment) { ClangCompletionAssistInterface interface("// @", 4); ContextProcessor processor{&interface}; @@ -96,7 +96,7 @@ TEST(ActivationSequeneContextProcessor, NonDoxygenComment) ASSERT_THAT(processor.completionKind(), CPlusPlus::T_EOF_SYMBOL); } -TEST(ActivationSequeneContextProcessor, Comment) +TEST(ActivationSequenceContextProcessor, Comment) { ClangCompletionAssistInterface interface("//", 2); ContextProcessor processor{&interface}; @@ -104,7 +104,7 @@ TEST(ActivationSequeneContextProcessor, Comment) ASSERT_THAT(processor.completionKind(), CPlusPlus::T_EOF_SYMBOL); } -TEST(ActivationSequeneContextProcessor, InsideALiteral) +TEST(ActivationSequenceContextProcessor, InsideALiteral) { ClangCompletionAssistInterface interface("\"foo\"", 2); ContextProcessor processor{&interface}; @@ -112,7 +112,7 @@ TEST(ActivationSequeneContextProcessor, InsideALiteral) ASSERT_THAT(processor.completionKind(), CPlusPlus::T_EOF_SYMBOL); } -TEST(ActivationSequeneContextProcessor, ShlashInsideAString) +TEST(ActivationSequenceContextProcessor, ShlashInsideAString) { ClangCompletionAssistInterface interface("\"foo/bar\"", 5); ContextProcessor processor{&interface}; @@ -120,7 +120,7 @@ TEST(ActivationSequeneContextProcessor, ShlashInsideAString) ASSERT_THAT(processor.completionKind(), CPlusPlus::T_EOF_SYMBOL); } -TEST(ActivationSequeneContextProcessor, ShlashOutsideAString) +TEST(ActivationSequenceContextProcessor, ShlashOutsideAString) { ClangCompletionAssistInterface interface("foo/bar", 4); ContextProcessor processor{&interface}; @@ -128,7 +128,7 @@ TEST(ActivationSequeneContextProcessor, ShlashOutsideAString) ASSERT_THAT(processor.completionKind(), CPlusPlus::T_EOF_SYMBOL); } -TEST(ActivationSequeneContextProcessor, FunctionLeftParen) +TEST(ActivationSequenceContextProcessor, FunctionLeftParen) { ClangCompletionAssistInterface interface("foo(", 4); ContextProcessor processor{&interface}; @@ -136,7 +136,7 @@ TEST(ActivationSequeneContextProcessor, FunctionLeftParen) ASSERT_THAT(processor.completionKind(), CPlusPlus::T_LPAREN); } -TEST(ActivationSequeneContextProcessor, TemplateFunctionLeftParen) +TEST(ActivationSequenceContextProcessor, TemplateFunctionLeftParen) { ClangCompletionAssistInterface interface("foo<X>(", 7); ContextProcessor processor{&interface}; @@ -144,7 +144,7 @@ TEST(ActivationSequeneContextProcessor, TemplateFunctionLeftParen) ASSERT_THAT(processor.completionKind(), CPlusPlus::T_LPAREN); } -TEST(ActivationSequeneContextProcessor, ExpressionLeftParen) +TEST(ActivationSequenceContextProcessor, ExpressionLeftParen) { ClangCompletionAssistInterface interface("x * (", 5); ContextProcessor processor{&interface}; @@ -152,7 +152,7 @@ TEST(ActivationSequeneContextProcessor, ExpressionLeftParen) ASSERT_THAT(processor.completionKind(), CPlusPlus::T_EOF_SYMBOL); } -TEST(ActivationSequeneContextProcessor, AngleInclude) +TEST(ActivationSequenceContextProcessor, AngleInclude) { ClangCompletionAssistInterface interface("#include <foo/bar>", 10); ContextProcessor processor{&interface}; @@ -160,7 +160,7 @@ TEST(ActivationSequeneContextProcessor, AngleInclude) ASSERT_THAT(processor.completionKind(), CPlusPlus::T_ANGLE_STRING_LITERAL); } -TEST(ActivationSequeneContextProcessor, SlashInclude) +TEST(ActivationSequenceContextProcessor, SlashInclude) { ClangCompletionAssistInterface interface("#include <foo/bar>", 14); ContextProcessor processor{&interface}; @@ -168,7 +168,7 @@ TEST(ActivationSequeneContextProcessor, SlashInclude) ASSERT_THAT(processor.completionKind(), CPlusPlus::T_SLASH); } -TEST(ActivationSequeneContextProcessor, QuoteInclude) +TEST(ActivationSequenceContextProcessor, QuoteInclude) { ClangCompletionAssistInterface interface("#include \"foo/bar\"", 10); ContextProcessor processor{&interface}; @@ -176,7 +176,7 @@ TEST(ActivationSequeneContextProcessor, QuoteInclude) ASSERT_THAT(processor.completionKind(), CPlusPlus::T_STRING_LITERAL); } -TEST(ActivationSequeneContextProcessor, SlashInExlude) +TEST(ActivationSequenceContextProcessor, SlashInExlude) { ClangCompletionAssistInterface interface("#exclude <foo/bar>", 14); ContextProcessor processor{&interface}; @@ -184,7 +184,7 @@ TEST(ActivationSequeneContextProcessor, SlashInExlude) ASSERT_THAT(processor.completionKind(), CPlusPlus::T_EOF_SYMBOL); } -TEST(ActivationSequeneContextProcessor, QuoteExclude) +TEST(ActivationSequenceContextProcessor, QuoteExclude) { ClangCompletionAssistInterface interface("#exclude \"foo/bar\"", 10); ContextProcessor processor{&interface}; @@ -192,7 +192,7 @@ TEST(ActivationSequeneContextProcessor, QuoteExclude) ASSERT_THAT(processor.completionKind(), CPlusPlus::T_EOF_SYMBOL); } -TEST(ActivationSequeneContextProcessor, SkipeWhiteSpacesBeforeCursor) +TEST(ActivationSequenceContextProcessor, SkipeWhiteSpacesBeforeCursor) { ClangCompletionAssistInterface interface("x-> ", 7); ContextProcessor processor{&interface}; @@ -200,7 +200,7 @@ TEST(ActivationSequeneContextProcessor, SkipeWhiteSpacesBeforeCursor) ASSERT_THAT(processor.completionKind(), CPlusPlus::T_ARROW); } -TEST(ActivationSequeneContextProcessor, SkipIdentifier) +TEST(ActivationSequenceContextProcessor, SkipIdentifier) { ClangCompletionAssistInterface interface("x->foo_", 7); ContextProcessor processor{&interface}; diff --git a/tests/unit/unittest/changedfilepathcompressor-test.cpp b/tests/unit/unittest/changedfilepathcompressor-test.cpp new file mode 100644 index 0000000000..9080e3f0f8 --- /dev/null +++ b/tests/unit/unittest/changedfilepathcompressor-test.cpp @@ -0,0 +1,87 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#include "googletest.h" + +#include <mockchangedfilepathcompressor.h> + +namespace { + +using testing::ElementsAre; +using testing::Invoke; +using testing::IsEmpty; +using testing::NiceMock; + +class ChangedFilePathCompressor : public testing::Test +{ +protected: + void SetUp(); + +protected: + NiceMock<MockChangedFilePathCompressor> mockCompressor; + ClangBackEnd::ChangedFilePathCompressor<FakeTimer> compressor; + QString filePath1{"filePath1"}; + QString filePath2{"filePath2"}; +}; + +TEST_F(ChangedFilePathCompressor, AddFilePath) +{ + mockCompressor.addFilePath(filePath1); + + ASSERT_THAT(mockCompressor.takeFilePaths(), ElementsAre(filePath1)); +} + +TEST_F(ChangedFilePathCompressor, NoFilePathsAferTakenThem) +{ + mockCompressor.addFilePath(filePath1); + + mockCompressor.takeFilePaths(); + + ASSERT_THAT(mockCompressor.takeFilePaths(), IsEmpty()); +} + +TEST_F(ChangedFilePathCompressor, CallRestartTimerAfterAddingPath) +{ + EXPECT_CALL(mockCompressor, restartTimer()); + + mockCompressor.addFilePath(filePath1); +} + +TEST_F(ChangedFilePathCompressor, CallTimeOutAfterAddingPath) +{ + EXPECT_CALL(mockCompressor, callbackCalled(ElementsAre(filePath1, filePath2))); + + compressor.addFilePath(filePath1); + compressor.addFilePath(filePath2); +} + +void ChangedFilePathCompressor::SetUp() +{ + compressor.setCallback([&] (Utils::PathStringVector &&filePaths) { + mockCompressor.callbackCalled(filePaths); + }); +} + +} diff --git a/tests/unit/unittest/clang_dependency.pri b/tests/unit/unittest/clang_dependency.pri index 61960c9f87..354ebd0c90 100644 --- a/tests/unit/unittest/clang_dependency.pri +++ b/tests/unit/unittest/clang_dependency.pri @@ -2,12 +2,26 @@ isEmpty(LLVM_INSTALL_DIR):LLVM_INSTALL_DIR=$$(LLVM_INSTALL_DIR) !isEmpty(LLVM_INSTALL_DIR) { include(../../../src/shared/clang/clang_installation.pri) requires(!isEmpty(LIBCLANG_LIBS)) - equals(LLVM_IS_COMPILED_WITH_RTTI, "NO") : message("LLVM needs to be compiled with RTTI!") requires(equals(LLVM_IS_COMPILED_WITH_RTTI, "YES")) DEFINES += CLANG_UNIT_TESTS INCLUDEPATH += $$LLVM_INCLUDEPATH -win32:LIBS += -lVersion +win32 { + LIBS += -lVersion + + # set run path for clang.dll dependency + bin_path = $$LLVM_INSTALL_DIR/bin + bin_path ~= s,/,\\,g + # the below gets added to later by testcase.prf + check.commands = cd . & set PATH=$$bin_path;%PATH%& cmd /c +} + LIBS += $$LIBTOOLING_LIBS $$LIBCLANG_LIBS +QMAKE_RPATHDIR += $$LLVM_LIBDIR + +LLVM_CXXFLAGS ~= s,-g, +QMAKE_CXXFLAGS += $$LLVM_CXXFLAGS } + +DEFINES += CLANG_COMPILER_PATH=\"R\\\"xxx($$LLVM_INSTALL_DIR/bin/clang)xxx\\\"\" diff --git a/tests/unit/unittest/clangcodecompleteresults-test.cpp b/tests/unit/unittest/clangcodecompleteresults-test.cpp index 85e3eac1c7..d561742d7a 100644 --- a/tests/unit/unittest/clangcodecompleteresults-test.cpp +++ b/tests/unit/unittest/clangcodecompleteresults-test.cpp @@ -54,7 +54,7 @@ static unsigned completionOptions() : 0; } -TEST(ClangCodeCompleteResults, GetData) +TEST(ClangCodeCompleteResultsSlowTest, GetData) { ProjectPart projectPart(Utf8StringLiteral("projectPartId")); ClangBackEnd::ProjectParts projects; @@ -86,7 +86,7 @@ TEST(ClangCodeCompleteResults, GetInvalidData) ASSERT_THAT(codeCompleteResults.data(), cxCodeCompleteResults); } -TEST(ClangCodeCompleteResults, MoveClangCodeCompleteResults) +TEST(ClangCodeCompleteResultsSlowTest, MoveClangCodeCompleteResults) { ProjectPart projectPart(Utf8StringLiteral("projectPartId")); ClangBackEnd::ProjectParts projects; diff --git a/tests/unit/unittest/clangcreateinitialdocumentpreamblejob-test.cpp b/tests/unit/unittest/clangcreateinitialdocumentpreamblejob-test.cpp index 7a793a903e..29ef7c6826 100644 --- a/tests/unit/unittest/clangcreateinitialdocumentpreamblejob-test.cpp +++ b/tests/unit/unittest/clangcreateinitialdocumentpreamblejob-test.cpp @@ -40,6 +40,8 @@ protected: ClangBackEnd::CreateInitialDocumentPreambleJob job; }; +using CreateInitialDocumentPreambleJobSlowTest = CreateInitialDocumentPreambleJob; + TEST_F(CreateInitialDocumentPreambleJob, PrepareAsyncRun) { job.setContext(jobContext); @@ -47,7 +49,7 @@ TEST_F(CreateInitialDocumentPreambleJob, PrepareAsyncRun) ASSERT_TRUE(job.prepareAsyncRun()); } -TEST_F(CreateInitialDocumentPreambleJob, RunAsync) +TEST_F(CreateInitialDocumentPreambleJobSlowTest, RunAsync) { document.parse(); document.setDirtyIfDependencyIsMet(document.filePath()); diff --git a/tests/unit/unittest/clangdiagnosticfilter-test.cpp b/tests/unit/unittest/clangdiagnosticfilter-test.cpp index a8d3c2f175..502e2538fc 100644 --- a/tests/unit/unittest/clangdiagnosticfilter-test.cpp +++ b/tests/unit/unittest/clangdiagnosticfilter-test.cpp @@ -63,22 +63,22 @@ DiagnosticContainer createDiagnostic(const QString &text, const QString mainFileHeaderPath = QString::fromUtf8(TESTDATA_DIR "/someHeader.h"); const QString mainFilePath = QString::fromUtf8(TESTDATA_DIR "/diagnostic_erroneous_source.cpp"); -const QString includedFilePath = QString::fromUtf8(TESTDATA_DIR "/diagnostic_erroneous_header.cpp"); +const QString headerFilePath = QString::fromUtf8(TESTDATA_DIR "/diagnostic_erroneous_header.cpp"); -DiagnosticContainer warningFromIncludedFile() +DiagnosticContainer warningFromHeader() { return createDiagnostic( QStringLiteral("warning: control reaches end of non-void function"), ClangBackEnd::DiagnosticSeverity::Warning, - includedFilePath); + headerFilePath); } -DiagnosticContainer errorFromIncludedFile() +DiagnosticContainer errorFromHeader() { return createDiagnostic( QStringLiteral("C++ requires a type specifier for all declarations"), ClangBackEnd::DiagnosticSeverity::Error, - includedFilePath); + headerFilePath); } DiagnosticContainer warningFromMainFile() @@ -144,9 +144,9 @@ DiagnosticContainer warningFromMainFileWithFixits() return createDiagnosticWithFixIt(mainFilePath); } -DiagnosticContainer warningFromIncludedFileWithFixits() +DiagnosticContainer warningFromHeaderFileWithFixits() { - return createDiagnosticWithFixIt(includedFilePath); + return createDiagnosticWithFixIt(headerFilePath); } class ClangDiagnosticFilter : public ::testing::Test @@ -162,11 +162,11 @@ TEST_F(ClangDiagnosticFilter, WarningsFromMainFileAreLetThrough) ASSERT_THAT(clangDiagnosticFilter.takeWarnings(),Contains(warningFromMainFile())); } -TEST_F(ClangDiagnosticFilter, WarningsFromIncludedFileAreIgnored) +TEST_F(ClangDiagnosticFilter, WarningsFromHeaderAreIgnored) { - clangDiagnosticFilter.filter({warningFromIncludedFile()}); + clangDiagnosticFilter.filter({warningFromHeader()}); - ASSERT_THAT(clangDiagnosticFilter.takeWarnings(), Not(Contains(warningFromIncludedFile()))); + ASSERT_THAT(clangDiagnosticFilter.takeWarnings(), Not(Contains(warningFromHeader()))); } TEST_F(ClangDiagnosticFilter, ErrorsFromMainFileAreLetThrough) @@ -176,11 +176,11 @@ TEST_F(ClangDiagnosticFilter, ErrorsFromMainFileAreLetThrough) ASSERT_THAT(clangDiagnosticFilter.takeErrors(), Contains(errorFromMainFile())); } -TEST_F(ClangDiagnosticFilter, ErrorsFromIncludedFileAreIgnored) +TEST_F(ClangDiagnosticFilter, ErrorsFromHeaderAreIgnored) { - clangDiagnosticFilter.filter({errorFromIncludedFile()}); + clangDiagnosticFilter.filter({errorFromHeader()}); - ASSERT_THAT(clangDiagnosticFilter.takeErrors(), Not(Contains(errorFromIncludedFile()))); + ASSERT_THAT(clangDiagnosticFilter.takeErrors(), Not(Contains(errorFromHeader()))); } TEST_F(ClangDiagnosticFilter, FixItsFromMainFileAreLetThrough) @@ -190,12 +190,12 @@ TEST_F(ClangDiagnosticFilter, FixItsFromMainFileAreLetThrough) ASSERT_THAT(clangDiagnosticFilter.takeFixIts(), Contains(warningFromMainFileWithFixits())); } -TEST_F(ClangDiagnosticFilter, FixItsFromIncludedFileAreIgnored) +TEST_F(ClangDiagnosticFilter, FixItsFromHeaderAreIgnored) { - clangDiagnosticFilter.filter({warningFromIncludedFileWithFixits()}); + clangDiagnosticFilter.filter({warningFromHeaderFileWithFixits()}); ASSERT_THAT(clangDiagnosticFilter.takeFixIts(), - Not(Contains(warningFromIncludedFileWithFixits()))); + Not(Contains(warningFromHeaderFileWithFixits()))); } TEST_F(ClangDiagnosticFilter, WarningsAreEmptyAfterTaking) diff --git a/tests/unit/unittest/clangdocument-test.cpp b/tests/unit/unittest/clangdocument-test.cpp index a6a32dcf93..4dec96a86b 100644 --- a/tests/unit/unittest/clangdocument-test.cpp +++ b/tests/unit/unittest/clangdocument-test.cpp @@ -90,6 +90,8 @@ protected: ::Document document; }; +using DocumentSlowTest = Document; + TEST_F(Document, DefaultDocumentIsInvalid) { ::Document document; @@ -135,7 +137,7 @@ TEST_F(Document, ThrowExceptionForGettingCxTranslationUnitForInvalidUnit) ASSERT_THROW(document.translationUnit().cxIndex(), ClangBackEnd::DocumentIsNullException); } -TEST_F(Document, CxTranslationUnitGetterIsNonNullForParsedUnit) +TEST_F(DocumentSlowTest, CxTranslationUnitGetterIsNonNullForParsedUnit) { document.parse(); @@ -164,7 +166,7 @@ TEST_F(Document, LastCommandLineArgumentIsFilePath) ASSERT_THAT(arguments.at(arguments.count() - 1), Eq(nativeFilePath)); } -TEST_F(Document, TimeStampForProjectPartChangeIsUpdatedAsNewCxTranslationUnitIsGenerated) +TEST_F(DocumentSlowTest, TimeStampForProjectPartChangeIsUpdatedAsNewCxTranslationUnitIsGenerated) { auto lastChangeTimePoint = document.lastProjectPartChangeTimePoint(); std::this_thread::sleep_for(Duration(1)); @@ -174,7 +176,7 @@ TEST_F(Document, TimeStampForProjectPartChangeIsUpdatedAsNewCxTranslationUnitIsG ASSERT_THAT(document.lastProjectPartChangeTimePoint(), Gt(lastChangeTimePoint)); } -TEST_F(Document, TimeStampForProjectPartChangeIsUpdatedAsProjectPartIsCleared) +TEST_F(DocumentSlowTest, TimeStampForProjectPartChangeIsUpdatedAsProjectPartIsCleared) { ProjectPart projectPart = document.projectPart(); document.parse(); @@ -194,7 +196,7 @@ TEST_F(Document, DocumentRevisionInFileContainerGetter) ASSERT_THAT(document.fileContainer().documentRevision(), 74); } -TEST_F(Document, DependedFilePaths) +TEST_F(DocumentSlowTest, DependedFilePaths) { document.parse(); @@ -217,7 +219,7 @@ TEST_F(Document, NeedsNoReparseAfterCreation) ASSERT_FALSE(document.isNeedingReparse()); } -TEST_F(Document, NeedsReparseAfterChangeOfMainFile) +TEST_F(DocumentSlowTest, NeedsReparseAfterChangeOfMainFile) { document.parse(); @@ -226,7 +228,7 @@ TEST_F(Document, NeedsReparseAfterChangeOfMainFile) ASSERT_TRUE(document.isNeedingReparse()); } -TEST_F(Document, NoNeedForReparsingForIndependendFile) +TEST_F(DocumentSlowTest, NoNeedForReparsingForIndependendFile) { document.parse(); @@ -235,7 +237,7 @@ TEST_F(Document, NoNeedForReparsingForIndependendFile) ASSERT_FALSE(document.isNeedingReparse()); } -TEST_F(Document, NeedsReparsingForDependendFile) +TEST_F(DocumentSlowTest, NeedsReparsingForDependendFile) { document.parse(); @@ -244,7 +246,7 @@ TEST_F(Document, NeedsReparsingForDependendFile) ASSERT_TRUE(document.isNeedingReparse()); } -TEST_F(Document, NeedsNoReparsingAfterReparsing) +TEST_F(DocumentSlowTest, NeedsNoReparsingAfterReparsing) { document.parse(); document.setDirtyIfDependencyIsMet(Utf8StringLiteral(TESTDATA_DIR"/translationunits.h")); @@ -254,7 +256,7 @@ TEST_F(Document, NeedsNoReparsingAfterReparsing) ASSERT_FALSE(document.isNeedingReparse()); } -TEST_F(Document, IsIntactAfterParsing) +TEST_F(DocumentSlowTest, IsIntactAfterParsing) { document.parse(); @@ -268,14 +270,14 @@ TEST_F(Document, IsNotIntactForDeletedFile) ASSERT_FALSE(document.isIntact()); } -TEST_F(Document, DoesNotNeedReparseAfterParse) +TEST_F(DocumentSlowTest, DoesNotNeedReparseAfterParse) { document.parse(); ASSERT_FALSE(document.isNeedingReparse()); } -TEST_F(Document, NeedsReparseAfterMainFileChanged) +TEST_F(DocumentSlowTest, NeedsReparseAfterMainFileChanged) { document.parse(); @@ -284,7 +286,7 @@ TEST_F(Document, NeedsReparseAfterMainFileChanged) ASSERT_TRUE(document.isNeedingReparse()); } -TEST_F(Document, NeedsReparseAfterIncludedFileChanged) +TEST_F(DocumentSlowTest, NeedsReparseAfterIncludedFileChanged) { document.parse(); @@ -293,7 +295,7 @@ TEST_F(Document, NeedsReparseAfterIncludedFileChanged) ASSERT_TRUE(document.isNeedingReparse()); } -TEST_F(Document, DoesNotNeedReparseAfterNotIncludedFileChanged) +TEST_F(DocumentSlowTest, DoesNotNeedReparseAfterNotIncludedFileChanged) { document.parse(); @@ -302,7 +304,7 @@ TEST_F(Document, DoesNotNeedReparseAfterNotIncludedFileChanged) ASSERT_FALSE(document.isNeedingReparse()); } -TEST_F(Document, DoesNotNeedReparseAfterReparse) +TEST_F(DocumentSlowTest, DoesNotNeedReparseAfterReparse) { document.parse(); document.setDirtyIfDependencyIsMet(documentFilePath); @@ -323,7 +325,7 @@ TEST_F(Document, SetDirtyIfProjectPartIsOutdated) ASSERT_TRUE(document.isNeedingReparse()); } -TEST_F(Document, SetNotDirtyIfProjectPartIsNotOutdated) +TEST_F(DocumentSlowTest, SetNotDirtyIfProjectPartIsNotOutdated) { document.parse(); diff --git a/tests/unit/unittest/clangdocumentprocessor-test.cpp b/tests/unit/unittest/clangdocumentprocessor-test.cpp index 1674b22478..0898ec73c0 100644 --- a/tests/unit/unittest/clangdocumentprocessor-test.cpp +++ b/tests/unit/unittest/clangdocumentprocessor-test.cpp @@ -72,6 +72,8 @@ protected: dummyIpcClient}; }; +using DocumentProcessorSlowTest = DocumentProcessor; + TEST_F(DocumentProcessor, ProcessEmpty) { const JobRequests jobsStarted = documentProcessor.process(); @@ -79,7 +81,7 @@ TEST_F(DocumentProcessor, ProcessEmpty) ASSERT_THAT(jobsStarted.size(), 0); } -TEST_F(DocumentProcessor, ProcessSingleJob) +TEST_F(DocumentProcessorSlowTest, ProcessSingleJob) { const JobRequest jobRequest = createJobRequest(JobRequest::Type::UpdateDocumentAnnotations); documentProcessor.addJob(jobRequest); diff --git a/tests/unit/unittest/clangdocumentprocessors-test.cpp b/tests/unit/unittest/clangdocumentprocessors-test.cpp index 7c36146aab..340c7144a0 100644 --- a/tests/unit/unittest/clangdocumentprocessors-test.cpp +++ b/tests/unit/unittest/clangdocumentprocessors-test.cpp @@ -78,6 +78,8 @@ protected: dummyIpcClient}; }; +using DocumentProcessorsSlowTest = DocumentProcessors; + TEST_F(DocumentProcessors, HasNoItemsInitially) { ASSERT_TRUE(documentProcessors.processors().empty()); @@ -144,7 +146,7 @@ TEST_F(DocumentProcessors, ProcessEmpty) ASSERT_TRUE(jobsStarted.isEmpty()); } -TEST_F(DocumentProcessors, ProcessSingle) +TEST_F(DocumentProcessorsSlowTest, ProcessSingle) { DocumentProcessor documentProcessor = documentProcessors.create(document); const JobRequest jobRequest = createJobRequest(JobRequest::Type::UpdateDocumentAnnotations); diff --git a/tests/unit/unittest/clangdocuments-test.cpp b/tests/unit/unittest/clangdocuments-test.cpp index 688d5ed32c..4380da86b5 100644 --- a/tests/unit/unittest/clangdocuments-test.cpp +++ b/tests/unit/unittest/clangdocuments-test.cpp @@ -83,6 +83,8 @@ protected: const ClangBackEnd::FileContainer headerContainer{headerPath, projectPartId}; }; +using DocumentsSlowTest = Documents; + TEST_F(Documents, ThrowForGettingWithWrongFilePath) { ASSERT_THROW(documents.document(nonExistingFilePath, projectPartId), @@ -199,7 +201,7 @@ TEST_F(Documents, UpdateMultiple) IsDocument(filePath, otherProjectPartId, 75u)); } -TEST_F(Documents, UpdateUnsavedFileAndCheckForReparse) +TEST_F(DocumentsSlowTest, UpdateUnsavedFileAndCheckForReparse) { ClangBackEnd::FileContainer fileContainer(filePath, projectPartId, Utf8StringVector(), 74u); ClangBackEnd::FileContainer headerContainer(headerPath, projectPartId, Utf8StringVector(), 74u); @@ -213,7 +215,7 @@ TEST_F(Documents, UpdateUnsavedFileAndCheckForReparse) ASSERT_TRUE(documents.document(filePath, projectPartId).isNeedingReparse()); } -TEST_F(Documents, RemoveFileAndCheckForReparse) +TEST_F(DocumentsSlowTest, RemoveFileAndCheckForReparse) { ClangBackEnd::FileContainer fileContainer(filePath, projectPartId, Utf8StringVector(), 74u); ClangBackEnd::FileContainer headerContainer(headerPath, projectPartId, Utf8StringVector(), 74u); diff --git a/tests/unit/unittest/clangipcserver-test.cpp b/tests/unit/unittest/clangipcserver-test.cpp index 2a3c75dc2a..88ced8fe5d 100644 --- a/tests/unit/unittest/clangipcserver-test.cpp +++ b/tests/unit/unittest/clangipcserver-test.cpp @@ -95,7 +95,7 @@ MATCHER_P5(HasDirtyDocument, } } -class ClangClangCodeModelServer : public ::testing::Test +class ClangCodeModelServer : public ::testing::Test { protected: void SetUp() override; @@ -171,7 +171,9 @@ protected: const Utf8String aProjectPartId = Utf8StringLiteral("aproject.pro"); }; -TEST_F(ClangClangCodeModelServer, GetCodeCompletion) +using ClangCodeModelServerSlowTest = ClangCodeModelServer; + +TEST_F(ClangCodeModelServerSlowTest, GetCodeCompletion) { registerProjectAndFile(filePathA); @@ -179,7 +181,7 @@ TEST_F(ClangClangCodeModelServer, GetCodeCompletion) completeCodeInFileA(); } -TEST_F(ClangClangCodeModelServer, RequestDocumentAnnotations) +TEST_F(ClangCodeModelServerSlowTest, RequestDocumentAnnotations) { registerProjectAndFileAndWaitForFinished(filePathB); @@ -187,7 +189,7 @@ TEST_F(ClangClangCodeModelServer, RequestDocumentAnnotations) requestDocumentAnnotations(filePathB); } -TEST_F(ClangClangCodeModelServer, NoInitialDocumentAnnotationsForClosedDocument) +TEST_F(ClangCodeModelServerSlowTest, NoInitialDocumentAnnotationsForClosedDocument) { const int expectedDocumentAnnotationsChangedCount = 0; registerProjectAndFile(filePathA, expectedDocumentAnnotationsChangedCount); @@ -195,7 +197,7 @@ TEST_F(ClangClangCodeModelServer, NoInitialDocumentAnnotationsForClosedDocument) unregisterFile(filePathA); } -TEST_F(ClangClangCodeModelServer, NoDocumentAnnotationsForClosedDocument) +TEST_F(ClangCodeModelServerSlowTest, NoDocumentAnnotationsForClosedDocument) { const int expectedDocumentAnnotationsChangedCount = 1; // Only for registration. registerProjectAndFileAndWaitForFinished(filePathA, expectedDocumentAnnotationsChangedCount); @@ -204,7 +206,7 @@ TEST_F(ClangClangCodeModelServer, NoDocumentAnnotationsForClosedDocument) unregisterFile(filePathA); } -TEST_F(ClangClangCodeModelServer, NoInitialDocumentAnnotationsForOutdatedDocumentRevision) +TEST_F(ClangCodeModelServerSlowTest, NoInitialDocumentAnnotationsForOutdatedDocumentRevision) { const int expectedDocumentAnnotationsChangedCount = 1; // Only for registration. registerProjectAndFile(filePathA, expectedDocumentAnnotationsChangedCount); @@ -212,7 +214,7 @@ TEST_F(ClangClangCodeModelServer, NoInitialDocumentAnnotationsForOutdatedDocumen updateUnsavedContent(filePathA, Utf8String(), 1); } -TEST_F(ClangClangCodeModelServer, NoCompletionsForClosedDocument) +TEST_F(ClangCodeModelServerSlowTest, NoCompletionsForClosedDocument) { const int expectedDocumentAnnotationsChangedCount = 1; // Only for registration. registerProjectAndFileAndWaitForFinished(filePathA, expectedDocumentAnnotationsChangedCount); @@ -221,7 +223,7 @@ TEST_F(ClangClangCodeModelServer, NoCompletionsForClosedDocument) unregisterFile(filePathA); } -TEST_F(ClangClangCodeModelServer, CodeCompletionDependingOnProject) +TEST_F(ClangCodeModelServerSlowTest, CodeCompletionDependingOnProject) { const int expectedDocumentAnnotationsChangedCount = 2; // For registration and due to project change. registerProjectAndFileAndWaitForFinished(filePathB, expectedDocumentAnnotationsChangedCount); @@ -231,7 +233,7 @@ TEST_F(ClangClangCodeModelServer, CodeCompletionDependingOnProject) completeCodeInFileB(); } -TEST_F(ClangClangCodeModelServer, GetCodeCompletionForUnsavedFile) +TEST_F(ClangCodeModelServerSlowTest, GetCodeCompletionForUnsavedFile) { registerProjectPart(); expectDocumentAnnotationsChanged(1); @@ -241,7 +243,7 @@ TEST_F(ClangClangCodeModelServer, GetCodeCompletionForUnsavedFile) completeCodeInFileA(); } -TEST_F(ClangClangCodeModelServer, GetNoCodeCompletionAfterRemovingUnsavedFile) +TEST_F(ClangCodeModelServerSlowTest, GetNoCodeCompletionAfterRemovingUnsavedFile) { const int expectedDocumentAnnotationsChangedCount = 2; // For registration and update/removal. registerProjectAndFileAndWaitForFinished(filePathA, expectedDocumentAnnotationsChangedCount); @@ -251,7 +253,7 @@ TEST_F(ClangClangCodeModelServer, GetNoCodeCompletionAfterRemovingUnsavedFile) completeCodeInFileA(); } -TEST_F(ClangClangCodeModelServer, GetNewCodeCompletionAfterUpdatingUnsavedFile) +TEST_F(ClangCodeModelServerSlowTest, GetNewCodeCompletionAfterUpdatingUnsavedFile) { const int expectedDocumentAnnotationsChangedCount = 2; // For registration and update/removal. registerProjectAndFileAndWaitForFinished(filePathA, expectedDocumentAnnotationsChangedCount); @@ -261,7 +263,7 @@ TEST_F(ClangClangCodeModelServer, GetNewCodeCompletionAfterUpdatingUnsavedFile) completeCodeInFileA(); } -TEST_F(ClangClangCodeModelServer, TicketNumberIsForwarded) +TEST_F(ClangCodeModelServerSlowTest, TicketNumberIsForwarded) { registerProjectAndFile(filePathA, 1); const CompleteCodeMessage message(filePathA, 20, 1, projectPartId); @@ -270,14 +272,14 @@ TEST_F(ClangClangCodeModelServer, TicketNumberIsForwarded) clangServer.completeCode(message); } -TEST_F(ClangClangCodeModelServer, TranslationUnitAfterCreationIsNotDirty) +TEST_F(ClangCodeModelServerSlowTest, TranslationUnitAfterCreationIsNotDirty) { registerProjectAndFile(filePathA, 1); ASSERT_THAT(clangServer, HasDirtyDocument(filePathA, projectPartId, 0U, false, false)); } -TEST_F(ClangClangCodeModelServer, SetCurrentAndVisibleEditor) +TEST_F(ClangCodeModelServerSlowTest, SetCurrentAndVisibleEditor) { registerProjectAndFilesAndWaitForFinished(); auto functionDocument = documents.document(filePathA, projectPartId); @@ -290,7 +292,7 @@ TEST_F(ClangClangCodeModelServer, SetCurrentAndVisibleEditor) ASSERT_TRUE(functionDocument.isVisibleInEditor()); } -TEST_F(ClangClangCodeModelServer, StartCompletionJobFirstOnEditThatTriggersCompletion) +TEST_F(ClangCodeModelServerSlowTest, StartCompletionJobFirstOnEditThatTriggersCompletion) { registerProjectAndFile(filePathA, 2); ASSERT_TRUE(waitUntilAllJobsFinished()); @@ -304,7 +306,7 @@ TEST_F(ClangClangCodeModelServer, StartCompletionJobFirstOnEditThatTriggersCompl ASSERT_THAT(jobs.first().jobRequest.type, Eq(JobRequest::Type::CompleteCode)); } -TEST_F(ClangClangCodeModelServer, SupportiveTranslationUnitNotInitializedAfterRegister) +TEST_F(ClangCodeModelServerSlowTest, SupportiveTranslationUnitNotInitializedAfterRegister) { registerProjectAndFile(filePathA, 1); @@ -312,7 +314,7 @@ TEST_F(ClangClangCodeModelServer, SupportiveTranslationUnitNotInitializedAfterRe ASSERT_FALSE(isSupportiveTranslationUnitInitialized(filePathA)); } -TEST_F(ClangClangCodeModelServer, SupportiveTranslationUnitIsSetupAfterFirstEdit) +TEST_F(ClangCodeModelServerSlowTest, SupportiveTranslationUnitIsSetupAfterFirstEdit) { registerProjectAndFile(filePathA, 2); ASSERT_TRUE(waitUntilAllJobsFinished()); @@ -323,7 +325,7 @@ TEST_F(ClangClangCodeModelServer, SupportiveTranslationUnitIsSetupAfterFirstEdit ASSERT_TRUE(isSupportiveTranslationUnitInitialized(filePathA)); } -TEST_F(ClangClangCodeModelServer, DoNotRunDuplicateJobs) +TEST_F(ClangCodeModelServerSlowTest, DoNotRunDuplicateJobs) { registerProjectAndFile(filePathA, 3); ASSERT_TRUE(waitUntilAllJobsFinished()); @@ -337,7 +339,7 @@ TEST_F(ClangClangCodeModelServer, DoNotRunDuplicateJobs) updateVisibilty(filePathA, filePathA); // triggers adding + runnings job on next processevents() } -TEST_F(ClangClangCodeModelServer, OpenDocumentAndEdit) +TEST_F(ClangCodeModelServerSlowTest, OpenDocumentAndEdit) { registerProjectAndFile(filePathA, 4); ASSERT_TRUE(waitUntilAllJobsFinished()); @@ -348,7 +350,7 @@ TEST_F(ClangClangCodeModelServer, OpenDocumentAndEdit) } } -TEST_F(ClangClangCodeModelServer, IsNotCurrentCurrentAndVisibleEditorAnymore) +TEST_F(ClangCodeModelServerSlowTest, IsNotCurrentCurrentAndVisibleEditorAnymore) { registerProjectAndFilesAndWaitForFinished(); auto functionDocument = documents.document(filePathA, projectPartId); @@ -363,7 +365,7 @@ TEST_F(ClangClangCodeModelServer, IsNotCurrentCurrentAndVisibleEditorAnymore) ASSERT_TRUE(variableDocument.isVisibleInEditor()); } -TEST_F(ClangClangCodeModelServer, TranslationUnitAfterUpdateNeedsReparse) +TEST_F(ClangCodeModelServerSlowTest, TranslationUnitAfterUpdateNeedsReparse) { registerProjectAndFileAndWaitForFinished(filePathA, 2); @@ -371,19 +373,19 @@ TEST_F(ClangClangCodeModelServer, TranslationUnitAfterUpdateNeedsReparse) ASSERT_THAT(clangServer, HasDirtyDocument(filePathA, projectPartId, 1U, true, true)); } -void ClangClangCodeModelServer::SetUp() +void ClangCodeModelServer::SetUp() { clangServer.setClient(&mockClangCodeModelClient); clangServer.setUpdateDocumentAnnotationsTimeOutInMsForTestsOnly(0); clangServer.setUpdateVisibleButNotCurrentDocumentsTimeOutInMsForTestsOnly(0); } -void ClangClangCodeModelServer::TearDown() +void ClangCodeModelServer::TearDown() { ASSERT_TRUE(waitUntilAllJobsFinished()); } -bool ClangClangCodeModelServer::waitUntilAllJobsFinished(int timeOutInMs) +bool ClangCodeModelServer::waitUntilAllJobsFinished(int timeOutInMs) { const auto noJobsRunningAnymore = [this]() { return clangServer.runningJobsForTestsOnly().isEmpty() @@ -394,7 +396,7 @@ bool ClangClangCodeModelServer::waitUntilAllJobsFinished(int timeOutInMs) return ProcessEventUtilities::processEventsUntilTrue(noJobsRunningAnymore, timeOutInMs); } -void ClangClangCodeModelServer::registerProjectAndFilesAndWaitForFinished( +void ClangCodeModelServer::registerProjectAndFilesAndWaitForFinished( int expectedDocumentAnnotationsChangedMessages) { registerProjectPart(); @@ -403,7 +405,7 @@ void ClangClangCodeModelServer::registerProjectAndFilesAndWaitForFinished( ASSERT_TRUE(waitUntilAllJobsFinished()); } -void ClangClangCodeModelServer::registerFile(const Utf8String &filePath, +void ClangCodeModelServer::registerFile(const Utf8String &filePath, int expectedDocumentAnnotationsChangedMessages) { const FileContainer fileContainer(filePath, projectPartId); @@ -414,7 +416,7 @@ void ClangClangCodeModelServer::registerFile(const Utf8String &filePath, clangServer.registerTranslationUnitsForEditor(message); } -void ClangClangCodeModelServer::registerFiles(int expectedDocumentAnnotationsChangedMessages) +void ClangCodeModelServer::registerFiles(int expectedDocumentAnnotationsChangedMessages) { const FileContainer fileContainerA(filePathA, projectPartId); const FileContainer fileContainerB(filePathB, projectPartId); @@ -428,12 +430,12 @@ void ClangClangCodeModelServer::registerFiles(int expectedDocumentAnnotationsCha clangServer.registerTranslationUnitsForEditor(message); } -void ClangClangCodeModelServer::expectDocumentAnnotationsChanged(int count) +void ClangCodeModelServer::expectDocumentAnnotationsChanged(int count) { EXPECT_CALL(mockClangCodeModelClient, documentAnnotationsChanged(_)).Times(count); } -void ClangClangCodeModelServer::registerFile(const Utf8String &filePath, const Utf8String &projectFilePath) +void ClangCodeModelServer::registerFile(const Utf8String &filePath, const Utf8String &projectFilePath) { const FileContainer fileContainer(filePath, projectFilePath); const RegisterTranslationUnitForEditorMessage message({fileContainer}, filePath, {filePath}); @@ -441,7 +443,7 @@ void ClangClangCodeModelServer::registerFile(const Utf8String &filePath, const U clangServer.registerTranslationUnitsForEditor(message); } -void ClangClangCodeModelServer::registerFileWithUnsavedContent(const Utf8String &filePath, +void ClangCodeModelServer::registerFileWithUnsavedContent(const Utf8String &filePath, const Utf8String &unsavedContent) { const FileContainer fileContainer(filePath, projectPartId, unsavedContent, true); @@ -450,7 +452,7 @@ void ClangClangCodeModelServer::registerFileWithUnsavedContent(const Utf8String clangServer.registerTranslationUnitsForEditor(message); } -void ClangClangCodeModelServer::completeCode(const Utf8String &filePath, +void ClangCodeModelServer::completeCode(const Utf8String &filePath, uint line, uint column, const Utf8String &projectPartId) @@ -464,17 +466,17 @@ void ClangClangCodeModelServer::completeCode(const Utf8String &filePath, clangServer.completeCode(message); } -void ClangClangCodeModelServer::completeCodeInFileA() +void ClangCodeModelServer::completeCodeInFileA() { completeCode(filePathA, 20, 1); } -void ClangClangCodeModelServer::completeCodeInFileB() +void ClangCodeModelServer::completeCodeInFileB() { completeCode(filePathB, 35, 1); } -bool ClangClangCodeModelServer::isSupportiveTranslationUnitInitialized(const Utf8String &filePath) +bool ClangCodeModelServer::isSupportiveTranslationUnitInitialized(const Utf8String &filePath) { Document document = clangServer.documentsForTestOnly().document(filePath, projectPartId); DocumentProcessor documentProcessor = clangServer.documentProcessors().processor(document); @@ -484,7 +486,7 @@ bool ClangClangCodeModelServer::isSupportiveTranslationUnitInitialized(const Utf && documentProcessor.isSupportiveTranslationUnitInitialized(); } -void ClangClangCodeModelServer::expectCompletion(const CodeCompletion &completion) +void ClangCodeModelServer::expectCompletion(const CodeCompletion &completion) { EXPECT_CALL(mockClangCodeModelClient, codeCompleted(Property(&CodeCompletedMessage::codeCompletions, @@ -492,7 +494,7 @@ void ClangClangCodeModelServer::expectCompletion(const CodeCompletion &completio .Times(1); } -void ClangClangCodeModelServer::expectCompletionFromFileBEnabledByMacro() +void ClangCodeModelServer::expectCompletionFromFileBEnabledByMacro() { const CodeCompletion completion(Utf8StringLiteral("ArgumentDefinitionVariable"), 34, @@ -501,7 +503,7 @@ void ClangClangCodeModelServer::expectCompletionFromFileBEnabledByMacro() expectCompletion(completion); } -void ClangClangCodeModelServer::expectCompletionFromFileAUnsavedMethodVersion1() +void ClangCodeModelServer::expectCompletionFromFileAUnsavedMethodVersion1() { const CodeCompletion completion(Utf8StringLiteral("Method2"), 34, @@ -510,7 +512,7 @@ void ClangClangCodeModelServer::expectCompletionFromFileAUnsavedMethodVersion1() expectCompletion(completion); } -void ClangClangCodeModelServer::expectCompletionFromFileAUnsavedMethodVersion2() +void ClangCodeModelServer::expectCompletionFromFileAUnsavedMethodVersion2() { const CodeCompletion completion(Utf8StringLiteral("Method3"), 34, @@ -519,7 +521,7 @@ void ClangClangCodeModelServer::expectCompletionFromFileAUnsavedMethodVersion2() expectCompletion(completion); } -void ClangClangCodeModelServer::expectCompletionWithTicketNumber(quint64 ticketNumber) +void ClangCodeModelServer::expectCompletionWithTicketNumber(quint64 ticketNumber) { EXPECT_CALL(mockClangCodeModelClient, codeCompleted(Property(&CodeCompletedMessage::ticketNumber, @@ -527,7 +529,7 @@ void ClangClangCodeModelServer::expectCompletionWithTicketNumber(quint64 ticketN .Times(1); } -void ClangClangCodeModelServer::expectNoCompletionWithUnsavedMethod() +void ClangCodeModelServer::expectNoCompletionWithUnsavedMethod() { const CodeCompletion completion(Utf8StringLiteral("Method2"), 34, @@ -539,7 +541,7 @@ void ClangClangCodeModelServer::expectNoCompletionWithUnsavedMethod() .Times(1); } -void ClangClangCodeModelServer::expectCompletionFromFileA() +void ClangCodeModelServer::expectCompletionFromFileA() { const CodeCompletion completion(Utf8StringLiteral("Function"), 34, @@ -548,14 +550,14 @@ void ClangClangCodeModelServer::expectCompletionFromFileA() expectCompletion(completion); } -void ClangClangCodeModelServer::requestDocumentAnnotations(const Utf8String &filePath) +void ClangCodeModelServer::requestDocumentAnnotations(const Utf8String &filePath) { const RequestDocumentAnnotationsMessage message({filePath, projectPartId}); clangServer.requestDocumentAnnotations(message); } -void ClangClangCodeModelServer::expectDocumentAnnotationsChangedForFileBWithSpecificHighlightingMark() +void ClangCodeModelServer::expectDocumentAnnotationsChangedForFileBWithSpecificHighlightingMark() { HighlightingTypes types; types.mainHighlightingType = ClangBackEnd::HighlightingType::Function; @@ -569,7 +571,7 @@ void ClangClangCodeModelServer::expectDocumentAnnotationsChangedForFileBWithSpec .Times(1); } -void ClangClangCodeModelServer::updateUnsavedContent(const Utf8String &filePath, +void ClangCodeModelServer::updateUnsavedContent(const Utf8String &filePath, const Utf8String &fileContent, quint32 revisionNumber) { @@ -579,7 +581,7 @@ void ClangClangCodeModelServer::updateUnsavedContent(const Utf8String &filePath, clangServer.updateTranslationUnitsForEditor(message); } -void ClangClangCodeModelServer::removeUnsavedFile(const Utf8String &filePath) +void ClangCodeModelServer::removeUnsavedFile(const Utf8String &filePath) { const FileContainer fileContainer(filePath, projectPartId, Utf8StringVector(), 74); const UpdateTranslationUnitsForEditorMessage message({fileContainer}); @@ -587,7 +589,7 @@ void ClangClangCodeModelServer::removeUnsavedFile(const Utf8String &filePath) clangServer.updateTranslationUnitsForEditor(message); } -void ClangClangCodeModelServer::unregisterFile(const Utf8String &filePath) +void ClangCodeModelServer::unregisterFile(const Utf8String &filePath) { const QVector<FileContainer> fileContainers = {FileContainer(filePath, projectPartId)}; const UnregisterTranslationUnitsForEditorMessage message(fileContainers); @@ -595,7 +597,7 @@ void ClangClangCodeModelServer::unregisterFile(const Utf8String &filePath) clangServer.unregisterTranslationUnitsForEditor(message); } -void ClangClangCodeModelServer::unregisterFile(const Utf8String &filePath, const Utf8String &projectPartId) +void ClangCodeModelServer::unregisterFile(const Utf8String &filePath, const Utf8String &projectPartId) { const QVector<FileContainer> fileContainers = {FileContainer(filePath, projectPartId)}; const UnregisterTranslationUnitsForEditorMessage message(fileContainers); @@ -603,28 +605,28 @@ void ClangClangCodeModelServer::unregisterFile(const Utf8String &filePath, const clangServer.unregisterTranslationUnitsForEditor(message); } -void ClangClangCodeModelServer::unregisterProject(const Utf8String &projectPartId) +void ClangCodeModelServer::unregisterProject(const Utf8String &projectPartId) { const UnregisterProjectPartsForEditorMessage message({projectPartId}); clangServer.unregisterProjectPartsForEditor(message); } -void ClangClangCodeModelServer::registerProjectPart() +void ClangCodeModelServer::registerProjectPart() { RegisterProjectPartsForEditorMessage message({ProjectPartContainer(projectPartId)}); clangServer.registerProjectPartsForEditor(message); } -void ClangClangCodeModelServer::registerProjectAndFile(const Utf8String &filePath, +void ClangCodeModelServer::registerProjectAndFile(const Utf8String &filePath, int expectedDocumentAnnotationsChangedMessages) { registerProjectPart(); registerFile(filePath, expectedDocumentAnnotationsChangedMessages); } -void ClangClangCodeModelServer::registerProjectAndFileAndWaitForFinished( +void ClangCodeModelServer::registerProjectAndFileAndWaitForFinished( const Utf8String &filePath, int expectedDocumentAnnotationsChangedMessages) { @@ -632,7 +634,7 @@ void ClangClangCodeModelServer::registerProjectAndFileAndWaitForFinished( ASSERT_TRUE(waitUntilAllJobsFinished()); } -void ClangClangCodeModelServer::changeProjectPartArguments() +void ClangCodeModelServer::changeProjectPartArguments() { const ProjectPartContainer projectPartContainer(projectPartId, {Utf8StringLiteral("-DArgumentDefinition")}); @@ -641,7 +643,7 @@ void ClangClangCodeModelServer::changeProjectPartArguments() clangServer.registerProjectPartsForEditor(message); } -void ClangClangCodeModelServer::updateVisibilty(const Utf8String ¤tEditor, +void ClangCodeModelServer::updateVisibilty(const Utf8String ¤tEditor, const Utf8String &additionalVisibleEditor) { const UpdateVisibleTranslationUnitsMessage message(currentEditor, @@ -650,7 +652,7 @@ void ClangClangCodeModelServer::updateVisibilty(const Utf8String ¤tEditor, clangServer.updateVisibleTranslationUnits(message); } -const Utf8String ClangClangCodeModelServer::unsavedContent(const QString &unsavedFilePath) +const Utf8String ClangCodeModelServer::unsavedContent(const QString &unsavedFilePath) { QFile unsavedFileContentFile(unsavedFilePath); const bool isOpen = unsavedFileContentFile.open(QIODevice::ReadOnly | QIODevice::Text); diff --git a/tests/unit/unittest/clangisdiagnosticrelatedtolocation-test.cpp b/tests/unit/unittest/clangisdiagnosticrelatedtolocation-test.cpp index 490b97c455..7e008886ad 100644 --- a/tests/unit/unittest/clangisdiagnosticrelatedtolocation-test.cpp +++ b/tests/unit/unittest/clangisdiagnosticrelatedtolocation-test.cpp @@ -137,7 +137,7 @@ TEST_F(ClangIsDiagnosticRelatedToLocation, DoNoMatchAfterRangeEnd) TEST_F(ClangIsDiagnosticRelatedToLocation, MatchInAdditionalRange) { - const QVector<SourceRangeContainer> additionalRanges{ createRange(5, 5, 5, 10) }; + const QVector<SourceRangeContainer> additionalRanges{createRange(5, 5, 5, 10)}; const DiagnosticContainer diagnostic = createDiagnosticWithLocation(1, 1); ASSERT_TRUE(isDiagnosticRelatedToLocation(diagnostic, additionalRanges, 5, 7)); diff --git a/tests/unit/unittest/clangjobs-test.cpp b/tests/unit/unittest/clangjobs-test.cpp index 6285fdd017..f688df3f60 100644 --- a/tests/unit/unittest/clangjobs-test.cpp +++ b/tests/unit/unittest/clangjobs-test.cpp @@ -74,6 +74,8 @@ protected: ClangBackEnd::Jobs jobs{documents, unsavedFiles, projects, dummyClientInterface}; }; +using JobsSlowTest = Jobs; + TEST_F(Jobs, ProcessEmptyQueue) { const JobRequests jobsStarted = jobs.process(); @@ -82,7 +84,7 @@ TEST_F(Jobs, ProcessEmptyQueue) ASSERT_TRUE(jobs.runningJobs().isEmpty()); } -TEST_F(Jobs, ProcessQueueWithSingleJob) +TEST_F(JobsSlowTest, ProcessQueueWithSingleJob) { jobs.add(createJobRequest(filePath1, JobRequest::Type::UpdateDocumentAnnotations)); @@ -92,7 +94,7 @@ TEST_F(Jobs, ProcessQueueWithSingleJob) ASSERT_THAT(jobs.runningJobs().size(), Eq(1)); } -TEST_F(Jobs, ProcessQueueUntilEmpty) +TEST_F(JobsSlowTest, ProcessQueueUntilEmpty) { jobs.add(createJobRequest(filePath1, JobRequest::Type::UpdateDocumentAnnotations)); jobs.add(createJobRequest(filePath1, JobRequest::Type::UpdateDocumentAnnotations)); @@ -103,7 +105,7 @@ TEST_F(Jobs, ProcessQueueUntilEmpty) waitUntilJobChainFinished(); } -TEST_F(Jobs, IsJobRunning) +TEST_F(JobsSlowTest, IsJobRunning) { jobs.add(createJobRequest(filePath1, JobRequest::Type::UpdateDocumentAnnotations)); jobs.process(); diff --git a/tests/unit/unittest/clangparsesupportivetranslationunitjobtest.cpp b/tests/unit/unittest/clangparsesupportivetranslationunitjob-test.cpp index 4b7d5bc23b..7a1edd4fc8 100644 --- a/tests/unit/unittest/clangparsesupportivetranslationunitjobtest.cpp +++ b/tests/unit/unittest/clangparsesupportivetranslationunitjob-test.cpp @@ -47,6 +47,8 @@ protected: ClangBackEnd::ParseSupportiveTranslationUnitJob job; }; +using ParseSupportiveTranslationUnitJobSlowTest = ParseSupportiveTranslationUnitJob; + TEST_F(ParseSupportiveTranslationUnitJob, PrepareAsyncRun) { job.setContext(jobContext); @@ -54,7 +56,7 @@ TEST_F(ParseSupportiveTranslationUnitJob, PrepareAsyncRun) ASSERT_TRUE(job.prepareAsyncRun()); } -TEST_F(ParseSupportiveTranslationUnitJob, RunAsync) +TEST_F(ParseSupportiveTranslationUnitJobSlowTest, RunAsync) { job.setContext(jobContext); job.prepareAsyncRun(); @@ -64,7 +66,7 @@ TEST_F(ParseSupportiveTranslationUnitJob, RunAsync) ASSERT_TRUE(waitUntilJobFinished(job)); } -TEST_F(ParseSupportiveTranslationUnitJob, DoNotIncorporateUpdaterResult) +TEST_F(ParseSupportiveTranslationUnitJobSlowTest, DoNotIncorporateUpdaterResult) { const TimePoint parseTimePointBefore = parseTimePointOfDocument(); job.setContext(jobContext); diff --git a/tests/unit/unittest/clangpathwatcher-test.cpp b/tests/unit/unittest/clangpathwatcher-test.cpp new file mode 100644 index 0000000000..7f2c4b7e61 --- /dev/null +++ b/tests/unit/unittest/clangpathwatcher-test.cpp @@ -0,0 +1,324 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#include "googletest.h" + +#include "faketimer.h" +#include "mockqfilesystemwatcher.h" +#include "mockclangpathwatchernotifier.h" + +#include <clangpathwatcher.h> +#include <stringcache.h> + +namespace { + +using testing::_; +using testing::ElementsAre; +using testing::IsEmpty; +using testing::SizeIs; +using testing::NiceMock; + +using Watcher = ClangBackEnd::ClangPathWatcher<NiceMock<MockQFileSytemWatcher>, FakeTimer>; +using ClangBackEnd::WatcherEntry; + +class ClangPathWatcher : public testing::Test +{ +protected: + ClangBackEnd::StringCache<Utils::PathString> pathCache; + NiceMock<MockClangPathWatcherNotifier> notifier; + Watcher watcher{pathCache, ¬ifier}; + NiceMock<MockQFileSytemWatcher> &mockQFileSytemWatcher = watcher.fileSystemWatcher(); + Utils::SmallString id1{"id4"}; + Utils::SmallString id2{"id2"}; + Utils::SmallString id3{"id3"}; + Utils::PathString path1{"/path/path1"}; + Utils::PathString path2{"/path/path2"}; + std::vector<uint> paths = watcher.pathCache().stringIds({path1, path2}); + std::vector<uint> ids = watcher.idCache().stringIds({id1, id2, id3}); + WatcherEntry watcherEntry1{ids[0], paths[0]}; + WatcherEntry watcherEntry2{ids[1], paths[0]}; + WatcherEntry watcherEntry3{ids[0], paths[1]}; + WatcherEntry watcherEntry4{ids[1], paths[1]}; + WatcherEntry watcherEntry5{ids[2], paths[1]}; +}; + +TEST_F(ClangPathWatcher, ConvertWatcherEntriesToQStringList) +{ + auto convertedList = watcher.convertWatcherEntriesToQStringList({watcherEntry1, watcherEntry3}); + + ASSERT_THAT(convertedList, ElementsAre(path1, path2)); +} + +TEST_F(ClangPathWatcher, UniquePaths) +{ + auto uniqueEntries = watcher.uniquePaths({watcherEntry1, watcherEntry2, watcherEntry3, watcherEntry4}); + + ASSERT_THAT(uniqueEntries, ElementsAre(watcherEntry1, watcherEntry3)); +} + +TEST_F(ClangPathWatcher, NotWatchedEntries) +{ + watcher.addEntries({watcherEntry1, watcherEntry4}); + + auto newEntries = watcher.notWatchedEntries({watcherEntry1, watcherEntry2, watcherEntry3, watcherEntry4}); + + ASSERT_THAT(newEntries, ElementsAre(watcherEntry2, watcherEntry3)); +} + +TEST_F(ClangPathWatcher, AddIdPaths) +{ + EXPECT_CALL(mockQFileSytemWatcher, addPaths(QStringList{path1, path2})); + + watcher.updateIdPaths({{id1, {paths[0], paths[1]}}, {id2, {paths[0], paths[1]}}}); +} + +TEST_F(ClangPathWatcher, UpdateIdPathsCallsAddPathInFileWatcher) +{ + watcher.updateIdPaths({{id1, {paths[0]}}, {id2, {paths[0]}}}); + + EXPECT_CALL(mockQFileSytemWatcher, addPaths(QStringList{path2})); + + watcher.updateIdPaths({{id1, {paths[0], paths[1]}}, {id2, {paths[0], paths[1]}}}); +} + +TEST_F(ClangPathWatcher, UpdateIdPathsAndRemoveUnusedPathsCallsRemovePathInFileWatcher) +{ + watcher.updateIdPaths({{id1, {paths[0], paths[1]}}, {id2, {paths[0], paths[1]}}, {id3, {paths[0]}}}); + + EXPECT_CALL(mockQFileSytemWatcher, removePaths(QStringList{path2})); + + watcher.updateIdPaths({{id1, {paths[0]}}, {id2, {paths[0]}}}); +} + +TEST_F(ClangPathWatcher, UpdateIdPathsAndRemoveUnusedPathsDoNotCallsRemovePathInFileWatcher) +{ + watcher.updateIdPaths({{id1, {paths[0], paths[1]}}, {id2, {paths[0], paths[1]}}, {id3, {paths[0]}}}); + + EXPECT_CALL(mockQFileSytemWatcher, removePaths(QStringList{path2})) + .Times(0); + + watcher.updateIdPaths({{id1, {paths[1]}}, {id2, {paths[0]}}}); +} + +TEST_F(ClangPathWatcher, UpdateIdPathsAndRemoveUnusedPaths) +{ + watcher.updateIdPaths({{id1, {paths[0], paths[1]}}, {id2, {paths[0], paths[1]}}, {id3, {paths[1]}}}); + + watcher.updateIdPaths({{id1, {paths[0]}}, {id2, {paths[1]}}}); + + ASSERT_THAT(watcher.watchedEntries(), ElementsAre(watcherEntry1, watcherEntry4, watcherEntry5)); +} + +TEST_F(ClangPathWatcher, ExtractSortedEntriesFromConvertIdPaths) +{ + auto entriesAndIds = watcher.convertIdPathsToWatcherEntriesAndIds({{id2, {paths[0], paths[1]}}, {id1, {paths[0], paths[1]}}}); + + ASSERT_THAT(entriesAndIds.first, ElementsAre(watcherEntry1, watcherEntry2, watcherEntry3, watcherEntry4)); +} + +TEST_F(ClangPathWatcher, ExtractSortedIdsFromConvertIdPaths) +{ + auto entriesAndIds = watcher.convertIdPathsToWatcherEntriesAndIds({{id2, {}}, {id1, {}}, {id3, {}}}); + + ASSERT_THAT(entriesAndIds.second, ElementsAre(ids[0], ids[1], ids[2])); +} + +TEST_F(ClangPathWatcher, NotWatchedPaths) +{ + watcher.mergeToWatchedEntries({watcherEntry1}); + + auto newEntries = watcher.notWatchedPaths({watcherEntry2, watcherEntry3}); + + ASSERT_THAT(newEntries, ElementsAre(watcherEntry3)); +} + +TEST_F(ClangPathWatcher, AddedPaths) +{ + watcher.mergeToWatchedEntries({watcherEntry1, watcherEntry2}); + + auto filteredEntries = watcher.filterNotWatchedPaths({watcherEntry1, watcherEntry2, watcherEntry3, watcherEntry4}); + + ASSERT_THAT(filteredEntries, ElementsAre(watcherEntry3)); +} + +TEST_F(ClangPathWatcher, MergeEntries) +{ + watcher.mergeToWatchedEntries({watcherEntry1, watcherEntry4}); + + ASSERT_THAT(watcher.watchedEntries(), ElementsAre(watcherEntry1, watcherEntry4)); +} + +TEST_F(ClangPathWatcher, MergeMoreEntries) +{ + watcher.mergeToWatchedEntries({watcherEntry1, watcherEntry4}); + + watcher.mergeToWatchedEntries({watcherEntry2, watcherEntry3}); + + ASSERT_THAT(watcher.watchedEntries(), ElementsAre(watcherEntry1, watcherEntry2, watcherEntry3, watcherEntry4)); +} + +TEST_F(ClangPathWatcher, AddEmptyEntries) +{ + EXPECT_CALL(mockQFileSytemWatcher, addPaths(_)) + .Times(0); + + watcher.addEntries({}); +} + +TEST_F(ClangPathWatcher, AddEntriesWithSameIdAndDifferentPaths) +{ + EXPECT_CALL(mockQFileSytemWatcher, addPaths(QStringList{path1, path2})); + + watcher.addEntries({watcherEntry1, watcherEntry3}); +} + +TEST_F(ClangPathWatcher, AddEntriesWithDifferentIdAndSamePaths) +{ + EXPECT_CALL(mockQFileSytemWatcher, addPaths(QStringList{path1})); + + watcher.addEntries({watcherEntry1, watcherEntry2}); +} + +TEST_F(ClangPathWatcher, DontAddNewEntriesWithSameIdAndSamePaths) +{ + watcher.addEntries({watcherEntry1}); + + EXPECT_CALL(mockQFileSytemWatcher, addPaths(QStringList{path1})) + .Times(0); + + watcher.addEntries({watcherEntry1}); +} + +TEST_F(ClangPathWatcher, DontAddNewEntriesWithDifferentIdAndSamePaths) +{ + watcher.addEntries({watcherEntry1}); + + EXPECT_CALL(mockQFileSytemWatcher, addPaths(QStringList{path1})) + .Times(0); + + watcher.addEntries({watcherEntry2}); +} + +TEST_F(ClangPathWatcher, RemoveEntriesWithId) +{ + watcher.addEntries({watcherEntry1, watcherEntry2, watcherEntry3, watcherEntry4, watcherEntry5}); + + watcher.removeIdsFromWatchedEntries({ids[0]}); + + ASSERT_THAT(watcher.watchedEntries(), ElementsAre(watcherEntry2, watcherEntry4, watcherEntry5)); +} + +TEST_F(ClangPathWatcher, RemoveNoPathsForEmptyIds) +{ + EXPECT_CALL(mockQFileSytemWatcher, removePaths(_)) + .Times(0); + + watcher.removeIds({}); +} + +TEST_F(ClangPathWatcher, RemoveNoPathsForOneId) +{ + watcher.addEntries({watcherEntry1, watcherEntry2, watcherEntry3, watcherEntry4}); + + EXPECT_CALL(mockQFileSytemWatcher, removePaths(_)) + .Times(0); + + watcher.removeIds({id1}); +} + +TEST_F(ClangPathWatcher, RemovePathForOneId) +{ + watcher.addEntries({watcherEntry1, watcherEntry2, watcherEntry3}); + + EXPECT_CALL(mockQFileSytemWatcher, removePaths(QStringList{path2})); + + watcher.removeIds({id1}); +} + +TEST_F(ClangPathWatcher, RemoveAllPathsForThreeId) +{ + watcher.addEntries({watcherEntry1, watcherEntry2, watcherEntry3, watcherEntry4, watcherEntry5}); + + EXPECT_CALL(mockQFileSytemWatcher, removePaths(QStringList{path1, path2})); + + watcher.removeIds({id1, id2, id3}); +} + +TEST_F(ClangPathWatcher, RemoveOnePathForTwoId) +{ + watcher.addEntries({watcherEntry1, watcherEntry2, watcherEntry3, watcherEntry4, watcherEntry5}); + + EXPECT_CALL(mockQFileSytemWatcher, removePaths(QStringList{path1})); + + watcher.removeIds({id1, id2}); +} + +TEST_F(ClangPathWatcher, NotAnymoreWatchedEntriesWithId) +{ + watcher.addEntries({watcherEntry1, watcherEntry2, watcherEntry3, watcherEntry4, watcherEntry5}); + + auto oldEntries = watcher.notAnymoreWatchedEntriesWithIds({watcherEntry1, watcherEntry4}, {ids[0], ids[1]}); + + ASSERT_THAT(oldEntries, ElementsAre(watcherEntry2, watcherEntry3)); +} + +TEST_F(ClangPathWatcher, RemoveUnusedEntries) +{ + watcher.addEntries({watcherEntry1, watcherEntry2, watcherEntry3, watcherEntry4, watcherEntry5}); + + watcher.removeFromWatchedEntries({watcherEntry2, watcherEntry3}); + + ASSERT_THAT(watcher.watchedEntries(), ElementsAre(watcherEntry1, watcherEntry4, watcherEntry5)); +} + +TEST_F(ClangPathWatcher, EmptyVectorNotifyFileChange) +{ + watcher.addEntries({watcherEntry3}); + + EXPECT_CALL(notifier, pathsWithIdsChanged(IsEmpty())).Times(1); + + mockQFileSytemWatcher.fileChanged(path1.toQString()); +} + +TEST_F(ClangPathWatcher, NotifyFileChange) +{ + watcher.addEntries({watcherEntry1, watcherEntry2, watcherEntry3, watcherEntry4, watcherEntry5}); + + EXPECT_CALL(notifier, pathsWithIdsChanged(ElementsAre(id2, id1))); + + mockQFileSytemWatcher.fileChanged(path1.toQString()); +} + +TEST_F(ClangPathWatcher, TwoNotifyFileChanges) +{ + watcher.addEntries({watcherEntry1, watcherEntry2, watcherEntry3, watcherEntry4, watcherEntry5}); + + EXPECT_CALL(notifier, pathsWithIdsChanged(ElementsAre(id2, id3, id1))); + + mockQFileSytemWatcher.fileChanged(path2.toQString()); + mockQFileSytemWatcher.fileChanged(path1.toQString()); +} + +} diff --git a/tests/unit/unittest/clangquery-test.cpp b/tests/unit/unittest/clangquery-test.cpp new file mode 100644 index 0000000000..a43872c43d --- /dev/null +++ b/tests/unit/unittest/clangquery-test.cpp @@ -0,0 +1,180 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#include "googletest.h" +#include "sourcerangecontainer-matcher.h" +#include "dynamicastmatcherdiagnosticcontainer-matcher.h" + +#include <clangquery.h> + +using ClangBackEnd::ClangQuery; + +using testing::IsEmpty; +using testing::Not; +using testing::AllOf; + +namespace { + +class ClangQuery : public ::testing::Test +{ +protected: + void SetUp() override; + +protected: + ::ClangQuery simpleFunctionQuery; + ::ClangQuery simpleClassQuery; +}; + +using ClangQuerySlowTest = ClangQuery; + +TEST_F(ClangQuery, NoSourceRangesForDefaultConstruction) +{ + auto sourceRanges = simpleFunctionQuery.takeSourceRanges(); + + ASSERT_THAT(sourceRanges.sourceRangeWithTextContainers(), IsEmpty()); +} + +TEST_F(ClangQuerySlowTest, SourceRangesForSimpleFunctionDeclarationAreNotEmpty) +{ + simpleFunctionQuery.setQuery("functionDecl()"); + + simpleFunctionQuery.findLocations(); + + ASSERT_THAT(simpleFunctionQuery.takeSourceRanges().sourceRangeWithTextContainers(), Not(IsEmpty())); +} + +TEST_F(ClangQuerySlowTest, RootSourceRangeForSimpleFunctionDeclarationRange) +{ + simpleFunctionQuery.setQuery("functionDecl()"); + + simpleFunctionQuery.findLocations(); + + ASSERT_THAT(simpleFunctionQuery.takeSourceRanges().sourceRangeWithTextContainers().at(0), + IsSourceRangeWithText(1, 1, 8, 2, "int function(int* pointer, int value)\n{\n if (pointer == nullptr) {\n return value + 1;\n } else {\n return value - 1;\n }\n}")); +} + +TEST_F(ClangQuerySlowTest, SourceRangeInUnsavedFileDeclarationRange) +{ + ::ClangQuery query; + query.addFile(TESTDATA_DIR, "query_simplefunction.cpp", "#include \"unsaved.h\"", {"cc", "query_simplefunction.cpp", "-std=c++14"}); + query.setQuery("functionDecl()"); + ClangBackEnd::V2::FileContainer unsavedFile{{TESTDATA_DIR, "unsaved.h"}, "void unsaved();", {}}; + query.addUnsavedFiles({unsavedFile}); + + query.findLocations(); + + ASSERT_THAT(query.takeSourceRanges().sourceRangeWithTextContainers().at(0), + IsSourceRangeWithText(1, 1, 1, 15, "void unsaved();")); +} + +TEST_F(ClangQuerySlowTest, RootSourceRangeForSimpleFieldDeclarationRange) +{ + simpleClassQuery.setQuery("fieldDecl(hasType(isInteger()))"); + + simpleClassQuery.findLocations(); + + ASSERT_THAT(simpleClassQuery.takeSourceRanges().sourceRangeWithTextContainers().at(0), + IsSourceRangeWithText(4, 5, 4, 10, " int x;")); +} + +TEST_F(ClangQuerySlowTest, NoSourceRangesForEmptyQuery) +{ + simpleClassQuery.findLocations(); + + ASSERT_THAT(simpleClassQuery.takeSourceRanges().sourceRangeWithTextContainers(), IsEmpty()); +} + +TEST_F(ClangQuerySlowTest, NoSourceRangesForWrongQuery) +{ + simpleClassQuery.setQuery("wrongQuery()"); + + simpleClassQuery.findLocations(); + + ASSERT_THAT(simpleClassQuery.takeSourceRanges().sourceRangeWithTextContainers(), IsEmpty()); +} + +TEST_F(ClangQuerySlowTest, NoDiagnosticsForDefaultConstruction) +{ + auto diagnostics = simpleFunctionQuery.takeDiagnosticContainers(); + + ASSERT_THAT(diagnostics, IsEmpty()); +} + +TEST_F(ClangQuerySlowTest, DiagnosticsForEmptyQuery) +{ + simpleFunctionQuery.findLocations(); + + ASSERT_THAT(simpleFunctionQuery.takeDiagnosticContainers(), + Not(IsEmpty())); +} + +TEST_F(ClangQuerySlowTest, DiagnosticsForWrongQuery) +{ + simpleClassQuery.setQuery("wrongQuery()"); + + simpleClassQuery.findLocations(); + + ASSERT_THAT(simpleClassQuery.takeDiagnosticContainers(), + Not(IsEmpty())); +} + +TEST_F(ClangQuerySlowTest, NoDiagnosticsForAccurateQuery) +{ + simpleFunctionQuery.setQuery("functionDecl()"); + + simpleFunctionQuery.findLocations(); + + ASSERT_THAT(simpleFunctionQuery.takeDiagnosticContainers(), + IsEmpty()); +} + +TEST_F(ClangQuerySlowTest, DiagnosticForWrongQuery) +{ + simpleClassQuery.setQuery("wrongQuery()"); + + simpleClassQuery.findLocations(); + + ASSERT_THAT(simpleClassQuery.takeDiagnosticContainers(), + HasDiagnosticMessage("RegistryMatcherNotFound", 1, 1, 1, 11)); +} + +TEST_F(ClangQuerySlowTest, DiagnosticForWrongArgumenType) +{ + simpleFunctionQuery.setQuery("functionDecl(1)"); + + simpleFunctionQuery.findLocations(); + + ASSERT_THAT(simpleFunctionQuery.takeDiagnosticContainers(), + AllOf(HasDiagnosticMessage("RegistryWrongArgType", 1, 14, 1, 15), + HasDiagnosticContext("MatcherConstruct", 1, 1, 1, 13))); +} + +void ClangQuery::SetUp() +{ + simpleFunctionQuery.addFile(TESTDATA_DIR, "query_simplefunction.cpp", "", {"cc", "query_simplefunction.cpp", "-std=c++14"}); + simpleClassQuery.addFile(TESTDATA_DIR, "query_simpleclass.cpp", "", {"cc", "query_simpleclass.cpp", "-std=c++14"}); + +} +} diff --git a/tests/unit/unittest/clangqueryprojectfindfilter-test.cpp b/tests/unit/unittest/clangqueryprojectfindfilter-test.cpp new file mode 100644 index 0000000000..6e509ba019 --- /dev/null +++ b/tests/unit/unittest/clangqueryprojectfindfilter-test.cpp @@ -0,0 +1,217 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#include "googletest.h" + +#include "mockrefactoringserver.h" +#include "mocksearch.h" +#include "mocksearchhandle.h" + +#include <clangqueryprojectsfindfilter.h> +#include <refactoringclient.h> + +#include <requestsourcelocationforrenamingmessage.h> +#include <requestsourcerangesanddiagnosticsforquerymessage.h> + +#include <cpptools/clangcompileroptionsbuilder.h> +#include <cpptools/projectpart.h> + +namespace { + +using ::testing::_; +using ::testing::NiceMock; +using ::testing::NotNull; +using ::testing::Return; +using ::testing::ReturnNew; +using ::testing::DefaultValue; +using ::testing::ByMove; + +using CppTools::ClangCompilerOptionsBuilder; + +class ClangQueryProjectFindFilter : public ::testing::Test +{ +protected: + void SetUp(); + std::unique_ptr<ClangRefactoring::SearchHandle> createSearchHandle(); + +protected: + NiceMock<MockRefactoringServer> mockRefactoringServer; + NiceMock<MockSearch> mockSearch; + ClangRefactoring::RefactoringClient refactoringClient; + ClangRefactoring::ClangQueryProjectsFindFilter findFilter{mockRefactoringServer, mockSearch, refactoringClient}; + QString findDeclQueryText{"functionDecl()"}; + QString curentDocumentFilePath{"/path/to/file.cpp"}; + QString unsavedDocumentContent{"void f();"}; + std::vector<Utils::SmallStringVector> commandLines; + std::vector<CppTools::ProjectPart::Ptr> projectsParts; + ClangBackEnd::V2::FileContainer unsavedContent{{"/path/to", "unsaved.cpp"}, + "void f();", + {}}; +}; + +TEST_F(ClangQueryProjectFindFilter, SupportedFindFlags) +{ + auto findFlags = findFilter.supportedFindFlags(); + + ASSERT_FALSE(findFlags); +} + +TEST_F(ClangQueryProjectFindFilter, IsNotUsableForUnusableServer) +{ + auto isUsable = findFilter.isUsable(); + + ASSERT_FALSE(isUsable); +} + +TEST_F(ClangQueryProjectFindFilter, IsUsableForUsableServer) +{ + mockRefactoringServer.setUsable(true); + + auto isUsable = findFilter.isUsable(); + + ASSERT_TRUE(isUsable); +} + +TEST_F(ClangQueryProjectFindFilter, ServerIsUsableForUsableFindFilter) +{ + findFilter.setUsable(true); + + auto isUsable = mockRefactoringServer.isUsable(); + + ASSERT_TRUE(isUsable); +} + +TEST_F(ClangQueryProjectFindFilter, SearchHandleSetIsSetAfterFindAll) +{ + findFilter.findAll(findDeclQueryText); + + auto searchHandle = refactoringClient.searchHandle(); + + ASSERT_THAT(searchHandle, NotNull()); +} + +TEST_F(ClangQueryProjectFindFilter, FindAllIsCallingStartNewSearch) +{ + EXPECT_CALL(mockSearch, startNewSearch(QStringLiteral("Clang Query"), + findDeclQueryText)) + .Times(1); + + findFilter.findAll(findDeclQueryText); +} + +TEST_F(ClangQueryProjectFindFilter, FindAllIsSettingExprectedResultCountInTheRefactoringClient) +{ + findFilter.findAll(findDeclQueryText); + + ASSERT_THAT(refactoringClient.expectedResultCount(), 3); +} + +TEST_F(ClangQueryProjectFindFilter, FindAllIsCallingRequestSourceRangesAndDiagnosticsForQueryMessage) +{ + ClangBackEnd::RequestSourceRangesAndDiagnosticsForQueryMessage message(findDeclQueryText, + {{{"/path/to", "file1.h"}, + "", + commandLines[0].clone()}, + {{"/path/to", "file1.cpp"}, + "", + commandLines[1].clone()}, + {{"/path/to", "file2.cpp"}, + "", + commandLines[2].clone()}}, + {unsavedContent.clone()}); + + EXPECT_CALL(mockRefactoringServer, requestSourceRangesAndDiagnosticsForQueryMessage(message)) + .Times(1); + + findFilter.findAll(findDeclQueryText); +} + +TEST_F(ClangQueryProjectFindFilter, CancelSearch) +{ + EXPECT_CALL(mockRefactoringServer, cancel()) + .Times(1); + + findFilter.findAll(findDeclQueryText); + + findFilter.searchHandleForTestOnly()->cancel(); +} + +std::vector<CppTools::ProjectPart::Ptr> createProjectParts() +{ + auto projectPart1 = CppTools::ProjectPart::Ptr(new CppTools::ProjectPart); + projectPart1->files.append({"/path/to/file1.h", CppTools::ProjectFile::CXXHeader}); + projectPart1->files.append({"/path/to/file1.cpp", CppTools::ProjectFile::CXXSource}); + + auto projectPart2 = CppTools::ProjectPart::Ptr(new CppTools::ProjectPart); + projectPart2->files.append({"/path/to/file2.cpp", CppTools::ProjectFile::CXXSource}); + projectPart2->files.append({"/path/to/unsaved.cpp", CppTools::ProjectFile::CXXSource}); + projectPart2->files.append({"/path/to/cheader.h", CppTools::ProjectFile::CHeader}); + + + return {projectPart1, projectPart2}; +} + +std::vector<Utils::SmallStringVector> +createCommandLines(const std::vector<CppTools::ProjectPart::Ptr> &projectParts) +{ + using Filter = ClangRefactoring::ClangQueryProjectsFindFilter; + + std::vector<Utils::SmallStringVector> commandLines; + + for (const CppTools::ProjectPart::Ptr &projectPart : projectParts) { + for (const CppTools::ProjectFile &projectFile : projectPart->files) { + Utils::SmallStringVector commandLine = Filter::compilerArguments(projectPart.data(), + projectFile.kind); + commandLine.emplace_back(projectFile.path); + commandLines.push_back(commandLine); + } + } + + return commandLines; +} + +void ClangQueryProjectFindFilter::SetUp() +{ + projectsParts = createProjectParts(); + commandLines = createCommandLines(projectsParts); + + findFilter.setProjectParts(projectsParts); + findFilter.setUnsavedContent({unsavedContent.clone()}); + + + ON_CALL(mockSearch, startNewSearch(QStringLiteral("Clang Query"), findDeclQueryText)) + .WillByDefault(Return(ByMove(createSearchHandle()))); + +} + +std::unique_ptr<ClangRefactoring::SearchHandle> ClangQueryProjectFindFilter::createSearchHandle() +{ + std::unique_ptr<ClangRefactoring::SearchHandle> handle(new NiceMock<MockSearchHandle>); + handle->setRefactoringServer(&mockRefactoringServer); + + return handle; +} + +} diff --git a/tests/unit/unittest/clangreparsesupportivetranslationunitjobtest.cpp b/tests/unit/unittest/clangreparsesupportivetranslationunitjob-test.cpp index 1796b183c4..449de4e2f3 100644 --- a/tests/unit/unittest/clangreparsesupportivetranslationunitjobtest.cpp +++ b/tests/unit/unittest/clangreparsesupportivetranslationunitjob-test.cpp @@ -48,6 +48,8 @@ protected: ClangBackEnd::ReparseSupportiveTranslationUnitJob job; }; +using ReparseSupportiveTranslationUnitJobSlowTest = ReparseSupportiveTranslationUnitJob; + TEST_F(ReparseSupportiveTranslationUnitJob, PrepareAsyncRun) { job.setContext(jobContext); @@ -55,7 +57,7 @@ TEST_F(ReparseSupportiveTranslationUnitJob, PrepareAsyncRun) ASSERT_TRUE(job.prepareAsyncRun()); } -TEST_F(ReparseSupportiveTranslationUnitJob, RunAsync) +TEST_F(ReparseSupportiveTranslationUnitJobSlowTest, RunAsync) { parse(); job.setContext(jobContext); @@ -66,7 +68,7 @@ TEST_F(ReparseSupportiveTranslationUnitJob, RunAsync) ASSERT_TRUE(waitUntilJobFinished(job)); } -TEST_F(ReparseSupportiveTranslationUnitJob, IncorporateUpdaterResult) +TEST_F(ReparseSupportiveTranslationUnitJobSlowTest, IncorporateUpdaterResult) { parse(); const TimePoint parseTimePointBefore = parseTimePointOfDocument(); @@ -79,7 +81,7 @@ TEST_F(ReparseSupportiveTranslationUnitJob, IncorporateUpdaterResult) ASSERT_THAT(parseTimePointOfDocument(), Not(Eq(parseTimePointBefore))); } -TEST_F(ReparseSupportiveTranslationUnitJob, DoNotIncorporateUpdaterResultIfDocumentWasClosed) +TEST_F(ReparseSupportiveTranslationUnitJobSlowTest, DoNotIncorporateUpdaterResultIfDocumentWasClosed) { parse(); const TimePoint parseTimePointBefore = parseTimePointOfDocument(); diff --git a/tests/unit/unittest/clangsupportivetranslationunitinitializertest.cpp b/tests/unit/unittest/clangsupportivetranslationunitinitializer-test.cpp index 3c75c20c6f..82041220e6 100644 --- a/tests/unit/unittest/clangsupportivetranslationunitinitializertest.cpp +++ b/tests/unit/unittest/clangsupportivetranslationunitinitializer-test.cpp @@ -132,6 +132,8 @@ protected: ClangBackEnd::SupportiveTranslationUnitInitializer &initializer = *d.initializer; }; +using SupportiveTranslationUnitInitializerSlowTest = SupportiveTranslationUnitInitializer; + TEST_F(SupportiveTranslationUnitInitializer, HasInitiallyNotInitializedState) { ASSERT_THAT(initializer.state(), Eq(ClangBackEnd::SupportiveTranslationUnitInitializer::State::NotInitialized)); @@ -147,7 +149,7 @@ TEST_F(SupportiveTranslationUnitInitializer, StartInitializingAbortsIfDocumentIs ASSERT_THAT(initializer.state(), Eq(ClangBackEnd::SupportiveTranslationUnitInitializer::State::Aborted)); } -TEST_F(SupportiveTranslationUnitInitializer, StartInitializingAddsTranslationUnit) +TEST_F(SupportiveTranslationUnitInitializerSlowTest, StartInitializingAddsTranslationUnit) { initializer.startInitializing(); @@ -155,7 +157,7 @@ TEST_F(SupportiveTranslationUnitInitializer, StartInitializingAddsTranslationUni ASSERT_FALSE(document.translationUnits().areAllTranslationUnitsParsed()); } -TEST_F(SupportiveTranslationUnitInitializer, StartInitializingStartsJob) +TEST_F(SupportiveTranslationUnitInitializerSlowTest, StartInitializingStartsJob) { initializer.startInitializing(); @@ -176,7 +178,7 @@ TEST_F(SupportiveTranslationUnitInitializer, CheckIfParseJobFinishedAbortsIfDocu ASSERT_THAT(initializer.state(), Eq(ClangBackEnd::SupportiveTranslationUnitInitializer::State::Aborted)); } -TEST_F(SupportiveTranslationUnitInitializer, CheckIfParseJobFinishedStartsJob) +TEST_F(SupportiveTranslationUnitInitializerSlowTest, CheckIfParseJobFinishedStartsJob) { parse(); initializer.setState(ClangBackEnd::SupportiveTranslationUnitInitializer::State::WaitingForParseJob); @@ -202,7 +204,7 @@ TEST_F(SupportiveTranslationUnitInitializer, CheckIfReparseJobFinishedAbortsIfDo ASSERT_THAT(initializer.state(), Eq(ClangBackEnd::SupportiveTranslationUnitInitializer::State::Aborted)); } -TEST_F(SupportiveTranslationUnitInitializer, CheckIfReparseJobFinishedStartsJob) +TEST_F(SupportiveTranslationUnitInitializerSlowTest, CheckIfReparseJobFinishedStartsJob) { parse(); initializer.setState(ClangBackEnd::SupportiveTranslationUnitInitializer::State::WaitingForReparseJob); @@ -215,7 +217,7 @@ TEST_F(SupportiveTranslationUnitInitializer, CheckIfReparseJobFinishedStartsJob) ASSERT_THAT(initializer.state(), Eq(ClangBackEnd::SupportiveTranslationUnitInitializer::State::Initialized)); } -TEST_F(SupportiveTranslationUnitInitializer, FullRun) +TEST_F(SupportiveTranslationUnitInitializerSlowTest, FullRun) { parse(); initializer.startInitializing(); diff --git a/tests/unit/unittest/clangtranslationunit-test.cpp b/tests/unit/unittest/clangtranslationunit-test.cpp index 10fee318ab..3e10138c8b 100644 --- a/tests/unit/unittest/clangtranslationunit-test.cpp +++ b/tests/unit/unittest/clangtranslationunit-test.cpp @@ -73,7 +73,9 @@ protected: QVector<DiagnosticContainer> extractedMainFileDiagnostics; }; -TEST_F(TranslationUnit, HasExpectedMainFileDiagnostics) +using TranslationUnitSlowTest = TranslationUnit; + +TEST_F(TranslationUnitSlowTest, HasExpectedMainFileDiagnostics) { translationUnit.extractDiagnostics(extractedFirstHeaderErrorDiagnostic, extractedMainFileDiagnostics); @@ -81,7 +83,7 @@ TEST_F(TranslationUnit, HasExpectedMainFileDiagnostics) ASSERT_THAT(extractedMainFileDiagnostics, ContainerEq(diagnosticsFromMainFile())); } -TEST_F(TranslationUnit, HasExpectedMainFileDiagnosticsAfterReparse) +TEST_F(TranslationUnitSlowTest, HasExpectedMainFileDiagnosticsAfterReparse) { reparse(); @@ -91,7 +93,7 @@ TEST_F(TranslationUnit, HasExpectedMainFileDiagnosticsAfterReparse) ASSERT_THAT(extractedMainFileDiagnostics, ContainerEq(diagnosticsFromMainFile())); } -TEST_F(TranslationUnit, HasErrorDiagnosticsInHeaders) +TEST_F(TranslationUnitSlowTest, HasErrorDiagnosticsInHeaders) { translationUnit.extractDiagnostics(extractedFirstHeaderErrorDiagnostic, extractedMainFileDiagnostics); @@ -100,7 +102,7 @@ TEST_F(TranslationUnit, HasErrorDiagnosticsInHeaders) Eq(errorDiagnosticsFromHeaders().first())); } -TEST_F(TranslationUnit, HasErrorDiagnosticsInHeadersAfterReparse) +TEST_F(TranslationUnitSlowTest, HasErrorDiagnosticsInHeadersAfterReparse) { reparse(); diff --git a/tests/unit/unittest/clangupdatedocumentannotationsjob-test.cpp b/tests/unit/unittest/clangupdatedocumentannotationsjob-test.cpp index 291f2e298c..1378cce878 100644 --- a/tests/unit/unittest/clangupdatedocumentannotationsjob-test.cpp +++ b/tests/unit/unittest/clangupdatedocumentannotationsjob-test.cpp @@ -43,6 +43,8 @@ protected: ClangBackEnd::UpdateDocumentAnnotationsJob job; }; +using UpdateDocumentAnnotationsJobSlowTest = UpdateDocumentAnnotationsJob; + TEST_F(UpdateDocumentAnnotationsJob, PrepareAsyncRun) { job.setContext(jobContext); @@ -50,7 +52,7 @@ TEST_F(UpdateDocumentAnnotationsJob, PrepareAsyncRun) ASSERT_TRUE(job.prepareAsyncRun()); } -TEST_F(UpdateDocumentAnnotationsJob, RunAsync) +TEST_F(UpdateDocumentAnnotationsJobSlowTest, RunAsync) { job.setContext(jobContext); job.prepareAsyncRun(); @@ -60,7 +62,7 @@ TEST_F(UpdateDocumentAnnotationsJob, RunAsync) ASSERT_TRUE(waitUntilJobFinished(job)); } -TEST_F(UpdateDocumentAnnotationsJob, SendAnnotations) +TEST_F(UpdateDocumentAnnotationsJobSlowTest, SendAnnotations) { job.setContext(jobContextWithMockClient); job.prepareAsyncRun(); @@ -71,7 +73,7 @@ TEST_F(UpdateDocumentAnnotationsJob, SendAnnotations) ASSERT_TRUE(waitUntilJobFinished(job)); } -TEST_F(UpdateDocumentAnnotationsJob, DontSendAnnotationsIfDocumentWasClosed) +TEST_F(UpdateDocumentAnnotationsJobSlowTest, DontSendAnnotationsIfDocumentWasClosed) { job.setContext(jobContextWithMockClient); job.prepareAsyncRun(); @@ -83,7 +85,7 @@ TEST_F(UpdateDocumentAnnotationsJob, DontSendAnnotationsIfDocumentWasClosed) ASSERT_TRUE(waitUntilJobFinished(job)); } -TEST_F(UpdateDocumentAnnotationsJob, DontSendAnnotationsIfDocumentRevisionChanged) +TEST_F(UpdateDocumentAnnotationsJobSlowTest, DontSendAnnotationsIfDocumentRevisionChanged) { job.setContext(jobContextWithMockClient); job.prepareAsyncRun(); @@ -95,7 +97,7 @@ TEST_F(UpdateDocumentAnnotationsJob, DontSendAnnotationsIfDocumentRevisionChange ASSERT_TRUE(waitUntilJobFinished(job)); } -TEST_F(UpdateDocumentAnnotationsJob, UpdatesTranslationUnit) +TEST_F(UpdateDocumentAnnotationsJobSlowTest, UpdatesTranslationUnit) { const TimePoint timePointBefore = document.lastProjectPartChangeTimePoint(); const QSet<Utf8String> dependendOnFilesBefore = document.dependedFilePaths(); diff --git a/tests/unit/unittest/clientserveroutsideprocess.cpp b/tests/unit/unittest/clientserveroutsideprocess-test.cpp index 9492280281..ded6b24a6d 100644 --- a/tests/unit/unittest/clientserveroutsideprocess.cpp +++ b/tests/unit/unittest/clientserveroutsideprocess-test.cpp @@ -51,6 +51,7 @@ #include <QString> #include <QVariant> +#include <memory> #include <vector> using namespace ClangBackEnd; @@ -58,6 +59,13 @@ using namespace ClangBackEnd; using ::testing::Eq; using ::testing::SizeIs; +struct Data { + Data() : client(&mockClangCodeModelClient) {} + + MockClangCodeModelClient mockClangCodeModelClient; + ClangBackEnd::ClangCodeModelConnectionClient client; +}; + class ClientServerOutsideProcess : public ::testing::Test { protected: @@ -67,14 +75,16 @@ protected: static void SetUpTestCase(); static void TearDownTestCase(); - static MockClangCodeModelClient mockClangCodeModelClient; - static ClangBackEnd::ClangCodeModelConnectionClient client; + static std::unique_ptr<Data> d; + MockClangCodeModelClient &mockClangCodeModelClient = d->mockClangCodeModelClient; + ClangBackEnd::ClangCodeModelConnectionClient &client = d->client; }; -MockClangCodeModelClient ClientServerOutsideProcess::mockClangCodeModelClient; -ClangBackEnd::ClangCodeModelConnectionClient ClientServerOutsideProcess::client(&ClientServerOutsideProcess::mockClangCodeModelClient); +std::unique_ptr<Data> ClientServerOutsideProcess::d; -TEST_F(ClientServerOutsideProcess, RestartProcessAsynchronously) +using ClientServerOutsideProcessSlowTest = ClientServerOutsideProcess; + +TEST_F(ClientServerOutsideProcessSlowTest, RestartProcessAsynchronously) { QSignalSpy clientSpy(&client, &ConnectionClient::connectedToLocalSocket); @@ -85,7 +95,7 @@ TEST_F(ClientServerOutsideProcess, RestartProcessAsynchronously) ASSERT_TRUE(client.isConnected()); } -TEST_F(ClientServerOutsideProcess, RestartProcessAfterAliveTimeout) +TEST_F(ClientServerOutsideProcessSlowTest, RestartProcessAfterAliveTimeout) { QSignalSpy clientSpy(&client, &ConnectionClient::connectedToLocalSocket); @@ -95,7 +105,7 @@ TEST_F(ClientServerOutsideProcess, RestartProcessAfterAliveTimeout) ASSERT_THAT(clientSpy, SizeIs(1)); } -TEST_F(ClientServerOutsideProcess, RestartProcessAfterTermination) +TEST_F(ClientServerOutsideProcessSlowTest, RestartProcessAfterTermination) { QSignalSpy clientSpy(&client, &ConnectionClient::connectedToLocalSocket); @@ -173,10 +183,12 @@ TEST_F(ClientServerOutsideProcess, SendUnregisterProjectPartsForEditorMessage) void ClientServerOutsideProcess::SetUpTestCase() { - QSignalSpy clientSpy(&client, &ConnectionClient::connectedToLocalSocket); - client.setProcessPath(Utils::HostOsInfo::withExecutableSuffix(QStringLiteral(ECHOSERVER))); + d.reset(new Data); + + QSignalSpy clientSpy(&d->client, &ConnectionClient::connectedToLocalSocket); + d->client.setProcessPath(Utils::HostOsInfo::withExecutableSuffix(QStringLiteral(ECHOSERVER))); - client.startProcessAndConnectToServerAsynchronously(); + d->client.startProcessAndConnectToServerAsynchronously(); ASSERT_TRUE(clientSpy.wait(100000)); ASSERT_THAT(clientSpy, SizeIs(1)); @@ -184,7 +196,8 @@ void ClientServerOutsideProcess::SetUpTestCase() void ClientServerOutsideProcess::TearDownTestCase() { - client.finishProcess(); + d->client.finishProcess(); + d.reset(); } void ClientServerOutsideProcess::SetUp() { diff --git a/tests/unit/unittest/codecompletion-test.cpp b/tests/unit/unittest/codecompleter-test.cpp index e29c2682ab..58948c5f2c 100644 --- a/tests/unit/unittest/codecompletion-test.cpp +++ b/tests/unit/unittest/codecompleter-test.cpp @@ -178,6 +178,8 @@ protected: }; }; +using CodeCompleterSlowTest = CodeCompleter; + Utf8String CodeCompleter::readFileContent(const QString &fileName) { QFile readFileContentFile(QStringLiteral(TESTDATA_DIR) + fileName); @@ -217,7 +219,7 @@ void CodeCompleter::SetUp() document.parse(); } -TEST_F(CodeCompleter, FunctionInUnsavedFile) +TEST_F(CodeCompleterSlowTest, FunctionInUnsavedFile) { unsavedFiles.createOrUpdate({unsavedMainFileContainer}); documents.update({unsavedMainFileContainer}); @@ -236,7 +238,7 @@ TEST_F(CodeCompleter, FunctionInUnsavedFile) CodeCompletion::FunctionCompletionKind))))); } -TEST_F(CodeCompleter, VariableInUnsavedFile) +TEST_F(CodeCompleterSlowTest, VariableInUnsavedFile) { unsavedFiles.createOrUpdate({unsavedMainFileContainer}); documents.update({unsavedMainFileContainer}); @@ -247,7 +249,7 @@ TEST_F(CodeCompleter, VariableInUnsavedFile) CodeCompletion::VariableCompletionKind))); } -TEST_F(CodeCompleter, GlobalVariableInUnsavedFile) +TEST_F(CodeCompleterSlowTest, GlobalVariableInUnsavedFile) { unsavedFiles.createOrUpdate({unsavedMainFileContainer}); documents.update({unsavedMainFileContainer}); @@ -258,7 +260,7 @@ TEST_F(CodeCompleter, GlobalVariableInUnsavedFile) CodeCompletion::VariableCompletionKind))); } -TEST_F(CodeCompleter, Macro) +TEST_F(CodeCompleterSlowTest, Macro) { unsavedFiles.createOrUpdate({unsavedMainFileContainer}); documents.update({unsavedMainFileContainer}); @@ -269,21 +271,21 @@ TEST_F(CodeCompleter, Macro) CodeCompletion::PreProcessorCompletionKind))); } -TEST_F(CodeCompleter, Keyword) +TEST_F(CodeCompleterSlowTest, Keyword) { ASSERT_THAT(completer->complete(27, 1), Contains(IsCodeCompletion(Utf8StringLiteral("switch"), CodeCompletion::KeywordCompletionKind))); } -TEST_F(CodeCompleter, FunctionInIncludedHeader) +TEST_F(CodeCompleterSlowTest, FunctionInIncludedHeader) { ASSERT_THAT(completer->complete(27, 1), Contains(IsCodeCompletion(Utf8StringLiteral("FunctionInIncludedHeader"), CodeCompletion::FunctionCompletionKind))); } -TEST_F(CodeCompleter, FunctionInUnsavedIncludedHeader) +TEST_F(CodeCompleterSlowTest, FunctionInUnsavedIncludedHeader) { unsavedFiles.createOrUpdate({unsavedTargetHeaderFileContainer}); documents.create({unsavedTargetHeaderFileContainer}); @@ -294,7 +296,7 @@ TEST_F(CodeCompleter, FunctionInUnsavedIncludedHeader) CodeCompletion::FunctionCompletionKind))); } -TEST_F(CodeCompleter, DISABLED_FunctionInChangedIncludedHeader) +TEST_F(CodeCompleterSlowTest, DISABLED_FunctionInChangedIncludedHeader) { copyChangedTargetHeaderToTemporaryIncludeDirecory(); @@ -303,7 +305,7 @@ TEST_F(CodeCompleter, DISABLED_FunctionInChangedIncludedHeader) CodeCompletion::FunctionCompletionKind))); } -TEST_F(CodeCompleter, DISABLED_FunctionInChangedIncludedHeaderWithUnsavedContentInMainFile) // it's not that bad because we reparse anyway +TEST_F(CodeCompleterSlowTest, DISABLED_FunctionInChangedIncludedHeaderWithUnsavedContentInMainFile) // it's not that bad because we reparse anyway { unsavedFiles.createOrUpdate({unsavedMainFileContainer}); documents.update({unsavedMainFileContainer}); @@ -316,7 +318,7 @@ TEST_F(CodeCompleter, DISABLED_FunctionInChangedIncludedHeaderWithUnsavedContent CodeCompletion::FunctionCompletionKind))); } -TEST_F(CodeCompleter, ArrowCompletion) +TEST_F(CodeCompleterSlowTest, ArrowCompletion) { auto myCompleter = setupCompleter(arrowFileContainer); @@ -329,7 +331,7 @@ TEST_F(CodeCompleter, ArrowCompletion) ClangBackEnd::CompletionCorrection::NoCorrection); } -TEST_F(CodeCompleter, DotToArrowCompletionForPointer) +TEST_F(CodeCompleterSlowTest, DotToArrowCompletionForPointer) { auto myCompleter = setupCompleter(dotArrowCorrectionForPointerFileContainer); @@ -342,7 +344,7 @@ TEST_F(CodeCompleter, DotToArrowCompletionForPointer) ClangBackEnd::CompletionCorrection::DotToArrowCorrection); } -TEST_F(CodeCompleter, DotToArrowCompletionForPointerInOutdatedDocument) +TEST_F(CodeCompleterSlowTest, DotToArrowCompletionForPointerInOutdatedDocument) { auto fileContainerBeforeTyping = dotArrowCorrectionForPointerFileContainerBeforeTyping; documents.create({fileContainerBeforeTyping}); @@ -363,7 +365,7 @@ TEST_F(CodeCompleter, DotToArrowCompletionForPointerInOutdatedDocument) ClangBackEnd::CompletionCorrection::DotToArrowCorrection); } -TEST_F(CodeCompleter, NoDotToArrowCompletionForObject) +TEST_F(CodeCompleterSlowTest, NoDotToArrowCompletionForObject) { auto myCompleter = setupCompleter(noDotArrowCorrectionForObjectFileContainer); @@ -375,7 +377,7 @@ TEST_F(CodeCompleter, NoDotToArrowCompletionForObject) ASSERT_THAT(myCompleter.neededCorrection(), ClangBackEnd::CompletionCorrection::NoCorrection); } -TEST_F(CodeCompleter, NoDotToArrowCompletionForFloat) +TEST_F(CodeCompleterSlowTest, NoDotToArrowCompletionForFloat) { auto myCompleter = setupCompleter(noDotArrowCorrectionForFloatFileContainer); @@ -385,7 +387,7 @@ TEST_F(CodeCompleter, NoDotToArrowCompletionForFloat) ASSERT_THAT(myCompleter.neededCorrection(), ClangBackEnd::CompletionCorrection::NoCorrection); } -TEST_F(CodeCompleter, NoDotArrowCorrectionForObjectWithArrowOperator) +TEST_F(CodeCompleterSlowTest, NoDotArrowCorrectionForObjectWithArrowOperator) { auto myCompleter = setupCompleter(noDotArrowCorrectionForObjectWithArrowOperatortFileContainer); @@ -397,7 +399,7 @@ TEST_F(CodeCompleter, NoDotArrowCorrectionForObjectWithArrowOperator) ASSERT_THAT(myCompleter.neededCorrection(), ClangBackEnd::CompletionCorrection::NoCorrection); } -TEST_F(CodeCompleter, NoDotArrowCorrectionForDotDot) +TEST_F(CodeCompleterSlowTest, NoDotArrowCorrectionForDotDot) { auto myCompleter = setupCompleter(noDotArrowCorrectionForDotDotFileContainer); @@ -407,7 +409,7 @@ TEST_F(CodeCompleter, NoDotArrowCorrectionForDotDot) ASSERT_THAT(myCompleter.neededCorrection(), ClangBackEnd::CompletionCorrection::NoCorrection); } -TEST_F(CodeCompleter, NoDotArrowCorrectionForArrowDot) +TEST_F(CodeCompleterSlowTest, NoDotArrowCorrectionForArrowDot) { auto myCompleter = setupCompleter(noDotArrowCorrectionForArrowDotFileContainer); @@ -417,7 +419,7 @@ TEST_F(CodeCompleter, NoDotArrowCorrectionForArrowDot) ASSERT_THAT(myCompleter.neededCorrection(), ClangBackEnd::CompletionCorrection::NoCorrection); } -TEST_F(CodeCompleter, NoDotArrowCorrectionForOnlyDot) +TEST_F(CodeCompleterSlowTest, NoDotArrowCorrectionForOnlyDot) { auto myCompleter = setupCompleter(noDotArrowCorrectionForOnlyDotFileContainer); @@ -429,7 +431,7 @@ TEST_F(CodeCompleter, NoDotArrowCorrectionForOnlyDot) ASSERT_THAT(myCompleter.neededCorrection(), ClangBackEnd::CompletionCorrection::NoCorrection); } -TEST_F(CodeCompleter, NoDotArrowCorrectionForColonColon) +TEST_F(CodeCompleterSlowTest, NoDotArrowCorrectionForColonColon) { auto myCompleter = setupCompleter(noDotArrowCorrectionForColonColonFileContainer); const ClangBackEnd::CodeCompletions completions = myCompleter.complete(1, 7); diff --git a/tests/unit/unittest/codecompletionsextractor-test.cpp b/tests/unit/unittest/codecompletionsextractor-test.cpp index 52ec3777dc..86406377a1 100644 --- a/tests/unit/unittest/codecompletionsextractor-test.cpp +++ b/tests/unit/unittest/codecompletionsextractor-test.cpp @@ -161,7 +161,9 @@ protected: Document briefCommentDocument{Utf8StringLiteral(TESTDATA_DIR"/complete_extractor_brief_comment.cpp"), project, Utf8StringVector(), documents}; }; -TEST_F(CodeCompletionsExtractor, Function) +using CodeCompletionsExtractorSlowTest = CodeCompletionsExtractor; + +TEST_F(CodeCompletionsExtractorSlowTest, Function) { ClangCodeCompleteResults completeResults(getResults(functionDocument, 20)); @@ -172,7 +174,7 @@ TEST_F(CodeCompletionsExtractor, Function) CodeCompletion::Available)); } -TEST_F(CodeCompletionsExtractor, TemplateFunction) +TEST_F(CodeCompletionsExtractorSlowTest, TemplateFunction) { ClangCodeCompleteResults completeResults(getResults(functionDocument, 20)); @@ -183,7 +185,7 @@ TEST_F(CodeCompletionsExtractor, TemplateFunction) CodeCompletion::Available)); } -TEST_F(CodeCompletionsExtractor, Variable) +TEST_F(CodeCompletionsExtractorSlowTest, Variable) { ClangCodeCompleteResults completeResults(getResults(variableDocument, 4)); @@ -194,8 +196,7 @@ TEST_F(CodeCompletionsExtractor, Variable) CodeCompletion::Available)); } - -TEST_F(CodeCompletionsExtractor, NonTypeTemplateParameter) +TEST_F(CodeCompletionsExtractorSlowTest, DISABLED_ON_WINDOWS(NonTypeTemplateParameter)) { ClangCodeCompleteResults completeResults(getResults(variableDocument, 25, 19)); @@ -207,7 +208,7 @@ TEST_F(CodeCompletionsExtractor, NonTypeTemplateParameter) } -TEST_F(CodeCompletionsExtractor, VariableReference) +TEST_F(CodeCompletionsExtractorSlowTest, VariableReference) { ClangCodeCompleteResults completeResults(getResults(variableDocument, 12)); @@ -218,7 +219,7 @@ TEST_F(CodeCompletionsExtractor, VariableReference) CodeCompletion::Available)); } -TEST_F(CodeCompletionsExtractor, Parameter) +TEST_F(CodeCompletionsExtractorSlowTest, Parameter) { ClangCodeCompleteResults completeResults(getResults(variableDocument, 4)); @@ -229,7 +230,7 @@ TEST_F(CodeCompletionsExtractor, Parameter) CodeCompletion::Available)); } -TEST_F(CodeCompletionsExtractor, Field) +TEST_F(CodeCompletionsExtractorSlowTest, Field) { ClangCodeCompleteResults completeResults(getResults(variableDocument, 20)); @@ -240,7 +241,7 @@ TEST_F(CodeCompletionsExtractor, Field) CodeCompletion::Available)); } -TEST_F(CodeCompletionsExtractor, Class) +TEST_F(CodeCompletionsExtractorSlowTest, DISABLED_ON_WINDOWS(Class)) { ClangCodeCompleteResults completeResults(getResults(classDocument, 20)); @@ -251,7 +252,7 @@ TEST_F(CodeCompletionsExtractor, Class) CodeCompletion::Available)); } -TEST_F(CodeCompletionsExtractor, Struct) +TEST_F(CodeCompletionsExtractorSlowTest, DISABLED_ON_WINDOWS(Struct)) { ClangCodeCompleteResults completeResults(getResults(classDocument, 20)); @@ -262,7 +263,7 @@ TEST_F(CodeCompletionsExtractor, Struct) CodeCompletion::Available)); } -TEST_F(CodeCompletionsExtractor, Union) +TEST_F(CodeCompletionsExtractorSlowTest, DISABLED_ON_WINDOWS(Union)) { ClangCodeCompleteResults completeResults(getResults(classDocument, 20)); @@ -273,7 +274,7 @@ TEST_F(CodeCompletionsExtractor, Union) CodeCompletion::Available)); } -TEST_F(CodeCompletionsExtractor, Typedef) +TEST_F(CodeCompletionsExtractorSlowTest, DISABLED_ON_WINDOWS(Typedef)) { ClangCodeCompleteResults completeResults(getResults(classDocument, 20)); @@ -284,7 +285,7 @@ TEST_F(CodeCompletionsExtractor, Typedef) CodeCompletion::Available)); } -TEST_F(CodeCompletionsExtractor, UsingAsTypeAlias) +TEST_F(CodeCompletionsExtractorSlowTest, DISABLED_ON_WINDOWS(UsingAsTypeAlias)) { ClangCodeCompleteResults completeResults(getResults(classDocument, 20)); @@ -295,7 +296,7 @@ TEST_F(CodeCompletionsExtractor, UsingAsTypeAlias) CodeCompletion::Available)); } -TEST_F(CodeCompletionsExtractor, TemplateTypeParameter) +TEST_F(CodeCompletionsExtractorSlowTest, DISABLED_ON_WINDOWS(TemplateTypeParameter)) { ClangCodeCompleteResults completeResults(getResults(classDocument, 20)); @@ -306,7 +307,7 @@ TEST_F(CodeCompletionsExtractor, TemplateTypeParameter) CodeCompletion::Available)); } -TEST_F(CodeCompletionsExtractor, TemplateClass) +TEST_F(CodeCompletionsExtractorSlowTest, DISABLED_ON_WINDOWS(TemplateClass)) { ClangCodeCompleteResults completeResults(getResults(classDocument, 20)); @@ -317,7 +318,7 @@ TEST_F(CodeCompletionsExtractor, TemplateClass) CodeCompletion::Available)); } -TEST_F(CodeCompletionsExtractor, TemplateTemplateParameter) +TEST_F(CodeCompletionsExtractorSlowTest, DISABLED_ON_WINDOWS(TemplateTemplateParameter)) { ClangCodeCompleteResults completeResults(getResults(classDocument, 20)); @@ -328,7 +329,7 @@ TEST_F(CodeCompletionsExtractor, TemplateTemplateParameter) CodeCompletion::Available)); } -TEST_F(CodeCompletionsExtractor, ClassTemplatePartialSpecialization) +TEST_F(CodeCompletionsExtractorSlowTest, DISABLED_ON_WINDOWS(ClassTemplatePartialSpecialization)) { ClangCodeCompleteResults completeResults(getResults(classDocument, 20)); @@ -339,7 +340,7 @@ TEST_F(CodeCompletionsExtractor, ClassTemplatePartialSpecialization) CodeCompletion::Available)); } -TEST_F(CodeCompletionsExtractor, Namespace) +TEST_F(CodeCompletionsExtractorSlowTest, Namespace) { ClangCodeCompleteResults completeResults(getResults(namespaceDocument, 20)); @@ -350,7 +351,7 @@ TEST_F(CodeCompletionsExtractor, Namespace) CodeCompletion::Available)); } -TEST_F(CodeCompletionsExtractor, NamespaceAlias) +TEST_F(CodeCompletionsExtractorSlowTest, NamespaceAlias) { ClangCodeCompleteResults completeResults(getResults(namespaceDocument, 20)); @@ -361,7 +362,7 @@ TEST_F(CodeCompletionsExtractor, NamespaceAlias) CodeCompletion::Available)); } -TEST_F(CodeCompletionsExtractor, Enumeration) +TEST_F(CodeCompletionsExtractorSlowTest, Enumeration) { ClangCodeCompleteResults completeResults(getResults(enumerationDocument, 20)); @@ -372,7 +373,7 @@ TEST_F(CodeCompletionsExtractor, Enumeration) CodeCompletion::Available)); } -TEST_F(CodeCompletionsExtractor, Enumerator) +TEST_F(CodeCompletionsExtractorSlowTest, Enumerator) { ClangCodeCompleteResults completeResults(getResults(enumerationDocument, 20)); @@ -383,7 +384,7 @@ TEST_F(CodeCompletionsExtractor, Enumerator) CodeCompletion::Available)); } -TEST_F(CodeCompletionsExtractor, DISABLED_Constructor) +TEST_F(CodeCompletionsExtractorSlowTest, DISABLED_Constructor) { ClangCodeCompleteResults completeResults(getResults(constructorDocument, 20)); @@ -394,7 +395,7 @@ TEST_F(CodeCompletionsExtractor, DISABLED_Constructor) CodeCompletion::Available)); } -TEST_F(CodeCompletionsExtractor, Destructor) +TEST_F(CodeCompletionsExtractorSlowTest, Destructor) { ClangCodeCompleteResults completeResults(getResults(constructorDocument, 20)); @@ -405,7 +406,7 @@ TEST_F(CodeCompletionsExtractor, Destructor) CodeCompletion::Available)); } -TEST_F(CodeCompletionsExtractor, Method) +TEST_F(CodeCompletionsExtractorSlowTest, Method) { ClangCodeCompleteResults completeResults(getResults(functionDocument, 20)); @@ -417,7 +418,7 @@ TEST_F(CodeCompletionsExtractor, Method) ASSERT_FALSE(extractor.currentCodeCompletion().hasParameters()); } -TEST_F(CodeCompletionsExtractor, MethodWithParameters) +TEST_F(CodeCompletionsExtractorSlowTest, MethodWithParameters) { ClangCodeCompleteResults completeResults(getResults(functionDocument, 20)); @@ -429,7 +430,7 @@ TEST_F(CodeCompletionsExtractor, MethodWithParameters) ASSERT_TRUE(extractor.currentCodeCompletion().hasParameters()); } -TEST_F(CodeCompletionsExtractor, Slot) +TEST_F(CodeCompletionsExtractorSlowTest, Slot) { ClangCodeCompleteResults completeResults(getResults(functionDocument, 20)); @@ -440,7 +441,7 @@ TEST_F(CodeCompletionsExtractor, Slot) CodeCompletion::Available)); } -TEST_F(CodeCompletionsExtractor, Signal) +TEST_F(CodeCompletionsExtractorSlowTest, Signal) { ClangCodeCompleteResults completeResults(getResults(functionDocument, 20)); @@ -451,7 +452,7 @@ TEST_F(CodeCompletionsExtractor, Signal) CodeCompletion::Available)); } -TEST_F(CodeCompletionsExtractor, MacroDefinition) +TEST_F(CodeCompletionsExtractorSlowTest, MacroDefinition) { ClangCodeCompleteResults completeResults(getResults(variableDocument, 35)); @@ -462,7 +463,7 @@ TEST_F(CodeCompletionsExtractor, MacroDefinition) CodeCompletion::Available)); } -TEST_F(CodeCompletionsExtractor, FunctionMacro) +TEST_F(CodeCompletionsExtractorSlowTest, FunctionMacro) { ClangCodeCompleteResults completeResults(getResults(functionDocument, 20)); @@ -473,7 +474,7 @@ TEST_F(CodeCompletionsExtractor, FunctionMacro) CodeCompletion::Available)); } -TEST_F(CodeCompletionsExtractor, IntKeyword) +TEST_F(CodeCompletionsExtractorSlowTest, IntKeyword) { ClangCodeCompleteResults completeResults(getResults(functionDocument, 20)); @@ -484,7 +485,7 @@ TEST_F(CodeCompletionsExtractor, IntKeyword) CodeCompletion::Available)); } -TEST_F(CodeCompletionsExtractor, SwitchKeyword) +TEST_F(CodeCompletionsExtractorSlowTest, SwitchKeyword) { ClangCodeCompleteResults completeResults(getResults(functionDocument, 20)); @@ -495,7 +496,7 @@ TEST_F(CodeCompletionsExtractor, SwitchKeyword) CodeCompletion::Available)); } -TEST_F(CodeCompletionsExtractor, ClassKeyword) +TEST_F(CodeCompletionsExtractorSlowTest, ClassKeyword) { ClangCodeCompleteResults completeResults(getResults(functionDocument, 20)); @@ -506,7 +507,7 @@ TEST_F(CodeCompletionsExtractor, ClassKeyword) CodeCompletion::Available)); } -TEST_F(CodeCompletionsExtractor, DeprecatedFunction) +TEST_F(CodeCompletionsExtractorSlowTest, DeprecatedFunction) { ClangCodeCompleteResults completeResults(getResults(functionDocument, 20)); @@ -517,7 +518,7 @@ TEST_F(CodeCompletionsExtractor, DeprecatedFunction) CodeCompletion::Deprecated)); } -TEST_F(CodeCompletionsExtractor, NotAccessibleFunction) +TEST_F(CodeCompletionsExtractorSlowTest, NotAccessibleFunction) { ClangCodeCompleteResults completeResults(getResults(functionDocument, 20)); @@ -528,7 +529,7 @@ TEST_F(CodeCompletionsExtractor, NotAccessibleFunction) CodeCompletion::NotAccessible)); } -TEST_F(CodeCompletionsExtractor, NotAvailableFunction) +TEST_F(CodeCompletionsExtractorSlowTest, NotAvailableFunction) { ClangCodeCompleteResults completeResults(getResults(functionDocument, 20)); @@ -539,7 +540,7 @@ TEST_F(CodeCompletionsExtractor, NotAvailableFunction) CodeCompletion::NotAvailable)); } -TEST_F(CodeCompletionsExtractor, UnsavedFile) +TEST_F(CodeCompletionsExtractorSlowTest, UnsavedFile) { Document document(Utf8String::fromUtf8(TESTDATA_DIR"/complete_extractor_function.cpp"), project, Utf8StringVector(), documents); unsavedFiles.createOrUpdate({unsavedDataFileContainer(TESTDATA_DIR"/complete_extractor_function.cpp", @@ -553,7 +554,7 @@ TEST_F(CodeCompletionsExtractor, UnsavedFile) CodeCompletion::Available)); } -TEST_F(CodeCompletionsExtractor, ChangeUnsavedFile) +TEST_F(CodeCompletionsExtractorSlowTest, ChangeUnsavedFile) { Document document(Utf8String::fromUtf8(TESTDATA_DIR"/complete_extractor_function.cpp"), project, Utf8StringVector(), documents); unsavedFiles.createOrUpdate({unsavedDataFileContainer(TESTDATA_DIR"/complete_extractor_function.cpp", @@ -570,7 +571,7 @@ TEST_F(CodeCompletionsExtractor, ChangeUnsavedFile) CodeCompletion::Available)); } -TEST_F(CodeCompletionsExtractor, ArgumentDefinition) +TEST_F(CodeCompletionsExtractorSlowTest, ArgumentDefinition) { project.setArguments({Utf8StringLiteral("-DArgumentDefinition"), Utf8StringLiteral("-std=gnu++14")}); ClangCodeCompleteResults completeResults(getResults(variableDocument, 35)); @@ -582,7 +583,7 @@ TEST_F(CodeCompletionsExtractor, ArgumentDefinition) CodeCompletion::Available)); } -TEST_F(CodeCompletionsExtractor, NoArgumentDefinition) +TEST_F(CodeCompletionsExtractorSlowTest, NoArgumentDefinition) { project.setArguments({Utf8StringLiteral("-std=gnu++14")}); ClangCodeCompleteResults completeResults(getResults(variableDocument, 35)); @@ -594,7 +595,7 @@ TEST_F(CodeCompletionsExtractor, NoArgumentDefinition) CodeCompletion::Available))); } -TEST_F(CodeCompletionsExtractor, CompletionChunksFunction) +TEST_F(CodeCompletionsExtractorSlowTest, CompletionChunksFunction) { ClangCodeCompleteResults completeResults(getResults(functionDocument, 20)); @@ -607,7 +608,7 @@ TEST_F(CodeCompletionsExtractor, CompletionChunksFunction) {CodeCompletionChunk::RightParen, Utf8StringLiteral(")")}}))); } -TEST_F(CodeCompletionsExtractor, CompletionChunksFunctionWithOptionalChunks) +TEST_F(CodeCompletionsExtractorSlowTest, CompletionChunksFunctionWithOptionalChunks) { ClangCodeCompleteResults completeResults(getResults(functionDocument, 20)); @@ -625,7 +626,7 @@ TEST_F(CodeCompletionsExtractor, CompletionChunksFunctionWithOptionalChunks) {CodeCompletionChunk::RightParen, Utf8StringLiteral(")")}}))); } -TEST_F(CodeCompletionsExtractor, CompletionChunksField) +TEST_F(CodeCompletionsExtractorSlowTest, CompletionChunksField) { ClangCodeCompleteResults completeResults(getResults(variableDocument, 20)); @@ -636,7 +637,7 @@ TEST_F(CodeCompletionsExtractor, CompletionChunksField) {CodeCompletionChunk::TypedText, Utf8StringLiteral("Field")}}))); } -TEST_F(CodeCompletionsExtractor, CompletionChunksEnumerator) +TEST_F(CodeCompletionsExtractorSlowTest, CompletionChunksEnumerator) { ClangCodeCompleteResults completeResults(getResults(enumerationDocument, 20)); @@ -647,7 +648,7 @@ TEST_F(CodeCompletionsExtractor, CompletionChunksEnumerator) {CodeCompletionChunk::TypedText, Utf8StringLiteral("Enumerator")}}))); } -TEST_F(CodeCompletionsExtractor, CompletionChunksEnumeration) +TEST_F(CodeCompletionsExtractorSlowTest, CompletionChunksEnumeration) { ClangCodeCompleteResults completeResults(getResults(enumerationDocument, 20)); @@ -657,7 +658,7 @@ TEST_F(CodeCompletionsExtractor, CompletionChunksEnumeration) CodeCompletionChunks({{CodeCompletionChunk::TypedText, Utf8StringLiteral("Enumeration")}}))); } -TEST_F(CodeCompletionsExtractor, CompletionChunksClass) +TEST_F(CodeCompletionsExtractorSlowTest, DISABLED_ON_WINDOWS(CompletionChunksClass)) { ClangCodeCompleteResults completeResults(getResults(classDocument, 20)); @@ -667,7 +668,7 @@ TEST_F(CodeCompletionsExtractor, CompletionChunksClass) CodeCompletionChunks({{CodeCompletionChunk::TypedText, Utf8StringLiteral("Class")}}))); } -TEST_F(CodeCompletionsExtractor, BriefComment) +TEST_F(CodeCompletionsExtractorSlowTest, BriefComment) { ClangCodeCompleteResults completeResults(getResults(briefCommentDocument, 10, 1, /*needsReparse=*/ true)); diff --git a/tests/unit/unittest/compare-operators.h b/tests/unit/unittest/compare-operators.h new file mode 100644 index 0000000000..54f397165b --- /dev/null +++ b/tests/unit/unittest/compare-operators.h @@ -0,0 +1,48 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#pragma once + +#include <coreplugin/find/searchresultitem.h> + +namespace Core { +namespace Search { + +inline +bool operator==(const TextPosition first, class TextPosition second) +{ + return first.line == second.line + && first.column == second.column + && first.offset == second.offset; +} + +inline +bool operator==(const TextRange first, class TextRange second) +{ + return first.begin == second.begin + && first.end == second.end; +} +} +} diff --git a/tests/unit/unittest/conditionally-disabled-tests.h b/tests/unit/unittest/conditionally-disabled-tests.h new file mode 100644 index 0000000000..90e309f45b --- /dev/null +++ b/tests/unit/unittest/conditionally-disabled-tests.h @@ -0,0 +1,32 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#include <QtGlobal> + +#ifdef Q_OS_WIN +# define DISABLED_ON_WINDOWS(x) DISABLED_##x +#else +# define DISABLED_ON_WINDOWS(x) x +#endif diff --git a/tests/unit/unittest/cplusplus.pri b/tests/unit/unittest/cplusplus.pri index 51909b717f..068cde9f1a 100644 --- a/tests/unit/unittest/cplusplus.pri +++ b/tests/unit/unittest/cplusplus.pri @@ -1,3 +1,4 @@ INCLUDEPATH += $$PWD + include($$PWD/../../../src/libs/cplusplus/cplusplus-lib.pri) diff --git a/tests/unit/unittest/cppprojectfilecategorizer-test.cpp b/tests/unit/unittest/cppprojectfilecategorizer-test.cpp new file mode 100644 index 0000000000..5abcbc59a8 --- /dev/null +++ b/tests/unit/unittest/cppprojectfilecategorizer-test.cpp @@ -0,0 +1,200 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#include "googletest.h" +#include "gtest-qt-printing.h" +#include "mimedatabase-utilities.h" + +#include <cpptools/cppprojectfilecategorizer.h> +#include <utils/mimetypes/mimedatabase.h> + +#include <QDebug> +#include <QFileInfo> + +using CppTools::ProjectFile; +using CppTools::ProjectFiles; +using CppTools::ProjectFileCategorizer; + +using testing::IsNull; +using testing::NotNull; +using testing::Eq; +using testing::Gt; +using testing::Contains; +using testing::EndsWith; +using testing::AllOf; + +namespace CppTools { + +void PrintTo(const ProjectFile &projectFile, std::ostream *os) +{ + *os << "ProjectFile("; + QString output; + QDebug(&output) << projectFile; + *os << qPrintable(output); + *os << ")"; +} + +} // namespace CppTools + +namespace { + +class ProjectFileCategorizer : public ::testing::Test +{ +protected: + void SetUp() override; + + static ProjectFiles singleFile(const QString &filePath, ProjectFile::Kind kind); + +protected: + const QString dummyProjectPartName; +}; + +using ProjectFileCategorizerVerySlowTest = ProjectFileCategorizer; + +TEST_F(ProjectFileCategorizerVerySlowTest, C) +{ + const QStringList inputFilePaths = QStringList() << "foo.c" << "foo.h"; + const ProjectFiles expected { + ProjectFile("foo.c", ProjectFile::CSource), + ProjectFile("foo.h", ProjectFile::CHeader), + }; + + ::ProjectFileCategorizer categorizer{dummyProjectPartName, inputFilePaths}; + + ASSERT_THAT(categorizer.cSources(), Eq(expected)); + ASSERT_TRUE(categorizer.cxxSources().isEmpty()); + ASSERT_TRUE(categorizer.objcSources().isEmpty()); + ASSERT_TRUE(categorizer.objcxxSources().isEmpty()); +} + +TEST_F(ProjectFileCategorizerVerySlowTest, CxxWithUnambiguousHeaderSuffix) +{ + const QStringList inputFilePaths = QStringList() << "foo.cpp" << "foo.hpp"; + const ProjectFiles expected { + ProjectFile("foo.cpp", ProjectFile::CXXSource), + ProjectFile("foo.hpp", ProjectFile::CXXHeader), + }; + + ::ProjectFileCategorizer categorizer{dummyProjectPartName, inputFilePaths}; + + ASSERT_THAT(categorizer.cxxSources(), Eq(expected)); + ASSERT_TRUE(categorizer.cSources().isEmpty()); + ASSERT_TRUE(categorizer.objcSources().isEmpty()); + ASSERT_TRUE(categorizer.objcxxSources().isEmpty()); +} + +TEST_F(ProjectFileCategorizerVerySlowTest, CxxWithAmbiguousHeaderSuffix) +{ + const QStringList inputFilePaths = QStringList() << "foo.cpp" << "foo.h"; + const ProjectFiles expected { + ProjectFile("foo.cpp", ProjectFile::CXXSource), + ProjectFile("foo.h", ProjectFile::CXXHeader), + }; + + ::ProjectFileCategorizer categorizer{dummyProjectPartName, inputFilePaths}; + + ASSERT_THAT(categorizer.cxxSources(), Eq(expected)); + ASSERT_TRUE(categorizer.cSources().isEmpty()); + ASSERT_TRUE(categorizer.objcSources().isEmpty()); + ASSERT_TRUE(categorizer.objcxxSources().isEmpty()); +} + +TEST_F(ProjectFileCategorizerVerySlowTest, ObjectiveC) +{ + const QStringList inputFilePaths = QStringList() << "foo.m" << "foo.h"; + const ProjectFiles expected { + ProjectFile("foo.m", ProjectFile::ObjCSource), + ProjectFile("foo.h", ProjectFile::ObjCHeader), + }; + + ::ProjectFileCategorizer categorizer{dummyProjectPartName, inputFilePaths}; + + ASSERT_THAT(categorizer.objcSources(), Eq(expected)); + ASSERT_TRUE(categorizer.cxxSources().isEmpty()); + ASSERT_TRUE(categorizer.cSources().isEmpty()); + ASSERT_TRUE(categorizer.objcxxSources().isEmpty()); +} + +TEST_F(ProjectFileCategorizerVerySlowTest, ObjectiveCxx) +{ + const QStringList inputFilePaths = QStringList() << "foo.mm" << "foo.h"; + const ProjectFiles expected { + ProjectFile("foo.mm", ProjectFile::ObjCXXSource), + ProjectFile("foo.h", ProjectFile::ObjCXXHeader), + }; + + ::ProjectFileCategorizer categorizer{dummyProjectPartName, inputFilePaths}; + + ASSERT_THAT(categorizer.objcxxSources(), Eq(expected)); + ASSERT_TRUE(categorizer.objcSources().isEmpty()); + ASSERT_TRUE(categorizer.cSources().isEmpty()); + ASSERT_TRUE(categorizer.cxxSources().isEmpty()); +} + +TEST_F(ProjectFileCategorizerVerySlowTest, MixedCAndCxx) +{ + const QStringList inputFilePaths = QStringList() << "foo.cpp" << "foo.h" + << "bar.c" << "bar.h"; + const ProjectFiles expectedCxxSources { + ProjectFile("foo.cpp", ProjectFile::CXXSource), + ProjectFile("foo.h", ProjectFile::CXXHeader), + ProjectFile("bar.h", ProjectFile::CXXHeader), + }; + const ProjectFiles expectedCSources { + ProjectFile("bar.c", ProjectFile::CSource), + ProjectFile("foo.h", ProjectFile::CHeader), + ProjectFile("bar.h", ProjectFile::CHeader), + }; + + ::ProjectFileCategorizer categorizer{dummyProjectPartName, inputFilePaths}; + + ASSERT_THAT(categorizer.cxxSources(), Eq(expectedCxxSources)); + ASSERT_THAT(categorizer.cSources(), Eq(expectedCSources)); + ASSERT_TRUE(categorizer.objcSources().isEmpty()); + ASSERT_TRUE(categorizer.objcxxSources().isEmpty()); +} + +TEST_F(ProjectFileCategorizerVerySlowTest, AmbiguousHeaderOnly) +{ + ::ProjectFileCategorizer categorizer{dummyProjectPartName, QStringList() << "foo.h"}; + + ASSERT_THAT(categorizer.cSources(), Eq(singleFile("foo.h", ProjectFile::CHeader))); + ASSERT_THAT(categorizer.cxxSources(), Eq(singleFile("foo.h", ProjectFile::CXXHeader))); + ASSERT_THAT(categorizer.objcSources(), Eq(singleFile("foo.h", ProjectFile::ObjCHeader))); + ASSERT_THAT(categorizer.objcxxSources(), Eq(singleFile("foo.h", ProjectFile::ObjCXXHeader))); +} + +void ProjectFileCategorizer::SetUp() +{ + ASSERT_TRUE(MimeDataBaseUtilities::addCppToolsMimeTypes()); +} + +QVector<CppTools::ProjectFile>ProjectFileCategorizer::singleFile(const QString &filePath, + ProjectFile::Kind kind) +{ + return { ProjectFile(filePath, kind) }; +} + +} // anonymous namespace diff --git a/tests/unit/unittest/cppprojectinfogenerator-test.cpp b/tests/unit/unittest/cppprojectinfogenerator-test.cpp new file mode 100644 index 0000000000..9a991a7520 --- /dev/null +++ b/tests/unit/unittest/cppprojectinfogenerator-test.cpp @@ -0,0 +1,170 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#include "googletest.h" +#include "gtest-qt-printing.h" +#include "mimedatabase-utilities.h" + +#include <cpptools/cppprojectinfogenerator.h> +#include <cpptools/projectinfo.h> + +#include <utils/mimetypes/mimedatabase.h> + +using CppTools::Internal::ProjectInfoGenerator; +using CppTools::ProjectFile; +using CppTools::ProjectInfo; +using CppTools::ProjectUpdateInfo; +using CppTools::ProjectPart; +using CppTools::RawProjectPart; + +using ProjectExplorer::ToolChain; + +using testing::Eq; +using testing::UnorderedElementsAre; +using testing::PrintToString; + +namespace { + +MATCHER_P2(IsProjectPart, languageVersion, fileKind, + std::string(negation ? "isn't" : "is") + + " project part with language version " + PrintToString(languageVersion) + + " and file kind " + PrintToString(fileKind)) +{ + const ProjectPart::Ptr &projectPart = arg; + + return projectPart->languageVersion == languageVersion + && projectPart->files.at(0).kind == fileKind; +} + +class ProjectInfoGenerator : public ::testing::Test +{ +protected: + void SetUp() override; + ProjectInfo generate(); + +protected: + RawProjectPart rawProjectPart; +}; + +TEST_F(ProjectInfoGenerator, CreateNoProjectPartsForEmptyFileList) +{ + const ProjectInfo projectInfo = generate(); + + ASSERT_TRUE(projectInfo.projectParts().isEmpty()); +} + +TEST_F(ProjectInfoGenerator, CreateSingleProjectPart) +{ + rawProjectPart.files = QStringList{ "foo.cpp", "foo.h"}; + + const ProjectInfo projectInfo = generate(); + + ASSERT_THAT(projectInfo.projectParts().size(), Eq(1)); +} + +TEST_F(ProjectInfoGenerator, CreateMultipleProjectParts) +{ + rawProjectPart.files = QStringList{ "foo.cpp", "foo.h", "bar.c", "bar.h" }; + + const ProjectInfo projectInfo = generate(); + + ASSERT_THAT(projectInfo.projectParts().size(), Eq(2)); +} + +TEST_F(ProjectInfoGenerator, ProjectPartIndicatesObjectiveCExtensionsByDefault) +{ + rawProjectPart.files = QStringList{ "foo.mm" }; + + const ProjectInfo projectInfo = generate(); + + ASSERT_THAT(projectInfo.projectParts().size(), Eq(1)); + const ProjectPart &projectPart = *projectInfo.projectParts().at(0); + ASSERT_TRUE(projectPart.languageExtensions & ProjectPart::ObjectiveCExtensions); +} + +TEST_F(ProjectInfoGenerator, ProjectPartHasLatestLanguageVersionByDefault) +{ + rawProjectPart.files = QStringList{ "foo.cpp" }; + + const ProjectInfo projectInfo = generate(); + + ASSERT_THAT(projectInfo.projectParts().size(), Eq(1)); + const ProjectPart &projectPart = *projectInfo.projectParts().at(0); + ASSERT_THAT(projectPart.languageVersion, Eq(ProjectPart::LatestCxxVersion)); +} + +TEST_F(ProjectInfoGenerator, UseCompilerFlagsForLanguageVersion) +{ + rawProjectPart.files = QStringList{ "foo.cpp" }; + rawProjectPart.flagsForCxx.compilerFlags = ToolChain::CompilerFlag::StandardCxx98; + + const ProjectInfo projectInfo = generate(); + + ASSERT_THAT(projectInfo.projectParts().size(), Eq(1)); + const ProjectPart &projectPart = *projectInfo.projectParts().at(0); + ASSERT_THAT(projectPart.languageVersion, Eq(ProjectPart::CXX98)); +} + +TEST_F(ProjectInfoGenerator, UseCompilerFlagsForLangaugeExtensions) +{ + rawProjectPart.files = QStringList{ "foo.cpp" }; + rawProjectPart.flagsForCxx.compilerFlags = ToolChain::CompilerFlag::MicrosoftExtensions; + + const ProjectInfo projectInfo = generate(); + + ASSERT_THAT(projectInfo.projectParts().size(), Eq(1)); + const ProjectPart &projectPart = *projectInfo.projectParts().at(0); + ASSERT_TRUE(projectPart.languageExtensions & ProjectPart::MicrosoftExtensions); +} + +TEST_F(ProjectInfoGenerator, ProjectFileKindsMatchProjectPartVersion) +{ + rawProjectPart.files = QStringList{ "foo.h" }; + + const ProjectInfo projectInfo = generate(); + + ASSERT_THAT(projectInfo.projectParts(), + UnorderedElementsAre(IsProjectPart(ProjectPart::LatestCVersion, ProjectFile::CHeader), + IsProjectPart(ProjectPart::LatestCVersion, ProjectFile::ObjCHeader), + IsProjectPart(ProjectPart::LatestCxxVersion, ProjectFile::CXXHeader), + IsProjectPart(ProjectPart::LatestCxxVersion, ProjectFile::ObjCXXHeader))); +} + +void ProjectInfoGenerator::SetUp() +{ + ASSERT_TRUE(MimeDataBaseUtilities::addCppToolsMimeTypes()); +} + +ProjectInfo ProjectInfoGenerator::generate() +{ + QFutureInterface<void> fi; + ProjectUpdateInfo projectUpdateInfo; + projectUpdateInfo.rawProjectParts += rawProjectPart; + ::ProjectInfoGenerator generator(fi, projectUpdateInfo); + + return generator.generate(); +} + +} // anonymous namespace diff --git a/tests/unit/unittest/cppprojectpartchooser-test.cpp b/tests/unit/unittest/cppprojectpartchooser-test.cpp new file mode 100644 index 0000000000..8020d1a35c --- /dev/null +++ b/tests/unit/unittest/cppprojectpartchooser-test.cpp @@ -0,0 +1,356 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#include "googletest.h" + +#include <cpptools/cppprojectpartchooser.h> +#include <cpptools/cpptools_utils.h> +#include <cpptools/projectpart.h> + +using CppTools::Internal::ProjectPartChooser; +using CppTools::ProjectPart; +using CppTools::ProjectPartInfo; +using CppTools::Language; + +using testing::Eq; + +namespace { + +class ProjectPartChooser : public ::testing::Test +{ +protected: + void SetUp() override; + const ProjectPartInfo choose() const; + + static QList<ProjectPart::Ptr> createProjectPartsWithDifferentProjects(); + static QList<ProjectPart::Ptr> createCAndCxxProjectParts(); + +protected: + QString filePath; + ProjectPart::Ptr currentProjectPart{new ProjectPart}; + ProjectPartInfo currentProjectPartInfo{currentProjectPart, + {currentProjectPart}, + ProjectPartInfo::NoHint}; + QString preferredProjectPartId; + const ProjectExplorer::Project *activeProject = nullptr; + Language languagePreference = Language::Cxx; + bool projectsChanged = false; + ::ProjectPartChooser chooser; + + QList<ProjectPart::Ptr> projectPartsForFile; + QList<ProjectPart::Ptr> projectPartsFromDependenciesForFile; + ProjectPart::Ptr fallbackProjectPart; +}; + +TEST_F(ProjectPartChooser, ChooseManuallySet) +{ + ProjectPart::Ptr p1(new ProjectPart); + ProjectPart::Ptr p2(new ProjectPart); + p2->projectFile = preferredProjectPartId = "someId"; + projectPartsForFile += {p1, p2}; + + const ProjectPart::Ptr chosen = choose().projectPart; + + ASSERT_THAT(chosen, Eq(p2)); +} + +TEST_F(ProjectPartChooser, IndicateManuallySet) +{ + ProjectPart::Ptr p1(new ProjectPart); + ProjectPart::Ptr p2(new ProjectPart); + p2->projectFile = preferredProjectPartId = "someId"; + projectPartsForFile += {p1, p2}; + + const ProjectPartInfo::Hints hints = choose().hints; + + ASSERT_TRUE(hints & ProjectPartInfo::IsPreferredMatch); +} + +TEST_F(ProjectPartChooser, IndicateManuallySetForFallbackToProjectPartFromDependencies) +{ + ProjectPart::Ptr p1(new ProjectPart); + ProjectPart::Ptr p2(new ProjectPart); + p2->projectFile = preferredProjectPartId = "someId"; + projectPartsFromDependenciesForFile += {p1, p2}; + + const ProjectPartInfo::Hints hints = choose().hints; + + ASSERT_TRUE(hints & ProjectPartInfo::IsPreferredMatch); +} + +TEST_F(ProjectPartChooser, DoNotIndicateNotManuallySet) +{ + const ProjectPartInfo::Hints hints = choose().hints; + + ASSERT_FALSE(hints & ProjectPartInfo::IsPreferredMatch); +} + +TEST_F(ProjectPartChooser, ForMultipleChooseFromActiveProject) +{ + const QList<ProjectPart::Ptr> projectParts = createProjectPartsWithDifferentProjects(); + const ProjectPart::Ptr secondProjectPart = projectParts.at(1); + projectPartsForFile += projectParts; + activeProject = secondProjectPart->project; + + const ProjectPart::Ptr chosen = choose().projectPart; + + ASSERT_THAT(chosen, Eq(secondProjectPart)); +} + +TEST_F(ProjectPartChooser, ForMultiplePreferSelectedForBuilding) +{ + const ProjectPart::Ptr firstProjectPart{new ProjectPart}; + const ProjectPart::Ptr secondProjectPart{new ProjectPart}; + firstProjectPart->selectedForBuilding = false; + secondProjectPart->selectedForBuilding = true; + projectPartsForFile += firstProjectPart; + projectPartsForFile += secondProjectPart; + + const ProjectPart::Ptr chosen = choose().projectPart; + + ASSERT_THAT(chosen, Eq(secondProjectPart)); +} + +TEST_F(ProjectPartChooser, ForMultipleFromDependenciesChooseFromActiveProject) +{ + const QList<ProjectPart::Ptr> projectParts = createProjectPartsWithDifferentProjects(); + const ProjectPart::Ptr secondProjectPart = projectParts.at(1); + projectPartsFromDependenciesForFile += projectParts; + activeProject = secondProjectPart->project; + + const ProjectPart::Ptr chosen = choose().projectPart; + + ASSERT_THAT(chosen, Eq(secondProjectPart)); +} + +TEST_F(ProjectPartChooser, ForMultipleCheckIfActiveProjectChanged) +{ + const QList<ProjectPart::Ptr> projectParts = createProjectPartsWithDifferentProjects(); + const ProjectPart::Ptr firstProjectPart = projectParts.at(0); + const ProjectPart::Ptr secondProjectPart = projectParts.at(1); + projectPartsForFile += projectParts; + currentProjectPartInfo.projectPart = firstProjectPart; + activeProject = secondProjectPart->project; + + const ProjectPart::Ptr chosen = choose().projectPart; + + ASSERT_THAT(chosen, Eq(secondProjectPart)); +} + +TEST_F(ProjectPartChooser, ForMultipleAndAmbigiousHeaderPreferCProjectPart) +{ + languagePreference = Language::C; + projectPartsForFile = createCAndCxxProjectParts(); + const ProjectPart::Ptr cProjectPart = projectPartsForFile.at(0); + + const ProjectPart::Ptr chosen = choose().projectPart; + + ASSERT_THAT(chosen, Eq(cProjectPart)); +} + +TEST_F(ProjectPartChooser, ForMultipleAndAmbigiousHeaderPreferCxxProjectPart) +{ + languagePreference = Language::Cxx; + projectPartsForFile = createCAndCxxProjectParts(); + const ProjectPart::Ptr cxxProjectPart = projectPartsForFile.at(1); + + const ProjectPart::Ptr chosen = choose().projectPart; + + ASSERT_THAT(chosen, Eq(cxxProjectPart)); +} + +TEST_F(ProjectPartChooser, IndicateMultiple) +{ + const ProjectPart::Ptr p1{new ProjectPart}; + const ProjectPart::Ptr p2{new ProjectPart}; + projectPartsForFile += { p1, p2 }; + + const ProjectPartInfo::Hints hints = choose().hints; + + ASSERT_TRUE(hints & ProjectPartInfo::IsAmbiguousMatch); +} + +TEST_F(ProjectPartChooser, IndicateMultipleForFallbackToProjectPartFromDependencies) +{ + const ProjectPart::Ptr p1{new ProjectPart}; + const ProjectPart::Ptr p2{new ProjectPart}; + projectPartsFromDependenciesForFile += { p1, p2 }; + + const ProjectPartInfo::Hints hints = choose().hints; + + ASSERT_TRUE(hints & ProjectPartInfo::IsAmbiguousMatch); +} + +TEST_F(ProjectPartChooser, ForMultipleChooseNewIfPreviousIsGone) +{ + const ProjectPart::Ptr newProjectPart{new ProjectPart}; + projectPartsForFile += newProjectPart; + + const ProjectPart::Ptr chosen = choose().projectPart; + + ASSERT_THAT(chosen, Eq(newProjectPart)); +} + +TEST_F(ProjectPartChooser, FallbackToProjectPartFromDependencies) +{ + const ProjectPart::Ptr fromDependencies{new ProjectPart}; + projectPartsFromDependenciesForFile += fromDependencies; + + const ProjectPart::Ptr chosen = choose().projectPart; + + ASSERT_THAT(chosen, Eq(fromDependencies)); +} + +TEST_F(ProjectPartChooser, FallbackToProjectPartFromModelManager) +{ + fallbackProjectPart.reset(new ProjectPart); + + const ProjectPart::Ptr chosen = choose().projectPart; + + ASSERT_THAT(chosen, Eq(fallbackProjectPart)); +} + +TEST_F(ProjectPartChooser, ContinueUsingFallbackFromModelManagerIfProjectDoesNotChange) +{ + // ...without re-calculating the dependency table. + fallbackProjectPart.reset(new ProjectPart); + currentProjectPartInfo.projectPart = fallbackProjectPart; + currentProjectPartInfo.hints |= ProjectPartInfo::IsFallbackMatch; + projectPartsFromDependenciesForFile += ProjectPart::Ptr(new ProjectPart); + + const ProjectPart::Ptr chosen = choose().projectPart; + + ASSERT_THAT(chosen, Eq(fallbackProjectPart)); +} + +TEST_F(ProjectPartChooser, StopUsingFallbackFromModelManagerIfProjectChanges1) +{ + fallbackProjectPart.reset(new ProjectPart); + currentProjectPartInfo.projectPart = fallbackProjectPart; + currentProjectPartInfo.hints |= ProjectPartInfo::IsFallbackMatch; + const ProjectPart::Ptr addedProject(new ProjectPart); + projectPartsForFile += addedProject; + + const ProjectPart::Ptr chosen = choose().projectPart; + + ASSERT_THAT(chosen, Eq(addedProject)); +} + +TEST_F(ProjectPartChooser, StopUsingFallbackFromModelManagerIfProjectChanges2) +{ + fallbackProjectPart.reset(new ProjectPart); + currentProjectPartInfo.projectPart = fallbackProjectPart; + currentProjectPartInfo.hints |= ProjectPartInfo::IsFallbackMatch; + const ProjectPart::Ptr addedProject(new ProjectPart); + projectPartsFromDependenciesForFile += addedProject; + projectsChanged = true; + + const ProjectPart::Ptr chosen = choose().projectPart; + + ASSERT_THAT(chosen, Eq(addedProject)); +} + +TEST_F(ProjectPartChooser, IndicateFallbacktoProjectPartFromModelManager) +{ + fallbackProjectPart.reset(new ProjectPart); + + const ProjectPartInfo::Hints hints = choose().hints; + + ASSERT_TRUE(hints & ProjectPartInfo::IsFallbackMatch); +} + +TEST_F(ProjectPartChooser, IndicateFromDependencies) +{ + projectPartsFromDependenciesForFile += ProjectPart::Ptr(new ProjectPart); + + const ProjectPartInfo::Hints hints = choose().hints; + + ASSERT_TRUE(hints & ProjectPartInfo::IsFromDependenciesMatch); +} + +TEST_F(ProjectPartChooser, DoNotIndicateFromDependencies) +{ + projectPartsForFile += ProjectPart::Ptr(new ProjectPart); + + const ProjectPartInfo::Hints hints = choose().hints; + + ASSERT_FALSE(hints & ProjectPartInfo::IsFromDependenciesMatch); +} + +void ProjectPartChooser::SetUp() +{ + chooser.setFallbackProjectPart([&]() { + return fallbackProjectPart; + }); + chooser.setProjectPartsForFile([&](const QString &) { + return projectPartsForFile; + }); + chooser.setProjectPartsFromDependenciesForFile([&](const QString &) { + return projectPartsFromDependenciesForFile; + }); +} + +const ProjectPartInfo ProjectPartChooser::choose() const +{ + return chooser.choose(filePath, + currentProjectPartInfo, + preferredProjectPartId, + activeProject, + languagePreference, + projectsChanged); +} + +QList<ProjectPart::Ptr> ProjectPartChooser::createProjectPartsWithDifferentProjects() +{ + QList<ProjectPart::Ptr> projectParts; + + const ProjectPart::Ptr p1{new ProjectPart}; + p1->project = reinterpret_cast<ProjectExplorer::Project *>(1 << 0); + projectParts.append(p1); + const ProjectPart::Ptr p2{new ProjectPart}; + p2->project = reinterpret_cast<ProjectExplorer::Project *>(1 << 1); + projectParts.append(p2); + + return projectParts; +} + +QList<ProjectPart::Ptr> ProjectPartChooser::createCAndCxxProjectParts() +{ + QList<ProjectPart::Ptr> projectParts; + + // Create project part for C + const ProjectPart::Ptr cprojectpart{new ProjectPart}; + cprojectpart->languageVersion = ProjectPart::C11; + projectParts.append(cprojectpart); + + // Create project part for CXX + const ProjectPart::Ptr cxxprojectpart{new ProjectPart}; + cxxprojectpart->languageVersion = ProjectPart::CXX98; + projectParts.append(cxxprojectpart); + + return projectParts; +} + +} // anonymous namespace diff --git a/tests/unit/unittest/creator_dependency.pri b/tests/unit/unittest/creator_dependency.pri index ef8101f2f9..1932640249 100644 --- a/tests/unit/unittest/creator_dependency.pri +++ b/tests/unit/unittest/creator_dependency.pri @@ -1,22 +1,28 @@ +# Set IDE_LIBEXEC_PATH and IDE_BIN_PATH to silence a warning about empty +# QTC_REL_TOOLS_PATH, which is not used by the tests. +IDE_LIBEXEC_PATH=$$PWD +IDE_BIN_PATH=$$PWD include($$PWD/../../../src/libs/utils/utils-lib.pri) + include($$PWD/../../../src/libs/sqlite/sqlite-lib.pri) include($$PWD/../../../src/libs/clangbackendipc/clangbackendipc-lib.pri) include($$PWD/../../../src/plugins/coreplugin/corepluginunittestfiles.pri) - -!isEmpty(LLVM_INSTALL_DIR) { -include($$PWD/../../../src/tools/clangbackend/ipcsource/clangbackendclangipc-source.pri) include($$PWD/../../../src/tools/clangrefactoringbackend/source/clangrefactoringbackend-source.pri) -include($$PWD/../../../src/plugins/clangcodemodel/clangcodemodelunittestfiles.pri) -include($$PWD/../../../src/plugins/cpptools/cpptoolsunittestfiles.pri) +include($$PWD/../../../src/tools/clangpchmanagerbackend/source/clangpchmanagerbackend-source.pri) include($$PWD/../../../src/plugins/clangrefactoring/clangrefactoring-source.pri) +include($$PWD/../../../src/plugins/clangpchmanager/clangpchmanager-source.pri) +include($$PWD/../../../src/plugins/cpptools/cpptoolsunittestfiles.pri) include(cplusplus.pri) -DEFINES += CLANG_VERSION=\\\"$${LLVM_VERSION}\\\" -DEFINES += "\"CLANG_RESOURCE_DIR=\\\"$${LLVM_LIBDIR}/clang/$${LLVM_VERSION}/include\\\"\"" +!isEmpty(LLVM_INSTALL_DIR) { +include($$PWD/../../../src/shared/clang/clang_defines.pri) +include($$PWD/../../../src/tools/clangbackend/ipcsource/clangbackendclangipc-source.pri) +include($$PWD/../../../src/plugins/clangcodemodel/clangcodemodelunittestfiles.pri) +} else { +DEFINES += CLANG_VERSION=\\\"3.9.1\\\" +DEFINES += "\"CLANG_RESOURCE_DIR=\\\"/usr/include\\\"\"" } -DEFINES += QTC_REL_TOOLS_PATH=$$shell_quote(\"$$relative_path($$IDE_LIBEXEC_PATH, $$IDE_BIN_PATH)\") - INCLUDEPATH += \ $$PWD/../../../src/libs \ $$PWD/../../../src/libs/3rdparty \ diff --git a/tests/unit/unittest/cursor-test.cpp b/tests/unit/unittest/cursor-test.cpp index 77df29a17a..f6b87c1243 100644 --- a/tests/unit/unittest/cursor-test.cpp +++ b/tests/unit/unittest/cursor-test.cpp @@ -193,7 +193,7 @@ TEST_F(Cursor, BriefComment) ASSERT_THAT(cursor.briefComment(), Utf8StringLiteral("A brief comment")); } -TEST_F(Cursor, RawComment) +TEST_F(Cursor, DISABLED_ON_WINDOWS(RawComment)) { auto cursor = translationUnit.cursorAt(Utf8StringLiteral(TESTDATA_DIR"/cursor.h"), 10, 7); @@ -395,7 +395,7 @@ TEST_F(Cursor, IsLocalVariableInStaticFunction) ASSERT_TRUE(cursor.isLocalVariable()); } -TEST_F(Cursor, IsLocalVariableInTemplateFunction) +TEST_F(Cursor, DISABLED_ON_WINDOWS(IsLocalVariableInTemplateFunction)) { auto cursor = translationUnit.cursorAt(52, 7); diff --git a/tests/unit/unittest/data/includecollector_external1.h b/tests/unit/unittest/data/includecollector_external1.h new file mode 100644 index 0000000000..79f1ee616f --- /dev/null +++ b/tests/unit/unittest/data/includecollector_external1.h @@ -0,0 +1,3 @@ +#pragma once + +#include "includecollector_indirect_external.h" diff --git a/tests/unit/unittest/data/includecollector_external2.h b/tests/unit/unittest/data/includecollector_external2.h new file mode 100644 index 0000000000..6f70f09bee --- /dev/null +++ b/tests/unit/unittest/data/includecollector_external2.h @@ -0,0 +1 @@ +#pragma once diff --git a/tests/unit/unittest/data/includecollector_external3.h b/tests/unit/unittest/data/includecollector_external3.h new file mode 100644 index 0000000000..6f70f09bee --- /dev/null +++ b/tests/unit/unittest/data/includecollector_external3.h @@ -0,0 +1 @@ +#pragma once diff --git a/tests/unit/unittest/data/includecollector_false.h b/tests/unit/unittest/data/includecollector_false.h new file mode 100644 index 0000000000..3f59c932d3 --- /dev/null +++ b/tests/unit/unittest/data/includecollector_false.h @@ -0,0 +1,2 @@ +#pragma once + diff --git a/tests/unit/unittest/data/includecollector_header1.h b/tests/unit/unittest/data/includecollector_header1.h new file mode 100644 index 0000000000..3f59c932d3 --- /dev/null +++ b/tests/unit/unittest/data/includecollector_header1.h @@ -0,0 +1,2 @@ +#pragma once + diff --git a/tests/unit/unittest/data/includecollector_header2.h b/tests/unit/unittest/data/includecollector_header2.h new file mode 100644 index 0000000000..7bcf32a89b --- /dev/null +++ b/tests/unit/unittest/data/includecollector_header2.h @@ -0,0 +1,3 @@ +#pragma once + +#include "includecollector_external3.h" diff --git a/tests/unit/unittest/data/includecollector_if.cpp b/tests/unit/unittest/data/includecollector_if.cpp new file mode 100644 index 0000000000..fab79180e2 --- /dev/null +++ b/tests/unit/unittest/data/includecollector_if.cpp @@ -0,0 +1,7 @@ +#if 0 +#include "includecollector_false.h" +#endif + +#if 1 +#include "includecollector_true.h" +#endif diff --git a/tests/unit/unittest/data/includecollector_indirect_external.h b/tests/unit/unittest/data/includecollector_indirect_external.h new file mode 100644 index 0000000000..6f70f09bee --- /dev/null +++ b/tests/unit/unittest/data/includecollector_indirect_external.h @@ -0,0 +1 @@ +#pragma once diff --git a/tests/unit/unittest/data/includecollector_main.cpp b/tests/unit/unittest/data/includecollector_main.cpp new file mode 100644 index 0000000000..068bf9546b --- /dev/null +++ b/tests/unit/unittest/data/includecollector_main.cpp @@ -0,0 +1,4 @@ +#include "includecollector_header1.h" +#include "includecollector_header2.h" +#include "includecollector_external1.h" +#include "../data/includecollector_external2.h" diff --git a/tests/unit/unittest/data/includecollector_main2.cpp b/tests/unit/unittest/data/includecollector_main2.cpp new file mode 100644 index 0000000000..243493ae3b --- /dev/null +++ b/tests/unit/unittest/data/includecollector_main2.cpp @@ -0,0 +1,5 @@ +#include "includecollector_header1.h" +#include "includecollector_header2.h" +#include "includecollector_external1.h" +#include "../data/includecollector_external2.h" +#include "includecollector_generated_file.h" diff --git a/tests/unit/unittest/data/includecollector_main3.cpp b/tests/unit/unittest/data/includecollector_main3.cpp new file mode 100644 index 0000000000..9cfae8e577 --- /dev/null +++ b/tests/unit/unittest/data/includecollector_main3.cpp @@ -0,0 +1,4 @@ +#include <includecollector_header1.h> +#include <includecollector_header2.h> +#include <includecollector_external1.h> +#include <includecollector_external2.h> diff --git a/tests/unit/unittest/data/includecollector_missingfile.cpp b/tests/unit/unittest/data/includecollector_missingfile.cpp new file mode 100644 index 0000000000..890b38c527 --- /dev/null +++ b/tests/unit/unittest/data/includecollector_missingfile.cpp @@ -0,0 +1,6 @@ +#include "missing_file.moc" +#include "foo/missing_file.moc" +#include <missing_file2.moc> +#include <foo2/missing_file2.moc> + +#include "includecollector_external1.h" diff --git a/tests/unit/unittest/data/includecollector_true.h b/tests/unit/unittest/data/includecollector_true.h new file mode 100644 index 0000000000..3f59c932d3 --- /dev/null +++ b/tests/unit/unittest/data/includecollector_true.h @@ -0,0 +1,2 @@ +#pragma once + diff --git a/tests/unit/unittest/data/query_simpleclass.cpp b/tests/unit/unittest/data/query_simpleclass.cpp new file mode 100644 index 0000000000..635e9fb794 --- /dev/null +++ b/tests/unit/unittest/data/query_simpleclass.cpp @@ -0,0 +1,8 @@ +class Class +{ +public: + int x; + + + +}; diff --git a/tests/unit/unittest/data/query_simplefunction.cpp b/tests/unit/unittest/data/query_simplefunction.cpp new file mode 100644 index 0000000000..189ac84d17 --- /dev/null +++ b/tests/unit/unittest/data/query_simplefunction.cpp @@ -0,0 +1,8 @@ +int function(int* pointer, int value) +{ + if (pointer == nullptr) { + return value + 1; + } else { + return value - 1; + } +} diff --git a/tests/unit/unittest/data/sourcerangeextractor_location.cpp b/tests/unit/unittest/data/sourcerangeextractor_location.cpp new file mode 100644 index 0000000000..8e63dcf97e --- /dev/null +++ b/tests/unit/unittest/data/sourcerangeextractor_location.cpp @@ -0,0 +1,2 @@ +int value; + diff --git a/tests/unit/unittest/diagnostic-test.cpp b/tests/unit/unittest/diagnostic-test.cpp index e5e3880965..d53800f571 100644 --- a/tests/unit/unittest/diagnostic-test.cpp +++ b/tests/unit/unittest/diagnostic-test.cpp @@ -120,7 +120,9 @@ protected: DiagnosticContainer expectedDiagnostic(ChildMode childMode) const; }; -TEST_F(Diagnostic, MoveContructor) +using DiagnosticSlowTest = Diagnostic; + +TEST_F(DiagnosticSlowTest, MoveContructor) { const auto diagnostic2 = std::move(d->d->diagnostic); @@ -128,7 +130,7 @@ TEST_F(Diagnostic, MoveContructor) ASSERT_FALSE(diagnostic2.isNull()); } -TEST_F(Diagnostic, MoveAssigment) +TEST_F(DiagnosticSlowTest, MoveAssigment) { auto diagnostic2 = std::move(d->d->diagnostic); d->d->diagnostic = std::move(diagnostic2); @@ -137,53 +139,53 @@ TEST_F(Diagnostic, MoveAssigment) ASSERT_FALSE(d->d->diagnostic.isNull()); } -TEST_F(Diagnostic, MoveSelfAssigment) +TEST_F(DiagnosticSlowTest, MoveSelfAssigment) { d->d->diagnostic = std::move(d->d->diagnostic); ASSERT_FALSE(d->d->diagnostic.isNull()); } -TEST_F(Diagnostic, Text) +TEST_F(DiagnosticSlowTest, Text) { ASSERT_THAT(d->d->diagnostic.text(), Utf8StringLiteral("warning: control reaches end of non-void function")); } -TEST_F(Diagnostic, Category) +TEST_F(DiagnosticSlowTest, Category) { ASSERT_THAT(d->d->diagnostic.category(), Utf8StringLiteral("Semantic Issue")); } -TEST_F(Diagnostic, EnableOption) +TEST_F(DiagnosticSlowTest, EnableOption) { ASSERT_THAT(d->d->diagnostic.options().first, Utf8StringLiteral("-Wreturn-type")); } -TEST_F(Diagnostic, DisableOption) +TEST_F(DiagnosticSlowTest, DisableOption) { ASSERT_THAT(d->d->diagnostic.options().second, Utf8StringLiteral("-Wno-return-type")); } -TEST_F(Diagnostic, Severity) +TEST_F(DiagnosticSlowTest, Severity) { ASSERT_THAT(d->d->diagnostic.severity(), DiagnosticSeverity::Warning); } -TEST_F(Diagnostic, ChildDiagnosticsSize) +TEST_F(DiagnosticSlowTest, ChildDiagnosticsSize) { auto diagnostic = d->d->diagnosticSet.back(); ASSERT_THAT(diagnostic.childDiagnostics().size(), 1); } -TEST_F(Diagnostic, ChildDiagnosticsText) +TEST_F(DiagnosticSlowTest, ChildDiagnosticsText) { auto childDiagnostic = d->d->diagnosticSet.back().childDiagnostics().front(); ASSERT_THAT(childDiagnostic.text(), Utf8StringLiteral("note: candidate function not viable: requires 1 argument, but 0 were provided")); } -TEST_F(Diagnostic, toDiagnosticContainerLetChildrenThroughByDefault) +TEST_F(DiagnosticSlowTest, toDiagnosticContainerLetChildrenThroughByDefault) { const auto diagnosticWithChild = expectedDiagnostic(WithChild); diff --git a/tests/unit/unittest/diagnosticset-test.cpp b/tests/unit/unittest/diagnosticset-test.cpp index a35c9de3b8..c7b04cb8ab 100644 --- a/tests/unit/unittest/diagnosticset-test.cpp +++ b/tests/unit/unittest/diagnosticset-test.cpp @@ -81,7 +81,9 @@ protected: DiagnosticContainer expectedDiagnostic(ChildMode childMode) const; }; -TEST_F(DiagnosticSet, SetHasContent) +using DiagnosticSetSlowTest = DiagnosticSet; + +TEST_F(DiagnosticSetSlowTest, SetHasContent) { document.parse(); const auto set = document.translationUnit().diagnostics(); @@ -89,7 +91,7 @@ TEST_F(DiagnosticSet, SetHasContent) ASSERT_THAT(set.size(), 1); } -TEST_F(DiagnosticSet, MoveConstructor) +TEST_F(DiagnosticSetSlowTest, MoveConstructor) { document.parse(); auto set = document.translationUnit().diagnostics(); @@ -100,7 +102,7 @@ TEST_F(DiagnosticSet, MoveConstructor) ASSERT_FALSE(set2.isNull()); } -TEST_F(DiagnosticSet, MoveAssigment) +TEST_F(DiagnosticSetSlowTest, MoveAssigment) { document.parse(); auto set = document.translationUnit().diagnostics(); @@ -112,7 +114,7 @@ TEST_F(DiagnosticSet, MoveAssigment) ASSERT_FALSE(set.isNull()); } -TEST_F(DiagnosticSet, MoveSelfAssigment) +TEST_F(DiagnosticSetSlowTest, MoveSelfAssigment) { document.parse(); auto set = document.translationUnit().diagnostics(); @@ -122,7 +124,7 @@ TEST_F(DiagnosticSet, MoveSelfAssigment) ASSERT_FALSE(set.isNull()); } -TEST_F(DiagnosticSet, FirstElementEqualBegin) +TEST_F(DiagnosticSetSlowTest, FirstElementEqualBegin) { document.parse(); auto set = document.translationUnit().diagnostics(); @@ -130,7 +132,7 @@ TEST_F(DiagnosticSet, FirstElementEqualBegin) ASSERT_TRUE(set.front() == *set.begin()); } -TEST_F(DiagnosticSet, BeginIsUnequalEnd) +TEST_F(DiagnosticSetSlowTest, BeginIsUnequalEnd) { document.parse(); auto set = document.translationUnit().diagnostics(); @@ -138,7 +140,7 @@ TEST_F(DiagnosticSet, BeginIsUnequalEnd) ASSERT_TRUE(set.begin() != set.end()); } -TEST_F(DiagnosticSet, BeginPlusOneIsEqualEnd) +TEST_F(DiagnosticSetSlowTest, BeginPlusOneIsEqualEnd) { document.parse(); auto set = document.translationUnit().diagnostics(); @@ -146,7 +148,7 @@ TEST_F(DiagnosticSet, BeginPlusOneIsEqualEnd) ASSERT_TRUE(++set.begin() == set.end()); } -TEST_F(DiagnosticSet, ToDiagnosticContainersLetThroughByDefault) +TEST_F(DiagnosticSetSlowTest, ToDiagnosticContainersLetThroughByDefault) { const auto diagnosticContainerWithoutChild = expectedDiagnostic(WithChild); documentMainFile.parse(); @@ -156,7 +158,7 @@ TEST_F(DiagnosticSet, ToDiagnosticContainersLetThroughByDefault) ASSERT_THAT(diagnostics, Contains(IsDiagnosticContainer(diagnosticContainerWithoutChild))); } -TEST_F(DiagnosticSet, ToDiagnosticContainersFiltersOutTopLevelItem) +TEST_F(DiagnosticSetSlowTest, ToDiagnosticContainersFiltersOutTopLevelItem) { documentMainFile.parse(); const ::DiagnosticSet diagnosticSetWithChildren{documentMainFile.translationUnit().diagnostics()}; diff --git a/tests/unit/unittest/dynamicastmatcherdiagnosticcontainer-matcher.h b/tests/unit/unittest/dynamicastmatcherdiagnosticcontainer-matcher.h new file mode 100644 index 0000000000..9a58f3b59f --- /dev/null +++ b/tests/unit/unittest/dynamicastmatcherdiagnosticcontainer-matcher.h @@ -0,0 +1,84 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#pragma once + +#include "googletest.h" + +using testing::PrintToString; + +namespace { + +MATCHER_P5(HasDiagnosticMessage, errorTypeText, startLine, startColumn, endLine, endColumn, + std::string(negation ? "isn't " : "is ") + + "{" + PrintToString(errorTypeText) + + ": (" + PrintToString(startLine) + + ", " + PrintToString(startColumn) + + "), (" + PrintToString(endLine) + + ", " + PrintToString(endColumn) + + ")}" + ) +{ + if (!arg.empty() && arg.front().messages().empty()) { + *result_listener << "no messages"; + return false; + } + + auto message = arg.front().messages().front(); + auto sourceRange = message.sourceRange(); + + return message.errorTypeText() == errorTypeText + && sourceRange.start().line() == uint(startLine) + && sourceRange.start().column() == uint(startColumn) + && sourceRange.end().line() == uint(endLine) + && sourceRange.end().column() == uint(endColumn); +} + +MATCHER_P5(HasDiagnosticContext, contextTypeText, startLine, startColumn, endLine, endColumn, + std::string(negation ? "isn't " : "is ") + + "{" + PrintToString(contextTypeText) + + ": (" + PrintToString(startLine) + + ", " + PrintToString(startColumn) + + "), (" + PrintToString(endLine) + + ", " + PrintToString(endColumn) + + ")}" + ) +{ + if (!arg.empty() && arg.front().messages().empty()) { + *result_listener << "no context"; + return false; + } + + auto context = arg.front().contexts().front(); + auto sourceRange = context.sourceRange(); + + return context.contextTypeText() == contextTypeText + && sourceRange.start().line() == uint(startLine) + && sourceRange.start().column() == uint(startColumn) + && sourceRange.end().line() == uint(endLine) + && sourceRange.end().column() == uint(endColumn); +} + +} diff --git a/tests/unit/unittest/fakeprocess.cpp b/tests/unit/unittest/fakeprocess.cpp new file mode 100644 index 0000000000..e4eb8592e6 --- /dev/null +++ b/tests/unit/unittest/fakeprocess.cpp @@ -0,0 +1,88 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#include "fakeprocess.h" + +FakeProcess::FakeProcess() +{ +} + +FakeProcess::~FakeProcess() +{ + if (m_isStarted && !m_isFinished) + emit finished(0, QProcess::NormalExit); +} + +void FakeProcess::finishUnsuccessfully() +{ + m_isFinished = true; + emit finished(1, QProcess::NormalExit); +} + +void FakeProcess::finishByCrash() +{ + m_isFinished = true; + emit finished(0, QProcess::CrashExit); +} + +void FakeProcess::finish() +{ + m_isFinished = true; + emit finished(0, QProcess::NormalExit); +} + +void FakeProcess::setArguments(const QStringList &arguments) +{ + m_arguments = arguments; +} + +void FakeProcess::setProgram(const QString &program) +{ + m_applicationPath = program; +} + +void FakeProcess::setProcessChannelMode(QProcess::ProcessChannelMode) +{ +} + +void FakeProcess::start() +{ + m_isStarted = true; +} + +bool FakeProcess::isStarted() const +{ + return m_isStarted; +} + +const QStringList &FakeProcess::arguments() const +{ + return m_arguments; +} + +const QString &FakeProcess::applicationPath() const +{ + return m_applicationPath; +} diff --git a/tests/unit/unittest/fakeprocess.h b/tests/unit/unittest/fakeprocess.h new file mode 100644 index 0000000000..88642b303d --- /dev/null +++ b/tests/unit/unittest/fakeprocess.h @@ -0,0 +1,62 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#pragma once + +#include <QProcess> + +class FakeProcess : public QObject +{ + Q_OBJECT + +public: + FakeProcess(); + ~FakeProcess(); + + void finishUnsuccessfully(); + void finishByCrash(); + void finish(); + + void start(); + void setArguments(const QStringList &arguments); + void setProgram(const QString &program); + + void setProcessChannelMode(QProcess::ProcessChannelMode mode); + + + bool isStarted() const; + + const QStringList &arguments() const; + const QString &applicationPath() const; + +signals: + void finished(int exitCode, QProcess::ExitStatus exitStatus); + +private: + QStringList m_arguments; + QString m_applicationPath; + bool m_isFinished = false; + bool m_isStarted = false; +}; diff --git a/tests/unit/unittest/faketimer.cpp b/tests/unit/unittest/faketimer.cpp new file mode 100644 index 0000000000..61e2689373 --- /dev/null +++ b/tests/unit/unittest/faketimer.cpp @@ -0,0 +1,46 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#include "faketimer.h" + +FakeTimer::~FakeTimer() +{ + emitTimoutIfStarted(); +} + +void FakeTimer::start(int) +{ + m_isStarted = true; +} + +void FakeTimer::setSingleShot(bool) +{ +} + +void FakeTimer::emitTimoutIfStarted() +{ + if (m_isStarted) + emit timeout(); +} diff --git a/tests/unit/unittest/faketimer.h b/tests/unit/unittest/faketimer.h new file mode 100644 index 0000000000..ef6945205c --- /dev/null +++ b/tests/unit/unittest/faketimer.h @@ -0,0 +1,46 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ +#pragma once + +#include <QObject> + +class FakeTimer : public QObject +{ + Q_OBJECT + +public: + ~FakeTimer(); + + void start(int interval); + void setSingleShot(bool); + + void emitTimoutIfStarted(); + +signals: + void timeout(); + +private: + bool m_isStarted = false; +}; diff --git a/tests/unit/unittest/fixit-test.cpp b/tests/unit/unittest/fixit-test.cpp index bedf945891..6e708effd4 100644 --- a/tests/unit/unittest/fixit-test.cpp +++ b/tests/unit/unittest/fixit-test.cpp @@ -124,7 +124,7 @@ TEST_F(FixIt, Text) } -TEST_F(FixIt, Start) +TEST_F(FixIt, DISABLED_ON_WINDOWS(Start)) { ASSERT_THAT(fixIt.range().start(), IsSourceLocation(Utf8StringLiteral("diagnostic_semicolon_fixit.cpp"), 3u, @@ -132,7 +132,7 @@ TEST_F(FixIt, Start) 29u)); } -TEST_F(FixIt, End) +TEST_F(FixIt, DISABLED_ON_WINDOWS(End)) { ASSERT_THAT(fixIt.range().end(), IsSourceLocation(Utf8StringLiteral("diagnostic_semicolon_fixit.cpp"), 3u, diff --git a/tests/unit/unittest/googletest.h b/tests/unit/unittest/googletest.h index da028e9f64..1a164bb530 100644 --- a/tests/unit/unittest/googletest.h +++ b/tests/unit/unittest/googletest.h @@ -28,4 +28,12 @@ #include <gmock/gmock.h> #include <gmock/gmock-matchers.h> #include <gtest/gtest.h> + +#include "compare-operators.h" + +#include "conditionally-disabled-tests.h" #include "gtest-qt-printing.h" +#include "gtest-creator-printing.h" +#ifdef CLANG_UNIT_TESTS +# include "gtest-clang-printing.h" +#endif diff --git a/tests/unit/unittest/gtest-clang-printing.cpp b/tests/unit/unittest/gtest-clang-printing.cpp new file mode 100644 index 0000000000..4e488379d8 --- /dev/null +++ b/tests/unit/unittest/gtest-clang-printing.cpp @@ -0,0 +1,93 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#if defined(__GNUC__) +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wunused-parameter" +#elif defined(_MSC_VER) +# pragma warning(push) +# pragma warning( disable : 4100 ) +#endif + +#ifdef CLANG_UNIT_TESTS +#include <clang/Basic/SourceLocation.h> +#include <clang/Basic/SourceManager.h> +#endif + +#if defined(__GNUC__) +# pragma GCC diagnostic pop +#elif defined(_MSC_VER) +# pragma warning(pop) +#endif + +#include <gtest/gtest-printers.h> + +namespace TestGlobal { + +const clang::SourceManager *globalSourceManager = nullptr; + +void setSourceManager(const clang::SourceManager *sourceManager) +{ + globalSourceManager = sourceManager; +} + +} + +namespace llvm { +std::ostream &operator<<(std::ostream &out, const StringRef stringReference) +{ + out.write(stringReference.data(), std::streamsize(stringReference.size())); + + return out; +} +} + +namespace clang { + +void PrintTo(const FullSourceLoc &sourceLocation, ::std::ostream *os) +{ + auto &&sourceManager = sourceLocation.getManager(); + auto fileName = sourceManager.getFileEntryForID(sourceLocation.getFileID())->getName(); + + *os << "(\"" + << fileName << ", " + << sourceLocation.getSpellingLineNumber() << ", " + << sourceLocation.getSpellingColumnNumber() << ")"; +} + +void PrintTo(const SourceRange &sourceRange, ::std::ostream *os) +{ + if (TestGlobal::globalSourceManager) { + *os << "(" + << sourceRange.getBegin().printToString(*TestGlobal::globalSourceManager) << ", " + << sourceRange.getEnd().printToString(*TestGlobal::globalSourceManager) << ")"; + } else { + *os << "(" + << sourceRange.getBegin().getRawEncoding() << ", " + << sourceRange.getEnd().getRawEncoding() << ")"; + } +} + +} diff --git a/tests/unit/unittest/gtest-clang-printing.h b/tests/unit/unittest/gtest-clang-printing.h new file mode 100644 index 0000000000..7ed5a8b960 --- /dev/null +++ b/tests/unit/unittest/gtest-clang-printing.h @@ -0,0 +1,50 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#pragma once + +#include <iosfwd> + +namespace llvm { + +class StringRef; + +std::ostream &operator<<(std::ostream &out, const StringRef stringReference); +} + +namespace clang { +class FullSourceLoc; +class SourceRange; +class SourceManager; + +void PrintTo(const FullSourceLoc &sourceLocation, ::std::ostream *os); +void PrintTo(const SourceRange &sourceLocation, ::std::ostream *os); + +} + +namespace TestGlobal { +void setSourceManager(const clang::SourceManager *sourceManager); +} + diff --git a/tests/unit/unittest/gtest-creator-printing.cpp b/tests/unit/unittest/gtest-creator-printing.cpp new file mode 100644 index 0000000000..5980ec6c63 --- /dev/null +++ b/tests/unit/unittest/gtest-creator-printing.cpp @@ -0,0 +1,56 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#include "gtest-creator-printing.h" + +#include <gtest/gtest-printers.h> + +#include <coreplugin/find/searchresultitem.h> + +namespace Core { +namespace Search { + +using testing::PrintToString; + +class TextPosition; +class TextRange; + +void PrintTo(const TextPosition &position, ::std::ostream *os) +{ + *os << "(" + << position.line << ", " + << position.column << ", " + << position.offset << ")"; +} + +void PrintTo(const TextRange &range, ::std::ostream *os) +{ + *os << "(" + << PrintToString(range.begin) << ", " + << PrintToString(range.end) << ")"; +} + +} +} diff --git a/tests/unit/unittest/gtest-creator-printing.h b/tests/unit/unittest/gtest-creator-printing.h new file mode 100644 index 0000000000..7792475d8f --- /dev/null +++ b/tests/unit/unittest/gtest-creator-printing.h @@ -0,0 +1,42 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#pragma once + +#include <QtGlobal> + +#include <iosfwd> + +namespace Core { +namespace Search { + +class TextPosition; +class TextRange; + +void PrintTo(const TextPosition &position, ::std::ostream *os); +void PrintTo(const TextRange &range, ::std::ostream *os); + +} +} diff --git a/tests/unit/unittest/gtest-qt-printing.cpp b/tests/unit/unittest/gtest-qt-printing.cpp new file mode 100644 index 0000000000..27cd5cfe1b --- /dev/null +++ b/tests/unit/unittest/gtest-qt-printing.cpp @@ -0,0 +1,66 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#include <QString> +#include <QDebug> + +#include <gtest/gtest-printers.h> + +#include <iostream> + +QT_BEGIN_NAMESPACE + +void PrintTo(const QByteArray &byteArray, ::std::ostream *os) +{ + if (byteArray.contains('\n')) { + QByteArray formattedArray = byteArray; + formattedArray.replace("\n", "\n\t"); + *os << "\n\t"; + os->write(formattedArray.data(), formattedArray.size()); + } else { + *os << "\""; + os->write(byteArray.data(), byteArray.size()); + *os << "\""; + } +} + +void PrintTo(const QVariant &variant, ::std::ostream *os) +{ + QString output; + QDebug debug(&output); + + debug << variant; + + PrintTo(output.toUtf8(), os); +} + +void PrintTo(const QString &text, ::std::ostream *os) +{ + const QByteArray utf8 = text.toUtf8(); + + PrintTo(text.toUtf8(), os); +} + +QT_END_NAMESPACE diff --git a/tests/unit/unittest/gtest-qt-printing.h b/tests/unit/unittest/gtest-qt-printing.h index 54c79569ae..8e050ce3ad 100644 --- a/tests/unit/unittest/gtest-qt-printing.h +++ b/tests/unit/unittest/gtest-qt-printing.h @@ -23,70 +23,18 @@ ** ****************************************************************************/ -#include <QString> -#include <QDebug> - -#if defined(__GNUC__) -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wunused-parameter" -#endif - -#ifdef CLANG_UNIT_TESTS -#include <clang/Basic/SourceLocation.h> -#include <clang/Basic/SourceManager.h> -#endif - -#if defined(__GNUC__) -#pragma GCC diagnostic pop -#endif - -#include <gtest/gtest-printers.h> +#pragma once -#include <iostream> +#include <QtGlobal> -#pragma once +#include <iosfwd> QT_BEGIN_NAMESPACE class QVariant; -inline void PrintTo(const QVariant &variant, ::std::ostream *os) -{ - QString output; - QDebug debug(&output); - - debug << variant; - - *os << output.toUtf8().constData(); -} - -inline void PrintTo(const QString &text, ::std::ostream *os) -{ - *os << text.toUtf8().constData(); -} +class QString; +void PrintTo(const QVariant &variant, ::std::ostream *os); +void PrintTo(const QString &text, ::std::ostream *os); +void PrintTo(const QByteArray &byteArray, ::std::ostream *os); QT_END_NAMESPACE - -#ifdef CLANG_UNIT_TESTS -namespace clang { - -inline void PrintTo(const clang::FullSourceLoc &sourceLocation, ::std::ostream *os) -{ - auto &&sourceManager = sourceLocation.getManager(); - auto fileName = sourceManager.getFileEntryForID(sourceLocation.getFileID())->getName(); - - *os << "SourceLocation(\"" - << fileName << ", " - << sourceLocation.getSpellingLineNumber() << ", " - << sourceLocation.getSpellingColumnNumber() << ")"; -} - -} -#endif - -//namespace testing { -//namespace internal { - -// void PrintTo(const QVariant &variant, ::std::ostream *os); - -//} -//} diff --git a/tests/unit/unittest/highlightingmarks-test.cpp b/tests/unit/unittest/highlightingmarks-test.cpp index e93b805997..db6995897c 100644 --- a/tests/unit/unittest/highlightingmarks-test.cpp +++ b/tests/unit/unittest/highlightingmarks-test.cpp @@ -676,49 +676,49 @@ TEST_F(HighlightingMarks, TemplateFunctionDeclaration) ASSERT_THAT(infos[1], HasOnlyType(HighlightingType::Function)); } -TEST_F(HighlightingMarks, TemplateTypeParameterReference) +TEST_F(HighlightingMarks, DISABLED_ON_WINDOWS(TemplateTypeParameterReference)) { const auto infos = translationUnit.highlightingMarksInRange(sourceRange(268, 58)); ASSERT_THAT(infos[0], HasOnlyType(HighlightingType::Type)); } -TEST_F(HighlightingMarks, TemplateTypeParameterDeclarationReference) +TEST_F(HighlightingMarks, DISABLED_ON_WINDOWS(TemplateTypeParameterDeclarationReference)) { const auto infos = translationUnit.highlightingMarksInRange(sourceRange(268, 58)); ASSERT_THAT(infos[1], HasOnlyType(HighlightingType::LocalVariable)); } -TEST_F(HighlightingMarks, NonTypeTemplateParameterReference) +TEST_F(HighlightingMarks, DISABLED_ON_WINDOWS(NonTypeTemplateParameterReference)) { const auto infos = translationUnit.highlightingMarksInRange(sourceRange(269, 71)); ASSERT_THAT(infos[3], HasOnlyType(HighlightingType::LocalVariable)); } -TEST_F(HighlightingMarks, NonTypeTemplateParameterReferenceReference) +TEST_F(HighlightingMarks, DISABLED_ON_WINDOWS(NonTypeTemplateParameterReferenceReference)) { const auto infos = translationUnit.highlightingMarksInRange(sourceRange(269, 71)); ASSERT_THAT(infos[1], HasOnlyType(HighlightingType::LocalVariable)); } -TEST_F(HighlightingMarks, TemplateTemplateParameterReference) +TEST_F(HighlightingMarks, DISABLED_ON_WINDOWS(TemplateTemplateParameterReference)) { const auto infos = translationUnit.highlightingMarksInRange(sourceRange(270, 89)); ASSERT_THAT(infos[0], HasOnlyType(HighlightingType::Type)); } -TEST_F(HighlightingMarks, TemplateTemplateContainerParameterReference) +TEST_F(HighlightingMarks, DISABLED_ON_WINDOWS(TemplateTemplateContainerParameterReference)) { const auto infos = translationUnit.highlightingMarksInRange(sourceRange(270, 89)); ASSERT_THAT(infos[2], HasOnlyType(HighlightingType::Type)); } -TEST_F(HighlightingMarks, TemplateTemplateParameterReferenceVariable) +TEST_F(HighlightingMarks, DISABLED_ON_WINDOWS(TemplateTemplateParameterReferenceVariable)) { const auto infos = translationUnit.highlightingMarksInRange(sourceRange(270, 89)); diff --git a/tests/unit/unittest/includecollector-test.cpp b/tests/unit/unittest/includecollector-test.cpp new file mode 100644 index 0000000000..d2c0d06b71 --- /dev/null +++ b/tests/unit/unittest/includecollector-test.cpp @@ -0,0 +1,138 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#include "googletest.h" + +#include <includecollector.h> +#include <stringcache.h> + +using testing::AllOf; +using testing::Contains; +using testing::Not; +using testing::ElementsAre; +using testing::UnorderedElementsAre; + +namespace { + +class IncludeCollector : public ::testing::Test +{ +protected: + void SetUp(); + uint id(const Utils::SmallString &path); + +protected: + ClangBackEnd::StringCache<Utils::PathString> filePathCache; + ClangBackEnd::IncludeCollector collector{filePathCache}; + ClangBackEnd::IncludeCollector emptyCollector{filePathCache}; + Utils::PathStringVector excludePaths = {TESTDATA_DIR "/includecollector_main.h", + TESTDATA_DIR "/includecollector_main2.h", + TESTDATA_DIR "/includecollector_header1.h", + TESTDATA_DIR "/includecollector_header2.h", + TESTDATA_DIR "/includecollector_generated_file.h"}; +}; + +TEST_F(IncludeCollector, IncludesExternalHeader) +{ + collector.collectIncludes(); + + ASSERT_THAT(collector.takeIncludeIds(), + AllOf(Contains(id(TESTDATA_DIR "/includecollector_external1.h")), + Contains(id(TESTDATA_DIR "/includecollector_external2.h")))); +} + +TEST_F(IncludeCollector, DoesNotIncludesInternalHeader) +{ + collector.collectIncludes(); + + ASSERT_THAT(collector.takeIncludeIds(), Not(Contains(id(TESTDATA_DIR "/includecollector_header1.h")))); +} + +TEST_F(IncludeCollector, NoDuplicate) +{ + collector.collectIncludes(); + + ASSERT_THAT(collector.takeIncludeIds(), + UnorderedElementsAre(id(TESTDATA_DIR "/includecollector_external1.h"), + id(TESTDATA_DIR "/includecollector_external2.h"), + id(TESTDATA_DIR "/includecollector_external3.h"))) << filePathCache.string(3); +} + +TEST_F(IncludeCollector, IncludesAreSorted) +{ + collector.collectIncludes(); + + ASSERT_THAT(collector.takeIncludeIds(), + ElementsAre(0, 1, 2)); +} + +TEST_F(IncludeCollector, If) +{ + emptyCollector.addFile(TESTDATA_DIR, "includecollector_if.cpp", "", {"cc", "includecollector_if.cpp"}); + + emptyCollector.collectIncludes(); + + ASSERT_THAT(emptyCollector.takeIncludeIds(), + ElementsAre(id(TESTDATA_DIR "/includecollector_true.h"))); +} + +TEST_F(IncludeCollector, LocalPath) +{ + emptyCollector.addFile(TESTDATA_DIR, "includecollector_main.cpp", "", {"cc", "includecollector_main.cpp"}); + + emptyCollector.collectIncludes(); + + ASSERT_THAT(emptyCollector.takeIncludeIds(), + UnorderedElementsAre(id(TESTDATA_DIR "/includecollector_external1.h"), + id(TESTDATA_DIR "/includecollector_external2.h"), + id(TESTDATA_DIR "/includecollector_external3.h"))); +} + +TEST_F(IncludeCollector, IgnoreMissingFile) +{ + emptyCollector.addFile(TESTDATA_DIR, "includecollector_missingfile.cpp", "", {"cc", "includecollector_missingfile.cpp"}); + + emptyCollector.collectIncludes(); + + ASSERT_THAT(emptyCollector.takeIncludeIds(), + UnorderedElementsAre(id(TESTDATA_DIR "/includecollector_external1.h"))); +} + +void IncludeCollector::SetUp() +{ + collector.addFile(TESTDATA_DIR, "includecollector_main.cpp", "", {"cc", "includecollector_main.cpp"}); + collector.addFile(TESTDATA_DIR, "includecollector_main2.cpp", "", {"cc", "includecollector_main2.cpp"}); + + collector.addUnsavedFiles({{{TESTDATA_DIR, "includecollector_generated_file.h"}, "#pragma once", {}}}); + + collector.setExcludedIncludes(excludePaths.clone()); + emptyCollector.setExcludedIncludes(excludePaths.clone()); +} + +uint IncludeCollector::id(const Utils::SmallString &path) +{ + return filePathCache.stringId(path); +} + +} diff --git a/tests/unit/unittest/mimedatabase-utilities.cpp b/tests/unit/unittest/mimedatabase-utilities.cpp new file mode 100644 index 0000000000..043ae75254 --- /dev/null +++ b/tests/unit/unittest/mimedatabase-utilities.cpp @@ -0,0 +1,60 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#include "mimedatabase-utilities.h" + +#include <QFile> +#include <QJsonDocument> +#include <QJsonObject> +#include <QJsonValue> +#include <QString> + +#include <utils/mimetypes/mimedatabase.h> + +namespace MimeDataBaseUtilities +{ + +bool addCppToolsMimeTypes() +{ + static bool alreadyAdded = false; + if (alreadyAdded) + return true; + + const QString filePath = CPPTOOLS_JSON; + QFile file(filePath); + if (file.open(QIODevice::ReadOnly)) { + auto doc = QJsonDocument::fromJson(file.readAll()); + QJsonValue mimetypes = doc.object().value("Mimetypes"); + if (!mimetypes.isString()) + return false; + Utils::addMimeTypes(filePath, mimetypes.toString().trimmed().toUtf8()); + alreadyAdded = true; + return true; + } + + return false; +} + +} diff --git a/tests/unit/unittest/mimedatabase-utilities.h b/tests/unit/unittest/mimedatabase-utilities.h new file mode 100644 index 0000000000..89f9ee28ae --- /dev/null +++ b/tests/unit/unittest/mimedatabase-utilities.h @@ -0,0 +1,33 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#pragma once + +#include <functional> + +namespace MimeDataBaseUtilities +{ + bool addCppToolsMimeTypes(); +} diff --git a/tests/unit/unittest/mockchangedfilepathcompressor.h b/tests/unit/unittest/mockchangedfilepathcompressor.h new file mode 100644 index 0000000000..d7988d9920 --- /dev/null +++ b/tests/unit/unittest/mockchangedfilepathcompressor.h @@ -0,0 +1,43 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#pragma once + +#include "googletest.h" + +#include "faketimer.h" + +#include <changedfilepathcompressor.h> + +class MockChangedFilePathCompressor : public ClangBackEnd::ChangedFilePathCompressor<FakeTimer> +{ +public: + MOCK_METHOD0(restartTimer, + void ()); + + MOCK_METHOD1(callbackCalled, + void (const Utils::PathStringVector &filePaths)); +}; + diff --git a/tests/unit/unittest/mockclangcodemodelclient.h b/tests/unit/unittest/mockclangcodemodelclient.h index 8ffe1ac763..650980a9ab 100644 --- a/tests/unit/unittest/mockclangcodemodelclient.h +++ b/tests/unit/unittest/mockclangcodemodelclient.h @@ -25,6 +25,8 @@ #pragma once +#include "googletest.h" + #include <clangbackendipc/clangcodemodelclientinterface.h> #include <clangbackendipc/cmbcodecompletedmessage.h> #include <clangbackendipc/cmbechomessage.h> @@ -34,11 +36,6 @@ #include <clangbackendipc/updatetranslationunitsforeditormessage.h> #include <clangbackendipc/updatevisibletranslationunitsmessage.h> -#include <gmock/gmock.h> -#include <gmock/gmock-matchers.h> -#include <gtest/gtest.h> -#include "gtest-qt-printing.h" - class MockClangCodeModelClient : public ClangBackEnd::ClangCodeModelClientInterface { public: diff --git a/tests/unit/unittest/mockclangpathwatcher.h b/tests/unit/unittest/mockclangpathwatcher.h new file mode 100644 index 0000000000..9539b1b652 --- /dev/null +++ b/tests/unit/unittest/mockclangpathwatcher.h @@ -0,0 +1,42 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#pragma once + +#include "googletest.h" + +#include <clangpathwatcherinterface.h> + +class MockClangPathWatcher : public ClangBackEnd::ClangPathWatcherInterface +{ +public: + MOCK_METHOD1(updateIdPaths, + void (const std::vector<ClangBackEnd::IdPaths> &idPaths)); + MOCK_METHOD1(removeIds, + void (const Utils::SmallStringVector &ids)); + MOCK_METHOD1(setNotifier, + void (ClangBackEnd::ClangPathWatcherNotifier *notifier)); + +}; diff --git a/tests/unit/unittest/mockclangpathwatchernotifier.h b/tests/unit/unittest/mockclangpathwatchernotifier.h new file mode 100644 index 0000000000..fa1b09972b --- /dev/null +++ b/tests/unit/unittest/mockclangpathwatchernotifier.h @@ -0,0 +1,38 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#pragma once + +#include "googletest.h" + +#include <clangpathwatchernotifier.h> + +class MockClangPathWatcherNotifier : public ClangBackEnd::ClangPathWatcherNotifier +{ +public: + MOCK_METHOD1(pathsWithIdsChanged, + void (const Utils::SmallStringVector &ids)); +}; + diff --git a/tests/unit/unittest/mockpchcreator.h b/tests/unit/unittest/mockpchcreator.h new file mode 100644 index 0000000000..dfc3a60051 --- /dev/null +++ b/tests/unit/unittest/mockpchcreator.h @@ -0,0 +1,54 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#pragma once + +#include "googletest.h" + +#include <filecontainerv2.h> +#include <pchcreatorinterface.h> +#include <projectpartpch.h> +#include <projectpartcontainerv2.h> + +class MockPchCreator : public ClangBackEnd::PchCreatorInterface +{ +public: + MOCK_METHOD1(generatePchs, + void(const ClangBackEnd::V2::ProjectPartContainers &projectParts)); + MOCK_METHOD1(setGeneratedFiles, + void(const ClangBackEnd::V2::FileContainers &generatedFiles)); + MOCK_METHOD0(takeProjectsIncludes, + std::vector<ClangBackEnd::IdPaths>()); + + void generatePchs(std::vector<ClangBackEnd::V2::ProjectPartContainer> &&projectParts) override + { + generatePchs(projectParts); + } + + void setGeneratedFiles(ClangBackEnd::V2::FileContainers &&generatedFiles) override + { + setGeneratedFiles(generatedFiles); + } +}; diff --git a/tests/unit/unittest/mockpchgeneratornotifier.h b/tests/unit/unittest/mockpchgeneratornotifier.h new file mode 100644 index 0000000000..fe5b8b2af4 --- /dev/null +++ b/tests/unit/unittest/mockpchgeneratornotifier.h @@ -0,0 +1,38 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#pragma once + +#include "googletest.h" + +#include <pchgeneratornotifierinterface.h> + +class MockPchGeneratorNotifier : public ClangBackEnd::PchGeneratorNotifierInterface +{ +public: + MOCK_METHOD2(taskFinished, + void (ClangBackEnd::TaskFinishStatus status, + const ClangBackEnd::ProjectPartPch &projectPartPch)); +}; diff --git a/tests/unit/unittest/mockpchmanagerclient.h b/tests/unit/unittest/mockpchmanagerclient.h new file mode 100644 index 0000000000..f5d6632a60 --- /dev/null +++ b/tests/unit/unittest/mockpchmanagerclient.h @@ -0,0 +1,44 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#pragma once + +#include "googletest.h" + +#include <pchmanagerclientinterface.h> + +class MockPchManagerClient : public ClangBackEnd::PchManagerClientInterface +{ +public: + MOCK_METHOD0(alive, + void()); + MOCK_METHOD1(precompiledHeadersUpdated, + void(const ClangBackEnd::PrecompiledHeadersUpdatedMessage &message)); + + void precompiledHeadersUpdated(ClangBackEnd::PrecompiledHeadersUpdatedMessage &&message) override + { + precompiledHeadersUpdated(message); + } +}; diff --git a/tests/unit/unittest/mockpchmanagernotifier.h b/tests/unit/unittest/mockpchmanagernotifier.h new file mode 100644 index 0000000000..961d383cae --- /dev/null +++ b/tests/unit/unittest/mockpchmanagernotifier.h @@ -0,0 +1,43 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#pragma once + +#include "googletest.h" + +#include <pchmanagernotifierinterface.h> + +class MockPchManagerNotifier : public ClangPchManager::PchManagerNotifierInterface +{ +public: + MockPchManagerNotifier(ClangPchManager::PchManagerClient &pchManagerClient) + : ClangPchManager::PchManagerNotifierInterface(pchManagerClient) + {} + + MOCK_METHOD2(precompiledHeaderUpdated, + void (const QString &projectPartId, const QString &pchFilePath)); + MOCK_METHOD1(precompiledHeaderRemoved, + void (const QString &projectPartId)); +}; diff --git a/tests/unit/unittest/mockpchmanagerserver.h b/tests/unit/unittest/mockpchmanagerserver.h new file mode 100644 index 0000000000..f5c703afd1 --- /dev/null +++ b/tests/unit/unittest/mockpchmanagerserver.h @@ -0,0 +1,51 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#pragma once + +#include "googletest.h" + +#include <pchmanagerserverinterface.h> + +class MockPchManagerServer : public ClangBackEnd::PchManagerServerInterface +{ +public: + MOCK_METHOD0(end, + void()); + MOCK_METHOD1(updatePchProjectParts, + void (const ClangBackEnd::UpdatePchProjectPartsMessage&)); + MOCK_METHOD1(removePchProjectParts, + void (const ClangBackEnd::RemovePchProjectPartsMessage&)); + + void updatePchProjectParts(ClangBackEnd::UpdatePchProjectPartsMessage &&message) override + { + updatePchProjectParts(message); + } + + void removePchProjectParts(ClangBackEnd::RemovePchProjectPartsMessage &&message) override + { + removePchProjectParts(message); + } +}; diff --git a/tests/unit/unittest/mockprojectparts.h b/tests/unit/unittest/mockprojectparts.h new file mode 100644 index 0000000000..611e12b9fe --- /dev/null +++ b/tests/unit/unittest/mockprojectparts.h @@ -0,0 +1,46 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#pragma once + +#include "googletest.h" + +#include <projectpartsinterface.h> + +class MockProjectParts : public ClangBackEnd::ProjectPartsInterface +{ +public: + MOCK_METHOD1(update, + ClangBackEnd::V2::ProjectPartContainers(const ClangBackEnd::V2::ProjectPartContainers &projectsParts)); + MOCK_METHOD1(remove, + void(const Utils::SmallStringVector &projectPartIds)); + MOCK_CONST_METHOD1(projects, + ClangBackEnd::V2::ProjectPartContainers(const Utils::SmallStringVector &projectPartIds)); + + ClangBackEnd::V2::ProjectPartContainers update(ClangBackEnd::V2::ProjectPartContainers &&projectsParts) override + { + return update(projectsParts); + } +}; diff --git a/tests/unit/unittest/mockqfilesystemwatcher.h b/tests/unit/unittest/mockqfilesystemwatcher.h new file mode 100644 index 0000000000..1bb90b2c37 --- /dev/null +++ b/tests/unit/unittest/mockqfilesystemwatcher.h @@ -0,0 +1,44 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#pragma once + +#include "googletest.h" + +#include <QObject> + +class MockQFileSytemWatcher : public QObject +{ + Q_OBJECT + +public: + MOCK_METHOD1(addPaths, + void (const QStringList&)); + MOCK_METHOD1(removePaths, + void (const QStringList&)); + +signals: + void fileChanged(const QString &); +}; diff --git a/tests/unit/unittest/mockrefactoringclient.h b/tests/unit/unittest/mockrefactoringclient.h index f233412ba5..3a0c653038 100644 --- a/tests/unit/unittest/mockrefactoringclient.h +++ b/tests/unit/unittest/mockrefactoringclient.h @@ -25,12 +25,9 @@ #pragma once -#include <refactoringclientinterface.h> +#include "googletest.h" -#include <gmock/gmock.h> -#include <gmock/gmock-matchers.h> -#include <gtest/gtest.h> -#include "gtest-qt-printing.h" +#include <refactoringclientinterface.h> class MockRefactoringClient : public ClangBackEnd::RefactoringClientInterface { @@ -39,12 +36,19 @@ public: void()); MOCK_METHOD1(sourceLocationsForRenamingMessage, void (const ClangBackEnd::SourceLocationsForRenamingMessage&)); + MOCK_METHOD1(sourceRangesAndDiagnosticsForQueryMessage, + void (const ClangBackEnd::SourceRangesAndDiagnosticsForQueryMessage&)); void sourceLocationsForRenamingMessage(ClangBackEnd::SourceLocationsForRenamingMessage &&message) override { sourceLocationsForRenamingMessage(message); } + void sourceRangesAndDiagnosticsForQueryMessage(ClangBackEnd::SourceRangesAndDiagnosticsForQueryMessage &&message) override + { + sourceRangesAndDiagnosticsForQueryMessage(message); + } + void setLocalRenamingCallback(RenameCallback &&) { } diff --git a/tests/unit/unittest/mockrefactoringserver.h b/tests/unit/unittest/mockrefactoringserver.h index 8a84785515..c88ab1d36b 100644 --- a/tests/unit/unittest/mockrefactoringserver.h +++ b/tests/unit/unittest/mockrefactoringserver.h @@ -25,12 +25,9 @@ #pragma once -#include <refactoringserverinterface.h> +#include "googletest.h" -#include <gmock/gmock.h> -#include <gmock/gmock-matchers.h> -#include <gtest/gtest.h> -#include "gtest-qt-printing.h" +#include <refactoringserverinterface.h> class MockRefactoringServer : public ClangBackEnd::RefactoringServerInterface { @@ -41,8 +38,19 @@ public: MOCK_METHOD1(requestSourceLocationsForRenamingMessage, void (const ClangBackEnd::RequestSourceLocationsForRenamingMessage&)); + MOCK_METHOD1(requestSourceRangesAndDiagnosticsForQueryMessage, + void (const ClangBackEnd::RequestSourceRangesAndDiagnosticsForQueryMessage&)); + + MOCK_METHOD0(cancel, + void ()); + void requestSourceLocationsForRenamingMessage(ClangBackEnd::RequestSourceLocationsForRenamingMessage &&message) override { requestSourceLocationsForRenamingMessage(message); } + + void requestSourceRangesAndDiagnosticsForQueryMessage(ClangBackEnd::RequestSourceRangesAndDiagnosticsForQueryMessage &&message) override + { + requestSourceRangesAndDiagnosticsForQueryMessage(message); + } }; diff --git a/tests/unit/unittest/mocksearch.h b/tests/unit/unittest/mocksearch.h new file mode 100644 index 0000000000..539c07833d --- /dev/null +++ b/tests/unit/unittest/mocksearch.h @@ -0,0 +1,38 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#pragma once + +#include "googletest.h" + +#include <searchinterface.h> + +class MockSearch : public ClangRefactoring::SearchInterface +{ +public: + MOCK_METHOD2(startNewSearch, + std::unique_ptr<ClangRefactoring::SearchHandle>(const QString &searchLabel, + const QString &searchTerm)); +}; diff --git a/tests/unit/unittest/mocksearchhandle.h b/tests/unit/unittest/mocksearchhandle.h new file mode 100644 index 0000000000..f13b06b2a8 --- /dev/null +++ b/tests/unit/unittest/mocksearchhandle.h @@ -0,0 +1,45 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#pragma once + +#include "googletest.h" + +#include <searchhandle.h> + +class MockSearchHandle : public ClangRefactoring::SearchHandle +{ +public: + MockSearchHandle() = default; + using ClangRefactoring::SearchHandle::SearchHandle; + + MOCK_METHOD3(addResult, + void(const QString &fileName, + const QString &lineText, + Core::Search::TextRange textRange)); + MOCK_METHOD1(setExpectedResultCount, void(uint count)); + MOCK_METHOD1(setResultCounter, void(uint counter)); + MOCK_METHOD0(finishSearch, void()); +}; diff --git a/tests/unit/unittest/mocksearchresult.h b/tests/unit/unittest/mocksearchresult.h new file mode 100644 index 0000000000..9acc47b960 --- /dev/null +++ b/tests/unit/unittest/mocksearchresult.h @@ -0,0 +1,28 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#pragma once + +#include "googletest.h" diff --git a/tests/unit/unittest/pchcreator-test.cpp b/tests/unit/unittest/pchcreator-test.cpp new file mode 100644 index 0000000000..0798e9d63c --- /dev/null +++ b/tests/unit/unittest/pchcreator-test.cpp @@ -0,0 +1,347 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#include "googletest.h" + +#include "fakeprocess.h" +#include "mockpchgeneratornotifier.h" +#include "testenvironment.h" + +#include <pchcreator.h> +#include <pchgenerator.h> +#include <stringcache.h> + +#include <QFileInfo> + +namespace { + +using ClangBackEnd::IdPaths; +using ClangBackEnd::ProjectPartPch; +using ClangBackEnd::V2::ProjectPartContainer; +using ClangBackEnd::V2::FileContainer; +using ClangBackEnd::FilePath; +using Utils::PathString; +using Utils::SmallString; + +using testing::_; +using testing::AllOf; +using testing::AtLeast; +using testing::ContainerEq; +using testing::Contains; +using testing::ElementsAre; +using testing::EndsWith; +using testing::Eq; +using testing::Field; +using testing::HasSubstr; +using testing::IsEmpty; +using testing::NiceMock; +using testing::Not; +using testing::Property; +using testing::SizeIs; +using testing::UnorderedElementsAre; + +class PchCreator: public ::testing::Test +{ +protected: + uint id(const Utils::SmallString &path); + +protected: + ClangBackEnd::StringCache<Utils::PathString> filePathCache; + PathString main1Path = TESTDATA_DIR "/includecollector_main3.cpp"; + PathString main2Path = TESTDATA_DIR "/includecollector_main2.cpp"; + PathString header1Path = TESTDATA_DIR "/includecollector_header1.h"; + PathString header2Path = TESTDATA_DIR "/includecollector_header2.h"; + SmallString generatedFileName = "includecollector_generated_file.h"; + PathString generatedFilePath = TESTDATA_DIR "/includecollector_generated_file.h"; + ProjectPartContainer projectPart1{"project1", + {"-I", TESTDATA_DIR, "-Wno-pragma-once-outside-header"}, + {header1Path.clone()}, + {main1Path.clone()}}; + ProjectPartContainer projectPart2{"project2", + {"-I", TESTDATA_DIR, "-x", "c++-header", "-Wno-pragma-once-outside-header"}, + {header2Path.clone()}, + {main2Path.clone()}}; + TestEnvironment environment; + FileContainer generatedFile{{TESTDATA_DIR, generatedFileName.clone()}, "#pragma once", {}}; + NiceMock<MockPchGeneratorNotifier> mockPchGeneratorNotifier; + ClangBackEnd::PchGenerator<FakeProcess> generator{environment, &mockPchGeneratorNotifier}; + ClangBackEnd::PchCreator creator{{projectPart1.clone(),projectPart2.clone()}, + environment, + filePathCache, + &generator, + {generatedFile}}; +}; +using PchCreatorSlowTest = PchCreator; +using PchCreatorVerySlowTest = PchCreator; + +TEST_F(PchCreator, CreateGlobalHeaderPaths) +{ + auto filePaths = creator.generateGlobalHeaderPaths(); + + ASSERT_THAT(filePaths, + UnorderedElementsAre(header1Path, header2Path, generatedFilePath)); +} + +TEST_F(PchCreator, CreateGlobalSourcePaths) +{ + auto filePaths = creator.generateGlobalSourcePaths(); + + ASSERT_THAT(filePaths, + UnorderedElementsAre(main1Path, main2Path)); +} + +TEST_F(PchCreator, CreateGlobalHeaderAndSourcePaths) +{ + auto filePaths = creator.generateGlobalHeaderAndSourcePaths(); + + ASSERT_THAT(filePaths, + UnorderedElementsAre(main1Path, main2Path, header1Path, header2Path, generatedFilePath)); +} + +TEST_F(PchCreator, CreateGlobalArguments) +{ + auto arguments = creator.generateGlobalArguments(); + + ASSERT_THAT(arguments, ElementsAre("-I", TESTDATA_DIR, "-Wno-pragma-once-outside-header", "-I", TESTDATA_DIR, "-x" , "c++-header", "-Wno-pragma-once-outside-header")); +} + +TEST_F(PchCreator, CreateGlobalCommandLine) +{ + auto arguments = creator.generateGlobalCommandLine(); + + ASSERT_THAT(arguments, ElementsAre(environment.clangCompilerPath(), "-I", TESTDATA_DIR, "-Wno-pragma-once-outside-header", "-I", TESTDATA_DIR, "-x" , "c++-header", "-Wno-pragma-once-outside-header")); +} + +TEST_F(PchCreatorVerySlowTest, CreateGlobalPchIncludes) +{ + auto includeIds = creator.generateGlobalPchIncludeIds(); + + ASSERT_THAT(includeIds, + AllOf(Contains(id(TESTDATA_DIR "/includecollector_external3.h")), + Contains(id(TESTDATA_DIR "/includecollector_external1.h")), + Contains(id(TESTDATA_DIR "/includecollector_external2.h")))); +} + +TEST_F(PchCreatorVerySlowTest, CreateGlobalPchFileContent) +{ + auto content = creator.generateGlobalPchHeaderFileContent(); + + ASSERT_THAT(content, + AllOf(HasSubstr("#include \"" TESTDATA_DIR "/includecollector_external3.h\"\n"), + HasSubstr("#include \"" TESTDATA_DIR "/includecollector_external1.h\"\n"), + HasSubstr("#include \"" TESTDATA_DIR "/includecollector_external2.h\"\n"))); +} + +TEST_F(PchCreatorVerySlowTest, CreateGlobalPchHeaderFile) +{ + auto file = creator.generateGlobalPchHeaderFile(); + file->open(QIODevice::ReadOnly); + + auto content = file->readAll(); + + ASSERT_THAT(content.toStdString(), + AllOf(HasSubstr("#include \"" TESTDATA_DIR "/includecollector_external3.h\"\n"), + HasSubstr("#include \"" TESTDATA_DIR "/includecollector_external1.h\"\n"), + HasSubstr("#include \"" TESTDATA_DIR "/includecollector_external2.h\"\n"))); +} + +TEST_F(PchCreator, ConvertToQStringList) +{ + auto arguments = creator.convertToQStringList({"-I", TESTDATA_DIR}); + + ASSERT_THAT(arguments, ElementsAre(QString("-I"), QString(TESTDATA_DIR))); +} + +TEST_F(PchCreator, CreateGlobalPchCompilerArguments) +{ + auto arguments = creator.generateGlobalPchCompilerArguments(); + + ASSERT_THAT(arguments, ElementsAre("-x","c++-header", "-Xclang", "-emit-pch", "-o", EndsWith(".pch"), EndsWith(".h"))); +} + +TEST_F(PchCreator, CreateGlobalClangCompilerArguments) +{ + auto arguments = creator.generateGlobalClangCompilerArguments(); + + ASSERT_THAT(arguments, AllOf(Contains("-Wno-pragma-once-outside-header"), + Contains("-emit-pch"), + Contains("-o"), + Not(Contains(environment.clangCompilerPath())))); +} + +TEST_F(PchCreator, CreateProjectPartCommandLine) +{ + auto commandLine = creator.generateProjectPartCommandLine(projectPart1); + + ASSERT_THAT(commandLine, ElementsAre(environment.clangCompilerPath(), "-I", TESTDATA_DIR, "-Wno-pragma-once-outside-header")); +} + +TEST_F(PchCreator, CreateProjectPartHeaders) +{ + auto includeIds = creator.generateProjectPartHeaders(projectPart1); + + ASSERT_THAT(includeIds, UnorderedElementsAre(header1Path, generatedFilePath)); +} + +TEST_F(PchCreator, CreateProjectPartHeaderAndSources) +{ + auto includeIds = creator.generateProjectPartHeaderAndSourcePaths(projectPart1); + + ASSERT_THAT(includeIds, UnorderedElementsAre(main1Path, header1Path)); +} + +TEST_F(PchCreatorSlowTest, CreateProjectPartPchIncludes) +{ + auto includeIds = creator.generateProjectPartPchIncludes(projectPart1); + + ASSERT_THAT(includeIds, + AllOf(Contains(id(TESTDATA_DIR "/includecollector_external1.h")), + Contains(id(TESTDATA_DIR "/includecollector_external2.h")), + Contains(id(TESTDATA_DIR "/includecollector_header2.h")))); +} + +TEST_F(PchCreatorSlowTest, CreateProjectPartPchFileContent) +{ + auto includes = creator.generateProjectPartPchIncludes(projectPart1); + + auto content = creator.generatePchIncludeFileContent(includes); + + ASSERT_THAT(content, + AllOf(HasSubstr("#include \"" TESTDATA_DIR "/includecollector_header2.h\"\n"), + HasSubstr("#include \"" TESTDATA_DIR "/includecollector_external1.h\"\n"), + HasSubstr("#include \"" TESTDATA_DIR "/includecollector_external2.h\"\n"))); +} + +TEST_F(PchCreatorSlowTest, CreateProjectPartPchIncludeFile) +{ + auto includeIds = creator.generateProjectPartPchIncludes(projectPart1); + auto content = creator.generatePchIncludeFileContent(includeIds); + auto pchIncludeFilePath = creator.generateProjectPathPchHeaderFilePath(projectPart1); + auto file = creator.generateFileWithContent(pchIncludeFilePath, content); + file->open(QIODevice::ReadOnly); + + auto fileContent = file->readAll(); + + ASSERT_THAT(fileContent.toStdString(), + AllOf(HasSubstr("#include \"" TESTDATA_DIR "/includecollector_header2.h\"\n"), + HasSubstr("#include \"" TESTDATA_DIR "/includecollector_external1.h\"\n"), + HasSubstr("#include \"" TESTDATA_DIR "/includecollector_external2.h\"\n"))); +} + +TEST_F(PchCreator, CreateProjectPartPchCompilerArguments) +{ + auto arguments = creator.generateProjectPartPchCompilerArguments(projectPart1); + + ASSERT_THAT(arguments, AllOf(Contains("-x"), + Contains("c++-header"), +// Contains("-Xclang"), +// Contains("-include-pch"), +// Contains("-Xclang"), +// Contains(EndsWith(".pch")), + Contains("-Xclang"), + Contains("-emit-pch"), + Contains("-o"), + Contains(EndsWith(".pch")))); +} + +TEST_F(PchCreator, CreateProjectPartClangCompilerArguments) +{ + auto arguments = creator.generateProjectPartClangCompilerArguments(projectPart1); + + ASSERT_THAT(arguments, AllOf(Contains(TESTDATA_DIR), + Contains("-emit-pch"), + Contains("-o"), + Not(Contains(environment.clangCompilerPath())))); +} + +TEST_F(PchCreatorVerySlowTest, ProjectPartPchsExistsAfterCreation) +{ + creator.generateGlobalPch(); + + creator.generateProjectPartPch(projectPart1); + + ASSERT_TRUE(QFileInfo::exists(creator.generateProjectPathPchHeaderFilePath(projectPart1))); +} + +TEST_F(PchCreatorVerySlowTest, DISABLED_CreatePartPchs) +{ + creator.generateGlobalPch(); + + auto includePaths = creator.generateProjectPartPch(projectPart1); + + ASSERT_THAT(includePaths.id, projectPart1.projectPartId()); + ASSERT_THAT(includePaths.paths, AllOf(Contains(1), Contains(2), Contains(3))); +} + +TEST_F(PchCreatorVerySlowTest, IncludesForCreatePchsForProjectParts) +{ + creator.generatePchs(); + + ASSERT_THAT(creator.takeProjectsIncludes(), + ElementsAre(Field(&IdPaths::id, "project1"), + Field(&IdPaths::id, "project2"))); +} + +TEST_F(PchCreatorVerySlowTest, ProjectPartPchsForCreatePchsForProjectParts) +{ + EXPECT_CALL(mockPchGeneratorNotifier, + taskFinished(ClangBackEnd::TaskFinishStatus::Successfully, + Property(&ProjectPartPch::id, "project1"))); + EXPECT_CALL(mockPchGeneratorNotifier, + taskFinished(ClangBackEnd::TaskFinishStatus::Successfully, + Property(&ProjectPartPch::id, "project2"))); + + creator.generatePchs(); +} + +TEST_F(PchCreatorVerySlowTest, IdPathsForCreatePchsForProjectParts) +{ + creator.generatePchs(); + + ASSERT_THAT(creator.takeProjectsIncludes(), + ElementsAre(AllOf(Field(&IdPaths::id, "project1"), + Field(&IdPaths::paths, AllOf(Contains(id(TESTDATA_DIR "/includecollector_header2.h")), + Contains(id(TESTDATA_DIR "/includecollector_external1.h")), + Contains(id(TESTDATA_DIR "/includecollector_external2.h"))))), + AllOf(Field(&IdPaths::id, "project2"), + Field(&IdPaths::paths, AllOf(Contains(id(TESTDATA_DIR "/includecollector_external1.h")), + Contains(id(TESTDATA_DIR "/includecollector_external3.h")), + Contains(id(TESTDATA_DIR "/includecollector_header1.h")), + Contains(id(TESTDATA_DIR "/includecollector_external2.h"))))))); +} + +TEST_F(PchCreator, CreateProjectPartHeaderAndSourcesContent) +{ + auto content = creator.generateProjectPartHeaderAndSourcesContent(projectPart1); + + ASSERT_THAT(content, Eq("#include \"" TESTDATA_DIR "/includecollector_header1.h\"\n" + "#include \"" TESTDATA_DIR "/includecollector_main3.cpp\"\n")); +} + +uint PchCreator::id(const Utils::SmallString &path) +{ + return filePathCache.stringId(path); +} +} diff --git a/tests/unit/unittest/pchgenerator-test.cpp b/tests/unit/unittest/pchgenerator-test.cpp new file mode 100644 index 0000000000..d7b1980064 --- /dev/null +++ b/tests/unit/unittest/pchgenerator-test.cpp @@ -0,0 +1,219 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#include "googletest.h" + +#include "fakeprocess.h" +#include "testenvironment.h" +#include "mockpchgeneratornotifier.h" + +#include <pchgenerator.h> + +namespace { + +using testing::_; +using testing::Contains; +using testing::Eq; +using testing::NiceMock; +using testing::Not; +using testing::PrintToString; +using ClangBackEnd::TaskFinishStatus; + +MATCHER_P(ContainsProcess, process, + std::string(negation ? "isn't" : "is") + + " process " + PrintToString(process)) +{ + auto found = std::find_if(arg.begin(), + arg.end(), + [&] (const std::unique_ptr<FakeProcess> &processOwner) { + return processOwner.get() == process; + }); + + return found != arg.end(); +} + +class PchGenerator : public testing::Test +{ +protected: + TestEnvironment environment; + NiceMock<MockPchGeneratorNotifier> mockNotifier; + ClangBackEnd::PchGenerator<FakeProcess> generator{environment, &mockNotifier}; + Utils::SmallStringVector compilerArguments = {"-DXXXX", "-Ifoo"}; + ClangBackEnd::ProjectPartPch projectPartPch{"projectPartId", "/path/to/pch"}; +}; + +TEST_F(PchGenerator, ProcessFinished) +{ + EXPECT_CALL(mockNotifier, taskFinished(TaskFinishStatus::Successfully, std::move(projectPartPch))); + + generator.startTask(compilerArguments.clone(), projectPartPch.clone()); +} + +TEST_F(PchGenerator, ProcessFinishedForDeferredProcess) +{ + auto process = generator.addTask(compilerArguments.clone(), projectPartPch.clone()); + generator.startTask(compilerArguments.clone(), projectPartPch.clone()); + + EXPECT_CALL(mockNotifier, taskFinished(TaskFinishStatus::Successfully, std::move(projectPartPch))) + .Times(3); + + generator.startTask(compilerArguments.clone(), projectPartPch.clone()); + process->finish(); +} + +TEST_F(PchGenerator, ProcessSuccessfullyFinished) +{ + EXPECT_CALL(mockNotifier, taskFinished(TaskFinishStatus::Unsuccessfully, std::move(projectPartPch))); + + auto process = generator.addTask(compilerArguments.clone(), projectPartPch.clone()); + process->finishUnsuccessfully(); +} + +TEST_F(PchGenerator, ProcessSuccessfullyFinishedByWrongExitCode) +{ + EXPECT_CALL(mockNotifier, taskFinished(TaskFinishStatus::Unsuccessfully, std::move(projectPartPch))); + + auto process = generator.addTask(compilerArguments.clone(), projectPartPch.clone()); + process->finishUnsuccessfully(); +} + +TEST_F(PchGenerator, AddTaskAddsProcessToProcesses) +{ + auto process = generator.addTask(compilerArguments.clone(), projectPartPch.clone()); + + ASSERT_THAT(generator.runningProcesses(), ContainsProcess(process)); +} + +TEST_F(PchGenerator, RemoveProcessAfterFinishingProcess) +{ + auto process = generator.addTask(compilerArguments.clone(), projectPartPch.clone()); + + process->finish(); + + ASSERT_THAT(generator.runningProcesses(), Not(ContainsProcess(process))); +} + +TEST_F(PchGenerator, ProcessSuccessfullyFinishedByCrash) +{ + EXPECT_CALL(mockNotifier, taskFinished(TaskFinishStatus::Unsuccessfully, std::move(projectPartPch))); + + auto process = generator.addTask(compilerArguments.clone(), projectPartPch.clone()); + process->finishByCrash(); +} + +TEST_F(PchGenerator, CreateProcess) +{ + auto process = generator.addTask(compilerArguments.clone(), projectPartPch.clone()); + + ASSERT_THAT(generator.runningProcesses(), ContainsProcess(process)); +} + +TEST_F(PchGenerator, DeleteProcess) +{ + auto process = generator.addTask(compilerArguments.clone(), projectPartPch.clone()); + + generator.deleteProcess(process); + + ASSERT_THAT(generator.runningProcesses(), Not(ContainsProcess(process))); +} + +TEST_F(PchGenerator, StartProcessApplicationPath) +{ + auto process = generator.addTask(compilerArguments.clone(), projectPartPch.clone()); + + ASSERT_THAT(process->applicationPath(), environment.clangCompilerPath()); + +} + +TEST_F(PchGenerator, SetCompilerArguments) +{ + auto process = generator.addTask(compilerArguments.clone(), projectPartPch.clone()); + + ASSERT_THAT(process->arguments(), compilerArguments); +} + +TEST_F(PchGenerator, ProcessIsStartedAfterAddingTask) +{ + auto process = generator.addTask(compilerArguments.clone(), projectPartPch.clone()); + + ASSERT_TRUE(process->isStarted()); +} + +TEST_F(PchGenerator, DeferProcess) +{ + generator.addTask(compilerArguments.clone(), projectPartPch.clone()); + generator.addTask(compilerArguments.clone(), projectPartPch.clone()); + + auto deferProcess = generator.deferProcess(); + + ASSERT_TRUE(deferProcess); +} + +TEST_F(PchGenerator, ThirdTaskIsDeferred) +{ + generator.addTask(compilerArguments.clone(), projectPartPch.clone()); + generator.addTask(compilerArguments.clone(), projectPartPch.clone()); + + auto process = generator.addTask(compilerArguments.clone(), projectPartPch.clone()); + + ASSERT_THAT(process, generator.deferredProcesses().back().get()); +} + +TEST_F(PchGenerator, ThirdTaskIsNotRunning) +{ + generator.addTask(compilerArguments.clone(), projectPartPch.clone()); + generator.addTask(compilerArguments.clone(), projectPartPch.clone()); + + auto process = generator.addTask(compilerArguments.clone(), projectPartPch.clone()); + + ASSERT_THAT(generator.runningProcesses(), Not(ContainsProcess(process))); +} + +TEST_F(PchGenerator, DoNotDeferProcess) +{ + generator.addTask(compilerArguments.clone(), projectPartPch.clone()); + + auto deferProcess = generator.deferProcess(); + + ASSERT_FALSE(deferProcess); +} + +TEST_F(PchGenerator, DoNotActivateIfNothingIsDeferred) +{ + generator.activateNextDeferredProcess(); +} + +TEST_F(PchGenerator, AfterActivationProcessIsRunning) +{ + generator.addTask(compilerArguments.clone(), projectPartPch.clone()); + generator.addTask(compilerArguments.clone(), projectPartPch.clone()); + auto process = generator.addTask(compilerArguments.clone(), projectPartPch.clone()); + + generator.activateNextDeferredProcess(); + + ASSERT_THAT(generator.runningProcesses(), ContainsProcess(process)); +} + +} diff --git a/tests/unit/unittest/pchmanagerclient-test.cpp b/tests/unit/unittest/pchmanagerclient-test.cpp new file mode 100644 index 0000000000..6e0ac27101 --- /dev/null +++ b/tests/unit/unittest/pchmanagerclient-test.cpp @@ -0,0 +1,92 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#include "googletest.h" + +#include "mockpchmanagernotifier.h" +#include "mockpchmanagerserver.h" + +#include <pchmanagerclient.h> +#include <projectupdater.h> + +#include <precompiledheadersupdatedmessage.h> +#include <removepchprojectpartsmessage.h> +#include <updatepchprojectpartsmessage.h> + +namespace { + +using ClangBackEnd::PrecompiledHeadersUpdatedMessage; + +using testing::_; +using testing::Contains; +using testing::Not; + +class PchManagerClient : public ::testing::Test +{ +protected: + MockPchManagerServer mockPchManagerServer; + ClangPchManager::PchManagerClient client; + MockPchManagerNotifier mockPchManagerNotifier{client}; + ClangPchManager::ProjectUpdater projectUpdater{mockPchManagerServer, client}; + Utils::SmallString projectPartId{"projectPartId"}; + Utils::SmallString pchFilePath{"/path/to/pch"}; + PrecompiledHeadersUpdatedMessage message{{{projectPartId.clone(), pchFilePath.clone()}}}; +}; + +TEST_F(PchManagerClient, NotifierAttached) +{ + MockPchManagerNotifier notifier(client); + + ASSERT_THAT(client.notifiers(), Contains(¬ifier)); +} + +TEST_F(PchManagerClient, NotifierDetached) +{ + MockPchManagerNotifier *notifierPointer = nullptr; + + { + MockPchManagerNotifier notifier(client); + notifierPointer = ¬ifier; + } + + ASSERT_THAT(client.notifiers(), Not(Contains(notifierPointer))); +} + +TEST_F(PchManagerClient, Update) +{ + EXPECT_CALL(mockPchManagerNotifier, precompiledHeaderUpdated(projectPartId.toQString(), pchFilePath.toQString())); + + client.precompiledHeadersUpdated(message.clone()); +} + +TEST_F(PchManagerClient, Remove) +{ + EXPECT_CALL(mockPchManagerNotifier, precompiledHeaderRemoved(projectPartId.toQString())) + .Times(2); + + projectUpdater.removeProjectParts({projectPartId.clone(), projectPartId.clone()}); +} + +} diff --git a/tests/unit/unittest/pchmanagerclientserverinprocess-test.cpp b/tests/unit/unittest/pchmanagerclientserverinprocess-test.cpp new file mode 100644 index 0000000000..ed2ced2311 --- /dev/null +++ b/tests/unit/unittest/pchmanagerclientserverinprocess-test.cpp @@ -0,0 +1,159 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#include "googletest.h" + +#include "mockpchmanagerclient.h" +#include "mockpchmanagerserver.h" + +#include <writemessageblock.h> +#include <pchmanagerclientproxy.h> +#include <pchmanagerserverproxy.h> +#include <precompiledheadersupdatedmessage.h> +#include <removepchprojectpartsmessage.h> +#include <updatepchprojectpartsmessage.h> + +#include <QBuffer> +#include <QString> +#include <QVariant> + +#include <vector> + +using ClangBackEnd::UpdatePchProjectPartsMessage; +using ClangBackEnd::V2::FileContainer; +using ClangBackEnd::V2::ProjectPartContainer; +using ClangBackEnd::RemovePchProjectPartsMessage; +using ClangBackEnd::PrecompiledHeadersUpdatedMessage; + +using ::testing::Args; +using ::testing::Property; +using ::testing::Eq; + +namespace { + +class PchManagerClientServerInProcess : public ::testing::Test +{ +protected: + PchManagerClientServerInProcess(); + + void SetUp(); + void TearDown(); + + void scheduleServerMessages(); + void scheduleClientMessages(); + +protected: + QBuffer buffer; + MockPchManagerClient mockPchManagerClient; + MockPchManagerServer mockPchManagerServer; + + ClangBackEnd::PchManagerServerProxy serverProxy; + ClangBackEnd::PchManagerClientProxy clientProxy; +}; + +TEST_F(PchManagerClientServerInProcess, SendEndMessage) +{ + EXPECT_CALL(mockPchManagerServer, end()); + + serverProxy.end(); + scheduleServerMessages(); +} + +TEST_F(PchManagerClientServerInProcess, SendAliveMessage) +{ + + EXPECT_CALL(mockPchManagerClient, alive()); + + clientProxy.alive(); + scheduleClientMessages(); +} + +TEST_F(PchManagerClientServerInProcess, SendUpdatePchProjectPartsMessage) +{ + ProjectPartContainer projectPart2{"projectPartId", + {"-x", "c++-header", "-Wno-pragma-once-outside-header"}, + {TESTDATA_DIR "/includecollector_header.h"}, + {TESTDATA_DIR "/includecollector_main.cpp"}}; + FileContainer fileContainer{{"/path/to/", "file"}, "content", {}}; + UpdatePchProjectPartsMessage message{{projectPart2}, {fileContainer}}; + + EXPECT_CALL(mockPchManagerServer, updatePchProjectParts(message)); + + serverProxy.updatePchProjectParts(message.clone()); + scheduleServerMessages(); +} + +TEST_F(PchManagerClientServerInProcess, SendRemovePchProjectPartsMessage) +{ + RemovePchProjectPartsMessage message{{"projectPartId1", "projectPartId2"}}; + + EXPECT_CALL(mockPchManagerServer, removePchProjectParts(message)); + + serverProxy.removePchProjectParts(message.clone()); + scheduleServerMessages(); +} + +TEST_F(PchManagerClientServerInProcess, SendPrecompiledHeaderUpdatedMessage) +{ + PrecompiledHeadersUpdatedMessage message{{{"projectPartId", "/path/to/pch"}}}; + + + EXPECT_CALL(mockPchManagerClient, precompiledHeadersUpdated(message)); + + clientProxy.precompiledHeadersUpdated(message.clone()); + scheduleClientMessages(); +} + +PchManagerClientServerInProcess::PchManagerClientServerInProcess() + : serverProxy(&mockPchManagerClient, &buffer), + clientProxy(&mockPchManagerServer, &buffer) +{ +} + +void PchManagerClientServerInProcess::SetUp() +{ + buffer.open(QIODevice::ReadWrite); +} + +void PchManagerClientServerInProcess::TearDown() +{ + buffer.close(); +} + +void PchManagerClientServerInProcess::scheduleServerMessages() +{ + buffer.seek(0); + clientProxy.readMessages(); + buffer.buffer().clear(); +} + +void PchManagerClientServerInProcess::scheduleClientMessages() +{ + buffer.seek(0); + serverProxy.readMessages(); + buffer.buffer().clear(); +} + +} diff --git a/tests/unit/unittest/pchmanagerserver-test.cpp b/tests/unit/unittest/pchmanagerserver-test.cpp new file mode 100644 index 0000000000..8ac039b16a --- /dev/null +++ b/tests/unit/unittest/pchmanagerserver-test.cpp @@ -0,0 +1,191 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#include "googletest.h" + +#include "mockclangpathwatcher.h" +#include "mockpchmanagerclient.h" +#include "mockpchcreator.h" +#include "mockprojectparts.h" + +#include <pchmanagerserver.h> +#include <precompiledheadersupdatedmessage.h> +#include <removepchprojectpartsmessage.h> +#include <updatepchprojectpartsmessage.h> + +namespace { + +using testing::ElementsAre; +using testing::UnorderedElementsAre; +using testing::ByMove; +using testing::NiceMock; +using testing::Return; +using testing::_; +using testing::IsEmpty; + +using Utils::PathString; +using Utils::SmallString; +using ClangBackEnd::V2::FileContainer; +using ClangBackEnd::V2::ProjectPartContainer; +using ClangBackEnd::TaskFinishStatus; + +class PchManagerServer : public ::testing::Test +{ + void SetUp() override; + +protected: + NiceMock<MockPchCreator> mockPchCreator; + NiceMock<MockClangPathWatcher> mockClangPathWatcher; + NiceMock<MockProjectParts> mockProjectParts; + ClangBackEnd::StringCache<Utils::PathString> filePathCache; + ClangBackEnd::PchManagerServer server{filePathCache, mockClangPathWatcher, mockPchCreator, mockProjectParts}; + NiceMock<MockPchManagerClient> mockPchManagerClient; + SmallString projectPartId1 = "project1"; + SmallString projectPartId2 = "project2"; + PathString main1Path = TESTDATA_DIR "/includecollector_main3.cpp"; + PathString main2Path = TESTDATA_DIR "/includecollector_main2.cpp"; + PathString header1Path = TESTDATA_DIR "/includecollector_header1.h"; + PathString header2Path = TESTDATA_DIR "/includecollector_header2.h"; + std::vector<ClangBackEnd::IdPaths> idPaths = {{projectPartId1, {1, 2}}}; + ProjectPartContainer projectPart1{projectPartId1.clone(), + {"-I", TESTDATA_DIR, "-Wno-pragma-once-outside-header"}, + {header1Path.clone()}, + {main1Path.clone()}}; + ProjectPartContainer projectPart2{projectPartId2.clone(), + {"-x", "c++-header", "-Wno-pragma-once-outside-header"}, + {header2Path.clone()}, + {main2Path.clone()}}; + std::vector<ProjectPartContainer> projectParts{projectPart1, projectPart2}; + FileContainer generatedFile{{"/path/to/", "file"}, "content", {}}; + ClangBackEnd::UpdatePchProjectPartsMessage updatePchProjectPartsMessage{Utils::clone(projectParts), + {generatedFile}}; + ClangBackEnd::ProjectPartPch projectPartPch1{projectPart1.projectPartId().clone(), "/path1/to/pch"}; + ClangBackEnd::ProjectPartPch projectPartPch2{projectPart2.projectPartId().clone(), "/path2/to/pch"}; + std::vector<ClangBackEnd::ProjectPartPch> projectPartPchs{projectPartPch1, projectPartPch2}; + ClangBackEnd::PrecompiledHeadersUpdatedMessage precompiledHeaderUpdatedMessage1{{projectPartPch1}}; + ClangBackEnd::PrecompiledHeadersUpdatedMessage precompiledHeaderUpdatedMessage2{{projectPartPch2}}; + ClangBackEnd::RemovePchProjectPartsMessage removePchProjectPartsMessage{{projectPart1.projectPartId().clone(), + projectPart2.projectPartId().clone()}}; +}; + +TEST_F(PchManagerServer, CallPrecompiledHeadersForSuccessfullyFinishedTask) +{ + EXPECT_CALL(mockPchManagerClient, precompiledHeadersUpdated(precompiledHeaderUpdatedMessage1)); + + server.taskFinished(TaskFinishStatus::Successfully, projectPartPch1); +} + +TEST_F(PchManagerServer, DoNotCallPrecompiledHeadersForUnsuccessfullyFinishedTask) +{ + EXPECT_CALL(mockPchManagerClient, precompiledHeadersUpdated(precompiledHeaderUpdatedMessage1)) + .Times(0); + + server.taskFinished(TaskFinishStatus::Unsuccessfully, projectPartPch1); +} + +TEST_F(PchManagerServer, CallBuildInPchCreator) +{ + auto &&callSetGeneratedFiles = EXPECT_CALL(mockPchCreator, + setGeneratedFiles(updatePchProjectPartsMessage.generatedFiles())); + EXPECT_CALL(mockPchCreator, generatePchs(updatePchProjectPartsMessage.projectsParts())) + .After(callSetGeneratedFiles); + + server.updatePchProjectParts(updatePchProjectPartsMessage.clone()); +} + +TEST_F(PchManagerServer, UpdateIncludesOfFileWatcher) +{ + EXPECT_CALL(mockClangPathWatcher, updateIdPaths(idPaths)); + + server.updatePchProjectParts(updatePchProjectPartsMessage.clone()); +} + +TEST_F(PchManagerServer, GetChangedProjectPartsFromProjectParts) +{ + EXPECT_CALL(mockProjectParts, update(_)); + + server.updatePchProjectParts(updatePchProjectPartsMessage.clone()); +} + +TEST_F(PchManagerServer, RemoveIncludesFromFileWatcher) +{ + EXPECT_CALL(mockClangPathWatcher, removeIds(removePchProjectPartsMessage.projectsPartIds())); + + server.removePchProjectParts(removePchProjectPartsMessage.clone()); +} + +TEST_F(PchManagerServer, RemoveProjectPartsFromProjectParts) +{ + EXPECT_CALL(mockProjectParts, remove(removePchProjectPartsMessage.projectsPartIds())); + + server.removePchProjectParts(removePchProjectPartsMessage.clone()); +} + +TEST_F(PchManagerServer, SetPathWatcherNotifier) +{ + EXPECT_CALL(mockClangPathWatcher, setNotifier(_)); + + ClangBackEnd::PchManagerServer server{filePathCache, mockClangPathWatcher, mockPchCreator, mockProjectParts}; +} + +TEST_F(PchManagerServer, CallProjectsInProjectPartsForIncludeChange) +{ + server.updatePchProjectParts(updatePchProjectPartsMessage.clone()); + + EXPECT_CALL(mockProjectParts, projects(ElementsAre(projectPart1.projectPartId()))); + + server.pathsWithIdsChanged({projectPartId1}); +} + +TEST_F(PchManagerServer, CallGeneratePchsInPchCreatorForIncludeChange) +{ + server.updatePchProjectParts(updatePchProjectPartsMessage.clone()); + + EXPECT_CALL(mockPchCreator, generatePchs(ElementsAre(projectPart1))); + + server.pathsWithIdsChanged({projectPartId1}); +} + +TEST_F(PchManagerServer, CallUpdateIdPathsInFileSystemWatcherForIncludeChange) +{ + server.updatePchProjectParts(updatePchProjectPartsMessage.clone()); + + EXPECT_CALL(mockClangPathWatcher, updateIdPaths(idPaths)); + + server.pathsWithIdsChanged({projectPartId1}); +} + +void PchManagerServer::SetUp() +{ + server.setClient(&mockPchManagerClient); + + ON_CALL(mockProjectParts, update(projectParts)) + .WillByDefault(Return(projectParts)); + ON_CALL(mockProjectParts, projects(Utils::SmallStringVector{{projectPartId1}})) + .WillByDefault(Return(std::vector<ClangBackEnd::V2::ProjectPartContainer>{{projectPart1}})); + ON_CALL(mockPchCreator, takeProjectsIncludes()) + .WillByDefault(Return(idPaths)); +} +} diff --git a/tests/unit/unittest/projectparts-test.cpp b/tests/unit/unittest/projectparts-test.cpp new file mode 100644 index 0000000000..e8680dbccc --- /dev/null +++ b/tests/unit/unittest/projectparts-test.cpp @@ -0,0 +1,189 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#include "googletest.h" + +#include <projectparts.h> + +#include <projectpartcontainerv2.h> + +namespace { + +using testing::ElementsAre; +using testing::UnorderedElementsAre; +using testing::IsEmpty; + +using ClangBackEnd::V2::ProjectPartContainer; + +class ProjectParts : public testing::Test +{ +protected: + ClangBackEnd::ProjectParts projectParts; + ProjectPartContainer projectPartContainer1{"id", + {"-DUNIX", "-O2"}, + {"headers1.h", "header2.h"}, + {"source1.cpp", "source2.cpp"}}; + ProjectPartContainer updatedProjectPartContainer1{"id", + {"-DUNIX", "-O2"}, + {"headers1.h", "header2.h"}, + {"source1.cpp", "source2.cpp", "source3.cpp" }}; + ProjectPartContainer projectPartContainer2{"id2", + {"-DUNIX", "-O2"}, + {"headers1.h", "header2.h"}, + {"source1.cpp", "source2.cpp"}}; +}; + +TEST_F(ProjectParts, GetNoProjectPartsForAddingEmptyProjectParts) +{ + auto updatedProjectParts = projectParts.update({}); + + ASSERT_THAT(updatedProjectParts, IsEmpty()); +} + +TEST_F(ProjectParts, GetProjectPartForAddingProjectPart) +{ + auto updatedProjectParts = projectParts.update({projectPartContainer1}); + + ASSERT_THAT(updatedProjectParts, ElementsAre(projectPartContainer1)); +} + +TEST_F(ProjectParts, ProjectPartAdded) +{ + projectParts.update({projectPartContainer1}); + + ASSERT_THAT(projectParts.projectParts(), ElementsAre(projectPartContainer1)); +} + +TEST_F(ProjectParts, FilterDublicateProjectPartsForUpdating) +{ + auto updatedProjectParts = projectParts.update({projectPartContainer1, projectPartContainer1}); + + ASSERT_THAT(updatedProjectParts, ElementsAre(projectPartContainer1)); +} + +TEST_F(ProjectParts, FilteredProjectPartAdded) +{ + projectParts.update({projectPartContainer1, projectPartContainer1}); + + ASSERT_THAT(projectParts.projectParts(), ElementsAre(projectPartContainer1)); +} + +TEST_F(ProjectParts, DoNotUpdateNotNewProjectPart) +{ + projectParts.update({projectPartContainer1}); + + auto updatedProjectParts = projectParts.update({projectPartContainer1}); + + ASSERT_THAT(updatedProjectParts, IsEmpty()); +} + +TEST_F(ProjectParts, NoDuplicateProjectPartAfterUpdatingWithNotNewProjectPart) +{ + projectParts.update({projectPartContainer1}); + + auto updatedProjectParts = projectParts.update({projectPartContainer1}); + + ASSERT_THAT(projectParts.projectParts(), ElementsAre(projectPartContainer1)); +} + +TEST_F(ProjectParts, FilterUniqueProjectParts) +{ + auto updatedProjectParts = projectParts.uniqueProjectParts({projectPartContainer1, projectPartContainer2, projectPartContainer1}); + + ASSERT_THAT(updatedProjectParts, ElementsAre(projectPartContainer1, projectPartContainer2)); +} + +TEST_F(ProjectParts, MergeProjectParts) +{ + projectParts.mergeProjectParts({projectPartContainer1, projectPartContainer2}); + + ASSERT_THAT(projectParts.projectParts(), ElementsAre(projectPartContainer1, projectPartContainer2)); +} + +TEST_F(ProjectParts, MergeProjectMultipleTimesParts) +{ + projectParts.mergeProjectParts({projectPartContainer2}); + + projectParts.mergeProjectParts({projectPartContainer1}); + + ASSERT_THAT(projectParts.projectParts(), ElementsAre(projectPartContainer1, projectPartContainer2)); +} + +TEST_F(ProjectParts, GetNewProjectParts) +{ + projectParts.mergeProjectParts({projectPartContainer2}); + + auto newProjectParts = projectParts.newProjectParts({projectPartContainer1, projectPartContainer2}); + + ASSERT_THAT(newProjectParts, ElementsAre(projectPartContainer1)); +} + +TEST_F(ProjectParts, GetUpdatedProjectPart) +{ + projectParts.update({projectPartContainer1, projectPartContainer2}); + + auto updatedProjectParts = projectParts.update({updatedProjectPartContainer1}); + + ASSERT_THAT(updatedProjectParts, ElementsAre(updatedProjectPartContainer1)); +} + +TEST_F(ProjectParts, ProjectPartIsReplacedWithUpdatedProjectPart) +{ + projectParts.update({projectPartContainer1, projectPartContainer2}); + + projectParts.update({updatedProjectPartContainer1}); + + ASSERT_THAT(projectParts.projectParts(), ElementsAre(updatedProjectPartContainer1, projectPartContainer2)); +} + +TEST_F(ProjectParts, Remove) +{ + projectParts.update({projectPartContainer1, projectPartContainer2}); + + projectParts.remove({projectPartContainer1.projectPartId()}); + + ASSERT_THAT(projectParts.projectParts(), ElementsAre(projectPartContainer2)); +} + +TEST_F(ProjectParts, GetProjectById) +{ + projectParts.update({projectPartContainer1, projectPartContainer2}); + + auto projectPartContainers = projectParts.projects({projectPartContainer1.projectPartId()}); + + ASSERT_THAT(projectPartContainers, ElementsAre(projectPartContainer1)); +} + + +TEST_F(ProjectParts, GetProjectsByIds) +{ + projectParts.update({projectPartContainer1, projectPartContainer2}); + + auto projectPartContainers = projectParts.projects({projectPartContainer1.projectPartId(), projectPartContainer2.projectPartId()}); + + ASSERT_THAT(projectPartContainers, UnorderedElementsAre(projectPartContainer1, projectPartContainer2)); +} + +} diff --git a/tests/unit/unittest/projectupdater-test.cpp b/tests/unit/unittest/projectupdater-test.cpp new file mode 100644 index 0000000000..39ddc4ff14 --- /dev/null +++ b/tests/unit/unittest/projectupdater-test.cpp @@ -0,0 +1,148 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#include "googletest.h" + +#include "mockpchmanagerclient.h" +#include "mockpchmanagernotifier.h" +#include "mockpchmanagerserver.h" + +#include <projectupdater.h> + +#include <pchmanagerclient.h> +#include <precompiledheadersupdatedmessage.h> +#include <removepchprojectpartsmessage.h> +#include <updatepchprojectpartsmessage.h> + +#include <cpptools/clangcompileroptionsbuilder.h> +#include <cpptools/projectpart.h> + +namespace { + +using testing::_; +using testing::ElementsAre; +using testing::SizeIs; +using testing::NiceMock; +using testing::AnyNumber; + +using ClangBackEnd::V2::FileContainer; +using ClangBackEnd::V2::ProjectPartContainer; +using CppTools::ClangCompilerOptionsBuilder; + +class ProjectUpdater : public testing::Test +{ +protected: + void SetUp() override; + +protected: + ClangPchManager::PchManagerClient pchManagerClient; + MockPchManagerNotifier mockPchManagerNotifier{pchManagerClient}; + NiceMock<MockPchManagerServer> mockPchManagerServer; + ClangPchManager::ProjectUpdater updater{mockPchManagerServer, pchManagerClient}; + Utils::SmallString projectPartId{"project1"}; + Utils::SmallString projectPartId2{"project2"}; + Utils::PathStringVector headerPaths = {"/path/to/header1.h", "/path/to/header2.h"}; + Utils::PathStringVector sourcePaths = {"/path/to/source1.cpp", "/path/to/source2.cpp"}; + CppTools::ProjectFile header1ProjectFile{headerPaths[0], CppTools::ProjectFile::CXXHeader}; + CppTools::ProjectFile header2ProjectFile{headerPaths[1], CppTools::ProjectFile::CXXHeader}; + CppTools::ProjectFile source1ProjectFile{sourcePaths[0], CppTools::ProjectFile::CXXSource}; + CppTools::ProjectFile source2ProjectFile{sourcePaths[1], CppTools::ProjectFile::CXXSource}; + CppTools::ProjectPart projectPart; + ProjectPartContainer expectedContainer; + FileContainer generatedFile{{"/path/to", "header1.h"}, "content", {}}; +}; + +TEST_F(ProjectUpdater, CallUpdatePchProjectParts) +{ + std::vector<CppTools::ProjectPart*> projectParts = {&projectPart, &projectPart}; + ClangBackEnd::UpdatePchProjectPartsMessage message{{expectedContainer.clone(), expectedContainer.clone()}, + {generatedFile}}; + + EXPECT_CALL(mockPchManagerServer, updatePchProjectParts(message)); + + updater.updateProjectParts(projectParts, {generatedFile}); +} + +TEST_F(ProjectUpdater, CallRemovePchProjectParts) +{ + EXPECT_CALL(mockPchManagerNotifier, precompiledHeaderRemoved(_)).Times(AnyNumber()); + ClangBackEnd::RemovePchProjectPartsMessage message{{projectPartId, projectPartId2}}; + + EXPECT_CALL(mockPchManagerServer, removePchProjectParts(message)); + + updater.removeProjectParts({projectPartId, projectPartId2}); +} + +TEST_F(ProjectUpdater, CallPrecompiledHeaderRemoved) +{ + ClangBackEnd::RemovePchProjectPartsMessage message{{projectPartId, projectPartId2}}; + + EXPECT_CALL(mockPchManagerNotifier, precompiledHeaderRemoved(projectPartId.toQString())); + EXPECT_CALL(mockPchManagerNotifier, precompiledHeaderRemoved(projectPartId2.toQString())); + + updater.removeProjectParts({projectPartId, projectPartId2}); +} + +TEST_F(ProjectUpdater, ConvertProjectPartToProjectPartContainer) +{ + updater.setExcludedPaths({"/path/to/header1.h"}); + + auto container = updater.toProjectPartContainer(&projectPart); + + ASSERT_THAT(container, expectedContainer); +} + +TEST_F(ProjectUpdater, ConvertProjectPartToProjectPartContainersHaveSameSizeLikeProjectParts) +{ + auto containers = updater.toProjectPartContainers({&projectPart, &projectPart}); + + ASSERT_THAT(containers, SizeIs(2)); +} + +TEST_F(ProjectUpdater, CreateExcludedPaths) +{ + auto excludedPaths = updater.createExcludedPaths({generatedFile}); + + ASSERT_THAT(excludedPaths, ElementsAre("/path/to/header1.h")); +} + +void ProjectUpdater::SetUp() +{ + projectPart.files.push_back(header1ProjectFile); + projectPart.files.push_back(header2ProjectFile); + projectPart.files.push_back(source1ProjectFile); + projectPart.files.push_back(source2ProjectFile); + projectPart.displayName = projectPartId; + + Utils::SmallStringVector arguments{ClangPchManager::ProjectUpdater::compilerArguments( + &projectPart)}; + + expectedContainer = {projectPartId.clone(), + arguments.clone(), + {headerPaths[1]}, + sourcePaths.clone()}; +} +} + diff --git a/tests/unit/unittest/refactoringclient-test.cpp b/tests/unit/unittest/refactoringclient-test.cpp index 69b8259e1b..9ccc9c2d12 100644 --- a/tests/unit/unittest/refactoringclient-test.cpp +++ b/tests/unit/unittest/refactoringclient-test.cpp @@ -25,14 +25,17 @@ #include "googletest.h" #include "mockrefactoringclientcallback.h" +#include "mocksearchhandle.h" +#include <clangqueryprojectsfindfilter.h> #include <refactoringclient.h> -#include <refactoringcompileroptionsbuilder.h> #include <refactoringengine.h> #include <refactoringconnectionclient.h> #include <sourcelocationsforrenamingmessage.h> +#include <sourcerangesanddiagnosticsforquerymessage.h> +#include <cpptools/clangcompileroptionsbuilder.h> #include <cpptools/projectpart.h> #include <utils/smallstringvector.h> @@ -42,10 +45,17 @@ namespace { -using ClangRefactoring::RefactoringCompilerOptionsBuilder; +using CppTools::ClangCompilerOptionsBuilder; + using ClangRefactoring::RefactoringEngine; +using ClangBackEnd::SourceLocationsForRenamingMessage; +using ClangBackEnd::SourceRangesAndDiagnosticsForQueryMessage; + using testing::_; +using testing::Pair; +using testing::Contains; +using testing::NiceMock; using Utils::SmallString; using Utils::SmallStringVector; @@ -55,6 +65,7 @@ class RefactoringClient : public ::testing::Test void SetUp(); protected: + NiceMock<MockSearchHandle> mockSearchHandle; MockRefactoringClientCallBack callbackMock; ClangRefactoring::RefactoringClient client; ClangBackEnd::RefactoringConnectionClient connectionClient{&client}; @@ -64,14 +75,20 @@ protected: QTextCursor cursor{&textDocument}; QString qStringFilePath{QStringLiteral("/home/user/file.cpp")}; Utils::FileName filePath{Utils::FileName::fromString(qStringFilePath)}; - ClangBackEnd::FilePath clangBackEndFilePath{"/home/user", "file.cpp"}; + ClangBackEnd::FilePath clangBackEndFilePath{qStringFilePath}; SmallStringVector commandLine; CppTools::ProjectPart::Ptr projectPart; CppTools::ProjectFile projectFile{qStringFilePath, CppTools::ProjectFile::CXXSource}; - ClangBackEnd::SourceLocationsForRenamingMessage message{"symbol", - {{{42u, clangBackEndFilePath.clone()}}, - {{42u, 1, 1}, {42u, 2, 5}}}, - 1}; + SourceLocationsForRenamingMessage renameMessage{"symbol", + {{{42u, clangBackEndFilePath.clone()}}, + {{42u, 1, 1, 0}, {42u, 2, 5, 10}}}, + 1}; + SourceRangesAndDiagnosticsForQueryMessage queryResultMessage{{{{42u, clangBackEndFilePath.clone()}}, + {{42u, 1, 1, 0, 1, 5, 4, ""}, + {42u, 2, 1, 5, 2, 5, 10, ""}}}, + {}}; + SourceRangesAndDiagnosticsForQueryMessage emptyQueryResultMessage{{{},{}}, + {}}; }; TEST_F(RefactoringClient, SourceLocationsForRenaming) @@ -84,12 +101,12 @@ TEST_F(RefactoringClient, SourceLocationsForRenaming) textDocumentRevision); }); - EXPECT_CALL(callbackMock, localRenaming(message.symbolName().toQString(), - message.sourceLocations(), - message.textDocumentRevision())) + EXPECT_CALL(callbackMock, localRenaming(renameMessage.symbolName().toQString(), + renameMessage.sourceLocations(), + renameMessage.textDocumentRevision())) .Times(1); - client.sourceLocationsForRenamingMessage(std::move(message)); + client.sourceLocationsForRenamingMessage(std::move(renameMessage)); } TEST_F(RefactoringClient, AfterSourceLocationsForRenamingEngineIsUsableAgain) @@ -103,28 +120,145 @@ TEST_F(RefactoringClient, AfterSourceLocationsForRenamingEngineIsUsableAgain) }); EXPECT_CALL(callbackMock, localRenaming(_,_,_)); - client.sourceLocationsForRenamingMessage(std::move(message)); + client.sourceLocationsForRenamingMessage(std::move(renameMessage)); ASSERT_TRUE(engine.isUsable()); } TEST_F(RefactoringClient, AfterStartLocalRenameHasValidCallback) { - engine.startLocalRenaming(cursor, filePath, textDocument.revision(), projectPart.data(), {}); + engine.startLocalRenaming(cursor, + filePath, + textDocument.revision(), + projectPart.data(), + [&] (const QString &, + const ClangBackEnd::SourceLocationsContainer &, + int) {}); ASSERT_TRUE(client.hasValidLocalRenamingCallback()); } +TEST_F(RefactoringClient, CallAddResultsForEmptyQueryMessage) +{ + EXPECT_CALL(mockSearchHandle, addResult(_ ,_ ,_)) + .Times(0); + + client.sourceRangesAndDiagnosticsForQueryMessage(std::move(emptyQueryResultMessage)); +} + +TEST_F(RefactoringClient, CallAddResultsForQueryMessage) +{ + EXPECT_CALL(mockSearchHandle, addResult(_ ,_ ,_)) + .Times(2); + + client.sourceRangesAndDiagnosticsForQueryMessage(std::move(queryResultMessage)); +} + +TEST_F(RefactoringClient, CallFinishSearchForEmptyQueryMessage) +{ + EXPECT_CALL(mockSearchHandle, finishSearch()) + .Times(1); + + client.sourceRangesAndDiagnosticsForQueryMessage(std::move(emptyQueryResultMessage)); +} + +TEST_F(RefactoringClient, CallFinishSearchQueryMessage) +{ + EXPECT_CALL(mockSearchHandle, finishSearch()) + .Times(1); + + client.sourceRangesAndDiagnosticsForQueryMessage(std::move(queryResultMessage)); +} + +TEST_F(RefactoringClient, CallFinishSearchForTwoQueryMessages) +{ + client.setExpectedResultCount(2); + + EXPECT_CALL(mockSearchHandle, finishSearch()) + .Times(1); + + client.sourceRangesAndDiagnosticsForQueryMessage(std::move(queryResultMessage)); + client.sourceRangesAndDiagnosticsForQueryMessage(std::move(queryResultMessage)); +} + +TEST_F(RefactoringClient, CallSetExpectedResultCountInSearchHandle) +{ + EXPECT_CALL(mockSearchHandle, setExpectedResultCount(3)) + .Times(1); + + client.setExpectedResultCount(3); +} + +TEST_F(RefactoringClient, ResultCounterIsOneAfterQueryMessage) +{ + client.sourceRangesAndDiagnosticsForQueryMessage(std::move(queryResultMessage)); + + ASSERT_THAT(client.resultCounter(), 1); +} + +TEST_F(RefactoringClient, ResultCounterIsSetInSearchHandleToOne) +{ + EXPECT_CALL(mockSearchHandle, setResultCounter(1)) + .Times(1); + + client.sourceRangesAndDiagnosticsForQueryMessage(std::move(queryResultMessage)); +} + +TEST_F(RefactoringClient, ResultCounterIsSetInSearchHandleToTwo) +{ + client.sourceRangesAndDiagnosticsForQueryMessage(std::move(queryResultMessage)); + + EXPECT_CALL(mockSearchHandle, setResultCounter(2)) + .Times(1); + + client.sourceRangesAndDiagnosticsForQueryMessage(std::move(queryResultMessage)); +} + + +TEST_F(RefactoringClient, ResultCounterIsZeroAfterSettingExpectedResultCount) +{ + client.sourceRangesAndDiagnosticsForQueryMessage(std::move(queryResultMessage)); + + client.setExpectedResultCount(3); + + ASSERT_THAT(client.resultCounter(), 0); +} + + +TEST_F(RefactoringClient, ConvertFilePaths) +{ + std::unordered_map<uint, ClangBackEnd::FilePath> filePaths{{42u, clangBackEndFilePath.clone()}}; + + auto qstringFilePaths = ClangRefactoring::RefactoringClient::convertFilePaths(filePaths); + + ASSERT_THAT(qstringFilePaths, Contains(Pair(42u, qStringFilePath))); +} + +TEST_F(RefactoringClient, XXX) +{ + const Core::Search::TextRange textRange{{1,0,1},{1,0,1}}; + const ClangBackEnd::SourceRangeWithTextContainer sourceRange{1, 1, 1, 1, 1, 1, 1, "function"}; + std::unordered_map<uint, QString> filePaths = {{1, "/path/to/file"}}; + + EXPECT_CALL(mockSearchHandle, addResult(QString("/path/to/file"), QString("function"), textRange)) + .Times(1); + + client.addSearchResult(sourceRange, filePaths); +} + void RefactoringClient::SetUp() { + using Filter = ClangRefactoring::ClangQueryProjectsFindFilter; + client.setRefactoringEngine(&engine); projectPart = CppTools::ProjectPart::Ptr(new CppTools::ProjectPart); projectPart->files.push_back(projectFile); - commandLine = RefactoringCompilerOptionsBuilder::build(projectPart.data(), - projectFile.kind, - RefactoringCompilerOptionsBuilder::PchUsage::None); + commandLine = Filter::compilerArguments(projectPart.data(), projectFile.kind); + + client.setSearchHandle(&mockSearchHandle); + client.setExpectedResultCount(1); } } diff --git a/tests/unit/unittest/refactoringclientserverinprocess-test.cpp b/tests/unit/unittest/refactoringclientserverinprocess-test.cpp index 1080df77ab..1d7a00c25c 100644 --- a/tests/unit/unittest/refactoringclientserverinprocess-test.cpp +++ b/tests/unit/unittest/refactoringclientserverinprocess-test.cpp @@ -32,7 +32,9 @@ #include <refactoringclientproxy.h> #include <refactoringserverproxy.h> #include <sourcelocationsforrenamingmessage.h> +#include <sourcerangesanddiagnosticsforquerymessage.h> #include <requestsourcelocationforrenamingmessage.h> +#include <requestsourcerangesanddiagnosticsforquerymessage.h> #include <QBuffer> #include <QString> @@ -101,7 +103,7 @@ TEST_F(RefactoringClientServerInProcess, SendSourceLocationsForRenamingMessage) TEST_F(RefactoringClientServerInProcess, SendRequestSourceLocationsForRenamingMessage) { - RequestSourceLocationsForRenamingMessage message{{"/home/marco/dev/qt-creator/tests/unit/unittest/data", "renamevariable.cpp"}, + RequestSourceLocationsForRenamingMessage message{{TESTDATA_DIR, "renamevariable.cpp"}, 1, 5, "int v;\n\nint x = v + 3;\n", @@ -115,6 +117,49 @@ TEST_F(RefactoringClientServerInProcess, SendRequestSourceLocationsForRenamingMe scheduleServerMessages(); } +TEST_F(RefactoringClientServerInProcess, SourceRangesAndDiagnosticsForQueryMessage) +{ + ClangBackEnd::SourceRangesContainer sourceRangesContainer; + std::vector<ClangBackEnd::DynamicASTMatcherDiagnosticContainer> diagnosticContainers; + ClangBackEnd::SourceRangesAndDiagnosticsForQueryMessage message(std::move(sourceRangesContainer), + std::move(diagnosticContainers)); + + EXPECT_CALL(mockRefactoringClient, sourceRangesAndDiagnosticsForQueryMessage(message)) + .Times(1); + + clientProxy.sourceRangesAndDiagnosticsForQueryMessage(message.clone()); + scheduleClientMessages(); +} + +TEST_F(RefactoringClientServerInProcess, RequestSourceRangesAndDiagnosticsForQueryMessage) +{ + RequestSourceRangesAndDiagnosticsForQueryMessage message{"functionDecl()", + {{{TESTDATA_DIR, "query_simplefunction.cpp"}, + "void f();", + {"cc", "query_simplefunction.cpp"}, + 1}}, + {{{TESTDATA_DIR, "query_simplefunction.h"}, + "void f();", + {}, + 1}}}; + + EXPECT_CALL(mockRefactoringServer, requestSourceRangesAndDiagnosticsForQueryMessage(message)) + .Times(1); + + serverProxy.requestSourceRangesAndDiagnosticsForQueryMessage(message.clone()); + scheduleServerMessages(); +} + +TEST_F(RefactoringClientServerInProcess, CancelMessage) +{ + EXPECT_CALL(mockRefactoringServer, cancel()) + .Times(1); + + serverProxy.cancel(); + scheduleServerMessages(); +} + + RefactoringClientServerInProcess::RefactoringClientServerInProcess() : serverProxy(&mockRefactoringClient, &buffer), clientProxy(&mockRefactoringServer, &buffer) diff --git a/tests/unit/unittest/refactoringcompilationdatabase-test.cpp b/tests/unit/unittest/refactoringcompilationdatabase-test.cpp index 83ea151618..84f426cacd 100644 --- a/tests/unit/unittest/refactoringcompilationdatabase-test.cpp +++ b/tests/unit/unittest/refactoringcompilationdatabase-test.cpp @@ -27,13 +27,15 @@ #include <refactoringcompilationdatabase.h> +#include <utils/smallstring.h> + +#include <QDir> + using testing::Contains; using testing::IsEmpty; using testing::Not; using testing::PrintToString; -using ClangBackEnd::RefactoringCompilationDatabase; - namespace { MATCHER_P3(IsCompileCommand, directory, fileName, commandLine, @@ -51,48 +53,53 @@ MATCHER_P3(IsCompileCommand, directory, fileName, commandLine, return true; } -TEST(RefactoringCompilationDatabase, GetAllFilesContainsTranslationUnit) +class RefactoringCompilationDatabase : public ::testing::Test { - RefactoringCompilationDatabase database; - database.addFile("/tmp", "data.cpp", {"cc", "data.cpp", "-DNO_DEBUG"}); +protected: + void SetUp(); +protected: + ClangBackEnd::RefactoringCompilationDatabase database; + Utils::SmallString temporaryDirectoryPath = QDir::toNativeSeparators(QDir::tempPath()); + Utils::SmallString temporarySourceFilePath = QDir::toNativeSeparators(QDir::tempPath() + "/data.cpp"); + +}; + +TEST_F(RefactoringCompilationDatabase, GetAllFilesContainsTranslationUnit) +{ auto filePaths = database.getAllFiles(); - ASSERT_THAT(filePaths, Contains("/tmp/data.cpp")); + ASSERT_THAT(filePaths, Contains(temporarySourceFilePath)); } -TEST(RefactoringCompilationDatabase, CompileCommandForFilePath) +TEST_F(RefactoringCompilationDatabase, CompileCommandForFilePath) { - RefactoringCompilationDatabase database; - database.addFile("/tmp", "data.cpp", {"cc", "data.cpp", "-DNO_DEBUG"}); - auto compileCommands = database.getAllCompileCommands(); - ASSERT_THAT(compileCommands, Contains(IsCompileCommand("/tmp", + ASSERT_THAT(compileCommands, Contains(IsCompileCommand(temporaryDirectoryPath, "data.cpp", - std::vector<std::string>{"cc", "data.cpp", "-DNO_DEBUG"}))); + std::vector<std::string>{"cc", "data.cpp", "-DNO_DEBUG"}))); } -TEST(RefactoringCompilationDatabase, NoCompileCommandForFilePath) +TEST_F(RefactoringCompilationDatabase, NoCompileCommandForFilePath) { - RefactoringCompilationDatabase database; - database.addFile("/tmp", "data.cpp", {"cc", "data.cpp", "-DNO_DEBUG"}); - auto compileCommands = database.getAllCompileCommands(); - ASSERT_THAT(compileCommands, Not(Contains(IsCompileCommand("/tmp", + ASSERT_THAT(compileCommands, Not(Contains(IsCompileCommand(temporaryDirectoryPath, "data.cpp2", std::vector<std::string>{"cc", "data.cpp", "-DNO_DEBUG"})))); } -TEST(RefactoringCompilationDatabase, FilePaths) +TEST_F(RefactoringCompilationDatabase, FilePaths) { - RefactoringCompilationDatabase database; - database.addFile("/tmp", "data.cpp", {"cc", "data.cpp", "-DNO_DEBUG"}); - auto filePaths = database.getAllFiles(); - ASSERT_THAT(filePaths, Contains("/tmp/data.cpp")); + ASSERT_THAT(filePaths, Contains(temporarySourceFilePath)); +} + +void RefactoringCompilationDatabase::SetUp() +{ + database.addFile(temporaryDirectoryPath, "data.cpp", {"cc", "data.cpp", "-DNO_DEBUG"}); } } diff --git a/tests/unit/unittest/refactoringengine-test.cpp b/tests/unit/unittest/refactoringengine-test.cpp index 6efbebfb41..3226863d56 100644 --- a/tests/unit/unittest/refactoringengine-test.cpp +++ b/tests/unit/unittest/refactoringengine-test.cpp @@ -28,14 +28,18 @@ #include "mockrefactoringserver.h" #include "mockrefactoringclient.h" -#include <refactoringcompileroptionsbuilder.h> #include <refactoringengine.h> #include <requestsourcelocationforrenamingmessage.h> +#include <requestsourcerangesanddiagnosticsforquerymessage.h> #include <sourcelocationsforrenamingmessage.h> +#include <sourcerangesanddiagnosticsforquerymessage.h> +#include <cpptools/clangcompileroptionsbuilder.h> #include <cpptools/projectpart.h> +#include <utils/smallstringvector.h> + #include <QTextCursor> #include <QTextDocument> @@ -43,7 +47,7 @@ namespace { using testing::_; -using ClangRefactoring::RefactoringCompilerOptionsBuilder; +using CppTools::ClangCompilerOptionsBuilder; using ClangBackEnd::RequestSourceLocationsForRenamingMessage; @@ -66,7 +70,7 @@ protected: QTextCursor cursor{&textDocument}; QString qStringFilePath{QStringLiteral("/home/user/file.cpp")}; Utils::FileName filePath{Utils::FileName::fromString(qStringFilePath)}; - ClangBackEnd::FilePath clangBackEndFilePath{"/home/user", "file.cpp"}; + ClangBackEnd::FilePath clangBackEndFilePath{qStringFilePath}; SmallStringVector commandLine; CppTools::ProjectPart::Ptr projectPart; CppTools::ProjectFile projectFile{qStringFilePath, CppTools::ProjectFile::CXXSource}; @@ -97,6 +101,25 @@ TEST_F(RefactoringEngine, AfterSendRequestSourceLocationsForRenamingMessageIsUnu ASSERT_FALSE(engine.isUsable()); } +TEST_F(RefactoringEngine, EngineIsNotUsableForUnusableServer) +{ + ASSERT_FALSE(engine.isUsable()); +} + +TEST_F(RefactoringEngine, EngineIsUsableForUsableServer) +{ + mockRefactoringServer.setUsable(true); + + ASSERT_TRUE(engine.isUsable()); +} + +TEST_F(RefactoringEngine, ServerIsUsableForUsableEngine) +{ + engine.setUsable(true); + + ASSERT_TRUE(mockRefactoringServer.isUsable()); +} + RefactoringEngine::RefactoringEngine() : engine(mockRefactoringServer, mockRefactoringClient) { @@ -107,9 +130,12 @@ void RefactoringEngine::SetUp() projectPart = CppTools::ProjectPart::Ptr(new CppTools::ProjectPart); projectPart->files.push_back(projectFile); - commandLine = RefactoringCompilerOptionsBuilder::build(projectPart.data(), - projectFile.kind, - RefactoringCompilerOptionsBuilder::PchUsage::None); + commandLine = Utils::SmallStringVector(ClangCompilerOptionsBuilder::build( + projectPart.data(), + projectFile.kind, + CppTools::CompilerOptionsBuilder::PchUsage::None, + CLANG_VERSION, + CLANG_RESOURCE_DIR)); commandLine.push_back(qStringFilePath); } diff --git a/tests/unit/unittest/refactoringserver-test.cpp b/tests/unit/unittest/refactoringserver-test.cpp index 897a47d162..bfcb4c7324 100644 --- a/tests/unit/unittest/refactoringserver-test.cpp +++ b/tests/unit/unittest/refactoringserver-test.cpp @@ -26,37 +26,43 @@ #include "googletest.h" #include "mockrefactoringclient.h" +#include "sourcerangecontainer-matcher.h" #include <refactoringserver.h> #include <requestsourcelocationforrenamingmessage.h> +#include <requestsourcerangesanddiagnosticsforquerymessage.h> #include <sourcelocationsforrenamingmessage.h> +#include <sourcerangesanddiagnosticsforquerymessage.h> #include <sourcelocationscontainer.h> namespace { using testing::AllOf; using testing::Contains; +using testing::NiceMock; using testing::Pair; using testing::PrintToString; using testing::Property; using testing::_; +using ClangBackEnd::FilePath; using ClangBackEnd::RequestSourceLocationsForRenamingMessage; +using ClangBackEnd::RequestSourceRangesAndDiagnosticsForQueryMessage; using ClangBackEnd::SourceLocationsContainer; using ClangBackEnd::SourceLocationsForRenamingMessage; -using ClangBackEnd::FilePath; +using ClangBackEnd::SourceRangesAndDiagnosticsForQueryMessage; +using ClangBackEnd::SourceRangesContainer; +using ClangBackEnd::V2::FileContainer; MATCHER_P2(IsSourceLocation, line, column, - std::string(negation ? "isn't" : "is") - + ", line " + PrintToString(line) - + ", column " + PrintToString(column) + std::string(negation ? "isn't " : "is ") + + "(" + PrintToString(line) + + ", " + PrintToString(column) + + ")" ) { - if (arg.line() != uint(line) - || arg.column() != uint(column)) - return false; - - return true; + return arg.line() == uint(line) + && arg.column() == uint(column); } class RefactoringServer : public ::testing::Test @@ -65,11 +71,17 @@ class RefactoringServer : public ::testing::Test protected: ClangBackEnd::RefactoringServer refactoringServer; - MockRefactoringClient mockRefactoringClient; - + NiceMock<MockRefactoringClient> mockRefactoringClient; + Utils::SmallString sourceContent{"void f()\n {}"}; + FileContainer source{{TESTDATA_DIR, "query_simplefunction.cpp"}, + sourceContent.clone(), + {"cc", "query_simplefunction.cpp"}}; }; -TEST_F(RefactoringServer, RequestSourceLocationsForRenamingMessage) +using RefactoringServerSlowTest = RefactoringServer; +using RefactoringServerVerySlowTest = RefactoringServer; + +TEST_F(RefactoringServerSlowTest, RequestSourceLocationsForRenamingMessage) { RequestSourceLocationsForRenamingMessage requestSourceLocationsForRenamingMessage{{TESTDATA_DIR, "renamevariable.cpp"}, 1, @@ -77,22 +89,121 @@ TEST_F(RefactoringServer, RequestSourceLocationsForRenamingMessage) "int v;\n\nint x = v + 3;\n", {"cc", "renamevariable.cpp"}, 1}; - SourceLocationsForRenamingMessage sourceLocationsForRenamingMessage; EXPECT_CALL(mockRefactoringClient, sourceLocationsForRenamingMessage( - AllOf(Property(&SourceLocationsForRenamingMessage::symbolName, "v"), + AllOf(Property(&SourceLocationsForRenamingMessage::textDocumentRevision, 1), + Property(&SourceLocationsForRenamingMessage::symbolName, "v"), Property(&SourceLocationsForRenamingMessage::sourceLocations, AllOf(Property(&SourceLocationsContainer::sourceLocationContainers, AllOf(Contains(IsSourceLocation(1, 5)), Contains(IsSourceLocation(3, 9)))), - Property(&SourceLocationsContainer::filePathsForTestOnly, + Property(&SourceLocationsContainer::filePaths, Contains(Pair(_, FilePath(TESTDATA_DIR, "renamevariable.cpp"))))))))) .Times(1); refactoringServer.requestSourceLocationsForRenamingMessage(std::move(requestSourceLocationsForRenamingMessage)); } +TEST_F(RefactoringServerSlowTest, RequestSingleSourceRangesAndDiagnosticsForQueryMessage) +{ + RequestSourceRangesAndDiagnosticsForQueryMessage requestSourceRangesAndDiagnosticsForQueryMessage{"functionDecl()", + {source.clone()}, + {}}; + + EXPECT_CALL(mockRefactoringClient, + sourceRangesAndDiagnosticsForQueryMessage( + Property(&SourceRangesAndDiagnosticsForQueryMessage::sourceRanges, + Property(&SourceRangesContainer::sourceRangeWithTextContainers, + Contains(IsSourceRangeWithText(1, 1, 2, 4, sourceContent)))))) + .Times(1); + + refactoringServer.requestSourceRangesAndDiagnosticsForQueryMessage(std::move(requestSourceRangesAndDiagnosticsForQueryMessage)); +} + +TEST_F(RefactoringServerSlowTest, RequestSingleSourceRangesAndDiagnosticsWithUnsavedContentForQueryMessage) +{ + Utils::SmallString unsavedContent{"void f();"}; + FileContainer source{{TESTDATA_DIR, "query_simplefunction.cpp"}, + "#include \"query_simplefunction.h\"", + {"cc", "query_simplefunction.cpp"}}; + FileContainer unsaved{{TESTDATA_DIR, "query_simplefunction.h"}, + unsavedContent.clone(), + {}}; + RequestSourceRangesAndDiagnosticsForQueryMessage requestSourceRangesAndDiagnosticsForQueryMessage{"functionDecl()", + {source.clone()}, + {unsaved.clone()}}; + + EXPECT_CALL(mockRefactoringClient, + sourceRangesAndDiagnosticsForQueryMessage( + Property(&SourceRangesAndDiagnosticsForQueryMessage::sourceRanges, + Property(&SourceRangesContainer::sourceRangeWithTextContainers, + Contains(IsSourceRangeWithText(1, 1, 1, 9, unsavedContent)))))) + .Times(1); + + refactoringServer.requestSourceRangesAndDiagnosticsForQueryMessage(std::move(requestSourceRangesAndDiagnosticsForQueryMessage)); +} + +TEST_F(RefactoringServerSlowTest, RequestTwoSourceRangesAndDiagnosticsForQueryMessage) +{ + RequestSourceRangesAndDiagnosticsForQueryMessage requestSourceRangesAndDiagnosticsForQueryMessage{"functionDecl()", + {source.clone(), source.clone()}, + {}}; + + EXPECT_CALL(mockRefactoringClient, + sourceRangesAndDiagnosticsForQueryMessage( + Property(&SourceRangesAndDiagnosticsForQueryMessage::sourceRanges, + Property(&SourceRangesContainer::sourceRangeWithTextContainers, + Contains(IsSourceRangeWithText(1, 1, 2, 4, sourceContent)))))) + .Times(2); + + refactoringServer.requestSourceRangesAndDiagnosticsForQueryMessage(std::move(requestSourceRangesAndDiagnosticsForQueryMessage)); +} + +TEST_F(RefactoringServerVerySlowTest, RequestManySourceRangesAndDiagnosticsForQueryMessage) +{ + std::vector<FileContainer> sources; + std::fill_n(std::back_inserter(sources), + std::thread::hardware_concurrency() + 3, + source.clone()); + RequestSourceRangesAndDiagnosticsForQueryMessage requestSourceRangesAndDiagnosticsForQueryMessage{"functionDecl()", + std::move(sources), + {}}; + + EXPECT_CALL(mockRefactoringClient, + sourceRangesAndDiagnosticsForQueryMessage( + Property(&SourceRangesAndDiagnosticsForQueryMessage::sourceRanges, + Property(&SourceRangesContainer::sourceRangeWithTextContainers, + Contains(IsSourceRangeWithText(1, 1, 2, 4, sourceContent)))))) + .Times(std::thread::hardware_concurrency() + 3); + + refactoringServer.requestSourceRangesAndDiagnosticsForQueryMessage(std::move(requestSourceRangesAndDiagnosticsForQueryMessage)); +} + +TEST_F(RefactoringServer, CancelJobs) +{ + refactoringServer.cancel(); + + ASSERT_TRUE(refactoringServer.isCancelingJobs()); +} + +TEST_F(RefactoringServerVerySlowTest, PollEventLoopAsQueryIsRunning) +{ + std::vector<FileContainer> sources; + std::fill_n(std::back_inserter(sources), + std::thread::hardware_concurrency() + 3, + source.clone()); + RequestSourceRangesAndDiagnosticsForQueryMessage requestSourceRangesAndDiagnosticsForQueryMessage{"functionDecl()", + std::move(sources), + {}}; + bool eventLoopIsPolled = false; + refactoringServer.supersedePollEventLoop([&] () { eventLoopIsPolled = true; }); + + refactoringServer.requestSourceRangesAndDiagnosticsForQueryMessage(std::move(requestSourceRangesAndDiagnosticsForQueryMessage)); + + ASSERT_TRUE(eventLoopIsPolled); +} + void RefactoringServer::SetUp() { refactoringServer.setClient(&mockRefactoringClient); diff --git a/tests/unit/unittest/skippedsourceranges-test.cpp b/tests/unit/unittest/skippedsourceranges-test.cpp index 1e1d9d4ee6..fdf995ab84 100644 --- a/tests/unit/unittest/skippedsourceranges-test.cpp +++ b/tests/unit/unittest/skippedsourceranges-test.cpp @@ -126,7 +126,7 @@ TEST_F(SkippedSourceRanges, RangeWithZero) ASSERT_THAT(ranges, SizeIs(2)); } -TEST_F(SkippedSourceRanges, RangeOne) +TEST_F(SkippedSourceRanges, DISABLED_ON_WINDOWS(RangeOne)) { auto ranges = skippedSourceRanges.sourceRanges(); @@ -134,7 +134,7 @@ TEST_F(SkippedSourceRanges, RangeOne) ASSERT_THAT(ranges[0].end(), IsSourceLocation(filePath, 5, 7, 24)); } -TEST_F(SkippedSourceRanges, RangeTwo) +TEST_F(SkippedSourceRanges, DISABLED_ON_WINDOWS(RangeTwo)) { auto ranges = skippedSourceRanges.sourceRanges(); diff --git a/tests/unit/unittest/smallstring-benchmark.cpp b/tests/unit/unittest/smallstring-benchmark.cpp index 46b32cde0e..99bc27dded 100644 --- a/tests/unit/unittest/smallstring-benchmark.cpp +++ b/tests/unit/unittest/smallstring-benchmark.cpp @@ -29,10 +29,6 @@ #include <utils/smallstringvector.h> -#ifndef __cpp_constexpr -#define constexpr -#endif - namespace { Utils::SmallStringView createText(int size) diff --git a/tests/unit/unittest/smallstring-test.cpp b/tests/unit/unittest/smallstring-test.cpp index 4770ed2f99..29c4063542 100644 --- a/tests/unit/unittest/smallstring-test.cpp +++ b/tests/unit/unittest/smallstring-test.cpp @@ -31,12 +31,9 @@ #include <utils/smallstringio.h> #include <utils/smallstringvector.h> -#ifndef __cpp_constexpr -#define constexpr -#endif - using namespace ::testing; +using Utils::PathString; using Utils::SmallString; using Utils::SmallStringLiteral; using Utils::SmallStringView; @@ -105,6 +102,15 @@ TEST(SmallString, CreateFromSmallStringIterators) ASSERT_THAT(text, SmallString("this is very very very very very much text")); } +TEST(SmallString, CreateFromStringView) +{ + SmallStringView sourceText = "this is very very very very very much text"; + + SmallString text(sourceText); + + ASSERT_THAT(text, SmallString("this is very very very very very much text")); +} + TEST(SmallString, ShortSmallStringIsReference) { SmallString longText("very very very very very long text"); @@ -199,6 +205,15 @@ TEST(SmallString, CopyLongConstExpressionSmallStringIsLongSmallString) ASSERT_FALSE(longTextCopy.isShortString()); } +TEST(SmallString, ShortPathStringIsShortString) +{ + const char *rawText = "very very very very very very very very very very very long path which fits in the short memory"; + + PathString text(rawText); + + ASSERT_TRUE(text.isShortString()); +} + TEST(SmallString, SmallStringFromCharacterArrayIsReference) { const char longCString[] = "very very very very very very very very very very very long string"; @@ -317,6 +332,29 @@ TEST(SmallString, RBeginPlusOneIsEqualREndForSmallStringWidthSizeOne) ASSERT_THAT(beginPlusOne, Eq(text.rend())); } +TEST(SmallString, ConstRBeginIsEqualREndForEmptySmallString) +{ + const SmallString text; + + ASSERT_THAT(text.rbegin(), Eq(text.rend())); +} + +TEST(SmallString, ConstRBeginIsNotEqualREndForNonEmptySmallString) +{ + const SmallString text("x"); + + ASSERT_THAT(text.rbegin(), Ne(text.rend())); +} + +TEST(SmallString, ConstRBeginPlusOneIsEqualREndForSmallStringWidthSizeOne) +{ + const SmallString text("x"); + + auto beginPlusOne = text.rbegin() + 1l; + + ASSERT_THAT(beginPlusOne, Eq(text.rend())); +} + TEST(SmallString, ConstructorStandardString) { std::string stdStringText = "short string"; @@ -417,6 +455,15 @@ TEST(SmallString, SizeShortSmallString) ASSERT_THAT(size, 4); } +TEST(SmallString, SizeShortPathString) +{ + SmallString shortPath("very very very very very very very very very very very long path which fits in the short memory"); + + auto size = shortPath.size(); + + ASSERT_THAT(size, 95); +} + TEST(SmallString, SizeLongSmallString) { auto longText = SmallString::fromUtf8("very very very very very very very very very very very long string"); @@ -523,6 +570,15 @@ TEST(SmallString, AppendShortSmallString) ASSERT_THAT(text, SmallString("some text")); } +TEST(SmallString, AppendLongSmallStringToShortSmallString) +{ + SmallString text("some "); + + text.append(SmallString("very very very very very long string")); + + ASSERT_THAT(text, SmallString("some very very very very very long string")); +} + TEST(SmallString, AppendLongSmallString) { SmallString longText("some very very very very very very very very very very very long string"); @@ -564,6 +620,14 @@ TEST(SmallString, EqualSmallStringOperator) ASSERT_FALSE(SmallString("text") == SmallString("text2")); } +TEST(SmallString, EqualSmallStringOperatorWithDifferenceClassSizes) +{ + ASSERT_TRUE(SmallString() == PathString("")); + ASSERT_FALSE(SmallString() == PathString("text")); + ASSERT_TRUE(SmallString("text") == PathString("text")); + ASSERT_FALSE(SmallString("text") == PathString("text2")); +} + TEST(SmallString, EqualCStringArrayOperator) { ASSERT_TRUE(SmallString() == ""); @@ -630,6 +694,36 @@ TEST(SmallString, SmallerOperator) ASSERT_FALSE(SmallString("text") < SmallString("text")); } +TEST(SmallString, SmallerOperatorWithStringViewRight) +{ + ASSERT_TRUE(SmallString() < SmallStringView("text")); + ASSERT_TRUE(SmallString("some") < SmallStringView("text")); + ASSERT_TRUE(SmallString("text") < SmallStringView("texta")); + ASSERT_FALSE(SmallString("texta") < SmallStringView("text")); + ASSERT_FALSE(SmallString("text") < SmallStringView("some")); + ASSERT_FALSE(SmallString("text") < SmallStringView("text")); +} + +TEST(SmallString, SmallerOperatorWithStringViewLeft) +{ + ASSERT_TRUE(SmallStringView("") < SmallString("text")); + ASSERT_TRUE(SmallStringView("some") < SmallString("text")); + ASSERT_TRUE(SmallStringView("text") < SmallString("texta")); + ASSERT_FALSE(SmallStringView("texta") < SmallString("text")); + ASSERT_FALSE(SmallStringView("text") < SmallString("some")); + ASSERT_FALSE(SmallStringView("text") < SmallString("text")); +} + +TEST(SmallString, SmallerOperatorForDifferenceClassSizes) +{ + ASSERT_TRUE(SmallString() < PathString("text")); + ASSERT_TRUE(SmallString("some") < PathString("text")); + ASSERT_TRUE(SmallString("text") < PathString("texta")); + ASSERT_FALSE(SmallString("texta") < PathString("text")); + ASSERT_FALSE(SmallString("text") < PathString("some")); + ASSERT_FALSE(SmallString("text") < PathString("text")); +} + TEST(SmallString, IsEmpty) { ASSERT_FALSE(SmallString("text").isEmpty()); @@ -653,6 +747,15 @@ TEST(SmallString, Clear) ASSERT_TRUE(text.isEmpty()); } +TEST(SmallString, ReplaceWithCharacter) +{ + SmallString text("here is some text, here is some text, here is some text"); + + text.replace('s', 'x'); + + ASSERT_THAT(text, SmallString("here ix xome text, here ix xome text, here ix xome text")); +} + TEST(SmallString, ReplaceWithEqualSizedText) { SmallString text("here is some text"); @@ -783,25 +886,43 @@ TEST(SmallString, EndsWithSmallString) ASSERT_TRUE(text.endsWith('h')); } -TEST(SmallString, ReserveSmallerThanReference) +TEST(SmallString, ReserveSmallerThanShortStringCapacity) { SmallString text("text"); text.reserve(2); - ASSERT_THAT(text.capacity(), 30); + ASSERT_THAT(text.capacity(), AnyOf(30, 4)); } -TEST(SmallString, ReserveBiggerThanReference) +TEST(SmallString, ReserveSmallerThanReference) +{ + SmallString text("some very very very very very very very very very very very long string"); + + text.reserve(35); + + ASSERT_THAT(text.capacity(), 71); +} + +TEST(SmallString, ReserveBiggerThanShortStringCapacity) { SmallString text("text"); text.reserve(10); - ASSERT_THAT(text.capacity(), 30); + ASSERT_THAT(text.capacity(), AnyOf(30, 10)); } -TEST(SmallString, ReserveMuchBiggerThanReference) +TEST(SmallString, ReserveBiggerThanReference) +{ + SmallString text("some very very very very very very very very very very very long string"); + + text.reserve(35); + + ASSERT_THAT(text.capacity(), 71); +} + +TEST(SmallString, ReserveMuchBiggerThanShortStringCapacity) { SmallString text("text"); @@ -810,6 +931,24 @@ TEST(SmallString, ReserveMuchBiggerThanReference) ASSERT_THAT(text.capacity(), 100); } +TEST(SmallString, TextIsCopiedAfterReserveFromShortToLongString) +{ + SmallString text("text"); + + text.reserve(100); + + ASSERT_THAT(text, "text"); +} + +TEST(SmallString, TextIsCopiedAfterReserveReferenceToLongString) +{ + SmallString text("some very very very very very very very very very very very long string"); + + text.reserve(100); + + ASSERT_THAT(text, "some very very very very very very very very very very very long string"); +} + TEST(SmallString, ReserveSmallerThanShortSmallString) { SmallString text = SmallString::fromUtf8("text"); @@ -1027,3 +1166,93 @@ TEST(SmallString, ReplaceByPositionEqualSizedTexts) ASSERT_THAT(text, SmallString("this is very very very very very much text")); } +TEST(SmallString, CompareTextWithDifferentLineEndings) +{ + SmallString unixText("some \ntext"); + SmallString windowsText("some \n\rtext"); + + auto convertedText = windowsText.toCarriageReturnsStripped(); + + ASSERT_THAT(unixText, convertedText); +} + +TEST(SmallString, ConstSubscriptOperator) +{ + const SmallString text = {"some text"}; + + auto &&sign = text[5]; + + ASSERT_THAT(sign, 't'); +} + +TEST(SmallString, NonConstSubscriptOperator) +{ + SmallString text = {"some text"}; + + auto &&sign = text[5]; + + ASSERT_THAT(sign, 't'); +} + +TEST(SmallString, ManipulateConstSubscriptOperator) +{ + const SmallString text = {"some text"}; + auto &&sign = text[5]; + + sign = 'q'; + + ASSERT_THAT(text, SmallString{"some text"}); +} + +TEST(SmallString, ManipulateNonConstSubscriptOperator) +{ + char rawText[] = "some text"; + SmallString text{rawText}; + auto &&sign = text[5]; + + sign = 'q'; + + ASSERT_THAT(text, SmallString{"some qext"}); +} + +TEST(SmallString, EmptyInitializerListContent) +{ + SmallString text = {}; + + ASSERT_THAT(text, SmallString()); +} + +TEST(SmallString, EmptyInitializerListSize) +{ + SmallString text = {}; + + ASSERT_THAT(text, SizeIs(0)); +} + +TEST(SmallString, EmptyInitializerListNullTerminated) +{ + auto end = SmallString{{}}[0]; + + ASSERT_THAT(end, '\0'); +} + +TEST(SmallString, InitializerListContent) +{ + SmallString text = {"some", " ", "text"}; + + ASSERT_THAT(text, SmallString("some text")); +} + +TEST(SmallString, InitializerListSize) +{ + SmallString text = {"some", " ", "text"}; + + ASSERT_THAT(text, SizeIs(9)); +} + +TEST(SmallString, InitializerListNullTerminated) +{ + auto end = SmallString{"some", " ", "text"}[9]; + + ASSERT_THAT(end, '\0'); +} diff --git a/tests/unit/unittest/sourcelocation-test.cpp b/tests/unit/unittest/sourcelocation-test.cpp index 3c9cb640a3..59a981fe38 100644 --- a/tests/unit/unittest/sourcelocation-test.cpp +++ b/tests/unit/unittest/sourcelocation-test.cpp @@ -107,7 +107,7 @@ TEST_F(SourceLocation, Column) ASSERT_THAT(sourceLocation.column(), 1); } -TEST_F(SourceLocation, Offset) +TEST_F(SourceLocation, DISABLED_ON_WINDOWS(Offset)) { ASSERT_THAT(sourceLocation.offset(), 18); } diff --git a/tests/unit/unittest/sourcerange-test.cpp b/tests/unit/unittest/sourcerange-test.cpp index c50bb98dc2..2b20c4029d 100644 --- a/tests/unit/unittest/sourcerange-test.cpp +++ b/tests/unit/unittest/sourcerange-test.cpp @@ -143,7 +143,7 @@ TEST_F(SourceRange, Size) ASSERT_THAT(diagnostic.ranges().size(), 2); } -TEST_F(SourceRange, Start) +TEST_F(SourceRange, DISABLED_ON_WINDOWS(Start)) { ASSERT_THAT(sourceRange.start(), IsSourceLocation(Utf8StringLiteral("diagnostic_source_range.cpp"), 8u, @@ -151,7 +151,7 @@ TEST_F(SourceRange, Start) 43u)); } -TEST_F(SourceRange, End) +TEST_F(SourceRange, DISABLED_ON_WINDOWS(End)) { ASSERT_THAT(sourceRange.end(), IsSourceLocation(Utf8StringLiteral("diagnostic_source_range.cpp"), 8u, diff --git a/tests/unit/unittest/sourcerangecontainer-matcher.h b/tests/unit/unittest/sourcerangecontainer-matcher.h new file mode 100644 index 0000000000..3656b840d7 --- /dev/null +++ b/tests/unit/unittest/sourcerangecontainer-matcher.h @@ -0,0 +1,67 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#pragma once + +#include "googletest.h" + +using testing::PrintToString; + +namespace { + +MATCHER_P4(IsSourceRange, startLine, startColumn, endLine, endColumn, + std::string(negation ? "isn't" : "is") + + "[(" + PrintToString(startLine) + + ", " + PrintToString(startColumn) + + "), (" + PrintToString(endLine) + + ", " + PrintToString(endColumn) + + ")]" + ) +{ + return arg.start().line() == uint(startLine) + && arg.start().column() == uint(startColumn) + && arg.end().line() == uint(endLine) + && arg.end().column() == uint(endColumn); +} + +MATCHER_P5(IsSourceRangeWithText, startLine, startColumn, endLine, endColumn, text, + std::string(negation ? "isn't " : "is ") + + "((" + PrintToString(startLine) + + ", " + PrintToString(startColumn) + + "), (" + PrintToString(endLine) + + ", " + PrintToString(endColumn) + + "), " + PrintToString(text) + + ")" + ) +{ + return arg.start().line() == uint(startLine) + && arg.start().column() == uint(startColumn) + && arg.end().line() == uint(endLine) + && arg.end().column() == uint(endColumn) + && arg.text().toCarriageReturnsStripped() == text; + +} + +} diff --git a/tests/unit/unittest/sourcerangeextractor-test.cpp b/tests/unit/unittest/sourcerangeextractor-test.cpp new file mode 100644 index 0000000000..df527b4e62 --- /dev/null +++ b/tests/unit/unittest/sourcerangeextractor-test.cpp @@ -0,0 +1,193 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#include "googletest.h" +#include "testclangtool.h" + +#include <sourcerangeextractor.h> +#include <sourcerangescontainer.h> + +#if defined(__GNUC__) +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wunused-parameter" +#elif defined(_MSC_VER) +# pragma warning(push) +# pragma warning( disable : 4100 ) +#endif + +#include <clang/Basic/SourceManager.h> +#include <clang/Lex/Lexer.h> + +#if defined(__GNUC__) +# pragma GCC diagnostic pop +#elif defined(_MSC_VER) +# pragma warning(pop) +#endif + +using testing::Contains; +using ::testing::Eq; +using ::testing::StrEq; + +using ClangBackEnd::SourceRangeWithTextContainer; +using ClangBackEnd::SourceRangeExtractor; + +namespace { + +class SourceRangeExtractor : public ::testing::Test +{ +protected: + void SetUp() override; + void TearDown() override; + +protected: + TestClangTool clangTool{TESTDATA_DIR, "sourcerangeextractor_location.cpp", "", {"cc", "sourcerangeextractor_location.cpp"}}; + ClangBackEnd::SourceRangesContainer sourceRangesContainer; + const clang::SourceManager &sourceManager{clangTool.sourceManager()}; + ClangBackEnd::SourceRangeExtractor extractor{sourceManager, clangTool.languageOptions(), sourceRangesContainer}; + clang::SourceLocation startLocation = sourceManager.getLocForStartOfFile(sourceManager.getMainFileID()); + clang::SourceLocation endLocation = sourceManager.getLocForStartOfFile(sourceManager.getMainFileID()).getLocWithOffset(4); + clang::SourceRange sourceRange{startLocation, endLocation}; + clang::SourceRange extendedSourceRange{startLocation, endLocation.getLocWithOffset(5)}; +}; + +using SourceRangeExtractorSlowTest = SourceRangeExtractor; + +TEST_F(SourceRangeExtractorSlowTest, ExtractSourceRangeContainer) +{ + SourceRangeWithTextContainer sourceRangeContainer{1, 1, 1, 0, 1, 10, 9, Utils::SmallString("int value;")}; + + extractor.addSourceRange(sourceRange); + + ASSERT_THAT(extractor.sourceRangeWithTextContainers(), Contains(sourceRangeContainer)); +} + +TEST_F(SourceRangeExtractorSlowTest, ExtendedSourceRange) +{ + auto range = extractor.extendSourceRangeToLastTokenEnd(sourceRange); + + ASSERT_THAT(range, extendedSourceRange); +} + +TEST_F(SourceRangeExtractorSlowTest, FindStartOfLineInEmptyBuffer) +{ + clang::StringRef text = ""; + + auto found = ::SourceRangeExtractor::findStartOfLineInBuffer(text, 0); + + ASSERT_THAT(found, StrEq("")); +} + +TEST_F(SourceRangeExtractorSlowTest, FindStartOfLineInBufferInFirstLine) +{ + clang::StringRef text = "first line"; + + auto found = ::SourceRangeExtractor::findStartOfLineInBuffer(text, 5); + + ASSERT_THAT(found, StrEq("first line")); +} + +TEST_F(SourceRangeExtractorSlowTest, FindStartOfNewLineInBufferInSecondLine) +{ + clang::StringRef text = "first line\nsecond line"; + + auto found = ::SourceRangeExtractor::findStartOfLineInBuffer(text, 15); + + ASSERT_THAT(found, StrEq("second line")); +} + +TEST_F(SourceRangeExtractorSlowTest, FindStartOfCarriageReturnInBufferInSecondLine) +{ + clang::StringRef text = "first line\rsecond line"; + + auto found = ::SourceRangeExtractor::findStartOfLineInBuffer(text, 15); + + ASSERT_THAT(found, StrEq("second line")); +} + +TEST_F(SourceRangeExtractorSlowTest, FindStartOfNewLineCarriageReturnInBufferInSecondLine) +{ + clang::StringRef text = "first line\n\rsecond line"; + + auto found = ::SourceRangeExtractor::findStartOfLineInBuffer(text, 15); + + ASSERT_THAT(found, StrEq("second line")); +} + +TEST_F(SourceRangeExtractorSlowTest, FindEndOfLineInEmptyBuffer) +{ + clang::StringRef text = ""; + + auto found = ::SourceRangeExtractor::findEndOfLineInBuffer(text, 0); + + ASSERT_THAT(found, StrEq("")); +} + +TEST_F(SourceRangeExtractorSlowTest, FindEndOfLineInBuffer) +{ + clang::StringRef text = "first line"; + + auto found = ::SourceRangeExtractor::findEndOfLineInBuffer(text, 5); + + ASSERT_THAT(found, StrEq("")); +} + +TEST_F(SourceRangeExtractorSlowTest, FindEndOfLineInBufferInFirstLineWithNewLine) +{ + clang::StringRef text = "first line\nsecond line\nthird line"; + + auto found = ::SourceRangeExtractor::findEndOfLineInBuffer(text, 15); + + ASSERT_THAT(found, StrEq("\nthird line")); +} + +TEST_F(SourceRangeExtractorSlowTest, FindEndOfLineInBufferInFirstLineWithCarriageReturn) +{ + clang::StringRef text = "first line\rsecond line\rthird line"; + + auto found = ::SourceRangeExtractor::findEndOfLineInBuffer(text, 15); + + ASSERT_THAT(found, StrEq("\rthird line")); +} + +TEST_F(SourceRangeExtractorSlowTest, EpandText) +{ + clang::StringRef text = "first line\nsecond line\nthird line\nforth line"; + + auto expandedText = ::SourceRangeExtractor::getExpandedText(text, 15, 25); + + ASSERT_THAT(expandedText, StrEq("second line\nthird line")); +} + +void SourceRangeExtractor::SetUp() +{ + TestGlobal::setSourceManager(&sourceManager); +} + +void SourceRangeExtractor::TearDown() +{ + TestGlobal::setSourceManager(nullptr); +} +} + diff --git a/tests/unit/unittest/sqlitedatabasebackend-test.cpp b/tests/unit/unittest/sqlitedatabasebackend-test.cpp index 8cba32029a..99e443da30 100644 --- a/tests/unit/unittest/sqlitedatabasebackend-test.cpp +++ b/tests/unit/unittest/sqlitedatabasebackend-test.cpp @@ -43,6 +43,8 @@ protected: ::SqliteDatabaseBackend databaseBackend; }; +using SqliteDatabaseBackendSlowTest = SqliteDatabaseBackend; + TEST_F(SqliteDatabaseBackend, OpenAlreadyOpenDatabase) { ASSERT_THROW(databaseBackend.open(databaseFilePath), SqliteException); @@ -64,7 +66,7 @@ TEST_F(SqliteDatabaseBackend, DefaultJournalMode) ASSERT_THAT(databaseBackend.journalMode(), JournalMode::Delete); } -TEST_F(SqliteDatabaseBackend, WalJournalMode) +TEST_F(SqliteDatabaseBackendSlowTest, WalJournalMode) { databaseBackend.setJournalMode(JournalMode::Wal); diff --git a/tests/unit/unittest/stringcache-test.cpp b/tests/unit/unittest/stringcache-test.cpp new file mode 100644 index 0000000000..92a2be71a3 --- /dev/null +++ b/tests/unit/unittest/stringcache-test.cpp @@ -0,0 +1,128 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#include "googletest.h" + +#include <stringcache.h> + +#include <utils/smallstringio.h> + +namespace { + +using testing::ElementsAre; + +class StringCache : public testing::Test +{ +protected: + ClangBackEnd::StringCache<Utils::PathString> cache; + Utils::PathString filePath1{"/file/pathOne"}; + Utils::PathString filePath2{"/file/pathTwo"}; + Utils::PathString filePath3{"/file/pathThree"}; + Utils::PathString filePath4{"/file/pathFour"}; +}; + +TEST_F(StringCache, AddFilePath) +{ + auto id = cache.stringId(filePath1); + + ASSERT_THAT(id, 0); +} + +TEST_F(StringCache, AddSecondFilePath) +{ + cache.stringId(filePath1); + + auto id = cache.stringId(filePath2); + + ASSERT_THAT(id, 1); +} + +TEST_F(StringCache, AddDuplicateFilePath) +{ + cache.stringId(filePath1); + + auto id = cache.stringId(filePath1); + + ASSERT_THAT(id, 0); +} + +TEST_F(StringCache, AddDuplicateFilePathBetweenOtherEntries) +{ + cache.stringId(filePath1); + cache.stringId(filePath2); + cache.stringId(filePath3); + cache.stringId(filePath4); + + auto id = cache.stringId(filePath3); + + ASSERT_THAT(id, 2); +} + +TEST_F(StringCache, ThrowForGettingPathForNoEntry) +{ + EXPECT_ANY_THROW(cache.string(0)); +} + +TEST_F(StringCache, GetFilePathForIdWithOneEntry) +{ + cache.stringId(filePath1); + + auto filePath = cache.string(0); + + ASSERT_THAT(filePath, filePath1); +} + +TEST_F(StringCache, GetFilePathForIdWithSomeEntries) +{ + cache.stringId(filePath1); + cache.stringId(filePath2); + cache.stringId(filePath3); + cache.stringId(filePath4); + + auto filePath = cache.string(2); + + ASSERT_THAT(filePath, filePath3); +} + +TEST_F(StringCache, GetAllFilePaths) +{ + cache.stringId(filePath1); + cache.stringId(filePath2); + cache.stringId(filePath3); + cache.stringId(filePath4); + + const auto &filePaths = cache.strings({0, 1, 2, 3}); + + ASSERT_THAT(filePaths, ElementsAre(filePath1, filePath2, filePath3, filePath4)); +} + +TEST_F(StringCache, AddFilePaths) +{ + auto ids = cache.stringIds({filePath1, filePath2, filePath3, filePath4}); + + ASSERT_THAT(ids, ElementsAre(0, 1, 2, 3)); +} + +} diff --git a/tests/unit/unittest/symbolfinder-test.cpp b/tests/unit/unittest/symbolfinder-test.cpp index dfbde15bff..c32bed0baa 100644 --- a/tests/unit/unittest/symbolfinder-test.cpp +++ b/tests/unit/unittest/symbolfinder-test.cpp @@ -42,7 +42,7 @@ namespace { MATCHER_P2(IsSourceLocation, line, column, std::string(negation ? "isn't" : "is") - + ", line " + PrintToString(line) + + "line " + PrintToString(line) + ", column " + PrintToString(column) ) { @@ -68,7 +68,7 @@ TEST(SymbolFinder, FileContentFilePath) ASSERT_THAT(fileContent.filePath, toNativePath("/tmp/data.cpp")); } -TEST(SymbolFinder, FindName) +TEST(SymbolFinderSlowTest, FindName) { SymbolFinder finder(1, 5); finder.addFile(TESTDATA_DIR, "renamevariable.cpp", "int variable;", {"cc", "renamevariable.cpp"}); @@ -78,7 +78,7 @@ TEST(SymbolFinder, FindName) ASSERT_THAT(finder.takeSymbolName(), "variable"); } -TEST(SymbolFinder, FindNameInUnsavedFile) +TEST(SymbolFinderSlowTest, FindNameInUnsavedFile) { SymbolFinder finder(1, 5); finder.addFile(TESTDATA_DIR, "renamevariable.cpp", "int newVariable;", {"cc", "renamevariable.cpp"}); @@ -88,7 +88,7 @@ TEST(SymbolFinder, FindNameInUnsavedFile) ASSERT_THAT(finder.takeSymbolName(), "newVariable"); } -TEST(SymbolFinder, FindUsrs) +TEST(SymbolFinderSlowTest, FindUsrs) { SymbolFinder finder(1, 5); finder.addFile(TESTDATA_DIR, "renamevariable.cpp", "int variable;", {"cc", "renamevariable.cpp", "-std=c++14"}); @@ -98,7 +98,7 @@ TEST(SymbolFinder, FindUsrs) ASSERT_THAT(finder.unifiedSymbolResolutions().front(), StrEq("c:@variable")); } -TEST(SymbolFinder, VariableDeclarationSourceLocations) +TEST(SymbolFinderSlowTest, VariableDeclarationSourceLocations) { SymbolFinder finder(1, 5); finder.addFile(TESTDATA_DIR, "renamevariable.cpp", "", {"cc", "renamevariable.cpp", "-std=c++14"}); @@ -110,7 +110,7 @@ TEST(SymbolFinder, VariableDeclarationSourceLocations) Contains(IsSourceLocation(3, 9)))); } -TEST(SymbolFinder, VariableUsageSourceLocations) +TEST(SymbolFinderSlowTest, VariableUsageSourceLocations) { SymbolFinder finder(3, 9); finder.addFile(TESTDATA_DIR, "renamevariable.cpp", "", {"cc", "renamevariable.cpp", "-std=c++14"}); @@ -122,7 +122,7 @@ TEST(SymbolFinder, VariableUsageSourceLocations) Contains(IsSourceLocation(3, 9)))); } -TEST(SymbolFinder, TemplateMemberVariableDeclarationSourceLocations) +TEST(SymbolFinderSlowTest, TemplateMemberVariableDeclarationSourceLocations) { SymbolFinder finder(8, 18); finder.addFile(TESTDATA_DIR, "renamevariable.cpp", "", {"cc", "renamevariable.cpp", "-std=c++14"}); @@ -135,7 +135,7 @@ TEST(SymbolFinder, TemplateMemberVariableDeclarationSourceLocations) Contains(IsSourceLocation(18, 19)))); } -TEST(SymbolFinder, TemplateMemberVariableUsageSourceLocations) +TEST(SymbolFinderSlowTest, TemplateMemberVariableUsageSourceLocations) { SymbolFinder finder(15, 14); finder.addFile(TESTDATA_DIR, "renamevariable.cpp", "", {"cc", "renamevariable.cpp", "-std=c++14"}); @@ -148,7 +148,7 @@ TEST(SymbolFinder, TemplateMemberVariableUsageSourceLocations) Contains(IsSourceLocation(18, 19)))); } -TEST(SymbolFinder, TemplateMemberVariableUsageInLambdaSourceLocations) +TEST(SymbolFinderSlowTest, TemplateMemberVariableUsageInLambdaSourceLocations) { SymbolFinder finder(18, 19); finder.addFile(TESTDATA_DIR, "renamevariable.cpp", "", {"cc", "renamevariable.cpp", "-std=c++14"}); @@ -161,7 +161,7 @@ TEST(SymbolFinder, TemplateMemberVariableUsageInLambdaSourceLocations) Contains(IsSourceLocation(18, 19)))); } -TEST(SymbolFinder, CursorOverMacroDefintionSymbolName) +TEST(SymbolFinderSlowTest, CursorOverMacroDefintionSymbolName) { SymbolFinder finder(1, 9); finder.addFile(TESTDATA_DIR, "symbolfinder_macro.cpp", "", {"cc", "symbolfinder_macro.cpp"}); @@ -171,7 +171,7 @@ TEST(SymbolFinder, CursorOverMacroDefintionSymbolName) ASSERT_THAT(finder.takeSymbolName(), "Macro"); } -TEST(SymbolFinder, CursorOverMacroExpansionSymbolName) +TEST(SymbolFinderSlowTest, CursorOverMacroExpansionSymbolName) { SymbolFinder finder(10, 10); finder.addFile(TESTDATA_DIR, "symbolfinder_macro.cpp", "", {"cc", "symbolfinder_macro.cpp"}); @@ -181,7 +181,7 @@ TEST(SymbolFinder, CursorOverMacroExpansionSymbolName) ASSERT_THAT(finder.takeSymbolName(), "Macro"); } -TEST(SymbolFinder, FindMacroDefinition) +TEST(SymbolFinderSlowTest, FindMacroDefinition) { SymbolFinder finder(1, 9); finder.addFile(TESTDATA_DIR, "symbolfinder_macro.cpp", "", {"cc", "symbolfinder_macro.cpp"}); @@ -192,7 +192,7 @@ TEST(SymbolFinder, FindMacroDefinition) Contains(IsSourceLocation(1, 9))); } -TEST(SymbolFinder, FindMacroExpansion) +TEST(SymbolFinderSlowTest, FindMacroExpansion) { SymbolFinder finder(1, 9); finder.addFile(TESTDATA_DIR, "symbolfinder_macro.cpp", "", {"cc", "symbolfinder_macro.cpp"}); @@ -203,7 +203,7 @@ TEST(SymbolFinder, FindMacroExpansion) Contains(IsSourceLocation(5, 17))); } -TEST(SymbolFinder, DoNotFindUndedefinedMacroExpansion) +TEST(SymbolFinderSlowTest, DoNotFindUndedefinedMacroExpansion) { SymbolFinder finder(1, 9); finder.addFile(TESTDATA_DIR, "symbolfinder_macro.cpp", "", {"cc", "symbolfinder_macro.cpp"}); @@ -214,7 +214,7 @@ TEST(SymbolFinder, DoNotFindUndedefinedMacroExpansion) Not(Contains(IsSourceLocation(10, 10)))); } -TEST(SymbolFinder, FindMacroDefinitionFromMacroExpansion) +TEST(SymbolFinderSlowTest, FindMacroDefinitionFromMacroExpansion) { SymbolFinder finder(10, 10); finder.addFile(TESTDATA_DIR, "symbolfinder_macro.cpp", "", {"cc", "symbolfinder_macro.cpp"}); @@ -226,7 +226,7 @@ TEST(SymbolFinder, FindMacroDefinitionFromMacroExpansion) } -TEST(SymbolFinder, FindMacroExpansionBeforeMacroExpansionWithCursor) +TEST(SymbolFinderSlowTest, FindMacroExpansionBeforeMacroExpansionWithCursor) { SymbolFinder finder(12, 10); finder.addFile(TESTDATA_DIR, "symbolfinder_macro.cpp", "", {"cc", "symbolfinder_macro.cpp"}); @@ -237,7 +237,7 @@ TEST(SymbolFinder, FindMacroExpansionBeforeMacroExpansionWithCursor) Contains(IsSourceLocation(10, 10))); } -TEST(SymbolFinder, FindMacroExpansionAfterMacroExpansionWithCursor) +TEST(SymbolFinderSlowTest, FindMacroExpansionAfterMacroExpansionWithCursor) { SymbolFinder finder(10, 10); finder.addFile(TESTDATA_DIR, "symbolfinder_macro.cpp", "", {"cc", "symbolfinder_macro.cpp"}); diff --git a/tests/unit/unittest/testclangtool.cpp b/tests/unit/unittest/testclangtool.cpp new file mode 100644 index 0000000000..de41e42a81 --- /dev/null +++ b/tests/unit/unittest/testclangtool.cpp @@ -0,0 +1,53 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#include "testclangtool.h" + +TestClangTool::TestClangTool(std::string &&directory, + std::string &&fileName, + std::string &&content, + std::vector<std::string> &&commandLine) +{ + addFile(std::move(directory), std::move(fileName), std::move(content), std::move(commandLine)); + + auto clangTool = createTool(); + + clangTool.buildASTs(asts); +} + +const clang::ASTUnit *TestClangTool::ast() const +{ + return asts.front().get(); +} + +const clang::SourceManager &TestClangTool::sourceManager() const +{ + return ast()->getSourceManager(); +} + +const clang::LangOptions &TestClangTool::languageOptions() const +{ + return ast()->getLangOpts(); +} diff --git a/tests/unit/unittest/testclangtool.h b/tests/unit/unittest/testclangtool.h new file mode 100644 index 0000000000..f8ae0caf16 --- /dev/null +++ b/tests/unit/unittest/testclangtool.h @@ -0,0 +1,45 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#pragma once + +#include <clangtool.h> + +class TestClangTool : public ClangBackEnd::ClangTool +{ +public: + TestClangTool(std::string &&directory, + std::string &&fileName, + std::string &&content, + std::vector<std::string> &&commandLine); + + const clang::ASTUnit *ast() const; + const clang::SourceManager &sourceManager() const; + const clang::LangOptions &languageOptions() const; + +private: + std::vector<std::unique_ptr<clang::ASTUnit>> asts; +}; + diff --git a/tests/unit/unittest/testenvironment.h b/tests/unit/unittest/testenvironment.h new file mode 100644 index 0000000000..a071b45432 --- /dev/null +++ b/tests/unit/unittest/testenvironment.h @@ -0,0 +1,55 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#pragma once + +#include <environment.h> + +#include <QTemporaryDir> + +class TestEnvironment final : public ClangBackEnd::Environment +{ +public: + TestEnvironment() { + temporaryDirectory.setAutoRemove(true); + } + QString pchBuildDirectory() const override + { + return temporaryDirectory.path(); + } + + QString clangCompilerPath() const override + { + return QString::fromUtf8(CLANG_COMPILER_PATH); + } + + uint hardwareConcurrency() const + { + return 2; + } + +private: + QTemporaryDir temporaryDirectory; +}; diff --git a/tests/unit/unittest/translationunitupdater-test.cpp b/tests/unit/unittest/translationunitupdater-test.cpp index dd490cda98..b491018956 100644 --- a/tests/unit/unittest/translationunitupdater-test.cpp +++ b/tests/unit/unittest/translationunitupdater-test.cpp @@ -59,7 +59,9 @@ protected: Utf8String filePath = Utf8StringLiteral(TESTDATA_DIR"/translationunits.cpp"); }; -TEST_F(TranslationUnitUpdater, ParsesIfNeeded) +using TranslationUnitUpdaterSlowTest = TranslationUnitUpdater; + +TEST_F(TranslationUnitUpdaterSlowTest, ParsesIfNeeded) { ::TranslationUnitUpdater updater = createUpdater(createInput()); @@ -69,7 +71,7 @@ TEST_F(TranslationUnitUpdater, ParsesIfNeeded) ASSERT_FALSE(result.hasReparsed()); } -TEST_F(TranslationUnitUpdater, ReparsesIfNeeded) +TEST_F(TranslationUnitUpdaterSlowTest, ReparsesIfNeeded) { ::TranslationUnitUpdater updater = createUpdater(createInput(SetReparseNeeded)); @@ -78,7 +80,7 @@ TEST_F(TranslationUnitUpdater, ReparsesIfNeeded) ASSERT_TRUE(result.hasReparsed()); } -TEST_F(TranslationUnitUpdater, PropagatesTranslationUnitId) +TEST_F(TranslationUnitUpdaterSlowTest, PropagatesTranslationUnitId) { const Utf8String translationUnitId = Utf8StringLiteral("myId"); ::TranslationUnitUpdater updater = createUpdater(createInput(SetReparseNeeded), translationUnitId); @@ -88,7 +90,7 @@ TEST_F(TranslationUnitUpdater, PropagatesTranslationUnitId) ASSERT_THAT(result.translationUnitId, Eq(translationUnitId)); } -TEST_F(TranslationUnitUpdater, UpdatesParseTimePoint) +TEST_F(TranslationUnitUpdaterSlowTest, UpdatesParseTimePoint) { ::TranslationUnitUpdater updater = createUpdater(createInput()); const TimePoint now = Clock::now(); @@ -99,7 +101,7 @@ TEST_F(TranslationUnitUpdater, UpdatesParseTimePoint) ASSERT_THAT(result.parseTimePoint, Gt(now)); } -TEST_F(TranslationUnitUpdater, NotUpdatingParseTimePointForReparseOnly) +TEST_F(TranslationUnitUpdaterSlowTest, NotUpdatingParseTimePointForReparseOnly) { ::TranslationUnitUpdater updater = createUpdater(createInput()); TranslationUnitUpdateResult result = updater.update(::TranslationUnitUpdater::UpdateMode::AsNeeded); @@ -111,7 +113,7 @@ TEST_F(TranslationUnitUpdater, NotUpdatingParseTimePointForReparseOnly) ASSERT_FALSE(result.hasParsed()); } -TEST_F(TranslationUnitUpdater, UpdatesDependendOnFilesOnParse) +TEST_F(TranslationUnitUpdaterSlowTest, UpdatesDependendOnFilesOnParse) { ::TranslationUnitUpdater updater = createUpdater(createInput()); diff --git a/tests/unit/unittest/unittest.pro b/tests/unit/unittest/unittest.pro index aa4b560fb6..382df1df90 100644 --- a/tests/unit/unittest/unittest.pro +++ b/tests/unit/unittest/unittest.pro @@ -1,19 +1,17 @@ INCLUDEPATH += ../mockup +QT += core network testlib widgets +CONFIG += console c++14 testcase object_parallel_to_source +CONFIG -= app_bundle shared + include(gmock_dependency.pri) include(clang_dependency.pri) include(creator_dependency.pri) include(benchmark_dependency.pri) -QT += core network testlib widgets -CONFIG += console c++14 testcase object_parallel_to_source -CONFIG -= app_bundle - OBJECTS_DIR = $$OUT_PWD/obj # workaround for qmake bug in object_parallel_to_source -osx:QMAKE_CXXFLAGS = -stdlib=libc++ - -force_debug_info:QMAKE_CXXFLAGS += -fno-omit-frame-pointer +!msvc:force_debug_info:QMAKE_CXXFLAGS += -fno-omit-frame-pointer DEFINES += \ QT_RESTRICTED_CAST_FROM_ASCII \ @@ -24,17 +22,47 @@ msvc: QMAKE_CXXFLAGS_WARN_ON -= -w34100 # 'unreferenced formal parameter' in MAT win32:DEFINES += ECHOSERVER=\"R\\\"xxx($$OUT_PWD/../echo)xxx\\\"\" unix: DEFINES += ECHOSERVER=\"R\\\"xxx($$OUT_PWD/../echoserver/echo)xxx\\\"\" +linux { +QMAKE_LFLAGS_RELEASE = #disable optimization +QMAKE_LFLAGS += -fno-merge-debug-strings -fuse-ld=gold +CONFIG(release, debug|release):QMAKE_LFLAGS += -Wl,--strip-debug +} + +# create fake CppTools.json for the mime type definitions +dependencyList = "\"Dependencies\" : []" +cpptoolsjson.input = $$PWD/../../../src/plugins/cpptools/CppTools.json.in +cpptoolsjson.output = $$OUT_PWD/CppTools.json +QMAKE_SUBSTITUTES += cpptoolsjson +DEFINES += CPPTOOLS_JSON=\"R\\\"xxx($${cpptoolsjson.output})xxx\\\"\" + SOURCES += \ clientserverinprocess-test.cpp \ - clientserveroutsideprocess.cpp \ lineprefixer-test.cpp \ + cppprojectfilecategorizer-test.cpp \ + cppprojectinfogenerator-test.cpp \ + cppprojectpartchooser-test.cpp \ processevents-utilities.cpp \ + mimedatabase-utilities.cpp \ readandwritemessageblock-test.cpp \ sizedarray-test.cpp \ smallstring-test.cpp \ spydummy.cpp \ unittests-main.cpp \ - utf8-test.cpp + utf8-test.cpp \ + gtest-qt-printing.cpp \ + gtest-creator-printing.cpp \ + clientserveroutsideprocess-test.cpp \ + clangpathwatcher-test.cpp \ + projectparts-test.cpp \ + stringcache-test.cpp \ + changedfilepathcompressor-test.cpp \ + faketimer.cpp \ + pchgenerator-test.cpp \ + fakeprocess.cpp \ + pchmanagerclient-test.cpp \ + projectupdater-test.cpp \ + pchmanagerserver-test.cpp \ + pchmanagerclientserverinprocess-test.cpp \ !isEmpty(LIBCLANG_LIBS) { SOURCES += \ @@ -56,16 +84,12 @@ SOURCES += \ clangisdiagnosticrelatedtolocation-test.cpp \ clangjobqueue-test.cpp \ clangjobs-test.cpp \ - clangparsesupportivetranslationunitjobtest.cpp \ - clangreparsesupportivetranslationunitjobtest.cpp \ clangrequestdocumentannotationsjob-test.cpp \ - clangsupportivetranslationunitinitializertest.cpp \ clangstring-test.cpp \ clangtranslationunit-test.cpp \ clangtranslationunits-test.cpp \ clangupdatedocumentannotationsjob-test.cpp \ codecompletionsextractor-test.cpp \ - codecompletion-test.cpp \ completionchunkstotextconverter-test.cpp \ createtablesqlstatementbuilder-test.cpp \ cursor-test.cpp \ @@ -88,17 +112,28 @@ SOURCES += \ translationunitupdater-test.cpp \ unsavedfiles-test.cpp \ unsavedfile-test.cpp \ - utf8positionfromlinecolumn-test.cpp + utf8positionfromlinecolumn-test.cpp \ + clangparsesupportivetranslationunitjob-test.cpp \ + clangreparsesupportivetranslationunitjob-test.cpp \ + clangsupportivetranslationunitinitializer-test.cpp \ + codecompleter-test.cpp } !isEmpty(LIBTOOLING_LIBS) { SOURCES += \ + clangquery-test.cpp \ + clangqueryprojectfindfilter-test.cpp \ refactoringclientserverinprocess-test.cpp \ refactoringclient-test.cpp \ refactoringcompilationdatabase-test.cpp \ refactoringengine-test.cpp \ refactoringserver-test.cpp \ - symbolfinder-test.cpp + symbolfinder-test.cpp \ + sourcerangeextractor-test.cpp \ + gtest-clang-printing.cpp \ + testclangtool.cpp \ + includecollector-test.cpp \ + pchcreator-test.cpp } exists($$GOOGLEBENCHMARK_DIR) { @@ -111,24 +146,48 @@ HEADERS += \ googletest.h \ gtest-qt-printing.h \ processevents-utilities.h \ - spydummy.h + mimedatabase-utilities.h \ + spydummy.h \ + sourcerangecontainer-matcher.h \ + dynamicastmatcherdiagnosticcontainer-matcher.h \ + mocksearchresult.h \ + mocksearch.h \ + mocksearchhandle.h \ + compare-operators.h \ + gtest-creator-printing.h \ + conditionally-disabled-tests.h \ + mockqfilesystemwatcher.h \ + mockclangpathwatcher.h \ + mockprojectparts.h \ + mockclangpathwatchernotifier.h \ + mockchangedfilepathcompressor.h \ + faketimer.h \ + mockpchgeneratornotifier.h \ + fakeprocess.h \ + mockpchmanagerserver.h \ + mockpchmanagerclient.h \ + testenvironment.h \ + mockpchmanagernotifier.h \ + mockpchcreator.h \ + dummyclangipcclient.h \ + mockclangcodemodelclient.h \ + mockclangcodemodelserver.h !isEmpty(LIBCLANG_LIBS) { HEADERS += \ chunksreportedmonitor.h \ clangasyncjob-base.h \ diagnosticcontainer-matcher.h \ - clangcompareoperators.h \ - dummyclangipcclient.h \ - mockclangcodemodelclient.h \ - mockclangcodemodelserver.h + clangcompareoperators.h } !isEmpty(LIBTOOLING_LIBS) { HEADERS += \ mockrefactoringclientcallback.h \ mockrefactoringclient.h \ - mockrefactoringserver.h + mockrefactoringserver.h \ + gtest-clang-printing.h \ + testclangtool.h } OTHER_FILES += $$files(data/*) diff --git a/tests/unit/unittest/unittests-main.cpp b/tests/unit/unittest/unittests-main.cpp index 0e6d913165..3229a4e252 100644 --- a/tests/unit/unittest/unittests-main.cpp +++ b/tests/unit/unittest/unittests-main.cpp @@ -25,6 +25,8 @@ #include <sqliteglobal.h> +#include <utils/temporarydirectory.h> + #include <QCoreApplication> #include <QLoggingCategory> @@ -37,6 +39,11 @@ int main(int argc, char *argv[]) { + const QString temporayDirectoryPath = QDir::tempPath() +"/QtCreator-UnitTests-XXXXXX"; + Utils::TemporaryDirectory::setMasterTemporaryDirectory(temporayDirectoryPath); + qputenv("TMPDIR", Utils::TemporaryDirectory::masterDirectoryPath().toUtf8()); + qputenv("TEMP", Utils::TemporaryDirectory::masterDirectoryPath().toUtf8()); + Sqlite::registerTypes(); QCoreApplication application(argc, argv); |