From 9c333ade1a1b694fc6ce22e483f5de3e952c17ad Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Mon, 22 May 2017 17:50:30 +0200 Subject: move everying into sources/shiboken2 (5.9 edition) in preparation for a subtree merge. this should not be necessary to do in a separate commit, but git is a tad stupid about following history correctly without it. --- .../shiboken2/ApiExtractor/tests/testtemplates.cpp | 439 +++++++++++++++++++++ 1 file changed, 439 insertions(+) create mode 100644 sources/shiboken2/ApiExtractor/tests/testtemplates.cpp (limited to 'sources/shiboken2/ApiExtractor/tests/testtemplates.cpp') diff --git a/sources/shiboken2/ApiExtractor/tests/testtemplates.cpp b/sources/shiboken2/ApiExtractor/tests/testtemplates.cpp new file mode 100644 index 000000000..4a66264d8 --- /dev/null +++ b/sources/shiboken2/ApiExtractor/tests/testtemplates.cpp @@ -0,0 +1,439 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $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 +#include +#include "testutil.h" +#include +#include + +void TestTemplates::testTemplateWithNamespace() +{ + const char cppCode[] = "\n\ + template struct QList {}; \n\ + struct Url {\n\ + void name();\n\ + };\n\ + namespace Internet {\n\ + struct Url{};\n\ + struct Bookmarks {\n\ + QList list();\n\ + };\n\ + }"; + const char xmlCode0[] = "\n\ + \n\ + \n\ + "; + + QTemporaryFile file; + QVERIFY(file.open()); + file.write(xmlCode0); + file.close(); + + QString xmlCode1 = QString::fromLatin1("\n\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n\ + ").arg(file.fileName()); + + QScopedPointer 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")); +} + +void TestTemplates::testTemplateOnContainers() +{ + const char cppCode[] = "\n\ + struct Base {};\n\ + template struct QList {}; \n\ + namespace Namespace {\n\ + enum SomeEnum { E1, E2 };\n\ + template struct A {\n\ + A foo(const QList >& a);\n\ + };\n\ + typedef A B;\n\ + }\n\ + "; + const char xmlCode[] = "\n\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n\ + "; + + QScopedPointer 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().isNull()); + 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[] = "\n\ + template struct List {};\n\ + void func(List arg) {}\n\ + "; + + const char xmlCode[] = "\n\ + \n\ + \n\ + \n\ + \n\ + \n\ + "; + + QScopedPointer 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)")); + QCOMPARE(func->arguments().first()->type()->cppSignature(), QLatin1String("List")); +} + +void TestTemplates::testTemplatePointerAsArgument() +{ + const char cppCode[] = "\n\ + template struct List {};\n\ + void func(List* arg) {}\n\ + "; + + const char xmlCode[] = "\n\ + \n\ + \n\ + \n\ + \n\ + \n\ + "; + + QScopedPointer 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*)")); + QCOMPARE(func->arguments().first()->type()->cppSignature(), QLatin1String("List *")); +} + +void TestTemplates::testTemplateReferenceAsArgument() +{ + const char cppCode[] = "\n\ + template struct List {};\n\ + void func(List& arg) {}\n\ + "; + + const char xmlCode[] = "\n\ + \n\ + \n\ + \n\ + \n\ + \n\ + "; + + QScopedPointer 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&)")); + QCOMPARE(func->arguments().first()->type()->cppSignature(), QLatin1String("List &")); +} + +void TestTemplates::testTemplateParameterFixup() +{ + const char cppCode[] = "\n\ + template\n\ + struct List {\n\ + struct Iterator {};\n\ + void append(List l);\n\ + void erase(List::Iterator it);\n\ + };\n"; + + const char xmlCode[] = "\n\ + \n\ + \n\ + \n\ + \n"; + + QScopedPointer 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" + const AbstractMetaFunction *append = list->findFunction(QStringLiteral("append")); + QVERIFY(append); + QCOMPARE(append->arguments().size(), 1); + QCOMPARE(append->arguments().at(0)->type()->cppSignature(), QLatin1String("List")); + // 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[] = "\n\ + template\n\ + struct ListContainer {\n\ + inline void push_front(const T& t);\n\ + inline T& front();\n\ + };\n\ + struct FooBar {};\n\ + struct FooBars : public ListContainer {};\n\ + "; + + const char xmlCode[] = "\n\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n\ + "; + + QScopedPointer 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[] = "\n\ + enum SomeEnum { E1, E2 };\n\ + template struct Future;\n\ + template\n\ + struct A {\n\ + A();\n\ + void method();\n\ + friend struct Future;\n\ + };\n\ + typedef A B;\n\ + template struct Future {};\n\ + "; + const char xmlCode[] = "\n\ + \n\ + \n\ + \n\ + \n\ + \n\ + "; + + QScopedPointer 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().isNull()); + // 3 functions: simple constructor, copy constructor and "method()". + QCOMPARE(classB->functions().count(), 3); +} + +void TestTemplates::testTemplateInheritanceMixedWithNamespaceAndForwardDeclaration() +{ + const char cppCode[] = "\n\ + namespace Namespace {\n\ + enum SomeEnum { E1, E2 };\n\ + template struct Future;\n\ + template\n\ + struct A {\n\ + A();\n\ + void method();\n\ + friend struct Future;\n\ + };\n\ + typedef A B;\n\ + template struct Future {};\n\ + };\n\ + "; + const char xmlCode[] = "\n\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n\ + "; + + QScopedPointer 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().isNull()); + // 3 functions: simple constructor, copy constructor and "method()". + QCOMPARE(classB->functions().count(), 3); +} + +void TestTemplates::testTypedefOfInstantiationOfTemplateClass() +{ + const char cppCode[] = "\n\ + namespace NSpace {\n\ + enum ClassType {\n\ + TypeOne\n\ + };\n\ + template\n\ + struct BaseTemplateClass {\n\ + inline ClassType getClassType() const { CLASS_TYPE; }\n\ + };\n\ + typedef BaseTemplateClass TypeOneClass;\n\ + }\n\ + "; + + const char xmlCode[] = "\n\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n\ + "; + + QScopedPointer 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"))); + + 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 ="\n\ + template\n\ + class Vector {\n\ + void method(const Vector& vector);\n\ + Vector otherMethod();\n\ + };\n\ + template \n\ + void Vector::method(const Vector& vector) {}\n\ + template \n\ + Vector Vector::otherMethod() { return Vector(); }\n\ + typedef Vector IntVector;\n\ + "; + const char* xmlCode = "\n\ + \n\ + \n\ + \n\ + \n\ + "; + + QScopedPointer 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); + QVERIFY(vector->typeEntry()->baseContainerType()); + QCOMPARE(reinterpret_cast(vector->typeEntry()->baseContainerType())->type(), ContainerTypeEntry::VectorContainer); + QCOMPARE(vector->functions().count(), 4); + + const AbstractMetaFunction* method = vector->findFunction(QLatin1String("method")); + QVERIFY(method); + QCOMPARE(method->signature(), QLatin1String("method(const Vector & vector)")); + + const AbstractMetaFunction* otherMethod = vector->findFunction(QLatin1String("otherMethod")); + QVERIFY(otherMethod); + QCOMPARE(otherMethod->signature(), QLatin1String("otherMethod()")); + QVERIFY(otherMethod->type()); + QCOMPARE(otherMethod->type()->cppSignature(), QLatin1String("Vector")); +} + +QTEST_APPLESS_MAIN(TestTemplates) -- cgit v1.2.3