diff options
Diffstat (limited to 'sources/shiboken2/ApiExtractor/tests')
20 files changed, 381 insertions, 40 deletions
diff --git a/sources/shiboken2/ApiExtractor/tests/CMakeLists.txt b/sources/shiboken2/ApiExtractor/tests/CMakeLists.txt index 860a37d9d..e100ef493 100644 --- a/sources/shiboken2/ApiExtractor/tests/CMakeLists.txt +++ b/sources/shiboken2/ApiExtractor/tests/CMakeLists.txt @@ -4,13 +4,18 @@ find_package(Qt5Test) find_package(Qt5Xml) find_package(Qt5XmlPatterns) +set(CMAKE_AUTORCC ON) + macro(declare_test testname) # gone: qt4_automoc("${testname}.cpp") - if (EXISTS "${testname}.h") - add_executable(${testname} "${testname}.h ${testname}.cpp") - else () - add_executable(${testname} "${testname}.cpp") + set(SOURCES "${testname}.cpp") + if (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/${testname}.h") + list(APPEND SOURCES "${testname}.h") + endif () + if (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/${testname}.qrc") + list(APPEND SOURCES "${testname}.qrc") endif () + add_executable(${testname} ${SOURCES}) include_directories(${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR} ${apiextractor_SOURCE_DIR} @@ -35,8 +40,6 @@ declare_test(testabstractmetatype) declare_test(testaddfunction) declare_test(testarrayargument) declare_test(testcodeinjection) -configure_file("${CMAKE_CURRENT_SOURCE_DIR}/utf8code.txt" - "${CMAKE_CURRENT_BINARY_DIR}/utf8code.txt" COPYONLY) declare_test(testcontainer) declare_test(testconversionoperator) declare_test(testconversionruletag) @@ -68,7 +71,5 @@ declare_test(testvoidarg) declare_test(testtyperevision) if (NOT DISABLE_DOCSTRINGS) declare_test(testmodifydocumentation) - configure_file("${CMAKE_CURRENT_SOURCE_DIR}/a.xml" - "${CMAKE_CURRENT_BINARY_DIR}/a.xml" COPYONLY) endif() diff --git a/sources/shiboken2/ApiExtractor/tests/injectedcode.txt b/sources/shiboken2/ApiExtractor/tests/injectedcode.txt new file mode 100644 index 000000000..872898810 --- /dev/null +++ b/sources/shiboken2/ApiExtractor/tests/injectedcode.txt @@ -0,0 +1,5 @@ +// Bla +// @snippet label +code line +// @snippet label +// Bla diff --git a/sources/shiboken2/ApiExtractor/tests/testabstractmetatype.cpp b/sources/shiboken2/ApiExtractor/tests/testabstractmetatype.cpp index 7f1361a7d..fc67ebba5 100644 --- a/sources/shiboken2/ApiExtractor/tests/testabstractmetatype.cpp +++ b/sources/shiboken2/ApiExtractor/tests/testabstractmetatype.cpp @@ -31,6 +31,37 @@ #include "testutil.h" #include <abstractmetalang.h> #include <typesystem.h> +#include <parser/codemodel.h> +#include <typeparser.h> + +void TestAbstractMetaType::parsing_data() +{ + QTest::addColumn<QString>("input"); + QTest::addColumn<QString>("output"); + QTest::newRow("primitive") + << QString::fromLatin1("int") << QString::fromLatin1("int"); + QTest::newRow("ref") + << QString::fromLatin1("int &") << QString::fromLatin1("int&"); + QTest::newRow("pointer") + << QString::fromLatin1("int **") << QString::fromLatin1("int**"); + QTest::newRow("const ref") + << QString::fromLatin1("const int &") << QString::fromLatin1("const int&"); + QTest::newRow("const pointer") + << QString::fromLatin1("const int **") << QString::fromLatin1("const int**"); + QTest::newRow("const pointer const") + << QString::fromLatin1("const int *const*") << QString::fromLatin1("const int*const*"); +} + +void TestAbstractMetaType::parsing() +{ + QFETCH(QString, input); + QFETCH(QString, output); + QString errorMessage; + const TypeInfo ti = TypeParser::parse(input, &errorMessage); + QVERIFY2(errorMessage.isEmpty(), qPrintable(errorMessage)); + const QString actual = ti.toString(); + QCOMPARE(actual, output); +} void TestAbstractMetaType::testConstCharPtrType() { @@ -72,7 +103,8 @@ void TestAbstractMetaType::testApiVersionSupported() <function signature='justAtest2()' since='1.1'/>\n\ <function signature='justAtest3()'/>\n\ </typesystem>\n"; - QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, false, "1.0")); + QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, + false, QLatin1String("1.0"))); QVERIFY(!builder.isNull()); AbstractMetaClassList classes = builder->classes(); @@ -90,7 +122,8 @@ void TestAbstractMetaType::testApiVersionNotSupported() const char* xmlCode = "<typesystem package='Foo'>\n\ <value-type name='object' since='0.1'/>\n\ </typesystem>\n"; - QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, true, "0.1")); + QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, + true, QLatin1String("0.1"))); QVERIFY(!builder.isNull()); AbstractMetaClassList classes = builder->classes(); diff --git a/sources/shiboken2/ApiExtractor/tests/testabstractmetatype.h b/sources/shiboken2/ApiExtractor/tests/testabstractmetatype.h index b2aa7544f..b39a27a54 100644 --- a/sources/shiboken2/ApiExtractor/tests/testabstractmetatype.h +++ b/sources/shiboken2/ApiExtractor/tests/testabstractmetatype.h @@ -35,6 +35,8 @@ class TestAbstractMetaType : public QObject { Q_OBJECT private slots: + void parsing_data(); + void parsing(); void testConstCharPtrType(); void testCharType(); void testTypedef(); diff --git a/sources/shiboken2/ApiExtractor/tests/testaddfunction.cpp b/sources/shiboken2/ApiExtractor/tests/testaddfunction.cpp index 2a953243e..db49942c9 100644 --- a/sources/shiboken2/ApiExtractor/tests/testaddfunction.cpp +++ b/sources/shiboken2/ApiExtractor/tests/testaddfunction.cpp @@ -366,7 +366,8 @@ void TestAddFunction::testAddFunctionWithApiVersion() <inject-code class='target' position='beginning'>custom_code();</inject-code>\n\ </add-function>\n\ </typesystem>\n"; - QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, true, "0.1")); + QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, + true, QLatin1String("0.1"))); QVERIFY(!builder.isNull()); AbstractMetaFunctionList globalFuncs = builder->globalFunctions(); QCOMPARE(globalFuncs.count(), 1); diff --git a/sources/shiboken2/ApiExtractor/tests/testcodeinjection.cpp b/sources/shiboken2/ApiExtractor/tests/testcodeinjection.cpp index 7bbde3bd4..9f71b495a 100644 --- a/sources/shiboken2/ApiExtractor/tests/testcodeinjection.cpp +++ b/sources/shiboken2/ApiExtractor/tests/testcodeinjection.cpp @@ -34,19 +34,43 @@ #include <abstractmetalang.h> #include <typesystem.h> -void TestCodeInjections::testReadFileUtf8() +void TestCodeInjections::testReadFile_data() { + QTest::addColumn<QString>("filePath"); + QTest::addColumn<QString>("snippet"); + QTest::addColumn<QString>("expected"); + + QTest::newRow("utf8") + << QString::fromLatin1(":/utf8code.txt") + << QString() + << QString::fromUtf8("\xC3\xA1\xC3\xA9\xC3\xAD\xC3\xB3\xC3\xBA"); + + QTest::newRow("snippet") + << QString::fromLatin1(":/injectedcode.txt") + << QString::fromLatin1("label") + << QString::fromLatin1("code line"); +} + +void TestCodeInjections::testReadFile() +{ + QFETCH(QString, filePath); + QFETCH(QString, snippet); + QFETCH(QString, expected); + const char* cppCode ="struct A {};\n"; int argc = 0; char *argv[] = {NULL}; QCoreApplication app(argc, argv); - QString filePath = QDir::currentPath(); + + QString attribute = QLatin1String("file='") + filePath + QLatin1Char('\''); + if (!snippet.isEmpty()) + attribute += QLatin1String(" snippet='") + snippet + QLatin1Char('\''); + QString xmlCode = QLatin1String("\ <typesystem package=\"Foo\">\n\ <value-type name='A'>\n\ - <conversion-rule file='") + filePath + QLatin1String("/utf8code.txt'/>\n\ - <inject-code class='target' file='") + filePath - + QLatin1String("/utf8code.txt'/>\n\ + <conversion-rule ") + attribute + QLatin1String("/>\n\ + <inject-code class='target' ") + attribute + QLatin1String("/>\n\ </value-type>\n\ <value-type name='A::B'/>\n\ </typesystem>\n"); @@ -56,10 +80,9 @@ void TestCodeInjections::testReadFileUtf8() const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, QLatin1String("A")); QCOMPARE(classA->typeEntry()->codeSnips().count(), 1); QString code = classA->typeEntry()->codeSnips().first().code(); - QString utf8Data = QString::fromUtf8("\xC3\xA1\xC3\xA9\xC3\xAD\xC3\xB3\xC3\xBA"); - QVERIFY(code.indexOf(utf8Data) != -1); + QVERIFY(code.indexOf(expected) != -1); code = classA->typeEntry()->conversionRule(); - QVERIFY(code.indexOf(utf8Data) != -1); + QVERIFY(code.indexOf(expected) != -1); } void TestCodeInjections::testInjectWithValidApiVersion() @@ -74,7 +97,8 @@ void TestCodeInjections::testInjectWithValidApiVersion() </value-type>\n\ </typesystem>\n"; - QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, true, "1.0")); + QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, + true, QLatin1String("1.0"))); QVERIFY(!builder.isNull()); AbstractMetaClassList classes = builder->classes(); AbstractMetaClass* classA = AbstractMetaClass::findClass(classes, QLatin1String("A")); @@ -93,7 +117,8 @@ void TestCodeInjections::testInjectWithInvalidApiVersion() </value-type>\n\ </typesystem>\n"; - QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, true, "0.1")); + QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, + true, QLatin1String("0.1"))); QVERIFY(!builder.isNull()); AbstractMetaClassList classes = builder->classes(); diff --git a/sources/shiboken2/ApiExtractor/tests/testcodeinjection.h b/sources/shiboken2/ApiExtractor/tests/testcodeinjection.h index bd5e7ece1..1ac873970 100644 --- a/sources/shiboken2/ApiExtractor/tests/testcodeinjection.h +++ b/sources/shiboken2/ApiExtractor/tests/testcodeinjection.h @@ -37,7 +37,8 @@ class TestCodeInjections : public QObject { Q_OBJECT private slots: - void testReadFileUtf8(); + void testReadFile_data(); + void testReadFile(); void testInjectWithValidApiVersion(); void testInjectWithInvalidApiVersion(); }; diff --git a/sources/shiboken2/ApiExtractor/tests/testcodeinjection.qrc b/sources/shiboken2/ApiExtractor/tests/testcodeinjection.qrc new file mode 100644 index 000000000..fd7616bd2 --- /dev/null +++ b/sources/shiboken2/ApiExtractor/tests/testcodeinjection.qrc @@ -0,0 +1,6 @@ +<RCC> + <qresource> + <file>utf8code.txt</file> + <file>injectedcode.txt</file> + </qresource> +</RCC> diff --git a/sources/shiboken2/ApiExtractor/tests/testdroptypeentries.cpp b/sources/shiboken2/ApiExtractor/tests/testdroptypeentries.cpp index b46c23f56..6abebb922 100644 --- a/sources/shiboken2/ApiExtractor/tests/testdroptypeentries.cpp +++ b/sources/shiboken2/ApiExtractor/tests/testdroptypeentries.cpp @@ -70,7 +70,8 @@ void TestDropTypeEntries::testDropEntries() droppedEntries << QLatin1String("Foo.ObjectB") << QLatin1String("Foo.NamespaceA.InnerClassA"); droppedEntries << QLatin1String("Foo.NamespaceB") << QLatin1String("Foo.EnumB") << QLatin1String("Foo.funcB()"); droppedEntries << QLatin1String("Foo.NamespaceA.InnerNamespaceA"); - QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, false, Q_NULLPTR, droppedEntries)); + QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, false, + QString(), droppedEntries)); QVERIFY(!builder.isNull()); AbstractMetaClassList classes = builder->classes(); @@ -129,7 +130,8 @@ static const char* xmlCode2 = "\ void TestDropTypeEntries::testDropEntryWithChildTags() { QStringList droppedEntries(QLatin1String("Foo.ValueA")); - QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode2, xmlCode2, false, Q_NULLPTR, droppedEntries)); + QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode2, xmlCode2, false, + QString(), droppedEntries)); QVERIFY(!builder.isNull()); QVERIFY(!AbstractMetaClass::findClass(builder->classes(), QLatin1String("ValueA"))); } diff --git a/sources/shiboken2/ApiExtractor/tests/testenum.cpp b/sources/shiboken2/ApiExtractor/tests/testenum.cpp index 87f2608a1..ebdcf8d81 100644 --- a/sources/shiboken2/ApiExtractor/tests/testenum.cpp +++ b/sources/shiboken2/ApiExtractor/tests/testenum.cpp @@ -104,7 +104,8 @@ void TestEnum::testEnumWithApiVersion() </value-type>\n\ </typesystem>\n"; - QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, true, "0.1")); + QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, + true, QLatin1String("0.1"))); QVERIFY(!builder.isNull()); AbstractMetaClassList classes = builder->classes(); QCOMPARE(classes.count(), 1); diff --git a/sources/shiboken2/ApiExtractor/tests/testmodifydocumentation.cpp b/sources/shiboken2/ApiExtractor/tests/testmodifydocumentation.cpp index 7911a5eb1..f615befb4 100644 --- a/sources/shiboken2/ApiExtractor/tests/testmodifydocumentation.cpp +++ b/sources/shiboken2/ApiExtractor/tests/testmodifydocumentation.cpp @@ -60,7 +60,7 @@ R"(<typesystem package="Foo"> QCOMPARE(docMods[1].code().trimmed(), QLatin1String("<para>Some changed contents here</para>")); QCOMPARE(docMods[1].signature(), QString()); QtDocParser docParser; - docParser.setDocumentationDataDirectory(QDir::currentPath()); + docParser.setDocumentationDataDirectory(QLatin1String(":")); docParser.fillDocumentation(classA); const QString actualDocSimplified = classA->documentation().value().simplified(); diff --git a/sources/shiboken2/ApiExtractor/tests/testmodifydocumentation.qrc b/sources/shiboken2/ApiExtractor/tests/testmodifydocumentation.qrc new file mode 100644 index 000000000..76b1bfc61 --- /dev/null +++ b/sources/shiboken2/ApiExtractor/tests/testmodifydocumentation.qrc @@ -0,0 +1,5 @@ +<RCC> + <qresource> + <file>a.xml</file> + </qresource> +</RCC> diff --git a/sources/shiboken2/ApiExtractor/tests/testmodifyfunction.cpp b/sources/shiboken2/ApiExtractor/tests/testmodifyfunction.cpp index d0a0c9c7a..af24689fe 100644 --- a/sources/shiboken2/ApiExtractor/tests/testmodifyfunction.cpp +++ b/sources/shiboken2/ApiExtractor/tests/testmodifyfunction.cpp @@ -136,7 +136,8 @@ void TestModifyFunction::invalidateAfterUse() </object-type>\n\ <object-type name='E' />\n\ </typesystem>\n"; - QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, false, "0.1")); + QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, + false, QLatin1String("0.1"))); QVERIFY(!builder.isNull()); AbstractMetaClassList classes = builder->classes(); const AbstractMetaClass *classB = AbstractMetaClass::findClass(classes, QLatin1String("B")); @@ -208,7 +209,8 @@ void TestModifyFunction::testWithApiVersion() </modify-function>\n\ </object-type>\n\ </typesystem>\n"; - QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, false, "0.1")); + QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, + false, QLatin1String("0.1"))); QVERIFY(!builder.isNull()); AbstractMetaClassList classes = builder->classes(); AbstractMetaClass* classB = AbstractMetaClass::findClass(classes, QLatin1String("B")); @@ -220,6 +222,61 @@ void TestModifyFunction::testWithApiVersion() QVERIFY(func->ownership(func->ownerClass(), TypeSystem::TargetLangCode, 0) != TypeSystem::CppOwnership); } +void TestModifyFunction::testAllowThread() +{ + const char cppCode[] =R"CPP(\ +struct A { + void f1(); + void f2(); + void f3(); + int getter1() const; + int getter2() const; +}; +)CPP"; + + const char xmlCode[] = R"XML( +<typesystem package='Foo'> + <primitive-type name='int'/> + <object-type name='A'> + <modify-function signature='f2()' allow-thread='auto'/> + <modify-function signature='f3()' allow-thread='no'/> + <modify-function signature='getter2()const' allow-thread='yes'/> + </object-type> +</typesystem> +)XML"; + QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, + false, QLatin1String("0.1"))); + QVERIFY(!builder.isNull()); + AbstractMetaClassList classes = builder->classes(); + const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, QLatin1String("A")); + QVERIFY(classA); + + // Nothing specified, true + const AbstractMetaFunction *f1 = classA->findFunction(QLatin1String("f1")); + QVERIFY(f1); + QVERIFY(f1->allowThread()); + + // 'auto' specified, should be true for nontrivial function + const AbstractMetaFunction *f2 = classA->findFunction(QLatin1String("f2")); + QVERIFY(f2); + QVERIFY(f2->allowThread()); + + // 'no' specified, should be false + const AbstractMetaFunction *f3 = classA->findFunction(QLatin1String("f3")); + QVERIFY(f3); + QVERIFY(!f3->allowThread()); + + // Nothing specified, should be false for simple getter + const AbstractMetaFunction *getter1 = classA->findFunction(QLatin1String("getter1")); + QVERIFY(getter1); + QVERIFY(!getter1->allowThread()); + + // Forced to true simple getter + const AbstractMetaFunction *getter2 = classA->findFunction(QLatin1String("getter2")); + QVERIFY(getter2); + QVERIFY(getter2->allowThread()); // Forced to true simple getter +} + void TestModifyFunction::testGlobalFunctionModification() { const char* cppCode ="\ @@ -258,4 +315,42 @@ void TestModifyFunction::testGlobalFunctionModification() QCOMPARE(arg->defaultValueExpression(), QLatin1String("A()")); } +void TestModifyFunction::testExceptionSpecification() +{ + const char cppCode[] = R"CPP( +struct A { + void unspecified(); + void nonThrowing() noexcept; + void throwing() throw(int); +}; +)CPP"; + const char xmlCode[] = R"XML( +<typesystem package="Foo"> + <primitive-type name='int'/> + <object-type name='A'> + <modify-function signature='throwing()' exception-handling='auto-on'/> + </object-type> +</typesystem>)XML"; + QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, false)); + QVERIFY(!builder.isNull()); + + const AbstractMetaClass *classA = AbstractMetaClass::findClass(builder->classes(), QLatin1String("A")); + QVERIFY(classA); + + const AbstractMetaFunction *f = classA->findFunction(QStringLiteral("unspecified")); + QVERIFY(f); + QCOMPARE(f->exceptionSpecification(), ExceptionSpecification::Unknown); + QVERIFY(!f->generateExceptionHandling()); + + f = classA->findFunction(QStringLiteral("nonThrowing")); + QVERIFY(f); + QCOMPARE(f->exceptionSpecification(), ExceptionSpecification::NoExcept); + QVERIFY(!f->generateExceptionHandling()); + + f = classA->findFunction(QStringLiteral("throwing")); + QVERIFY(f); + QCOMPARE(f->exceptionSpecification(), ExceptionSpecification::Throws); + QVERIFY(f->generateExceptionHandling()); +} + QTEST_APPLESS_MAIN(TestModifyFunction) diff --git a/sources/shiboken2/ApiExtractor/tests/testmodifyfunction.h b/sources/shiboken2/ApiExtractor/tests/testmodifyfunction.h index f116b5124..494f31991 100644 --- a/sources/shiboken2/ApiExtractor/tests/testmodifyfunction.h +++ b/sources/shiboken2/ApiExtractor/tests/testmodifyfunction.h @@ -37,10 +37,12 @@ class TestModifyFunction : public QObject private slots: void testOwnershipTransfer(); void testWithApiVersion(); + void testAllowThread(); void testRenameArgument_data(); void testRenameArgument(); void invalidateAfterUse(); void testGlobalFunctionModification(); + void testExceptionSpecification(); }; #endif diff --git a/sources/shiboken2/ApiExtractor/tests/testrefcounttag.cpp b/sources/shiboken2/ApiExtractor/tests/testrefcounttag.cpp index 11cda3317..38099c455 100644 --- a/sources/shiboken2/ApiExtractor/tests/testrefcounttag.cpp +++ b/sources/shiboken2/ApiExtractor/tests/testrefcounttag.cpp @@ -82,7 +82,8 @@ void TestRefCountTag::testWithApiVersion() </object-type>\n\ </typesystem>\n"; - QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, false, "0.1")); + QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, + false, QLatin1String("0.1"))); QVERIFY(!builder.isNull()); AbstractMetaClassList classes = builder->classes(); const AbstractMetaClass *classB = AbstractMetaClass::findClass(classes, QLatin1String("B")); diff --git a/sources/shiboken2/ApiExtractor/tests/testtemplates.cpp b/sources/shiboken2/ApiExtractor/tests/testtemplates.cpp index 8d869e3f9..b1b171bae 100644 --- a/sources/shiboken2/ApiExtractor/tests/testtemplates.cpp +++ b/sources/shiboken2/ApiExtractor/tests/testtemplates.cpp @@ -28,6 +28,7 @@ #include "testtemplates.h" #include <QtTest/QTest> +#include <QtCore/QTextStream> #include <QTemporaryFile> #include "testutil.h" #include <abstractmetalang.h> @@ -438,4 +439,122 @@ typedef Vector<int> IntVector; QCOMPARE(otherMethod->type()->cppSignature(), QLatin1String("Vector<int >")); } +// Perform checks on template inheritance; a typedef of a template class +// should result in rewritten types. +void TestTemplates::testTemplateTypeDefs_data() +{ + QTest::addColumn<QString>("cpp"); + QTest::addColumn<QString>("xml"); + + const char optionalClassDef[] = R"CPP( +template<class T> // Some value type similar to std::optional +class Optional { +public: + T value() const { return m_value; } + operator bool() const { return m_success; } + + T m_value; + bool m_success = false; +}; +)CPP"; + + const char xmlPrefix[] = R"XML( +<typesystem package='Foo'> + <primitive-type name='int'/> + <primitive-type name='bool'/> +)XML"; + + const char xmlOptionalDecl[] = "<value-type name='Optional' generate='no'/>\n"; + const char xmlOptionalIntDecl[] = "<value-type name='IntOptional'/>\n"; + const char xmlPostFix[] = "</typesystem>\n"; + + // Flat, global namespace + QString cpp; + QTextStream(&cpp) << optionalClassDef + << "typedef Optional<int> IntOptional;\n"; + QString xml; + QTextStream(&xml) << xmlPrefix << xmlOptionalDecl << xmlOptionalIntDecl + << "<typedef-type name='XmlIntOptional' source='Optional<int>'/>" + << xmlPostFix; + QTest::newRow("global-namespace") + << cpp << xml; + + // Typedef from namespace Std + cpp.clear(); + QTextStream(&cpp) << "namespace Std {\n" << optionalClassDef << "}\n" + << "typedef Std::Optional<int> IntOptional;\n"; + xml.clear(); + QTextStream(&xml) << xmlPrefix + << "<namespace-type name='Std'>\n" << xmlOptionalDecl + << "</namespace-type>\n" << xmlOptionalIntDecl + << "<typedef-type name='XmlIntOptional' source='Std::Optional<int>'/>" + << xmlPostFix; + QTest::newRow("namespace-Std") + << cpp << xml; + + // Typedef from nested class + cpp.clear(); + QTextStream(&cpp) << "class Outer {\npublic:\n" << optionalClassDef << "\n};\n" + << "typedef Outer::Optional<int> IntOptional;\n"; + xml.clear(); + QTextStream(&xml) << xmlPrefix + << "<object-type name='Outer'>\n" << xmlOptionalDecl + << "</object-type>\n" << xmlOptionalIntDecl + << "<typedef-type name='XmlIntOptional' source='Outer::Optional<int>'/>" + << xmlPostFix; + QTest::newRow("nested-class") + << cpp << xml; +} + +void TestTemplates::testTemplateTypeDefs() +{ + QFETCH(QString, cpp); + QFETCH(QString, xml); + + const QByteArray cppBa = cpp.toLocal8Bit(); + const QByteArray xmlBa = xml.toLocal8Bit(); + QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppBa.constData(), xmlBa.constData(), true)); + QVERIFY(!builder.isNull()); + AbstractMetaClassList classes = builder->classes(); + + const AbstractMetaClass *optional = AbstractMetaClass::findClass(classes, QLatin1String("Optional")); + QVERIFY(optional); + + // Find the typedef'ed class + const AbstractMetaClass *optionalInt = + AbstractMetaClass::findClass(classes, QLatin1String("IntOptional")); + QVERIFY(optionalInt); + QCOMPARE(optionalInt->templateBaseClass(), optional); + + // Find the class typedef'ed in the typesystem XML + const AbstractMetaClass *xmlOptionalInt = + AbstractMetaClass::findClass(classes, QLatin1String("XmlIntOptional")); + QVERIFY(xmlOptionalInt); + QCOMPARE(xmlOptionalInt->templateBaseClass(), optional); + + // Check whether the value() method now has an 'int' return + const AbstractMetaFunction *valueMethod = + optionalInt->findFunction(QLatin1String("value")); + QVERIFY(valueMethod); + QCOMPARE(valueMethod->type()->cppSignature(), QLatin1String("int")); + + // ditto for typesystem XML + const AbstractMetaFunction *xmlValueMethod = + xmlOptionalInt->findFunction(QLatin1String("value")); + QVERIFY(xmlValueMethod); + QCOMPARE(xmlValueMethod->type()->cppSignature(), QLatin1String("int")); + + // Check whether the m_value field is of type 'int' + const AbstractMetaField *valueField = + optionalInt->findField(QLatin1String("m_value")); + QVERIFY(valueField); + QCOMPARE(valueField->type()->cppSignature(), QLatin1String("int")); + + // ditto for typesystem XML + const AbstractMetaField *xmlValueField = + xmlOptionalInt->findField(QLatin1String("m_value")); + QVERIFY(xmlValueField); + QCOMPARE(xmlValueField->type()->cppSignature(), QLatin1String("int")); +} + QTEST_APPLESS_MAIN(TestTemplates) diff --git a/sources/shiboken2/ApiExtractor/tests/testtemplates.h b/sources/shiboken2/ApiExtractor/tests/testtemplates.h index 3e1565933..df3de18b9 100644 --- a/sources/shiboken2/ApiExtractor/tests/testtemplates.h +++ b/sources/shiboken2/ApiExtractor/tests/testtemplates.h @@ -46,6 +46,8 @@ private slots: void testTemplateInheritanceMixedWithNamespaceAndForwardDeclaration(); void testTypedefOfInstantiationOfTemplateClass(); void testContainerTypeIncompleteArgument(); + void testTemplateTypeDefs_data(); + void testTemplateTypeDefs(); }; #endif diff --git a/sources/shiboken2/ApiExtractor/tests/testtyperevision.cpp b/sources/shiboken2/ApiExtractor/tests/testtyperevision.cpp index 1ec7ce025..a7e88e437 100644 --- a/sources/shiboken2/ApiExtractor/tests/testtyperevision.cpp +++ b/sources/shiboken2/ApiExtractor/tests/testtyperevision.cpp @@ -31,6 +31,7 @@ #include "testutil.h" #include <abstractmetalang.h> #include <typesystem.h> +#include <typedatabase.h> void TestTypeRevision::testRevisionAttr() { @@ -49,21 +50,55 @@ void TestTypeRevision::testRevisionAttr() QVERIFY(!builder.isNull()); AbstractMetaClassList classes = builder->classes(); const AbstractMetaClass *rev0 = AbstractMetaClass::findClass(classes, QLatin1String("Rev_0")); - QCOMPARE(getTypeRevision(rev0->typeEntry()), 0); + QCOMPARE(rev0->typeEntry()->revision(), 0); const AbstractMetaClass *rev1 = AbstractMetaClass::findClass(classes, QLatin1String("Rev_1")); - QCOMPARE(getTypeRevision(rev1->typeEntry()), 1); + QCOMPARE(rev1->typeEntry()->revision(), 1); AbstractMetaClass *rev2 = AbstractMetaClass::findClass(classes, QLatin1String("Rev_2")); - QCOMPARE(getTypeRevision(rev2->typeEntry()), 2); + QCOMPARE(rev2->typeEntry()->revision(), 2); AbstractMetaEnum* rev3 = rev2->findEnum(QLatin1String("Rev_3")); - QCOMPARE(getTypeRevision(rev3->typeEntry()), 3); + QCOMPARE(rev3->typeEntry()->revision(), 3); FlagsTypeEntry* rev4 = rev3->typeEntry()->flags(); - QCOMPARE(getTypeRevision(rev4), 4); + QCOMPARE(rev4->revision(), 4); AbstractMetaEnum* rev5 = rev2->findEnum(QLatin1String("Rev_5")); - QCOMPARE(getTypeRevision(rev5->typeEntry()), 5); - QCOMPARE(getTypeRevision(rev5->typeEntry()->flags()), 5); + const EnumTypeEntry *revEnumTypeEntry = rev5->typeEntry(); + QCOMPARE(revEnumTypeEntry->revision(), 5); + QCOMPARE(revEnumTypeEntry->flags()->revision(), 5); +} + + +void TestTypeRevision::testVersion_data() +{ + QTest::addColumn<QString>("version"); + QTest::addColumn<int>("expectedClassCount"); + + QTest::newRow("none") << QString() << 2; + QTest::newRow("1.0") << QString::fromLatin1("1.0") << 1; // Bar20 excluded + QTest::newRow("2.0") << QString::fromLatin1("2.0") << 2; +} + +void TestTypeRevision::testVersion() +{ + QFETCH(QString, version); + QFETCH(int, expectedClassCount); + + const char cppCode[] = R"CPP( +class Bar {}; +class Bar20 {}; +)CPP"; + const char xmlCode[] = R"XML( +<typesystem package="Foo"> + <value-type name="Bar"/> + <value-type name="Bar20" since="2.0"/> +</typesystem> +)XML"; + + QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, true, version)); + QVERIFY(!builder.isNull()); + + QCOMPARE(builder->classes().size(), expectedClassCount); } QTEST_APPLESS_MAIN(TestTypeRevision) diff --git a/sources/shiboken2/ApiExtractor/tests/testtyperevision.h b/sources/shiboken2/ApiExtractor/tests/testtyperevision.h index 4dfa241e3..3832c3883 100644 --- a/sources/shiboken2/ApiExtractor/tests/testtyperevision.h +++ b/sources/shiboken2/ApiExtractor/tests/testtyperevision.h @@ -37,6 +37,8 @@ class TestTypeRevision : public QObject private slots: void testRevisionAttr(); + void testVersion_data(); + void testVersion(); }; #endif diff --git a/sources/shiboken2/ApiExtractor/tests/testutil.h b/sources/shiboken2/ApiExtractor/tests/testutil.h index 6152793f5..c6ad19d7e 100644 --- a/sources/shiboken2/ApiExtractor/tests/testutil.h +++ b/sources/shiboken2/ApiExtractor/tests/testutil.h @@ -40,20 +40,23 @@ namespace TestUtil { static AbstractMetaBuilder *parse(const char *cppCode, const char *xmlCode, bool silent = true, - const char *apiVersion = Q_NULLPTR, + const QString &apiVersion = QString(), const QStringList &dropTypeEntries = QStringList()) { ReportHandler::setSilent(silent); TypeDatabase* td = TypeDatabase::instance(true); - if (apiVersion && !td->setApiVersion(QLatin1String("*"), QLatin1String(apiVersion))) - return Q_NULLPTR; + if (apiVersion.isEmpty()) + TypeDatabase::clearApiVersions(); + else if (!td->setApiVersion(QLatin1String("*"), apiVersion)) + return nullptr; td->setDropTypeEntries(dropTypeEntries); QBuffer buffer; // parse typesystem buffer.setData(xmlCode); if (!buffer.open(QIODevice::ReadOnly)) return Q_NULLPTR; - td->parseFile(&buffer); + if (!td->parseFile(&buffer)) + return nullptr; buffer.close(); // parse C++ code QTemporaryFile tempSource(QDir::tempPath() + QLatin1String("/st_XXXXXX_main.cpp")); |