diff options
Diffstat (limited to 'tests')
69 files changed, 3408 insertions, 855 deletions
diff --git a/tests/auto/algorithm/tst_algorithm.cpp b/tests/auto/algorithm/tst_algorithm.cpp index 9eabd58557..5f2eaf23e2 100644 --- a/tests/auto/algorithm/tst_algorithm.cpp +++ b/tests/auto/algorithm/tst_algorithm.cpp @@ -145,8 +145,7 @@ void tst_Algorithm::transform() Utils::sort(i2); QCOMPARE(i2, QList<int>({1, 3, 132})); QList<qsizetype> i3 = Utils::transform<QList>(strings, &QString::size); - Utils::sort(i3); - QCOMPARE(i3, QList<qsizetype>({1, 1, 3})); + QCOMPARE(Utils::sorted(i3), QList<qsizetype>({1, 1, 3})); } { const QList<Struct> list({4, 3, 2, 1, 2}); @@ -421,13 +420,11 @@ void tst_Algorithm::sort() // member function with pointers QList<QString> arr1({"12345", "3333", "22"}); QList<QString *> s5({&arr1[0], &arr1[1], &arr1[2]}); - Utils::sort(s5, &QString::size); - QCOMPARE(s5, QList<QString *>({&arr1[2], &arr1[1], &arr1[0]})); + QCOMPARE(Utils::sorted(s5, &QString::size), QList<QString *>({&arr1[2], &arr1[1], &arr1[0]})); // member with pointers QList<Struct> arr2({4, 1, 3}); QList<Struct *> s6({&arr2[0], &arr2[1], &arr2[2]}); - Utils::sort(s6, &Struct::member); - QCOMPARE(s6, QList<Struct *>({&arr2[1], &arr2[2], &arr2[0]})); + QCOMPARE(Utils::sorted(s6, &Struct::member), QList<Struct *>({&arr2[1], &arr2[2], &arr2[0]})); // std::array: std::array<int, 4> array = {{4, 10, 8, 1}}; Utils::sort(array); diff --git a/tests/auto/cplusplus/c99/CMakeLists.txt b/tests/auto/cplusplus/c99/CMakeLists.txt index e7329dab5f..a2185b45ae 100644 --- a/tests/auto/cplusplus/c99/CMakeLists.txt +++ b/tests/auto/cplusplus/c99/CMakeLists.txt @@ -1,4 +1,4 @@ add_qtc_test(tst_cplusplus_c99 - DEPENDS CppEditor + DEPENDS CppEditor Utils SOURCES tst_c99.cpp ) diff --git a/tests/auto/cplusplus/c99/tst_c99.cpp b/tests/auto/cplusplus/c99/tst_c99.cpp index a5f80619de..029e54933a 100644 --- a/tests/auto/cplusplus/c99/tst_c99.cpp +++ b/tests/auto/cplusplus/c99/tst_c99.cpp @@ -73,7 +73,7 @@ class tst_c99: public QObject Document::Ptr document(const QString &fileName, QByteArray *errors = 0) { - Document::Ptr doc = Document::create(fileName); + Document::Ptr doc = Document::create(Utils::FilePath::fromString(fileName)); QFile file(testdata(fileName)); if (file.open(QFile::ReadOnly)) { LanguageFeatures features; diff --git a/tests/auto/cplusplus/checksymbols/CMakeLists.txt b/tests/auto/cplusplus/checksymbols/CMakeLists.txt index 18ced5c658..0dc5517c9c 100644 --- a/tests/auto/cplusplus/checksymbols/CMakeLists.txt +++ b/tests/auto/cplusplus/checksymbols/CMakeLists.txt @@ -1,4 +1,4 @@ add_qtc_test(tst_cplusplus_checksymbols - DEPENDS CppEditor ProjectExplorer TextEditor + DEPENDS CppEditor ProjectExplorer TextEditor Utils SOURCES tst_checksymbols.cpp ) diff --git a/tests/auto/cplusplus/checksymbols/tst_checksymbols.cpp b/tests/auto/cplusplus/checksymbols/tst_checksymbols.cpp index 8f2e17ddb7..314b0570f1 100644 --- a/tests/auto/cplusplus/checksymbols/tst_checksymbols.cpp +++ b/tests/auto/cplusplus/checksymbols/tst_checksymbols.cpp @@ -9,8 +9,11 @@ #include <cppeditor/cppchecksymbols.h> #include <cppeditor/cppsemanticinfo.h> #include <cppeditor/cpptoolstestcase.h> + #include <texteditor/semantichighlighter.h> +#include <utils/filepath.h> + #include <QDebug> #include <QDir> #include <QList> @@ -26,6 +29,7 @@ enum { enableListing = 0 }; using namespace CPlusPlus; using namespace CppEditor; +using namespace Utils; typedef QByteArray _; typedef CheckSymbols::Result Use; @@ -89,7 +93,7 @@ public: { // Write source to temporary file const QString filePath = QDir::tempPath() + QLatin1String("/file.h"); - Tests::TestCase::writeFile(filePath, source); + Tests::TestCase::writeFile(FilePath::fromString(filePath), source); // Process source const Document::Ptr document = createDocument(filePath, source); @@ -112,12 +116,12 @@ public: static Document::Ptr createDocument(const QString &filePath, const QByteArray &source) { - Environment env; + CPlusPlus::Environment env; Preprocessor preprocess(0, &env); preprocess.setKeepComments(true); const QByteArray preprocessedSource = preprocess.run(filePath, source); - Document::Ptr document = Document::create(filePath); + Document::Ptr document = Document::create(Utils::FilePath::fromString(filePath)); document->setUtf8Source(preprocessedSource); if (!document->parse()) return Document::Ptr(); @@ -1142,16 +1146,16 @@ void tst_CheckSymbols::test_checksymbols_infiniteLoop() QFETCH(QByteArray, source2); const QString filePath1 = QDir::tempPath() + QLatin1String("/file1.h"); - Tests::TestCase::writeFile(filePath1, source1); + Tests::TestCase::writeFile(FilePath::fromString(filePath1), source1); - const QString filePath2 = QDir::tempPath() + QLatin1String("/file2.h"); + const FilePath filePath2 = FilePath::fromString(QDir::tempPath()) / "/file2.h"; Tests::TestCase::writeFile(filePath2, source2); const Document::Ptr document1 = TestCase::createDocument(filePath1, source1); document1->addIncludeFile(Document::Include("file2.h", filePath2, 1, Client::IncludeLocal)); Snapshot snapshot; snapshot.insert(document1); - snapshot.insert(TestCase::createDocument(filePath2, source2)); + snapshot.insert(TestCase::createDocument(filePath2.toString(), source2)); TestCase::runCheckSymbols(document1, snapshot); } diff --git a/tests/auto/cplusplus/cppselectionchanger/CMakeLists.txt b/tests/auto/cplusplus/cppselectionchanger/CMakeLists.txt index c1af242bf4..64a5bfe767 100644 --- a/tests/auto/cplusplus/cppselectionchanger/CMakeLists.txt +++ b/tests/auto/cplusplus/cppselectionchanger/CMakeLists.txt @@ -1,4 +1,4 @@ add_qtc_test(tst_cplusplus_cppselectionchangertest - DEPENDS CppEditor + DEPENDS CppEditor Utils SOURCES tst_cppselectionchangertest.cpp ) diff --git a/tests/auto/cplusplus/cppselectionchanger/tst_cppselectionchangertest.cpp b/tests/auto/cplusplus/cppselectionchanger/tst_cppselectionchangertest.cpp index 5b098c136e..1d690da849 100644 --- a/tests/auto/cplusplus/cppselectionchanger/tst_cppselectionchangertest.cpp +++ b/tests/auto/cplusplus/cppselectionchanger/tst_cppselectionchangertest.cpp @@ -9,11 +9,14 @@ #include <cplusplus/TranslationUnit.h> #include <cplusplus/pp-engine.h> +#include <utils/filepath.h> + #include <QtTest> #include <QTextDocument> using namespace CPlusPlus; using namespace CppEditor; +using namespace Utils; //TESTED_COMPONENT=src/plugins/cppeditor @@ -175,7 +178,7 @@ inline void tst_CppSelectionChanger::doShrink(QTextCursor& cursor, const QString QByteArray tst_CppSelectionChanger::preprocess(const QByteArray &source, const QString &fileName) { Client *client = 0; // no client. - Environment env; + CPlusPlus::Environment env; Preprocessor preprocess(client, &env); preprocess.setKeepComments(true); return preprocess.run(fileName, source); @@ -193,7 +196,7 @@ void tst_CppSelectionChanger::initTestCase() textDocument.setPlainText(cppFileString); // Create the CPP document and preprocess the source, just like how the CppEditor does it. - cppDocument = Document::create(fileName); + cppDocument = Document::create(FilePath::fromString(fileName)); const QByteArray preprocessedSource = preprocess(cppFileString.toUtf8(), fileName); cppDocument->setUtf8Source(preprocessedSource); cppDocument->parse(); diff --git a/tests/auto/cplusplus/cxx11/CMakeLists.txt b/tests/auto/cplusplus/cxx11/CMakeLists.txt index f5de369232..b72c9c5aa8 100644 --- a/tests/auto/cplusplus/cxx11/CMakeLists.txt +++ b/tests/auto/cplusplus/cxx11/CMakeLists.txt @@ -1,4 +1,4 @@ add_qtc_test(tst_cplusplus_cxx11 - DEPENDS CppEditor + DEPENDS CppEditor Utils SOURCES tst_cxx11.cpp ) diff --git a/tests/auto/cplusplus/cxx11/data/defaultdeleteInitializer.1.cpp b/tests/auto/cplusplus/cxx11/data/defaultdeleteInitializer.1.cpp index 7ec9e9b91e..8db6ea2b1d 100644 --- a/tests/auto/cplusplus/cxx11/data/defaultdeleteInitializer.1.cpp +++ b/tests/auto/cplusplus/cxx11/data/defaultdeleteInitializer.1.cpp @@ -1,8 +1,10 @@ class C { - C() = default; + C(); C(const C &) = delete; C &operator=(const C &) = default; void foo() = delete; template <class T> void bar(T) = delete; }; + +C::C() = default; diff --git a/tests/auto/cplusplus/cxx11/tst_cxx11.cpp b/tests/auto/cplusplus/cxx11/tst_cxx11.cpp index 7630bc56b1..797d20e756 100644 --- a/tests/auto/cplusplus/cxx11/tst_cxx11.cpp +++ b/tests/auto/cplusplus/cxx11/tst_cxx11.cpp @@ -12,6 +12,7 @@ //TESTED_COMPONENT=src/libs/cplusplus using namespace CPlusPlus; +using namespace Utils; #define VERIFY_ERRORS() \ do { \ @@ -113,7 +114,7 @@ class tst_cxx11: public QObject Document::Ptr document(const QString &fileName, QByteArray *errors = 0, bool c99Enabled = false) { - Document::Ptr doc = Document::create(fileName); + Document::Ptr doc = Document::create(FilePath::fromString(fileName)); QFile file(testdata(fileName)); if (file.open(QFile::ReadOnly)) { LanguageFeatures features; @@ -274,7 +275,7 @@ void tst_cxx11::lambdaType() features.cxxEnabled = true; QByteArray errors; - Document::Ptr doc = Document::create(QLatin1String("testFile")); + Document::Ptr doc = Document::create(FilePath::fromPathPart(u"testFile")); processDocument(doc, source.toUtf8(), features, &errors); const bool hasErrors = !errors.isEmpty(); diff --git a/tests/auto/cplusplus/fileiterationorder/CMakeLists.txt b/tests/auto/cplusplus/fileiterationorder/CMakeLists.txt index 27ed533a77..12591f9606 100644 --- a/tests/auto/cplusplus/fileiterationorder/CMakeLists.txt +++ b/tests/auto/cplusplus/fileiterationorder/CMakeLists.txt @@ -1,4 +1,4 @@ add_qtc_test(tst_cplusplus_fileiterationorder - DEPENDS CppEditor + DEPENDS CppEditor Utils SOURCES tst_fileiterationorder.cpp ) diff --git a/tests/auto/cplusplus/findusages/tst_findusages.cpp b/tests/auto/cplusplus/findusages/tst_findusages.cpp index f7098283a0..21950ae193 100644 --- a/tests/auto/cplusplus/findusages/tst_findusages.cpp +++ b/tests/auto/cplusplus/findusages/tst_findusages.cpp @@ -47,6 +47,8 @@ private: const char *_name; }; +const Usage::Tags Initialization{Usage::Tag::Declaration, Usage::Tag::Write}; + class tst_FindUsages: public QObject { Q_OBJECT @@ -114,13 +116,15 @@ private Q_SLOTS: void variadicMacros(); void writableRefs(); + void mocInvokables(); + void virtualOverride(); }; void tst_FindUsages::dump(const QList<Usage> &usages) const { QTextStream err(stderr, QIODevice::WriteOnly); err << "DEBUG : " << usages.size() << " usages:" << Qt::endl; - foreach (const Usage &usage, usages) { + for (const Usage &usage : usages) { err << "DEBUG : " << usage.path << ":" << usage.line << ":" << usage.col << ":" << usage.len << ":" << usage.lineText << Qt::endl; } @@ -158,8 +162,8 @@ void tst_FindUsages::inlineMethod() FindUsages findUsages(src, doc, snapshot, true); findUsages(arg); QCOMPARE(findUsages.usages().size(), 2); - QCOMPARE(findUsages.usages().at(0).type, Usage::Type::Declaration); - QCOMPARE(findUsages.usages().at(1).type, Usage::Type::Read); + QCOMPARE(findUsages.usages().at(0).tags, Usage::Tag::Declaration); + QCOMPARE(findUsages.usages().at(1).tags, Usage::Tag::Read); QCOMPARE(findUsages.references().size(), 2); } @@ -193,9 +197,9 @@ void tst_FindUsages::lambdaCaptureByValue() FindUsages findUsages(src, doc, snapshot, true); findUsages(d); QCOMPARE(findUsages.usages().size(), 3); - QCOMPARE(findUsages.usages().at(0).type, Usage::Type::Declaration); - QCOMPARE(findUsages.usages().at(1).type, Usage::Type::Other); - QCOMPARE(findUsages.usages().at(2).type, Usage::Type::Read); + QCOMPARE(findUsages.usages().at(0).tags, Usage::Tag::Declaration); + QCOMPARE(findUsages.usages().at(1).tags, Usage::Tags()); + QCOMPARE(findUsages.usages().at(2).tags, Usage::Tag::Read); } void tst_FindUsages::lambdaCaptureByReference() @@ -228,10 +232,10 @@ void tst_FindUsages::lambdaCaptureByReference() FindUsages findUsages(src, doc, snapshot, true); findUsages(d); QCOMPARE(findUsages.usages().size(), 3); - QCOMPARE(findUsages.usages().at(0).type, Usage::Type::Declaration); - QCOMPARE(findUsages.usages().at(1).type, Usage::Type::Other); + QCOMPARE(findUsages.usages().at(0).tags, Usage::Tag::Declaration); + QCOMPARE(findUsages.usages().at(1).tags, Usage::Tags()); QEXPECT_FAIL(nullptr, "parser does not record capture type", Continue); - QCOMPARE(findUsages.usages().at(2).type, Usage::Type::Write); + QCOMPARE(findUsages.usages().at(2).tags, Usage::Tag::Write); } void tst_FindUsages::shadowedNames_1() @@ -262,8 +266,8 @@ void tst_FindUsages::shadowedNames_1() FindUsages findUsages(src, doc, snapshot, true); findUsages(d); QCOMPARE(findUsages.usages().size(), 2); - QCOMPARE(findUsages.usages().at(0).type, Usage::Type::Declaration); - QCOMPARE(findUsages.usages().at(1).type, Usage::Type::Other); + QCOMPARE(findUsages.usages().at(0).tags, Usage::Tag::Declaration); + QCOMPARE(findUsages.usages().at(1).tags, Usage::Tags()); } void tst_FindUsages::shadowedNames_2() @@ -297,9 +301,9 @@ void tst_FindUsages::shadowedNames_2() FindUsages findUsages(src, doc, snapshot, true); findUsages(d); QCOMPARE(findUsages.usages().size(), 3); - QCOMPARE(findUsages.usages().at(0).type, Usage::Type::Declaration); - QCOMPARE(findUsages.usages().at(1).type, Usage::Type::Declaration); - QCOMPARE(findUsages.usages().at(2).type, Usage::Type::Other); + QCOMPARE(findUsages.usages().at(0).tags, Usage::Tag::Declaration); + QCOMPARE(findUsages.usages().at(1).tags, Usage::Tag::Declaration); + QCOMPARE(findUsages.usages().at(2).tags, Usage::Tags()); } void tst_FindUsages::staticVariables() @@ -346,11 +350,11 @@ void tst_FindUsages::staticVariables() FindUsages findUsages(src, doc, snapshot, true); findUsages(d); QCOMPARE(findUsages.usages().size(), 5); - QCOMPARE(findUsages.usages().at(0).type, Usage::Type::Declaration); - QCOMPARE(findUsages.usages().at(1).type, Usage::Type::Initialization); - QCOMPARE(findUsages.usages().at(2).type, Usage::Type::Write); - QCOMPARE(findUsages.usages().at(3).type, Usage::Type::Write); - QCOMPARE(findUsages.usages().at(4).type, Usage::Type::Write); + QCOMPARE(findUsages.usages().at(0).tags, Usage::Tag::Declaration); + QCOMPARE(findUsages.usages().at(1).tags, Initialization); + QCOMPARE(findUsages.usages().at(2).tags, Usage::Tag::Write); + QCOMPARE(findUsages.usages().at(3).tags, Usage::Tag::Write); + QCOMPARE(findUsages.usages().at(4).tags, Usage::Tag::Write); } void tst_FindUsages::structuredBinding() @@ -380,13 +384,13 @@ void tst_FindUsages::structuredBinding() FindUsages findUsages(src, doc, snapshot, true); findUsages(d1); QCOMPARE(findUsages.usages().size(), 2); - QCOMPARE(findUsages.usages().at(0).type, Usage::Type::Initialization); - QCOMPARE(findUsages.usages().at(1).type, Usage::Type::Read); + QCOMPARE(findUsages.usages().at(0).tags, Initialization); + QCOMPARE(findUsages.usages().at(1).tags, Usage::Tag::Read); findUsages(d2); QCOMPARE(findUsages.usages().size(), 2); - QCOMPARE(findUsages.usages().at(0).type, Usage::Type::Initialization); - QCOMPARE(findUsages.usages().at(1).type, Usage::Type::Read); + QCOMPARE(findUsages.usages().at(0).tags, Initialization); + QCOMPARE(findUsages.usages().at(1).tags, Usage::Tag::Read); } void tst_FindUsages::functionNameFoundInArguments() @@ -419,15 +423,15 @@ void foo2(int b=bar()){} // 3rd result QCOMPARE(find.usages().size(), 3); - QCOMPARE(find.usages()[0].type, Usage::Type::Declaration); + QCOMPARE(find.usages()[0].tags, Usage::Tag::Declaration); QCOMPARE(find.usages()[0].line, 1); QCOMPARE(find.usages()[0].col, 5); - QCOMPARE(find.usages()[1].type, Usage::Type::Other); + QCOMPARE(find.usages()[1].tags, Usage::Tags()); QCOMPARE(find.usages()[1].line, 4); QCOMPARE(find.usages()[1].col, 16); - QCOMPARE(find.usages()[2].type, Usage::Type::Other); + QCOMPARE(find.usages()[2].tags, Usage::Tags()); QCOMPARE(find.usages()[2].line, 5); QCOMPARE(find.usages()[2].col, 16); } @@ -486,22 +490,22 @@ struct Struct{ find(memberFunctionFoo); QCOMPARE(find.usages().size(), 2); - QCOMPARE(find.usages()[0].type, Usage::Type::Declaration); + QCOMPARE(find.usages()[0].tags, Usage::Tag::Declaration); QCOMPARE(find.usages()[0].line, 3); QCOMPARE(find.usages()[0].col, 15); - QCOMPARE(find.usages()[1].type, Usage::Type::Other); + QCOMPARE(find.usages()[1].tags, Usage::Tags()); QCOMPARE(find.usages()[1].line, 5); QCOMPARE(find.usages()[1].col, 24); find(variableFoo); QCOMPARE(find.usages().size(), 2); - QCOMPARE(find.usages()[0].type, Usage::Type::Initialization); + QCOMPARE(find.usages()[0].tags, Initialization); QCOMPARE(find.usages()[0].line, 5); QCOMPARE(find.usages()[0].col, 12); - QCOMPARE(find.usages()[1].type, Usage::Type::Read); + QCOMPARE(find.usages()[1].tags, Usage::Tag::Read); QCOMPARE(find.usages()[1].line, 6); QCOMPARE(find.usages()[1].col, 22); } @@ -558,13 +562,13 @@ int main() { FindUsages find(src, doc, snapshot, true); find(sv); QCOMPARE(find.usages().size(), 7); - QCOMPARE(find.usages().at(0).type, Usage::Type::Declaration); - QCOMPARE(find.usages().at(1).type, Usage::Type::Read); - QCOMPARE(find.usages().at(2).type, Usage::Type::Read); - QCOMPARE(find.usages().at(3).type, Usage::Type::Read); - QCOMPARE(find.usages().at(4).type, Usage::Type::Read); - QCOMPARE(find.usages().at(5).type, Usage::Type::Read); - QCOMPARE(find.usages().at(6).type, Usage::Type::Read); + QCOMPARE(find.usages().at(0).tags, Usage::Tag::Declaration); + QCOMPARE(find.usages().at(1).tags, Usage::Tag::Read); + QCOMPARE(find.usages().at(2).tags, Usage::Tag::Read); + QCOMPARE(find.usages().at(3).tags, Usage::Tag::Read); + QCOMPARE(find.usages().at(4).tags, Usage::Tag::Read); + QCOMPARE(find.usages().at(5).tags, Usage::Tag::Read); + QCOMPARE(find.usages().at(6).tags, Usage::Tag::Read); } void tst_FindUsages::templateConstructorVsCallOperator() @@ -617,13 +621,13 @@ int main() FindUsages find(src, doc, snapshot, true); find(sv); QCOMPARE(find.usages().size(), 7); - QCOMPARE(find.usages().at(0).type, Usage::Type::Declaration); - QCOMPARE(find.usages().at(1).type, Usage::Type::Read); - QCOMPARE(find.usages().at(2).type, Usage::Type::Read); - QCOMPARE(find.usages().at(3).type, Usage::Type::Read); - QCOMPARE(find.usages().at(4).type, Usage::Type::Read); - QCOMPARE(find.usages().at(5).type, Usage::Type::Read); - QCOMPARE(find.usages().at(6).type, Usage::Type::Read); + QCOMPARE(find.usages().at(0).tags, Usage::Tag::Declaration); + QCOMPARE(find.usages().at(1).tags, Usage::Tag::Read); + QCOMPARE(find.usages().at(2).tags, Usage::Tag::Read); + QCOMPARE(find.usages().at(3).tags, Usage::Tag::Read); + QCOMPARE(find.usages().at(4).tags, Usage::Tag::Read); + QCOMPARE(find.usages().at(5).tags, Usage::Tag::Read); + QCOMPARE(find.usages().at(6).tags, Usage::Tag::Read); } #if 0 @@ -720,9 +724,18 @@ void tst_FindUsages::qproperty_1() FindUsages findUsages(src, doc, snapshot, true); findUsages(setX_method); QCOMPARE(findUsages.usages().size(), 2); - QCOMPARE(findUsages.usages().at(0).type, Usage::Type::Other); - QCOMPARE(findUsages.usages().at(1).type, Usage::Type::Declaration); - QCOMPARE(findUsages.references().size(), 2); + QCOMPARE(findUsages.usages().at(0).tags, Usage::Tags()); + QCOMPARE(findUsages.usages().at(1).tags, Usage::Tag::Declaration); + + Declaration *xChangedSignal = tst->memberAt(3)->asDeclaration(); + QVERIFY(xChangedSignal); + QCOMPARE(xChangedSignal->identifier()->chars(), "xChanged"); + findUsages(xChangedSignal); + QCOMPARE(findUsages.usages().size(), 3); + QCOMPARE(findUsages.usages().at(0).tags, Usage::Tags()); + QCOMPARE(findUsages.usages().at(1).tags, Usage::Tags()); + QCOMPARE(findUsages.usages().at(2).tags, + (Usage::Tags{Usage::Tag::Declaration, Usage::Tag::MocInvokable})); } void tst_FindUsages::instantiateTemplateWithNestedClass() @@ -766,8 +779,8 @@ void tst_FindUsages::instantiateTemplateWithNestedClass() FindUsages findUsages(src, doc, snapshot, true); findUsages(barDeclaration); QCOMPARE(findUsages.usages().size(), 2); - QCOMPARE(findUsages.usages().at(0).type, Usage::Type::Declaration); - QCOMPARE(findUsages.usages().at(1).type, Usage::Type::Read); + QCOMPARE(findUsages.usages().at(0).tags, Usage::Tag::Declaration); + QCOMPARE(findUsages.usages().at(1).tags, Usage::Tag::Read); } void tst_FindUsages::operatorAsteriskOfNestedClassOfTemplateClass_QTCREATORBUG9006() @@ -813,8 +826,8 @@ void tst_FindUsages::operatorAsteriskOfNestedClassOfTemplateClass_QTCREATORBUG90 findUsages(fooDeclaration); QCOMPARE(findUsages.usages().size(), 2); - QCOMPARE(findUsages.usages().at(0).type, Usage::Type::Declaration); - QCOMPARE(findUsages.usages().at(1).type, Usage::Type::Read); + QCOMPARE(findUsages.usages().at(0).tags, Usage::Tag::Declaration); + QCOMPARE(findUsages.usages().at(1).tags, Usage::Tag::Read); } void tst_FindUsages::anonymousClass_QTCREATORBUG8963() @@ -858,8 +871,8 @@ void tst_FindUsages::anonymousClass_QTCREATORBUG8963() findUsages(isNotIntDeclaration); QCOMPARE(findUsages.usages().size(), 2); - QCOMPARE(findUsages.usages().at(0).type, Usage::Type::Declaration); - QCOMPARE(findUsages.usages().at(1).type, Usage::Type::Read); + QCOMPARE(findUsages.usages().at(0).tags, Usage::Tag::Declaration); + QCOMPARE(findUsages.usages().at(1).tags, Usage::Tag::Read); } void tst_FindUsages::anonymousClass_QTCREATORBUG11859() @@ -901,12 +914,12 @@ void tst_FindUsages::anonymousClass_QTCREATORBUG11859() findUsages(fooAsStruct); QCOMPARE(findUsages.references().size(), 1); QCOMPARE(findUsages.usages().size(), 1); - QCOMPARE(findUsages.usages().first().type, Usage::Type::Declaration); + QCOMPARE(findUsages.usages().first().tags, Usage::Tag::Declaration); findUsages(fooAsMemberOfAnonymousStruct); QCOMPARE(findUsages.references().size(), 2); - QCOMPARE(findUsages.usages().at(0).type, Usage::Type::Declaration); - QCOMPARE(findUsages.usages().at(1).type, Usage::Type::Read); + QCOMPARE(findUsages.usages().at(0).tags, Usage::Tag::Declaration); + QCOMPARE(findUsages.usages().at(1).tags, Usage::Tag::Read); } void tst_FindUsages::using_insideGlobalNamespace() @@ -947,9 +960,9 @@ void tst_FindUsages::using_insideGlobalNamespace() findUsages(structSymbol); QCOMPARE(findUsages.usages().size(), 3); - QCOMPARE(findUsages.usages().at(0).type, Usage::Type::Declaration); - QCOMPARE(findUsages.usages().at(1).type, Usage::Type::Other); - QCOMPARE(findUsages.usages().at(2).type, Usage::Type::Other); + QCOMPARE(findUsages.usages().at(0).tags, Usage::Tag::Declaration); + QCOMPARE(findUsages.usages().at(1).tags, Usage::Tags()); + QCOMPARE(findUsages.usages().at(2).tags, Usage::Tags()); } void tst_FindUsages::using_insideNamespace() @@ -993,9 +1006,9 @@ void tst_FindUsages::using_insideNamespace() findUsages(structSymbol); QCOMPARE(findUsages.usages().size(), 3); - QCOMPARE(findUsages.usages().at(0).type, Usage::Type::Declaration); - QCOMPARE(findUsages.usages().at(1).type, Usage::Type::Other); - QCOMPARE(findUsages.usages().at(2).type, Usage::Type::Other); + QCOMPARE(findUsages.usages().at(0).tags, Usage::Tag::Declaration); + QCOMPARE(findUsages.usages().at(1).tags, Usage::Tags()); + QCOMPARE(findUsages.usages().at(2).tags, Usage::Tags()); } void tst_FindUsages::using_insideFunction() @@ -1036,9 +1049,9 @@ void tst_FindUsages::using_insideFunction() findUsages(structSymbol); QCOMPARE(findUsages.usages().size(), 3); - QCOMPARE(findUsages.usages().at(0).type, Usage::Type::Declaration); - QCOMPARE(findUsages.usages().at(1).type, Usage::Type::Other); - QCOMPARE(findUsages.usages().at(2).type, Usage::Type::Other); + QCOMPARE(findUsages.usages().at(0).tags, Usage::Tag::Declaration); + QCOMPARE(findUsages.usages().at(1).tags, Usage::Tags()); + QCOMPARE(findUsages.usages().at(2).tags, Usage::Tags()); } void tst_FindUsages::operatorArrowOfNestedClassOfTemplateClass_QTCREATORBUG9005() @@ -1083,8 +1096,8 @@ void tst_FindUsages::operatorArrowOfNestedClassOfTemplateClass_QTCREATORBUG9005( FindUsages findUsages(src, doc, snapshot, true); findUsages(fooDeclaration); QCOMPARE(findUsages.usages().size(), 2); - QCOMPARE(findUsages.usages().at(0).type, Usage::Type::Declaration); - QCOMPARE(findUsages.usages().at(1).type, Usage::Type::Read); + QCOMPARE(findUsages.usages().at(0).tags, Usage::Tag::Declaration); + QCOMPARE(findUsages.usages().at(1).tags, Usage::Tag::Read); } void tst_FindUsages::templateClassParameters() @@ -1120,11 +1133,11 @@ void tst_FindUsages::templateClassParameters() FindUsages findUsages(src, doc, snapshot, true); findUsages(templArgument); QCOMPARE(findUsages.usages().size(), 5); - QCOMPARE(findUsages.usages().at(0).type, Usage::Type::Declaration); - QCOMPARE(findUsages.usages().at(1).type, Usage::Type::Other); - QCOMPARE(findUsages.usages().at(2).type, Usage::Type::Other); - QCOMPARE(findUsages.usages().at(3).type, Usage::Type::Other); - QCOMPARE(findUsages.usages().at(4).type, Usage::Type::Other); + QCOMPARE(findUsages.usages().at(0).tags, Usage::Tag::Declaration); + QCOMPARE(findUsages.usages().at(1).tags, Usage::Tag::Template); + QCOMPARE(findUsages.usages().at(2).tags, Usage::Tags()); + QCOMPARE(findUsages.usages().at(3).tags, Usage::Tags()); + QCOMPARE(findUsages.usages().at(4).tags, Usage::Tags()); } void tst_FindUsages::templateClass_className() @@ -1166,13 +1179,13 @@ void tst_FindUsages::templateClass_className() FindUsages findUsages(src, doc, snapshot, true); findUsages(classTS); QCOMPARE(findUsages.usages().size(), 7); - QCOMPARE(findUsages.usages().at(0).type, Usage::Type::Declaration); - QCOMPARE(findUsages.usages().at(1).type, Usage::Type::Other); - QCOMPARE(findUsages.usages().at(2).type, Usage::Type::Other); - QCOMPARE(findUsages.usages().at(3).type, Usage::Type::Other); - QCOMPARE(findUsages.usages().at(4).type, Usage::Type::Other); - QCOMPARE(findUsages.usages().at(5).type, Usage::Type::Other); - QCOMPARE(findUsages.usages().at(6).type, Usage::Type::Other); + QCOMPARE(findUsages.usages().at(0).tags, Usage::Tag::Declaration); + QCOMPARE(findUsages.usages().at(1).tags, Usage::Tag::ConstructorDestructor); + QCOMPARE(findUsages.usages().at(2).tags, Usage::Tag::ConstructorDestructor); + QCOMPARE(findUsages.usages().at(3).tags, Usage::Tags()); + QCOMPARE(findUsages.usages().at(4).tags, Usage::Tag::ConstructorDestructor); + QCOMPARE(findUsages.usages().at(5).tags, Usage::Tags()); + QCOMPARE(findUsages.usages().at(6).tags, Usage::Tag::ConstructorDestructor); } void tst_FindUsages::templateFunctionParameters() @@ -1206,10 +1219,10 @@ void tst_FindUsages::templateFunctionParameters() FindUsages findUsages(src, doc, snapshot, true); findUsages(templArgument); QCOMPARE(findUsages.usages().size(), 4); - QCOMPARE(findUsages.usages().at(0).type, Usage::Type::Declaration); - QCOMPARE(findUsages.usages().at(1).type, Usage::Type::Other); - QCOMPARE(findUsages.usages().at(2).type, Usage::Type::Other); - QCOMPARE(findUsages.usages().at(3).type, Usage::Type::Other); + QCOMPARE(findUsages.usages().at(0).tags, Usage::Tag::Declaration); + QCOMPARE(findUsages.usages().at(1).tags, Usage::Tags()); + QCOMPARE(findUsages.usages().at(2).tags, Usage::Tag::Template); + QCOMPARE(findUsages.usages().at(3).tags, Usage::Tags()); } void tst_FindUsages::templatedFunction_QTCREATORBUG9749() @@ -1240,8 +1253,9 @@ void tst_FindUsages::templatedFunction_QTCREATORBUG9749() FindUsages findUsages(src, doc, snapshot, true); findUsages(func); QCOMPARE(findUsages.usages().size(), 2); - QCOMPARE(findUsages.usages().at(0).type, Usage::Type::Declaration); - QCOMPARE(findUsages.usages().at(1).type, Usage::Type::Other); + QCOMPARE(findUsages.usages().at(0).tags, + (Usage::Tags{Usage::Tag::Declaration, Usage::Tag::Template})); + QCOMPARE(findUsages.usages().at(1).tags, Usage::Tags()); } void tst_FindUsages::templateInNamespaceTypeOutside() @@ -1279,8 +1293,8 @@ int func() FindUsages findUsages(src, doc, snapshot, true); findUsages(v); QCOMPARE(findUsages.usages().size(), 2); - QCOMPARE(findUsages.usages().at(0).type, Usage::Type::Declaration); - QCOMPARE(findUsages.usages().at(1).type, Usage::Type::Read); + QCOMPARE(findUsages.usages().at(0).tags, Usage::Tag::Declaration); + QCOMPARE(findUsages.usages().at(1).tags, Usage::Tag::Read); } void tst_FindUsages::usingInDifferentNamespace_QTCREATORBUG7978() @@ -1320,9 +1334,9 @@ void tst_FindUsages::usingInDifferentNamespace_QTCREATORBUG7978() FindUsages findUsages(src, doc, snapshot, true); findUsages(templateClass); QCOMPARE(findUsages.usages().size(), 3); - QCOMPARE(findUsages.usages().at(0).type, Usage::Type::Declaration); - QCOMPARE(findUsages.usages().at(1).type, Usage::Type::Other); - QCOMPARE(findUsages.usages().at(2).type, Usage::Type::Other); + QCOMPARE(findUsages.usages().at(0).tags, Usage::Tag::Declaration); + QCOMPARE(findUsages.usages().at(1).tags, Usage::Tags()); + QCOMPARE(findUsages.usages().at(2).tags, Usage::Tags()); } void tst_FindUsages::unicodeIdentifier() @@ -1350,8 +1364,8 @@ void tst_FindUsages::unicodeIdentifier() findUsages(declaration); const QList<Usage> usages = findUsages.usages(); QCOMPARE(usages.size(), 2); - QCOMPARE(findUsages.usages().at(0).type, Usage::Type::Declaration); - QCOMPARE(findUsages.usages().at(1).type, Usage::Type::Write); + QCOMPARE(findUsages.usages().at(0).tags, Usage::Tag::Declaration); + QCOMPARE(findUsages.usages().at(1).tags, Usage::Tag::Write); QCOMPARE(usages.at(0).len, 7); QCOMPARE(usages.at(1).len, 7); } @@ -1381,10 +1395,10 @@ void tst_FindUsages::inAlignas() FindUsages find(src, doc, snapshot, true); find(c); QCOMPARE(find.usages().size(), 2); - QCOMPARE(find.usages()[0].type, Usage::Type::Declaration); + QCOMPARE(find.usages()[0].tags, Usage::Tag::Declaration); QCOMPARE(find.usages()[0].line, 1); QCOMPARE(find.usages()[0].col, 7); - QCOMPARE(find.usages()[1].type, Usage::Type::Other); + QCOMPARE(find.usages()[1].tags, Usage::Tags()); QCOMPARE(find.usages()[1].line, 2); QCOMPARE(find.usages()[1].col, 15); } @@ -1424,10 +1438,10 @@ void tst_FindUsages::memberAccessAsTemplate() FindUsages find(src, doc, snapshot, true); find(c); QCOMPARE(find.usages().size(), 2); - QCOMPARE(find.usages()[0].type, Usage::Type::Declaration); + QCOMPARE(find.usages()[0].tags, Usage::Tag::Declaration); QCOMPARE(find.usages()[0].line, 1); QCOMPARE(find.usages()[0].col, 7); - QCOMPARE(find.usages()[1].type, Usage::Type::Other); + QCOMPARE(find.usages()[1].tags, Usage::Tags()); QCOMPARE(find.usages()[1].line, 11); QCOMPARE(find.usages()[1].col, 24); } @@ -1445,10 +1459,11 @@ void tst_FindUsages::memberAccessAsTemplate() FindUsages find(src, doc, snapshot, true); find(f); QCOMPARE(find.usages().size(), 2); - QCOMPARE(find.usages()[0].type, Usage::Type::Declaration); + QCOMPARE(find.usages()[0].tags, + (Usage::Tags{Usage::Tag::Declaration, Usage::Tag::Template})); QCOMPARE(find.usages()[0].line, 4); QCOMPARE(find.usages()[0].col, 7); - QCOMPARE(find.usages()[1].type, Usage::Type::Other); + QCOMPARE(find.usages()[1].tags, Usage::Tags()); QCOMPARE(find.usages()[1].line, 11); QCOMPARE(find.usages()[1].col, 11); } @@ -1488,10 +1503,10 @@ void tst_FindUsages::variadicFunctionTemplate() FindUsages find(src, doc, snapshot, true); find(v); QCOMPARE(find.usages().size(), 4); - QCOMPARE(find.usages().at(0).type, Usage::Type::Declaration); - QCOMPARE(find.usages().at(1).type, Usage::Type::Read); - QCOMPARE(find.usages().at(2).type, Usage::Type::Read); - QCOMPARE(find.usages().at(3).type, Usage::Type::Read); + QCOMPARE(find.usages().at(0).tags, Usage::Tag::Declaration); + QCOMPARE(find.usages().at(1).tags, Usage::Tag::Read); + QCOMPARE(find.usages().at(2).tags, Usage::Tag::Read); + QCOMPARE(find.usages().at(3).tags, Usage::Tag::Read); } } @@ -1539,13 +1554,13 @@ void tst_FindUsages::typeTemplateParameterWithDefault() FindUsages find(src, doc, snapshot, true); find(xv); QCOMPARE(find.usages().size(), 2); - QCOMPARE(find.usages().at(0).type, Usage::Type::Declaration); - QCOMPARE(find.usages().at(1).type, Usage::Type::Read); + QCOMPARE(find.usages().at(0).tags, Usage::Tag::Declaration); + QCOMPARE(find.usages().at(1).tags, Usage::Tag::Read); find(sv); QCOMPARE(find.usages().size(), 3); - QCOMPARE(find.usages().at(0).type, Usage::Type::Declaration); - QCOMPARE(find.usages().at(1).type, Usage::Type::Read); - QCOMPARE(find.usages().at(2).type, Usage::Type::Read); + QCOMPARE(find.usages().at(0).tags, Usage::Tag::Declaration); + QCOMPARE(find.usages().at(1).tags, Usage::Tag::Read); + QCOMPARE(find.usages().at(2).tags, Usage::Tag::Read); } } @@ -1583,8 +1598,8 @@ void tst_FindUsages::resolveOrder_for_templateFunction_vs_function() FindUsages find(src, doc, snapshot, true); find(xv); QCOMPARE(find.usages().size(), 2); - QCOMPARE(find.usages().at(0).type, Usage::Type::Declaration); - QCOMPARE(find.usages().at(1).type, Usage::Type::Read); + QCOMPARE(find.usages().at(0).tags, Usage::Tag::Declaration); + QCOMPARE(find.usages().at(1).tags, Usage::Tag::Read); } } @@ -1625,9 +1640,9 @@ void tst_FindUsages::templateArrowOperator_with_defaultType() FindUsages find(src, doc, snapshot, true); find(sv); QCOMPARE(find.usages().size(), 3); - QCOMPARE(find.usages().at(0).type, Usage::Type::Declaration); - QCOMPARE(find.usages().at(1).type, Usage::Type::Read); - QCOMPARE(find.usages().at(2).type, Usage::Type::Read); + QCOMPARE(find.usages().at(0).tags, Usage::Tag::Declaration); + QCOMPARE(find.usages().at(1).tags, Usage::Tag::Read); + QCOMPARE(find.usages().at(2).tags, Usage::Tag::Read); } } @@ -1707,23 +1722,23 @@ void tst_FindUsages::templateSpecialization_with_IntArgument() find(sv[1]); QCOMPARE(find.usages().size(), 2); - QCOMPARE(find.usages()[0].type, Usage::Type::Initialization); + QCOMPARE(find.usages()[0].tags, Initialization); QCOMPARE(find.usages()[0].line, 2); QCOMPARE(find.usages()[0].col, 15); - QCOMPARE(find.usages()[1].type, Usage::Type::Read); + QCOMPARE(find.usages()[1].tags, Usage::Tag::Read); QCOMPARE(find.usages()[1].line, 13); QCOMPARE(find.usages()[1].col, 9); find(sv[2]); QCOMPARE(find.usages().size(), 3); - QCOMPARE(find.usages()[0].type, Usage::Type::Initialization); + QCOMPARE(find.usages()[0].tags, Initialization); QCOMPARE(find.usages()[0].line, 3); QCOMPARE(find.usages()[0].col, 15); - QCOMPARE(find.usages()[1].type, Usage::Type::Write); + QCOMPARE(find.usages()[1].tags, Usage::Tag::Write); QCOMPARE(find.usages()[1].line, 14); QCOMPARE(find.usages()[1].col, 9); - QCOMPARE(find.usages()[2].type, Usage::Type::Read); + QCOMPARE(find.usages()[2].tags, Usage::Tag::Read); QCOMPARE(find.usages()[2].line, 14); QCOMPARE(find.usages()[2].col, 22); } @@ -1786,20 +1801,20 @@ void tst_FindUsages::templateSpecialization_with_BoolArgument() find(sv[0]); QCOMPARE(find.usages().size(), 2); - QCOMPARE(find.usages()[0].type, Usage::Type::Initialization); + QCOMPARE(find.usages()[0].tags, Initialization); QCOMPARE(find.usages()[0].line, 1); QCOMPARE(find.usages()[0].col, 15); - QCOMPARE(find.usages()[1].type, Usage::Type::Read); + QCOMPARE(find.usages()[1].tags, Usage::Tag::Read); QCOMPARE(find.usages()[1].line, 9); QCOMPARE(find.usages()[1].col, 9); find(sv[1]); QCOMPARE(find.usages().size(), 2); - QCOMPARE(find.usages()[0].type, Usage::Type::Initialization); + QCOMPARE(find.usages()[0].tags, Initialization); QCOMPARE(find.usages()[0].line, 2); QCOMPARE(find.usages()[0].col, 15); - QCOMPARE(find.usages()[1].type, Usage::Type::Read); + QCOMPARE(find.usages()[1].tags, Usage::Tag::Read); QCOMPARE(find.usages()[1].line, 10); QCOMPARE(find.usages()[1].col, 9); } @@ -1862,20 +1877,20 @@ void tst_FindUsages::templatePartialSpecialization() find(sv[0]); QCOMPARE(find.usages().size(), 2); - QCOMPARE(find.usages()[0].type, Usage::Type::Initialization); + QCOMPARE(find.usages()[0].tags, Initialization); QCOMPARE(find.usages()[0].line, 1); QCOMPARE(find.usages()[0].col, 15); - QCOMPARE(find.usages()[1].type, Usage::Type::Read); + QCOMPARE(find.usages()[1].tags, Usage::Tag::Read); QCOMPARE(find.usages()[1].line, 9); QCOMPARE(find.usages()[1].col, 10); find(sv[1]); QCOMPARE(find.usages().size(), 2); - QCOMPARE(find.usages()[0].type, Usage::Type::Initialization); + QCOMPARE(find.usages()[0].tags, Initialization); QCOMPARE(find.usages()[0].line, 2); QCOMPARE(find.usages()[0].col, 15); - QCOMPARE(find.usages()[1].type, Usage::Type::Read); + QCOMPARE(find.usages()[1].tags, Usage::Tag::Read); QCOMPARE(find.usages()[1].line, 10); QCOMPARE(find.usages()[1].col, 10); } @@ -1931,18 +1946,18 @@ int main() find(sv[0]); QCOMPARE(find.usages().size(), 2); - QCOMPARE(find.usages().at(0).type, Usage::Type::Initialization); - QCOMPARE(find.usages().at(1).type, Usage::Type::Read); + QCOMPARE(find.usages().at(0).tags, Initialization); + QCOMPARE(find.usages().at(1).tags, Usage::Tag::Read); find(sv[1]); QCOMPARE(find.usages().size(), 2); - QCOMPARE(find.usages().at(0).type, Usage::Type::Initialization); - QCOMPARE(find.usages().at(1).type, Usage::Type::Read); + QCOMPARE(find.usages().at(0).tags, Initialization); + QCOMPARE(find.usages().at(1).tags, Usage::Tag::Read); find(sv[2]); QCOMPARE(find.usages().size(), 2); - QCOMPARE(find.usages().at(0).type, Usage::Type::Initialization); - QCOMPARE(find.usages().at(1).type, Usage::Type::Read); + QCOMPARE(find.usages().at(0).tags, Initialization); + QCOMPARE(find.usages().at(1).tags, Usage::Tag::Read); } void tst_FindUsages::template_SFINAE_1() @@ -1981,8 +1996,8 @@ int main(){ FindUsages find(src, doc, snapshot, true); find(sv); QCOMPARE(find.usages().size(), 2); - QCOMPARE(find.usages().at(0).type, Usage::Type::Initialization); - QCOMPARE(find.usages().at(1).type, Usage::Type::Read); + QCOMPARE(find.usages().at(0).tags, Initialization); + QCOMPARE(find.usages().at(1).tags, Usage::Tag::Read); } void tst_FindUsages::variableTemplateInExpression() @@ -2026,8 +2041,8 @@ int main(){ FindUsages find(src, doc, snapshot, true); find(sv); QCOMPARE(find.usages().size(), 2); - QCOMPARE(find.usages().at(0).type, Usage::Type::Declaration); - QCOMPARE(find.usages().at(1).type, Usage::Type::Read); + QCOMPARE(find.usages().at(0).tags, Usage::Tag::Declaration); + QCOMPARE(find.usages().at(1).tags, Usage::Tag::Read); } void tst_FindUsages::variadicMacros() @@ -2066,8 +2081,8 @@ int main(){} FindUsages find(src, doc, snapshot, true); find(sv); QCOMPARE(find.usages().size(), 2); - QCOMPARE(find.usages().at(0).type, Usage::Type::Declaration); - QCOMPARE(find.usages().at(1).type, Usage::Type::Read); + QCOMPARE(find.usages().at(0).tags, Usage::Tag::Declaration); + QCOMPARE(find.usages().at(1).tags, Usage::Tag::Read); } void tst_FindUsages::writableRefs() @@ -2179,37 +2194,37 @@ int main() FindUsages find(src, doc, snapshot, true); find(sv); QCOMPARE(find.usages().size(), 31); - QCOMPARE(find.usages().at(0).type, Usage::Type::Read); - QCOMPARE(find.usages().at(1).type, Usage::Type::Declaration); - QCOMPARE(find.usages().at(2).type, Usage::Type::WritableRef); - QCOMPARE(find.usages().at(3).type, Usage::Type::WritableRef); - QCOMPARE(find.usages().at(4).type, Usage::Type::WritableRef); - QCOMPARE(find.usages().at(5).type, Usage::Type::WritableRef); - QCOMPARE(find.usages().at(6).type, Usage::Type::WritableRef); - QCOMPARE(find.usages().at(7).type, Usage::Type::Read); - QCOMPARE(find.usages().at(8).type, Usage::Type::Read); - QCOMPARE(find.usages().at(9).type, Usage::Type::WritableRef); - QCOMPARE(find.usages().at(10).type, Usage::Type::WritableRef); - QCOMPARE(find.usages().at(11).type, Usage::Type::Read); - QCOMPARE(find.usages().at(12).type, Usage::Type::WritableRef); - QCOMPARE(find.usages().at(13).type, Usage::Type::Read); - QCOMPARE(find.usages().at(14).type, Usage::Type::WritableRef); - QCOMPARE(find.usages().at(15).type, Usage::Type::Read); - QCOMPARE(find.usages().at(16).type, Usage::Type::Read); - QCOMPARE(find.usages().at(17).type, Usage::Type::Read); - QCOMPARE(find.usages().at(18).type, Usage::Type::Read); - QCOMPARE(find.usages().at(19).type, Usage::Type::Read); - QCOMPARE(find.usages().at(20).type, Usage::Type::Write); - QCOMPARE(find.usages().at(21).type, Usage::Type::Read); - QCOMPARE(find.usages().at(22).type, Usage::Type::Write); - QCOMPARE(find.usages().at(23).type, Usage::Type::Write); - QCOMPARE(find.usages().at(24).type, Usage::Type::Write); - QCOMPARE(find.usages().at(25).type, Usage::Type::Write); - QCOMPARE(find.usages().at(26).type, Usage::Type::Read); - QCOMPARE(find.usages().at(27).type, Usage::Type::Read); - QCOMPARE(find.usages().at(28).type, Usage::Type::Read); - QCOMPARE(find.usages().at(29).type, Usage::Type::Write); - QCOMPARE(find.usages().at(30).type, Usage::Type::Read); + QCOMPARE(find.usages().at(0).tags, Usage::Tag::Read); + QCOMPARE(find.usages().at(1).tags, Usage::Tag::Declaration); + QCOMPARE(find.usages().at(2).tags, Usage::Tag::WritableRef); + QCOMPARE(find.usages().at(3).tags, Usage::Tag::WritableRef); + QCOMPARE(find.usages().at(4).tags, Usage::Tag::WritableRef); + QCOMPARE(find.usages().at(5).tags, Usage::Tag::WritableRef); + QCOMPARE(find.usages().at(6).tags, Usage::Tag::WritableRef); + QCOMPARE(find.usages().at(7).tags, Usage::Tag::Read); + QCOMPARE(find.usages().at(8).tags, Usage::Tag::Read); + QCOMPARE(find.usages().at(9).tags, Usage::Tag::WritableRef); + QCOMPARE(find.usages().at(10).tags, Usage::Tag::WritableRef); + QCOMPARE(find.usages().at(11).tags, Usage::Tag::Read); + QCOMPARE(find.usages().at(12).tags, Usage::Tag::WritableRef); + QCOMPARE(find.usages().at(13).tags, Usage::Tag::Read); + QCOMPARE(find.usages().at(14).tags, Usage::Tag::WritableRef); + QCOMPARE(find.usages().at(15).tags, Usage::Tag::Read); + QCOMPARE(find.usages().at(16).tags, Usage::Tag::Read); + QCOMPARE(find.usages().at(17).tags, Usage::Tag::Read); + QCOMPARE(find.usages().at(18).tags, Usage::Tag::Read); + QCOMPARE(find.usages().at(19).tags, Usage::Tag::Read); + QCOMPARE(find.usages().at(20).tags, Usage::Tag::Write); + QCOMPARE(find.usages().at(21).tags, Usage::Tag::Read); + QCOMPARE(find.usages().at(22).tags, Usage::Tag::Write); + QCOMPARE(find.usages().at(23).tags, Usage::Tag::Write); + QCOMPARE(find.usages().at(24).tags, Usage::Tag::Write); + QCOMPARE(find.usages().at(25).tags, Usage::Tag::Write); + QCOMPARE(find.usages().at(26).tags, Usage::Tag::Read); + QCOMPARE(find.usages().at(27).tags, Usage::Tag::Read); + QCOMPARE(find.usages().at(28).tags, Usage::Tag::Read); + QCOMPARE(find.usages().at(29).tags, Usage::Tag::Write); + QCOMPARE(find.usages().at(30).tags, Usage::Tag::Read); Declaration * const sv2 = structS->memberAt(2)->asDeclaration(); QVERIFY(sv2); @@ -2218,8 +2233,8 @@ int main() // Member initialization in constructor find(sv2); QCOMPARE(find.usages().size(), 2); - QCOMPARE(find.usages().at(0).type, Usage::Type::Write); - QCOMPARE(find.usages().at(1).type, Usage::Type::Declaration); + QCOMPARE(find.usages().at(0).tags, Usage::Tag::Write); + QCOMPARE(find.usages().at(1).tags, Usage::Tag::Declaration); // Make sure that pure virtual declaration is not mistaken for an assignment. Declaration * const pureVirtual = structS->memberAt(11)->asDeclaration(); @@ -2227,13 +2242,13 @@ int main() QCOMPARE(pureVirtual->name()->identifier()->chars(), "pureVirtual"); find(pureVirtual); QCOMPARE(find.usages().size(), 1); - QCOMPARE(find.usages().at(0).type, Usage::Type::Declaration); + QCOMPARE(find.usages().at(0).tags, Usage::Tag::Declaration); Function * const pureVirtual2 = structS->memberAt(12)->asFunction(); QVERIFY(pureVirtual2); QCOMPARE(pureVirtual2->name()->identifier()->chars(), "pureVirtual2"); find(pureVirtual2); QCOMPARE(find.usages().size(), 1); - QCOMPARE(find.usages().at(0).type, Usage::Type::Declaration); + QCOMPARE(find.usages().at(0).tags, Usage::Tag::Declaration); Function * const main = doc->globalSymbolAt(6)->asFunction(); QVERIFY(main); @@ -2248,16 +2263,16 @@ int main() QCOMPARE(p->name()->identifier()->chars(), "p"); find(p); QCOMPARE(find.usages().size(), 10); - QCOMPARE(find.usages().at(0).type, Usage::Type::Initialization); - QCOMPARE(find.usages().at(1).type, Usage::Type::Write); - QCOMPARE(find.usages().at(2).type, Usage::Type::Write); - QCOMPARE(find.usages().at(3).type, Usage::Type::WritableRef); - QCOMPARE(find.usages().at(4).type, Usage::Type::Read); - QCOMPARE(find.usages().at(5).type, Usage::Type::WritableRef); - QCOMPARE(find.usages().at(6).type, Usage::Type::Read); - QCOMPARE(find.usages().at(7).type, Usage::Type::Read); - QCOMPARE(find.usages().at(8).type, Usage::Type::WritableRef); - QCOMPARE(find.usages().at(9).type, Usage::Type::Read); + QCOMPARE(find.usages().at(0).tags, Initialization); + QCOMPARE(find.usages().at(1).tags, Usage::Tag::Write); + QCOMPARE(find.usages().at(2).tags, Usage::Tag::Write); + QCOMPARE(find.usages().at(3).tags, Usage::Tag::WritableRef); + QCOMPARE(find.usages().at(4).tags, Usage::Tag::Read); + QCOMPARE(find.usages().at(5).tags, Usage::Tag::WritableRef); + QCOMPARE(find.usages().at(6).tags, Usage::Tag::Read); + QCOMPARE(find.usages().at(7).tags, Usage::Tag::Read); + QCOMPARE(find.usages().at(8).tags, Usage::Tag::WritableRef); + QCOMPARE(find.usages().at(9).tags, Usage::Tag::Read); // Access to struct variable via its members Declaration * const varS = block->memberAt(0)->asDeclaration(); @@ -2265,70 +2280,70 @@ int main() QCOMPARE(varS->name()->identifier()->chars(), "s"); find(varS); QCOMPARE(find.usages().size(), 33); - QCOMPARE(find.usages().at(0).type, Usage::Type::Declaration); - QCOMPARE(find.usages().at(1).type, Usage::Type::WritableRef); - QCOMPARE(find.usages().at(2).type, Usage::Type::WritableRef); - QCOMPARE(find.usages().at(3).type, Usage::Type::WritableRef); - QCOMPARE(find.usages().at(4).type, Usage::Type::Write); - QCOMPARE(find.usages().at(5).type, Usage::Type::WritableRef); - QCOMPARE(find.usages().at(6).type, Usage::Type::Write); - QCOMPARE(find.usages().at(7).type, Usage::Type::Read); - QCOMPARE(find.usages().at(8).type, Usage::Type::Write); - QCOMPARE(find.usages().at(9).type, Usage::Type::Read); - QCOMPARE(find.usages().at(10).type, Usage::Type::WritableRef); - QCOMPARE(find.usages().at(11).type, Usage::Type::WritableRef); - QCOMPARE(find.usages().at(12).type, Usage::Type::Read); - QCOMPARE(find.usages().at(13).type, Usage::Type::WritableRef); - QCOMPARE(find.usages().at(14).type, Usage::Type::Read); - QCOMPARE(find.usages().at(15).type, Usage::Type::WritableRef); - QCOMPARE(find.usages().at(16).type, Usage::Type::Read); - QCOMPARE(find.usages().at(17).type, Usage::Type::Read); + QCOMPARE(find.usages().at(0).tags, Usage::Tag::Declaration); + QCOMPARE(find.usages().at(1).tags, Usage::Tag::WritableRef); + QCOMPARE(find.usages().at(2).tags, Usage::Tag::WritableRef); + QCOMPARE(find.usages().at(3).tags, Usage::Tag::WritableRef); + QCOMPARE(find.usages().at(4).tags, Usage::Tag::Write); + QCOMPARE(find.usages().at(5).tags, Usage::Tag::WritableRef); + QCOMPARE(find.usages().at(6).tags, Usage::Tag::Write); + QCOMPARE(find.usages().at(7).tags, Usage::Tag::Read); + QCOMPARE(find.usages().at(8).tags, Usage::Tag::Write); + QCOMPARE(find.usages().at(9).tags, Usage::Tag::Read); + QCOMPARE(find.usages().at(10).tags, Usage::Tag::WritableRef); + QCOMPARE(find.usages().at(11).tags, Usage::Tag::WritableRef); + QCOMPARE(find.usages().at(12).tags, Usage::Tag::Read); + QCOMPARE(find.usages().at(13).tags, Usage::Tag::WritableRef); + QCOMPARE(find.usages().at(14).tags, Usage::Tag::Read); + QCOMPARE(find.usages().at(15).tags, Usage::Tag::WritableRef); + QCOMPARE(find.usages().at(16).tags, Usage::Tag::Read); + QCOMPARE(find.usages().at(17).tags, Usage::Tag::Read); // Direct access to struct variable - QCOMPARE(find.usages().at(18).type, Usage::Type::Write); - QCOMPARE(find.usages().at(19).type, Usage::Type::WritableRef); + QCOMPARE(find.usages().at(18).tags, Usage::Tag::Write); + QCOMPARE(find.usages().at(19).tags, Usage::Tag::WritableRef); QEXPECT_FAIL(nullptr, "parser does not record const qualifier for auto types", Continue); - QCOMPARE(find.usages().at(20).type, Usage::Type::Read); + QCOMPARE(find.usages().at(20).tags, Usage::Tag::Read); QEXPECT_FAIL(nullptr, "parser does not record reference qualifier for auto types", Continue); - QCOMPARE(find.usages().at(21).type, Usage::Type::WritableRef); + QCOMPARE(find.usages().at(21).tags, Usage::Tag::WritableRef); QEXPECT_FAIL(nullptr, "parser does not record const qualifier for auto types", Continue); - QCOMPARE(find.usages().at(22).type, Usage::Type::Read); + QCOMPARE(find.usages().at(22).tags, Usage::Tag::Read); // Member function calls. - QCOMPARE(find.usages().at(23).type, Usage::Type::Read); - QCOMPARE(find.usages().at(24).type, Usage::Type::WritableRef); - QCOMPARE(find.usages().at(25).type, Usage::Type::WritableRef); - QCOMPARE(find.usages().at(26).type, Usage::Type::Read); - QCOMPARE(find.usages().at(27).type, Usage::Type::WritableRef); - QCOMPARE(find.usages().at(28).type, Usage::Type::Read); - QCOMPARE(find.usages().at(29).type, Usage::Type::Read); - QCOMPARE(find.usages().at(31).type, Usage::Type::Other); - QCOMPARE(find.usages().at(32).type, Usage::Type::Other); + QCOMPARE(find.usages().at(23).tags, Usage::Tag::Read); + QCOMPARE(find.usages().at(24).tags, Usage::Tag::WritableRef); + QCOMPARE(find.usages().at(25).tags, Usage::Tag::WritableRef); + QCOMPARE(find.usages().at(26).tags, Usage::Tag::Read); + QCOMPARE(find.usages().at(27).tags, Usage::Tag::WritableRef); + QCOMPARE(find.usages().at(28).tags, Usage::Tag::Read); + QCOMPARE(find.usages().at(29).tags, Usage::Tag::Read); + QCOMPARE(find.usages().at(31).tags, Usage::Tags()); + QCOMPARE(find.usages().at(32).tags, Usage::Tags()); // Usages of struct type find(structS); QCOMPARE(find.usages().size(), 18); - QCOMPARE(find.usages().at(0).type, Usage::Type::Declaration); - QCOMPARE(find.usages().at(1).type, Usage::Type::Other); - QCOMPARE(find.usages().at(2).type, Usage::Type::Other); - QCOMPARE(find.usages().at(3).type, Usage::Type::Other); - QCOMPARE(find.usages().at(4).type, Usage::Type::Other); + QCOMPARE(find.usages().at(0).tags, Usage::Tag::Declaration); + QCOMPARE(find.usages().at(1).tags, Usage::Tag::ConstructorDestructor); + QCOMPARE(find.usages().at(2).tags, Usage::Tags()); + QCOMPARE(find.usages().at(3).tags, Usage::Tags()); + QCOMPARE(find.usages().at(4).tags, Usage::Tags()); // These are conceptually questionable, as S is a type and thus we cannot "read from" // or "write to" it. But it possibly matches the intuitive user expectation. - QCOMPARE(find.usages().at(5).type, Usage::Type::Read); - QCOMPARE(find.usages().at(6).type, Usage::Type::Read); - QCOMPARE(find.usages().at(7).type, Usage::Type::Write); - QCOMPARE(find.usages().at(8).type, Usage::Type::Read); - QCOMPARE(find.usages().at(9).type, Usage::Type::Write); - QCOMPARE(find.usages().at(10).type, Usage::Type::Write); - QCOMPARE(find.usages().at(11).type, Usage::Type::Write); - QCOMPARE(find.usages().at(12).type, Usage::Type::Write); - QCOMPARE(find.usages().at(13).type, Usage::Type::Read); - QCOMPARE(find.usages().at(14).type, Usage::Type::Read); - QCOMPARE(find.usages().at(15).type, Usage::Type::Read); - QCOMPARE(find.usages().at(16).type, Usage::Type::Write); - QCOMPARE(find.usages().at(17).type, Usage::Type::Read); + QCOMPARE(find.usages().at(5).tags, Usage::Tag::Read); + QCOMPARE(find.usages().at(6).tags, Usage::Tag::Read); + QCOMPARE(find.usages().at(7).tags, Usage::Tag::Write); + QCOMPARE(find.usages().at(8).tags, Usage::Tag::Read); + QCOMPARE(find.usages().at(9).tags, Usage::Tag::Write); + QCOMPARE(find.usages().at(10).tags, Usage::Tag::Write); + QCOMPARE(find.usages().at(11).tags, Usage::Tag::Write); + QCOMPARE(find.usages().at(12).tags, Usage::Tag::Write); + QCOMPARE(find.usages().at(13).tags, Usage::Tag::Read); + QCOMPARE(find.usages().at(14).tags, Usage::Tag::Read); + QCOMPARE(find.usages().at(15).tags, Usage::Tag::Read); + QCOMPARE(find.usages().at(16).tags, Usage::Tag::Write); + QCOMPARE(find.usages().at(17).tags, Usage::Tag::Read); // Arrays. Declaration * const array = block->memberAt(17)->asDeclaration(); @@ -2336,9 +2351,141 @@ int main() QCOMPARE(array->name()->identifier()->chars(), "array"); find(array); QCOMPARE(find.usages().size(), 3); - QCOMPARE(find.usages().at(0).type, Usage::Type::Declaration); - QCOMPARE(find.usages().at(1).type, Usage::Type::Write); - QCOMPARE(find.usages().at(2).type, Usage::Type::Read); + QCOMPARE(find.usages().at(0).tags, Usage::Tag::Declaration); + QCOMPARE(find.usages().at(1).tags, Usage::Tag::Write); + QCOMPARE(find.usages().at(2).tags, Usage::Tag::Read); +} + +void tst_FindUsages::mocInvokables() +{ + const QByteArray src = + R"( +class O : public QObject { +public: + void aPublicFunction(); + Q_SLOT void aSlot(); + Q_SIGNAL void aSignal(); + Q_INVOKABLE void anInvokable(); +public slots: + void anotherSlot(); +signals: + void anotherSignal(); +private slots: + void yetAnotherSlot(); +private: + void aPrivateFunction(); +}; +)"; + + Document::Ptr doc = Document::create("mocInvokables"); + doc->setUtf8Source(src); + doc->parse(); + doc->check(); + + QVERIFY(doc->diagnosticMessages().isEmpty()); + QVERIFY(doc->globalSymbolCount() >= 1); + + Snapshot snapshot; + snapshot.insert(doc); + + Class *s = doc->globalSymbolAt(0)->asClass(); + QVERIFY(s); + QCOMPARE(s->name()->identifier()->chars(), "O"); + QCOMPARE(s->memberCount(), 8); + + const Usage::Tags invokable{Usage::Tag::Declaration, Usage::Tag::MocInvokable}; + + Declaration *sv = s->memberAt(0)->asDeclaration(); + QVERIFY(sv); + QCOMPARE(sv->name()->identifier()->chars(), "aPublicFunction"); + FindUsages find(src, doc, snapshot, true); + find(sv); + QCOMPARE(find.usages().size(), 1); + QCOMPARE(find.usages().at(0).tags, Usage::Tag::Declaration); + + sv = s->memberAt(1)->asDeclaration(); + QVERIFY(sv); + QCOMPARE(sv->name()->identifier()->chars(), "aSlot"); + find(sv); + QCOMPARE(find.usages().size(), 1); + QCOMPARE(find.usages().at(0).tags, invokable); + + sv = s->memberAt(2)->asDeclaration(); + QVERIFY(sv); + QCOMPARE(sv->name()->identifier()->chars(), "aSignal"); + find(sv); + QCOMPARE(find.usages().size(), 1); + QCOMPARE(find.usages().at(0).tags, invokable); + + sv = s->memberAt(3)->asDeclaration(); + QVERIFY(sv); + QCOMPARE(sv->name()->identifier()->chars(), "anInvokable"); + find(sv); + QCOMPARE(find.usages().size(), 1); + QCOMPARE(find.usages().at(0).tags, invokable); + + sv = s->memberAt(4)->asDeclaration(); + QVERIFY(sv); + QCOMPARE(sv->name()->identifier()->chars(), "anotherSlot"); + find(sv); + QCOMPARE(find.usages().size(), 1); + QCOMPARE(find.usages().at(0).tags, invokable); + + sv = s->memberAt(5)->asDeclaration(); + QVERIFY(sv); + QCOMPARE(sv->name()->identifier()->chars(), "anotherSignal"); + find(sv); + QCOMPARE(find.usages().size(), 1); + QCOMPARE(find.usages().at(0).tags, invokable); + + sv = s->memberAt(6)->asDeclaration(); + QVERIFY(sv); + QCOMPARE(sv->name()->identifier()->chars(), "yetAnotherSlot"); + find(sv); + QCOMPARE(find.usages().size(), 1); + QCOMPARE(find.usages().at(0).tags, invokable); + + sv = s->memberAt(7)->asDeclaration(); + QVERIFY(sv); + QCOMPARE(sv->name()->identifier()->chars(), "aPrivateFunction"); + find(sv); + QCOMPARE(find.usages().size(), 1); + QCOMPARE(find.usages().at(0).tags, Usage::Tag::Declaration); +} + +void tst_FindUsages::virtualOverride() +{ + const QByteArray src = + R"( +struct Base { virtual void foo(); }; +struct Derived : public Base { void foo() override; }; +)"; + + Document::Ptr doc = Document::create("virtualOverride"); + doc->setUtf8Source(src); + doc->parse(); + doc->check(); + + QVERIFY(doc->diagnosticMessages().isEmpty()); + QVERIFY(doc->globalSymbolCount() >= 2); + + Snapshot snapshot; + snapshot.insert(doc); + + Class *s = doc->globalSymbolAt(1)->asClass(); + QVERIFY(s); + QCOMPARE(s->name()->identifier()->chars(), "Derived"); + QCOMPARE(s->memberCount(), 1); + + Declaration *sv = s->memberAt(0)->asDeclaration(); + QVERIFY(sv); + QCOMPARE(sv->name()->identifier()->chars(), "foo"); + + FindUsages find(src, doc, snapshot, true); + find(sv); + QCOMPARE(find.usages().size(), 1); + QCOMPARE(find.usages().at(0).tags, + (Usage::Tags{Usage::Tag::Declaration, Usage::Tag::Override})); } QTEST_APPLESS_MAIN(tst_FindUsages) diff --git a/tests/auto/cplusplus/lookup/CMakeLists.txt b/tests/auto/cplusplus/lookup/CMakeLists.txt index 06091aece7..d350ab32de 100644 --- a/tests/auto/cplusplus/lookup/CMakeLists.txt +++ b/tests/auto/cplusplus/lookup/CMakeLists.txt @@ -1,4 +1,4 @@ add_qtc_test(tst_cplusplus_lookup - DEPENDS CppEditor + DEPENDS CppEditor Utils SOURCES tst_lookup.cpp ) diff --git a/tests/auto/cplusplus/preprocessor/CMakeLists.txt b/tests/auto/cplusplus/preprocessor/CMakeLists.txt index 088aabe6cc..de38d2a304 100644 --- a/tests/auto/cplusplus/preprocessor/CMakeLists.txt +++ b/tests/auto/cplusplus/preprocessor/CMakeLists.txt @@ -1,4 +1,4 @@ add_qtc_test(tst_cplusplus_preprocessor - DEPENDS CppEditor + DEPENDS CppEditor Utils SOURCES tst_preprocessor.cpp ) diff --git a/tests/auto/cplusplus/preprocessor/tst_preprocessor.cpp b/tests/auto/cplusplus/preprocessor/tst_preprocessor.cpp index 34562b8bcd..2e2a107d90 100644 --- a/tests/auto/cplusplus/preprocessor/tst_preprocessor.cpp +++ b/tests/auto/cplusplus/preprocessor/tst_preprocessor.cpp @@ -152,12 +152,12 @@ public: virtual void stopSkippingBlocks(int utf16charsOffset) { m_skippedBlocks.last().end = utf16charsOffset; } - virtual void sourceNeeded(int line, const QString &includedFileName, IncludeType mode, - const QStringList &initialIncludes = QStringList()) + virtual void sourceNeeded(int line, const Utils::FilePath &includedFileName, IncludeType mode, + const Utils::FilePaths &initialIncludes = {}) { Q_UNUSED(initialIncludes) #if 1 - m_recordedIncludes.append(Include(includedFileName, mode, line)); + m_recordedIncludes.append(Include(includedFileName.toString(), mode, line)); Q_UNUSED(m_env) Q_UNUSED(m_includeDepth) #else diff --git a/tests/auto/cplusplus/translationunit/tst_translationunit.cpp b/tests/auto/cplusplus/translationunit/tst_translationunit.cpp index 683b163af0..ac00d61c00 100644 --- a/tests/auto/cplusplus/translationunit/tst_translationunit.cpp +++ b/tests/auto/cplusplus/translationunit/tst_translationunit.cpp @@ -9,6 +9,8 @@ #include <cplusplus/TranslationUnit.h> #include <cplusplus/pp-engine.h> +#include <utils/filepath.h> + #include <QtTest> #include <QDebug> diff --git a/tests/auto/languageserverprotocol/tst_languageserverprotocol.cpp b/tests/auto/languageserverprotocol/tst_languageserverprotocol.cpp index 75732e98bf..449125d06c 100644 --- a/tests/auto/languageserverprotocol/tst_languageserverprotocol.cpp +++ b/tests/auto/languageserverprotocol/tst_languageserverprotocol.cpp @@ -476,7 +476,7 @@ void tst_LanguageServerProtocol::documentUri_data() QTest::newRow("home dir") - << DocumentUri::fromFilePath(Utils::FilePath::fromString(QDir::homePath())) + << DocumentUri::fromFilePath(Utils::FilePath::fromString(QDir::homePath()), [](auto in){ return in;}) << true << Utils::FilePath::fromUserInput(QDir::homePath()) << QString(filePrefix + QDir::homePath()); @@ -484,7 +484,7 @@ void tst_LanguageServerProtocol::documentUri_data() const QString argv0 = QFileInfo(qApp->arguments().first()).absoluteFilePath(); const auto argv0FileName = Utils::FilePath::fromUserInput(argv0); QTest::newRow("argv0 file name") - << DocumentUri::fromFilePath(argv0FileName) + << DocumentUri::fromFilePath(argv0FileName, [](auto in){ return in;}) << true << argv0FileName << QString(filePrefix + QDir::fromNativeSeparators(argv0)); @@ -514,7 +514,7 @@ void tst_LanguageServerProtocol::documentUri() QFETCH(QString, string); QCOMPARE(uri.isValid(), isValid); - QCOMPARE(uri.toFilePath(), fileName); + QCOMPARE(uri.toFilePath([](auto in){ return in;}), fileName); QCOMPARE(uri.toString(), string); } diff --git a/tests/auto/qml/codemodel/importscheck/tst_importscheck.cpp b/tests/auto/qml/codemodel/importscheck/tst_importscheck.cpp index 45d5f51577..8f300db02f 100644 --- a/tests/auto/qml/codemodel/importscheck/tst_importscheck.cpp +++ b/tests/auto/qml/codemodel/importscheck/tst_importscheck.cpp @@ -58,7 +58,7 @@ void scanDirectory(const QString &dir) ModelManagerInterface::instance(), false); ModelManagerInterface::instance()->test_joinAllThreads(); ViewerContext vCtx; - vCtx.paths.append(dirPath); + vCtx.paths.insert(dirPath); Snapshot snap = ModelManagerInterface::instance()->snapshot(); ImportDependencies *iDeps = snap.importDependencies(); @@ -176,7 +176,10 @@ void tst_ImportCheck::test() ModelManagerInterface::instance(), false); ModelManagerInterface::instance()->test_joinAllThreads(); ViewerContext vCtx; - vCtx.paths.append(pathPaths); + + for (const Utils::FilePath &path : pathPaths) + vCtx.paths.insert(path); + Snapshot snap = ModelManagerInterface::instance()->snapshot(); ImportDependencies *iDeps = snap.importDependencies(); diff --git a/tests/auto/qml/qmldesigner/coretests/CMakeLists.txt b/tests/auto/qml/qmldesigner/coretests/CMakeLists.txt index 5ce2cffa82..d7fce48ef7 100644 --- a/tests/auto/qml/qmldesigner/coretests/CMakeLists.txt +++ b/tests/auto/qml/qmldesigner/coretests/CMakeLists.txt @@ -1,13 +1,19 @@ add_qtc_test(tst_qml_testcore EXCLUDE_FROM_PRECHECK CONDITION TARGET QmlProjectManager AND Qt5_VERSION VERSION_GREATER_EQUAL 6.2.0 - DEPENDS Sqlite + DEPENDS + Sqlite + QmlDesignerCore + Qt5::Widgets + Qt5::Qml DEFINES QT_CREATOR - QMLDESIGNER_TEST IDE_PLUGIN_PATH="${PROJECT_BINARY_DIR}/${IDE_PLUGIN_PATH}" IDE_DATA_PATH="${PROJECT_BINARY_DIR}/${IDE_DATA_PATH}" TESTSRCDIR="${CMAKE_CURRENT_SOURCE_DIR}" + QMLDESIGNERCORE_STATIC_LIBRARY QMLDESIGNERUTILS_STATIC_LIBRARY + INCLUDES + "${CMAKE_CURRENT_LIST_DIR}/../../../../../share/qtcreator/qml/qmlpuppet/commands" SOURCES ../data/testfiles.qrc ../testview.cpp @@ -20,5 +26,3 @@ add_qtc_test(tst_qml_testcore ../testconnectionmanager.h ) -include(../../../../../src/plugins/qmldesigner/qmldesignercore.cmake) -extend_with_qmldesigner_core(tst_qml_testcore) diff --git a/tests/auto/qml/qmldesigner/coretests/testrewriterview.cpp b/tests/auto/qml/qmldesigner/coretests/testrewriterview.cpp index 015bb582d6..9e3866dea3 100644 --- a/tests/auto/qml/qmldesigner/coretests/testrewriterview.cpp +++ b/tests/auto/qml/qmldesigner/coretests/testrewriterview.cpp @@ -58,8 +58,9 @@ VariantProperty TestModelToTextMerger::findAddedVariantProperty(const VariantPro return VariantProperty(); } -TestRewriterView::TestRewriterView(DifferenceHandling differenceHandling) - : RewriterView(differenceHandling) +TestRewriterView::TestRewriterView(ExternalDependenciesInterface &externalDependencies, + DifferenceHandling differenceHandling) + : RewriterView(externalDependencies, differenceHandling) { //Unit tests do not like the semantic errors setCheckSemanticErrors(false); diff --git a/tests/auto/qml/qmldesigner/coretests/testrewriterview.h b/tests/auto/qml/qmldesigner/coretests/testrewriterview.h index 20d27fe6d8..e8af846a13 100644 --- a/tests/auto/qml/qmldesigner/coretests/testrewriterview.h +++ b/tests/auto/qml/qmldesigner/coretests/testrewriterview.h @@ -26,7 +26,8 @@ class TestRewriterView : public RewriterView Q_OBJECT public: - TestRewriterView(DifferenceHandling differenceHandling = RewriterView::Validate); + TestRewriterView(ExternalDependenciesInterface &externalDependencies, + DifferenceHandling differenceHandling = RewriterView::Validate); Internal::TestModelToTextMerger *modelToTextMerger() const; Internal::TextToModelMerger *textToModelMerger() const; diff --git a/tests/auto/qml/qmldesigner/coretests/tst_testcore.cpp b/tests/auto/qml/qmldesigner/coretests/tst_testcore.cpp index 0fc0e2f344..365748c1fb 100644 --- a/tests/auto/qml/qmldesigner/coretests/tst_testcore.cpp +++ b/tests/auto/qml/qmldesigner/coretests/tst_testcore.cpp @@ -10,19 +10,22 @@ #include <QTest> #include <QVariant> +#include <designersettings.h> +#include <externaldependenciesinterface.h> +#include <invalididexception.h> +#include <invalidmodelnodeexception.h> #include <metainfo.h> #include <model.h> #include <modelmerger.h> #include <modelnode.h> -#include <qmlanchors.h> -#include <invalididexception.h> -#include <invalidmodelnodeexception.h> -#include <rewritingexception.h> -#include <nodeinstanceview.h> #include <nodeinstance.h> -#include <subcomponentmanager.h> +#include <nodeinstanceview.h> +#include <rewritingexception.h> #include <stylesheetmerger.h> +#include <subcomponentmanager.h> #include <QDebug> +#include <qmlanchors.h> +#include <qmlmodelnodefacade.h> #include "../testconnectionmanager.h" #include "../testview.h" @@ -120,10 +123,53 @@ static void initializeMetaTypeSystem(const QString &resourcePath) qWarning() << qPrintable(errorAndWarning); } -static std::unique_ptr<QmlDesigner::Model> createModel(const QString &typeName, - int major = 2, - int minor = 1, - Model *metaInfoPropxyModel = 0) +namespace { + +class ExternalDependenciesFake : public QObject, public ExternalDependenciesInterface +{ +public: + ExternalDependenciesFake(Model &model) + : model{model} + {} + + double formEditorDevicePixelRatio() const override { return 1.; } + QString currentProjectDirPath() const override + { + return QFileInfo(model.fileUrl().toLocalFile()).absolutePath(); + } + + QUrl currentResourcePath() const override + { + return QUrl::fromLocalFile(QFileInfo(model.fileUrl().toLocalFile()).absolutePath()); + } + + QString defaultPuppetFallbackDirectory() const override { return {}; } + QString defaultPuppetToplevelBuildDirectory() const override { return {}; } + QString qmlPuppetFallbackDirectory() const override { return {}; } + QUrl projectUrl() const override { return {}; } + QList<QColor> designerSettingsEdit3DViewBackgroundColor() const override { return {}; } + QColor designerSettingsEdit3DViewGridColor() const override { return {}; } + void parseItemLibraryDescriptions() override {} + const QmlDesigner::DesignerSettings &designerSettings() const override { return settings; } + void undoOnCurrentDesignDocument() override {} + bool viewManagerUsesRewriterView(class RewriterView *) const override { return true; } + void viewManagerDiableWidgets() override {} + QString itemLibraryImportUserComponentsTitle() const override { return {}; } + bool isQt6Import() const override { return true; } + bool hasStartupTarget() const override { return true; } + PuppetStartData puppetStartData(const class Model &) const override { return {}; } + bool instantQmlTextUpdate() const override { return true; } + +public: + QSettings qsettings; + QmlDesigner::DesignerSettings settings{&qsettings}; + Model &model; +}; + +ModelPointer createModel(const QString &typeName, + int major = 2, + int minor = 1, + Model *metaInfoPropxyModel = 0) { QApplication::processEvents(); @@ -131,25 +177,41 @@ static std::unique_ptr<QmlDesigner::Model> createModel(const QString &typeName, QPlainTextEdit *textEdit = new QPlainTextEdit; QObject::connect(model.get(), &QObject::destroyed, textEdit, &QObject::deleteLater); - textEdit->setPlainText(QString("import %1 %3.%4; %2{}").arg(typeName.split(".").first()) - .arg(typeName.split(".").last()) - .arg(major) - .arg(minor)); + textEdit->setPlainText(QString("import %1 %3.%4; %2{}") + .arg(typeName.split(".").first()) + .arg(typeName.split(".").last()) + .arg(major) + .arg(minor)); NotIndentingTextEditModifier *modifier = new NotIndentingTextEditModifier(textEdit); modifier->setParent(textEdit); - auto rewriterView = new QmlDesigner::RewriterView(QmlDesigner::RewriterView::Validate); + auto externalDependencies = new ExternalDependenciesFake{*model}; + externalDependencies->setParent(model.get()); + + auto rewriterView = new QmlDesigner::RewriterView(*externalDependencies, + QmlDesigner::RewriterView::Validate); rewriterView->setParent(model.get()); - //rewriterView->setCheckSemanticErrors(false); + rewriterView->setCheckSemanticErrors(false); rewriterView->setTextModifier(modifier); model->attachView(rewriterView); return model; +} +auto createTextRewriterView( + Model &model, RewriterView::DifferenceHandling differenceHandling = RewriterView::Amend) +{ + auto externalDependencies = new ExternalDependenciesFake{model}; + auto rewriter = std::make_unique<TestRewriterView>(*externalDependencies, differenceHandling); + externalDependencies->setParent(rewriter.get()); + + return rewriter; } +} // namespace + tst_TestCore::tst_TestCore() : QObject() { @@ -160,6 +222,8 @@ tst_TestCore::tst_TestCore() void tst_TestCore::initTestCase() { + QmlModelNodeFacade::enableUglyWorkaroundForIsValidQmlModelNodeFacadeInTests(); + MetaInfo::disableParseItemLibraryDescriptionsUgly(); Exception::setShouldAssert(false); if (!QmlJS::ModelManagerInterface::instance()) @@ -228,9 +292,9 @@ void tst_TestCore::loadEmptyCoreModel() auto model1(Model::create("QtQuick.Item")); - QScopedPointer<TestRewriterView> testRewriterView1(new TestRewriterView()); + auto testRewriterView1 = createTextRewriterView(*model1); testRewriterView1->setTextModifier(&modifier1); - model1->attachView(testRewriterView1.data()); + model1->attachView(testRewriterView1.get()); QPlainTextEdit textEdit2; textEdit2.setPlainText("import QtQuick 1.1; Item{}"); @@ -238,9 +302,9 @@ void tst_TestCore::loadEmptyCoreModel() auto model2(Model::create("QtQuick.Item")); - QScopedPointer<TestRewriterView> testRewriterView2(new TestRewriterView()); + auto testRewriterView2 = createTextRewriterView(*model2); testRewriterView2->setTextModifier(&modifier2); - model2->attachView(testRewriterView2.data()); + model2->attachView(testRewriterView2.get()); QVERIFY(compareTree(testRewriterView1->rootModelNode(), testRewriterView2->rootModelNode())); } @@ -261,9 +325,9 @@ void tst_TestCore::testRewriterView2() ModelNode rootModelNode(view->rootModelNode()); QVERIFY(rootModelNode.isValid()); - QScopedPointer<TestRewriterView> testRewriterView(new TestRewriterView()); + auto testRewriterView = createTextRewriterView(*model); testRewriterView->setTextModifier(&textModifier); - model->attachView(testRewriterView.data()); + model->attachView(testRewriterView.get()); while (testRewriterView->hasIncompleteTypeInformation()) { QApplication::processEvents(QEventLoop::AllEvents, 1000); @@ -321,7 +385,7 @@ void tst_TestCore::testRewriterView2() .value(), QVariant(90)); - model->detachView(testRewriterView.data()); + model->detachView(testRewriterView.get()); } catch (Exception &e) { QFAIL(qPrintable(e.description())); } @@ -341,10 +405,10 @@ void tst_TestCore::testRewriterView() auto model(Model::create("QtQuick.Item", 2, 15)); QVERIFY(model.get()); - QScopedPointer<TestRewriterView> testRewriterView(new TestRewriterView()); + auto testRewriterView = createTextRewriterView(*model); testRewriterView->setTextModifier(&textModifier); testRewriterView->setCheckSemanticErrors(true); - model->attachView(testRewriterView.data()); + model->attachView(testRewriterView.get()); while (testRewriterView->hasIncompleteTypeInformation()) { QApplication::processEvents(QEventLoop::AllEvents, 1000); @@ -402,7 +466,7 @@ void tst_TestCore::testRewriterView() QCOMPARE(testRewriterView->modelToTextMerger()->findAddedVariantProperty(childNode.variantProperty("x")).value(), QVariant(70)); QCOMPARE(testRewriterView->modelToTextMerger()->findAddedVariantProperty(childNode.variantProperty("y")).value(), QVariant(90)); - model->detachView(testRewriterView.data()); + model->detachView(testRewriterView.get()); } catch (Exception &e) { QFAIL(qPrintable(e.description())); } @@ -423,9 +487,9 @@ void tst_TestCore::testRewriterErrors() ModelNode rootModelNode(view->rootModelNode()); QVERIFY(rootModelNode.isValid()); - QScopedPointer<TestRewriterView> testRewriterView(new TestRewriterView()); + auto testRewriterView = createTextRewriterView(*model); testRewriterView->setTextModifier(&textModifier); - model->attachView(testRewriterView.data()); + model->attachView(testRewriterView.get()); QVERIFY(testRewriterView->errors().isEmpty()); testRewriterView->setCheckSemanticErrors(true); @@ -448,9 +512,9 @@ void tst_TestCore::saveEmptyCoreModel() auto model1(Model::create("QtQuick.Item")); - QScopedPointer<TestRewriterView> testRewriterView1(new TestRewriterView()); + auto testRewriterView1 = createTextRewriterView(*model1); testRewriterView1->setTextModifier(&modifier1); - model1->attachView(testRewriterView1.data()); + model1->attachView(testRewriterView1.get()); QPlainTextEdit textEdit2; textEdit2.setPlainText("import QtQuick 1.1; Item{}"); @@ -458,9 +522,9 @@ void tst_TestCore::saveEmptyCoreModel() auto model2(Model::create("QtQuick.Item")); - QScopedPointer<TestRewriterView> testRewriterView2(new TestRewriterView()); + auto testRewriterView2 = createTextRewriterView(*model2); testRewriterView2->setTextModifier(&modifier2); - model2->attachView(testRewriterView2.data()); + model2->attachView(testRewriterView2.get()); QVERIFY(compareTree(testRewriterView1->rootModelNode(), testRewriterView2->rootModelNode())); } @@ -476,9 +540,9 @@ void tst_TestCore::loadAttributesInCoreModel() auto model1(Model::create("QtQuick.Item")); - QScopedPointer<TestRewriterView> testRewriterView1(new TestRewriterView()); + auto testRewriterView1 = createTextRewriterView(*model1); testRewriterView1->setTextModifier(&modifier1); - model1->attachView(testRewriterView1.data()); + model1->attachView(testRewriterView1.get()); QPlainTextEdit textEdit2; textEdit2.setPlainText("import QtQuick 1.1; Item{}"); @@ -486,9 +550,9 @@ void tst_TestCore::loadAttributesInCoreModel() auto model2(Model::create("QtQuick.Item")); - QScopedPointer<TestRewriterView> testRewriterView2(new TestRewriterView()); + auto testRewriterView2 = createTextRewriterView(*model2); testRewriterView2->setTextModifier(&modifier2); - model2->attachView(testRewriterView2.data()); + model2->attachView(testRewriterView2.get()); ModelNode rootModelNode = testRewriterView2->rootModelNode(); @@ -511,9 +575,9 @@ void tst_TestCore::saveAttributesInCoreModel() auto model1(Model::create("QtQuick.Item")); - QScopedPointer<TestRewriterView> testRewriterView1(new TestRewriterView()); + auto testRewriterView1 = createTextRewriterView(*model1); testRewriterView1->setTextModifier(&modifier1); - model1->attachView(testRewriterView1.data()); + model1->attachView(testRewriterView1.get()); QVERIFY(testRewriterView1->errors().isEmpty()); @@ -527,9 +591,9 @@ void tst_TestCore::saveAttributesInCoreModel() auto model2(Model::create("QtQuick.Item")); - QScopedPointer<TestRewriterView> testRewriterView2(new TestRewriterView()); + auto testRewriterView2 = createTextRewriterView(*model2); testRewriterView2->setTextModifier(&modifier2); - model2->attachView(testRewriterView2.data()); + model2->attachView(testRewriterView2.get()); QVERIFY(testRewriterView2->errors().isEmpty()); @@ -604,9 +668,9 @@ void tst_TestCore::testRewriterDynamicProperties() auto model1(Model::create("QtQuick.Item")); - QScopedPointer<TestRewriterView> testRewriterView1(new TestRewriterView()); + auto testRewriterView1 = createTextRewriterView(*model1); testRewriterView1->setTextModifier(&modifier1); - model1->attachView(testRewriterView1.data()); + model1->attachView(testRewriterView1.get()); QVERIFY(testRewriterView1->errors().isEmpty()); @@ -699,9 +763,9 @@ void tst_TestCore::testRewriterDynamicProperties() // // auto model2(Model::create("QtQuick.Item")); // - // QScopedPointer<TestRewriterView> testRewriterView2(new TestRewriterView()); + // auto testRewriterView2 = createTextRewriterView(*model2); // testRewriterView2->setTextModifier(&modifier2); - // model2->attachView(testRewriterView2.data()); + // model2->attachView(testRewriterView2.get()); // // testRewriterView2->rootModelNode().variantProperty("pushed").setDynamicTypeNameAndValue("bool", QVariant(false)); // @@ -726,9 +790,9 @@ void tst_TestCore::testRewriterGroupedProperties() auto model1(Model::create("QtQuick.Text")); - QScopedPointer<TestRewriterView> testRewriterView1(new TestRewriterView()); + auto testRewriterView1 = createTextRewriterView(*model1); testRewriterView1->setTextModifier(&modifier1); - model1->attachView(testRewriterView1.data()); + model1->attachView(testRewriterView1.get()); QVERIFY(testRewriterView1->errors().isEmpty()); @@ -808,9 +872,9 @@ void tst_TestCore::testRewriterPreserveOrder() auto model(Model::create("QtQuick.Text")); - QScopedPointer<TestRewriterView> testRewriterView(new TestRewriterView()); + auto testRewriterView = createTextRewriterView(*model); testRewriterView->setTextModifier(&modifier); - model->attachView(testRewriterView.data()); + model->attachView(testRewriterView.get()); QVERIFY(testRewriterView->errors().isEmpty()); @@ -843,9 +907,9 @@ void tst_TestCore::testRewriterPreserveOrder() auto model(Model::create("QtQuick.Text")); - QScopedPointer<TestRewriterView> testRewriterView(new TestRewriterView()); + auto testRewriterView = createTextRewriterView(*model); testRewriterView->setTextModifier(&modifier); - model->attachView(testRewriterView.data()); + model->attachView(testRewriterView.get()); QVERIFY(testRewriterView->errors().isEmpty()); @@ -897,9 +961,9 @@ void tst_TestCore::testRewriterActionCompression() auto model1(Model::create("QtQuick.Rectangle")); - QScopedPointer<TestRewriterView> testRewriterView(new TestRewriterView()); + auto testRewriterView = createTextRewriterView(*model1); testRewriterView->setTextModifier(&modifier1); - model1->attachView(testRewriterView.data()); + model1->attachView(testRewriterView.get()); QVERIFY(testRewriterView->errors().isEmpty()); @@ -952,9 +1016,9 @@ void tst_TestCore::testRewriterImports() auto model(Model::create("QtQuick.Item")); model->setFileUrl(QUrl::fromLocalFile(fileName)); - QScopedPointer<TestRewriterView> testRewriterView(new TestRewriterView()); + auto testRewriterView = createTextRewriterView(*model); testRewriterView->setTextModifier(&modifier); - model->attachView(testRewriterView.data()); + model->attachView(testRewriterView.get()); QVERIFY(testRewriterView->errors().isEmpty()); @@ -998,9 +1062,9 @@ void tst_TestCore::testRewriterChangeImports() auto model(Model::create("QtQuick.Rectangle")); - QScopedPointer<TestRewriterView> testRewriterView(new TestRewriterView(RewriterView::Amend)); + auto testRewriterView = createTextRewriterView(*model, RewriterView::Amend); testRewriterView->setTextModifier(&modifier); - model->attachView(testRewriterView.data()); + model->attachView(testRewriterView.get()); QVERIFY(testRewriterView->errors().isEmpty()); @@ -1082,9 +1146,9 @@ void tst_TestCore::testRewriterUnicodeChars() auto model(Model::create("QtQuick.Rectangle")); - QScopedPointer<TestRewriterView> testRewriterView(new TestRewriterView(RewriterView::Amend)); + auto testRewriterView = createTextRewriterView(*model, RewriterView::Amend); testRewriterView->setTextModifier(&modifier); - model->attachView(testRewriterView.data()); + model->attachView(testRewriterView.get()); QVERIFY(testRewriterView->errors().isEmpty()); @@ -1112,9 +1176,9 @@ void tst_TestCore::testRewriterTransactionAddingAfterReparenting() auto model(Model::create("QtQuick.Rectangle")); - QScopedPointer<TestRewriterView> testRewriterView(new TestRewriterView(RewriterView::Amend)); + auto testRewriterView = createTextRewriterView(*model, RewriterView::Amend); testRewriterView->setTextModifier(&modifier); - model->attachView(testRewriterView.data()); + model->attachView(testRewriterView.get()); QVERIFY(testRewriterView->errors().isEmpty()); @@ -1154,9 +1218,9 @@ void tst_TestCore::testRewriterReparentToNewNode() auto model(Model::create("QtQuick.Rectangle")); - QScopedPointer<TestRewriterView> testRewriterView(new TestRewriterView(RewriterView::Amend)); + auto testRewriterView = createTextRewriterView(*model, RewriterView::Amend); testRewriterView->setTextModifier(&modifier); - model->attachView(testRewriterView.data()); + model->attachView(testRewriterView.get()); QVERIFY(testRewriterView->errors().isEmpty()); @@ -1253,9 +1317,9 @@ void tst_TestCore::testRewriterBehaivours() auto model(Model::create("QtQuick.Rectangle")); - QScopedPointer<TestRewriterView> testRewriterView(new TestRewriterView(RewriterView::Amend)); + auto testRewriterView = createTextRewriterView(*model, RewriterView::Amend); testRewriterView->setTextModifier(&modifier); - model->attachView(testRewriterView.data()); + model->attachView(testRewriterView.get()); //qDebug() << testRewriterView->errors().first().toString(); QVERIFY(testRewriterView->errors().isEmpty()); @@ -1356,9 +1420,9 @@ void tst_TestCore::testRewriterSignalDefinition() auto model(Model::create("QtQuick.Text")); - QScopedPointer<TestRewriterView> testRewriterView(new TestRewriterView()); + auto testRewriterView = createTextRewriterView(*model); testRewriterView->setTextModifier(&modifier); - model->attachView(testRewriterView.data()); + model->attachView(testRewriterView.get()); QVERIFY(testRewriterView->errors().isEmpty()); @@ -1486,9 +1550,9 @@ void tst_TestCore::testRewriterForGradientMagic() auto model(Model::create("QtQuick.Text")); - QScopedPointer<TestRewriterView> testRewriterView(new TestRewriterView()); + auto testRewriterView = createTextRewriterView(*model); testRewriterView->setTextModifier(&modifier); - model->attachView(testRewriterView.data()); + model->attachView(testRewriterView.get()); QVERIFY(testRewriterView->errors().isEmpty()); @@ -1506,13 +1570,13 @@ void tst_TestCore::testRewriterForGradientMagic() QScopedPointer<TestView> view1(new TestView); model1->attachView(view1.data()); - QScopedPointer<TestRewriterView> testRewriterView1(new TestRewriterView()); + auto testRewriterView1 = createTextRewriterView(*model1); QPlainTextEdit textEdit1; textEdit1.setPlainText("import QtQuick 2.1; Item {}"); NotIndentingTextEditModifier modifier1(&textEdit1); testRewriterView1->setTextModifier(&modifier1); - model1->attachView(testRewriterView1.data()); + model1->attachView(testRewriterView1.get()); QVERIFY(testRewriterView1->errors().isEmpty()); @@ -1562,10 +1626,10 @@ void tst_TestCore::testStatesVersionFailing() ModelNode rootModelNode(view->rootModelNode()); QVERIFY(rootModelNode.isValid()); QCOMPARE(rootModelNode.type(), QmlDesigner::TypeName("QtQuick.Item")); - QScopedPointer<TestRewriterView> testRewriterView(new TestRewriterView()); + auto testRewriterView = createTextRewriterView(*model); testRewriterView->setTextModifier(&textModifier); - model->attachView(testRewriterView.data()); + model->attachView(testRewriterView.get()); QVERIFY(rootModelNode.isValid()); QCOMPARE(rootModelNode.type(), QmlDesigner::TypeName("QtQuick.Rectangle")); @@ -1645,9 +1709,9 @@ void tst_TestCore::loadSubItems() auto model1(Model::create("QtQuick.Item", 2, 0)); - QScopedPointer<TestRewriterView> testRewriterView1(new TestRewriterView()); + auto testRewriterView1 = createTextRewriterView(*model1); testRewriterView1->setTextModifier(&modifier1); - model1->attachView(testRewriterView1.data()); + model1->attachView(testRewriterView1.get()); } void tst_TestCore::createInvalidCoreModel() @@ -1694,13 +1758,6 @@ void tst_TestCore::testModelCreateSubNode() expectedCalls << TestView::MethodCall("nodeIdChanged", QStringList() << "blah" << "blah" << ""); QCOMPARE(view->methodCalls(), expectedCalls); - try { - childNode.setIdWithoutRefactoring("invalid id"); - QFAIL("Setting an invalid id does not throw an exception"); - } catch (Exception &exception) { - QCOMPARE(exception.type(), QString("InvalidIdException")); - } - QCOMPARE(childNode.id(), QString("blah")); QCOMPARE(view->methodCalls(), expectedCalls); @@ -1807,10 +1864,10 @@ void tst_TestCore::testBasicStates() ModelNode rootModelNode(view->rootModelNode()); QVERIFY(rootModelNode.isValid()); QCOMPARE(rootModelNode.type(), QmlDesigner::TypeName("QtQuick.Item")); - QScopedPointer<TestRewriterView> testRewriterView(new TestRewriterView()); + auto testRewriterView = createTextRewriterView(*model); testRewriterView->setTextModifier(&textModifier); - model->attachView(testRewriterView.data()); + model->attachView(testRewriterView.get()); QVERIFY(rootModelNode.isValid()); QCOMPARE(rootModelNode.type(), QmlDesigner::TypeName("QtQuick.Rectangle")); @@ -1906,9 +1963,9 @@ void tst_TestCore::testBasicStatesQtQuick20() auto model(Model::create("QtQuick.Item")); QVERIFY(model.get()); - QScopedPointer<TestRewriterView> testRewriterView(new TestRewriterView()); + auto testRewriterView = createTextRewriterView(*model); testRewriterView->setTextModifier(&textModifier); - model->attachView(testRewriterView.data()); + model->attachView(testRewriterView.get()); ModelNode rootModelNode(testRewriterView->rootModelNode()); QVERIFY(rootModelNode.isValid()); @@ -2234,9 +2291,9 @@ void tst_TestCore::testModelNodePropertyDynamicSource() auto model(Model::create("QtQuick.Item", 2, 1)); QVERIFY(model.get()); - QScopedPointer<TestRewriterView> testRewriterView(new TestRewriterView()); + auto testRewriterView = createTextRewriterView(*model); testRewriterView->setTextModifier(&textModifier); - model->attachView(testRewriterView.data()); + model->attachView(testRewriterView.get()); QVERIFY(model.get()); ModelNode rootModelNode(testRewriterView->rootModelNode()); @@ -2491,7 +2548,8 @@ void tst_TestCore::testModelRemoveNode() model->attachView(view.data()); TestConnectionManager connectionManager; - NodeInstanceView nodeInstanceView{connectionManager}; + ExternalDependenciesFake externalDependenciesFake{*model}; + NodeInstanceView nodeInstanceView{connectionManager, externalDependenciesFake}; model->attachView(&nodeInstanceView); QCOMPARE(view->rootModelNode().directSubModelNodes().count(), 0); @@ -2618,9 +2676,9 @@ void tst_TestCore::reparentingNodeLikeDragAndDrop() auto model(Model::create("QtQuick.Item")); QVERIFY(model.get()); - QScopedPointer<TestRewriterView> testRewriterView(new TestRewriterView()); + auto testRewriterView = createTextRewriterView(*model); testRewriterView->setTextModifier(&textModifier); - model->attachView(testRewriterView.data()); + model->attachView(testRewriterView.get()); QScopedPointer<TestView> view(new TestView); QVERIFY(view.data()); @@ -3068,11 +3126,10 @@ void tst_TestCore::testRewriterId() ModelNode rootModelNode(view->rootModelNode()); QVERIFY(rootModelNode.isValid()); - QScopedPointer<TestRewriterView> testRewriterView(new TestRewriterView()); + auto testRewriterView = createTextRewriterView(*model); testRewriterView->setTextModifier(&textModifier); - - model->attachView(testRewriterView.data()); + model->attachView(testRewriterView.get()); QCOMPARE(rootModelNode.type(), QmlDesigner::TypeName("QtQuick.Rectangle")); QVERIFY(rootModelNode.isValid()); @@ -3112,10 +3169,10 @@ void tst_TestCore::testRewriterNodeReparentingTransaction1() ModelNode rootModelNode(view->rootModelNode()); QVERIFY(rootModelNode.isValid()); QCOMPARE(rootModelNode.type(), QmlDesigner::TypeName("QtQuick.Item")); - QScopedPointer<TestRewriterView> testRewriterView(new TestRewriterView()); + auto testRewriterView = createTextRewriterView(*model); testRewriterView->setTextModifier(&textModifier); - model->attachView(testRewriterView.data()); + model->attachView(testRewriterView.get()); QVERIFY(rootModelNode.isValid()); @@ -3157,10 +3214,10 @@ void tst_TestCore::testRewriterNodeReparentingTransaction2() ModelNode rootModelNode(view->rootModelNode()); QVERIFY(rootModelNode.isValid()); QCOMPARE(rootModelNode.type(), QmlDesigner::TypeName("QtQuick.Item")); - QScopedPointer<TestRewriterView> testRewriterView(new TestRewriterView()); + auto testRewriterView = createTextRewriterView(*model); testRewriterView->setTextModifier(&textModifier); - model->attachView(testRewriterView.data()); + model->attachView(testRewriterView.get()); QVERIFY(rootModelNode.isValid()); @@ -3223,10 +3280,10 @@ void tst_TestCore::testRewriterNodeReparentingTransaction3() ModelNode rootModelNode(view->rootModelNode()); QVERIFY(rootModelNode.isValid()); QCOMPARE(rootModelNode.type(), QmlDesigner::TypeName("QtQuick.Item")); - QScopedPointer<TestRewriterView> testRewriterView(new TestRewriterView()); + auto testRewriterView = createTextRewriterView(*model); testRewriterView->setTextModifier(&textModifier); - model->attachView(testRewriterView.data()); + model->attachView(testRewriterView.get()); QVERIFY(rootModelNode.isValid()); @@ -3273,10 +3330,10 @@ void tst_TestCore::testRewriterNodeReparentingTransaction4() ModelNode rootModelNode(view->rootModelNode()); QVERIFY(rootModelNode.isValid()); QCOMPARE(rootModelNode.type(), QmlDesigner::TypeName("QtQuick.Item")); - QScopedPointer<TestRewriterView> testRewriterView(new TestRewriterView()); + auto testRewriterView = createTextRewriterView(*model); testRewriterView->setTextModifier(&textModifier); - model->attachView(testRewriterView.data()); + model->attachView(testRewriterView.get()); QVERIFY(rootModelNode.isValid()); @@ -3324,10 +3381,10 @@ void tst_TestCore::testRewriterAddNodeTransaction() ModelNode rootModelNode(view->rootModelNode()); QVERIFY(rootModelNode.isValid()); QCOMPARE(rootModelNode.type(), QmlDesigner::TypeName("QtQuick.Item")); - QScopedPointer<TestRewriterView> testRewriterView(new TestRewriterView()); + auto testRewriterView = createTextRewriterView(*model); testRewriterView->setTextModifier(&textModifier); - model->attachView(testRewriterView.data()); + model->attachView(testRewriterView.get()); QVERIFY(rootModelNode.isValid()); @@ -3368,11 +3425,11 @@ void tst_TestCore::testRewriterComponentId() QVERIFY(view.data()); model->attachView(view.data()); - QScopedPointer<TestRewriterView> testRewriterView(new TestRewriterView()); + auto testRewriterView = createTextRewriterView(*model); QVERIFY(!model->rewriterView()); testRewriterView->setTextModifier(&textModifier); - model->attachView(testRewriterView.data()); + model->attachView(testRewriterView.get()); QVERIFY(model->rewriterView()); QVERIFY(model->hasNodeMetaInfo("QtQuick.Item", 2, 1)); @@ -3407,10 +3464,10 @@ void tst_TestCore::testRewriterTransactionRewriter() ModelNode rootModelNode(view->rootModelNode()); QVERIFY(rootModelNode.isValid()); QCOMPARE(rootModelNode.type(), QmlDesigner::TypeName("QtQuick.Item")); - QScopedPointer<TestRewriterView> testRewriterView(new TestRewriterView()); + auto testRewriterView = createTextRewriterView(*model); testRewriterView->setTextModifier(&textModifier); - model->attachView(testRewriterView.data()); + model->attachView(testRewriterView.get()); QVERIFY(rootModelNode.isValid()); @@ -3476,9 +3533,9 @@ void tst_TestCore::testRewriterPropertyDeclarations() QVERIFY(view.data()); model->attachView(view.data()); - QScopedPointer<TestRewriterView> testRewriterView(new TestRewriterView()); + auto testRewriterView = createTextRewriterView(*model); testRewriterView->setTextModifier(&textModifier); - model->attachView(testRewriterView.data()); + model->attachView(testRewriterView.get()); QVERIFY(testRewriterView->errors().isEmpty()); @@ -3538,9 +3595,9 @@ void tst_TestCore::testRewriterPropertyAliases() QVERIFY(view.data()); model->attachView(view.data()); - QScopedPointer<TestRewriterView> testRewriterView(new TestRewriterView()); + auto testRewriterView = createTextRewriterView(*model); testRewriterView->setTextModifier(&textModifier); - model->attachView(testRewriterView.data()); + model->attachView(testRewriterView.get()); ModelNode rootModelNode(view->rootModelNode()); QVERIFY(rootModelNode.isValid()); @@ -3598,9 +3655,9 @@ void tst_TestCore::testRewriterPositionAndOffset() model->attachView(view.data()); // read in - QScopedPointer<TestRewriterView> testRewriterView(new TestRewriterView()); + auto testRewriterView = createTextRewriterView(*model); testRewriterView->setTextModifier(&textModifier); - model->attachView(testRewriterView.data()); + model->attachView(testRewriterView.get()); ModelNode rootNode = view->rootModelNode(); QVERIFY(rootNode.isValid()); @@ -3700,9 +3757,9 @@ void tst_TestCore::testRewriterComponentTextModifier() model->attachView(view.data()); // read in - QScopedPointer<TestRewriterView> testRewriterView(new TestRewriterView()); + auto testRewriterView = createTextRewriterView(*model); testRewriterView->setTextModifier(&textModifier); - model->attachView(testRewriterView.data()); + model->attachView(testRewriterView.get()); ModelNode rootNode = view->rootModelNode(); QVERIFY(rootNode.isValid()); @@ -3739,9 +3796,9 @@ void tst_TestCore::testRewriterComponentTextModifier() QCOMPARE(componentTextModifier.text(), qmlExpected); auto componentModel(Model::create("QtQuick.Item", 1, 1)); - QScopedPointer<TestRewriterView> testRewriterViewComponent(new TestRewriterView()); + auto testRewriterViewComponent = createTextRewriterView(*componentModel); testRewriterViewComponent->setTextModifier(&componentTextModifier); - componentModel->attachView(testRewriterViewComponent.data()); + componentModel->attachView(testRewriterViewComponent.get()); ModelNode componentrootNode = testRewriterViewComponent->rootModelNode(); QVERIFY(componentrootNode.isValid()); @@ -3771,9 +3828,9 @@ void tst_TestCore::testRewriterPreserveType() model->attachView(view.data()); // read in - QScopedPointer<TestRewriterView> testRewriterView(new TestRewriterView()); + auto testRewriterView = createTextRewriterView(*model); testRewriterView->setTextModifier(&textModifier); - model->attachView(testRewriterView.data()); + model->attachView(testRewriterView.get()); ModelNode rootNode = view->rootModelNode(); QVERIFY(rootNode.isValid()); @@ -3816,9 +3873,9 @@ void tst_TestCore::testRewriterForArrayMagic() model->attachView(view.data()); // read in - QScopedPointer<TestRewriterView> testRewriterView(new TestRewriterView()); + auto testRewriterView = createTextRewriterView(*model); testRewriterView->setTextModifier(&textModifier); - model->attachView(testRewriterView.data()); + model->attachView(testRewriterView.get()); ModelNode rootNode = view->rootModelNode(); QVERIFY(rootNode.isValid()); @@ -3868,9 +3925,9 @@ void tst_TestCore::testRewriterWithSignals() model->attachView(view.data()); // read in - QScopedPointer<TestRewriterView> testRewriterView(new TestRewriterView()); + auto testRewriterView = createTextRewriterView(*model); testRewriterView->setTextModifier(&textModifier); - model->attachView(testRewriterView.data()); + model->attachView(testRewriterView.get()); ModelNode rootNode = view->rootModelNode(); QVERIFY(rootNode.isValid()); @@ -3911,9 +3968,9 @@ void tst_TestCore::testRewriterNodeSliding() model->attachView(view.data()); // read in - QScopedPointer<TestRewriterView> testRewriterView(new TestRewriterView()); + auto testRewriterView = createTextRewriterView(*model); testRewriterView->setTextModifier(&textModifier); - model->attachView(testRewriterView.data()); + model->attachView(testRewriterView.get()); ModelNode rootNode = view->rootModelNode(); QVERIFY(rootNode.isValid()); @@ -3951,10 +4008,10 @@ void tst_TestCore::testRewriterExceptionHandling() model->attachView(view.data()); // read in - QScopedPointer<TestRewriterView> testRewriterView(new TestRewriterView()); + auto testRewriterView = createTextRewriterView(*model); testRewriterView->setTextModifier(&textModifier); testRewriterView->setCheckSemanticErrors(true); - model->attachView(testRewriterView.data()); + model->attachView(testRewriterView.get()); ModelNode rootNode = view->rootModelNode(); QVERIFY(rootNode.isValid()); @@ -4009,9 +4066,9 @@ void tst_TestCore::testRewriterFirstDefinitionInside() model->attachView(view.data()); // read in - QScopedPointer<TestRewriterView> testRewriterView(new TestRewriterView()); + auto testRewriterView = createTextRewriterView(*model); testRewriterView->setTextModifier(&textModifier); - model->attachView(testRewriterView.data()); + model->attachView(testRewriterView.get()); ModelNode rootNode = view->rootModelNode(); QVERIFY(rootNode.isValid()); @@ -4079,9 +4136,9 @@ void tst_TestCore::testCopyModelRewriter1() model1->attachView(view1.data()); // read in 1 - QScopedPointer<TestRewriterView> testRewriterView1(new TestRewriterView()); + auto testRewriterView1 = createTextRewriterView(*model1); testRewriterView1->setTextModifier(&textModifier1); - model1->attachView(testRewriterView1.data()); + model1->attachView(testRewriterView1.get()); ModelNode rootNode1 = view1->rootModelNode(); QVERIFY(rootNode1.isValid()); @@ -4098,9 +4155,9 @@ void tst_TestCore::testCopyModelRewriter1() model2->attachView(view2.data()); // read in 2 - QScopedPointer<TestRewriterView> testRewriterView2(new TestRewriterView()); + auto testRewriterView2 = createTextRewriterView(*model2); testRewriterView2->setTextModifier(&textModifier2); - model2->attachView(testRewriterView2.data()); + model2->attachView(testRewriterView2.get()); ModelNode rootNode2 = view2->rootModelNode(); QVERIFY(rootNode2.isValid()); @@ -4294,9 +4351,9 @@ void tst_TestCore::testMergeModelRewriter1() templateModel->attachView(templateView.data()); // read in 1 - QScopedPointer<TestRewriterView> templateRewriterView(new TestRewriterView()); + auto templateRewriterView = createTextRewriterView(*templateModel); templateRewriterView->setTextModifier(&textModifier1); - templateModel->attachView(templateRewriterView.data()); + templateModel->attachView(templateRewriterView.get()); ModelNode templateRootNode = templateView->rootModelNode(); QVERIFY(templateRootNode.isValid()); @@ -4312,9 +4369,9 @@ void tst_TestCore::testMergeModelRewriter1() styleModel->attachView(styleView.data()); // read in 2 - QScopedPointer<TestRewriterView> styleRewriterView(new TestRewriterView()); + auto styleRewriterView = createTextRewriterView(*styleModel); styleRewriterView->setTextModifier(&textModifier2); - styleModel->attachView(styleRewriterView.data()); + styleModel->attachView(styleRewriterView.get()); StylesheetMerger merger(templateView.data(), styleView.data()); merger.merge(); @@ -4384,9 +4441,9 @@ void tst_TestCore::testCopyModelRewriter2() templateModel->attachView(view1.data()); // read in 1 - QScopedPointer<TestRewriterView> testRewriterView1(new TestRewriterView()); + auto testRewriterView1 = createTextRewriterView(*templateModel); testRewriterView1->setTextModifier(&textModifier1); - templateModel->attachView(testRewriterView1.data()); + templateModel->attachView(testRewriterView1.get()); ModelNode rootNode1 = view1->rootModelNode(); QVERIFY(rootNode1.isValid()); @@ -4403,9 +4460,9 @@ void tst_TestCore::testCopyModelRewriter2() QScopedPointer<TestView> view2(new TestView); styleModel->attachView(view2.data()); - QScopedPointer<TestRewriterView> styleRewriterView(new TestRewriterView()); + auto styleRewriterView = createTextRewriterView(*styleModel); styleRewriterView->setTextModifier(&textModifier2); - styleModel->attachView(styleRewriterView.data()); + styleModel->attachView(styleRewriterView.get()); ModelNode rootNode2 = view2->rootModelNode(); QVERIFY(rootNode2.isValid()); @@ -4465,7 +4522,9 @@ void tst_TestCore::testSubComponentManager() auto model(createModel("QtQuick.Rectangle", 2, 15)); model->setFileUrl(QUrl::fromLocalFile(fileName)); - QScopedPointer<SubComponentManager> subComponentManager(new SubComponentManager(model.get())); + ExternalDependenciesFake externalDependenciesFake{*model}; + QScopedPointer<SubComponentManager> subComponentManager( + new SubComponentManager(model.get(), externalDependenciesFake)); subComponentManager->update(QUrl::fromLocalFile(fileName), model->imports()); QVERIFY(model->hasNodeMetaInfo("QtQuick.Rectangle", 2, 15)); @@ -4521,9 +4580,9 @@ void tst_TestCore::testAnchorsAndRewriting() model->attachView(view.data()); // read in - QScopedPointer<TestRewriterView> testRewriterView(new TestRewriterView()); + auto testRewriterView = createTextRewriterView(*model); testRewriterView->setTextModifier(&textModifier); - model->attachView(testRewriterView.data()); + model->attachView(testRewriterView.get()); ModelNode rootNode = view->rootModelNode(); QVERIFY(rootNode.isValid()); @@ -4587,9 +4646,9 @@ void tst_TestCore::testAnchorsAndRewritingCenter() model->attachView(view.data()); // read in - QScopedPointer<TestRewriterView> testRewriterView(new TestRewriterView()); + auto testRewriterView = createTextRewriterView(*model); testRewriterView->setTextModifier(&textModifier); - model->attachView(testRewriterView.data()); + model->attachView(testRewriterView.get()); ModelNode rootNode = view->rootModelNode(); QVERIFY(rootNode.isValid()); @@ -4659,11 +4718,11 @@ void tst_TestCore::loadQml() QVERIFY(rootModelNode.isValid()); QCOMPARE(rootModelNode.type(), QmlDesigner::TypeName("QtQuick.Item")); - QScopedPointer<TestRewriterView> testRewriterView(new TestRewriterView()); + auto testRewriterView = createTextRewriterView(*model); testRewriterView->setCheckSemanticErrors(true); testRewriterView->setTextModifier(&textModifier); - model->attachView(testRewriterView.data()); + model->attachView(testRewriterView.get()); while (testRewriterView->hasIncompleteTypeInformation()) { QApplication::processEvents(QEventLoop::AllEvents, 1000); @@ -4762,7 +4821,7 @@ void tst_TestCore::testMetaInfoSimpleType() QCOMPARE(itemMetaInfo.minorVersion(), 1); // super classes - NodeMetaInfo qobject = itemMetaInfo.superClasses().front(); + NodeMetaInfo qobject = itemMetaInfo.superClasses()[1]; QVERIFY(qobject.isValid()); QVERIFY(qobject.isQtObject()); @@ -4790,7 +4849,7 @@ void tst_TestCore::testMetaInfoUncreatableType() QCOMPARE(animationTypeInfo.majorVersion(), 2); QCOMPARE(animationTypeInfo.minorVersion(), 1); - NodeMetaInfo qObjectTypeInfo = animationTypeInfo.superClasses().front(); + NodeMetaInfo qObjectTypeInfo = animationTypeInfo.superClasses()[1]; QVERIFY(qObjectTypeInfo.isValid()); QCOMPARE(qObjectTypeInfo.simplifiedTypeName(), QmlDesigner::TypeName("QtObject")); @@ -4808,7 +4867,7 @@ void tst_TestCore::testMetaInfoExtendedType() QVERIFY(typeInfo.hasProperty("font")); // from QGraphicsWidget QVERIFY(typeInfo.hasProperty("enabled")); // from QGraphicsItem - NodeMetaInfo graphicsObjectTypeInfo = typeInfo.superClasses().front(); + NodeMetaInfo graphicsObjectTypeInfo = typeInfo.superClasses()[1]; QVERIFY(graphicsObjectTypeInfo.isValid()); } @@ -4830,7 +4889,7 @@ void tst_TestCore::testMetaInfoCustomType() QVERIFY(propertyChangesInfo.hasProperty("restoreEntryValues")); QVERIFY(propertyChangesInfo.hasProperty("explicit")); - NodeMetaInfo stateOperationInfo = propertyChangesInfo.superClasses().front(); + NodeMetaInfo stateOperationInfo = propertyChangesInfo.superClasses()[1]; QVERIFY(stateOperationInfo.isValid()); QCOMPARE(stateOperationInfo.typeName(), QmlDesigner::TypeName("QtQuick.QQuickStateOperation")); QCOMPARE(stateOperationInfo.majorVersion(), -1); @@ -4921,10 +4980,10 @@ void tst_TestCore::testMetaInfoQtQuickVersion2() auto model(Model::create("QtQuick.Item")); QVERIFY(model.get()); - QScopedPointer<TestRewriterView> testRewriterView(new TestRewriterView()); + auto testRewriterView = createTextRewriterView(*model); testRewriterView->setTextModifier(&textModifier); - model->attachView(testRewriterView.data()); + model->attachView(testRewriterView.get()); ModelNode rootModelNode = testRewriterView->rootModelNode(); QVERIFY(rootModelNode.isValid()); @@ -5030,7 +5089,7 @@ void tst_TestCore::testQtQuick20Basic() auto model(Model::create("QtQuick.Item")); QVERIFY(model.get()); - auto testRewriterView = std::make_unique<TestRewriterView>(); + auto testRewriterView = createTextRewriterView(*model); testRewriterView->setTextModifier(&modifier); model->attachView(testRewriterView.get()); @@ -5052,7 +5111,7 @@ void tst_TestCore::testQtQuick20BasicRectangle() auto model(Model::create("QtQuick.Item")); QVERIFY(model.get()); - auto testRewriterView = std::make_unique<TestRewriterView>(); + auto testRewriterView = createTextRewriterView(*model); testRewriterView->setTextModifier(&modifier); model->attachView(testRewriterView.get()); @@ -5098,7 +5157,7 @@ void tst_TestCore::testQtQuickControls2() QVERIFY(view.data()); model->attachView(view.data()); - auto testRewriterView = std::make_unique<TestRewriterView>(); + auto testRewriterView = createTextRewriterView(*model); testRewriterView->setTextModifier(&modifier); model->attachView(testRewriterView.get()); @@ -5192,7 +5251,7 @@ void tst_TestCore::testImplicitComponents() QVERIFY(view.data()); model->attachView(view.data()); - auto testRewriterView = std::make_unique<TestRewriterView>(); + auto testRewriterView = createTextRewriterView(*model); testRewriterView->setTextModifier(&modifier); model->attachView(testRewriterView.get()); @@ -5252,7 +5311,7 @@ void tst_TestCore::testRevisionedProperties() QVERIFY(view.data()); model->attachView(view.data()); - auto testRewriterView = std::make_unique<TestRewriterView>(); + auto testRewriterView = createTextRewriterView(*model); testRewriterView->setCheckSemanticErrors(true); testRewriterView->setTextModifier(&modifier); model->attachView(testRewriterView.get()); @@ -5286,7 +5345,7 @@ void tst_TestCore::testStatesRewriter() QVERIFY(view.data()); model->attachView(view.data()); - auto testRewriterView = std::make_unique<TestRewriterView>(); + auto testRewriterView = createTextRewriterView(*model); testRewriterView->setTextModifier(&modifier); model->attachView(testRewriterView.get()); @@ -5335,7 +5394,7 @@ void tst_TestCore::testGradientsRewriter() QVERIFY(view.data()); model->attachView(view.data()); - auto testRewriterView = std::make_unique<TestRewriterView>(); + auto testRewriterView = createTextRewriterView(*model); testRewriterView->setTextModifier(&modifier); model->attachView(testRewriterView.get()); @@ -6655,8 +6714,8 @@ void tst_TestCore::testInstancesAttachToExistingModel() // Attach NodeInstanceView TestConnectionManager connectionManager; - - NodeInstanceView instanceView{connectionManager}; + ExternalDependenciesFake externalDependenciesFake{*model}; + NodeInstanceView instanceView{connectionManager, externalDependenciesFake}; model->attachView(&instanceView); @@ -6739,7 +6798,7 @@ void tst_TestCore::testQmlModelStateWithName() auto model1(Model::create("QtQuick.Item")); - auto testRewriterView1 = std::make_unique<TestRewriterView>(); + auto testRewriterView1 = createTextRewriterView(*model1); testRewriterView1->setTextModifier(&modifier1); model1->attachView(testRewriterView1.get()); @@ -6791,7 +6850,7 @@ void tst_TestCore::testRewriterAutomaticSemicolonAfterChangedProperty() auto model1(Model::create("QtQuick.Item")); - auto testRewriterView1 = std::make_unique<TestRewriterView>(); + auto testRewriterView1 = createTextRewriterView(*model1); testRewriterView1->setTextModifier(&modifier1); model1->attachView(testRewriterView1.get()); @@ -6835,9 +6894,9 @@ void tst_TestCore::testModelPropertyValueTypes() auto model1(Model::create("QtQuick.Item")); - QScopedPointer<TestRewriterView> testRewriterView1(new TestRewriterView()); + auto testRewriterView1 = createTextRewriterView(*model1); testRewriterView1->setTextModifier(&modifier1); - model1->attachView(testRewriterView1.data()); + model1->attachView(testRewriterView1.get()); QVERIFY(testRewriterView1->errors().isEmpty()); @@ -6936,9 +6995,9 @@ void tst_TestCore::testModelChangeType() model->attachView(view.data()); // read in - QScopedPointer<TestRewriterView> testRewriterView(new TestRewriterView()); + auto testRewriterView = createTextRewriterView(*model); testRewriterView->setTextModifier(&textModifier); - model->attachView(testRewriterView.data()); + model->attachView(testRewriterView.get()); ModelNode rootNode = view->rootModelNode(); QVERIFY(rootNode.isValid()); @@ -7045,9 +7104,9 @@ void tst_TestCore::loadAnchors() auto model(Model::create("QtQuick.Item")); - QScopedPointer<TestRewriterView> testRewriterView1(new TestRewriterView()); + auto testRewriterView1 = createTextRewriterView(*model); testRewriterView1->setTextModifier(&modifier1); - model->attachView(testRewriterView1.data()); + model->attachView(testRewriterView1.get()); auto testView = std::make_unique<TestView>(); model->attachView(testView.get()); @@ -7084,9 +7143,9 @@ void tst_TestCore::changeAnchors() auto model(Model::create("QtQuick.Item")); - QScopedPointer<TestRewriterView> testRewriterView1(new TestRewriterView()); + auto testRewriterView1 = createTextRewriterView(*model); testRewriterView1->setTextModifier(&modifier1); - model->attachView(testRewriterView1.data()); + model->attachView(testRewriterView1.get()); auto testView = std::make_unique<TestView>(); @@ -7147,9 +7206,9 @@ void tst_TestCore::anchorToSibling() auto model(Model::create("QtQuick.Item")); - QScopedPointer<TestRewriterView> testRewriterView1(new TestRewriterView()); + auto testRewriterView1 = createTextRewriterView(*model); testRewriterView1->setTextModifier(&modifier1); - model->attachView(testRewriterView1.data()); + model->attachView(testRewriterView1.get()); auto testView = std::make_unique<TestView>(); @@ -7193,9 +7252,9 @@ void tst_TestCore::removeFillAnchorByDetaching() auto model(Model::create("QtQuick.Item")); - QScopedPointer<TestRewriterView> testRewriterView1(new TestRewriterView()); + auto testRewriterView1 = createTextRewriterView(*model); testRewriterView1->setTextModifier(&modifier1); - model->attachView(testRewriterView1.data()); + model->attachView(testRewriterView1.get()); auto testView = std::make_unique<TestView>(); @@ -7274,9 +7333,9 @@ void tst_TestCore::removeFillAnchorByChanging() auto model(Model::create("QtQuick.Item")); - QScopedPointer<TestRewriterView> testRewriterView1(new TestRewriterView()); + auto testRewriterView1 = createTextRewriterView(*model); testRewriterView1->setTextModifier(&modifier1); - model->attachView(testRewriterView1.data()); + model->attachView(testRewriterView1.get()); auto testView = std::make_unique<TestView>(); @@ -7541,9 +7600,9 @@ void tst_TestCore::testRewriterChangeId() QVERIFY(view.data()); model->attachView(view.data()); - QScopedPointer<TestRewriterView> testRewriterView(new TestRewriterView()); + auto testRewriterView = createTextRewriterView(*model); testRewriterView->setTextModifier(&textModifier); - model->attachView(testRewriterView.data()); + model->attachView(testRewriterView.get()); ModelNode rootModelNode(view->rootModelNode()); QVERIFY(rootModelNode.isValid()); @@ -7579,9 +7638,9 @@ void tst_TestCore::testRewriterRemoveId() QVERIFY(view.data()); model->attachView(view.data()); - QScopedPointer<TestRewriterView> testRewriterView(new TestRewriterView(TestRewriterView::Amend)); + auto testRewriterView = createTextRewriterView(*model, TestRewriterView::Amend); testRewriterView->setTextModifier(&textModifier); - model->attachView(testRewriterView.data()); + model->attachView(testRewriterView.get()); ModelNode rootModelNode(view->rootModelNode()); QVERIFY(rootModelNode.isValid()); @@ -7611,9 +7670,9 @@ void tst_TestCore::testRewriterChangeValueProperty() QVERIFY(view.data()); model->attachView(view.data()); - QScopedPointer<TestRewriterView> testRewriterView(new TestRewriterView()); + auto testRewriterView = createTextRewriterView(*model); testRewriterView->setTextModifier(&textModifier); - model->attachView(testRewriterView.data()); + model->attachView(testRewriterView.get()); ModelNode rootModelNode(view->rootModelNode()); QVERIFY(rootModelNode.isValid()); @@ -7651,9 +7710,9 @@ void tst_TestCore::testRewriterRemoveValueProperty() QVERIFY(view.data()); model->attachView(view.data()); - QScopedPointer<TestRewriterView> testRewriterView(new TestRewriterView()); + auto testRewriterView = createTextRewriterView(*model); testRewriterView->setTextModifier(&textModifier); - model->attachView(testRewriterView.data()); + model->attachView(testRewriterView.get()); ModelNode rootModelNode(view->rootModelNode()); QVERIFY(rootModelNode.isValid()); @@ -7693,9 +7752,9 @@ void tst_TestCore::testRewriterSignalProperty() QVERIFY(view.data()); model->attachView(view.data()); - QScopedPointer<TestRewriterView> testRewriterView(new TestRewriterView()); + auto testRewriterView = createTextRewriterView(*model); testRewriterView->setTextModifier(&textModifier); - model->attachView(testRewriterView.data()); + model->attachView(testRewriterView.get()); ModelNode rootModelNode(view->rootModelNode()); QVERIFY(rootModelNode.isValid()); @@ -7718,9 +7777,9 @@ void tst_TestCore::testRewriterObjectTypeProperty() QVERIFY(view.data()); model->attachView(view.data()); - QScopedPointer<TestRewriterView> testRewriterView(new TestRewriterView()); + auto testRewriterView = createTextRewriterView(*model); testRewriterView->setTextModifier(&textModifier); - model->attachView(testRewriterView.data()); + model->attachView(testRewriterView.get()); ModelNode rootModelNode(view->rootModelNode()); QVERIFY(rootModelNode.isValid()); @@ -7766,9 +7825,9 @@ void tst_TestCore::testRewriterPropertyChanges() model->attachView(view.data()); // read in - QScopedPointer<TestRewriterView> testRewriterView(new TestRewriterView()); + auto testRewriterView = createTextRewriterView(*model); testRewriterView->setTextModifier(&textModifier); - model->attachView(testRewriterView.data()); + model->attachView(testRewriterView.get()); ModelNode rootNode = view->rootModelNode(); QVERIFY(rootNode.isValid()); @@ -7817,9 +7876,9 @@ void tst_TestCore::testRewriterListModel() auto model(Model::create("QtQuick.Item", 2, 1)); QVERIFY(model.get()); - QScopedPointer<TestRewriterView> testRewriterView(new TestRewriterView()); + auto testRewriterView = createTextRewriterView(*model); testRewriterView->setTextModifier(&textModifier); - model->attachView(testRewriterView.data()); + model->attachView(testRewriterView.get()); QScopedPointer<TestView> view(new TestView); model->attachView(view.data()); @@ -7857,9 +7916,9 @@ void tst_TestCore::testRewriterAddProperty() model->attachView(view.data()); // read in - QScopedPointer<TestRewriterView> testRewriterView(new TestRewriterView()); + auto testRewriterView = createTextRewriterView(*model); testRewriterView->setTextModifier(&textModifier); - model->attachView(testRewriterView.data()); + model->attachView(testRewriterView.get()); ModelNode rootNode = view->rootModelNode(); QVERIFY(rootNode.isValid()); @@ -7901,9 +7960,9 @@ void tst_TestCore::testRewriterAddPropertyInNestedObject() model->attachView(view.data()); // read in - QScopedPointer<TestRewriterView> testRewriterView(new TestRewriterView()); + auto testRewriterView = createTextRewriterView(*model); testRewriterView->setTextModifier(&textModifier); - model->attachView(testRewriterView.data()); + model->attachView(testRewriterView.get()); ModelNode rootNode = view->rootModelNode(); QVERIFY(rootNode.isValid()); @@ -7947,9 +8006,9 @@ void tst_TestCore::testRewriterAddObjectDefinition() model->attachView(view.data()); // read in - QScopedPointer<TestRewriterView> testRewriterView(new TestRewriterView()); + auto testRewriterView = createTextRewriterView(*model); testRewriterView->setTextModifier(&textModifier); - model->attachView(testRewriterView.data()); + model->attachView(testRewriterView.get()); ModelNode rootNode = view->rootModelNode(); QVERIFY(rootNode.isValid()); @@ -7980,9 +8039,9 @@ void tst_TestCore::testRewriterAddStatesArray() QScopedPointer<TestView> view(new TestView); model->attachView(view.data()); - QScopedPointer<TestRewriterView> testRewriterView(new TestRewriterView()); + auto testRewriterView = createTextRewriterView(*model); testRewriterView->setTextModifier(&textModifier); - model->attachView(testRewriterView.data()); + model->attachView(testRewriterView.get()); ModelNode rootNode = view->rootModelNode(); QVERIFY(rootNode.isValid()); @@ -8042,9 +8101,9 @@ void tst_TestCore::testRewriterRemoveStates() QScopedPointer<TestView> view(new TestView); model->attachView(view.data()); - QScopedPointer<TestRewriterView> testRewriterView(new TestRewriterView()); + auto testRewriterView = createTextRewriterView(*model); testRewriterView->setTextModifier(&textModifier); - model->attachView(testRewriterView.data()); + model->attachView(testRewriterView.get()); ModelNode rootNode = view->rootModelNode(); QVERIFY(rootNode.isValid()); @@ -8101,9 +8160,9 @@ void tst_TestCore::testRewriterRemoveObjectDefinition() model->attachView(view.data()); // read in - QScopedPointer<TestRewriterView> testRewriterView(new TestRewriterView()); + auto testRewriterView = createTextRewriterView(*model); testRewriterView->setTextModifier(&textModifier); - model->attachView(testRewriterView.data()); + model->attachView(testRewriterView.get()); ModelNode rootNode = view->rootModelNode(); QVERIFY(rootNode.isValid()); @@ -8160,9 +8219,9 @@ void tst_TestCore::testRewriterRemoveScriptBinding() model->attachView(view.data()); // read in - QScopedPointer<TestRewriterView> testRewriterView(new TestRewriterView()); + auto testRewriterView = createTextRewriterView(*model); testRewriterView->setTextModifier(&textModifier); - model->attachView(testRewriterView.data()); + model->attachView(testRewriterView.get()); ModelNode rootNode = view->rootModelNode(); QVERIFY(rootNode.isValid()); @@ -8213,9 +8272,9 @@ void tst_TestCore::testRewriterNodeReparenting() model->attachView(view.data()); // read in - QScopedPointer<TestRewriterView> testRewriterView(new TestRewriterView()); + auto testRewriterView = createTextRewriterView(*model); testRewriterView->setTextModifier(&textModifier); - model->attachView(testRewriterView.data()); + model->attachView(testRewriterView.get()); ModelNode rootNode = view->rootModelNode(); QVERIFY(rootNode.isValid()); @@ -8321,9 +8380,9 @@ void tst_TestCore::testRewriterNodeReparentingWithTransaction() model->attachView(view.data()); // read in - QScopedPointer<TestRewriterView> testRewriterView(new TestRewriterView()); + auto testRewriterView = createTextRewriterView(*model); testRewriterView->setTextModifier(&textModifier); - model->attachView(testRewriterView.data()); + model->attachView(testRewriterView.get()); ModelNode rootNode = view->rootModelNode(); QVERIFY(rootNode.isValid()); @@ -8382,9 +8441,9 @@ void tst_TestCore::testRewriterMovingInOut() model->attachView(view.data()); // read in - QScopedPointer<TestRewriterView> testRewriterView(new TestRewriterView()); + auto testRewriterView = createTextRewriterView(*model); testRewriterView->setTextModifier(&textModifier); - model->attachView(testRewriterView.data()); + model->attachView(testRewriterView.get()); ModelNode rootNode = view->rootModelNode(); QVERIFY(rootNode.isValid()); @@ -8440,9 +8499,9 @@ void tst_TestCore::testRewriterMovingInOutWithTransaction() model->attachView(view.data()); // read in - QScopedPointer<TestRewriterView> testRewriterView(new TestRewriterView()); + auto testRewriterView = createTextRewriterView(*model); testRewriterView->setTextModifier(&textModifier); - model->attachView(testRewriterView.data()); + model->attachView(testRewriterView.get()); ModelNode rootNode = view->rootModelNode(); QVERIFY(rootNode.isValid()); @@ -8494,9 +8553,9 @@ void tst_TestCore::testRewriterComplexMovingInOut() model->attachView(view.data()); // read in - QScopedPointer<TestRewriterView> testRewriterView(new TestRewriterView()); + auto testRewriterView = createTextRewriterView(*model); testRewriterView->setTextModifier(&textModifier); - model->attachView(testRewriterView.data()); + model->attachView(testRewriterView.get()); ModelNode rootNode = view->rootModelNode(); QVERIFY(rootNode.isValid()); @@ -8582,9 +8641,9 @@ void tst_TestCore::removeCenteredInAnchorByDetaching() auto model(Model::create("QtQuick.Item")); - QScopedPointer<TestRewriterView> testRewriterView1(new TestRewriterView()); + auto testRewriterView1 = createTextRewriterView(*model); testRewriterView1->setTextModifier(&modifier1); - model->attachView(testRewriterView1.data()); + model->attachView(testRewriterView1.get()); auto testView = std::make_unique<TestView>(); @@ -8682,9 +8741,9 @@ void tst_TestCore::loadTestFiles() auto model(Model::create("QtQuick.Item", 1, 1)); QVERIFY(model.get()); - QScopedPointer<TestRewriterView> testRewriterView(new TestRewriterView()); + auto testRewriterView = createTextRewriterView(*model); testRewriterView->setTextModifier(&textModifier); - model->attachView(testRewriterView.data()); + model->attachView(testRewriterView.get()); QVERIFY(model.get()); ModelNode rootModelNode(testRewriterView->rootModelNode()); @@ -8704,9 +8763,9 @@ void tst_TestCore::loadTestFiles() auto model(Model::create("QtQuick.Item", 2, 1)); QVERIFY(model.get()); - QScopedPointer<TestRewriterView> testRewriterView(new TestRewriterView()); + auto testRewriterView = createTextRewriterView(*model); testRewriterView->setTextModifier(&textModifier); - model->attachView(testRewriterView.data()); + model->attachView(testRewriterView.get()); QVERIFY(model.get()); ModelNode rootModelNode(testRewriterView->rootModelNode()); @@ -8733,9 +8792,9 @@ void tst_TestCore::loadTestFiles() auto model(Model::create("QtQuick.Item", 2, 1)); QVERIFY(model.get()); - QScopedPointer<TestRewriterView> testRewriterView(new TestRewriterView()); + auto testRewriterView = createTextRewriterView(*model); testRewriterView->setTextModifier(&textModifier); - model->attachView(testRewriterView.data()); + model->attachView(testRewriterView.get()); QVERIFY(model.get()); ModelNode rootModelNode(testRewriterView->rootModelNode()); @@ -8781,9 +8840,9 @@ void tst_TestCore::loadTestFiles() auto model(Model::create("QtQuick.Item", 2, 1)); QVERIFY(model.get()); - QScopedPointer<TestRewriterView> testRewriterView(new TestRewriterView()); + auto testRewriterView = createTextRewriterView(*model); testRewriterView->setTextModifier(&textModifier); - model->attachView(testRewriterView.data()); + model->attachView(testRewriterView.get()); QVERIFY(testRewriterView->errors().isEmpty()); @@ -8818,9 +8877,9 @@ void tst_TestCore::loadGradient() auto model(Model::create("QtQuick.Item", 2, 1)); QVERIFY(model.get()); - QScopedPointer<TestRewriterView> testRewriterView(new TestRewriterView()); + auto testRewriterView = createTextRewriterView(*model); testRewriterView->setTextModifier(&textModifier); - model->attachView(testRewriterView.data()); + model->attachView(testRewriterView.get()); QVERIFY(model.get()); ModelNode rootModelNode(testRewriterView->rootModelNode()); @@ -8916,9 +8975,9 @@ void tst_TestCore::changeGradientId() auto model(Model::create("QtQuick.Item", 2, 1)); QVERIFY(model.get()); - QScopedPointer<TestRewriterView> testRewriterView(new TestRewriterView()); + auto testRewriterView = createTextRewriterView(*model); testRewriterView->setTextModifier(&textModifier); - model->attachView(testRewriterView.data()); + model->attachView(testRewriterView.get()); QVERIFY(model.get()); ModelNode rootModelNode(testRewriterView->rootModelNode()); @@ -9016,9 +9075,9 @@ void tst_TestCore::writeAnnotations() auto model(Model::create("QtQuick.Item", 2, 1)); QVERIFY(model.get()); - QScopedPointer<TestRewriterView> testRewriterView(new TestRewriterView()); + auto testRewriterView = createTextRewriterView(*model); testRewriterView->setTextModifier(&textModifier); - model->attachView(testRewriterView.data()); + model->attachView(testRewriterView.get()); QVERIFY(model.get()); ModelNode rootModelNode(testRewriterView->rootModelNode()); @@ -9034,7 +9093,7 @@ void tst_TestCore::writeAnnotations() const QString metaSource = testRewriterView->auxiliaryDataAsQML(); QmlJS::SimpleReader reader; - checkChildNodes(reader.readFromSource(metaSource), testRewriterView.data()); + checkChildNodes(reader.readFromSource(metaSource), testRewriterView.get()); testRewriterView->writeAuxiliaryData(); const QString textWithMeta = testRewriterView->textModifier()->text(); @@ -9070,9 +9129,9 @@ void tst_TestCore::readAnnotations() auto model(Model::create("QtQuick.Item", 2, 1)); QVERIFY(model.get()); - QScopedPointer<TestRewriterView> testRewriterView(new TestRewriterView()); + auto testRewriterView = createTextRewriterView(*model); testRewriterView->setTextModifier(&textModifier); - model->attachView(testRewriterView.data()); + model->attachView(testRewriterView.get()); QVERIFY(model.get()); ModelNode rootModelNode(testRewriterView->rootModelNode()); diff --git a/tests/auto/qml/qmldesigner/testview.cpp b/tests/auto/qml/qmldesigner/testview.cpp index d698023e88..d22ee79efc 100644 --- a/tests/auto/qml/qmldesigner/testview.cpp +++ b/tests/auto/qml/qmldesigner/testview.cpp @@ -15,7 +15,9 @@ #include <model.h> #include <nodeinstanceview.h> -TestView::TestView() {} +TestView::TestView(QmlDesigner::ExternalDependenciesInterface *externalDependencies) + : QmlDesigner::AbstractView{*externalDependencies} +{} void TestView::modelAttached(QmlDesigner::Model *model) { @@ -196,7 +198,7 @@ QString TestView::lastFunction() const return m_methodCalls.last().name; } -QmlDesigner::NodeInstanceView *TestView::nodeInstanceView() const +const QmlDesigner::NodeInstanceView *TestView::nodeInstanceView() const { return QmlDesigner::AbstractView::nodeInstanceView(); diff --git a/tests/auto/qml/qmldesigner/testview.h b/tests/auto/qml/qmldesigner/testview.h index e8983efa26..5a79444f68 100644 --- a/tests/auto/qml/qmldesigner/testview.h +++ b/tests/auto/qml/qmldesigner/testview.h @@ -29,7 +29,7 @@ public: QStringList arguments; }; - TestView(); + TestView(QmlDesigner::ExternalDependenciesInterface *externalDependencies = nullptr); void modelAttached(QmlDesigner::Model *model); void modelAboutToBeDetached(QmlDesigner::Model *model); @@ -77,7 +77,7 @@ public: QString lastFunction() const; - QmlDesigner::NodeInstanceView *nodeInstanceView() const; + const QmlDesigner::NodeInstanceView *nodeInstanceView() const; QmlDesigner::QmlObjectNode rootQmlObjectNode() const; diff --git a/tests/auto/qml/qmlprojectmanager/fileformat/tst_fileformat.cpp b/tests/auto/qml/qmlprojectmanager/fileformat/tst_fileformat.cpp index f3329d97c8..028a29b01a 100644 --- a/tests/auto/qml/qmlprojectmanager/fileformat/tst_fileformat.cpp +++ b/tests/auto/qml/qmlprojectmanager/fileformat/tst_fileformat.cpp @@ -41,7 +41,7 @@ tst_FileFormat::tst_FileFormat() static QString testDataDir = QLatin1String(SRCDIR "/data"); -static QmlProjectItem *loadQmlProject(QString name, QString *error) +static std::unique_ptr<QmlProjectItem> loadQmlProject(QString name, QString *error) { return QmlProjectFileFormat::parseProjectFile( Utils::FilePath::fromString(testDataDir).pathAppended(name + ".qmlproject"), error); @@ -54,7 +54,7 @@ void tst_FileFormat::testFileFilter() // Search for qml files in directory + subdirectories // { - QmlProjectItem *project = loadQmlProject(QLatin1String("testFileFilter1"), &error); + auto project = loadQmlProject(QLatin1String("testFileFilter1"), &error); QVERIFY(project); QVERIFY(error.isEmpty()); @@ -64,14 +64,13 @@ void tst_FileFormat::testFileFilter() << testDataDir + "/file2.qml" << testDataDir + "/subdir/file3.qml"); COMPARE_AS_SETS(project->files(), expectedFiles); - delete project; } // // search for all qml files in directory // { - QmlProjectItem *project = loadQmlProject(QLatin1String("testFileFilter2"), &error); + auto project = loadQmlProject(QLatin1String("testFileFilter2"), &error); QVERIFY(project); QVERIFY(error.isEmpty()); @@ -80,14 +79,13 @@ void tst_FileFormat::testFileFilter() QStringList expectedFiles(QStringList() << testDataDir + "/file1.qml" << testDataDir + "/file2.qml"); COMPARE_AS_SETS(project->files(), expectedFiles); - delete project; } // // search for all qml files in subdirectory // { - QmlProjectItem *project = loadQmlProject(QLatin1String("testFileFilter3"), &error); + auto project = loadQmlProject(QLatin1String("testFileFilter3"), &error); QVERIFY(project); QVERIFY(error.isEmpty()); @@ -95,14 +93,13 @@ void tst_FileFormat::testFileFilter() QStringList expectedFiles(QStringList() << testDataDir + "/subdir/file3.qml"); COMPARE_AS_SETS(project->files(), expectedFiles); - delete project; } // // multiple entries // { - QmlProjectItem *project = loadQmlProject(QLatin1String("testFileFilter4"), &error); + auto project = loadQmlProject(QLatin1String("testFileFilter4"), &error); QVERIFY(project); QVERIFY(error.isEmpty()); @@ -113,14 +110,13 @@ void tst_FileFormat::testFileFilter() << testDataDir + "/subdir/file3.qml"); QCOMPARE(project->files().size(), 3); COMPARE_AS_SETS(project->files(), expectedFiles); - delete project; } // // include specific list // { - QmlProjectItem *project = loadQmlProject(QLatin1String("testFileFilter5"), &error); + auto project = loadQmlProject(QLatin1String("testFileFilter5"), &error); QVERIFY(project); QVERIFY(error.isEmpty()); @@ -129,14 +125,13 @@ void tst_FileFormat::testFileFilter() QStringList expectedFiles(QStringList() << testDataDir + "/file1.qml" << testDataDir + "/file2.qml"); COMPARE_AS_SETS(project->files(), expectedFiles); - delete project; } // // include specific list // { - QmlProjectItem *project = loadQmlProject(QLatin1String("testFileFilter6"), &error); + auto project = loadQmlProject(QLatin1String("testFileFilter6"), &error); QVERIFY(project); QVERIFY(error.isEmpty()); @@ -144,14 +139,13 @@ void tst_FileFormat::testFileFilter() QStringList expectedFiles(QStringList() << testDataDir + "/image.gif"); COMPARE_AS_SETS(project->files(), expectedFiles); - delete project; } // // use wildcards // { - QmlProjectItem *project = loadQmlProject(QLatin1String("testFileFilter7"), &error); + auto project = loadQmlProject(QLatin1String("testFileFilter7"), &error); QVERIFY(project); QVERIFY(error.isEmpty()); @@ -159,14 +153,13 @@ void tst_FileFormat::testFileFilter() QStringList expectedFiles(QStringList() << testDataDir + "/image.gif"); COMPARE_AS_SETS(project->files(), expectedFiles); - delete project; } // // use Files element (1.1) // { - QmlProjectItem *project = loadQmlProject(QLatin1String("testFileFilter8"), &error); + auto project = loadQmlProject(QLatin1String("testFileFilter8"), &error); QVERIFY(project); QVERIFY(error.isEmpty()); @@ -174,7 +167,6 @@ void tst_FileFormat::testFileFilter() QStringList expectedFiles(QStringList() << testDataDir + "/image.gif"); COMPARE_AS_SETS(project->files(), expectedFiles); - delete project; } } @@ -184,7 +176,7 @@ void tst_FileFormat::testMatchesFile() // // search for qml files in local directory // - QmlProjectItem *project = loadQmlProject(QLatin1String("testMatchesFile"), &error); + auto project = loadQmlProject(QLatin1String("testMatchesFile"), &error); QVERIFY(project); QVERIFY(error.isEmpty()); @@ -195,7 +187,6 @@ void tst_FileFormat::testMatchesFile() QVERIFY(project->matchesFile(testDataDir + "/subdir/notyetexistingfile.qml")); QVERIFY(project->matchesFile(testDataDir + "/script.js")); QVERIFY(!project->matchesFile(testDataDir + "/script.css")); - delete project; } void tst_FileFormat::testLibraryPaths() @@ -204,7 +195,7 @@ void tst_FileFormat::testLibraryPaths() // // search for qml files in local directory // - QmlProjectItem *project = loadQmlProject(QLatin1String("testLibraryPaths"), &error); + auto project = loadQmlProject(QLatin1String("testLibraryPaths"), &error); QVERIFY(project); QVERIFY(error.isEmpty()); @@ -214,7 +205,6 @@ void tst_FileFormat::testLibraryPaths() const QStringList expectedPaths({base.relativeFilePath(SRCDIR "/otherLibrary"), base.relativeFilePath(SRCDIR "/data/library")}); COMPARE_AS_SETS(project->importPaths(), expectedPaths); - delete project; } void tst_FileFormat::testMainFile() @@ -223,12 +213,11 @@ void tst_FileFormat::testMainFile() // // search for qml files in local directory // - QmlProjectItem *project = loadQmlProject(QLatin1String("testMainFile"), &error); + auto project = loadQmlProject(QLatin1String("testMainFile"), &error); QVERIFY(project); QVERIFY(error.isEmpty()); QCOMPARE(project->mainFile(), QString("file1.qml")); - delete project; } QTEST_GUILESS_MAIN(tst_FileFormat); diff --git a/tests/auto/utils/CMakeLists.txt b/tests/auto/utils/CMakeLists.txt index b8be57696b..29548a5680 100644 --- a/tests/auto/utils/CMakeLists.txt +++ b/tests/auto/utils/CMakeLists.txt @@ -1,13 +1,18 @@ add_subdirectory(ansiescapecodehandler) +add_subdirectory(asynctask) +add_subdirectory(commandline) +add_subdirectory(deviceshell) +add_subdirectory(expected) add_subdirectory(fileutils) +add_subdirectory(fsengine) add_subdirectory(fuzzymatcher) add_subdirectory(indexedcontainerproxyconstiterator) +add_subdirectory(mathutils) +add_subdirectory(multicursor) add_subdirectory(persistentsettings) add_subdirectory(qtcprocess) add_subdirectory(settings) add_subdirectory(stringutils) +add_subdirectory(tasktree) add_subdirectory(templateengine) add_subdirectory(treemodel) -add_subdirectory(multicursor) -add_subdirectory(deviceshell) -add_subdirectory(fsengine) diff --git a/tests/auto/utils/asynctask/CMakeLists.txt b/tests/auto/utils/asynctask/CMakeLists.txt new file mode 100644 index 0000000000..8b234dbb02 --- /dev/null +++ b/tests/auto/utils/asynctask/CMakeLists.txt @@ -0,0 +1,4 @@ +add_qtc_test(tst_utils_asynctask + DEPENDS Utils + SOURCES tst_asynctask.cpp +) diff --git a/tests/auto/utils/asynctask/asynctask.qbs b/tests/auto/utils/asynctask/asynctask.qbs new file mode 100644 index 0000000000..8f478147e8 --- /dev/null +++ b/tests/auto/utils/asynctask/asynctask.qbs @@ -0,0 +1,7 @@ +import qbs + +QtcAutotest { + name: "AsyncTask autotest" + Depends { name: "Utils" } + files: "tst_asynctask.cpp" +} diff --git a/tests/auto/utils/asynctask/tst_asynctask.cpp b/tests/auto/utils/asynctask/tst_asynctask.cpp new file mode 100644 index 0000000000..ebe0d5c289 --- /dev/null +++ b/tests/auto/utils/asynctask/tst_asynctask.cpp @@ -0,0 +1,437 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0+ OR GPL-3.0 WITH Qt-GPL-exception-1.0 + +#include "utils/asynctask.h" + +#include "utils/algorithm.h" + +#include <QtTest> + +using namespace Utils; + +class tst_AsyncTask : public QObject +{ + Q_OBJECT + +private slots: + void runAsync(); + void crefFunction(); + void futureSynchonizer(); + void taskTree(); + void mapReduce_data(); + void mapReduce(); +private: + QThreadPool m_threadPool; +}; + +void report3(QFutureInterface<int> &fi) +{ + fi.reportResults({0, 2, 1}); +} + +void reportN(QFutureInterface<double> &fi, int n) +{ + fi.reportResults(QVector<double>(n, 0)); +} + +void reportString1(QFutureInterface<QString> &fi, const QString &s) +{ + fi.reportResult(s); +} + +void reportString2(QFutureInterface<QString> &fi, QString s) +{ + fi.reportResult(s); +} + +class Callable { +public: + void operator()(QFutureInterface<double> &fi, int n) const + { + fi.reportResults(QVector<double>(n, 0)); + } +}; + +class MyObject { +public: + static void staticMember0(QFutureInterface<double> &fi) + { + fi.reportResults({0, 2, 1}); + } + + static void staticMember1(QFutureInterface<double> &fi, int n) + { + fi.reportResults(QVector<double>(n, 0)); + } + + void member0(QFutureInterface<double> &fi) const + { + fi.reportResults({0, 2, 1}); + } + + void member1(QFutureInterface<double> &fi, int n) const + { + fi.reportResults(QVector<double>(n, 0)); + } + + void memberString1(QFutureInterface<QString> &fi, const QString &s) const + { + fi.reportResult(s); + } + + void memberString2(QFutureInterface<QString> &fi, QString s) const + { + fi.reportResult(s); + } + + void nonConstMember(QFutureInterface<double> &fi) + { + fi.reportResults({0, 2, 1}); + } +}; + +template <typename Function, typename ...Args, + typename ResultType = typename Internal::resultType<Function>::type> +std::shared_ptr<AsyncTask<ResultType>> createAsyncTask(const Function &function, const Args &...args) +{ + auto asyncTask = std::make_shared<AsyncTask<ResultType>>(); + asyncTask->setAsyncCallData(function, args...); + asyncTask->start(); + return asyncTask; +} + +void tst_AsyncTask::runAsync() +{ + // free function pointer + QCOMPARE(createAsyncTask(&report3)->results(), + QList<int>({0, 2, 1})); + QCOMPARE(createAsyncTask(report3)->results(), + QList<int>({0, 2, 1})); + + QCOMPARE(createAsyncTask(reportN, 4)->results(), + QList<double>({0, 0, 0, 0})); + QCOMPARE(createAsyncTask(reportN, 2)->results(), + QList<double>({0, 0})); + + QString s = QLatin1String("string"); + const QString &crs = QLatin1String("cr string"); + const QString cs = QLatin1String("c string"); + + QCOMPARE(createAsyncTask(reportString1, s)->results(), + QList<QString>({s})); + QCOMPARE(createAsyncTask(reportString1, crs)->results(), + QList<QString>({crs})); + QCOMPARE(createAsyncTask(reportString1, cs)->results(), + QList<QString>({cs})); + QCOMPARE(createAsyncTask(reportString1, QString(QLatin1String("rvalue")))->results(), + QList<QString>({QString(QLatin1String("rvalue"))})); + + QCOMPARE(createAsyncTask(reportString2, s)->results(), + QList<QString>({s})); + QCOMPARE(createAsyncTask(reportString2, crs)->results(), + QList<QString>({crs})); + QCOMPARE(createAsyncTask(reportString2, cs)->results(), + QList<QString>({cs})); + QCOMPARE(createAsyncTask(reportString2, QString(QLatin1String("rvalue")))->results(), + QList<QString>({QString(QLatin1String("rvalue"))})); + + // lambda + QCOMPARE(createAsyncTask([](QFutureInterface<double> &fi, int n) { + fi.reportResults(QVector<double>(n, 0)); + }, 3)->results(), + QList<double>({0, 0, 0})); + + // std::function + const std::function<void(QFutureInterface<double>&,int)> fun = [](QFutureInterface<double> &fi, int n) { + fi.reportResults(QVector<double>(n, 0)); + }; + QCOMPARE(createAsyncTask(fun, 2)->results(), + QList<double>({0, 0})); + + // operator() + QCOMPARE(createAsyncTask(Callable(), 3)->results(), + QList<double>({0, 0, 0})); + const Callable c{}; + QCOMPARE(createAsyncTask(c, 2)->results(), + QList<double>({0, 0})); + + // static member functions + QCOMPARE(createAsyncTask(&MyObject::staticMember0)->results(), + QList<double>({0, 2, 1})); + QCOMPARE(createAsyncTask(&MyObject::staticMember1, 2)->results(), + QList<double>({0, 0})); + + // member functions + const MyObject obj{}; + QCOMPARE(createAsyncTask(&MyObject::member0, &obj)->results(), + QList<double>({0, 2, 1})); + QCOMPARE(createAsyncTask(&MyObject::member1, &obj, 4)->results(), + QList<double>({0, 0, 0, 0})); + QCOMPARE(createAsyncTask(&MyObject::memberString1, &obj, s)->results(), + QList<QString>({s})); + QCOMPARE(createAsyncTask(&MyObject::memberString1, &obj, crs)->results(), + QList<QString>({crs})); + QCOMPARE(createAsyncTask(&MyObject::memberString1, &obj, cs)->results(), + QList<QString>({cs})); + QCOMPARE(createAsyncTask(&MyObject::memberString1, &obj, QString(QLatin1String("rvalue")))->results(), + QList<QString>({QString(QLatin1String("rvalue"))})); + QCOMPARE(createAsyncTask(&MyObject::memberString2, &obj, s)->results(), + QList<QString>({s})); + QCOMPARE(createAsyncTask(&MyObject::memberString2, &obj, crs)->results(), + QList<QString>({crs})); + QCOMPARE(createAsyncTask(&MyObject::memberString2, &obj, cs)->results(), + QList<QString>({cs})); + QCOMPARE(createAsyncTask(&MyObject::memberString2, &obj, QString(QLatin1String("rvalue")))->results(), + QList<QString>({QString(QLatin1String("rvalue"))})); + MyObject nonConstObj{}; + QCOMPARE(createAsyncTask(&MyObject::nonConstMember, &nonConstObj)->results(), + QList<double>({0, 2, 1})); +} + +void tst_AsyncTask::crefFunction() +{ + // free function pointer with future interface + auto fun = &report3; + QCOMPARE(createAsyncTask(std::cref(fun))->results(), + QList<int>({0, 2, 1})); + + // lambda with future interface + auto lambda = [](QFutureInterface<double> &fi, int n) { + fi.reportResults(QVector<double>(n, 0)); + }; + QCOMPARE(createAsyncTask(std::cref(lambda), 3)->results(), + QList<double>({0, 0, 0})); + + // std::function with future interface + const std::function<void(QFutureInterface<double>&,int)> funObj = [](QFutureInterface<double> &fi, int n) { + fi.reportResults(QVector<double>(n, 0)); + }; + QCOMPARE(createAsyncTask(std::cref(funObj), 2)->results(), + QList<double>({0, 0})); + + // callable with future interface + const Callable c{}; + QCOMPARE(createAsyncTask(std::cref(c), 2)->results(), + QList<double>({0, 0})); + + // member functions with future interface + auto member = &MyObject::member0; + const MyObject obj{}; + QCOMPARE(createAsyncTask(std::cref(member), &obj)->results(), + QList<double>({0, 2, 1})); +} + +template <typename Function, typename ...Args, + typename ResultType = typename Internal::resultType<Function>::type> +typename AsyncTask<ResultType>::StartHandler startHandler(const Function &function, const Args &...args) +{ + return [=] { return Utils::runAsync(function, args...); }; +} + +void tst_AsyncTask::futureSynchonizer() +{ + auto lambda = [](QFutureInterface<int> &fi) { + while (true) { + if (fi.isCanceled()) { + fi.reportCanceled(); + fi.reportFinished(); + return; + } + QThread::msleep(100); + } + }; + + FutureSynchronizer synchronizer; + { + AsyncTask<int> task; + task.setAsyncCallData(lambda); + task.setFutureSynchronizer(&synchronizer); + task.start(); + QThread::msleep(10); + // We assume here that worker thread will still work for about 90 ms. + QVERIFY(!task.isCanceled()); + QVERIFY(!task.isDone()); + } + synchronizer.flushFinishedFutures(); + QVERIFY(!synchronizer.isEmpty()); + // The destructor of synchronizer should wait for about 90 ms for worker thread to be canceled +} + +void multiplyBy2(QFutureInterface<int> &fi, int input) { fi.reportResult(input * 2); } + +void tst_AsyncTask::taskTree() +{ + using namespace Tasking; + + int value = 1; + + const auto setupIntAsync = [&](AsyncTask<int> &task) { + task.setAsyncCallData(multiplyBy2, value); + }; + const auto handleIntAsync = [&](const AsyncTask<int> &task) { + value = task.result(); + }; + + const Group root { + Async<int>(setupIntAsync, handleIntAsync), + Async<int>(setupIntAsync, handleIntAsync), + Async<int>(setupIntAsync, handleIntAsync), + Async<int>(setupIntAsync, handleIntAsync), + }; + + TaskTree tree(root); + + QEventLoop eventLoop; + connect(&tree, &TaskTree::done, &eventLoop, &QEventLoop::quit); + tree.start(); + eventLoop.exec(); + + QCOMPARE(value, 16); +} + +static int returnxx(int x) +{ + return x * x; +} + +static void returnxxWithFI(QFutureInterface<int> &fi, int x) +{ + fi.reportResult(x * x); +} + +static double s_sum = 0; +static QList<double> s_results; + +void tst_AsyncTask::mapReduce_data() +{ + using namespace Tasking; + + QTest::addColumn<Group>("root"); + QTest::addColumn<double>("sum"); + QTest::addColumn<QList<double>>("results"); + + const auto initTree = [] { + s_sum = 0; + s_results.append(s_sum); + }; + const auto setupAsync = [](AsyncTask<int> &task, int input) { + task.setAsyncCallData(returnxx, input); + }; + const auto setupAsyncWithFI = [](AsyncTask<int> &task, int input) { + task.setAsyncCallData(returnxxWithFI, input); + }; + const auto setupAsyncWithTP = [this](AsyncTask<int> &task, int input) { + task.setAsyncCallData(returnxx, input); + task.setThreadPool(&m_threadPool); + }; + const auto handleAsync = [](const AsyncTask<int> &task) { + s_sum += task.result(); + s_results.append(task.result()); + }; + const auto handleTreeParallel = [] { + s_sum /= 2; + s_results.append(s_sum); + Utils::sort(s_results); // mapping order is undefined + }; + const auto handleTreeSequential = [] { + s_sum /= 2; + s_results.append(s_sum); + }; + + using namespace Tasking; + using namespace std::placeholders; + + using SetupHandler = std::function<void(AsyncTask<int> &task, int input)>; + using DoneHandler = std::function<void()>; + + const auto createTask = [=](const TaskItem &executeMode, + const SetupHandler &setupHandler, + const DoneHandler &doneHandler) { + return Group { + executeMode, + OnGroupSetup(initTree), + Async<int>(std::bind(setupHandler, _1, 1), handleAsync), + Async<int>(std::bind(setupHandler, _1, 2), handleAsync), + Async<int>(std::bind(setupHandler, _1, 3), handleAsync), + Async<int>(std::bind(setupHandler, _1, 4), handleAsync), + Async<int>(std::bind(setupHandler, _1, 5), handleAsync), + OnGroupDone(doneHandler) + }; + }; + + const Group parallelRoot = createTask(parallel, setupAsync, handleTreeParallel); + const Group parallelRootWithFI = createTask(parallel, setupAsyncWithFI, handleTreeParallel); + const Group parallelRootWithTP = createTask(parallel, setupAsyncWithTP, handleTreeParallel); + const Group sequentialRoot = createTask(sequential, setupAsync, handleTreeSequential); + const Group sequentialRootWithFI = createTask(sequential, setupAsyncWithFI, handleTreeSequential); + const Group sequentialRootWithTP = createTask(sequential, setupAsyncWithTP, handleTreeSequential); + + const double defaultSum = 27.5; + const QList<double> defaultResult{0., 1., 4., 9., 16., 25., 27.5}; + + QTest::newRow("Parallel") << parallelRoot << defaultSum << defaultResult; + QTest::newRow("ParallelWithFutureInterface") << parallelRootWithFI << defaultSum << defaultResult; + QTest::newRow("ParallelWithThreadPool") << parallelRootWithTP << defaultSum << defaultResult; + QTest::newRow("Sequential") << sequentialRoot << defaultSum << defaultResult; + QTest::newRow("SequentialWithFutureInterface") << sequentialRootWithFI << defaultSum << defaultResult; + QTest::newRow("SequentialWithThreadPool") << sequentialRootWithTP << defaultSum << defaultResult; + + const auto setupSimpleAsync = [](AsyncTask<int> &task, int input) { + task.setAsyncCallData([](int input) { return input * 2; }, input); + }; + const auto handleSimpleAsync = [](const AsyncTask<int> &task) { + s_sum += task.result() / 4.; + s_results.append(s_sum); + }; + const Group simpleRoot = { + sequential, + OnGroupSetup([] { s_sum = 0; }), + Async<int>(std::bind(setupSimpleAsync, _1, 1), handleSimpleAsync), + Async<int>(std::bind(setupSimpleAsync, _1, 2), handleSimpleAsync), + Async<int>(std::bind(setupSimpleAsync, _1, 3), handleSimpleAsync) + }; + QTest::newRow("Simple") << simpleRoot << 3.0 << QList<double>({.5, 1.5, 3.}); + + const auto setupStringAsync = [](AsyncTask<int> &task, const QString &input) { + task.setAsyncCallData([](const QString &input) -> int { return input.size(); }, input); + }; + const auto handleStringAsync = [](const AsyncTask<int> &task) { + s_sum /= task.result(); + }; + const Group stringRoot = { + parallel, + OnGroupSetup([] { s_sum = 90.0; }), + Async<int>(std::bind(setupStringAsync, _1, "blubb"), handleStringAsync), + Async<int>(std::bind(setupStringAsync, _1, "foo"), handleStringAsync), + Async<int>(std::bind(setupStringAsync, _1, "blah"), handleStringAsync) + }; + QTest::newRow("String") << stringRoot << 1.5 << QList<double>({}); +} + +void tst_AsyncTask::mapReduce() +{ + QThreadPool pool; + + s_sum = 0; + s_results.clear(); + + using namespace Tasking; + + QFETCH(Group, root); + QFETCH(double, sum); + QFETCH(QList<double>, results); + + TaskTree tree(root); + + QEventLoop eventLoop; + connect(&tree, &TaskTree::done, &eventLoop, &QEventLoop::quit); + tree.start(); + eventLoop.exec(); + + QCOMPARE(s_results, results); + QCOMPARE(s_sum, sum); +} + +QTEST_GUILESS_MAIN(tst_AsyncTask) + +#include "tst_asynctask.moc" diff --git a/tests/auto/utils/commandline/CMakeLists.txt b/tests/auto/utils/commandline/CMakeLists.txt new file mode 100644 index 0000000000..b839403bfe --- /dev/null +++ b/tests/auto/utils/commandline/CMakeLists.txt @@ -0,0 +1,8 @@ +file(RELATIVE_PATH RELATIVE_TEST_PATH "${PROJECT_BINARY_DIR}" "${CMAKE_CURRENT_BINARY_DIR}") +file(RELATIVE_PATH TEST_RELATIVE_LIBEXEC_PATH "/${RELATIVE_TEST_PATH}" "/${IDE_LIBEXEC_PATH}") + +add_qtc_test(tst_utils_commandline + DEFINES "TEST_RELATIVE_LIBEXEC_PATH=\"${TEST_RELATIVE_LIBEXEC_PATH}\"" + DEPENDS Utils app_version + SOURCES tst_commandline.cpp +) diff --git a/tests/auto/utils/commandline/commandline.qbs b/tests/auto/utils/commandline/commandline.qbs new file mode 100644 index 0000000000..4b3e337ce1 --- /dev/null +++ b/tests/auto/utils/commandline/commandline.qbs @@ -0,0 +1,12 @@ +Project { + QtcAutotest { + name: "CommandLine autotest" + + Depends { name: "Utils" } + Depends { name: "app_version_header" } + + files: [ + "tst_commandline.cpp", + ] + } +} diff --git a/tests/auto/utils/commandline/tst_commandline.cpp b/tests/auto/utils/commandline/tst_commandline.cpp new file mode 100644 index 0000000000..1845e3fa1e --- /dev/null +++ b/tests/auto/utils/commandline/tst_commandline.cpp @@ -0,0 +1,149 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0+ OR GPL-3.0 WITH Qt-GPL-exception-1.0 + +#include <app/app_version.h> + +#include <utils/commandline.h> +#include <utils/environment.h> +#include <utils/hostosinfo.h> +#include <utils/launcherinterface.h> +#include <utils/processinterface.h> +#include <utils/qtcprocess.h> +#include <utils/temporarydirectory.h> + +#include <QObject> +#include <QtTest> + +#include <iostream> + +using namespace Utils; + +FilePath self; + +class tst_CommandLine : public QObject +{ + Q_OBJECT +private: + Environment testEnv = Environment::systemEnvironment(); + QString newLine; + + QString run(const CommandLine &cmd) + { + QtcProcess p; + p.setCommand(cmd); + p.setEnvironment(testEnv); + p.runBlocking(); + return QString::fromUtf8(p.readAllStandardOutput()); + } + +private slots: + void initTestCase() + { + TemporaryDirectory::setMasterTemporaryDirectory( + QDir::tempPath() + "/" + Core::Constants::IDE_CASED_ID + "-XXXXXX"); + + const QString libExecPath(qApp->applicationDirPath() + '/' + + QLatin1String(TEST_RELATIVE_LIBEXEC_PATH)); + LauncherInterface::setPathToLauncher(libExecPath); + + testEnv.appendOrSet("TEST_ECHO", "1"); + + if (HostOsInfo::isWindowsHost()) + newLine = "\r\n"; + else + newLine = "\n"; + } + + void cleanupTestCase() { Singleton::deleteAll(); } + + void testSpace() + { + CommandLine cmd(self, {"With Space"}); + QString expected = "With Space" + newLine; + QCOMPARE(run(cmd), expected); + } + + void testQuote() + { + QStringList args = {"\"With <\"Quote\"> % ^^ \"", "Hallo ??"}; + CommandLine cmd(self, args); + QString expected = args.join(newLine) + newLine; + QCOMPARE(run(cmd), expected); + } + + void testAnd() + { + QStringList args = {"foo", "bar", "baz"}; + CommandLine cmd(self, {args[0]}); + CommandLine cmd2(self, args.sliced(1)); + + cmd.addCommandLineWithAnd(cmd2); + + QString expected = args.join(newLine) + newLine; + + QCOMPARE(run(cmd), expected); + } + + void testAndComplex() + { + QStringList args = {"foo", "long with space", "bar\"", "blizz is 'great"}; + CommandLine cmd(self, args.sliced(0, 2)); + CommandLine cmd2(self, args.sliced(2, 2)); + + cmd.addCommandLineWithAnd(cmd2); + QString expected = args.join(newLine) + newLine; + QString actual = run(cmd); + QCOMPARE(actual, expected); + } + + void testAndAdd() + { + if (HostOsInfo::isWindowsHost()) + QSKIP("The test does not yet work on Windows."); + + QStringList args = {"foo", "long with space", "bar", "blizz is great"}; + + CommandLine cmd(self, args.sliced(0, 2)); + CommandLine cmd2(self, args.sliced(2, 2)); + + cmd.addCommandLineWithAnd(cmd2); + + CommandLine shell; + if (HostOsInfo::isWindowsHost()) { + shell.setExecutable(FilePath::fromUserInput(qEnvironmentVariable("COMSPEC"))); + shell.addArgs({"/v:off", "/s", "/c"}); + } else { + shell.setExecutable(FilePath::fromUserInput("/bin/sh")); + shell.addArgs({"-c"}); + } + + shell.addCommandLineAsSingleArg(cmd); + + QString expected = args.join(newLine) + newLine; + QString actual = run(shell); + QCOMPARE(actual, expected); + } +}; + +int main(int argc, char *argv[]) +{ + QCoreApplication app(argc, argv); + + self = FilePath::fromString(argv[0]); + + if (qEnvironmentVariableIsSet("TEST_ECHO")) { + for (int i = 1; i < argc; ++i) { + std::cout << argv[i] << std::endl; + } + return 0; + } + + TESTLIB_SELFCOVERAGE_START(tst_CommandLine) + QT_PREPEND_NAMESPACE(QTest::Internal::callInitMain)<tst_CommandLine>(); + + tst_CommandLine tc; + QTEST_SET_MAIN_SOURCE_PATH + return QTest::qExec(&tc, argc, argv); +} + +#include "tst_commandline.moc" diff --git a/tests/auto/utils/expected/CMakeLists.txt b/tests/auto/utils/expected/CMakeLists.txt new file mode 100644 index 0000000000..cfc5c62c3f --- /dev/null +++ b/tests/auto/utils/expected/CMakeLists.txt @@ -0,0 +1,4 @@ +add_qtc_test(tst_utils_expected + DEPENDS Utils + SOURCES tst_expected.cpp +) diff --git a/tests/auto/utils/expected/expected.qbs b/tests/auto/utils/expected/expected.qbs new file mode 100644 index 0000000000..490a721928 --- /dev/null +++ b/tests/auto/utils/expected/expected.qbs @@ -0,0 +1,7 @@ +import qbs + +QtcAutotest { + name: "Expected autotest" + Depends { name: "Utils" } + files: "tst_expected.cpp" +} diff --git a/tests/auto/utils/expected/tst_expected.cpp b/tests/auto/utils/expected/tst_expected.cpp new file mode 100644 index 0000000000..0003dc01ba --- /dev/null +++ b/tests/auto/utils/expected/tst_expected.cpp @@ -0,0 +1,38 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0+ OR GPL-3.0 WITH Qt-GPL-exception-1.0 + +#include <QtTest/qtestcase.h> +#include <QtTest> + +#include <utils/expected.h> +#include <utils/filepath.h> + +using namespace Utils; + +class tst_expected : public QObject +{ + Q_OBJECT + +private slots: + void initTestCase() {} + + void tryMonads() + { + FilePath p = "idontexists.ne"; + + auto result = p.fileContents() + .and_then([](auto) { return expected_str<QByteArray>{}; }) + .or_else([](auto error) { + return expected_str<QByteArray>( + make_unexpected(QString("Error: " + error))); + }) + .transform_or([](auto error) -> QString { + return QString(QString("More Info: ") + error); + }); + + QVERIFY(!result); + } +}; +QTEST_GUILESS_MAIN(tst_expected) + +#include "tst_expected.moc" diff --git a/tests/auto/utils/fileutils/tst_fileutils.cpp b/tests/auto/utils/fileutils/tst_fileutils.cpp index 1446f82096..cf5f2758e1 100644 --- a/tests/auto/utils/fileutils/tst_fileutils.cpp +++ b/tests/auto/utils/fileutils/tst_fileutils.cpp @@ -1,9 +1,9 @@ // Copyright (C) 2016 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0+ OR GPL-3.0 WITH Qt-GPL-exception-1.0 -#include <QtTest> #include <QDebug> #include <QRandomGenerator> +#include <QtTest> #include <utils/fileutils.h> #include <utils/hostosinfo.h> @@ -13,12 +13,12 @@ using namespace Utils; namespace QTest { - template<> - char *toString(const FilePath &filePath) - { - return qstrdup(filePath.toString().toLocal8Bit().constData()); - } +template<> +char *toString(const FilePath &filePath) +{ + return qstrdup(filePath.toString().toLocal8Bit().constData()); } +} // namespace QTest class tst_fileutils : public QObject { @@ -58,6 +58,9 @@ private slots: void fromString_data(); void fromString(); + void fromUserInput_data(); + void fromUserInput(); + void toString_data(); void toString(); @@ -84,8 +87,10 @@ private slots: void bytesAvailableFromDF_data(); void bytesAvailableFromDF(); + void rootLength_data(); void rootLength(); + void schemeAndHostLength_data(); void schemeAndHostLength(); @@ -96,8 +101,8 @@ private slots: void onDevice_data(); void onDevice(); - void plus(); - void plus_data(); + void stringAppended(); + void stringAppended_data(); void url(); void url_data(); @@ -203,7 +208,7 @@ void tst_fileutils::parentDir() QFETCH(QString, parentPath); QFETCH(QString, expectFailMessage); - FilePath result = FilePath::fromString(path).parentDir(); + FilePath result = FilePath::fromUserInput(path).parentDir(); if (!expectFailMessage.isEmpty()) QEXPECT_FAIL("", expectFailMessage.toUtf8().constData(), Continue); QCOMPARE(result.toString(), parentPath); @@ -243,8 +248,8 @@ void tst_fileutils::isChildOf() QFETCH(QString, childPath); QFETCH(bool, result); - const FilePath child = FilePath::fromString(childPath); - const FilePath parent = FilePath::fromString(path); + const FilePath child = FilePath::fromUserInput(childPath); + const FilePath parent = FilePath::fromUserInput(path); QCOMPARE(child.isChildOf(parent), result); } @@ -574,8 +579,8 @@ void tst_fileutils::fromString_data() QTest::newRow("unix-folder-with-trailing-slash") << D("/tmp/", "", "", "/tmp/"); QTest::newRow("windows-root") << D("c:", "", "", "c:"); - QTest::newRow("windows-folder") << D("c:\\Windows", "", "", "c:/Windows"); - QTest::newRow("windows-folder-with-trailing-slash") << D("c:\\Windows\\", "", "", "c:/Windows/"); + QTest::newRow("windows-folder") << D("c:/Windows", "", "", "c:/Windows"); + QTest::newRow("windows-folder-with-trailing-slash") << D("c:/Windows/", "", "", "c:/Windows/"); QTest::newRow("windows-folder-slash") << D("C:/Windows", "", "", "C:/Windows"); QTest::newRow("docker-root-url") << D("docker://1234/", "docker", "1234", "/"); @@ -631,6 +636,88 @@ void tst_fileutils::fromString() QCOMPARE(filePath.path(), data.path); } +void tst_fileutils::fromUserInput_data() +{ + using D = FromStringData; + QTest::addColumn<D>("data"); + + QTest::newRow("empty") << D("", "", "", ""); + QTest::newRow("single-colon") << D(":", "", "", ":"); + QTest::newRow("single-slash") << D("/", "", "", "/"); + QTest::newRow("single-char") << D("a", "", "", "a"); + QTest::newRow("relative") << D("./rel", "", "", "rel"); + QTest::newRow("qrc") << D(":/test.txt", "", "", ":/test.txt"); + QTest::newRow("qrc-no-slash") << D(":test.txt", "", "", ":test.txt"); + + QTest::newRow("unc-incomplete") << D("//", "", "", "//"); + QTest::newRow("unc-incomplete-only-server") << D("//server", "", "", "//server"); + QTest::newRow("unc-incomplete-only-server-2") << D("//server/", "", "", "//server/"); + QTest::newRow("unc-server-and-share") << D("//server/share", "", "", "//server/share"); + QTest::newRow("unc-server-and-share-2") << D("//server/share/", "", "", "//server/share"); + QTest::newRow("unc-full") << D("//server/share/test.txt", "", "", "//server/share/test.txt"); + + QTest::newRow("unix-root") << D("/", "", "", "/"); + QTest::newRow("unix-folder") << D("/tmp", "", "", "/tmp"); + QTest::newRow("unix-folder-with-trailing-slash") << D("/tmp/", "", "", "/tmp"); + + QTest::newRow("windows-root") << D("c:", "", "", "c:"); + QTest::newRow("windows-folder") << D("c:/Windows", "", "", "c:/Windows"); + QTest::newRow("windows-folder-with-trailing-slash") << D("c:\\Windows\\", "", "", "c:/Windows"); + QTest::newRow("windows-folder-slash") << D("C:/Windows", "", "", "C:/Windows"); + + QTest::newRow("docker-root-url") << D("docker://1234/", "docker", "1234", "/"); + QTest::newRow("docker-root-url-special-linux") << D("/__qtc_devices__/docker/1234/", "docker", "1234", "/"); + QTest::newRow("docker-root-url-special-win") << D("c:/__qtc_devices__/docker/1234/", "docker", "1234", "/"); + QTest::newRow("docker-relative-path") << D("docker://1234/./rel", "docker", "1234", "rel", FailEverywhere); + + QTest::newRow("qtc-dev-linux") << D("/__qtc_devices__", "", "", "/__qtc_devices__"); + QTest::newRow("qtc-dev-win") << D("c:/__qtc_devices__", "", "", "c:/__qtc_devices__"); + QTest::newRow("qtc-dev-type-linux") << D("/__qtc_devices__/docker", "", "", "/__qtc_devices__/docker"); + QTest::newRow("qtc-dev-type-win") << D("c:/__qtc_devices__/docker", "", "", "c:/__qtc_devices__/docker"); + QTest::newRow("qtc-dev-type-dev-linux") << D("/__qtc_devices__/docker/1234", "docker", "1234", "/"); + QTest::newRow("qtc-dev-type-dev-win") << D("c:/__qtc_devices__/docker/1234", "docker", "1234", "/"); + + // "Remote Windows" is currently truly not supported. + QTest::newRow("cross-os-linux") + << D("/__qtc_devices__/docker/1234/c:/test.txt", "docker", "1234", "c:/test.txt", FailEverywhere); + QTest::newRow("cross-os-win") + << D("c:/__qtc_devices__/docker/1234/c:/test.txt", "docker", "1234", "c:/test.txt", FailEverywhere); + QTest::newRow("cross-os-unclean-linux") + << D("/__qtc_devices__/docker/1234/c:\\test.txt", "docker", "1234", "c:/test.txt", FailEverywhere); + QTest::newRow("cross-os-unclean-win") + << D("c:/__qtc_devices__/docker/1234/c:\\test.txt", "docker", "1234", "c:/test.txt", FailEverywhere); + + QTest::newRow("unc-full-in-docker-linux") + << D("/__qtc_devices__/docker/1234//server/share/test.txt", "docker", "1234", "//server/share/test.txt", FailEverywhere); + QTest::newRow("unc-full-in-docker-win") + << D("c:/__qtc_devices__/docker/1234//server/share/test.txt", "docker", "1234", "//server/share/test.txt", FailEverywhere); + + QTest::newRow("unc-dos-1") << D("//?/c:", "", "", "c:"); + QTest::newRow("unc-dos-com") << D("//./com1", "", "", "//./com1"); +} + +void tst_fileutils::fromUserInput() +{ + QFETCH(FromStringData, data); + + FilePath filePath = FilePath::fromUserInput(data.input); + + bool expectFail = ((data.expectedPass & FailOnLinux) && !HostOsInfo::isWindowsHost()) + || ((data.expectedPass & FailOnWindows) && HostOsInfo::isWindowsHost()); + + if (expectFail) { + QString actual = filePath.scheme() + '|' + filePath.host() + '|' + filePath.path(); + QString expected = data.scheme + '|' + data.host + '|' + data.path; + QEXPECT_FAIL("", "", Continue); + QCOMPARE(actual, expected); + return; + } + + QCOMPARE(filePath.scheme(), data.scheme); + QCOMPARE(filePath.host(), data.host); + QCOMPARE(filePath.path(), data.path); +} + void tst_fileutils::fromToString_data() { QTest::addColumn<QString>("scheme"); @@ -852,6 +939,8 @@ void tst_fileutils::resolvePath_data() QTest::newRow("s4") << FilePath("/a") << FilePath("/b") << FilePath("/b"); QTest::newRow("s5") << FilePath("a") << FilePath("/b") << FilePath("/b"); QTest::newRow("s6") << FilePath("/a") << FilePath("b") << FilePath("/a/b"); + QTest::newRow("s7") << FilePath("/a") << FilePath(".") << FilePath("/a"); + QTest::newRow("s8") << FilePath("/a") << FilePath("./b") << FilePath("/a/b"); } void tst_fileutils::resolvePath() @@ -938,7 +1027,7 @@ void tst_fileutils::asyncLocalCopy() const FilePath orig = FilePath::fromString(rootPath).pathAppended("x/y/fileToCopy.txt"); QVERIFY(orig.exists()); const FilePath dest = FilePath::fromString(rootPath).pathAppended("x/fileToCopyDest.txt"); - auto afterCopy = [&orig, &dest, this] (bool result) { + auto afterCopy = [&orig, &dest, this](expected_str<void> result) { QVERIFY(result); // check existence, size and content QVERIFY(dest.exists()); @@ -995,7 +1084,7 @@ void tst_fileutils::onDevice() QCOMPARE(path.onDevice(templatePath), expected); } -void tst_fileutils::plus_data() +void tst_fileutils::stringAppended_data() { QTest::addColumn<FilePath>("left"); QTest::addColumn<QString>("right"); @@ -1011,13 +1100,13 @@ void tst_fileutils::plus_data() QTest::newRow("slash-trailing-slash") << FilePath::fromString("/a/") << QString("b/") << FilePath("/a/b/"); } -void tst_fileutils::plus() +void tst_fileutils::stringAppended() { QFETCH(FilePath, left); QFETCH(QString, right); QFETCH(FilePath, expected); - const FilePath result = left + right; + const FilePath result = left.stringAppended(right); QCOMPARE(expected, result); } diff --git a/tests/auto/utils/fsengine/tst_fsengine.cpp b/tests/auto/utils/fsengine/tst_fsengine.cpp index e9a21353f9..c3f289791d 100644 --- a/tests/auto/utils/fsengine/tst_fsengine.cpp +++ b/tests/auto/utils/fsengine/tst_fsengine.cpp @@ -76,26 +76,24 @@ void tst_fsengine::testFilePathFromToString() QCOMPARE(p.path(), u"/test.txt"); QString asString = p.toFSPathString(); - QCOMPARE(asString, - FilePath::specialPath(FilePath::SpecialPathComponent::DeviceRootPath) - + "/test/test.txt"); + QCOMPARE(asString, FilePath::specialDeviceRootPath() + "/test/test.txt"); FilePath p2 = FilePath::fromString(asString); - QCOMPARE(p.scheme(), u"device"); - QCOMPARE(p.host(), u"test"); - QCOMPARE(p.path(), u"/test.txt"); + QCOMPARE(p2.scheme(), u"device"); + QCOMPARE(p2.host(), u"test"); + QCOMPARE(p2.path(), u"/test.txt"); } void tst_fsengine::testRootPathContainsFakeDir() { const QStringList rootList = QDir::root().entryList(); - QVERIFY(rootList.contains(FilePath::specialPath(FilePath::SpecialPathComponent::RootName))); + QVERIFY(rootList.contains(FilePath::specialRootName())); - QDir schemes(FilePath::specialPath(FilePath::SpecialPathComponent::RootPath)); + QDir schemes(FilePath::specialRootPath()); const QStringList schemeList = schemes.entryList(); QVERIFY(schemeList.contains("device")); - QDir deviceRoot(FilePath::specialPath(FilePath::SpecialPathComponent::DeviceRootPath) + "/test" + startWithSlash(QDir::rootPath())); + QDir deviceRoot(FilePath::specialDeviceRootPath() + "/test" + startWithSlash(QDir::rootPath())); const QStringList deviceRootList = deviceRoot.entryList(); QVERIFY(!deviceRootList.isEmpty()); } @@ -127,12 +125,10 @@ void tst_fsengine::testCreateDir() QString tst_fsengine::makeTestPath(QString path, bool asUrl) { - if (asUrl) { + if (asUrl) return QString("device://test%1/tst_fsengine/%2").arg(tempFolder, path); - } - return QString(FilePath::specialPath(FilePath::SpecialPathComponent::DeviceRootPath) - + "/test%1/tst_fsengine/%2") + return QString(FilePath::specialDeviceRootPath() + "/test%1/tst_fsengine/%2") .arg(startWithSlash(tempFolder), path); } @@ -193,8 +189,7 @@ void tst_fsengine::testRead() tmp.write(data); tmp.flush(); - QFile file(FilePath::specialPath(FilePath::SpecialPathComponent::DeviceRootPath) + "/test" - + tmp.fileName()); + QFile file(FilePath::specialDeviceRootPath() + "/test" + tmp.fileName()); QVERIFY(file.open(QIODevice::ReadOnly)); QCOMPARE(file.readAll(), data); } @@ -205,8 +200,7 @@ void tst_fsengine::testWrite() const QString path = dir.path() + "/testWrite.txt"; const QByteArray data = "Hello World!"; { - QFile file(FilePath::specialPath(FilePath::SpecialPathComponent::DeviceRootPath) + "/test" - + path); + QFile file(FilePath::specialDeviceRootPath() + "/test" + path); QVERIFY(file.open(QIODevice::WriteOnly)); QCOMPARE(file.write(data), qint64(data.size())); } diff --git a/tests/auto/utils/mathutils/CMakeLists.txt b/tests/auto/utils/mathutils/CMakeLists.txt new file mode 100644 index 0000000000..d2ec2d5194 --- /dev/null +++ b/tests/auto/utils/mathutils/CMakeLists.txt @@ -0,0 +1,4 @@ +add_qtc_test(tst_utils_mathutils + DEPENDS Utils + SOURCES tst_mathutils.cpp +) diff --git a/tests/auto/utils/mathutils/mathutils.qbs b/tests/auto/utils/mathutils/mathutils.qbs new file mode 100644 index 0000000000..36fa42ffc4 --- /dev/null +++ b/tests/auto/utils/mathutils/mathutils.qbs @@ -0,0 +1,7 @@ +import qbs + +QtcAutotest { + name: "MathUtils autotest" + Depends { name: "Utils" } + files: "tst_mathutils.cpp" +} diff --git a/tests/auto/utils/mathutils/tst_mathutils.cpp b/tests/auto/utils/mathutils/tst_mathutils.cpp new file mode 100644 index 0000000000..a585868d99 --- /dev/null +++ b/tests/auto/utils/mathutils/tst_mathutils.cpp @@ -0,0 +1,104 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0+ OR GPL-3.0 WITH Qt-GPL-exception-1.0 + +#include "utils/mathutils.h" + +#include <QtTest> + +using namespace Utils; + +class tst_MathUtils : public QObject +{ + Q_OBJECT + +private slots: + void interpolateLinear_data(); + void interpolateLinear(); + void interpolateTangential_data(); + void interpolateTangential(); + void interpolateExponential_data(); + void interpolateExponential(); +}; + +void tst_MathUtils::interpolateLinear_data() +{ + QTest::addColumn<int>("x"); + QTest::addColumn<int>("x1"); + QTest::addColumn<int>("x2"); + QTest::addColumn<int>("y1"); + QTest::addColumn<int>("y2"); + QTest::addColumn<int>("result"); + + QTest::newRow("x1") << 2 << 2 << 8 << 10 << 20 << 10; + QTest::newRow("middleValue") << 5 << 2 << 8 << 10 << 20 << 15; + QTest::newRow("x2") << 8 << 2 << 8 << 10 << 20 << 20; + QTest::newRow("belowX1") << -1 << 2 << 8 << 10 << 20 << 5; + QTest::newRow("aboveX2") << 11 << 2 << 8 << 10 << 20 << 25; +} + +void tst_MathUtils::interpolateLinear() +{ + QFETCH(int, x); + QFETCH(int, x1); + QFETCH(int, x2); + QFETCH(int, y1); + QFETCH(int, y2); + QFETCH(int, result); + + const int y = MathUtils::interpolateLinear(x, x1, x2, y1, y2); + QCOMPARE(y, result); +} + +void tst_MathUtils::interpolateTangential_data() +{ + QTest::addColumn<int>("x"); + QTest::addColumn<int>("xHalfLife"); + QTest::addColumn<int>("y1"); + QTest::addColumn<int>("y2"); + QTest::addColumn<int>("result"); + + QTest::newRow("zero") << 0 << 8 << 10 << 20 << 10; + QTest::newRow("halfLife") << 8 << 8 << 10 << 20 << 15; + QTest::newRow("approxInfinity") << 1000 << 8 << 10 << 20 << 20; +} + +void tst_MathUtils::interpolateTangential() +{ + QFETCH(int, x); + QFETCH(int, xHalfLife); + QFETCH(int, y1); + QFETCH(int, y2); + QFETCH(int, result); + + const int y = MathUtils::interpolateTangential(x, xHalfLife, y1, y2); + QCOMPARE(y, result); +} + +void tst_MathUtils::interpolateExponential_data() +{ + QTest::addColumn<int>("x"); + QTest::addColumn<int>("xHalfLife"); + QTest::addColumn<int>("y1"); + QTest::addColumn<int>("y2"); + QTest::addColumn<int>("result"); + + QTest::newRow("zero") << 0 << 8 << 10 << 20 << 10; + QTest::newRow("halfLife") << 8 << 8 << 10 << 20 << 15; + QTest::newRow("approxInfinity") << 1000 << 8 << 10 << 20 << 20; +} + +void tst_MathUtils::interpolateExponential() +{ + QFETCH(int, x); + QFETCH(int, xHalfLife); + QFETCH(int, y1); + QFETCH(int, y2); + QFETCH(int, result); + + const int y = MathUtils::interpolateExponential(x, xHalfLife, y1, y2); + QCOMPARE(y, result); +} + +QTEST_GUILESS_MAIN(tst_MathUtils) + +#include "tst_mathutils.moc" diff --git a/tests/auto/utils/qtcprocess/processtestapp/processtestapp.cpp b/tests/auto/utils/qtcprocess/processtestapp/processtestapp.cpp index a37a4f199f..98ae43f922 100644 --- a/tests/auto/utils/qtcprocess/processtestapp/processtestapp.cpp +++ b/tests/auto/utils/qtcprocess/processtestapp/processtestapp.cpp @@ -77,7 +77,7 @@ SubProcessConfig::SubProcessConfig(const char *envVar, const QString &envVal) { } -void SubProcessConfig::setupSubProcess(QtcProcess *subProcess) +void SubProcessConfig::setupSubProcess(QtcProcess *subProcess) const { subProcess->setEnvironment(m_environment); const FilePath filePath = FilePath::fromString(s_pathToProcessTestApp @@ -85,14 +85,13 @@ void SubProcessConfig::setupSubProcess(QtcProcess *subProcess) subProcess->setCommand(CommandLine(filePath, {})); } -void SubProcessConfig::setupSubProcess(QProcess *subProcess) +void SubProcessConfig::setupSubProcess(QProcess *subProcess) const { subProcess->setProcessEnvironment(m_environment.toProcessEnvironment()); subProcess->setProgram(FilePath::fromString(s_pathToProcessTestApp + QLatin1String("/processtestapp")).withExecutableSuffix().toString()); } - static void doCrash() { qFatal("The application has crashed purposefully!"); diff --git a/tests/auto/utils/qtcprocess/processtestapp/processtestapp.h b/tests/auto/utils/qtcprocess/processtestapp/processtestapp.h index 446fd0e313..5deabdb4a1 100644 --- a/tests/auto/utils/qtcprocess/processtestapp/processtestapp.h +++ b/tests/auto/utils/qtcprocess/processtestapp/processtestapp.h @@ -72,8 +72,8 @@ class SubProcessConfig { public: SubProcessConfig(const char *envVar, const QString &envVal); - void setupSubProcess(Utils::QtcProcess *subProcess); - void setupSubProcess(QProcess *subProcess); + void setupSubProcess(Utils::QtcProcess *subProcess) const; + void setupSubProcess(QProcess *subProcess) const; static void setPathToProcessTestApp(const QString &path); diff --git a/tests/auto/utils/tasktree/CMakeLists.txt b/tests/auto/utils/tasktree/CMakeLists.txt new file mode 100644 index 0000000000..87c31f1886 --- /dev/null +++ b/tests/auto/utils/tasktree/CMakeLists.txt @@ -0,0 +1,11 @@ +add_subdirectory(testapp) + +file(RELATIVE_PATH RELATIVE_TEST_PATH "${PROJECT_BINARY_DIR}" "${CMAKE_CURRENT_BINARY_DIR}") +file(RELATIVE_PATH TEST_RELATIVE_LIBEXEC_PATH "/${RELATIVE_TEST_PATH}" "/${IDE_LIBEXEC_PATH}") + +add_qtc_test(tst_utils_tasktree + DEFINES "TEST_RELATIVE_LIBEXEC_PATH=\"${TEST_RELATIVE_LIBEXEC_PATH}\"" + "TESTAPP_PATH=\"${CMAKE_CURRENT_BINARY_DIR}/testapp\"" + DEPENDS Utils app_version + SOURCES tst_tasktree.cpp +) diff --git a/tests/auto/utils/tasktree/tasktree.qbs b/tests/auto/utils/tasktree/tasktree.qbs new file mode 100644 index 0000000000..ed138d9f39 --- /dev/null +++ b/tests/auto/utils/tasktree/tasktree.qbs @@ -0,0 +1,27 @@ +import qbs.FileInfo + +Project { + QtcAutotest { + name: "TaskTree autotest" + + Depends { name: "Utils" } + Depends { name: "app_version_header" } + + files: [ + "tst_tasktree.cpp", + ] + cpp.defines: { + var defines = base; + if (qbs.targetOS === "windows") + defines.push("_CRT_SECURE_NO_WARNINGS"); + var absLibExecPath = FileInfo.joinPaths(qbs.installRoot, qbs.installPrefix, + qtc.ide_libexec_path); + var relLibExecPath = FileInfo.relativePath(destinationDirectory, absLibExecPath); + defines.push('TEST_RELATIVE_LIBEXEC_PATH="' + relLibExecPath + '"'); + defines.push('TESTAPP_PATH="' + + FileInfo.joinPaths(destinationDirectory, "testapp") + '"'); + return defines; + } + } + references: "testapp/testapp.qbs" +} diff --git a/tests/auto/utils/tasktree/testapp/CMakeLists.txt b/tests/auto/utils/tasktree/testapp/CMakeLists.txt new file mode 100644 index 0000000000..27a1289137 --- /dev/null +++ b/tests/auto/utils/tasktree/testapp/CMakeLists.txt @@ -0,0 +1,12 @@ +add_qtc_executable(testapp + DEPENDS Utils app_version + SOURCES main.cpp + SKIP_INSTALL + INTERNAL_ONLY +) + +set_target_properties(testapp PROPERTIES + LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}" + ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}" + RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}" +) diff --git a/tests/auto/utils/tasktree/testapp/main.cpp b/tests/auto/utils/tasktree/testapp/main.cpp new file mode 100644 index 0000000000..218ff783a4 --- /dev/null +++ b/tests/auto/utils/tasktree/testapp/main.cpp @@ -0,0 +1,63 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0+ OR GPL-3.0 WITH Qt-GPL-exception-1.0 + +#include <app/app_version.h> + +#include <QString> +#include <QThread> + +#ifdef Q_OS_WIN +#include <crtdbg.h> +#include <cstdlib> +#endif + +const char CRASH_OPTION[] = "-crash"; +const char RETURN_OPTION[] = "-return"; +const char SLEEP_OPTION[] = "-sleep"; + +int main(int argc, char **argv) +{ +#ifdef Q_OS_WIN + // avoid crash reporter dialog + _set_error_mode(_OUT_TO_STDERR); + _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_DEBUG); +#endif + + if (argc > 1) { + const auto arg = QString::fromLocal8Bit(argv[1]); + if (arg == CRASH_OPTION) { + qFatal("The application has crashed purposefully!"); + return 1; + } + if (arg == RETURN_OPTION) { + if (argc > 2) { + const auto retString = QString::fromLocal8Bit(argv[2]); + bool ok = false; + const int retVal = retString.toInt(&ok); + if (ok) + return retVal; + // not an int return value + return 1; + } + // lacking return value + return 1; + } + if (arg == SLEEP_OPTION) { + if (argc > 2) { + const auto secondsString = QString::fromLocal8Bit(argv[2]); + bool ok = false; + const int secondsVal = secondsString.toInt(&ok); + if (ok) { + QThread::sleep(secondsVal); + return 0; + } + // not an int return value + return 1; + } + // lacking return value + return 1; + } + } + // not recognized option + return 1; +} diff --git a/tests/auto/utils/tasktree/testapp/testapp.qbs b/tests/auto/utils/tasktree/testapp/testapp.qbs new file mode 100644 index 0000000000..a106e85146 --- /dev/null +++ b/tests/auto/utils/tasktree/testapp/testapp.qbs @@ -0,0 +1,20 @@ +import qbs.FileInfo + +QtApplication { + name: "testapp" + Depends { name: "qtc" } + Depends { name: "Utils" } + Depends { name: "app_version_header" } + + consoleApplication: true + cpp.cxxLanguageVersion: "c++17" + cpp.rpaths: project.buildDirectory + '/' + qtc.ide_library_path + + install: false + destinationDirectory: project.buildDirectory + '/' + + FileInfo.relativePath(project.ide_source_tree, sourceDirectory) + + files: [ + "main.cpp", + ] +} diff --git a/tests/auto/utils/tasktree/tst_tasktree.cpp b/tests/auto/utils/tasktree/tst_tasktree.cpp new file mode 100644 index 0000000000..c036cb5291 --- /dev/null +++ b/tests/auto/utils/tasktree/tst_tasktree.cpp @@ -0,0 +1,578 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0+ OR GPL-3.0 WITH Qt-GPL-exception-1.0 + +#include <app/app_version.h> + +#include <utils/launcherinterface.h> +#include <utils/qtcprocess.h> +#include <utils/singleton.h> +#include <utils/temporarydirectory.h> + +#include <QtTest> + +#include <iostream> +#include <fstream> + +using namespace Utils; +using namespace Utils::Tasking; + +class tst_TaskTree : public QObject +{ + Q_OBJECT + +private slots: + void initTestCase(); + + void validConstructs(); // compile test + void processTree_data(); + void processTree(); + void storageOperators(); + void storageDestructor(); + + void cleanupTestCase(); + +private: + FilePath m_testAppPath; +}; + +void tst_TaskTree::initTestCase() +{ + Utils::TemporaryDirectory::setMasterTemporaryDirectory(QDir::tempPath() + "/" + + Core::Constants::IDE_CASED_ID + "-XXXXXX"); + const QString libExecPath(qApp->applicationDirPath() + '/' + + QLatin1String(TEST_RELATIVE_LIBEXEC_PATH)); + LauncherInterface::setPathToLauncher(libExecPath); + m_testAppPath = FilePath::fromString(QLatin1String(TESTAPP_PATH) + + QLatin1String("/testapp")).withExecutableSuffix(); +} + +void tst_TaskTree::cleanupTestCase() +{ + Utils::Singleton::deleteAll(); +} + +void tst_TaskTree::validConstructs() +{ + const Group process { + parallel, + Process([](QtcProcess &) {}, [](const QtcProcess &) {}), + Process([](QtcProcess &) {}, [](const QtcProcess &) {}), + Process([](QtcProcess &) {}, [](const QtcProcess &) {}) + }; + + const Group group1 { + process + }; + + const Group group2 { + parallel, + Group { + parallel, + Process([](QtcProcess &) {}, [](const QtcProcess &) {}), + Group { + parallel, + Process([](QtcProcess &) {}, [](const QtcProcess &) {}), + Group { + parallel, + Process([](QtcProcess &) {}, [](const QtcProcess &) {}) + } + }, + Group { + parallel, + Process([](QtcProcess &) {}, [](const QtcProcess &) {}), + OnGroupDone([] {}), + } + }, + process, + OnGroupDone([] {}), + OnGroupError([] {}) + }; +} + +static const char s_processIdProperty[] = "__processId"; + +enum class Handler { + Setup, + Done, + Error, + GroupSetup, + GroupDone, + GroupError +}; + +using Log = QList<QPair<int, Handler>>; + +struct CustomStorage +{ + CustomStorage() { ++s_count; } + ~CustomStorage() { --s_count; } + Log m_log; + static int instanceCount() { return s_count; } +private: + static int s_count; +}; + +int CustomStorage::s_count = 0; + + +void tst_TaskTree::processTree_data() +{ + using namespace std::placeholders; + + QTest::addColumn<Group>("root"); + QTest::addColumn<TreeStorage<CustomStorage>>("storage"); + QTest::addColumn<Log>("expectedLog"); + QTest::addColumn<bool>("runningAfterStart"); + QTest::addColumn<bool>("success"); + QTest::addColumn<int>("taskCount"); + + TreeStorage<CustomStorage> storage; + + const auto setupProcessHelper = [storage, testAppPath = m_testAppPath] + (QtcProcess &process, const QStringList &args, int processId) { + process.setCommand(CommandLine(testAppPath, args)); + process.setProperty(s_processIdProperty, processId); + storage->m_log.append({processId, Handler::Setup}); + }; + const auto setupProcess = [setupProcessHelper](QtcProcess &process, int processId) { + setupProcessHelper(process, {"-return", "0"}, processId); + }; + const auto setupCrashProcess = [setupProcessHelper](QtcProcess &process, int processId) { + setupProcessHelper(process, {"-crash"}, processId); + }; + const auto readResultAnonymous = [storage](const QtcProcess &) { + storage->m_log.append({-1, Handler::Done}); + }; + const auto readResult = [storage](const QtcProcess &process) { + const int processId = process.property(s_processIdProperty).toInt(); + storage->m_log.append({processId, Handler::Done}); + }; + const auto readError = [storage](const QtcProcess &process) { + const int processId = process.property(s_processIdProperty).toInt(); + storage->m_log.append({processId, Handler::Error}); + }; + const auto groupSetup = [storage](int processId) { + storage->m_log.append({processId, Handler::GroupSetup}); + }; + const auto groupDone = [storage](int processId) { + storage->m_log.append({processId, Handler::GroupDone}); + }; + const auto rootDone = [storage] { + storage->m_log.append({-1, Handler::GroupDone}); + }; + const auto rootError = [storage] { + storage->m_log.append({-1, Handler::GroupError}); + }; + + const Group emptyRoot { + Storage(storage), + OnGroupDone(rootDone) + }; + const Log emptyLog{{-1, Handler::GroupDone}}; + QTest::newRow("Empty") << emptyRoot << storage << emptyLog << false << true << 0; + + const Group nestedRoot { + Storage(storage), + Group { + Group { + Group { + Group { + Group { + Process(std::bind(setupProcess, _1, 5), readResult), + OnGroupSetup(std::bind(groupSetup, 5)), + OnGroupDone(std::bind(groupDone, 5)) + }, + OnGroupSetup(std::bind(groupSetup, 4)), + OnGroupDone(std::bind(groupDone, 4)) + }, + OnGroupSetup(std::bind(groupSetup, 3)), + OnGroupDone(std::bind(groupDone, 3)) + }, + OnGroupSetup(std::bind(groupSetup, 2)), + OnGroupDone(std::bind(groupDone, 2)) + }, + OnGroupSetup(std::bind(groupSetup, 1)), + OnGroupDone(std::bind(groupDone, 1)) + }, + OnGroupDone(rootDone) + }; + const Log nestedLog{{1, Handler::GroupSetup}, + {2, Handler::GroupSetup}, + {3, Handler::GroupSetup}, + {4, Handler::GroupSetup}, + {5, Handler::GroupSetup}, + {5, Handler::Setup}, + {5, Handler::Done}, + {5, Handler::GroupDone}, + {4, Handler::GroupDone}, + {3, Handler::GroupDone}, + {2, Handler::GroupDone}, + {1, Handler::GroupDone}, + {-1, Handler::GroupDone}}; + QTest::newRow("Nested") << nestedRoot << storage << nestedLog << true << true << 1; + + const Group parallelRoot { + Storage(storage), + parallel, + Process(std::bind(setupProcess, _1, 1), readResultAnonymous), + Process(std::bind(setupProcess, _1, 2), readResultAnonymous), + Process(std::bind(setupProcess, _1, 3), readResultAnonymous), + Process(std::bind(setupProcess, _1, 4), readResultAnonymous), + Process(std::bind(setupProcess, _1, 5), readResultAnonymous), + OnGroupDone(rootDone) + }; + const Log parallelLog{{1, Handler::Setup}, // Setup order is determined in parallel mode + {2, Handler::Setup}, + {3, Handler::Setup}, + {4, Handler::Setup}, + {5, Handler::Setup}, + {-1, Handler::Done}, // Done order isn't determined in parallel mode + {-1, Handler::Done}, + {-1, Handler::Done}, + {-1, Handler::Done}, + {-1, Handler::Done}, + {-1, Handler::GroupDone}}; // Done handlers may come in different order + QTest::newRow("Parallel") << parallelRoot << storage << parallelLog << true << true << 5; + + const Group sequentialRoot { + Storage(storage), + Process(std::bind(setupProcess, _1, 1), readResult), + Process(std::bind(setupProcess, _1, 2), readResult), + Process(std::bind(setupProcess, _1, 3), readResult), + Process(std::bind(setupProcess, _1, 4), readResult), + Process(std::bind(setupProcess, _1, 5), readResult), + OnGroupDone(rootDone) + }; + const Group sequentialEncapsulatedRoot { + Storage(storage), + Group { + Process(std::bind(setupProcess, _1, 1), readResult) + }, + Group { + Process(std::bind(setupProcess, _1, 2), readResult) + }, + Group { + Process(std::bind(setupProcess, _1, 3), readResult) + }, + Group { + Process(std::bind(setupProcess, _1, 4), readResult) + }, + Group { + Process(std::bind(setupProcess, _1, 5), readResult) + }, + OnGroupDone(rootDone) + }; + auto setupSubTree = [=](TaskTree &taskTree) { + const Group nestedRoot { + Storage(storage), + Process(std::bind(setupProcess, _1, 2), readResult), + Process(std::bind(setupProcess, _1, 3), readResult), + Process(std::bind(setupProcess, _1, 4), readResult), + }; + taskTree.setupRoot(nestedRoot); + CustomStorage *activeStorage = storage.activeStorage(); + auto collectSubLog = [activeStorage](CustomStorage *subTreeStorage){ + activeStorage->m_log += subTreeStorage->m_log; + }; + taskTree.onStorageDone(storage, collectSubLog); + }; + const Group sequentialSubTreeRoot { + Storage(storage), + Process(std::bind(setupProcess, _1, 1), readResult), + Tree(setupSubTree), + Process(std::bind(setupProcess, _1, 5), readResult), + OnGroupDone(rootDone) + }; + const Log sequentialLog{{1, Handler::Setup}, + {1, Handler::Done}, + {2, Handler::Setup}, + {2, Handler::Done}, + {3, Handler::Setup}, + {3, Handler::Done}, + {4, Handler::Setup}, + {4, Handler::Done}, + {5, Handler::Setup}, + {5, Handler::Done}, + {-1, Handler::GroupDone}}; + QTest::newRow("Sequential") << sequentialRoot << storage << sequentialLog << true << true << 5; + QTest::newRow("SequentialEncapsulated") << sequentialEncapsulatedRoot << storage + << sequentialLog << true << true << 5; + QTest::newRow("SequentialSubTree") << sequentialSubTreeRoot << storage << sequentialLog + << true << true << 3; // We don't inspect subtrees + + const Group sequentialNestedRoot { + Storage(storage), + Group { + Process(std::bind(setupProcess, _1, 1), readResult), + Group { + Process(std::bind(setupProcess, _1, 2), readResult), + Group { + Process(std::bind(setupProcess, _1, 3), readResult), + Group { + Process(std::bind(setupProcess, _1, 4), readResult), + Group { + Process(std::bind(setupProcess, _1, 5), readResult), + OnGroupDone(std::bind(groupDone, 5)) + }, + OnGroupDone(std::bind(groupDone, 4)) + }, + OnGroupDone(std::bind(groupDone, 3)) + }, + OnGroupDone(std::bind(groupDone, 2)) + }, + OnGroupDone(std::bind(groupDone, 1)) + }, + OnGroupDone(rootDone) + }; + const Log sequentialNestedLog{{1, Handler::Setup}, + {1, Handler::Done}, + {2, Handler::Setup}, + {2, Handler::Done}, + {3, Handler::Setup}, + {3, Handler::Done}, + {4, Handler::Setup}, + {4, Handler::Done}, + {5, Handler::Setup}, + {5, Handler::Done}, + {5, Handler::GroupDone}, + {4, Handler::GroupDone}, + {3, Handler::GroupDone}, + {2, Handler::GroupDone}, + {1, Handler::GroupDone}, + {-1, Handler::GroupDone}}; + QTest::newRow("SequentialNested") << sequentialNestedRoot << storage << sequentialNestedLog + << true << true << 5; + + const Group sequentialErrorRoot { + Storage(storage), + Process(std::bind(setupProcess, _1, 1), readResult), + Process(std::bind(setupProcess, _1, 2), readResult), + Process(std::bind(setupCrashProcess, _1, 3), readResult, readError), + Process(std::bind(setupProcess, _1, 4), readResult), + Process(std::bind(setupProcess, _1, 5), readResult), + OnGroupDone(rootDone), + OnGroupError(rootError) + }; + const Log sequentialErrorLog{{1, Handler::Setup}, + {1, Handler::Done}, + {2, Handler::Setup}, + {2, Handler::Done}, + {3, Handler::Setup}, + {3, Handler::Error}, + {-1, Handler::GroupError}}; + QTest::newRow("SequentialError") << sequentialErrorRoot << storage << sequentialErrorLog + << true << false << 5; + + const auto constructSimpleSequence = [=](const Workflow &policy) { + return Group { + Storage(storage), + policy, + Process(std::bind(setupProcess, _1, 1), readResult), + Process(std::bind(setupCrashProcess, _1, 2), readResult, readError), + Process(std::bind(setupProcess, _1, 3), readResult), + OnGroupDone(rootDone), + OnGroupError(rootError) + }; + }; + + const Group stopOnErrorRoot = constructSimpleSequence(stopOnError); + const Log stopOnErrorLog{{1, Handler::Setup}, + {1, Handler::Done}, + {2, Handler::Setup}, + {2, Handler::Error}, + {-1, Handler::GroupError}}; + QTest::newRow("StopOnError") << stopOnErrorRoot << storage << stopOnErrorLog << true << false << 3; + + const Group continueOnErrorRoot = constructSimpleSequence(continueOnError); + const Log continueOnErrorLog{{1, Handler::Setup}, + {1, Handler::Done}, + {2, Handler::Setup}, + {2, Handler::Error}, + {3, Handler::Setup}, + {3, Handler::Done}, + {-1, Handler::GroupError}}; + QTest::newRow("ContinueOnError") << continueOnErrorRoot << storage << continueOnErrorLog + << true << false << 3; + + const Group stopOnDoneRoot = constructSimpleSequence(stopOnDone); + const Log stopOnDoneLog{{1, Handler::Setup}, + {1, Handler::Done}, + {-1, Handler::GroupDone}}; + QTest::newRow("StopOnDone") << stopOnDoneRoot << storage << stopOnDoneLog + << true << true << 3; + + const Group continueOnDoneRoot = constructSimpleSequence(continueOnDone); + const Log continueOnDoneLog{{1, Handler::Setup}, + {1, Handler::Done}, + {2, Handler::Setup}, + {2, Handler::Error}, + {3, Handler::Setup}, + {3, Handler::Done}, + {-1, Handler::GroupDone}}; + QTest::newRow("ContinueOnDone") << continueOnDoneRoot << storage << continueOnDoneLog + << true << true << 3; + + const Group optionalRoot { + Storage(storage), + optional, + Process(std::bind(setupCrashProcess, _1, 1), readResult, readError), + Process(std::bind(setupCrashProcess, _1, 2), readResult, readError), + OnGroupDone(rootDone), + OnGroupError(rootError) + }; + const Log optionalLog{{1, Handler::Setup}, + {1, Handler::Error}, + {2, Handler::Setup}, + {2, Handler::Error}, + {-1, Handler::GroupDone}}; + QTest::newRow("Optional") << optionalRoot << storage << optionalLog << true << true << 2; + + const auto stopWithDoneSetup = [] { return GroupConfig{GroupAction::StopWithDone}; }; + const auto stopWithErrorSetup = [] { return GroupConfig{GroupAction::StopWithError}; }; + const auto continueAllSetup = [] { return GroupConfig{GroupAction::ContinueAll}; }; + const auto continueSelSetup = [] { return GroupConfig{GroupAction::ContinueSelected, {0, 2}}; }; + const auto constructDynamicSetup = [=](const DynamicSetup &dynamicSetup) { + return Group { + Storage(storage), + Group { + Process(std::bind(setupProcess, _1, 1), readResult) + }, + Group { + dynamicSetup, + Process(std::bind(setupProcess, _1, 2), readResult), + Process(std::bind(setupProcess, _1, 3), readResult), + Process(std::bind(setupProcess, _1, 4), readResult) + }, + OnGroupDone(rootDone), + OnGroupError(rootError) + }; + }; + const Group dynamicSetupDoneRoot = constructDynamicSetup({stopWithDoneSetup}); + const Log dynamicSetupDoneLog{{1, Handler::Setup}, + {1, Handler::Done}, + {-1, Handler::GroupDone}}; + QTest::newRow("DynamicSetupDone") << dynamicSetupDoneRoot << storage << dynamicSetupDoneLog + << true << true << 4; + + const Group dynamicSetupErrorRoot = constructDynamicSetup({stopWithErrorSetup}); + const Log dynamicSetupErrorLog{{1, Handler::Setup}, + {1, Handler::Done}, + {-1, Handler::GroupError}}; + QTest::newRow("DynamicSetupError") << dynamicSetupErrorRoot << storage << dynamicSetupErrorLog + << true << false << 4; + + const Group dynamicSetupAllRoot = constructDynamicSetup({continueAllSetup}); + const Log dynamicSetupAllLog{{1, Handler::Setup}, + {1, Handler::Done}, + {2, Handler::Setup}, + {2, Handler::Done}, + {3, Handler::Setup}, + {3, Handler::Done}, + {4, Handler::Setup}, + {4, Handler::Done}, + {-1, Handler::GroupDone}}; + QTest::newRow("DynamicSetupAll") << dynamicSetupAllRoot << storage << dynamicSetupAllLog + << true << true << 4; + + const Group dynamicSetupSelRoot = constructDynamicSetup({continueSelSetup}); + const Log dynamicSetupSelLog{{1, Handler::Setup}, + {1, Handler::Done}, + {2, Handler::Setup}, + {2, Handler::Done}, + {4, Handler::Setup}, + {4, Handler::Done}, + {-1, Handler::GroupDone}}; + QTest::newRow("DynamicSetupSelected") << dynamicSetupSelRoot << storage << dynamicSetupSelLog + << true << true << 4; + +} + +void tst_TaskTree::processTree() +{ + QFETCH(Group, root); + QFETCH(TreeStorage<CustomStorage>, storage); + QFETCH(Log, expectedLog); + QFETCH(bool, runningAfterStart); + QFETCH(bool, success); + QFETCH(int, taskCount); + + QEventLoop eventLoop; + TaskTree taskTree(root); + QCOMPARE(taskTree.taskCount(), taskCount); + int doneCount = 0; + int errorCount = 0; + connect(&taskTree, &TaskTree::done, this, [&doneCount, &eventLoop] { + ++doneCount; + eventLoop.quit(); + }); + connect(&taskTree, &TaskTree::errorOccurred, this, [&errorCount, &eventLoop] { + ++errorCount; + eventLoop.quit(); + }); + Log actualLog; + auto collectLog = [&actualLog](CustomStorage *storage){ + actualLog = storage->m_log; + }; + taskTree.onStorageDone(storage, collectLog); + taskTree.start(); + QCOMPARE(taskTree.isRunning(), runningAfterStart); + + if (runningAfterStart) { + QTimer timer; + bool timedOut = false; + connect(&timer, &QTimer::timeout, &eventLoop, [&eventLoop, &timedOut] { + timedOut = true; + eventLoop.quit(); + }); + timer.setInterval(2000); + timer.setSingleShot(true); + timer.start(); + eventLoop.exec(); + QCOMPARE(timedOut, false); + QCOMPARE(taskTree.isRunning(), false); + } + + QCOMPARE(taskTree.progressValue(), taskCount); + QCOMPARE(actualLog, expectedLog); + QCOMPARE(CustomStorage::instanceCount(), 0); + + const int expectedDoneCount = success ? 1 : 0; + const int expectedErrorCount = success ? 0 : 1; + QCOMPARE(doneCount, expectedDoneCount); + QCOMPARE(errorCount, expectedErrorCount); +} + +void tst_TaskTree::storageOperators() +{ + TreeStorageBase storage1 = TreeStorage<CustomStorage>(); + TreeStorageBase storage2 = TreeStorage<CustomStorage>(); + TreeStorageBase storage3 = storage1; + + QVERIFY(storage1 == storage3); + QVERIFY(storage1 != storage2); + QVERIFY(storage2 != storage3); +} + +void tst_TaskTree::storageDestructor() +{ + QCOMPARE(CustomStorage::instanceCount(), 0); + { + const auto setupProcess = [testAppPath = m_testAppPath](QtcProcess &process) { + process.setCommand(CommandLine(testAppPath, {"-sleep", "1"})); + }; + const Group root { + Storage(TreeStorage<CustomStorage>()), + Process(setupProcess) + }; + + TaskTree processTree(root); + QCOMPARE(CustomStorage::instanceCount(), 0); + processTree.start(); + QCOMPARE(CustomStorage::instanceCount(), 1); + } + QCOMPARE(CustomStorage::instanceCount(), 0); +} + +QTEST_GUILESS_MAIN(tst_TaskTree) + +#include "tst_tasktree.moc" diff --git a/tests/auto/utils/utils.qbs b/tests/auto/utils/utils.qbs index 363d020397..eea3664423 100644 --- a/tests/auto/utils/utils.qbs +++ b/tests/auto/utils/utils.qbs @@ -3,18 +3,23 @@ import qbs Project { name: "Utils autotests" references: [ + "ansiescapecodehandler/ansiescapecodehandler.qbs", + "asynctask/asynctask.qbs", + "commandline/commandline.qbs", + "deviceshell/deviceshell.qbs", + "expected/expected.qbs", "fileutils/fileutils.qbs", "fsengine/fsengine.qbs", - "ansiescapecodehandler/ansiescapecodehandler.qbs", "fuzzymatcher/fuzzymatcher.qbs", "indexedcontainerproxyconstiterator/indexedcontainerproxyconstiterator.qbs", + "mathutils/mathutils.qbs", + "multicursor/multicursor.qbs", "persistentsettings/persistentsettings.qbs", "qtcprocess/qtcprocess.qbs", "settings/settings.qbs", "stringutils/stringutils.qbs", + "tasktree/tasktree.qbs", "templateengine/templateengine.qbs", "treemodel/treemodel.qbs", - "multicursor/multicursor.qbs", - "deviceshell/deviceshell.qbs", ] } diff --git a/tests/auto/valgrind/memcheck/modeldemo.cpp b/tests/auto/valgrind/memcheck/modeldemo.cpp index 4cd40bc44b..f164fd8558 100644 --- a/tests/auto/valgrind/memcheck/modeldemo.cpp +++ b/tests/auto/valgrind/memcheck/modeldemo.cpp @@ -1,6 +1,7 @@ // Copyright (C) 2016 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0+ OR GPL-3.0 WITH Qt-GPL-exception-1.0 +#include <utils/commandline.h> #include <utils/launcherinterface.h> #include <utils/temporarydirectory.h> diff --git a/tests/manual/CMakeLists.txt b/tests/manual/CMakeLists.txt index 42aaac7961..c171a70deb 100644 --- a/tests/manual/CMakeLists.txt +++ b/tests/manual/CMakeLists.txt @@ -3,6 +3,7 @@ # add_subdirectory(cplusplus-tools) # add_subdirectory(cppquickfix) add_subdirectory(debugger) +add_subdirectory(deviceshell) # add_subdirectory(distribution) # add_subdirectory(dockwidgets) add_subdirectory(fakevim) @@ -15,5 +16,5 @@ add_subdirectory(proparser) # add_subdirectory(qt4projectmanager) # add_subdirectory(search) add_subdirectory(shootout) +add_subdirectory(tasktree) add_subdirectory(widgets) -add_subdirectory(deviceshell) diff --git a/tests/manual/manual.qbs b/tests/manual/manual.qbs index 566f5e8245..e3ebf0707a 100644 --- a/tests/manual/manual.qbs +++ b/tests/manual/manual.qbs @@ -13,6 +13,7 @@ Project { "pluginview/pluginview.qbs", "proparser/testreader.qbs", "shootout/shootout.qbs", + "tasktree/tasktree.qbs", "widgets/widgets.qbs", ] } diff --git a/tests/manual/tasktree/CMakeLists.txt b/tests/manual/tasktree/CMakeLists.txt new file mode 100644 index 0000000000..19bd81bfb2 --- /dev/null +++ b/tests/manual/tasktree/CMakeLists.txt @@ -0,0 +1,6 @@ +add_qtc_test(tst_manual_tasktree + MANUALTEST + DEPENDS Utils + SOURCES + main.cpp taskwidget.h taskwidget.cpp +) diff --git a/tests/manual/tasktree/main.cpp b/tests/manual/tasktree/main.cpp new file mode 100644 index 0000000000..33d9d9d9d5 --- /dev/null +++ b/tests/manual/tasktree/main.cpp @@ -0,0 +1,268 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0+ OR GPL-3.0 WITH Qt-GPL-exception-1.0 + +#include "taskwidget.h" + +#include <utils/asynctask.h> +#include <utils/futuresynchronizer.h> +#include <utils/layoutbuilder.h> +#include <utils/theme/theme_p.h> + +#include <QApplication> +#include <QCheckBox> +#include <QProgressBar> +#include <QScrollArea> +#include <QTimer> +#include <QToolButton> + +using namespace Utils; + +// TODO: make tasks cancellable +static void sleepInThread(QFutureInterface<void> &fi, int seconds, bool reportSuccess) +{ + QThread::sleep(seconds); + if (!reportSuccess) + fi.reportCanceled(); +} + +int main(int argc, char *argv[]) +{ + QApplication app(argc, argv); + + setCreatorTheme(new Theme("default", &app)); + + QWidget mainWidget; + mainWidget.setWindowTitle("Task Tree Demo"); + + // Non-task GUI + + QToolButton *startButton = new QToolButton(); + startButton->setText("Start"); + QToolButton *stopButton = new QToolButton(); + stopButton->setText("Stop"); + QToolButton *resetButton = new QToolButton(); + resetButton->setText("Reset"); + QProgressBar *progressBar = new QProgressBar(); + QCheckBox *synchronizerCheckBox = new QCheckBox("Use Future Synchronizer"); + synchronizerCheckBox->setChecked(true); + QScrollArea *scrollArea = new QScrollArea(); + scrollArea->setWidgetResizable(true); + QWidget *scrollAreaWidget = new QWidget(); + + // Task GUI + + QList<StateWidget *> allStateWidgets; + + auto createGroupWidget = [&allStateWidgets] { + auto *widget = new GroupWidget(); + allStateWidgets.append(widget); + return widget; + }; + auto createTaskWidget = [&allStateWidgets] { + auto *widget = new TaskWidget(); + allStateWidgets.append(widget); + return widget; + }; + + GroupWidget *rootGroup = createGroupWidget(); + + GroupWidget *groupTask_1 = createGroupWidget(); + TaskWidget *task_1_1 = createTaskWidget(); + TaskWidget *task_1_2 = createTaskWidget(); + TaskWidget *task_1_3 = createTaskWidget(); + + TaskWidget *task_2 = createTaskWidget(); + TaskWidget *task_3 = createTaskWidget(); + + GroupWidget *groupTask_4 = createGroupWidget(); + TaskWidget *task_4_1 = createTaskWidget(); + TaskWidget *task_4_2 = createTaskWidget(); + GroupWidget *groupTask_4_3 = createGroupWidget(); + TaskWidget *task_4_3_1 = createTaskWidget(); + TaskWidget *task_4_3_2 = createTaskWidget(); + TaskWidget *task_4_3_3 = createTaskWidget(); + TaskWidget *task_4_3_4 = createTaskWidget(); + TaskWidget *task_4_4 = createTaskWidget(); + TaskWidget *task_4_5 = createTaskWidget(); + + TaskWidget *task_5 = createTaskWidget(); + + // Task initial configuration + + task_1_2->setBusyTime(2); + task_1_2->setSuccess(false); + task_1_3->setBusyTime(3); + task_4_3_1->setBusyTime(4); + task_4_3_2->setBusyTime(2); + task_4_3_3->setBusyTime(1); + task_4_3_4->setBusyTime(3); + task_4_3_4->setSuccess(false); + task_4_4->setBusyTime(6); + task_4_4->setBusyTime(3); + + groupTask_1->setWorkflowPolicy(Tasking::WorkflowPolicy::ContinueOnDone); + groupTask_4->setWorkflowPolicy(Tasking::WorkflowPolicy::Optional); + groupTask_4_3->setExecuteMode(Tasking::ExecuteMode::Parallel); + groupTask_4_3->setWorkflowPolicy(Tasking::WorkflowPolicy::StopOnError); + + // Task layout + + { + using namespace Layouting; + + Column { + TaskGroup { rootGroup, { + TaskGroup { groupTask_1, { + task_1_1, hr, + task_1_2, hr, + task_1_3, + }}, hr, + task_2, hr, + task_3, hr, + TaskGroup { groupTask_4, { + task_4_1, hr, + task_4_2, hr, + TaskGroup { groupTask_4_3, { + task_4_3_1, hr, + task_4_3_2, hr, + task_4_3_3, hr, + task_4_3_4, + }}, hr, + task_4_4, hr, + task_4_5, + }}, hr, + task_5 + }}, st + }.attachTo(scrollAreaWidget); + + scrollArea->setWidget(scrollAreaWidget); + + Column { + Row { startButton, stopButton, resetButton, synchronizerCheckBox, progressBar }, + hr, + scrollArea + }.attachTo(&mainWidget); + } + + // Task tree creator (takes configuation from GUI) + + std::unique_ptr<TaskTree> taskTree; + FutureSynchronizer synchronizer; + synchronizer.setCancelOnWait(true); + + auto treeRoot = [&] { + using namespace Tasking; + + auto taskItem = [sync = &synchronizer, synchronizerCheckBox](TaskWidget *widget) { + const auto setupHandler = [=](AsyncTask<void> &task) { + task.setAsyncCallData(sleepInThread, widget->busyTime(), widget->isSuccess()); + if (synchronizerCheckBox->isChecked()) + task.setFutureSynchronizer(sync); + widget->setState(State::Running); + }; + const auto doneHandler = [widget](const AsyncTask<void> &) { + widget->setState(State::Done); + }; + const auto errorHandler = [widget](const AsyncTask<void> &) { + widget->setState(State::Error); + }; + return Async<void>(setupHandler, doneHandler, errorHandler); + }; + + const Group root { + Execute(rootGroup->executeMode()), + Workflow(rootGroup->workflowPolicy()), + OnGroupSetup([rootGroup] { rootGroup->setState(State::Running); }), + OnGroupDone([rootGroup] { rootGroup->setState(State::Done); }), + OnGroupError([rootGroup] { rootGroup->setState(State::Error); }), + + Group { + Execute(groupTask_1->executeMode()), + Workflow(groupTask_1->workflowPolicy()), + OnGroupSetup([groupTask_1] { groupTask_1->setState(State::Running); }), + OnGroupDone([groupTask_1] { groupTask_1->setState(State::Done); }), + OnGroupError([groupTask_1] { groupTask_1->setState(State::Error); }), + + taskItem(task_1_1), + taskItem(task_1_2), + taskItem(task_1_3) + }, + taskItem(task_2), + taskItem(task_3), + Group { + Execute(groupTask_4->executeMode()), + Workflow(groupTask_4->workflowPolicy()), + OnGroupSetup([groupTask_4] { groupTask_4->setState(State::Running); }), + OnGroupDone([groupTask_4] { groupTask_4->setState(State::Done); }), + OnGroupError([groupTask_4] { groupTask_4->setState(State::Error); }), + + taskItem(task_4_1), + taskItem(task_4_2), + Group { + Execute(groupTask_4_3->executeMode()), + Workflow(groupTask_4_3->workflowPolicy()), + OnGroupSetup([groupTask_4_3] { groupTask_4_3->setState(State::Running); }), + OnGroupDone([groupTask_4_3] { groupTask_4_3->setState(State::Done); }), + OnGroupError([groupTask_4_3] { groupTask_4_3->setState(State::Error); }), + + taskItem(task_4_3_1), + taskItem(task_4_3_2), + taskItem(task_4_3_3), + taskItem(task_4_3_4) + }, + taskItem(task_4_4), + taskItem(task_4_5) + }, + taskItem(task_5) + }; + return root; + }; + + // Non-task GUI handling + + auto createTaskTree = [&] { + TaskTree *taskTree = new TaskTree(treeRoot()); + progressBar->setMaximum(taskTree->progressMaximum()); + QObject::connect(taskTree, &TaskTree::progressValueChanged, + progressBar, &QProgressBar::setValue); + return taskTree; + }; + + auto stopTaskTree = [&] { + if (taskTree) + taskTree->stop(); + // TODO: unlock GUI controls? + }; + + auto resetTaskTree = [&] { + if (!taskTree) + return; + + stopTaskTree(); + taskTree.reset(); + for (StateWidget *widget : allStateWidgets) + widget->setState(State::Initial); + progressBar->setValue(0); + }; + + auto startTaskTree = [&] { + resetTaskTree(); + taskTree.reset(createTaskTree()); + taskTree->start(); + // TODO: lock GUI controls? + }; + + QObject::connect(startButton, &QAbstractButton::clicked, startTaskTree); + QObject::connect(stopButton, &QAbstractButton::clicked, stopTaskTree); + QObject::connect(resetButton, &QAbstractButton::clicked, resetTaskTree); + + // Hack in order to show initial size minimal, but without scrollbars. + // Apparently setSizeAdjustPolicy(QAbstractScrollArea::AdjustToContentsOnFirstShow) doesn't work. + const int margin = 2; + scrollArea->setMinimumSize(scrollAreaWidget->minimumSizeHint().grownBy({0, 0, margin, margin})); + QTimer::singleShot(0, scrollArea, [&] { scrollArea->setMinimumSize({0, 0}); }); + + mainWidget.show(); + + return app.exec(); +} diff --git a/tests/manual/tasktree/tasktree.qbs b/tests/manual/tasktree/tasktree.qbs new file mode 100644 index 0000000000..dad8e14763 --- /dev/null +++ b/tests/manual/tasktree/tasktree.qbs @@ -0,0 +1,14 @@ +import qbs.FileInfo + +QtcManualtest { + name: "Manual TaskTree test" + type: ["application"] + + Depends { name: "Utils" } + + files: [ + "main.cpp", + "taskwidget.h", + "taskwidget.cpp", + ] +} diff --git a/tests/manual/tasktree/taskwidget.cpp b/tests/manual/tasktree/taskwidget.cpp new file mode 100644 index 0000000000..b01fba612f --- /dev/null +++ b/tests/manual/tasktree/taskwidget.cpp @@ -0,0 +1,189 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0+ OR GPL-3.0 WITH Qt-GPL-exception-1.0 + +#include "taskwidget.h" + +#include <utils/layoutbuilder.h> +#include <utils/progressindicator.h> +#include <utils/qtcassert.h> + +#include <QCheckBox> +#include <QComboBox> +#include <QGroupBox> +#include <QLabel> +#include <QSpinBox> + +using namespace Utils; +using namespace Layouting; + +static QString colorButtonStyleSheet(const QColor &bgColor) +{ + QString rc("border-width: 2px; border-radius: 2px; border-color: black; "); + rc += bgColor.isValid() ? "border-style: solid; background:" + bgColor.name() + ";" + : QString("border-style: dotted;"); + return rc; +} + +static QColor stateToColor(State state) { + switch (state) { + case State::Initial: return Qt::gray; + case State::Running: return Qt::yellow; + case State::Done: return Qt::green; + case State::Error: return Qt::red; + } + return {}; +} + +class StateIndicator : public QLabel +{ +public: + StateIndicator() + { + m_progressIndicator = new ProgressIndicator(ProgressIndicatorSize::Small); + m_progressIndicator->attachToWidget(this); + m_progressIndicator->hide(); + updateState(); + } + + void setState(State state) + { + if (m_state == state) + return; + m_state = state; + updateState(); + } + +private: + void updateState() + { + setStyleSheet(colorButtonStyleSheet(stateToColor(m_state))); + if (m_state == State::Running) + m_progressIndicator->show(); + else + m_progressIndicator->hide(); + } + State m_state = State::Initial; + ProgressIndicator *m_progressIndicator = nullptr; +}; + +StateWidget::StateWidget() + : m_stateIndicator(new StateIndicator) +{ +} + +void StateWidget::setState(State state) +{ + m_stateIndicator->setState(state); +} + +TaskWidget::TaskWidget() + : m_infoLabel(new QLabel("Sleep:")) + , m_spinBox(new QSpinBox) + , m_checkBox(new QCheckBox("Report success")) +{ + m_stateIndicator->setFixedSize(30, 30); + m_spinBox->setSuffix(" sec"); + setBusyTime(1); + setSuccess(true); + + Row { + m_stateIndicator, + m_infoLabel, + m_spinBox, + m_checkBox, + st + }.attachTo(this, WithoutMargins); +} + +void TaskWidget::setBusyTime(int seconds) +{ + m_spinBox->setValue(seconds); +} + +int TaskWidget::busyTime() const +{ + return m_spinBox->value(); +} + +void TaskWidget::setSuccess(bool success) +{ + m_checkBox->setChecked(success); +} + +bool TaskWidget::isSuccess() const +{ + return m_checkBox->isChecked(); +} + +GroupWidget::GroupWidget() + : m_executeCombo(new QComboBox) + , m_workflowCombo(new QComboBox) +{ + m_stateIndicator->setFixedWidth(30); + + m_executeCombo->addItem("Sequential", (int)Tasking::ExecuteMode::Sequential); + m_executeCombo->addItem("Parallel", (int)Tasking::ExecuteMode::Parallel); + updateExecuteMode(); + connect(m_executeCombo, &QComboBox::currentIndexChanged, this, [this](int index) { + m_executeMode = (Tasking::ExecuteMode)m_executeCombo->itemData(index).toInt(); + }); + + m_workflowCombo->addItem("Stop On Error", (int)Tasking::WorkflowPolicy::StopOnError); + m_workflowCombo->addItem("Cont On Error", (int)Tasking::WorkflowPolicy::ContinueOnError); + m_workflowCombo->addItem("Stop On Done", (int)Tasking::WorkflowPolicy::StopOnDone); + m_workflowCombo->addItem("Cont On Done", (int)Tasking::WorkflowPolicy::ContinueOnDone); + m_workflowCombo->addItem("Optional", (int)Tasking::WorkflowPolicy::Optional); + updateWorkflowPolicy(); + connect(m_workflowCombo, &QComboBox::currentIndexChanged, this, [this](int index) { + m_workflowPolicy = (Tasking::WorkflowPolicy)m_workflowCombo->itemData(index).toInt(); + }); + + Row { + m_stateIndicator, + Column { + new QLabel("Execute:"), + m_executeCombo, + new QLabel("Workflow:"), + m_workflowCombo, + st + } + }.attachTo(this, WithoutMargins); + + setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Preferred); +} + +void GroupWidget::setExecuteMode(Tasking::ExecuteMode mode) +{ + m_executeMode = mode; + updateExecuteMode(); +} + +void GroupWidget::updateExecuteMode() +{ + m_executeCombo->setCurrentIndex(m_executeCombo->findData((int)m_executeMode)); +} + +Tasking::ExecuteMode GroupWidget::executeMode() const +{ + return m_executeMode; +} + +void GroupWidget::setWorkflowPolicy(Tasking::WorkflowPolicy policy) +{ + m_workflowPolicy = policy; + updateWorkflowPolicy(); +} + +void GroupWidget::updateWorkflowPolicy() +{ + m_workflowCombo->setCurrentIndex(m_workflowCombo->findData((int)m_workflowPolicy)); +} + +Tasking::WorkflowPolicy GroupWidget::workflowPolicy() const +{ + return m_workflowPolicy; +} + +TaskGroup::TaskGroup(QWidget *group, std::initializer_list<LayoutBuilder::LayoutItem> items) + : Row({ group, Group { Column { items } } }) {} + diff --git a/tests/manual/tasktree/taskwidget.h b/tests/manual/tasktree/taskwidget.h new file mode 100644 index 0000000000..aa692617b6 --- /dev/null +++ b/tests/manual/tasktree/taskwidget.h @@ -0,0 +1,78 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0+ OR GPL-3.0 WITH Qt-GPL-exception-1.0 + +#include <utils/layoutbuilder.h> +#include <utils/tasktree.h> + +#include <QWidget> + +class StateIndicator; + +QT_BEGIN_NAMESPACE +class QCheckBox; +class QComboBox; +class QLabel; +class QSpinBox; +QT_END_NAMESPACE + +enum class State { + Initial, + Running, + Done, + Error +}; + +class StateWidget : public QWidget +{ +public: + StateWidget(); + + void setState(State state); + +protected: + StateIndicator *m_stateIndicator = nullptr; +}; + +class TaskWidget : public StateWidget +{ +public: + TaskWidget(); + + void setBusyTime(int seconds); + int busyTime() const; + void setSuccess(bool success); + bool isSuccess() const; + +private: + QLabel *m_infoLabel = nullptr; + QSpinBox *m_spinBox = nullptr; + QCheckBox *m_checkBox = nullptr; +}; + +class GroupWidget : public StateWidget +{ +public: + GroupWidget(); + + void setExecuteMode(Utils::Tasking::ExecuteMode mode); + Utils::Tasking::ExecuteMode executeMode() const; + + void setWorkflowPolicy(Utils::Tasking::WorkflowPolicy policy); + Utils::Tasking::WorkflowPolicy workflowPolicy() const; + +private: + void updateExecuteMode(); + void updateWorkflowPolicy(); + + QComboBox *m_executeCombo = nullptr; + QComboBox *m_workflowCombo = nullptr; + + Utils::Tasking::ExecuteMode m_executeMode = Utils::Tasking::ExecuteMode::Sequential; + Utils::Tasking::WorkflowPolicy m_workflowPolicy = Utils::Tasking::WorkflowPolicy::StopOnError; +}; + +class TaskGroup : public Utils::Layouting::Row +{ +public: + TaskGroup(QWidget *group, std::initializer_list<Utils::LayoutBuilder::LayoutItem> items); +}; diff --git a/tests/manual/widgets/infolabel/tst_manual_widgets_infolabel.cpp b/tests/manual/widgets/infolabel/tst_manual_widgets_infolabel.cpp index a522b37913..78d8e5a2f3 100644 --- a/tests/manual/widgets/infolabel/tst_manual_widgets_infolabel.cpp +++ b/tests/manual/widgets/infolabel/tst_manual_widgets_infolabel.cpp @@ -5,7 +5,6 @@ #include <QApplication> #include <QFormLayout> -#include <QLayout> #include <QMessageBox> #include <QSettings> diff --git a/tests/manual/widgets/manhattanstyle/tst_manual_widgets_manhattanstyle.cpp b/tests/manual/widgets/manhattanstyle/tst_manual_widgets_manhattanstyle.cpp index 5cb3c71406..a3f9e92353 100644 --- a/tests/manual/widgets/manhattanstyle/tst_manual_widgets_manhattanstyle.cpp +++ b/tests/manual/widgets/manhattanstyle/tst_manual_widgets_manhattanstyle.cpp @@ -8,7 +8,6 @@ #include <QGroupBox> #include <QComboBox> #include <QLineEdit> -#include <QFormLayout> #include <QLayout> #include <QListWidget> #include <QMenuBar> diff --git a/tests/unit/mockup/qmldesigner/designercore/include/nodeinstanceview.h b/tests/unit/mockup/qmldesigner/designercore/include/nodeinstanceview.h index c89da38284..7c948dfa01 100644 --- a/tests/unit/mockup/qmldesigner/designercore/include/nodeinstanceview.h +++ b/tests/unit/mockup/qmldesigner/designercore/include/nodeinstanceview.h @@ -17,7 +17,9 @@ class NodeInstanceView : public AbstractView Q_OBJECT public: - NodeInstanceView([[maybe_unused]] QObject *parent) {} + NodeInstanceView(ExternalDependenciesInterface &externalDependencies) + : AbstractView{externalDependencies} + {} ~NodeInstanceView() override {} void modelAttached([[maybe_unused]] Model *model) override {} diff --git a/tests/unit/mockup/qmldesigner/designercore/include/nodemetainfo.h b/tests/unit/mockup/qmldesigner/designercore/include/nodemetainfo.h index 9a35096103..fe8abea17b 100644 --- a/tests/unit/mockup/qmldesigner/designercore/include/nodemetainfo.h +++ b/tests/unit/mockup/qmldesigner/designercore/include/nodemetainfo.h @@ -76,6 +76,8 @@ public: bool isQtQuick3DModel() const { return {}; } bool isQtQuick3DMaterial() const { return {}; } bool isQtQuickLoader() const { return {}; } + bool isQtQuickItem() const { return {}; } + bool isQtQuick3DTexture() const { return {}; } QString importDirectoryPath() const { return {}; } diff --git a/tests/unit/mockup/qmldesigner/designercore/include/rewriterview.h b/tests/unit/mockup/qmldesigner/designercore/include/rewriterview.h index be1ba9e7d8..edde6b32e5 100644 --- a/tests/unit/mockup/qmldesigner/designercore/include/rewriterview.h +++ b/tests/unit/mockup/qmldesigner/designercore/include/rewriterview.h @@ -44,7 +44,9 @@ public: }; public: - RewriterView(DifferenceHandling, QObject *) {} + RewriterView(DifferenceHandling, ExternalDependenciesInterface &externalDependencies) + : AbstractView{externalDependencies} + {} ~RewriterView() override {} void modelAttached(Model *) override {} diff --git a/tests/unit/unittest/CMakeLists.txt b/tests/unit/unittest/CMakeLists.txt index 4e04d2e6f2..4e2deb605d 100644 --- a/tests/unit/unittest/CMakeLists.txt +++ b/tests/unit/unittest/CMakeLists.txt @@ -155,10 +155,10 @@ extend_qtc_test(unittest "${QmlDesignerDir}/designercore" "${QmlDesignerDir}/designercore/include" "${QmlDesignerDir}/designercore/imagecache" - "${QmlDesignerDir}/../../../share/qtcreator/qml/qmlpuppet/interfaces" - "${QmlDesignerDir}/../../../share/qtcreator/qml/qmlpuppet/types" + "${QmlDesignerDir}/../../../src/libs/qmlpuppetcommunication/interfaces" + "${QmlDesignerDir}/../../../src/libs/qmlpuppetcommunication/types" DEFINES - QMLDESIGNER_TEST QMLDESIGNER_STATIC_LIBRARY + QMLDESIGNERCORE_STATIC_LIBRARY QMLDESIGNER_STATIC_LIBRARY SOURCES_PREFIX "${QmlDesignerDir}" SOURCES @@ -167,7 +167,7 @@ extend_qtc_test(unittest extend_qtc_test(unittest SOURCES_PREFIX "${QmlDesignerDir}/designercore" SOURCES - ../../../../share/qtcreator/qml/qmlpuppet/interfaces/commondefines.h + ../../../../src/libs/qmlpuppetcommunication/interfaces/commondefines.h ../components/listmodeleditor/listmodeleditormodel.cpp ../components/listmodeleditor/listmodeleditormodel.h exceptions/exception.cpp diff --git a/tests/unit/unittest/abstractviewmock.h b/tests/unit/unittest/abstractviewmock.h index 5d3ba2a49e..45a599f7f7 100644 --- a/tests/unit/unittest/abstractviewmock.h +++ b/tests/unit/unittest/abstractviewmock.h @@ -10,5 +10,8 @@ class AbstractViewMock : public QmlDesigner::AbstractView { public: + AbstractViewMock(QmlDesigner::ExternalDependenciesInterface *externalDependencies = nullptr) + : QmlDesigner::AbstractView{*externalDependencies} + {} MOCK_METHOD(void, nodeOrderChanged, (const QmlDesigner::NodeListProperty &listProperty), (override)); }; diff --git a/tests/unit/unittest/filesystemmock.h b/tests/unit/unittest/filesystemmock.h index 0c325d1bbb..0af7eef864 100644 --- a/tests/unit/unittest/filesystemmock.h +++ b/tests/unit/unittest/filesystemmock.h @@ -15,6 +15,7 @@ public: directoryEntries, (const QString &directoryPath), (const, override)); + MOCK_METHOD(QStringList, qmlFileNames, (const QString &directoryPath), (const, override)); MOCK_METHOD(long long, lastModified, (QmlDesigner::SourceId sourceId), (const, override)); MOCK_METHOD(QmlDesigner::FileStatus, fileStatus, (QmlDesigner::SourceId sourceId), (const, override)); MOCK_METHOD(void, remove, (const QmlDesigner::SourceIds &sourceIds), (override)); diff --git a/tests/unit/unittest/gtest-creator-printing.cpp b/tests/unit/unittest/gtest-creator-printing.cpp index c703b802ad..3eadd98e8f 100644 --- a/tests/unit/unittest/gtest-creator-printing.cpp +++ b/tests/unit/unittest/gtest-creator-printing.cpp @@ -676,9 +676,12 @@ std::ostream &operator<<(std::ostream &out, ChangeLevel changeLevel) std::ostream &operator<<(std::ostream &out, const SynchronizationPackage &package) { - return out << "(" << package.imports << ", " << package.types << ", " - << package.updatedSourceIds << ", " << package.fileStatuses << ", " - << package.updatedFileStatusSourceIds << ", " << package.projectDatas << ")"; + return out << "(imports: " << package.imports << ", types: " << package.types + << ", updatedSourceIds: " << package.updatedSourceIds + << ", fileStatuses: " << package.fileStatuses + << ", updatedFileStatusSourceIds: " << package.updatedFileStatusSourceIds + << ", updatedProjectSourceIds: " << package.updatedProjectSourceIds + << ", projectDatas: " << package.projectDatas << ")"; } std::ostream &operator<<(std::ostream &out, const ProjectData &data) diff --git a/tests/unit/unittest/listmodeleditor-test.cpp b/tests/unit/unittest/listmodeleditor-test.cpp index 9b12adc003..bde9b74700 100644 --- a/tests/unit/unittest/listmodeleditor-test.cpp +++ b/tests/unit/unittest/listmodeleditor-test.cpp @@ -175,7 +175,7 @@ public: protected: MockFunction<ModelNode(const ModelNode &)> mockGoIntoComponent; - std::unique_ptr<QmlDesigner::Model> designerModel{QmlDesigner::Model::create("QtQuick.Item", 1, 1)}; + QmlDesigner::ModelPointer designerModel{QmlDesigner::Model::create("QtQuick.Item", 1, 1)}; NiceMock<MockListModelEditorView> mockView; QmlDesigner::ListModelEditorModel model{ [&] { return mockView.createModelNode("QtQml.Models.ListModel", 2, 15); }, @@ -187,7 +187,7 @@ protected: ModelNode element1; ModelNode element2; ModelNode element3; - std::unique_ptr<QmlDesigner::Model> componentModel{ + QmlDesigner::ModelPointer componentModel{ QmlDesigner::Model::create("QtQml.Models.ListModel", 1, 1)}; NiceMock<MockListModelEditorView> mockComponentView; ModelNode componentElement; diff --git a/tests/unit/unittest/mocklistmodeleditorview.h b/tests/unit/unittest/mocklistmodeleditorview.h index ba2c2b66b5..ec00129d43 100644 --- a/tests/unit/unittest/mocklistmodeleditorview.h +++ b/tests/unit/unittest/mocklistmodeleditorview.h @@ -10,6 +10,9 @@ class MockListModelEditorView : public QmlDesigner::AbstractView { public: + MockListModelEditorView(QmlDesigner::ExternalDependenciesInterface *externalDependencies = nullptr) + : AbstractView{*externalDependencies} + {} MOCK_METHOD(void, variantPropertiesChanged, (const QList<QmlDesigner::VariantProperty> &propertyList, diff --git a/tests/unit/unittest/projectstorageupdater-test.cpp b/tests/unit/unittest/projectstorageupdater-test.cpp index 30f46081ff..6d55565c1e 100644 --- a/tests/unit/unittest/projectstorageupdater-test.cpp +++ b/tests/unit/unittest/projectstorageupdater-test.cpp @@ -103,7 +103,8 @@ MATCHER_P4(IsProjectData, const Storage::Synchronization::ProjectData &projectData = arg; return compareInvalidAreTrue(projectData.projectSourceId, projectSourceId) - && projectData.sourceId == sourceId && projectData.moduleId == moduleId + && projectData.sourceId == sourceId + && compareInvalidAreTrue(projectData.moduleId, moduleId) && projectData.fileType == fileType; } @@ -138,9 +139,17 @@ public: ON_CALL(projectStorageMock, fetchFileStatus(Eq(qmlDirPathSourceId))) .WillByDefault(Return(FileStatus{qmlDirPathSourceId, 2, 421})); + ON_CALL(fileSystemMock, fileStatus(Eq(directoryPathSourceId))) + .WillByDefault(Return(FileStatus{directoryPathSourceId, 2, 421})); + ON_CALL(projectStorageMock, fetchFileStatus(Eq(directoryPathSourceId))) + .WillByDefault(Return(FileStatus{directoryPathSourceId, 2, 421})); + ON_CALL(fileSystemMock, contentAsQString(Eq(QString("/path/qmldir")))) .WillByDefault(Return(qmldirContent)); + ON_CALL(fileSystemMock, qmlFileNames(Eq(QString("/path")))) + .WillByDefault(Return(QStringList{"First.qml", "First2.qml", "Second.qml"})); + ON_CALL(fileSystemMock, fileStatus(Eq(qmlDocumentSourceId1))) .WillByDefault(Return(FileStatus{qmlDocumentSourceId1, 22, 12})); ON_CALL(projectStorageMock, fetchFileStatus(Eq(qmlDocumentSourceId1))) @@ -218,6 +227,7 @@ protected: SourceId qmltypesPathSourceId = sourcePathCache.sourceId("/path/example.qmltypes"); SourceId qmltypes2PathSourceId = sourcePathCache.sourceId("/path/types/example2.qmltypes"); SourceId qmlDirPathSourceId = sourcePathCache.sourceId("/path/qmldir"); + SourceId directoryPathSourceId = sourcePathCache.sourceId("/path/."); SourceId qmlDocumentSourceId1 = sourcePathCache.sourceId("/path/First.qml"); SourceId qmlDocumentSourceId2 = sourcePathCache.sourceId("/path/First2.qml"); SourceId qmlDocumentSourceId3 = sourcePathCache.sourceId("/path/Second.qml"); @@ -270,13 +280,13 @@ protected: QString qmldirContent{"module Example\ntypeinfo example.qmltypes\n"}; QString qmltypes1{"Module {\ndependencies: [module1]}"}; QString qmltypes2{"Module {\ndependencies: [module2]}"}; - QStringList qmlDirs = {"/path/qmldir"}; + QStringList directories = {"/path"}; }; TEST_F(ProjectStorageUpdater, GetContentForQmlDirPathsIfFileStatusIsDifferent) { SourceId qmlDir3PathSourceId = sourcePathCache.sourceId("/path/three/qmldir"); - QStringList qmlDirs = {"/path/one/qmldir", "/path/two/qmldir", "/path/three/qmldir"}; + QStringList directories = {"/path/one", "/path/two", "/path/three"}; ON_CALL(fileSystemMock, fileStatus(_)).WillByDefault([](auto sourceId) { return FileStatus{sourceId, 21, 421}; }); @@ -291,7 +301,7 @@ TEST_F(ProjectStorageUpdater, GetContentForQmlDirPathsIfFileStatusIsDifferent) EXPECT_CALL(fileSystemMock, contentAsQString(Eq(QString("/path/one/qmldir")))); EXPECT_CALL(fileSystemMock, contentAsQString(Eq(QString("/path/two/qmldir")))); - updater.update(qmlDirs, {}); + updater.update(directories, {}); } TEST_F(ProjectStorageUpdater, RequestFileStatusFromFileSystem) @@ -300,25 +310,27 @@ TEST_F(ProjectStorageUpdater, RequestFileStatusFromFileSystem) EXPECT_CALL(fileSystemMock, fileStatus(Eq(qmlDirPathSourceId))); - updater.update(qmlDirs, {}); + updater.update(directories, {}); } TEST_F(ProjectStorageUpdater, GetContentForQmlTypes) { QString qmldir{R"(module Example typeinfo example.qmltypes)"}; + ON_CALL(fileSystemMock, qmlFileNames(Eq(QString("/path")))).WillByDefault(Return(QStringList{})); EXPECT_CALL(fileSystemMock, contentAsQString(Eq(QString("/path/qmldir")))) .WillRepeatedly(Return(qmldir)); EXPECT_CALL(fileSystemMock, contentAsQString(Eq(QString("/path/example.qmltypes")))); - updater.update(qmlDirs, {}); + updater.update(directories, {}); } TEST_F(ProjectStorageUpdater, GetContentForQmlTypesIfProjectStorageFileStatusIsInvalid) { QString qmldir{R"(module Example typeinfo example.qmltypes)"}; + ON_CALL(fileSystemMock, qmlFileNames(Eq(QString("/path")))).WillByDefault(Return(QStringList{})); EXPECT_CALL(fileSystemMock, contentAsQString(Eq(QString("/path/qmldir")))) .WillRepeatedly(Return(qmldir)); ON_CALL(projectStorageMock, fetchFileStatus(Eq(qmltypesPathSourceId))) @@ -326,20 +338,21 @@ TEST_F(ProjectStorageUpdater, GetContentForQmlTypesIfProjectStorageFileStatusIsI EXPECT_CALL(fileSystemMock, contentAsQString(Eq(QString("/path/example.qmltypes")))); - updater.update(qmlDirs, {}); + updater.update(directories, {}); } TEST_F(ProjectStorageUpdater, DontGetContentForQmlTypesIfFileSystemFileStatusIsInvalid) { QString qmldir{R"(module Example typeinfo example.qmltypes)"}; + ON_CALL(fileSystemMock, qmlFileNames(Eq(QString("/path")))).WillByDefault(Return(QStringList{})); EXPECT_CALL(fileSystemMock, contentAsQString(Eq(QString("/path/qmldir")))) .WillRepeatedly(Return(qmldir)); ON_CALL(fileSystemMock, fileStatus(Eq(qmltypesPathSourceId))).WillByDefault(Return(FileStatus{})); EXPECT_CALL(fileSystemMock, contentAsQString(Eq(QString("/path/example.qmltypes")))).Times(0); - updater.update(qmlDirs, {}); + updater.update(directories, {}); } TEST_F(ProjectStorageUpdater, ParseQmlTypes) @@ -360,7 +373,7 @@ TEST_F(ProjectStorageUpdater, ParseQmlTypes) EXPECT_CALL(qmlTypesParserMock, parse(qmltypes2, _, _, Field(&ProjectData::moduleId, exampleCppNativeModuleId))); - updater.update(qmlDirs, {}); + updater.update(directories, {}); } TEST_F(ProjectStorageUpdater, SynchronizeIsEmptyForNoChange) @@ -374,7 +387,7 @@ TEST_F(ProjectStorageUpdater, SynchronizeIsEmptyForNoChange) EXPECT_CALL(projectStorageMock, synchronize(PackageIsEmpty())); - updater.update(qmlDirs, {}); + updater.update(directories, {}); } TEST_F(ProjectStorageUpdater, SynchronizeQmlTypes) @@ -383,6 +396,7 @@ TEST_F(ProjectStorageUpdater, SynchronizeQmlTypes) Storage::Synchronization::Version{2, 3}, qmltypesPathSourceId}; QString qmltypes{"Module {\ndependencies: []}"}; + ON_CALL(fileSystemMock, qmlFileNames(Eq(QString("/path")))).WillByDefault(Return(QStringList{})); ON_CALL(fileSystemMock, contentAsQString(Eq(QString("/path/example.qmltypes")))) .WillByDefault(Return(qmltypes)); ON_CALL(qmlTypesParserMock, parse(qmltypes, _, _, _)) @@ -411,7 +425,7 @@ TEST_F(ProjectStorageUpdater, SynchronizeQmlTypes) Field(&SynchronizationPackage::updatedProjectSourceIds, UnorderedElementsAre(qmlDirPathSourceId))))); - updater.update(qmlDirs, {}); + updater.update(directories, {}); } TEST_F(ProjectStorageUpdater, SynchronizeQmlTypesAreEmptyIfFileDoesNotChanged) @@ -430,12 +444,14 @@ TEST_F(ProjectStorageUpdater, SynchronizeQmlTypesAreEmptyIfFileDoesNotChanged) EXPECT_CALL(projectStorageMock, synchronize(PackageIsEmpty())); - updater.update(qmlDirs, {}); + updater.update(directories, {}); } TEST_F(ProjectStorageUpdater, GetContentForQmlDocuments) { SourceId oldSecondSourceId3 = sourcePathCache.sourceId("/path/OldSecond.qml"); + ON_CALL(fileSystemMock, qmlFileNames(Eq(QString("/path")))) + .WillByDefault(Return(QStringList{"First.qml", "First2.qml", "OldSecond.qml", "Second.qml"})); ON_CALL(fileSystemMock, fileStatus(Eq(oldSecondSourceId3))) .WillByDefault(Return(FileStatus{oldSecondSourceId3, 22, 14})); ON_CALL(fileSystemMock, contentAsQString(Eq(QString("/path/OldSecond.qml")))) @@ -453,7 +469,7 @@ TEST_F(ProjectStorageUpdater, GetContentForQmlDocuments) EXPECT_CALL(fileSystemMock, contentAsQString(Eq(QString("/path/OldSecond.qml")))); EXPECT_CALL(fileSystemMock, contentAsQString(Eq(QString("/path/Second.qml")))); - updater.update(qmlDirs, {}); + updater.update(directories, {}); } TEST_F(ProjectStorageUpdater, ParseQmlDocuments) @@ -477,7 +493,7 @@ TEST_F(ProjectStorageUpdater, ParseQmlDocuments) EXPECT_CALL(qmlDocumentParserMock, parse(qmlDocument2, _, _, _)); EXPECT_CALL(qmlDocumentParserMock, parse(qmlDocument3, _, _, _)); - updater.update(qmlDirs, {}); + updater.update(directories, {}); } TEST_F(ProjectStorageUpdater, ParseQmlDocumentsWithNonExistingQmlDocumentThrows) @@ -486,7 +502,7 @@ TEST_F(ProjectStorageUpdater, ParseQmlDocumentsWithNonExistingQmlDocumentThrows) NonexitingType 1.0 NonexitingType.qml)"}; ON_CALL(fileSystemMock, contentAsQString(Eq(QString("/path/qmldir")))).WillByDefault(Return(qmldir)); - ASSERT_THROW(updater.update(qmlDirs, {}), QmlDesigner::CannotParseQmlDocumentFile); + ASSERT_THROW(updater.update(directories, {}), QmlDesigner::CannotParseQmlDocumentFile); } TEST_F(ProjectStorageUpdater, SynchronizeQmlDocuments) @@ -501,188 +517,411 @@ TEST_F(ProjectStorageUpdater, SynchronizeQmlDocuments) projectStorageMock, synchronize(AllOf( Field(&SynchronizationPackage::imports, UnorderedElementsAre(import1, import2, import3)), + Field( + &SynchronizationPackage::types, + UnorderedElementsAre( + AllOf(IsStorageType("First.qml", + Storage::Synchronization::ImportedType{"Object"}, + TypeTraits::Reference, + qmlDocumentSourceId1, + Storage::Synchronization::ChangeLevel::Full), + Field(&Storage::Synchronization::Type::exportedTypes, + UnorderedElementsAre(IsExportedType(exampleModuleId, "FirstType", 1, 0), + IsExportedType(pathModuleId, "First", -1, -1)))), + AllOf(IsStorageType("First2.qml", + Storage::Synchronization::ImportedType{"Object2"}, + TypeTraits::Reference, + qmlDocumentSourceId2, + Storage::Synchronization::ChangeLevel::Full), + Field(&Storage::Synchronization::Type::exportedTypes, + UnorderedElementsAre(IsExportedType(exampleModuleId, "FirstType", 2, 2), + IsExportedType(pathModuleId, "First2", -1, -1)))), + AllOf(IsStorageType("Second.qml", + Storage::Synchronization::ImportedType{"Object3"}, + TypeTraits::Reference, + qmlDocumentSourceId3, + Storage::Synchronization::ChangeLevel::Full), + Field(&Storage::Synchronization::Type::exportedTypes, + UnorderedElementsAre(IsExportedType(exampleModuleId, "SecondType", 2, 2), + IsExportedType(pathModuleId, "Second", -1, -1)))))), + Field(&SynchronizationPackage::updatedSourceIds, + UnorderedElementsAre(qmlDirPathSourceId, + qmlDocumentSourceId1, + qmlDocumentSourceId2, + qmlDocumentSourceId3)), + Field(&SynchronizationPackage::updatedFileStatusSourceIds, + UnorderedElementsAre(qmlDirPathSourceId, + qmlDocumentSourceId1, + qmlDocumentSourceId2, + qmlDocumentSourceId3)), + Field(&SynchronizationPackage::fileStatuses, + UnorderedElementsAre(IsFileStatus(qmlDirPathSourceId, 21, 421), + IsFileStatus(qmlDocumentSourceId1, 22, 12), + IsFileStatus(qmlDocumentSourceId2, 22, 13), + IsFileStatus(qmlDocumentSourceId3, 22, 14))), + Field(&SynchronizationPackage::updatedProjectSourceIds, + UnorderedElementsAre(qmlDirPathSourceId)), + Field(&SynchronizationPackage::projectDatas, + UnorderedElementsAre( + IsProjectData(qmlDirPathSourceId, qmlDocumentSourceId1, ModuleId{}, FileType::QmlDocument), + IsProjectData(qmlDirPathSourceId, qmlDocumentSourceId2, ModuleId{}, FileType::QmlDocument), + IsProjectData(qmlDirPathSourceId, + qmlDocumentSourceId3, + ModuleId{}, + FileType::QmlDocument)))))); + + updater.update(directories, {}); +} + +TEST_F(ProjectStorageUpdater, SynchronizeAddOnlyQmlDocumentInDirectory) +{ + QString qmldir{R"(module Example + FirstType 1.0 First.qml)"}; + ON_CALL(fileSystemMock, contentAsQString(Eq(QString("/path/qmldir")))).WillByDefault(Return(qmldir)); + ON_CALL(fileSystemMock, fileStatus(Eq(qmlDocumentSourceId1))) + .WillByDefault(Return(FileStatus{qmlDocumentSourceId1, 22, 2})); + ON_CALL(fileSystemMock, qmlFileNames(Eq(QString("/path")))) + .WillByDefault(Return(QStringList{"First.qml", "First2.qml"})); + + EXPECT_CALL( + projectStorageMock, + synchronize(AllOf( + Field(&SynchronizationPackage::imports, UnorderedElementsAre(import1, import2, import3)), Field(&SynchronizationPackage::types, UnorderedElementsAre( AllOf(IsStorageType("First.qml", Storage::Synchronization::ImportedType{"Object"}, TypeTraits::Reference, qmlDocumentSourceId1, - Storage::Synchronization::ChangeLevel::Full), + Storage::Synchronization::ChangeLevel::Minimal), Field(&Storage::Synchronization::Type::exportedTypes, - ElementsAre(IsExportedType(exampleModuleId, "FirstType", 1, 0), - IsExportedType(pathModuleId, "First", -1, -1)))), + UnorderedElementsAre(IsExportedType(exampleModuleId, "FirstType", 1, 0), + IsExportedType(pathModuleId, "First", -1, -1)))), AllOf(IsStorageType("First2.qml", Storage::Synchronization::ImportedType{"Object2"}, TypeTraits::Reference, qmlDocumentSourceId2, Storage::Synchronization::ChangeLevel::Full), Field(&Storage::Synchronization::Type::exportedTypes, - ElementsAre(IsExportedType(exampleModuleId, "FirstType", 2, 2), - IsExportedType(pathModuleId, "First2", -1, -1)))), - AllOf(IsStorageType("Second.qml", - Storage::Synchronization::ImportedType{"Object3"}, - TypeTraits::Reference, - qmlDocumentSourceId3, - Storage::Synchronization::ChangeLevel::Full), - Field(&Storage::Synchronization::Type::exportedTypes, - ElementsAre(IsExportedType(exampleModuleId, "SecondType", 2, 2), - IsExportedType(pathModuleId, "Second", -1, -1)))))), + UnorderedElementsAre(IsExportedType(pathModuleId, "First2", -1, -1)))))), Field(&SynchronizationPackage::updatedSourceIds, - UnorderedElementsAre(qmlDirPathSourceId, - qmlDocumentSourceId1, - qmlDocumentSourceId2, - qmlDocumentSourceId3)), + UnorderedElementsAre(qmlDocumentSourceId1, qmlDocumentSourceId2)), Field(&SynchronizationPackage::updatedFileStatusSourceIds, - UnorderedElementsAre(qmlDirPathSourceId, - qmlDocumentSourceId1, - qmlDocumentSourceId2, - qmlDocumentSourceId3)), + UnorderedElementsAre(qmlDocumentSourceId2)), Field(&SynchronizationPackage::fileStatuses, - UnorderedElementsAre(IsFileStatus(qmlDirPathSourceId, 21, 421), - IsFileStatus(qmlDocumentSourceId1, 22, 12), - IsFileStatus(qmlDocumentSourceId2, 22, 13), - IsFileStatus(qmlDocumentSourceId3, 22, 14))), + UnorderedElementsAre(IsFileStatus(qmlDocumentSourceId2, 22, 13))), Field(&SynchronizationPackage::updatedProjectSourceIds, UnorderedElementsAre(qmlDirPathSourceId)), Field(&SynchronizationPackage::projectDatas, UnorderedElementsAre(IsProjectData(qmlDirPathSourceId, qmlDocumentSourceId1, - exampleModuleId, + ModuleId{}, FileType::QmlDocument), IsProjectData(qmlDirPathSourceId, qmlDocumentSourceId2, - exampleModuleId, - FileType::QmlDocument), - IsProjectData(qmlDirPathSourceId, - qmlDocumentSourceId3, - exampleModuleId, + ModuleId{}, FileType::QmlDocument)))))); - updater.update(qmlDirs, {}); + updater.update(directories, {}); } -TEST_F(ProjectStorageUpdater, SynchronizeRemoved) +TEST_F(ProjectStorageUpdater, SynchronizeRemovesQmlDocument) { QString qmldir{R"(module Example FirstType 1.0 First.qml FirstType 2.2 First2.qml - typeinfo example.qmltypes - typeinfo types/example2.qmltypes )"}; ON_CALL(fileSystemMock, contentAsQString(Eq(QString("/path/qmldir")))).WillByDefault(Return(qmldir)); - ON_CALL(projectStorageMock, fetchFileStatus(Eq(qmlDocumentSourceId2))) - .WillByDefault(Return(FileStatus{qmlDocumentSourceId2, 22, 13})); - ON_CALL(projectStorageMock, fetchFileStatus(Eq(qmltypes2PathSourceId))) - .WillByDefault(Return(FileStatus{qmltypes2PathSourceId, 21, 421})); + ON_CALL(fileSystemMock, fileStatus(Eq(qmlDirPathSourceId))) + .WillByDefault(Return(FileStatus{qmlDirPathSourceId, 21, 422})); + ON_CALL(fileSystemMock, fileStatus(Eq(qmlDocumentSourceId1))) + .WillByDefault(Return(FileStatus{qmlDocumentSourceId1, 22, 2})); + ON_CALL(fileSystemMock, fileStatus(Eq(qmlDocumentSourceId2))) + .WillByDefault(Return(FileStatus{qmlDocumentSourceId2, 22, 2})); + ON_CALL(fileSystemMock, fileStatus(Eq(qmlDocumentSourceId3))) + .WillByDefault(Return(FileStatus{qmlDocumentSourceId3, -1, -1})); ON_CALL(projectStorageMock, fetchProjectDatas(Eq(qmlDirPathSourceId))) .WillByDefault(Return(QmlDesigner::Storage::Synchronization::ProjectDatas{ - {qmlDirPathSourceId, qmltypesPathSourceId, exampleModuleId, FileType::QmlTypes}, - {qmlDirPathSourceId, qmltypes2PathSourceId, exampleModuleId, FileType::QmlTypes}, - {qmlDirPathSourceId, qmlDocumentSourceId1, exampleModuleId, FileType::QmlDocument}, - {qmlDirPathSourceId, qmlDocumentSourceId2, exampleModuleId, FileType::QmlDocument}, - {qmlDirPathSourceId, qmlDocumentSourceId3, exampleModuleId, FileType::QmlDocument}})); + {qmlDirPathSourceId, qmlDocumentSourceId1, ModuleId{}, FileType::QmlDocument}, + {qmlDirPathSourceId, qmlDocumentSourceId2, ModuleId{}, FileType::QmlDocument}, + {qmlDirPathSourceId, qmlDocumentSourceId3, ModuleId{}, FileType::QmlDocument}})); + ON_CALL(fileSystemMock, qmlFileNames(Eq(QString("/path")))) + .WillByDefault(Return(QStringList{"First.qml", "First2.qml"})); + + EXPECT_CALL(projectStorageMock, + synchronize(AllOf( + Field(&SynchronizationPackage::imports, IsEmpty()), + Field(&SynchronizationPackage::types, + UnorderedElementsAre( + AllOf(IsStorageType("First.qml", + Storage::Synchronization::ImportedType{}, + TypeTraits::Reference, + qmlDocumentSourceId1, + Storage::Synchronization::ChangeLevel::Minimal), + Field(&Storage::Synchronization::Type::exportedTypes, + UnorderedElementsAre( + IsExportedType(exampleModuleId, "FirstType", 1, 0), + IsExportedType(pathModuleId, "First", -1, -1)))), + AllOf(IsStorageType("First2.qml", + Storage::Synchronization::ImportedType{}, + TypeTraits::Reference, + qmlDocumentSourceId2, + Storage::Synchronization::ChangeLevel::Minimal), + Field(&Storage::Synchronization::Type::exportedTypes, + UnorderedElementsAre( + IsExportedType(exampleModuleId, "FirstType", 2, 2), + IsExportedType(pathModuleId, "First2", -1, -1)))))), + Field(&SynchronizationPackage::updatedSourceIds, + UnorderedElementsAre(qmlDirPathSourceId, + qmlDocumentSourceId1, + qmlDocumentSourceId2, + qmlDocumentSourceId3)), + Field(&SynchronizationPackage::updatedFileStatusSourceIds, + UnorderedElementsAre(qmlDirPathSourceId, qmlDocumentSourceId3)), + Field(&SynchronizationPackage::fileStatuses, + UnorderedElementsAre(IsFileStatus(qmlDirPathSourceId, 21, 422))), + Field(&SynchronizationPackage::updatedProjectSourceIds, + UnorderedElementsAre(qmlDirPathSourceId)), + Field(&SynchronizationPackage::projectDatas, + UnorderedElementsAre(IsProjectData(qmlDirPathSourceId, + qmlDocumentSourceId1, + ModuleId{}, + FileType::QmlDocument), + IsProjectData(qmlDirPathSourceId, + qmlDocumentSourceId2, + ModuleId{}, + FileType::QmlDocument)))))); + + updater.update(directories, {}); +} + +TEST_F(ProjectStorageUpdater, SynchronizeRemovesQmlDocumentInQmldirOnly) +{ + QString qmldir{R"(module Example + FirstType 1.0 First.qml + )"}; + ON_CALL(fileSystemMock, contentAsQString(Eq(QString("/path/qmldir")))).WillByDefault(Return(qmldir)); + ON_CALL(fileSystemMock, fileStatus(Eq(qmlDirPathSourceId))) + .WillByDefault(Return(FileStatus{qmlDirPathSourceId, 21, 422})); + ON_CALL(fileSystemMock, fileStatus(Eq(qmlDocumentSourceId1))) + .WillByDefault(Return(FileStatus{qmlDocumentSourceId1, 22, 2})); + ON_CALL(fileSystemMock, fileStatus(Eq(qmlDocumentSourceId2))) + .WillByDefault(Return(FileStatus{qmlDocumentSourceId2, 22, 2})); + ON_CALL(projectStorageMock, fetchProjectDatas(Eq(qmlDirPathSourceId))) + .WillByDefault(Return(QmlDesigner::Storage::Synchronization::ProjectDatas{ + {qmlDirPathSourceId, qmlDocumentSourceId1, ModuleId{}, FileType::QmlDocument}, + {qmlDirPathSourceId, qmlDocumentSourceId2, ModuleId{}, FileType::QmlDocument}})); + ON_CALL(fileSystemMock, qmlFileNames(Eq(QString("/path")))) + .WillByDefault(Return(QStringList{"First.qml", "First2.qml"})); EXPECT_CALL( projectStorageMock, synchronize(AllOf( - Field(&SynchronizationPackage::imports, UnorderedElementsAre(import1, import4)), + Field(&SynchronizationPackage::imports, IsEmpty()), Field(&SynchronizationPackage::types, UnorderedElementsAre( - Eq(objectType), AllOf(IsStorageType("First.qml", - Storage::Synchronization::ImportedType{"Object"}, + Storage::Synchronization::ImportedType{}, TypeTraits::Reference, qmlDocumentSourceId1, - Storage::Synchronization::ChangeLevel::Full), + Storage::Synchronization::ChangeLevel::Minimal), Field(&Storage::Synchronization::Type::exportedTypes, - ElementsAre(IsExportedType(exampleModuleId, "FirstType", 1, 0), - IsExportedType(pathModuleId, "First", -1, -1)))), + UnorderedElementsAre(IsExportedType(exampleModuleId, "FirstType", 1, 0), + IsExportedType(pathModuleId, "First", -1, -1)))), AllOf(IsStorageType("First2.qml", Storage::Synchronization::ImportedType{}, TypeTraits::Reference, qmlDocumentSourceId2, Storage::Synchronization::ChangeLevel::Minimal), Field(&Storage::Synchronization::Type::exportedTypes, - ElementsAre(IsExportedType(exampleModuleId, "FirstType", 2, 2), - IsExportedType(pathModuleId, "First2", -1, -1)))))), + UnorderedElementsAre(IsExportedType(pathModuleId, "First2", -1, -1)))))), Field(&SynchronizationPackage::updatedSourceIds, - UnorderedElementsAre(qmlDirPathSourceId, - qmltypesPathSourceId, - qmlDocumentSourceId1, - qmlDocumentSourceId2, - qmlDocumentSourceId3)), + UnorderedElementsAre(qmlDirPathSourceId, qmlDocumentSourceId1, qmlDocumentSourceId2)), Field(&SynchronizationPackage::updatedFileStatusSourceIds, - UnorderedElementsAre(qmlDirPathSourceId, - qmlDocumentSourceId1, - qmltypesPathSourceId, - qmlDocumentSourceId3)), + UnorderedElementsAre(qmlDirPathSourceId)), Field(&SynchronizationPackage::fileStatuses, - UnorderedElementsAre(IsFileStatus(qmlDirPathSourceId, 21, 421), - IsFileStatus(qmlDocumentSourceId1, 22, 12), - IsFileStatus(qmltypesPathSourceId, 21, 421))), + UnorderedElementsAre(IsFileStatus(qmlDirPathSourceId, 21, 422))), Field(&SynchronizationPackage::updatedProjectSourceIds, UnorderedElementsAre(qmlDirPathSourceId)), Field(&SynchronizationPackage::projectDatas, UnorderedElementsAre(IsProjectData(qmlDirPathSourceId, qmlDocumentSourceId1, - exampleModuleId, + ModuleId{}, FileType::QmlDocument), IsProjectData(qmlDirPathSourceId, qmlDocumentSourceId2, - exampleModuleId, + ModuleId{}, + FileType::QmlDocument)))))); + + updater.update(directories, {}); +} + +TEST_F(ProjectStorageUpdater, SynchronizeAddQmlDocumentToQmldir) +{ + QString qmldir{R"(module Example + FirstType 1.0 First.qml + FirstType 2.2 First2.qml + )"}; + ON_CALL(fileSystemMock, contentAsQString(Eq(QString("/path/qmldir")))).WillByDefault(Return(qmldir)); + ON_CALL(fileSystemMock, fileStatus(Eq(qmlDirPathSourceId))) + .WillByDefault(Return(FileStatus{qmlDirPathSourceId, 21, 422})); + ON_CALL(fileSystemMock, fileStatus(Eq(qmlDocumentSourceId1))) + .WillByDefault(Return(FileStatus{qmlDocumentSourceId1, 22, 2})); + ON_CALL(fileSystemMock, fileStatus(Eq(qmlDocumentSourceId2))) + .WillByDefault(Return(FileStatus{qmlDocumentSourceId2, 22, 2})); + ON_CALL(projectStorageMock, fetchProjectDatas(Eq(qmlDirPathSourceId))) + .WillByDefault(Return(QmlDesigner::Storage::Synchronization::ProjectDatas{ + {qmlDirPathSourceId, qmlDocumentSourceId1, ModuleId{}, FileType::QmlDocument}, + {qmlDirPathSourceId, qmlDocumentSourceId2, ModuleId{}, FileType::QmlDocument}})); + ON_CALL(fileSystemMock, qmlFileNames(Eq(QString("/path")))) + .WillByDefault(Return(QStringList{"First.qml", "First2.qml"})); + + EXPECT_CALL( + projectStorageMock, + synchronize(AllOf( + Field(&SynchronizationPackage::imports, IsEmpty()), + Field( + &SynchronizationPackage::types, + UnorderedElementsAre( + AllOf(IsStorageType("First.qml", + Storage::Synchronization::ImportedType{}, + TypeTraits::Reference, + qmlDocumentSourceId1, + Storage::Synchronization::ChangeLevel::Minimal), + Field(&Storage::Synchronization::Type::exportedTypes, + UnorderedElementsAre(IsExportedType(exampleModuleId, "FirstType", 1, 0), + IsExportedType(pathModuleId, "First", -1, -1)))), + AllOf(IsStorageType("First2.qml", + Storage::Synchronization::ImportedType{}, + TypeTraits::Reference, + qmlDocumentSourceId2, + Storage::Synchronization::ChangeLevel::Minimal), + Field(&Storage::Synchronization::Type::exportedTypes, + UnorderedElementsAre(IsExportedType(exampleModuleId, "FirstType", 2, 2), + IsExportedType(pathModuleId, "First2", -1, -1)))))), + Field(&SynchronizationPackage::updatedSourceIds, + UnorderedElementsAre(qmlDirPathSourceId, qmlDocumentSourceId1, qmlDocumentSourceId2)), + Field(&SynchronizationPackage::updatedFileStatusSourceIds, + UnorderedElementsAre(qmlDirPathSourceId)), + Field(&SynchronizationPackage::fileStatuses, + UnorderedElementsAre(IsFileStatus(qmlDirPathSourceId, 21, 422))), + Field(&SynchronizationPackage::updatedProjectSourceIds, + UnorderedElementsAre(qmlDirPathSourceId)), + Field(&SynchronizationPackage::projectDatas, + UnorderedElementsAre(IsProjectData(qmlDirPathSourceId, + qmlDocumentSourceId1, + ModuleId{}, FileType::QmlDocument), IsProjectData(qmlDirPathSourceId, - qmltypesPathSourceId, - exampleCppNativeModuleId, - FileType::QmlTypes), - IsProjectData(qmlDirPathSourceId, - qmltypes2PathSourceId, - exampleCppNativeModuleId, - FileType::QmlTypes)))))); + qmlDocumentSourceId2, + ModuleId{}, + FileType::QmlDocument)))))); - updater.update(qmlDirs, {}); + updater.update(directories, {}); } -TEST_F(ProjectStorageUpdater, SynchronizeQmlDocumentsDontUpdateIfUpToDate) +TEST_F(ProjectStorageUpdater, SynchronizeAddQmlDocumentToDirectory) { QString qmldir{R"(module Example FirstType 1.0 First.qml - FirstType 2.2 First2.qml - SecondType 2.2 Second.qml)"}; + )"}; ON_CALL(fileSystemMock, contentAsQString(Eq(QString("/path/qmldir")))).WillByDefault(Return(qmldir)); - ON_CALL(projectStorageMock, fetchFileStatus(Eq(qmlDocumentSourceId3))) - .WillByDefault(Return(FileStatus{qmlDocumentSourceId3, 22, 14})); + ON_CALL(fileSystemMock, fileStatus(Eq(qmlDirPathSourceId))) + .WillByDefault(Return(FileStatus{qmlDirPathSourceId, 21, 422})); + ON_CALL(fileSystemMock, fileStatus(Eq(qmlDocumentSourceId1))) + .WillByDefault(Return(FileStatus{qmlDocumentSourceId1, 22, 2})); + ON_CALL(fileSystemMock, fileStatus(Eq(qmlDocumentSourceId2))) + .WillByDefault(Return(FileStatus{qmlDocumentSourceId2, 22, 2})); + ON_CALL(projectStorageMock, fetchProjectDatas(Eq(qmlDirPathSourceId))) + .WillByDefault(Return(QmlDesigner::Storage::Synchronization::ProjectDatas{ + {qmlDirPathSourceId, qmlDocumentSourceId1, ModuleId{}, FileType::QmlDocument}, + {qmlDirPathSourceId, qmlDocumentSourceId2, ModuleId{}, FileType::QmlDocument}})); + ON_CALL(fileSystemMock, qmlFileNames(Eq(QString("/path")))) + .WillByDefault(Return(QStringList{"First.qml", "First2.qml"})); EXPECT_CALL( projectStorageMock, synchronize(AllOf( - Field(&SynchronizationPackage::imports, UnorderedElementsAre(import1, import2)), + Field(&SynchronizationPackage::imports, IsEmpty()), Field(&SynchronizationPackage::types, UnorderedElementsAre( AllOf(IsStorageType("First.qml", - Storage::Synchronization::ImportedType{"Object"}, + Storage::Synchronization::ImportedType{}, TypeTraits::Reference, qmlDocumentSourceId1, - Storage::Synchronization::ChangeLevel::Full), + Storage::Synchronization::ChangeLevel::Minimal), Field(&Storage::Synchronization::Type::exportedTypes, - ElementsAre(IsExportedType(exampleModuleId, "FirstType", 1, 0), - IsExportedType(pathModuleId, "First", -1, -1)))), + UnorderedElementsAre(IsExportedType(exampleModuleId, "FirstType", 1, 0), + IsExportedType(pathModuleId, "First", -1, -1)))), AllOf(IsStorageType("First2.qml", - Storage::Synchronization::ImportedType{"Object2"}, - TypeTraits::Reference, - qmlDocumentSourceId2, - Storage::Synchronization::ChangeLevel::Full), - Field(&Storage::Synchronization::Type::exportedTypes, - ElementsAre(IsExportedType(exampleModuleId, "FirstType", 2, 2), - IsExportedType(pathModuleId, "First2", -1, -1)))), - AllOf(IsStorageType("Second.qml", Storage::Synchronization::ImportedType{}, TypeTraits::Reference, - qmlDocumentSourceId3, + qmlDocumentSourceId2, Storage::Synchronization::ChangeLevel::Minimal), Field(&Storage::Synchronization::Type::exportedTypes, - ElementsAre(IsExportedType(exampleModuleId, "SecondType", 2, 2), - IsExportedType(pathModuleId, "Second", -1, -1)))))), + UnorderedElementsAre(IsExportedType(pathModuleId, "First2", -1, -1)))))), + Field(&SynchronizationPackage::updatedSourceIds, + UnorderedElementsAre(qmlDirPathSourceId, qmlDocumentSourceId1, qmlDocumentSourceId2)), + Field(&SynchronizationPackage::updatedFileStatusSourceIds, + UnorderedElementsAre(qmlDirPathSourceId)), + Field(&SynchronizationPackage::fileStatuses, + UnorderedElementsAre(IsFileStatus(qmlDirPathSourceId, 21, 422))), + Field(&SynchronizationPackage::updatedProjectSourceIds, + UnorderedElementsAre(qmlDirPathSourceId)), + Field(&SynchronizationPackage::projectDatas, + UnorderedElementsAre(IsProjectData(qmlDirPathSourceId, + qmlDocumentSourceId1, + ModuleId{}, + FileType::QmlDocument), + IsProjectData(qmlDirPathSourceId, + qmlDocumentSourceId2, + ModuleId{}, + FileType::QmlDocument)))))); + + updater.update(directories, {}); +} + +TEST_F(ProjectStorageUpdater, SynchronizeQmlDocumentsDontUpdateIfUpToDate) +{ + QString qmldir{R"(module Example + FirstType 1.0 First.qml + FirstType 2.2 First2.qml + SecondType 2.2 Second.qml)"}; + ON_CALL(fileSystemMock, contentAsQString(Eq(QString("/path/qmldir")))).WillByDefault(Return(qmldir)); + ON_CALL(projectStorageMock, fetchFileStatus(Eq(qmlDocumentSourceId3))) + .WillByDefault(Return(FileStatus{qmlDocumentSourceId3, 22, 14})); + + EXPECT_CALL( + projectStorageMock, + synchronize(AllOf( + Field(&SynchronizationPackage::imports, UnorderedElementsAre(import1, import2)), + Field( + &SynchronizationPackage::types, + UnorderedElementsAre( + AllOf(IsStorageType("First.qml", + Storage::Synchronization::ImportedType{"Object"}, + TypeTraits::Reference, + qmlDocumentSourceId1, + Storage::Synchronization::ChangeLevel::Full), + Field(&Storage::Synchronization::Type::exportedTypes, + UnorderedElementsAre(IsExportedType(exampleModuleId, "FirstType", 1, 0), + IsExportedType(pathModuleId, "First", -1, -1)))), + AllOf(IsStorageType("First2.qml", + Storage::Synchronization::ImportedType{"Object2"}, + TypeTraits::Reference, + qmlDocumentSourceId2, + Storage::Synchronization::ChangeLevel::Full), + Field(&Storage::Synchronization::Type::exportedTypes, + UnorderedElementsAre(IsExportedType(exampleModuleId, "FirstType", 2, 2), + IsExportedType(pathModuleId, "First2", -1, -1)))), + AllOf(IsStorageType("Second.qml", + Storage::Synchronization::ImportedType{}, + TypeTraits::Reference, + qmlDocumentSourceId3, + Storage::Synchronization::ChangeLevel::Minimal), + Field(&Storage::Synchronization::Type::exportedTypes, + UnorderedElementsAre(IsExportedType(exampleModuleId, "SecondType", 2, 2), + IsExportedType(pathModuleId, "Second", -1, -1)))))), Field(&SynchronizationPackage::updatedSourceIds, UnorderedElementsAre(qmlDirPathSourceId, qmlDocumentSourceId1, @@ -697,20 +936,15 @@ TEST_F(ProjectStorageUpdater, SynchronizeQmlDocumentsDontUpdateIfUpToDate) Field(&SynchronizationPackage::updatedProjectSourceIds, UnorderedElementsAre(qmlDirPathSourceId)), Field(&SynchronizationPackage::projectDatas, - UnorderedElementsAre(IsProjectData(qmlDirPathSourceId, - qmlDocumentSourceId1, - exampleModuleId, - FileType::QmlDocument), - IsProjectData(qmlDirPathSourceId, - qmlDocumentSourceId2, - exampleModuleId, - FileType::QmlDocument), - IsProjectData(qmlDirPathSourceId, - qmlDocumentSourceId3, - exampleModuleId, - FileType::QmlDocument)))))); - - updater.update(qmlDirs, {}); + UnorderedElementsAre( + IsProjectData(qmlDirPathSourceId, qmlDocumentSourceId1, ModuleId{}, FileType::QmlDocument), + IsProjectData(qmlDirPathSourceId, qmlDocumentSourceId2, ModuleId{}, FileType::QmlDocument), + IsProjectData(qmlDirPathSourceId, + qmlDocumentSourceId3, + ModuleId{}, + FileType::QmlDocument)))))); + + updater.update(directories, {}); } TEST_F(ProjectStorageUpdater, UpdateQmldirDocuments) @@ -744,7 +978,7 @@ TEST_F(ProjectStorageUpdater, AddSourceIdForForInvalidQmldirFileStatus) Field(&SynchronizationPackage::fileStatuses, IsEmpty()), Field(&SynchronizationPackage::updatedFileStatusSourceIds, IsEmpty()), Field(&SynchronizationPackage::projectDatas, IsEmpty())))); - updater.update(qmlDirs, {}); + updater.update(directories, {}); } TEST_F(ProjectStorageUpdater, SynchronizIfQmldirFileHasNotChanged) @@ -796,7 +1030,7 @@ TEST_F(ProjectStorageUpdater, SynchronizIfQmldirFileHasNotChanged) qmlDocumentSourceId2)), Field(&SynchronizationPackage::projectDatas, IsEmpty())))); - updater.update(qmlDirs, {}); + updater.update(directories, {}); } TEST_F(ProjectStorageUpdater, SynchronizIfQmldirFileHasNotChangedAndSomeUpdatedFiles) @@ -836,7 +1070,7 @@ TEST_F(ProjectStorageUpdater, SynchronizIfQmldirFileHasNotChangedAndSomeUpdatedF UnorderedElementsAre(qmltypesPathSourceId, qmlDocumentSourceId1)), Field(&SynchronizationPackage::projectDatas, IsEmpty())))); - updater.update(qmlDirs, {}); + updater.update(directories, {}); } TEST_F(ProjectStorageUpdater, UpdateQmlTypesFilesIsEmpty) @@ -913,39 +1147,39 @@ TEST_F(ProjectStorageUpdater, SynchronizeQmlDocumentsWithDifferentVersionButSame FirstType 1.1 First.qml FirstType 6.0 First.qml)"}; ON_CALL(fileSystemMock, contentAsQString(Eq(QString("/path/qmldir")))).WillByDefault(Return(qmldir)); + ON_CALL(fileSystemMock, qmlFileNames(Eq(QString("/path")))) + .WillByDefault(Return(QStringList{"First.qml"})); - EXPECT_CALL(projectStorageMock, - synchronize( - AllOf(Field(&SynchronizationPackage::imports, UnorderedElementsAre(import1)), - Field(&SynchronizationPackage::types, - UnorderedElementsAre(AllOf( - IsStorageType("First.qml", - Storage::Synchronization::ImportedType{"Object"}, - TypeTraits::Reference, - qmlDocumentSourceId1, - Storage::Synchronization::ChangeLevel::Full), - Field(&Storage::Synchronization::Type::exportedTypes, - UnorderedElementsAre( - IsExportedType(exampleModuleId, "FirstType", 1, 0), - IsExportedType(exampleModuleId, "FirstType", 1, 1), - IsExportedType(exampleModuleId, "FirstType", 6, 0), - IsExportedType(pathModuleId, "First", -1, -1)))))), - Field(&SynchronizationPackage::updatedSourceIds, - UnorderedElementsAre(qmlDirPathSourceId, qmlDocumentSourceId1)), - Field(&SynchronizationPackage::updatedFileStatusSourceIds, - UnorderedElementsAre(qmlDirPathSourceId, qmlDocumentSourceId1)), - Field(&SynchronizationPackage::fileStatuses, - UnorderedElementsAre(IsFileStatus(qmlDirPathSourceId, 21, 421), - IsFileStatus(qmlDocumentSourceId1, 22, 12))), - Field(&SynchronizationPackage::updatedProjectSourceIds, - UnorderedElementsAre(qmlDirPathSourceId)), - Field(&SynchronizationPackage::projectDatas, - UnorderedElementsAre(IsProjectData(qmlDirPathSourceId, - qmlDocumentSourceId1, - exampleModuleId, - FileType::QmlDocument)))))); + EXPECT_CALL( + projectStorageMock, + synchronize(AllOf( + Field(&SynchronizationPackage::imports, UnorderedElementsAre(import1)), + Field(&SynchronizationPackage::types, + UnorderedElementsAre(AllOf( + IsStorageType("First.qml", + Storage::Synchronization::ImportedType{"Object"}, + TypeTraits::Reference, + qmlDocumentSourceId1, + Storage::Synchronization::ChangeLevel::Full), + Field(&Storage::Synchronization::Type::exportedTypes, + UnorderedElementsAre(IsExportedType(exampleModuleId, "FirstType", 1, 0), + IsExportedType(exampleModuleId, "FirstType", 1, 1), + IsExportedType(exampleModuleId, "FirstType", 6, 0), + IsExportedType(pathModuleId, "First", -1, -1)))))), + Field(&SynchronizationPackage::updatedSourceIds, + UnorderedElementsAre(qmlDirPathSourceId, qmlDocumentSourceId1)), + Field(&SynchronizationPackage::updatedFileStatusSourceIds, + UnorderedElementsAre(qmlDirPathSourceId, qmlDocumentSourceId1)), + Field(&SynchronizationPackage::fileStatuses, + UnorderedElementsAre(IsFileStatus(qmlDirPathSourceId, 21, 421), + IsFileStatus(qmlDocumentSourceId1, 22, 12))), + Field(&SynchronizationPackage::updatedProjectSourceIds, + UnorderedElementsAre(qmlDirPathSourceId)), + Field(&SynchronizationPackage::projectDatas, + UnorderedElementsAre(IsProjectData( + qmlDirPathSourceId, qmlDocumentSourceId1, ModuleId{}, FileType::QmlDocument)))))); - updater.update(qmlDirs, {}); + updater.update(directories, {}); } TEST_F(ProjectStorageUpdater, SynchronizeQmlDocumentsWithDifferentTypeNameButSameVersionAndFileName) @@ -954,38 +1188,38 @@ TEST_F(ProjectStorageUpdater, SynchronizeQmlDocumentsWithDifferentTypeNameButSam FirstType 1.0 First.qml FirstType2 1.0 First.qml)"}; ON_CALL(fileSystemMock, contentAsQString(Eq(QString("/path/qmldir")))).WillByDefault(Return(qmldir)); + ON_CALL(fileSystemMock, qmlFileNames(Eq(QString("/path")))) + .WillByDefault(Return(QStringList{"First.qml"})); - EXPECT_CALL(projectStorageMock, - synchronize( - AllOf(Field(&SynchronizationPackage::imports, UnorderedElementsAre(import1)), - Field(&SynchronizationPackage::types, - UnorderedElementsAre(AllOf( - IsStorageType("First.qml", - Storage::Synchronization::ImportedType{"Object"}, - TypeTraits::Reference, - qmlDocumentSourceId1, - Storage::Synchronization::ChangeLevel::Full), - Field(&Storage::Synchronization::Type::exportedTypes, - UnorderedElementsAre( - IsExportedType(exampleModuleId, "FirstType", 1, 0), - IsExportedType(exampleModuleId, "FirstType2", 1, 0), - IsExportedType(pathModuleId, "First", -1, -1)))))), - Field(&SynchronizationPackage::updatedSourceIds, - UnorderedElementsAre(qmlDirPathSourceId, qmlDocumentSourceId1)), - Field(&SynchronizationPackage::updatedFileStatusSourceIds, - UnorderedElementsAre(qmlDirPathSourceId, qmlDocumentSourceId1)), - Field(&SynchronizationPackage::fileStatuses, - UnorderedElementsAre(IsFileStatus(qmlDirPathSourceId, 21, 421), - IsFileStatus(qmlDocumentSourceId1, 22, 12))), - Field(&SynchronizationPackage::updatedProjectSourceIds, - UnorderedElementsAre(qmlDirPathSourceId)), - Field(&SynchronizationPackage::projectDatas, - UnorderedElementsAre(IsProjectData(qmlDirPathSourceId, - qmlDocumentSourceId1, - exampleModuleId, - FileType::QmlDocument)))))); + EXPECT_CALL( + projectStorageMock, + synchronize(AllOf( + Field(&SynchronizationPackage::imports, UnorderedElementsAre(import1)), + Field(&SynchronizationPackage::types, + UnorderedElementsAre(AllOf( + IsStorageType("First.qml", + Storage::Synchronization::ImportedType{"Object"}, + TypeTraits::Reference, + qmlDocumentSourceId1, + Storage::Synchronization::ChangeLevel::Full), + Field(&Storage::Synchronization::Type::exportedTypes, + UnorderedElementsAre(IsExportedType(exampleModuleId, "FirstType", 1, 0), + IsExportedType(exampleModuleId, "FirstType2", 1, 0), + IsExportedType(pathModuleId, "First", -1, -1)))))), + Field(&SynchronizationPackage::updatedSourceIds, + UnorderedElementsAre(qmlDirPathSourceId, qmlDocumentSourceId1)), + Field(&SynchronizationPackage::updatedFileStatusSourceIds, + UnorderedElementsAre(qmlDirPathSourceId, qmlDocumentSourceId1)), + Field(&SynchronizationPackage::fileStatuses, + UnorderedElementsAre(IsFileStatus(qmlDirPathSourceId, 21, 421), + IsFileStatus(qmlDocumentSourceId1, 22, 12))), + Field(&SynchronizationPackage::updatedProjectSourceIds, + UnorderedElementsAre(qmlDirPathSourceId)), + Field(&SynchronizationPackage::projectDatas, + UnorderedElementsAre(IsProjectData( + qmlDirPathSourceId, qmlDocumentSourceId1, ModuleId{}, FileType::QmlDocument)))))); - updater.update(qmlDirs, {}); + updater.update(directories, {}); } TEST_F(ProjectStorageUpdater, DontSynchronizeSelectors) @@ -995,70 +1229,18 @@ TEST_F(ProjectStorageUpdater, DontSynchronizeSelectors) ON_CALL(fileSystemMock, contentAsQString(Eq(QString("/path/qml/+First.qml")))) .WillByDefault(Return(qmlDocument1)); QString qmldir{R"(module Example - FirstType 1.0 +First.qml - FirstType2 1.0 qml/+First.qml)"}; + FirstType 1.0 +First.qml)"}; ON_CALL(fileSystemMock, contentAsQString(Eq(QString("/path/qmldir")))).WillByDefault(Return(qmldir)); + ON_CALL(fileSystemMock, qmlFileNames(Eq(QString("/path")))) + .WillByDefault(Return(QStringList{"First.qml"})); EXPECT_CALL(projectStorageMock, - synchronize( - AllOf(Field(&SynchronizationPackage::imports, IsEmpty()), - Field(&SynchronizationPackage::types, IsEmpty()), - Field(&SynchronizationPackage::updatedSourceIds, - UnorderedElementsAre(qmlDirPathSourceId)), - Field(&SynchronizationPackage::fileStatuses, - UnorderedElementsAre(IsFileStatus(qmlDirPathSourceId, 21, 421))), - Field(&SynchronizationPackage::updatedFileStatusSourceIds, - UnorderedElementsAre(qmlDirPathSourceId)), - Field(&SynchronizationPackage::projectDatas, IsEmpty()), - Field(&SynchronizationPackage::updatedProjectSourceIds, - UnorderedElementsAre(qmlDirPathSourceId))))); - - updater.update(qmlDirs, {}); -} - -TEST_F(ProjectStorageUpdater, SynchronizeQmlDocumentsWithRelativeFilePath) -{ - SourceId qmlDocumentSourceId = sourcePathCache.sourceId("/path/First.qml"); - ON_CALL(fileSystemMock, fileStatus(Eq(qmlDocumentSourceId))) - .WillByDefault(Return(FileStatus{qmlDocumentSourceId, 22, 12})); - ON_CALL(fileSystemMock, contentAsQString(Eq(QString("/path/First.qml")))) - .WillByDefault(Return(qmlDocument1)); - QString qmldir{R"(module Example - FirstType 1.0 First.qml - FirstType2 1.0 First.qml)"}; - ON_CALL(fileSystemMock, contentAsQString(Eq(QString("/path/qmldir")))).WillByDefault(Return(qmldir)); - - EXPECT_CALL(projectStorageMock, - synchronize( - AllOf(Field(&SynchronizationPackage::imports, UnorderedElementsAre(import1)), - Field(&SynchronizationPackage::types, - UnorderedElementsAre(AllOf( - IsStorageType("First.qml", - Storage::Synchronization::ImportedType{"Object"}, - TypeTraits::Reference, - qmlDocumentSourceId, - Storage::Synchronization::ChangeLevel::Full), - Field(&Storage::Synchronization::Type::exportedTypes, - UnorderedElementsAre( - IsExportedType(exampleModuleId, "FirstType", 1, 0), - IsExportedType(exampleModuleId, "FirstType2", 1, 0), - IsExportedType(pathModuleId, "First", -1, -1)))))), - Field(&SynchronizationPackage::updatedSourceIds, - UnorderedElementsAre(qmlDirPathSourceId, qmlDocumentSourceId)), - Field(&SynchronizationPackage::updatedFileStatusSourceIds, - UnorderedElementsAre(qmlDirPathSourceId, qmlDocumentSourceId)), - Field(&SynchronizationPackage::fileStatuses, - UnorderedElementsAre(IsFileStatus(qmlDirPathSourceId, 21, 421), - IsFileStatus(qmlDocumentSourceId, 22, 12))), - Field(&SynchronizationPackage::updatedProjectSourceIds, - UnorderedElementsAre(qmlDirPathSourceId)), - Field(&SynchronizationPackage::projectDatas, - UnorderedElementsAre(IsProjectData(qmlDirPathSourceId, - qmlDocumentSourceId, - exampleModuleId, - FileType::QmlDocument)))))); + synchronize(Not(Field( + &SynchronizationPackage::types, + Contains(Field(&Storage::Synchronization::Type::exportedTypes, + Contains(IsExportedType(exampleModuleId, "FirstType", 1, 0)))))))); - updater.update(qmlDirs, {}); + updater.update(directories, {}); } TEST_F(ProjectStorageUpdater, SynchronizeQmldirDependencies) @@ -1089,7 +1271,7 @@ TEST_F(ProjectStorageUpdater, SynchronizeQmldirDependencies) Field(&SynchronizationPackage::updatedModuleDependencySourceIds, UnorderedElementsAre(qmltypesPathSourceId, qmltypes2PathSourceId))))); - updater.update(qmlDirs, {}); + updater.update(directories, {}); } TEST_F(ProjectStorageUpdater, SynchronizeQmldirDependenciesWithDoubleEntries) @@ -1121,7 +1303,7 @@ TEST_F(ProjectStorageUpdater, SynchronizeQmldirDependenciesWithDoubleEntries) Field(&SynchronizationPackage::updatedModuleDependencySourceIds, UnorderedElementsAre(qmltypesPathSourceId, qmltypes2PathSourceId))))); - updater.update(qmlDirs, {}); + updater.update(directories, {}); } TEST_F(ProjectStorageUpdater, SynchronizeQmldirDependenciesWithCollidingImports) @@ -1153,7 +1335,7 @@ TEST_F(ProjectStorageUpdater, SynchronizeQmldirDependenciesWithCollidingImports) Field(&SynchronizationPackage::updatedModuleDependencySourceIds, UnorderedElementsAre(qmltypesPathSourceId, qmltypes2PathSourceId))))); - updater.update(qmlDirs, {}); + updater.update(directories, {}); } TEST_F(ProjectStorageUpdater, SynchronizeQmldirWithNoDependencies) @@ -1170,7 +1352,7 @@ TEST_F(ProjectStorageUpdater, SynchronizeQmldirWithNoDependencies) Field(&SynchronizationPackage::updatedModuleDependencySourceIds, UnorderedElementsAre(qmltypesPathSourceId, qmltypes2PathSourceId))))); - updater.update(qmlDirs, {}); + updater.update(directories, {}); } TEST_F(ProjectStorageUpdater, SynchronizeQmldirImports) @@ -1212,7 +1394,7 @@ TEST_F(ProjectStorageUpdater, SynchronizeQmldirImports) IsAutoVersion::No})), Field(&SynchronizationPackage::updatedModuleIds, ElementsAre(exampleModuleId))))); - updater.update(qmlDirs, {}); + updater.update(directories, {}); } TEST_F(ProjectStorageUpdater, SynchronizeQmldirWithNoImports) @@ -1226,7 +1408,7 @@ TEST_F(ProjectStorageUpdater, SynchronizeQmldirWithNoImports) Field(&SynchronizationPackage::updatedModuleIds, ElementsAre(exampleModuleId))))); - updater.update(qmlDirs, {}); + updater.update(directories, {}); } TEST_F(ProjectStorageUpdater, SynchronizeQmldirImportsWithDoubleEntries) @@ -1269,7 +1451,7 @@ TEST_F(ProjectStorageUpdater, SynchronizeQmldirImportsWithDoubleEntries) IsAutoVersion::No})), Field(&SynchronizationPackage::updatedModuleIds, ElementsAre(exampleModuleId))))); - updater.update(qmlDirs, {}); + updater.update(directories, {}); } TEST_F(ProjectStorageUpdater, SynchronizeQmldirOptionalImports) @@ -1311,7 +1493,7 @@ TEST_F(ProjectStorageUpdater, SynchronizeQmldirOptionalImports) IsAutoVersion::No})), Field(&SynchronizationPackage::updatedModuleIds, ElementsAre(exampleModuleId))))); - updater.update(qmlDirs, {}); + updater.update(directories, {}); } } // namespace |