// 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 "testconversionruletag.h" #include "testutil.h" #include #include #include #include #include #include #include #include using namespace Qt::StringLiterals; void TestConversionRuleTag::testConversionRuleTagWithFile() { // FIXME PYSIDE7 remove // temp file used later const char conversionData[] = "Hi! I'm a conversion rule."; QTemporaryFile file; file.open(); QCOMPARE(file.write(conversionData), qint64(sizeof(conversionData)-1)); file.close(); const char cppCode[] = "struct A {};\n"; QString xmlCode = u"\ \n\ \n\ \n\ \n\ \n"_s; QScopedPointer builder(TestUtil::parse(cppCode, xmlCode.toLocal8Bit().data())); QVERIFY(!builder.isNull()); AbstractMetaClassList classes = builder->classes(); const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, u"A"); QVERIFY(classA); const ComplexTypeEntry* typeEntry = classA->typeEntry(); QVERIFY(typeEntry->hasTargetConversionRule()); QCOMPARE(typeEntry->targetConversionRule(), QLatin1String(conversionData)); } void TestConversionRuleTag::testConversionRuleTagReplace() { const char cppCode[] = "\ struct A {\n\ A();\n\ A(const char*, int);\n\ };\n\ struct B {\n\ A createA();\n\ };\n"; const char* xmlCode = "\ \n\ \n\ \n\ \n\ \n\ \n\ DoThis();\n\ return ConvertFromCppToPython(%IN);\n\ \n\ \n\ \n\ DoThat();\n\ DoSomething();\n\ %OUT = A();\n\ \n\ \n\ %OUT = %IN.createA();\n\ \n\ \n\ %OUT = new A(String_AsString(%IN), String_GetSize(%IN));\n\ \n\ \n\ \n\ \n\ \n\ \n"; QScopedPointer builder(TestUtil::parse(cppCode, xmlCode)); QVERIFY(!builder.isNull()); TypeDatabase* typeDb = TypeDatabase::instance(); PrimitiveTypeEntry* typeA = typeDb->findPrimitiveType(u"A"_s); QVERIFY(typeA); CustomConversion* conversion = typeA->customConversion(); QVERIFY(conversion); QCOMPARE(typeA, conversion->ownerType()); QCOMPARE(conversion->nativeToTargetConversion().simplified(), u"DoThis(); return ConvertFromCppToPython(%IN);"); QVERIFY(conversion->replaceOriginalTargetToNativeConversions()); QVERIFY(conversion->hasTargetToNativeConversions()); QCOMPARE(conversion->targetToNativeConversions().size(), 3); CustomConversion::TargetToNativeConversion* toNative = conversion->targetToNativeConversions().at(0); QVERIFY(toNative); QCOMPARE(toNative->sourceTypeName(), u"TargetNone"); QVERIFY(toNative->isCustomType()); QCOMPARE(toNative->sourceType(), nullptr); QCOMPARE(toNative->sourceTypeCheck(), u"%IN == Target_None"); QCOMPARE(toNative->conversion().simplified(), u"DoThat(); DoSomething(); %OUT = A();"); toNative = conversion->targetToNativeConversions().at(1); QVERIFY(toNative); QCOMPARE(toNative->sourceTypeName(), u"B"); QVERIFY(!toNative->isCustomType()); TypeEntry* typeB = typeDb->findType(u"B"_s); QVERIFY(typeB); QCOMPARE(toNative->sourceType(), typeB); QCOMPARE(toNative->sourceTypeCheck(), u"CheckIfInputObjectIsB(%IN)"); QCOMPARE(toNative->conversion().trimmed(), u"%OUT = %IN.createA();"); toNative = conversion->targetToNativeConversions().at(2); QVERIFY(toNative); QCOMPARE(toNative->sourceTypeName(), u"String"); QVERIFY(toNative->isCustomType()); QCOMPARE(toNative->sourceType(), nullptr); QCOMPARE(toNative->sourceTypeCheck(), u"String_Check(%IN)"); QCOMPARE(toNative->conversion().trimmed(), u"%OUT = new A(String_AsString(%IN), String_GetSize(%IN));"); } void TestConversionRuleTag::testConversionRuleTagAdd() { const char cppCode[] = "\ struct Date {\n\ Date();\n\ Date(int, int, int);\n\ };\n"; const char* xmlCode = "\ \n\ \n\ \n\ \n\ \n\ \n\ if (!TargetDateTimeAPI) TargetDateTime_IMPORT;\n\ %OUT = new Date(TargetDate_Day(%IN), TargetDate_Month(%IN), TargetDate_Year(%IN));\n\ \n\ \n\ \n\ \n\ \n"; QScopedPointer builder(TestUtil::parse(cppCode, xmlCode)); QVERIFY(!builder.isNull()); auto *classA = AbstractMetaClass::findClass(builder->classes(), u"Date"); QVERIFY(classA); CustomConversion* conversion = classA->typeEntry()->customConversion(); QVERIFY(conversion); QCOMPARE(conversion->nativeToTargetConversion(), QString()); QVERIFY(!conversion->replaceOriginalTargetToNativeConversions()); QVERIFY(conversion->hasTargetToNativeConversions()); QCOMPARE(conversion->targetToNativeConversions().size(), 1); CustomConversion::TargetToNativeConversion *toNative = conversion->targetToNativeConversions().constFirst(); QVERIFY(toNative); QCOMPARE(toNative->sourceTypeName(), u"TargetDate"); QVERIFY(toNative->isCustomType()); QCOMPARE(toNative->sourceType(), nullptr); QCOMPARE(toNative->sourceTypeCheck(), u"TargetDate_Check(%IN)"); QCOMPARE(toNative->conversion().trimmed(), uR"(if (!TargetDateTimeAPI) TargetDateTime_IMPORT; %OUT = new Date(TargetDate_Day(%IN), TargetDate_Month(%IN), TargetDate_Year(%IN));)"); } void TestConversionRuleTag::testConversionRuleTagWithInsertTemplate() { const char cppCode[] = "struct A {};"; const char* xmlCode = "\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n"; const char nativeToTargetExpected[] = "// TEMPLATE - native_to_target - START\n" "return ConvertFromCppToPython(%IN);\n" "// TEMPLATE - native_to_target - END"; const char targetToNativeExpected[] = "// TEMPLATE - target_to_native - START\n" "%OUT = %IN.createA();\n" "// TEMPLATE - target_to_native - END"; QScopedPointer builder(TestUtil::parse(cppCode, xmlCode)); QVERIFY(!builder.isNull()); TypeDatabase* typeDb = TypeDatabase::instance(); PrimitiveTypeEntry* typeA = typeDb->findPrimitiveType(u"A"_s); QVERIFY(typeA); CustomConversion* conversion = typeA->customConversion(); QVERIFY(conversion); QCOMPARE(typeA, conversion->ownerType()); QCOMPARE(conversion->nativeToTargetConversion().trimmed(), QLatin1StringView(nativeToTargetExpected)); QVERIFY(conversion->hasTargetToNativeConversions()); QCOMPARE(conversion->targetToNativeConversions().size(), 1); CustomConversion::TargetToNativeConversion* toNative = conversion->targetToNativeConversions().constFirst(); QVERIFY(toNative); QCOMPARE(toNative->conversion().trimmed(), QLatin1StringView(targetToNativeExpected)); } QTEST_APPLESS_MAIN(TestConversionRuleTag)