From 985e24dd5f1e0b148a79b0c5f9459233cf03dba4 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Fri, 17 Jun 2022 15:46:06 -0700 Subject: [PATCH] QMetaType: add a test to confirm that types are equal across libraries Because of the template shenanigans. This is just to make sure. Pick-to: 6.4 Change-Id: Id0fb9ab0089845ee8843fffd16f989e7d555894f Reviewed-by: Ulf Hermann --- .../corelib/kernel/qmetatype/CMakeLists.txt | 35 +++++- tests/auto/corelib/kernel/qmetatype/lib1.cpp | 5 + tests/auto/corelib/kernel/qmetatype/lib2.cpp | 5 + .../corelib/kernel/qmetatype/lib_common.cpp | 13 ++ .../corelib/kernel/qmetatype/tst_qmetatype.h | 4 + .../kernel/qmetatype/tst_qmetatype2.cpp | 112 +++++++++++++++++- .../kernel/qmetatype/tst_qmetatype_libs.h | 24 ++++ 7 files changed, 193 insertions(+), 5 deletions(-) create mode 100644 tests/auto/corelib/kernel/qmetatype/lib1.cpp create mode 100644 tests/auto/corelib/kernel/qmetatype/lib2.cpp create mode 100644 tests/auto/corelib/kernel/qmetatype/lib_common.cpp create mode 100644 tests/auto/corelib/kernel/qmetatype/tst_qmetatype_libs.h diff --git a/tests/auto/corelib/kernel/qmetatype/CMakeLists.txt b/tests/auto/corelib/kernel/qmetatype/CMakeLists.txt index 623b002becf..a176d2b0e7b 100644 --- a/tests/auto/corelib/kernel/qmetatype/CMakeLists.txt +++ b/tests/auto/corelib/kernel/qmetatype/CMakeLists.txt @@ -10,6 +10,35 @@ # Collect test data list(APPEND test_data "./typeFlags.bin") +qt_internal_add_cmake_library(qmetatype_lib1 + INSTALL_DIRECTORY "${INSTALL_TESTSDIR}/tst_qmetatype" + SOURCES + lib1.cpp + PUBLIC_LIBRARIES + Qt::Core +) +qt_internal_add_cmake_library(qmetatype_lib2 + INSTALL_DIRECTORY "${INSTALL_TESTSDIR}/tst_qmetatype" + SOURCES + lib2.cpp + PUBLIC_LIBRARIES + Qt::Core +) +set_target_properties(qmetatype_lib1 PROPERTIES + VERSION 1.0.0 + SOVERSION 0 + C_VISIBILITY_PRESET "hidden" + CXX_VISIBILITY_PRESET "hidden" + VISIBILITY_INLINES_HIDDEN ON +) +set_target_properties(qmetatype_lib2 PROPERTIES + VERSION 1.0.0 + SOVERSION 0 + C_VISIBILITY_PRESET "hidden" + CXX_VISIBILITY_PRESET "hidden" + VISIBILITY_INLINES_HIDDEN ON +) + qt_internal_add_test(tst_qmetatype SOURCES tst_qmetatype.h tst_qmetatype.cpp tst_qmetatype2.cpp @@ -21,6 +50,8 @@ qt_internal_add_test(tst_qmetatype LIBRARIES Qt::CorePrivate Qt::Gui + qmetatype_lib1 + qmetatype_lib2 TESTDATA ${test_data} ) @@ -28,7 +59,3 @@ qt_internal_extend_target(tst_qmetatype CONDITION MSVC COMPILE_OPTIONS /bigobj ) - -#### Keys ignored in scope 3:.:.:qmetatype.pro:CLANG: -# QMAKE_CFLAGS_RELEASE = "--O2" "--g" -# QMAKE_CXXFLAGS_RELEASE = "--O2" "--g" diff --git a/tests/auto/corelib/kernel/qmetatype/lib1.cpp b/tests/auto/corelib/kernel/qmetatype/lib1.cpp new file mode 100644 index 00000000000..6a811241e9f --- /dev/null +++ b/tests/auto/corelib/kernel/qmetatype/lib1.cpp @@ -0,0 +1,5 @@ +// Copyright (C) 2022 Intel Corporation +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 + +#define LIB_NAMESPACE Lib1 +#include "lib_common.cpp" diff --git a/tests/auto/corelib/kernel/qmetatype/lib2.cpp b/tests/auto/corelib/kernel/qmetatype/lib2.cpp new file mode 100644 index 00000000000..b5a56f6c683 --- /dev/null +++ b/tests/auto/corelib/kernel/qmetatype/lib2.cpp @@ -0,0 +1,5 @@ +// Copyright (C) 2022 Intel Corporation +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 + +#define LIB_NAMESPACE Lib2 +#include "lib_common.cpp" diff --git a/tests/auto/corelib/kernel/qmetatype/lib_common.cpp b/tests/auto/corelib/kernel/qmetatype/lib_common.cpp new file mode 100644 index 00000000000..f0554ec25c7 --- /dev/null +++ b/tests/auto/corelib/kernel/qmetatype/lib_common.cpp @@ -0,0 +1,13 @@ +// Copyright (C) 2022 Intel Corporation +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 + +#include +#include "tst_qmetatype_libs.h" + +#define DECLARE_FUNCTION(TYPE, ID) \ + Q_DECL_EXPORT QMetaType metatype_ ## TYPE() \ + { return QMetaType::fromType(); } + +namespace LIB_NAMESPACE { +FOR_EACH_METATYPE_LIBS(DECLARE_FUNCTION) +} diff --git a/tests/auto/corelib/kernel/qmetatype/tst_qmetatype.h b/tests/auto/corelib/kernel/qmetatype/tst_qmetatype.h index 796d64c5a3e..84ba7af2946 100644 --- a/tests/auto/corelib/kernel/qmetatype/tst_qmetatype.h +++ b/tests/auto/corelib/kernel/qmetatype/tst_qmetatype.h @@ -108,6 +108,10 @@ private slots: void fromType(); void operatorEq_data(); void operatorEq(); + void operatorEq2_data(); + void operatorEq2(); + void operatorEqAcrossLibs_data(); + void operatorEqAcrossLibs(); void typesWithInaccessibleDTors(); void voidIsNotUnknown(); void typeNameNormalization(); diff --git a/tests/auto/corelib/kernel/qmetatype/tst_qmetatype2.cpp b/tests/auto/corelib/kernel/qmetatype/tst_qmetatype2.cpp index 95cc0e7ed8f..11dc593ebb7 100644 --- a/tests/auto/corelib/kernel/qmetatype/tst_qmetatype2.cpp +++ b/tests/auto/corelib/kernel/qmetatype/tst_qmetatype2.cpp @@ -2,7 +2,7 @@ // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 #include "tst_qmetatype.h" -#include "tst_qvariant_common.h" +#include "tst_qmetatype_libs.h" #include @@ -412,6 +412,116 @@ void tst_QMetaType::operatorEq() QCOMPARE(typeB == typeA, eq); QCOMPARE(typeA != typeB, !eq); QCOMPARE(typeB != typeA, !eq); + +#if !defined(Q_OS_WIN) && !defined(Q_OS_INTEGRITY) + // for built-in types or locally-defined types, this must also hold true + if (eq) + QCOMPARE(typeA.iface(), typeB.iface()); +#endif +} + +void tst_QMetaType::operatorEq2_data() +{ + create_data(); +} + +void tst_QMetaType::operatorEq2() +{ + QFETCH(int, type); + QMetaType fromType1, fromType2; + QMetaType fromId1(type), fromId2(type); + + switch (type) { + case QMetaType::UnknownType: + break; +#define GET_METATYPE_FROM_TYPE(MetaTypeName, MetaTypeId, RealType) \ + case QMetaType::MetaTypeName: \ + fromType1 = QMetaType::fromType(); \ + fromType2 = QMetaType::fromType(); \ + break; +FOR_EACH_CORE_METATYPE(GET_METATYPE_FROM_TYPE) +#undef GET_METATYPE_FROM_TYPE + } + + // sanity check + QCOMPARE(fromId1.id(), type); + QCOMPARE(fromId2.id(), type); + + // confirm that they're all equal + QCOMPARE(fromId1, fromId2); + QCOMPARE(fromType1, fromType2); + QCOMPARE(fromType1, fromId1); + QCOMPARE(fromType2, fromId2); + +#if !defined(Q_OS_WIN) && !defined(Q_OS_INTEGRITY) + // for built-in types (other than void), this must be true + if (type != QMetaType::Void) { + QCOMPARE(fromType1.iface(), fromId1.iface()); + QCOMPARE(fromType2.iface(), fromId1.iface()); + } +#endif +} + +#define DECLARE_LIB_FUNCTION(TYPE, ID) \ + Q_DECL_IMPORT QMetaType metatype_ ## TYPE(); +namespace Lib1 { FOR_EACH_METATYPE_LIBS(DECLARE_LIB_FUNCTION) } +namespace Lib2 { FOR_EACH_METATYPE_LIBS(DECLARE_LIB_FUNCTION) } +#undef DECLARE_LIB_FUNCTION + +using LibMetatypeFunction = QMetaType (*)(); +void tst_QMetaType::operatorEqAcrossLibs_data() +{ + QTest::addColumn("builtinTypeId"); + QTest::addColumn("localType"); + QTest::addColumn("lib1Function"); + QTest::addColumn("lib2Function"); + +#define ADD_ROW(TYPE, ID) \ + QTest::addRow(QT_STRINGIFY(TYPE)) << int(ID) \ + << QMetaType::fromType() \ + << &Lib1::metatype_ ## TYPE \ + << &Lib2::metatype_ ## TYPE; +FOR_EACH_METATYPE_LIBS(ADD_ROW) +#undef ADD_ROW +} + +void tst_QMetaType::operatorEqAcrossLibs() +{ + QFETCH(int, builtinTypeId); + QFETCH(QMetaType, localType); + QFETCH(LibMetatypeFunction, lib1Function); + QFETCH(LibMetatypeFunction, lib2Function); + + QMetaType lib1Type = lib1Function(); + QMetaType lib2Type = lib2Function(); + + const QtPrivate::QMetaTypeInterface *localIface = localType.iface(); + const QtPrivate::QMetaTypeInterface *lib1Iface = lib1Type.iface(); + const QtPrivate::QMetaTypeInterface *lib2Iface = lib2Type.iface(); + + // DO THIS FIRST: + // if this isn't a built-in type, then the QMetaTypeInterface::typeId is + // initially set to 0 + QCOMPARE(lib1Type, lib2Type); + + int actualTypeId = localType.id(); + bool builtinTypeExpected = builtinTypeId != QMetaType::UnknownType; + bool builtinTypeActually = actualTypeId < QMetaType::User; + + qDebug() << "QMetaType for type" << QByteArray(localType.name()) + << "(type ID" << (actualTypeId >= 0x1000 ? Qt::hex : Qt::dec) << actualTypeId << ')' + << (builtinTypeActually ? "IS" : "is NOT") << "a built-in type;" + << "local interface:" << static_cast(localIface) + << "lib1 interface:" << static_cast(lib1Iface) + << "lib2 interface:" << static_cast(lib2Iface); + + QCOMPARE(builtinTypeActually, builtinTypeExpected); + QCOMPARE(lib1Type.id(), actualTypeId); + QCOMPARE(lib2Type.id(), actualTypeId); + QCOMPARE(QByteArray(lib1Type.name()), QByteArray(localType.name())); + QCOMPARE(QByteArray(lib2Type.name()), QByteArray(localType.name())); + QCOMPARE(lib1Type, localType); + QCOMPARE(lib2Type, localType); } class WithPrivateDTor { diff --git a/tests/auto/corelib/kernel/qmetatype/tst_qmetatype_libs.h b/tests/auto/corelib/kernel/qmetatype/tst_qmetatype_libs.h new file mode 100644 index 00000000000..908e80f9a88 --- /dev/null +++ b/tests/auto/corelib/kernel/qmetatype/tst_qmetatype_libs.h @@ -0,0 +1,24 @@ +// Copyright (C) 2022 Intel Corporation +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 + +#ifndef TST_QMETATYPE_LIBS_H +#define TST_QMETATYPE_LIBS_H + +#include + +#include // for div_t + +// void: builtin metatype, special +// int: builtin metatype, primitive type +// QString: builtin metatype, class +// QCollator: not builtin, class, Q_CORE_EXPORT +// div_t: not builtin, class, no export +#define FOR_EACH_METATYPE_LIBS(F) \ + F(void, QMetaType::Void) \ + F(int, QMetaType::Int) \ + F(QString, QMetaType::QString) \ + F(QCollator, QMetaType::UnknownType) \ + F(div_t, QMetaType::UnknownType) \ + /**/ + +#endif // TST_QMETATYPE_LIBS_H