From 87b5176fd23b749d13fef81e65db09939b446e4f Mon Sep 17 00:00:00 2001 From: Eike Ziller Date: Thu, 9 Mar 2023 11:30:31 +0100 Subject: [PATCH] Add test for examples parsing Change-Id: Id2ec8afcdbdff97e12b32b836c955552589081c4 Reviewed-by: Eike Ziller Reviewed-by: Christian Stenger Reviewed-by: --- src/plugins/qtsupport/examplesparser.cpp | 14 +- src/plugins/qtsupport/examplesparser.h | 21 ++- tests/auto/CMakeLists.txt | 1 + tests/auto/auto.qbs | 1 + tests/auto/examples/CMakeLists.txt | 5 + tests/auto/examples/examples.qbs | 9 ++ tests/auto/examples/tst_examples.cpp | 156 +++++++++++++++++++++++ 7 files changed, 198 insertions(+), 9 deletions(-) create mode 100644 tests/auto/examples/CMakeLists.txt create mode 100644 tests/auto/examples/examples.qbs create mode 100644 tests/auto/examples/tst_examples.cpp diff --git a/src/plugins/qtsupport/examplesparser.cpp b/src/plugins/qtsupport/examplesparser.cpp index 1d7211b6367..de6a14d8369 100644 --- a/src/plugins/qtsupport/examplesparser.cpp +++ b/src/plugins/qtsupport/examplesparser.cpp @@ -229,10 +229,18 @@ expected_str> parseExamples(const FilePath &manifest, if (!contents) return make_unexpected(contents.error()); - const FilePath path = manifest.parentDir(); + return parseExamples(*contents, manifest, examplesInstallPath, demosInstallPath, examples); +} +expected_str> parseExamples(const QByteArray &manifestData, + const Utils::FilePath &manifestPath, + const FilePath &examplesInstallPath, + const FilePath &demosInstallPath, + const bool examples) +{ + const FilePath path = manifestPath.parentDir(); QList items; - QXmlStreamReader reader(*contents); + QXmlStreamReader reader(manifestData); while (!reader.atEnd()) { switch (reader.readNext()) { case QXmlStreamReader::StartElement: @@ -251,7 +259,7 @@ expected_str> parseExamples(const FilePath &manifest, if (reader.hasError()) { qDeleteAll(items); return make_unexpected(QString("Could not parse file \"%1\" as XML document: %2:%3: %4") - .arg(manifest.toUserOutput()) + .arg(manifestPath.toUserOutput()) .arg(reader.lineNumber()) .arg(reader.columnNumber()) .arg(reader.errorString())); diff --git a/src/plugins/qtsupport/examplesparser.h b/src/plugins/qtsupport/examplesparser.h index 494a42b1473..b133d2c6c8a 100644 --- a/src/plugins/qtsupport/examplesparser.h +++ b/src/plugins/qtsupport/examplesparser.h @@ -3,6 +3,8 @@ #pragma once +#include "qtsupport_global.h" + #include #include #include @@ -11,7 +13,7 @@ namespace QtSupport::Internal { enum InstructionalType { Example = 0, Demo, Tutorial }; -class ExampleItem : public Core::ListItem +class QTSUPPORT_EXPORT ExampleItem : public Core::ListItem { public: Utils::FilePath projectPath; @@ -20,7 +22,6 @@ public: Utils::FilePath mainFile; /* file to be visible after opening filesToOpen */ Utils::FilePaths dependencies; InstructionalType type; - int difficulty = 0; bool hasSourceCode = false; bool isVideo = false; bool isHighlighted = false; @@ -29,10 +30,18 @@ public: QStringList platforms; }; -Utils::expected_str> parseExamples(const Utils::FilePath &manifest, - const Utils::FilePath &examplesInstallPath, - const Utils::FilePath &demosInstallPath, - bool examples); +QTSUPPORT_EXPORT Utils::expected_str> parseExamples( + const Utils::FilePath &manifest, + const Utils::FilePath &examplesInstallPath, + const Utils::FilePath &demosInstallPath, + bool examples); + +QTSUPPORT_EXPORT Utils::expected_str> parseExamples( + const QByteArray &manifestData, + const Utils::FilePath &manifestPath, + const Utils::FilePath &examplesInstallPath, + const Utils::FilePath &demosInstallPath, + bool examples); } // namespace QtSupport::Internal diff --git a/tests/auto/CMakeLists.txt b/tests/auto/CMakeLists.txt index c71cbafdb2d..98ee3458965 100644 --- a/tests/auto/CMakeLists.txt +++ b/tests/auto/CMakeLists.txt @@ -6,6 +6,7 @@ add_subdirectory(cplusplus) add_subdirectory(debugger) add_subdirectory(diff) add_subdirectory(environment) +add_subdirectory(examples) add_subdirectory(extensionsystem) add_subdirectory(externaltool) add_subdirectory(filesearch) diff --git a/tests/auto/auto.qbs b/tests/auto/auto.qbs index af173fa9f09..2ff98d14097 100644 --- a/tests/auto/auto.qbs +++ b/tests/auto/auto.qbs @@ -12,6 +12,7 @@ Project { "debugger/debugger.qbs", "diff/diff.qbs", "environment/environment.qbs", + "examples/examples.qbs", "extensionsystem/extensionsystem.qbs", "externaltool/externaltool.qbs", "filesearch/filesearch.qbs", diff --git a/tests/auto/examples/CMakeLists.txt b/tests/auto/examples/CMakeLists.txt new file mode 100644 index 00000000000..cf8d1e4191e --- /dev/null +++ b/tests/auto/examples/CMakeLists.txt @@ -0,0 +1,5 @@ +add_qtc_test(tst_examples + DEPENDS Utils Core QtSupport + SOURCES tst_examples.cpp +) + diff --git a/tests/auto/examples/examples.qbs b/tests/auto/examples/examples.qbs new file mode 100644 index 00000000000..39cacc395fa --- /dev/null +++ b/tests/auto/examples/examples.qbs @@ -0,0 +1,9 @@ +import qbs + +QtcAutotest { + name: "Examples autotest" + Depends { name: "Core" } + Depends { name: "QtSupport" } + Depends { name: "Utils" } + files: "tst_examples.cpp" +} diff --git a/tests/auto/examples/tst_examples.cpp b/tests/auto/examples/tst_examples.cpp new file mode 100644 index 00000000000..22236ed4c5d --- /dev/null +++ b/tests/auto/examples/tst_examples.cpp @@ -0,0 +1,156 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 + +#include +#include + +#include + +using namespace Utils; +using namespace QtSupport::Internal; + +class tst_Examples : public QObject +{ + Q_OBJECT + +public: + tst_Examples(); + ~tst_Examples(); + +private slots: + void parsing_data(); + void parsing(); +}; + +tst_Examples::tst_Examples() = default; +tst_Examples::~tst_Examples() = default; + +static ExampleItem fetchItem() +{ + QFETCH(QString, name); + QFETCH(QString, description); + QFETCH(QString, imageUrl); + QFETCH(QStringList, tags); + QFETCH(FilePath, projectPath); + QFETCH(QString, docUrl); + QFETCH(FilePaths, filesToOpen); + QFETCH(FilePath, mainFile); + QFETCH(FilePaths, dependencies); + QFETCH(InstructionalType, type); + QFETCH(bool, hasSourceCode); + QFETCH(bool, isVideo); + QFETCH(bool, isHighlighted); + QFETCH(QString, videoUrl); + QFETCH(QString, videoLength); + QFETCH(QStringList, platforms); + ExampleItem item; + item.name = name; + item.description = description; + item.imageUrl = imageUrl; + item.tags = tags; + item.projectPath = projectPath; + item.docUrl = docUrl; + item.filesToOpen = filesToOpen; + item.mainFile = mainFile; + item.dependencies = dependencies; + item.type = type; + item.hasSourceCode = hasSourceCode; + item.isVideo = isVideo; + item.isHighlighted = isHighlighted; + item.videoUrl = videoUrl; + item.videoLength = videoLength; + item.platforms = platforms; + return item; +} + +void tst_Examples::parsing_data() +{ + QTest::addColumn("data"); + QTest::addColumn("isExamples"); + QTest::addColumn("name"); + QTest::addColumn("description"); + QTest::addColumn("imageUrl"); + QTest::addColumn("tags"); + QTest::addColumn("projectPath"); + QTest::addColumn("docUrl"); + QTest::addColumn("filesToOpen"); + QTest::addColumn("mainFile"); + QTest::addColumn("dependencies"); + QTest::addColumn("type"); + QTest::addColumn("hasSourceCode"); + QTest::addColumn("isVideo"); + QTest::addColumn("isHighlighted"); + QTest::addColumn("videoUrl"); + QTest::addColumn("videoLength"); + QTest::addColumn("platforms"); + + QTest::addRow("example") + << QByteArray(R"raw( + + + + ios,widgets + widgets/widgets/analogclock/main.cpp + widgets/widgets/analogclock/analogclock.h + widgets/widgets/analogclock/analogclock.cpp + + Graphics + widgets + + + + )raw") << /*isExamples=*/true + << "Analog Clock" + << "The Analog Clock example shows how to draw the contents of a custom widget." + << "qthelp://org.qt-project.qtwidgets.660/qtwidgets/images/analogclock-example.png" + << QStringList{"ios", "widgets"} + << FilePath::fromUserInput("manifest/widgets/widgets/analogclock/CMakeLists.txt") + << "qthelp://org.qt-project.qtwidgets.660/qtwidgets/" + "qtwidgets-widgets-analogclock-example.html" + << FilePaths{FilePath::fromUserInput("manifest/widgets/widgets/analogclock/main.cpp"), + FilePath::fromUserInput("manifest/widgets/widgets/analogclock/analogclock.h"), + FilePath::fromUserInput( + "manifest/widgets/widgets/analogclock/analogclock.cpp")} + << FilePath::fromUserInput("manifest/widgets/widgets/analogclock/analogclock.cpp") + << FilePaths() << Example << true << false << false << "" + << "" << QStringList(); +} + +void tst_Examples::parsing() +{ + QFETCH(QByteArray, data); + QFETCH(bool, isExamples); + const ExampleItem expected = fetchItem(); + const expected_str> result + = parseExamples(data, + FilePath("manifest/examples-manifest.xml"), + FilePath("examples"), + FilePath("demos"), + isExamples); + QVERIFY(result); + QCOMPARE(result->size(), 1); + const ExampleItem item = *result->at(0); + QCOMPARE(item.name, expected.name); + QCOMPARE(item.description, expected.description); + QCOMPARE(item.imageUrl, expected.imageUrl); + QCOMPARE(item.tags, expected.tags); + QCOMPARE(item.projectPath, expected.projectPath); + QCOMPARE(item.docUrl, expected.docUrl); + QCOMPARE(item.filesToOpen, expected.filesToOpen); + QCOMPARE(item.mainFile, expected.mainFile); + QCOMPARE(item.dependencies, expected.dependencies); + QCOMPARE(item.type, expected.type); + QCOMPARE(item.hasSourceCode, expected.hasSourceCode); + QCOMPARE(item.isVideo, expected.isVideo); + QCOMPARE(item.isHighlighted, expected.isHighlighted); + QCOMPARE(item.videoUrl, expected.videoUrl); + QCOMPARE(item.videoLength, expected.videoLength); + QCOMPARE(item.platforms, expected.platforms); + qDeleteAll(*result); +} + +QTEST_APPLESS_MAIN(tst_Examples) + +#include "tst_examples.moc"