diff options
Diffstat (limited to 'sources/shiboken2/ApiExtractor/tests/testtemplates.cpp')
-rw-r--r-- | sources/shiboken2/ApiExtractor/tests/testtemplates.cpp | 644 |
1 files changed, 0 insertions, 644 deletions
diff --git a/sources/shiboken2/ApiExtractor/tests/testtemplates.cpp b/sources/shiboken2/ApiExtractor/tests/testtemplates.cpp deleted file mode 100644 index ec3ddb8b2..000000000 --- a/sources/shiboken2/ApiExtractor/tests/testtemplates.cpp +++ /dev/null @@ -1,644 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of Qt for Python. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "testtemplates.h" -#include <QtTest/QTest> -#include <QtCore/QTextStream> -#include <QTemporaryFile> -#include "testutil.h" -#include <abstractmetalang.h> -#include <typesystem.h> - -void TestTemplates::testTemplateWithNamespace() -{ - const char cppCode[] = R"CPP( -template<typename T> struct QList {}; -struct Url { - void name(); -}; -namespace Internet { - struct Url{}; - struct Bookmarks { - QList<Url> list(); - }; -}; -)CPP"; - - const char xmlCode0[] = R"XML( -<typesystem package='Package.Network'> - <value-type name='Url'/> -</typesystem>)XML"; - - QTemporaryFile file; - QVERIFY(file.open()); - file.write(xmlCode0); - file.close(); - - QString xmlCode1 = QString::fromLatin1(R"XML( -<typesystem package='Package.Internet'> - <load-typesystem name='%1' generate='no'/> - <container-type name='QList' type='list'/> - <namespace-type name='Internet' generate='no'> - <value-type name='Url'/> - <value-type name='Bookmarks'/> - </namespace-type> -</typesystem>)XML").arg(file.fileName()); - - QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, qPrintable(xmlCode1), false)); - QVERIFY(!builder.isNull()); - AbstractMetaClassList classes = builder->classes(); - - AbstractMetaClass* classB = AbstractMetaClass::findClass(classes, QLatin1String("Bookmarks")); - QVERIFY(classB); - const AbstractMetaFunction* func = classB->findFunction(QLatin1String("list")); - AbstractMetaType* funcType = func->type(); - QVERIFY(funcType); - QCOMPARE(funcType->cppSignature(), QLatin1String("QList<Internet::Url >")); -} - -void TestTemplates::testTemplateOnContainers() -{ - const char cppCode[] = R"CPP( -struct Base {}; -template<typename T> struct QList {}; -namespace Namespace { - enum SomeEnum { E1, E2 }; - template<SomeEnum type> struct A { - A<type> foo(const QList<A<type> >& a); - }; - typedef A<E1> B; -} -)CPP"; - - const char xmlCode[] = R"XML( -<typesystem package="Package"> - <container-type name='QList' type='list'/> - <namespace-type name='Namespace'> - <enum-type name='SomeEnum'/> - <object-type name='A' generate='no'/> - <object-type name='B'/> - </namespace-type> - <object-type name='Base'/> -</typesystem>)XML"; - - QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, false)); - QVERIFY(!builder.isNull()); - AbstractMetaClassList classes = builder->classes(); - - AbstractMetaClass* classB = AbstractMetaClass::findClass(classes, QLatin1String("B")); - QVERIFY(classB); - QVERIFY(!classB->baseClass()); - QVERIFY(classB->baseClassName().isEmpty()); - const AbstractMetaFunction* func = classB->findFunction(QLatin1String("foo")); - AbstractMetaType* argType = func->arguments().first()->type(); - QCOMPARE(argType->instantiations().count(), 1); - QCOMPARE(argType->typeEntry()->qualifiedCppName(), QLatin1String("QList")); - - const AbstractMetaType* instance1 = argType->instantiations().first(); - QCOMPARE(instance1->instantiations().count(), 1); - QCOMPARE(instance1->typeEntry()->qualifiedCppName(), QLatin1String("Namespace::A")); - - const AbstractMetaType* instance2 = instance1->instantiations().first(); - QCOMPARE(instance2->instantiations().count(), 0); - QCOMPARE(instance2->typeEntry()->qualifiedCppName(), QLatin1String("Namespace::E1")); -} - -void TestTemplates::testTemplateValueAsArgument() -{ - const char cppCode[] = R"CPP( -template<typename T> struct List {}; -void func(List<int> arg) {} -)CPP"; - - const char xmlCode[] = R"XML( -<typesystem package='Package'> - <primitive-type name='int'/> - <container-type name='List' type='list'/> - <function signature='func(List<int>)'/> -</typesystem>)XML"; - - QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, false)); - QVERIFY(!builder.isNull()); - AbstractMetaFunctionList globalFuncs = builder->globalFunctions(); - QCOMPARE(globalFuncs.count(), 1); - - AbstractMetaFunction* func = globalFuncs.first(); - QCOMPARE(func->minimalSignature(), QLatin1String("func(List<int>)")); - QCOMPARE(func->arguments().first()->type()->cppSignature(), QLatin1String("List<int >")); -} - -void TestTemplates::testTemplatePointerAsArgument() -{ - const char cppCode[] = R"CPP( -template<typename T> struct List {}; -void func(List<int>* arg) {} -)CPP"; - - const char xmlCode[] = R"XML( - <typesystem package='Package'> - <primitive-type name='int'/> - <container-type name='List' type='list'/> - <function signature='func(List<int>*)'/> - </typesystem>)XML"; - - QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, false)); - QVERIFY(!builder.isNull()); - AbstractMetaFunctionList globalFuncs = builder->globalFunctions(); - QCOMPARE(globalFuncs.count(), 1); - - AbstractMetaFunction* func = globalFuncs.first(); - QCOMPARE(func->minimalSignature(), QLatin1String("func(List<int>*)")); - QCOMPARE(func->arguments().first()->type()->cppSignature(), QLatin1String("List<int > *")); -} - -void TestTemplates::testTemplateReferenceAsArgument() -{ - const char cppCode[] = R"CPP( -template<typename T> struct List {}; -void func(List<int>& arg) {} - )CPP"; - - const char xmlCode[] = R"XML( -<typesystem package='Package'> - <primitive-type name='int'/> - <container-type name='List' type='list'/> - <function signature='func(List<int>&)'/> -</typesystem>)XML"; - - QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, false)); - QVERIFY(!builder.isNull()); - AbstractMetaFunctionList globalFuncs = builder->globalFunctions(); - QCOMPARE(globalFuncs.count(), 1); - - AbstractMetaFunction* func = globalFuncs.first(); - QCOMPARE(func->minimalSignature(), QLatin1String("func(List<int>&)")); - QCOMPARE(func->arguments().first()->type()->cppSignature(), QLatin1String("List<int > &")); -} - -void TestTemplates::testTemplateParameterFixup() -{ - const char cppCode[] = R"CPP( -template<typename T> -struct List { - struct Iterator {}; - void append(List l); - void erase(List::Iterator it); -}; -)CPP"; - - const char xmlCode[] = R"XML( - <typesystem package='Package'> - <container-type name='List' type='list'> - <value-type name='Iterator'/> - </container-type> - </typesystem>)XML"; - - QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, false)); - QVERIFY(!builder.isNull()); - const AbstractMetaClassList templates = builder->templates(); - - QCOMPARE(templates.count(), 1); - const AbstractMetaClass *list = templates.first(); - // Verify that the parameter of "void append(List l)" gets fixed to "List<T >" - const AbstractMetaFunction *append = list->findFunction(QStringLiteral("append")); - QVERIFY(append); - QCOMPARE(append->arguments().size(), 1); - QCOMPARE(append->arguments().at(0)->type()->cppSignature(), QLatin1String("List<T >")); - // Verify that the parameter of "void erase(Iterator)" is not modified - const AbstractMetaFunction *erase = list->findFunction(QStringLiteral("erase")); - QVERIFY(erase); - QCOMPARE(erase->arguments().size(), 1); - QEXPECT_FAIL("", "Clang: Some other code changes the parameter type", Abort); - QCOMPARE(erase->arguments().at(0)->type()->cppSignature(), QLatin1String("List::Iterator")); -} - -void TestTemplates::testInheritanceFromContainterTemplate() -{ - const char cppCode[] = R"CPP( -template<typename T> -struct ListContainer { - inline void push_front(const T& t); - inline T& front(); -}; -struct FooBar {}; -struct FooBars : public ListContainer<FooBar> {}; -)CPP"; - - const char xmlCode[] = R"XML( -<typesystem package='Package'> - <container-type name='ListContainer' type='list'/> - <value-type name='FooBar'/> - <value-type name='FooBars'> - <modify-function signature='push_front(FooBar)' remove='all'/> - <modify-function signature='front()' remove='all'/> - </value-type> -</typesystem>)XML"; - - QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, false)); - QVERIFY(!builder.isNull()); - AbstractMetaClassList classes = builder->classes(); - AbstractMetaClassList templates = builder->templates(); - QCOMPARE(classes.count(), 2); - QCOMPARE(templates.count(), 1); - - const AbstractMetaClass* foobars = AbstractMetaClass::findClass(classes, QLatin1String("FooBars")); - QCOMPARE(foobars->functions().count(), 4); - - const AbstractMetaClass* lc = templates.first(); - QCOMPARE(lc->functions().count(), 2); -} - -void TestTemplates::testTemplateInheritanceMixedWithForwardDeclaration() -{ - const char cppCode[] = R"CPP( -enum SomeEnum { E1, E2 }; -template<SomeEnum type> struct Future; -template<SomeEnum type> -struct A { - A(); - void method(); - friend struct Future<type>; -}; -typedef A<E1> B; -template<SomeEnum type> struct Future {}; -)CPP"; - - const char xmlCode[] = R"XML( -<typesystem package='Package'> - <enum-type name='SomeEnum'/> - <value-type name='A' generate='no'/> - <value-type name='B'/> - <value-type name='Future' generate='no'/> -</typesystem>)XML"; - - QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, false)); - QVERIFY(!builder.isNull()); - AbstractMetaClassList classes = builder->classes(); - - AbstractMetaClass* classB = AbstractMetaClass::findClass(classes, QLatin1String("B")); - QVERIFY(classB); - QVERIFY(!classB->baseClass()); - QVERIFY(classB->baseClassName().isEmpty()); - // 3 functions: simple constructor, copy constructor and "method()". - QCOMPARE(classB->functions().count(), 3); -} - -void TestTemplates::testTemplateInheritanceMixedWithNamespaceAndForwardDeclaration() -{ - const char cppCode[] = R"CPP( -namespace Namespace { -enum SomeEnum { E1, E2 }; -template<SomeEnum type> struct Future; -template<SomeEnum type> -struct A { - A(); - void method(); - friend struct Future<type>; -}; -typedef A<E1> B; -template<SomeEnum type> struct Future {}; -}; -)CPP"; - - const char xmlCode[] = R"XML( -<typesystem package='Package'> - <namespace-type name='Namespace'> - <enum-type name='SomeEnum'/> - <value-type name='A' generate='no'/> - <value-type name='B'/> - <value-type name='Future' generate='no'/> - </namespace-type> -</typesystem>)XML"; - - QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, false)); - QVERIFY(!builder.isNull()); - AbstractMetaClassList classes = builder->classes(); - - AbstractMetaClass* classB = AbstractMetaClass::findClass(classes, QLatin1String("Namespace::B")); - QVERIFY(classB); - QVERIFY(!classB->baseClass()); - QVERIFY(classB->baseClassName().isEmpty()); - // 3 functions: simple constructor, copy constructor and "method()". - QCOMPARE(classB->functions().count(), 3); -} - -void TestTemplates::testTypedefOfInstantiationOfTemplateClass() -{ - const char cppCode[] = R"CPP( -namespace NSpace { -enum ClassType { - TypeOne -}; -template<ClassType CLASS_TYPE> -struct BaseTemplateClass { - inline ClassType getClassType() const { CLASS_TYPE; } -}; -typedef BaseTemplateClass<TypeOne> TypeOneClass; -} -)CPP"; - - const char xmlCode[] = R"XML( -<typesystem package='Package'> - <namespace-type name='NSpace'> - <enum-type name='ClassType'/> - <object-type name='BaseTemplateClass' generate='no'/> - <object-type name='TypeOneClass'/> - </namespace-type> -</typesystem>)XML"; - - QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, false)); - QVERIFY(!builder.isNull()); - AbstractMetaClassList classes = builder->classes(); - QCOMPARE(classes.count(), 3); - - const AbstractMetaClass* base = AbstractMetaClass::findClass(classes, QLatin1String("BaseTemplateClass")); - QVERIFY(base); - const AbstractMetaClass* one = AbstractMetaClass::findClass(classes, QLatin1String("TypeOneClass")); - QVERIFY(one); - QCOMPARE(one->templateBaseClass(), base); - QCOMPARE(one->functions().count(), base->functions().count()); - QVERIFY(one->isTypeDef()); - const ComplexTypeEntry* oneType = one->typeEntry(); - const ComplexTypeEntry* baseType = base->typeEntry(); - QCOMPARE(oneType->baseContainerType(), baseType); - QCOMPARE(one->baseClassNames(), QStringList(QLatin1String("BaseTemplateClass<TypeOne>"))); - - QVERIFY(one->hasTemplateBaseClassInstantiations()); - AbstractMetaTypeList instantiations = one->templateBaseClassInstantiations(); - QCOMPARE(instantiations.count(), 1); - const AbstractMetaType* inst = instantiations.first(); - QVERIFY(inst); - QVERIFY(!inst->isEnum()); - QVERIFY(!inst->typeEntry()->isEnum()); - QVERIFY(inst->typeEntry()->isEnumValue()); - QCOMPARE(inst->cppSignature(), QLatin1String("NSpace::TypeOne")); -} - -void TestTemplates::testContainerTypeIncompleteArgument() -{ - const char cppCode[] = R"CPP( -template<typename T> -class Vector { - void method(const Vector& vector); - Vector otherMethod(); -}; -template <typename T> -void Vector<T>::method(const Vector<T>& vector) {} -template <typename T> -Vector<T> Vector<T>::otherMethod() { return Vector<T>(); } -typedef Vector<int> IntVector; -)CPP"; - - const char xmlCode[] = R"XML( -<typesystem package='Foo'> - <primitive-type name='int'/> - <container-type name='Vector' type='vector'/> - <value-type name='IntVector'/> -</typesystem>)XML"; - - QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, true)); - QVERIFY(!builder.isNull()); - AbstractMetaClassList classes = builder->classes(); - QCOMPARE(classes.count(), 1); - - AbstractMetaClass* vector = AbstractMetaClass::findClass(classes, QLatin1String("IntVector")); - QVERIFY(vector); - auto baseContainer = vector->typeEntry()->baseContainerType(); - QVERIFY(baseContainer); - QCOMPARE(reinterpret_cast<const ContainerTypeEntry*>(baseContainer)->containerKind(), - ContainerTypeEntry::VectorContainer); - QCOMPARE(vector->functions().count(), 4); - - const AbstractMetaFunction* method = vector->findFunction(QLatin1String("method")); - QVERIFY(method); - QCOMPARE(method->signature(), QLatin1String("method(const Vector<int > & vector)")); - - const AbstractMetaFunction* otherMethod = vector->findFunction(QLatin1String("otherMethod")); - QVERIFY(otherMethod); - QCOMPARE(otherMethod->signature(), QLatin1String("otherMethod()")); - QVERIFY(otherMethod->type()); - QCOMPARE(otherMethod->type()->cppSignature(), QLatin1String("Vector<int >")); -} - -void TestTemplates::testNonTypeTemplates() -{ - // PYSIDe-1296, functions with non type templates parameters. - const char cppCode[] = R"CPP( -template <class T, int Size> -class Array { - T array[Size]; -}; - -Array<int, 2> foo(); - -)CPP"; - - const char xmlCode[] = R"XML( -<typesystem package='Foo'> - <primitive-type name='int'/> - <container-type name='Array' type='vector'/> - <function signature="foo()"/> -</typesystem>)XML"; - - QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, true)); - QVERIFY(!builder.isNull()); - auto functions = builder->globalFunctions(); - QCOMPARE(functions.count(), 1); - auto foo = functions.constFirst(); - QCOMPARE(foo->name(), QLatin1String("foo")); - QCOMPARE(foo->type()->name(), QLatin1String("Array")); -} - -// 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")); -} - -void TestTemplates::testTemplateTypeAliases() -{ - // Model Qt 6's "template<typename T> using QList = QVector<T>" - const char cppCode[] = R"CPP( -template<typename T> -class Container1 { }; - -template<typename T> -using Container2 = Container1<T>; - -class Test -{ -public: - Container2<int> m_intContainer; -}; - -class Derived : public Container2<int> -{ -public: -}; -)CPP"; - - const char xmlCode[] = R"XML( -<typesystem package='Foo'> - <primitive-type name='int'/> - <value-type name='Container1'/> - <value-type name='Derived'/> - <object-type name='Test'/> -</typesystem>)XML"; - - QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, true)); - QVERIFY(!builder.isNull()); - - AbstractMetaClassList classes = builder->classes(); - auto testClass = AbstractMetaClass::findClass(classes, QLatin1String("Test")); - QVERIFY(testClass); - - auto fields = testClass->fields(); - QCOMPARE(fields.count(), 1); - auto fieldType = testClass->fields().at(0)->type(); - QCOMPARE(fieldType->name(), QLatin1String("Container1")); - QCOMPARE(fieldType->instantiations().size(), 1); - - auto derived = AbstractMetaClass::findClass(classes, QLatin1String("Derived")); - QVERIFY(derived); - auto base = derived->templateBaseClass(); - QCOMPARE(base->name(), QLatin1String("Container1")); -} - -QTEST_APPLESS_MAIN(TestTemplates) |