diff options
Diffstat (limited to 'sources/shiboken6/ApiExtractor/tests/testdroptypeentries.cpp')
-rw-r--r-- | sources/shiboken6/ApiExtractor/tests/testdroptypeentries.cpp | 228 |
1 files changed, 228 insertions, 0 deletions
diff --git a/sources/shiboken6/ApiExtractor/tests/testdroptypeentries.cpp b/sources/shiboken6/ApiExtractor/tests/testdroptypeentries.cpp new file mode 100644 index 000000000..16f50e69d --- /dev/null +++ b/sources/shiboken6/ApiExtractor/tests/testdroptypeentries.cpp @@ -0,0 +1,228 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 + +#include "testdroptypeentries.h" +#include "testutil.h" +#include <abstractmetaenum.h> +#include <abstractmetalang.h> +#include <typesystem.h> +#include <conditionalstreamreader.h> + +#include <qtcompat.h> + +#include <QtTest/QTest> + +using namespace Qt::StringLiterals; + +static const char cppCode[] = "\ + struct ValueA {};\n\ + struct ValueB {};\n\ + struct ObjectA {};\n\ + struct ObjectB {};\n\ + namespace NamespaceA {\n\ + struct InnerClassA {};\n\ + namespace InnerNamespaceA {}\n\ + }\n\ + namespace NamespaceB {}\n\ + enum EnumA { Value0 };\n\ + enum EnumB { Value1 };\n\ + void funcA();\n\ + void funcB();\n"; + +static const char xmlCode[] = "\ +<typesystem package='Foo'>\n\ + <value-type name='ValueA'/>\n\ + <value-type name='ValueB'/>\n\ + <object-type name='ObjectA'/>\n\ + <object-type name='ObjectB'/>\n\ + <namespace-type name='NamespaceA'>\n\ + <value-type name='InnerClassA'/>\n\ + <namespace-type name='InnerNamespaceA'/>\n\ + </namespace-type>\n\ + <namespace-type name='NamespaceB'/>\n\ + <enum-type name='EnumA'/>\n\ + <enum-type name='EnumB'/>\n\ + <function signature='funcA()'/>\n\ + <function signature='funcB()'/>\n\ +</typesystem>\n"; + +void TestDropTypeEntries::testDropEntries() +{ + const QStringList droppedEntries{u"Foo.ValueB"_s, + u"ObjectB"_s, // Check whether module can be omitted + u"Foo.NamespaceA.InnerClassA"_s, + u"Foo.NamespaceB"_s, u"Foo.EnumB"_s, + u"Foo.funcB()"_s, + u"Foo.NamespaceA.InnerNamespaceA"_s}; + QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, false, + QString(), droppedEntries)); + QVERIFY(builder); + + AbstractMetaClassList classes = builder->classes(); + QVERIFY(AbstractMetaClass::findClass(classes, "ValueA")); + QVERIFY(!AbstractMetaClass::findClass(classes, "ValueB")); + QVERIFY(AbstractMetaClass::findClass(classes, "ObjectA")); + QVERIFY(!AbstractMetaClass::findClass(classes, "ObjectB")); + QVERIFY(AbstractMetaClass::findClass(classes, "NamespaceA")); + QVERIFY(!AbstractMetaClass::findClass(classes, "NamespaceA::InnerClassA")); + QVERIFY(!AbstractMetaClass::findClass(classes, "NamespaceB")); + + AbstractMetaEnumList globalEnums = builder->globalEnums(); + QCOMPARE(globalEnums.size(), 1); + QCOMPARE(globalEnums.constFirst().name(), u"EnumA"); + + auto *td = TypeDatabase::instance(); + QVERIFY(td->findType(u"funcA"_s)); + QVERIFY(!td->findType(u"funcB"_s)); +} + +void TestDropTypeEntries::testDontDropEntries() +{ + QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, false)); + QVERIFY(builder); + + AbstractMetaClassList classes = builder->classes(); + QVERIFY(AbstractMetaClass::findClass(classes, "ValueA")); + QVERIFY(AbstractMetaClass::findClass(classes, "ValueB")); + QVERIFY(AbstractMetaClass::findClass(classes, "ObjectA")); + QVERIFY(AbstractMetaClass::findClass(classes, "ObjectB")); + QVERIFY(AbstractMetaClass::findClass(classes, "NamespaceA")); + QVERIFY(AbstractMetaClass::findClass(classes, "NamespaceA::InnerClassA")); + QVERIFY(AbstractMetaClass::findClass(classes, "NamespaceB")); + + QCOMPARE(builder->globalEnums().size(), 2); + + auto *td = TypeDatabase::instance(); + QVERIFY(td->findType(u"funcA"_s)); + QVERIFY(td->findType(u"funcB"_s)); +} + +static const char cppCode2[] = "\ + struct ValueA {\n\ + void func();\n\ + };\n"; + +static const char xmlCode2[] = R"( +<typesystem package='Foo'> + <value-type name='ValueA'> + <modify-function signature='func()' remove='all'/> + </value-type> +</typesystem> +)"; + +void TestDropTypeEntries::testDropEntryWithChildTags() +{ + QStringList droppedEntries(u"Foo.ValueA"_s); + QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode2, xmlCode2, false, + QString(), droppedEntries)); + QVERIFY(builder); + QVERIFY(!AbstractMetaClass::findClass(builder->classes(), "ValueA")); +} + + +void TestDropTypeEntries::testDontDropEntryWithChildTags() +{ + QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode2, xmlCode2, false)); + QVERIFY(builder); + QVERIFY(AbstractMetaClass::findClass(builder->classes(), "ValueA")); +} + +void TestDropTypeEntries::testConditionalParsing_data() +{ + const QString xml = R"(<?xml version="1.0" encoding="UTF-8"?> +<root> + <tag1>text</tag1> + <?if keyword1?> + <tag2>text</tag2> + <?if keyword2?> + <tag3>text</tag3> + <?endif?> + <?if keyword1 !keyword2?> + <tag4>text</tag4> + <?endif?> + <?endif?> + <tag5>text</tag5> + <?if !keyword99?> <!-- Exclusion only --> + <tag6>text</tag6> + <?endif?> +</root>)"_L1; + + constexpr auto root = "root"_L1; + constexpr auto tag1 = "tag1"_L1; + constexpr auto tag2 = "tag2"_L1; + constexpr auto tag3 = "tag3"_L1; + constexpr auto tag4 = "tag4"_L1; + constexpr auto tag5 = "tag5"_L1; + constexpr auto tag6 = "tag6"_L1; + constexpr auto keyword1 = "keyword1"_L1; + constexpr auto keyword2 = "keyword2"_L1; + + QTest::addColumn<QString>("xml"); + QTest::addColumn<QStringList>("keywords"); + QTest::addColumn<QStringList>("expectedTags"); + + QTest::newRow("no-keywords") + << xml << QStringList{} << QStringList{root, tag1, tag5, tag6}; + + QTest::newRow("skip-nested-condition") + << xml << QStringList{keyword1} + << QStringList{root, tag1, tag2, tag4, tag5, tag6}; + + QTest::newRow("both/check-not") + << xml << QStringList{keyword1, keyword2} + << QStringList{root, tag1, tag2, tag3, tag5, tag6}; +} + +// Parse XML and return a list of tags encountered +static QStringList parseXml(const QString &xml, const QStringList &keywords) +{ + QStringList tags; + ConditionalStreamReader reader(xml); + reader.setConditions(keywords); + while (!reader.atEnd()) { + auto t = reader.readNext(); + switch (t) { + case QXmlStreamReader::StartElement: + tags.append(reader.name().toString()); + break; + default: + break; + } + } + return tags; +} + +void TestDropTypeEntries::testConditionalParsing() +{ + QFETCH(QString, xml); + QFETCH(QStringList, keywords); + QFETCH(QStringList, expectedTags); + + const QStringList actualTags = parseXml(xml, keywords); + QCOMPARE(actualTags, expectedTags); +} + +void TestDropTypeEntries::testEntityParsing() +{ + const QString xml = R"(<?xml version="1.0" encoding="UTF-8"?> +<root> + <?entity testentity word1 word2?> + <text>bla &testentity;</text> +</root>)"_L1; + + QString actual; + ConditionalStreamReader reader(xml); + while (!reader.atEnd()) { + auto t = reader.readNext(); + switch (t) { + case QXmlStreamReader::Characters: + actual.append(reader.text()); + default: + break; + } + } + QVERIFY2(!reader.hasError(), qPrintable(reader.errorString())); + QCOMPARE(actual.trimmed(), u"bla word1 word2"); +} + +QTEST_APPLESS_MAIN(TestDropTypeEntries) |