mirror of
https://github.com/crystalidea/qt6windows7.git
synced 2025-07-03 07:45:30 +08:00
qt 6.5.1 original
This commit is contained in:
14
tests/auto/corelib/plugin/CMakeLists.txt
Normal file
14
tests/auto/corelib/plugin/CMakeLists.txt
Normal file
@ -0,0 +1,14 @@
|
||||
# Copyright (C) 2022 The Qt Company Ltd.
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
if(QT_BUILD_SHARED_LIBS)
|
||||
add_subdirectory(qfactoryloader)
|
||||
endif()
|
||||
add_subdirectory(quuid)
|
||||
if(QT_FEATURE_library)
|
||||
add_subdirectory(qpluginloader)
|
||||
add_subdirectory(qlibrary)
|
||||
endif()
|
||||
if(QT_BUILD_SHARED_LIBS AND QT_FEATURE_library)
|
||||
add_subdirectory(qplugin)
|
||||
endif()
|
6
tests/auto/corelib/plugin/qfactoryloader/CMakeLists.txt
Normal file
6
tests/auto/corelib/plugin/qfactoryloader/CMakeLists.txt
Normal file
@ -0,0 +1,6 @@
|
||||
# Copyright (C) 2022 The Qt Company Ltd.
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
add_subdirectory(plugin1)
|
||||
add_subdirectory(plugin2)
|
||||
add_subdirectory(test)
|
@ -0,0 +1,31 @@
|
||||
# Copyright (C) 2022 The Qt Company Ltd.
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
#####################################################################
|
||||
## plugin1 Generic Library:
|
||||
#####################################################################
|
||||
|
||||
qt_internal_add_cmake_library(tst_qfactoryloader_plugin1
|
||||
MODULE
|
||||
INSTALL_DIRECTORY "${INSTALL_TESTSDIR}/tst_qfactoryloader/bin"
|
||||
OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/../bin"
|
||||
SOURCES
|
||||
plugin1.cpp plugin1.h
|
||||
LIBRARIES
|
||||
Qt::Core
|
||||
)
|
||||
|
||||
if(ANDROID)
|
||||
# On Android the plugins must match the following mask:
|
||||
# "libplugins_{suffix}_*.so"
|
||||
# and the testcase uses "bin" as a suffix
|
||||
set_target_properties(tst_qfactoryloader_plugin1 PROPERTIES
|
||||
OUTPUT_NAME "plugins_bin_tst_qfactoryloader_plugin1")
|
||||
endif()
|
||||
|
||||
qt_internal_extend_target(tst_qfactoryloader_plugin1 CONDITION NOT QT_FEATURE_library
|
||||
DEFINES
|
||||
QT_STATICPLUGIN
|
||||
)
|
||||
|
||||
qt_autogen_tools_initial_setup(tst_qfactoryloader_plugin1)
|
@ -0,0 +1,9 @@
|
||||
// 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 <QtCore/qstring.h>
|
||||
#include "plugin1.h"
|
||||
|
||||
QString Plugin1::pluginName() const
|
||||
{
|
||||
return QLatin1String("Plugin1 ok");
|
||||
}
|
20
tests/auto/corelib/plugin/qfactoryloader/plugin1/plugin1.h
Normal file
20
tests/auto/corelib/plugin/qfactoryloader/plugin1/plugin1.h
Normal file
@ -0,0 +1,20 @@
|
||||
// Copyright (C) 2016 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
|
||||
#ifndef THEPLUGIN_H
|
||||
#define THEPLUGIN_H
|
||||
|
||||
#include <QtCore/qobject.h>
|
||||
#include <QtCore/qplugin.h>
|
||||
#include "plugininterface1.h"
|
||||
|
||||
class Plugin1 : public QObject, public PluginInterface1
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PLUGIN_METADATA(IID "org.qt-project.Qt.autotests.plugininterface1")
|
||||
Q_INTERFACES(PluginInterface1)
|
||||
|
||||
public:
|
||||
virtual QString pluginName() const override;
|
||||
};
|
||||
|
||||
#endif // THEPLUGIN_H
|
@ -0,0 +1,21 @@
|
||||
// Copyright (C) 2016 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
|
||||
#ifndef PLUGININTERFACE1_H
|
||||
#define PLUGININTERFACE1_H
|
||||
|
||||
#include <QtCore/QtGlobal>
|
||||
|
||||
struct PluginInterface1 {
|
||||
virtual ~PluginInterface1() {}
|
||||
virtual QString pluginName() const = 0;
|
||||
};
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
#define PluginInterface1_iid "org.qt-project.Qt.autotests.plugininterface1"
|
||||
|
||||
Q_DECLARE_INTERFACE(PluginInterface1, PluginInterface1_iid)
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#endif // PLUGININTERFACE1_H
|
@ -0,0 +1,31 @@
|
||||
# Copyright (C) 2022 The Qt Company Ltd.
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
#####################################################################
|
||||
## plugin2 Generic Library:
|
||||
#####################################################################
|
||||
|
||||
qt_internal_add_cmake_library(tst_qfactoryloader_plugin2
|
||||
MODULE
|
||||
INSTALL_DIRECTORY "${INSTALL_TESTSDIR}/tst_qfactoryloader/bin"
|
||||
OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/../bin"
|
||||
SOURCES
|
||||
plugin2.cpp plugin2.h
|
||||
LIBRARIES
|
||||
Qt::Core
|
||||
)
|
||||
|
||||
if(ANDROID)
|
||||
# On Android the plugins must match the following mask:
|
||||
# "libplugins_{suffix}_*.so"
|
||||
# and the testcase uses "bin" as a suffix
|
||||
set_target_properties(tst_qfactoryloader_plugin2 PROPERTIES
|
||||
OUTPUT_NAME "plugins_bin_tst_qfactoryloader_plugin2")
|
||||
endif()
|
||||
|
||||
qt_internal_extend_target(tst_qfactoryloader_plugin2 CONDITION NOT QT_FEATURE_library
|
||||
DEFINES
|
||||
QT_STATICPLUGIN
|
||||
)
|
||||
|
||||
qt_autogen_tools_initial_setup(tst_qfactoryloader_plugin2)
|
@ -0,0 +1,9 @@
|
||||
// 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 <QtCore/qstring.h>
|
||||
#include "plugin2.h"
|
||||
|
||||
QString Plugin2::pluginName() const
|
||||
{
|
||||
return QLatin1String("Plugin2 ok");
|
||||
}
|
20
tests/auto/corelib/plugin/qfactoryloader/plugin2/plugin2.h
Normal file
20
tests/auto/corelib/plugin/qfactoryloader/plugin2/plugin2.h
Normal file
@ -0,0 +1,20 @@
|
||||
// Copyright (C) 2016 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
|
||||
#ifndef THEPLUGIN_H
|
||||
#define THEPLUGIN_H
|
||||
|
||||
#include <QtCore/qobject.h>
|
||||
#include <QtCore/qplugin.h>
|
||||
#include "plugininterface2.h"
|
||||
|
||||
class Plugin2 : public QObject, public PluginInterface2
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PLUGIN_METADATA(IID "org.qt-project.Qt.autotests.plugininterface2")
|
||||
Q_INTERFACES(PluginInterface2)
|
||||
|
||||
public:
|
||||
virtual QString pluginName() const override;
|
||||
};
|
||||
|
||||
#endif // THEPLUGIN_H
|
@ -0,0 +1,21 @@
|
||||
// Copyright (C) 2016 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
|
||||
#ifndef PLUGININTERFACE2_H
|
||||
#define PLUGININTERFACE2_H
|
||||
|
||||
#include <QtCore/QtGlobal>
|
||||
|
||||
struct PluginInterface2 {
|
||||
virtual ~PluginInterface2() {}
|
||||
virtual QString pluginName() const = 0;
|
||||
};
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
#define PluginInterface2_iid "org.qt-project.Qt.autotests.plugininterface2"
|
||||
|
||||
Q_DECLARE_INTERFACE(PluginInterface2, PluginInterface2_iid)
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#endif // PLUGININTERFACE2_H
|
34
tests/auto/corelib/plugin/qfactoryloader/test/CMakeLists.txt
Normal file
34
tests/auto/corelib/plugin/qfactoryloader/test/CMakeLists.txt
Normal file
@ -0,0 +1,34 @@
|
||||
# Copyright (C) 2022 The Qt Company Ltd.
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
#####################################################################
|
||||
## tst_qfactoryloader Test:
|
||||
#####################################################################
|
||||
|
||||
qt_internal_add_test(tst_qfactoryloader
|
||||
OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/../"
|
||||
SOURCES
|
||||
../plugin1/plugininterface1.h
|
||||
../plugin2/plugininterface2.h
|
||||
../tst_qfactoryloader.cpp
|
||||
LIBRARIES
|
||||
Qt::CorePrivate
|
||||
)
|
||||
|
||||
## Scopes:
|
||||
#####################################################################
|
||||
|
||||
qt_internal_extend_target(tst_qfactoryloader CONDITION NOT QT_FEATURE_library
|
||||
LIBRARIES
|
||||
tst_qfactoryloader_plugin1
|
||||
tst_qfactoryloader_plugin2
|
||||
)
|
||||
|
||||
add_dependencies(tst_qfactoryloader tst_qfactoryloader_plugin1 tst_qfactoryloader_plugin2)
|
||||
|
||||
if(ANDROID)
|
||||
# QT_ANDROID_EXTRA_PLUGINS requires a list of directories, not files!
|
||||
set_target_properties(tst_qfactoryloader PROPERTIES
|
||||
QT_ANDROID_EXTRA_PLUGINS "${CMAKE_CURRENT_BINARY_DIR}/../bin"
|
||||
)
|
||||
endif()
|
113
tests/auto/corelib/plugin/qfactoryloader/tst_qfactoryloader.cpp
Normal file
113
tests/auto/corelib/plugin/qfactoryloader/tst_qfactoryloader.cpp
Normal file
@ -0,0 +1,113 @@
|
||||
// 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 <QtTest/qtest.h>
|
||||
#include <QtCore/qdir.h>
|
||||
#include <QtCore/qfileinfo.h>
|
||||
#include <QtCore/qplugin.h>
|
||||
#include <private/qfactoryloader_p.h>
|
||||
#include "plugin1/plugininterface1.h"
|
||||
#include "plugin2/plugininterface2.h"
|
||||
|
||||
#if !QT_CONFIG(library)
|
||||
Q_IMPORT_PLUGIN(Plugin1)
|
||||
Q_IMPORT_PLUGIN(Plugin2)
|
||||
#endif
|
||||
|
||||
class tst_QFactoryLoader : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
#ifdef Q_OS_ANDROID
|
||||
QSharedPointer<QTemporaryDir> directory;
|
||||
#endif
|
||||
|
||||
QString binFolder;
|
||||
public slots:
|
||||
void initTestCase();
|
||||
|
||||
private slots:
|
||||
void usingTwoFactoriesFromSameDir();
|
||||
void extraSearchPath();
|
||||
};
|
||||
|
||||
static const char binFolderC[] = "bin";
|
||||
|
||||
void tst_QFactoryLoader::initTestCase()
|
||||
{
|
||||
// On Android the plugins are bundled into APK's libs subdir
|
||||
#ifndef Q_OS_ANDROID
|
||||
binFolder = QFINDTESTDATA(binFolderC);
|
||||
QVERIFY2(!binFolder.isEmpty(), "Unable to locate 'bin' folder");
|
||||
#endif
|
||||
}
|
||||
|
||||
void tst_QFactoryLoader::usingTwoFactoriesFromSameDir()
|
||||
{
|
||||
#if QT_CONFIG(library) && !defined(Q_OS_ANDROID)
|
||||
// set the library path to contain the directory where the 'bin' dir is located
|
||||
QCoreApplication::setLibraryPaths( { QFileInfo(binFolder).absolutePath() });
|
||||
#endif
|
||||
|
||||
const QString suffix = QLatin1Char('/') + QLatin1String(binFolderC);
|
||||
QFactoryLoader loader1(PluginInterface1_iid, suffix);
|
||||
|
||||
PluginInterface1 *plugin1 = qobject_cast<PluginInterface1 *>(loader1.instance(0));
|
||||
QVERIFY2(plugin1,
|
||||
qPrintable(QString::fromLatin1("Cannot load plugin '%1'")
|
||||
.arg(QLatin1String(PluginInterface1_iid))));
|
||||
|
||||
QFactoryLoader loader2(PluginInterface2_iid, suffix);
|
||||
|
||||
PluginInterface2 *plugin2 = qobject_cast<PluginInterface2 *>(loader2.instance(0));
|
||||
QVERIFY2(plugin2,
|
||||
qPrintable(QString::fromLatin1("Cannot load plugin '%1'")
|
||||
.arg(QLatin1String(PluginInterface2_iid))));
|
||||
|
||||
QCOMPARE(plugin1->pluginName(), QLatin1String("Plugin1 ok"));
|
||||
QCOMPARE(plugin2->pluginName(), QLatin1String("Plugin2 ok"));
|
||||
}
|
||||
|
||||
void tst_QFactoryLoader::extraSearchPath()
|
||||
{
|
||||
#if defined(Q_OS_ANDROID) && !QT_CONFIG(library)
|
||||
QSKIP("Test not applicable in this configuration.");
|
||||
#else
|
||||
#ifdef Q_OS_ANDROID
|
||||
// On Android the libs are not stored in binFolder, but bundled into
|
||||
// APK's libs subdir
|
||||
const QStringList androidLibsPaths = QCoreApplication::libraryPaths();
|
||||
QCOMPARE(androidLibsPaths.size(), 1);
|
||||
#endif
|
||||
QCoreApplication::setLibraryPaths(QStringList());
|
||||
|
||||
#ifndef Q_OS_ANDROID
|
||||
QString pluginsPath = QFileInfo(binFolder).absoluteFilePath();
|
||||
QFactoryLoader loader1(PluginInterface1_iid, "/nonexistent");
|
||||
#else
|
||||
QString pluginsPath = androidLibsPaths.first();
|
||||
// On Android we still need to specify a valid suffix, because it's a part
|
||||
// of a file name, not directory structure
|
||||
const QString suffix = QLatin1Char('/') + QLatin1String(binFolderC);
|
||||
QFactoryLoader loader1(PluginInterface1_iid, suffix);
|
||||
#endif
|
||||
|
||||
// it shouldn't have scanned anything because we haven't given it a path yet
|
||||
QVERIFY(loader1.metaData().isEmpty());
|
||||
|
||||
loader1.setExtraSearchPath(pluginsPath);
|
||||
PluginInterface1 *plugin1 = qobject_cast<PluginInterface1 *>(loader1.instance(0));
|
||||
QVERIFY2(plugin1,
|
||||
qPrintable(QString::fromLatin1("Cannot load plugin '%1'")
|
||||
.arg(QLatin1String(PluginInterface1_iid))));
|
||||
|
||||
QCOMPARE(plugin1->pluginName(), QLatin1String("Plugin1 ok"));
|
||||
|
||||
// check that it forgets that plugin
|
||||
loader1.setExtraSearchPath(QString());
|
||||
QVERIFY(loader1.metaData().isEmpty());
|
||||
#endif
|
||||
}
|
||||
|
||||
QTEST_MAIN(tst_QFactoryLoader)
|
||||
#include "tst_qfactoryloader.moc"
|
6
tests/auto/corelib/plugin/qlibrary/CMakeLists.txt
Normal file
6
tests/auto/corelib/plugin/qlibrary/CMakeLists.txt
Normal file
@ -0,0 +1,6 @@
|
||||
# Copyright (C) 2022 The Qt Company Ltd.
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
add_subdirectory(lib)
|
||||
add_subdirectory(lib2)
|
||||
add_subdirectory(tst)
|
75
tests/auto/corelib/plugin/qlibrary/lib/CMakeLists.txt
Normal file
75
tests/auto/corelib/plugin/qlibrary/lib/CMakeLists.txt
Normal file
@ -0,0 +1,75 @@
|
||||
# Copyright (C) 2022 The Qt Company Ltd.
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
#####################################################################
|
||||
## mylib Generic Library:
|
||||
#####################################################################
|
||||
|
||||
qt_internal_add_cmake_library(mylib
|
||||
SHARED
|
||||
INSTALL_DIRECTORY "${INSTALL_TESTSDIR}/tst_qlibrary"
|
||||
SOURCES
|
||||
mylib.c
|
||||
LIBRARIES
|
||||
Qt::Core
|
||||
)
|
||||
|
||||
set_target_properties(mylib PROPERTIES
|
||||
VERSION 1.0.0
|
||||
SOVERSION 1
|
||||
C_VISIBILITY_PRESET "default"
|
||||
CXX_VISIBILITY_PRESET "default"
|
||||
)
|
||||
|
||||
if(WIN32)
|
||||
# CMake sets for Windows-GNU platforms the suffix "lib"
|
||||
set_property(TARGET mylib PROPERTY PREFIX "")
|
||||
endif()
|
||||
|
||||
if(UNIX)
|
||||
if(APPLE)
|
||||
add_custom_command(TARGET mylib POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
||||
$<TARGET_FILE:mylib>
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/../libmylib.1.0.0.dylib"
|
||||
COMMAND ${CMAKE_COMMAND} -E create_symlink
|
||||
"libmylib.1.0.0.dylib"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/../libmylib.1.dylib"
|
||||
VERBATIM)
|
||||
elseif(NOT ANDROID)
|
||||
add_custom_command(TARGET mylib POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
||||
$<TARGET_FILE:mylib>
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/../libmylib.so.1.0.0"
|
||||
COMMAND ${CMAKE_COMMAND} -E create_symlink
|
||||
"libmylib.so.1.0.0"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/../libmylib.so.1"
|
||||
COMMAND ${CMAKE_COMMAND} -E create_symlink
|
||||
"libmylib.so.1.0.0"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/../libmylib.so1"
|
||||
VERBATIM)
|
||||
else()
|
||||
# Android does not use symlinks. Also, according to our conventions,
|
||||
# libraries on Android MUST be named in the following pattern:
|
||||
# lib*.so
|
||||
add_custom_command(TARGET mylib POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
||||
$<TARGET_FILE:mylib>
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/../libmylib.so"
|
||||
VERBATIM)
|
||||
endif()
|
||||
else() #Win32
|
||||
add_custom_command(TARGET mylib POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
||||
$<TARGET_FILE:mylib>
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/../mylib.dll"
|
||||
VERBATIM)
|
||||
endif()
|
||||
|
||||
## Scopes:
|
||||
#####################################################################
|
||||
|
||||
qt_internal_extend_target(mylib CONDITION MSVC
|
||||
DEFINES
|
||||
WIN32_MSVC
|
||||
)
|
22
tests/auto/corelib/plugin/qlibrary/lib/mylib.c
Normal file
22
tests/auto/corelib/plugin/qlibrary/lib/mylib.c
Normal file
@ -0,0 +1,22 @@
|
||||
// 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 <qglobal.h>
|
||||
|
||||
#if defined(Q_CC_MSVC) || defined(Q_CC_MSVC_NET) || defined(Q_CC_BOR)
|
||||
#define LIB_EXPORT __declspec(dllexport)
|
||||
#else
|
||||
#define LIB_EXPORT
|
||||
#endif
|
||||
|
||||
#if defined(Q_CC_BOR)
|
||||
# define BORLAND_STDCALL __stdcall
|
||||
#else
|
||||
# define BORLAND_STDCALL
|
||||
#endif
|
||||
|
||||
LIB_EXPORT int BORLAND_STDCALL mylibversion()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
110
tests/auto/corelib/plugin/qlibrary/lib2/CMakeLists.txt
Normal file
110
tests/auto/corelib/plugin/qlibrary/lib2/CMakeLists.txt
Normal file
@ -0,0 +1,110 @@
|
||||
# Copyright (C) 2022 The Qt Company Ltd.
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
#####################################################################
|
||||
## mylib Generic Library:
|
||||
#####################################################################
|
||||
|
||||
qt_internal_add_cmake_library(mylib2
|
||||
SHARED
|
||||
INSTALL_DIRECTORY "${INSTALL_TESTSDIR}tst_qlibrary"
|
||||
#OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/../"
|
||||
SOURCES
|
||||
mylib.c
|
||||
LIBRARIES
|
||||
Qt::Core
|
||||
)
|
||||
|
||||
# This test is very "annoying" to get working with CMake as it involves having
|
||||
# two targets with the same name on the parent scope, which is not possible with
|
||||
# CMake. Furthermore, on UNIX, this version of the library should override the
|
||||
# root symlink (libmylib.so) to point to version 2.
|
||||
# Since we can't build two targets with the same name and in the same directory,
|
||||
# we build mylib2 in it's own directory and manually copy and create the
|
||||
# symlinks in the parent directory.
|
||||
# Finally we also need to create a libmylib.so2 file in the parent directory.
|
||||
#
|
||||
set_target_properties(mylib2 PROPERTIES
|
||||
OUTPUT_NAME mylib
|
||||
)
|
||||
set_target_properties(mylib2 PROPERTIES
|
||||
VERSION 2.0.0
|
||||
SOVERSION 2
|
||||
C_VISIBILITY_PRESET "default"
|
||||
CXX_VISIBILITY_PRESET "default"
|
||||
)
|
||||
|
||||
if(WIN32)
|
||||
# CMake sets for Windows-GNU platforms the suffix "lib"
|
||||
set_property(TARGET mylib2 PROPERTY PREFIX "")
|
||||
endif()
|
||||
|
||||
if(UNIX)
|
||||
if(APPLE)
|
||||
add_custom_command(TARGET mylib2 POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
||||
$<TARGET_FILE:mylib2>
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/../system.qt.test.mylib.so.dylib"
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
||||
$<TARGET_FILE:mylib2>
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/../libmylib.2.0.0.dylib"
|
||||
COMMAND ${CMAKE_COMMAND} -E create_symlink
|
||||
"libmylib.2.0.0.dylib"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/../libmylib.2.dylib"
|
||||
COMMAND ${CMAKE_COMMAND} -E remove
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/../libmylib.dylib"
|
||||
COMMAND ${CMAKE_COMMAND} -E create_symlink
|
||||
"libmylib.2.0.0.dylib"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/../libmylib.dylib"
|
||||
COMMAND ${CMAKE_COMMAND} -E create_symlink
|
||||
"libmylib.2.0.0.dylib"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/../libmylib.so2.dylib"
|
||||
VERBATIM)
|
||||
elseif(NOT ANDROID)
|
||||
add_custom_command(TARGET mylib2 POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
||||
$<TARGET_FILE:mylib2>
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/../system.qt.test.mylib.so"
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
||||
$<TARGET_FILE:mylib2>
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/../libmylib.so.2.0.0"
|
||||
COMMAND ${CMAKE_COMMAND} -E create_symlink
|
||||
"libmylib.so.2.0.0"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/../libmylib.so.2"
|
||||
COMMAND ${CMAKE_COMMAND} -E remove
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/../libmylib.so"
|
||||
COMMAND ${CMAKE_COMMAND} -E create_symlink
|
||||
"libmylib.so.2.0.0"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/../libmylib.so"
|
||||
COMMAND ${CMAKE_COMMAND} -E create_symlink
|
||||
"libmylib.so.2.0.0"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/../libmylib.so2"
|
||||
VERBATIM)
|
||||
else()
|
||||
# Android does not use symlinks. Also, according to our conventions,
|
||||
# libraries on Android MUST be named in the following pattern:
|
||||
# lib*.so
|
||||
add_custom_command(TARGET mylib2 POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
||||
$<TARGET_FILE:mylib2>
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/../libsystem.qt.test.mylib.so"
|
||||
VERBATIM)
|
||||
endif()
|
||||
else() #Win32
|
||||
add_custom_command(TARGET mylib2 POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
||||
$<TARGET_FILE:mylib2>
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/../system.qt.test.mylib.dll"
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
||||
$<TARGET_FILE:mylib2>
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/../mylib.dl2"
|
||||
VERBATIM)
|
||||
endif()
|
||||
|
||||
## Scopes:
|
||||
#####################################################################
|
||||
|
||||
qt_internal_extend_target(mylib2 CONDITION MSVC
|
||||
DEFINES
|
||||
WIN32_MSVC
|
||||
)
|
22
tests/auto/corelib/plugin/qlibrary/lib2/mylib.c
Normal file
22
tests/auto/corelib/plugin/qlibrary/lib2/mylib.c
Normal file
@ -0,0 +1,22 @@
|
||||
// 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 <qglobal.h>
|
||||
|
||||
#if defined(Q_CC_MSVC) || defined(Q_CC_MSVC_NET) || defined(Q_CC_BOR)
|
||||
#define LIB_EXPORT __declspec(dllexport)
|
||||
#else
|
||||
#define LIB_EXPORT
|
||||
#endif
|
||||
|
||||
#if defined(Q_CC_BOR)
|
||||
# define BORLAND_STDCALL __stdcall
|
||||
#else
|
||||
# define BORLAND_STDCALL
|
||||
#endif
|
||||
|
||||
LIB_EXPORT int BORLAND_STDCALL mylibversion()
|
||||
{
|
||||
return 2;
|
||||
}
|
||||
|
@ -0,0 +1 @@
|
||||
This should be an invalid shared object file.
|
28
tests/auto/corelib/plugin/qlibrary/tst/CMakeLists.txt
Normal file
28
tests/auto/corelib/plugin/qlibrary/tst/CMakeLists.txt
Normal file
@ -0,0 +1,28 @@
|
||||
# Copyright (C) 2022 The Qt Company Ltd.
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
#####################################################################
|
||||
## tst_qlibrary Test:
|
||||
#####################################################################
|
||||
|
||||
# Collect test data
|
||||
list(APPEND test_data "../library_path/invalid.so")
|
||||
|
||||
qt_internal_add_test(tst_qlibrary
|
||||
OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/../"
|
||||
SOURCES
|
||||
../tst_qlibrary.cpp
|
||||
TESTDATA ${test_data}
|
||||
LIBRARIES mylib mylib2
|
||||
)
|
||||
|
||||
add_dependencies(tst_qlibrary mylib mylib2)
|
||||
|
||||
if(ANDROID)
|
||||
list(APPEND extra_libs
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/../libmylib.so")
|
||||
list(APPEND extra_libs
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/../libsystem.qt.test.mylib.so")
|
||||
set_target_properties(tst_qlibrary PROPERTIES
|
||||
QT_ANDROID_EXTRA_LIBS "${extra_libs}")
|
||||
endif()
|
682
tests/auto/corelib/plugin/qlibrary/tst_qlibrary.cpp
Normal file
682
tests/auto/corelib/plugin/qlibrary/tst_qlibrary.cpp
Normal file
@ -0,0 +1,682 @@
|
||||
// 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 <QTest>
|
||||
#include <qdir.h>
|
||||
#include <qlibrary.h>
|
||||
#include <QtCore/QRegularExpression>
|
||||
|
||||
|
||||
// Helper macros to let us know if some suffixes and prefixes are valid
|
||||
#define bundle_VALID false
|
||||
#define dylib_VALID false
|
||||
#define sl_VALID false
|
||||
#define a_VALID false
|
||||
#define so_VALID false
|
||||
#define dll_VALID false
|
||||
#define DLL_VALID false
|
||||
|
||||
#if defined(Q_OS_DARWIN)
|
||||
# undef bundle_VALID
|
||||
# undef dylib_VALID
|
||||
# undef so_VALID
|
||||
# define bundle_VALID true
|
||||
# define dylib_VALID true
|
||||
# define so_VALID true
|
||||
# define SUFFIX ".dylib"
|
||||
# define PREFIX "lib"
|
||||
|
||||
#elif defined(Q_OS_HPUX)
|
||||
# undef sl_VALID
|
||||
# define sl_VALID true
|
||||
# ifndef __ia64
|
||||
# define SUFFIX ".sl"
|
||||
# define PREFIX "lib"
|
||||
# else
|
||||
# undef so_VALID
|
||||
# define so_VALID true
|
||||
# define SUFFIX ".so"
|
||||
# define PREFIX "lib"
|
||||
# endif
|
||||
|
||||
#elif defined(Q_OS_AIX)
|
||||
# undef a_VALID
|
||||
# undef so_VALID
|
||||
# define a_VALID true
|
||||
# define so_VALID true
|
||||
# define SUFFIX ".a"
|
||||
# define PREFIX "lib"
|
||||
|
||||
#elif defined(Q_OS_WIN)
|
||||
# undef dll_VALID
|
||||
# define dll_VALID true
|
||||
# undef DLL_VALID
|
||||
# define DLL_VALID true
|
||||
# define SUFFIX ".dll"
|
||||
# define PREFIX ""
|
||||
|
||||
#else // all other Unix
|
||||
# undef so_VALID
|
||||
# define so_VALID true
|
||||
# define SUFFIX ".so"
|
||||
# define PREFIX "lib"
|
||||
#endif
|
||||
|
||||
QT_FORWARD_DECLARE_CLASS(QLibrary)
|
||||
class tst_QLibrary : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
enum QLibraryOperation {
|
||||
Load = 1,
|
||||
Unload = 2,
|
||||
Resolve = 3,
|
||||
OperationMask = 7,
|
||||
DontSetFileName = 0x100
|
||||
};
|
||||
|
||||
QString sys_qualifiedLibraryName(const QString &fileName);
|
||||
|
||||
QString directory;
|
||||
private slots:
|
||||
void initTestCase();
|
||||
void cleanup();
|
||||
|
||||
void load_data();
|
||||
void load();
|
||||
void resolve_data();
|
||||
void resolve();
|
||||
void unload_data();
|
||||
void unload();
|
||||
void unload_after_implicit_load();
|
||||
void setFilenameAfterFailedLoad();
|
||||
void loadAfterFailedLoad();
|
||||
void isLibrary_data();
|
||||
void isLibrary();
|
||||
void version_data();
|
||||
void version();
|
||||
void loadTwoVersions();
|
||||
void setFileNameAndVersionTwice();
|
||||
void setFileNameAndVersionAfterFailedLoad_data() { version_data(); }
|
||||
void setFileNameAndVersionAfterFailedLoad();
|
||||
void errorString_data();
|
||||
void errorString();
|
||||
void loadHints();
|
||||
void loadHints_data();
|
||||
void fileName_data();
|
||||
void fileName();
|
||||
void multipleInstancesForOneLibrary();
|
||||
};
|
||||
|
||||
QString tst_QLibrary::sys_qualifiedLibraryName(const QString &fileName)
|
||||
{
|
||||
return directory + QLatin1Char('/') + PREFIX + fileName + SUFFIX;
|
||||
}
|
||||
|
||||
typedef int (*VersionFunction)(void);
|
||||
|
||||
void tst_QLibrary::initTestCase()
|
||||
{
|
||||
#ifdef Q_OS_ANDROID
|
||||
const QStringList paths = QCoreApplication::libraryPaths();
|
||||
QVERIFY(!paths.isEmpty());
|
||||
directory = paths.first();
|
||||
#else
|
||||
// chdir to our testdata directory, and use relative paths in some tests.
|
||||
QString testdatadir = QFileInfo(QFINDTESTDATA("library_path")).absolutePath();
|
||||
QVERIFY2(QDir::setCurrent(testdatadir), qPrintable("Could not chdir to " + testdatadir));
|
||||
directory = QCoreApplication::applicationDirPath();
|
||||
#endif
|
||||
}
|
||||
|
||||
void tst_QLibrary::cleanup()
|
||||
{
|
||||
// unload the libraries, if they are still loaded after the test ended
|
||||
// (probably in a failure)
|
||||
|
||||
static struct {
|
||||
QString name;
|
||||
int version = -1;
|
||||
} libs[] = {
|
||||
{ directory + "/mylib" },
|
||||
{ directory + "/mylib", 1 },
|
||||
{ directory + "/mylib", 2 },
|
||||
{ sys_qualifiedLibraryName("mylib") },
|
||||
|
||||
// stuff that load_data() succeeds with
|
||||
{ directory + "/" PREFIX "mylib" },
|
||||
{ directory + "/" PREFIX "mylib" SUFFIX },
|
||||
#if defined(Q_OS_WIN32)
|
||||
{ directory + "/mylib.dl2" },
|
||||
{ directory + "/system.qt.test.mylib.dll" },
|
||||
#elif !defined(Q_OS_ANDROID)
|
||||
// .so even on macOS
|
||||
{ directory + "/libmylib.so2" },
|
||||
{ directory + "/system.qt.test.mylib.so" },
|
||||
#endif
|
||||
|
||||
};
|
||||
for (const auto &entry : libs) {
|
||||
do {} while (QLibrary(entry.name, entry.version).unload());
|
||||
}
|
||||
}
|
||||
|
||||
void tst_QLibrary::version_data()
|
||||
{
|
||||
#ifdef Q_OS_ANDROID
|
||||
QSKIP("Versioned .so files are not generated for Android, so this test is not applicable.");
|
||||
#endif
|
||||
QTest::addColumn<QString>("lib");
|
||||
QTest::addColumn<int>("loadversion");
|
||||
QTest::addColumn<int>("resultversion");
|
||||
|
||||
QTest::newRow( "ok00, version 1" ) << "mylib" << 1 << 1;
|
||||
QTest::newRow( "ok00, version 2" ) << "mylib" << 2 << 2;
|
||||
QTest::newRow( "ok00, load without version" ) << "mylib" << -1 << 2;
|
||||
}
|
||||
|
||||
void tst_QLibrary::version()
|
||||
{
|
||||
QFETCH( QString, lib );
|
||||
QFETCH( int, loadversion );
|
||||
QFETCH( int, resultversion );
|
||||
|
||||
#if !defined(Q_OS_AIX) && !defined(Q_OS_WIN)
|
||||
QString appDir = directory;
|
||||
QLibrary library( appDir + QLatin1Char('/') + lib, loadversion );
|
||||
QVERIFY2(library.load(), qPrintable(library.errorString()));
|
||||
|
||||
VersionFunction fnVersion = (VersionFunction)library.resolve("mylibversion");
|
||||
QVERIFY(fnVersion);
|
||||
QCOMPARE(fnVersion(), resultversion);
|
||||
QVERIFY2(library.unload(), qPrintable(library.errorString()));
|
||||
#else
|
||||
Q_UNUSED(lib);
|
||||
Q_UNUSED(loadversion);
|
||||
Q_UNUSED(resultversion);
|
||||
#endif
|
||||
}
|
||||
|
||||
void tst_QLibrary::loadTwoVersions()
|
||||
{
|
||||
#if defined(Q_OS_ANDROID) || defined(Q_OS_WIN)
|
||||
QSKIP("Versioned files are not generated for this OS, so this test is not applicable.");
|
||||
#endif
|
||||
|
||||
QLibrary lib1(directory + "/mylib", 1);
|
||||
QLibrary lib2(directory + "/mylib", 2);
|
||||
QVERIFY(!lib1.isLoaded());
|
||||
QVERIFY(!lib2.isLoaded());
|
||||
|
||||
// load the first one
|
||||
QVERIFY(lib1.load());
|
||||
QVERIFY(lib1.isLoaded());
|
||||
|
||||
// let's see if we can load the second one too
|
||||
QVERIFY(lib2.load());
|
||||
QVERIFY(lib2.isLoaded());
|
||||
|
||||
auto p1 = (VersionFunction)lib1.resolve("mylibversion");
|
||||
QVERIFY(p1);
|
||||
|
||||
auto p2 = (VersionFunction)lib2.resolve("mylibversion");
|
||||
QVERIFY(p2);
|
||||
|
||||
QCOMPARE_NE(p1(), p2());
|
||||
|
||||
lib2.unload();
|
||||
lib1.unload();
|
||||
}
|
||||
|
||||
void tst_QLibrary::setFileNameAndVersionTwice()
|
||||
{
|
||||
#if defined(Q_OS_ANDROID) || defined(Q_OS_WIN)
|
||||
QSKIP("Versioned files are not generated for this OS, so this test is not applicable.");
|
||||
#endif
|
||||
|
||||
QLibrary library(directory + "/mylib", 1);
|
||||
QVERIFY(library.load());
|
||||
QVERIFY(library.isLoaded());
|
||||
|
||||
auto p1 = (VersionFunction)library.resolve("mylibversion");
|
||||
QVERIFY(p1);
|
||||
// don't .unload()
|
||||
|
||||
library.setFileNameAndVersion(directory + "/mylib", 2);
|
||||
QVERIFY(!library.isLoaded());
|
||||
QVERIFY(library.load());
|
||||
QVERIFY(library.isLoaded());
|
||||
|
||||
auto p2 = (VersionFunction)library.resolve("mylibversion");
|
||||
QVERIFY(p2);
|
||||
QCOMPARE_NE(p1(), p2());
|
||||
|
||||
QVERIFY(library.unload());
|
||||
QVERIFY(!library.isLoaded());
|
||||
|
||||
// set back
|
||||
library.setFileNameAndVersion(directory + "/mylib", 1);
|
||||
QVERIFY(library.isLoaded());
|
||||
QVERIFY(library.unload());
|
||||
QVERIFY(!library.isLoaded());
|
||||
}
|
||||
|
||||
void tst_QLibrary::load_data()
|
||||
{
|
||||
QTest::addColumn<QString>("lib");
|
||||
QTest::addColumn<bool>("result");
|
||||
|
||||
QString appDir = directory;
|
||||
|
||||
QTest::newRow( "ok00" ) << appDir + "/mylib" << true;
|
||||
QTest::newRow( "notexist" ) << appDir + "/nolib" << false;
|
||||
QTest::newRow( "badlibrary" ) << appDir + "/qlibrary.pro" << false;
|
||||
|
||||
#ifdef Q_OS_MAC
|
||||
QTest::newRow("ok (libmylib ver. 1)") << appDir + "/libmylib" <<true;
|
||||
#endif
|
||||
|
||||
# if defined(Q_OS_WIN32)
|
||||
QTest::newRow( "ok01 (with suffix)" ) << appDir + "/mylib.dll" << true;
|
||||
QTest::newRow( "ok02 (with non-standard suffix)" ) << appDir + "/mylib.dl2" << true;
|
||||
QTest::newRow( "ok03 (with many dots)" ) << appDir + "/system.qt.test.mylib.dll" << true;
|
||||
# elif defined Q_OS_UNIX
|
||||
QTest::newRow( "ok01 (with suffix)" ) << appDir + "/libmylib" SUFFIX << true;
|
||||
#ifndef Q_OS_ANDROID
|
||||
// We do not support non-standard suffixes on Android
|
||||
QTest::newRow( "ok02 (with non-standard suffix)" ) << appDir + "/libmylib.so2" << true;
|
||||
#endif
|
||||
QTest::newRow( "ok03 (with many dots)" ) << appDir + "/system.qt.test.mylib.so" << true;
|
||||
# endif // Q_OS_UNIX
|
||||
}
|
||||
|
||||
void tst_QLibrary::load()
|
||||
{
|
||||
QFETCH( QString, lib );
|
||||
QFETCH( bool, result );
|
||||
|
||||
QLibrary library( lib );
|
||||
bool ok = library.load();
|
||||
if ( result ) {
|
||||
QVERIFY2( ok, qPrintable(library.errorString()) );
|
||||
QVERIFY2( library.unload(), qPrintable(library.errorString()) );
|
||||
} else {
|
||||
QVERIFY( !ok );
|
||||
}
|
||||
}
|
||||
|
||||
void tst_QLibrary::unload_data()
|
||||
{
|
||||
QTest::addColumn<QString>("lib");
|
||||
QTest::addColumn<bool>("result");
|
||||
|
||||
QString appDir = directory;
|
||||
|
||||
QTest::newRow( "mylib" ) << appDir + "/mylib" << true;
|
||||
QTest::newRow( "ok01" ) << appDir + "/nolib" << false;
|
||||
}
|
||||
|
||||
void tst_QLibrary::unload()
|
||||
{
|
||||
QFETCH( QString, lib );
|
||||
QFETCH( bool, result );
|
||||
|
||||
QLibrary library( lib );
|
||||
library.load();
|
||||
bool ok = library.unload();
|
||||
if ( result ) {
|
||||
QVERIFY2( ok, qPrintable(library.errorString()) );
|
||||
} else {
|
||||
QVERIFY( !ok );
|
||||
}
|
||||
}
|
||||
|
||||
void tst_QLibrary::unload_after_implicit_load()
|
||||
{
|
||||
QLibrary library( directory + "/mylib" );
|
||||
QFunctionPointer p = library.resolve("mylibversion");
|
||||
QVERIFY(p); // Check if it was loaded
|
||||
QVERIFY(library.isLoaded());
|
||||
QVERIFY(library.unload());
|
||||
QCOMPARE(library.isLoaded(), false);
|
||||
}
|
||||
|
||||
void tst_QLibrary::setFilenameAfterFailedLoad()
|
||||
{
|
||||
#if defined(Q_OS_WIN) || defined(Q_OS_ANDROID)
|
||||
QSKIP("### FIXME: The helper libraries are currently messed up in the CMakeLists.txt");
|
||||
#endif
|
||||
|
||||
QLibrary library(directory + "/nolib");
|
||||
QVERIFY(!library.load());
|
||||
QVERIFY(!library.isLoaded());
|
||||
QVERIFY(!library.load());
|
||||
QVERIFY(!library.isLoaded());
|
||||
|
||||
library.setFileName(directory + "/mylib");
|
||||
QVERIFY(library.load());
|
||||
QVERIFY(library.isLoaded());
|
||||
auto p = (VersionFunction)library.resolve("mylibversion");
|
||||
QVERIFY(p);
|
||||
QCOMPARE(p(), 2);
|
||||
library.unload();
|
||||
}
|
||||
|
||||
void tst_QLibrary::setFileNameAndVersionAfterFailedLoad()
|
||||
{
|
||||
QLibrary library(directory + "/nolib");
|
||||
QVERIFY(!library.load());
|
||||
QVERIFY(!library.isLoaded());
|
||||
QVERIFY(!library.load());
|
||||
QVERIFY(!library.isLoaded());
|
||||
|
||||
#if !defined(Q_OS_AIX) && !defined(Q_OS_WIN)
|
||||
QFETCH(QString, lib);
|
||||
QFETCH(int, loadversion);
|
||||
QFETCH(int, resultversion);
|
||||
|
||||
library.setFileNameAndVersion(directory + '/' + lib, loadversion);
|
||||
QVERIFY(library.load());
|
||||
QVERIFY(library.isLoaded());
|
||||
auto p = (VersionFunction)library.resolve("mylibversion");
|
||||
QVERIFY(p);
|
||||
QCOMPARE(p(), resultversion);
|
||||
library.unload();
|
||||
#endif
|
||||
}
|
||||
|
||||
void tst_QLibrary::loadAfterFailedLoad()
|
||||
{
|
||||
#if defined(Q_OS_WIN) || defined(Q_OS_ANDROID)
|
||||
QSKIP("### FIXME: The helper libraries are currently messed up in the CMakeLists.txt");
|
||||
#endif
|
||||
|
||||
QTemporaryDir dir;
|
||||
QLibrary library(dir.path() + "/mylib");
|
||||
QVERIFY(!library.load());
|
||||
QVERIFY(!library.isLoaded());
|
||||
QVERIFY(!library.load());
|
||||
QVERIFY(!library.isLoaded());
|
||||
|
||||
// now copy the actual lib file into our dir
|
||||
QString actualLib = PREFIX "mylib" SUFFIX;
|
||||
QVERIFY(QFile::copy(directory + '/' + actualLib, dir.filePath(actualLib)));
|
||||
|
||||
// try again, must succeed now
|
||||
QVERIFY(library.load());
|
||||
QVERIFY(library.isLoaded());
|
||||
auto p = (VersionFunction)library.resolve("mylibversion");
|
||||
QVERIFY(p);
|
||||
QCOMPARE(p(), 2);
|
||||
library.unload();
|
||||
}
|
||||
|
||||
void tst_QLibrary::resolve_data()
|
||||
{
|
||||
QTest::addColumn<QString>("lib");
|
||||
QTest::addColumn<QString>("symbol");
|
||||
QTest::addColumn<bool>("goodPointer");
|
||||
|
||||
QString appDir = directory;
|
||||
|
||||
QTest::newRow( "ok00" ) << appDir + "/mylib" << QString("mylibversion") << true;
|
||||
QTest::newRow( "bad00" ) << appDir + "/mylib" << QString("nosym") << false;
|
||||
QTest::newRow( "bad01" ) << appDir + "/nolib" << QString("nosym") << false;
|
||||
}
|
||||
|
||||
void tst_QLibrary::resolve()
|
||||
{
|
||||
typedef int (*testFunc)();
|
||||
QFETCH( QString, lib );
|
||||
QFETCH( QString, symbol );
|
||||
QFETCH( bool, goodPointer );
|
||||
|
||||
QLibrary library( lib );
|
||||
testFunc func = (testFunc) library.resolve( symbol.toLatin1() );
|
||||
if ( goodPointer ) {
|
||||
QVERIFY( func != 0 );
|
||||
} else {
|
||||
QVERIFY( func == 0 );
|
||||
}
|
||||
library.unload();
|
||||
}
|
||||
|
||||
void tst_QLibrary::isLibrary_data()
|
||||
{
|
||||
QTest::addColumn<QString>("filename");
|
||||
QTest::addColumn<bool>("valid");
|
||||
|
||||
// use the macros #defined at the top of the file
|
||||
QTest::newRow("bad") << QString("mylib.bad") << false;
|
||||
QTest::newRow(".a") << QString("mylib.a") << a_VALID;
|
||||
QTest::newRow(".bundle") << QString("mylib.bundle") << bundle_VALID;
|
||||
QTest::newRow(".dll") << QString("mylib.dll") << dll_VALID;
|
||||
QTest::newRow(".DLL") << QString("MYLIB.DLL") << DLL_VALID;
|
||||
QTest::newRow(".dl2" ) << QString("mylib.dl2") << false;
|
||||
QTest::newRow(".dylib") << QString("mylib.dylib") << dylib_VALID;
|
||||
QTest::newRow(".sl") << QString("mylib.sl") << sl_VALID;
|
||||
QTest::newRow(".so") << QString("mylib.so") << so_VALID;
|
||||
QTest::newRow(".so+version") << QString("mylib.so.0") << so_VALID;
|
||||
QTest::newRow("version+.so") << QString("libc-2.7.so") << so_VALID;
|
||||
QTest::newRow("version+.so+version") << QString("liboil-0.3.so.0.1.0") << so_VALID;
|
||||
|
||||
// special tests:
|
||||
#ifdef Q_OS_MAC
|
||||
QTest::newRow("good (libmylib.1.0.0.dylib)") << QString("libmylib.1.0.0.dylib") << true;
|
||||
QTest::newRow("good (libmylib.dylib)") << QString("libmylib.dylib") << true;
|
||||
QTest::newRow("good (libmylib.so)") << QString("libmylib.so") << true;
|
||||
QTest::newRow("good (libmylib.so.1.0.0)") << QString("libmylib.so.1.0.0") << true;
|
||||
|
||||
QTest::newRow("bad (libmylib.1.0.0.foo)") << QString("libmylib.1.0.0.foo") << false;
|
||||
#elif defined(Q_OS_WIN)
|
||||
QTest::newRow("good (with many dots)" ) << "/system.qt.test.mylib.dll" << true;
|
||||
#endif
|
||||
}
|
||||
|
||||
void tst_QLibrary::isLibrary()
|
||||
{
|
||||
QFETCH( QString, filename );
|
||||
QFETCH( bool, valid );
|
||||
|
||||
QCOMPARE(QLibrary::isLibrary(filename), valid);
|
||||
}
|
||||
|
||||
void tst_QLibrary::errorString_data()
|
||||
{
|
||||
QTest::addColumn<int>("operation");
|
||||
QTest::addColumn<QString>("fileName");
|
||||
QTest::addColumn<bool>("success");
|
||||
QTest::addColumn<QString>("errorString");
|
||||
|
||||
QString appDir = directory;
|
||||
|
||||
QTest::newRow("bad load()") << (int)Load << QString("nosuchlib") << false << QString("Cannot load library nosuchlib: .*");
|
||||
QTest::newRow("call errorString() on QLibrary with no d-pointer (crashtest)") << (int)(Load | DontSetFileName) << QString() << false << QString("Unknown error");
|
||||
QTest::newRow("bad resolve") << (int)Resolve << appDir + "/mylib" << false << QString("Unknown error");
|
||||
QTest::newRow("good resolve") << (int)Resolve << appDir + "/mylib" << true << QString("Unknown error");
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
QTest::newRow("bad load() with .dll suffix") << (int)Load << QString("nosuchlib.dll") << false << QString("Cannot load library nosuchlib.dll: The specified module could not be found.");
|
||||
// QTest::newRow("bad unload") << (int)Unload << QString("nosuchlib.dll") << false << QString("QLibrary::unload_sys: Cannot unload nosuchlib.dll (The specified module could not be found.)");
|
||||
#elif defined Q_OS_MAC
|
||||
#else
|
||||
QTest::newRow("load invalid file") << (int)Load << QFINDTESTDATA("library_path/invalid.so") << false << QString("Cannot load library.*");
|
||||
#endif
|
||||
}
|
||||
|
||||
void tst_QLibrary::errorString()
|
||||
{
|
||||
QFETCH(int, operation);
|
||||
QFETCH(QString, fileName);
|
||||
QFETCH(bool, success);
|
||||
QFETCH(QString, errorString);
|
||||
|
||||
QLibrary lib;
|
||||
if (!(operation & DontSetFileName)) {
|
||||
lib.setFileName(fileName);
|
||||
}
|
||||
|
||||
bool ok = false;
|
||||
switch (operation & OperationMask) {
|
||||
case Load:
|
||||
ok = lib.load();
|
||||
break;
|
||||
case Unload:
|
||||
ok = lib.load(); //###
|
||||
ok = lib.unload();
|
||||
break;
|
||||
case Resolve: {
|
||||
ok = lib.load();
|
||||
QCOMPARE(ok, true);
|
||||
if (success) {
|
||||
ok = lib.resolve("mylibversion");
|
||||
} else {
|
||||
ok = lib.resolve("nosuchsymbol");
|
||||
}
|
||||
break;}
|
||||
default:
|
||||
QFAIL(qPrintable(QString("Unknown operation: %1").arg(operation)));
|
||||
break;
|
||||
}
|
||||
#if QT_CONFIG(regularexpression)
|
||||
QRegularExpression re(QRegularExpression::anchoredPattern(errorString));
|
||||
QString libErrorString = lib.errorString();
|
||||
QVERIFY2(re.match(libErrorString).hasMatch(), qPrintable(libErrorString));
|
||||
#endif
|
||||
QVERIFY(!lib.isLoaded() || lib.unload());
|
||||
QCOMPARE(ok, success);
|
||||
}
|
||||
|
||||
void tst_QLibrary::loadHints_data()
|
||||
{
|
||||
QTest::addColumn<QString>("lib");
|
||||
QTest::addColumn<int>("loadHints");
|
||||
QTest::addColumn<bool>("result");
|
||||
|
||||
QLibrary::LoadHints lh;
|
||||
|
||||
QString appDir = directory;
|
||||
|
||||
lh |= QLibrary::ResolveAllSymbolsHint;
|
||||
# if defined(Q_OS_WIN32)
|
||||
QTest::newRow( "ok01 (with suffix)" ) << appDir + "/mylib.dll" << int(lh) << true;
|
||||
QTest::newRow( "ok02 (with non-standard suffix)" ) << appDir + "/mylib.dl2" << int(lh) << true;
|
||||
QTest::newRow( "ok03 (with many dots)" ) << appDir + "/system.qt.test.mylib.dll" << int(lh) << true;
|
||||
# elif defined Q_OS_UNIX
|
||||
QTest::newRow( "ok01 (with suffix)" ) << appDir + "/libmylib" SUFFIX << int(lh) << true;
|
||||
#ifndef Q_OS_ANDROID
|
||||
// We do not support non-standard suffixes on Android
|
||||
QTest::newRow( "ok02 (with non-standard suffix)" ) << appDir + "/libmylib.so2" << int(lh) << true;
|
||||
#endif
|
||||
QTest::newRow( "ok03 (with many dots)" ) << appDir + "/system.qt.test.mylib.so" << int(lh) << true;
|
||||
# endif // Q_OS_UNIX
|
||||
}
|
||||
|
||||
void tst_QLibrary::loadHints()
|
||||
{
|
||||
QFETCH( QString, lib );
|
||||
QFETCH( int, loadHints);
|
||||
QFETCH( bool, result );
|
||||
//QLibrary library( lib );
|
||||
QLibrary library;
|
||||
QLibrary::LoadHints lh(loadHints);
|
||||
if (int(loadHints) != 0) {
|
||||
lh |= library.loadHints();
|
||||
library.setLoadHints(lh);
|
||||
|
||||
// confirm that another QLibrary doesn't get affected - QTBUG-39642
|
||||
QCOMPARE(QLibrary().loadHints(), QLibrary::LoadHints());
|
||||
}
|
||||
library.setFileName(lib);
|
||||
QCOMPARE(library.loadHints(), lh);
|
||||
bool ok = library.load();
|
||||
|
||||
// we can't change the hints anymore
|
||||
library.setLoadHints(QLibrary::LoadHints());
|
||||
QCOMPARE(library.loadHints(), lh);
|
||||
|
||||
// confirm that a new QLibrary inherits the hints too
|
||||
QCOMPARE(QLibrary(lib).loadHints(), lh);
|
||||
|
||||
if ( result ) {
|
||||
QVERIFY( ok );
|
||||
QVERIFY(library.unload());
|
||||
} else {
|
||||
QVERIFY( !ok );
|
||||
}
|
||||
}
|
||||
|
||||
void tst_QLibrary::fileName_data()
|
||||
{
|
||||
QTest::addColumn<QString>("libName");
|
||||
QTest::addColumn<QString>("expectedFilename");
|
||||
|
||||
QTest::newRow( "ok02" ) << sys_qualifiedLibraryName(QLatin1String("mylib"))
|
||||
<< sys_qualifiedLibraryName(QLatin1String("mylib"));
|
||||
#if defined(Q_OS_WIN)
|
||||
QTest::newRow( "ok03" ) << "user32"
|
||||
<< "USER32.dll";
|
||||
#endif
|
||||
}
|
||||
|
||||
void tst_QLibrary::fileName()
|
||||
{
|
||||
QFETCH( QString, libName);
|
||||
QFETCH( QString, expectedFilename);
|
||||
|
||||
QLibrary lib(libName);
|
||||
bool ok = lib.load();
|
||||
QVERIFY2(ok, qPrintable(lib.errorString()));
|
||||
#if defined(Q_OS_WIN)
|
||||
QCOMPARE(lib.fileName().toLower(), expectedFilename.toLower());
|
||||
#else
|
||||
QCOMPARE(lib.fileName(), expectedFilename);
|
||||
#endif
|
||||
QVERIFY(lib.unload());
|
||||
}
|
||||
|
||||
void tst_QLibrary::multipleInstancesForOneLibrary()
|
||||
{
|
||||
QString lib = directory + "/mylib";
|
||||
|
||||
{
|
||||
QLibrary lib1(lib);
|
||||
QLibrary lib2(lib);
|
||||
QCOMPARE(lib1.isLoaded(), false);
|
||||
QCOMPARE(lib2.isLoaded(), false);
|
||||
lib1.load();
|
||||
QCOMPARE(lib1.isLoaded(), true);
|
||||
QCOMPARE(lib2.isLoaded(), true);
|
||||
QCOMPARE(lib1.unload(), true);
|
||||
QCOMPARE(lib1.isLoaded(), false);
|
||||
QCOMPARE(lib2.isLoaded(), false);
|
||||
lib1.load();
|
||||
lib2.load();
|
||||
QCOMPARE(lib1.isLoaded(), true);
|
||||
QCOMPARE(lib2.isLoaded(), true);
|
||||
QCOMPARE(lib1.unload(), false);
|
||||
QCOMPARE(lib1.isLoaded(), true);
|
||||
QCOMPARE(lib2.isLoaded(), true);
|
||||
QCOMPARE(lib2.unload(), true);
|
||||
QCOMPARE(lib1.isLoaded(), false);
|
||||
QCOMPARE(lib2.isLoaded(), false);
|
||||
|
||||
// Finally; unload on that is already unloaded
|
||||
QCOMPARE(lib1.unload(), false);
|
||||
}
|
||||
|
||||
//now let's try with a 3rd one that will go out of scope
|
||||
{
|
||||
QLibrary lib1(lib);
|
||||
QCOMPARE(lib1.isLoaded(), false);
|
||||
lib1.load();
|
||||
QCOMPARE(lib1.isLoaded(), true);
|
||||
}
|
||||
QLibrary lib2(lib);
|
||||
//lib2 should be loaded because lib1 was loaded and never unloaded
|
||||
QCOMPARE(lib2.isLoaded(), true);
|
||||
}
|
||||
|
||||
QTEST_MAIN(tst_QLibrary)
|
||||
#include "tst_qlibrary.moc"
|
42
tests/auto/corelib/plugin/qplugin/CMakeLists.txt
Normal file
42
tests/auto/corelib/plugin/qplugin/CMakeLists.txt
Normal file
@ -0,0 +1,42 @@
|
||||
# Copyright (C) 2022 The Qt Company Ltd.
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
add_subdirectory(invalidplugin)
|
||||
add_subdirectory(debugplugin)
|
||||
add_subdirectory(releaseplugin)
|
||||
|
||||
qt_internal_add_test(tst_qplugin
|
||||
SOURCES
|
||||
tst_qplugin.cpp
|
||||
LIBRARIES
|
||||
Qt::CorePrivate
|
||||
)
|
||||
|
||||
if(NOT ANDROID)
|
||||
# Collect test data
|
||||
file(GLOB_RECURSE test_data_glob
|
||||
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
plugins/*)
|
||||
list(APPEND test_data ${test_data_glob})
|
||||
set_target_properties(tst_qplugin PROPERTIES TESTDATA "${test_data}")
|
||||
else()
|
||||
# On Android the plugins must be located in the libs subdir of the APK.
|
||||
# Use QT_ANDROID_EXTRA_LIBS to achieve that.
|
||||
set(plugins
|
||||
invalidplugin
|
||||
debugplugin
|
||||
releaseplugin
|
||||
)
|
||||
set(extra_libs)
|
||||
foreach(plugin IN LISTS plugins)
|
||||
list(APPEND extra_libs
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/plugins/lib${plugin}_${CMAKE_ANDROID_ARCH_ABI}.so")
|
||||
endforeach()
|
||||
set_target_properties(tst_qplugin PROPERTIES
|
||||
QT_ANDROID_EXTRA_LIBS "${extra_libs}"
|
||||
)
|
||||
endif()
|
||||
|
||||
target_compile_definitions(tst_qplugin PRIVATE CMAKE_BUILD=1)
|
||||
|
||||
add_dependencies(tst_qplugin invalidplugin debugplugin releaseplugin)
|
17
tests/auto/corelib/plugin/qplugin/debugplugin/CMakeLists.txt
Normal file
17
tests/auto/corelib/plugin/qplugin/debugplugin/CMakeLists.txt
Normal file
@ -0,0 +1,17 @@
|
||||
# Copyright (C) 2022 The Qt Company Ltd.
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
#####################################################################
|
||||
## debugplugin Generic Library:
|
||||
#####################################################################
|
||||
|
||||
qt_internal_add_cmake_library(debugplugin
|
||||
MODULE
|
||||
OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/../plugins"
|
||||
SOURCES
|
||||
main.cpp
|
||||
LIBRARIES
|
||||
Qt::Core
|
||||
)
|
||||
|
||||
qt_autogen_tools_initial_setup(debugplugin)
|
14
tests/auto/corelib/plugin/qplugin/debugplugin/main.cpp
Normal file
14
tests/auto/corelib/plugin/qplugin/debugplugin/main.cpp
Normal file
@ -0,0 +1,14 @@
|
||||
// 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 <QtPlugin>
|
||||
#include <QObject>
|
||||
|
||||
class DebugPlugin : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PLUGIN_METADATA(IID "SomeIID")
|
||||
public:
|
||||
DebugPlugin() {}
|
||||
};
|
||||
|
||||
#include "main.moc"
|
@ -0,0 +1,19 @@
|
||||
# Copyright (C) 2022 The Qt Company Ltd.
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
#####################################################################
|
||||
## invalidplugin Generic Library:
|
||||
#####################################################################
|
||||
|
||||
qt_internal_add_cmake_library(invalidplugin
|
||||
MODULE
|
||||
OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/../plugins"
|
||||
SOURCES
|
||||
main.cpp
|
||||
LIBRARIES
|
||||
Qt::Core
|
||||
)
|
||||
|
||||
# TEMPLATE = "lib"
|
||||
|
||||
qt_autogen_tools_initial_setup(invalidplugin)
|
25
tests/auto/corelib/plugin/qplugin/invalidplugin/main.cpp
Normal file
25
tests/auto/corelib/plugin/qplugin/invalidplugin/main.cpp
Normal file
@ -0,0 +1,25 @@
|
||||
// Copyright (C) 2018 Intel Corporation.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
|
||||
|
||||
#include <qplugin.h>
|
||||
|
||||
// be careful when updating to V2, the header is different on ELF systems
|
||||
QT_PLUGIN_METADATA_SECTION
|
||||
static const char pluginMetaData[512] = {
|
||||
'q', 'p', 'l', 'u', 'g', 'i', 'n', ' ',
|
||||
't', 'e', 's', 't', 'f', 'i', 'l', 'e'
|
||||
};
|
||||
|
||||
extern "C" {
|
||||
|
||||
const void *qt_plugin_query_metadata()
|
||||
{
|
||||
return pluginMetaData;
|
||||
}
|
||||
|
||||
Q_DECL_EXPORT void *qt_plugin_instance()
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,17 @@
|
||||
# Copyright (C) 2022 The Qt Company Ltd.
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
#####################################################################
|
||||
## releaseplugin Generic Library:
|
||||
#####################################################################
|
||||
|
||||
qt_internal_add_cmake_library(releaseplugin
|
||||
MODULE
|
||||
OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/../plugins"
|
||||
SOURCES
|
||||
main.cpp
|
||||
LIBRARIES
|
||||
Qt::Core
|
||||
)
|
||||
|
||||
qt_autogen_tools_initial_setup(releaseplugin)
|
14
tests/auto/corelib/plugin/qplugin/releaseplugin/main.cpp
Normal file
14
tests/auto/corelib/plugin/qplugin/releaseplugin/main.cpp
Normal file
@ -0,0 +1,14 @@
|
||||
// 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 <QtPlugin>
|
||||
#include <QObject>
|
||||
|
||||
class ReleasePlugin : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PLUGIN_METADATA(IID "SomeIID")
|
||||
public:
|
||||
ReleasePlugin() {}
|
||||
};
|
||||
|
||||
#include "main.moc"
|
238
tests/auto/corelib/plugin/qplugin/tst_qplugin.cpp
Normal file
238
tests/auto/corelib/plugin/qplugin/tst_qplugin.cpp
Normal file
@ -0,0 +1,238 @@
|
||||
// Copyright (C) 2020 The Qt Company Ltd.
|
||||
// Copyright (C) 2021 Intel Corporation.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
|
||||
#include <QTest>
|
||||
|
||||
#include <QCoreApplication>
|
||||
#include <QDebug>
|
||||
#include <QDir>
|
||||
#include <qplugin.h>
|
||||
#include <QPluginLoader>
|
||||
|
||||
#include <private/qplugin_p.h>
|
||||
|
||||
class tst_QPlugin : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
QDir dir;
|
||||
|
||||
public:
|
||||
tst_QPlugin();
|
||||
|
||||
private slots:
|
||||
void initTestCase();
|
||||
void loadDebugPlugin();
|
||||
void loadReleasePlugin();
|
||||
void scanInvalidPlugin_data();
|
||||
void scanInvalidPlugin();
|
||||
};
|
||||
|
||||
tst_QPlugin::tst_QPlugin()
|
||||
{
|
||||
// On Android the plugins must be located in the APK's libs subdir
|
||||
#ifndef Q_OS_ANDROID
|
||||
dir = QFINDTESTDATA("plugins");
|
||||
#else
|
||||
const QStringList paths = QCoreApplication::libraryPaths();
|
||||
if (!paths.isEmpty())
|
||||
dir = paths.first();
|
||||
#endif
|
||||
}
|
||||
|
||||
void tst_QPlugin::initTestCase()
|
||||
{
|
||||
QVERIFY2(dir.exists(),
|
||||
qPrintable(QString::fromLatin1("Cannot find the 'plugins' directory starting from '%1'").
|
||||
arg(QDir::toNativeSeparators(QDir::currentPath()))));
|
||||
}
|
||||
|
||||
void tst_QPlugin::loadDebugPlugin()
|
||||
{
|
||||
const auto fileNames = dir.entryList(QStringList() << "*debug*", QDir::Files);
|
||||
if (fileNames.isEmpty())
|
||||
QSKIP("No debug plugins found - skipping test");
|
||||
|
||||
for (const QString &fileName : fileNames) {
|
||||
if (!QLibrary::isLibrary(fileName))
|
||||
continue;
|
||||
QPluginLoader loader(dir.filePath(fileName));
|
||||
#if defined(Q_OS_UNIX) && !defined(Q_OS_MAC)
|
||||
// we can always load a plugin on unix
|
||||
QVERIFY(loader.load());
|
||||
QObject *object = loader.instance();
|
||||
QVERIFY(object != 0);
|
||||
#else
|
||||
# if defined(CMAKE_BUILD) && defined(QT_NO_DEBUG)
|
||||
QSKIP("Skipping test as it is not possible to disable build targets based on configuration with CMake");
|
||||
# endif
|
||||
// loading a plugin is dependent on which lib we are running against
|
||||
# if defined(QT_NO_DEBUG)
|
||||
// release build, we cannot load debug plugins
|
||||
QVERIFY(!loader.load());
|
||||
# else
|
||||
// debug build, we can load debug plugins
|
||||
QVERIFY(loader.load());
|
||||
QObject *object = loader.instance();
|
||||
QVERIFY(object != 0);
|
||||
# endif
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void tst_QPlugin::loadReleasePlugin()
|
||||
{
|
||||
const auto fileNames = dir.entryList(QStringList() << "*release*", QDir::Files);
|
||||
if (fileNames.isEmpty())
|
||||
QSKIP("No release plugins found - skipping test");
|
||||
|
||||
for (const QString &fileName : fileNames) {
|
||||
if (!QLibrary::isLibrary(fileName))
|
||||
continue;
|
||||
QPluginLoader loader(dir.filePath(fileName));
|
||||
#if defined(Q_OS_UNIX) && !defined(Q_OS_MAC)
|
||||
// we can always load a plugin on unix
|
||||
QVERIFY(loader.load());
|
||||
QObject *object = loader.instance();
|
||||
QVERIFY(object != 0);
|
||||
#else
|
||||
# if defined(CMAKE_BUILD) && !defined(QT_NO_DEBUG)
|
||||
QSKIP("Skipping test as it is not possible to disable build targets based on configuration with CMake");
|
||||
# endif
|
||||
// loading a plugin is dependent on which lib we are running against
|
||||
# if defined(QT_NO_DEBUG)
|
||||
// release build, we can load debug plugins
|
||||
QVERIFY(loader.load());
|
||||
QObject *object = loader.instance();
|
||||
QVERIFY(object != 0);
|
||||
# else
|
||||
// debug build, we cannot load debug plugins
|
||||
QVERIFY(!loader.load());
|
||||
# endif
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void tst_QPlugin::scanInvalidPlugin_data()
|
||||
{
|
||||
QTest::addColumn<QByteArray>("metadata");
|
||||
QTest::addColumn<bool>("loads");
|
||||
QTest::addColumn<QString>("errMsg");
|
||||
|
||||
// CBOR metadata
|
||||
static constexpr QPluginMetaData::MagicHeader header = {};
|
||||
static constexpr qsizetype MagicLen = sizeof(header.magic);
|
||||
QByteArray cprefix(reinterpret_cast<const char *>(&header), sizeof(header));
|
||||
|
||||
QByteArray cborValid = [] {
|
||||
QCborMap m;
|
||||
m.insert(int(QtPluginMetaDataKeys::IID), QLatin1String("org.qt-project.tst_qplugin"));
|
||||
m.insert(int(QtPluginMetaDataKeys::ClassName), QLatin1String("tst"));
|
||||
m.insert(int(QtPluginMetaDataKeys::MetaData), QCborMap());
|
||||
return QCborValue(m).toCbor();
|
||||
}();
|
||||
QTest::newRow("cbor-control") << (cprefix + cborValid) << true << "";
|
||||
|
||||
cprefix[MagicLen + 1] = QT_VERSION_MAJOR + 1;
|
||||
QTest::newRow("cbor-major-too-new") << (cprefix + cborValid) << false << "";
|
||||
|
||||
cprefix[MagicLen + 1] = QT_VERSION_MAJOR - 1;
|
||||
QTest::newRow("cbor-major-too-old") << (cprefix + cborValid) << false << "";
|
||||
|
||||
cprefix[MagicLen + 1] = QT_VERSION_MAJOR;
|
||||
cprefix[MagicLen + 2] = QT_VERSION_MINOR + 1;
|
||||
QTest::newRow("cbor-minor-too-new") << (cprefix + cborValid) << false << "";
|
||||
|
||||
cprefix[MagicLen + 2] = QT_VERSION_MINOR;
|
||||
QTest::newRow("cbor-invalid") << (cprefix + "\xff") << false
|
||||
<< " Metadata parsing error: Invalid CBOR stream: unexpected 'break' byte";
|
||||
QTest::newRow("cbor-not-map1") << (cprefix + "\x01") << false
|
||||
<< " Unexpected metadata contents";
|
||||
QTest::newRow("cbor-not-map2") << (cprefix + "\x81\x01") << false
|
||||
<< " Unexpected metadata contents";
|
||||
|
||||
++cprefix[MagicLen + 0];
|
||||
QTest::newRow("cbor-major-too-new-invalid")
|
||||
<< (cprefix + cborValid) << false << " Invalid metadata version";
|
||||
}
|
||||
|
||||
static const char invalidPluginSignature[] = "qplugin testfile";
|
||||
static qsizetype locateMetadata(const uchar *data, qsizetype len)
|
||||
{
|
||||
const uchar *dataend = data + len - strlen(invalidPluginSignature);
|
||||
|
||||
for (const uchar *ptr = data; ptr < dataend; ++ptr) {
|
||||
if (*ptr != invalidPluginSignature[0])
|
||||
continue;
|
||||
|
||||
int r = memcmp(ptr, invalidPluginSignature, strlen(invalidPluginSignature));
|
||||
if (r)
|
||||
continue;
|
||||
|
||||
return ptr - data;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
void tst_QPlugin::scanInvalidPlugin()
|
||||
{
|
||||
#if defined(Q_OS_MACOS) && defined(Q_PROCESSOR_ARM)
|
||||
QSKIP("This test crashes on ARM macOS");
|
||||
#endif
|
||||
const auto fileNames = dir.entryList({"*invalid*"}, QDir::Files);
|
||||
QString invalidPluginName;
|
||||
if (fileNames.isEmpty())
|
||||
QSKIP("No invalid plugin found - skipping test");
|
||||
else
|
||||
invalidPluginName = dir.absoluteFilePath(fileNames.first());
|
||||
|
||||
|
||||
// copy the file
|
||||
QFileInfo fn(invalidPluginName);
|
||||
QTemporaryDir tmpdir;
|
||||
QVERIFY(tmpdir.isValid());
|
||||
|
||||
QString newName = tmpdir.path() + '/' + fn.fileName();
|
||||
QVERIFY(QFile::copy(invalidPluginName, newName));
|
||||
|
||||
{
|
||||
QFile f(newName);
|
||||
QVERIFY(f.open(QIODevice::ReadWrite | QIODevice::Unbuffered));
|
||||
QVERIFY(f.size() > qint64(strlen(invalidPluginSignature)));
|
||||
uchar *data = f.map(0, f.size());
|
||||
QVERIFY(data);
|
||||
|
||||
static const qsizetype offset = locateMetadata(data, f.size());
|
||||
QVERIFY(offset > 0);
|
||||
|
||||
QFETCH(QByteArray, metadata);
|
||||
|
||||
// sanity check
|
||||
QVERIFY(metadata.size() < 512);
|
||||
|
||||
// replace the data
|
||||
memcpy(data + offset, metadata.constData(), metadata.size());
|
||||
memset(data + offset + metadata.size(), 0, 512 - metadata.size());
|
||||
}
|
||||
|
||||
#if defined(Q_OS_QNX)
|
||||
// On QNX plugin access is still too early
|
||||
QTest::qSleep(1000);
|
||||
#endif
|
||||
|
||||
// now try to load this
|
||||
QFETCH(bool, loads);
|
||||
QFETCH(QString, errMsg);
|
||||
if (!errMsg.isEmpty())
|
||||
QTest::ignoreMessage(QtWarningMsg,
|
||||
"Found invalid metadata in lib " + QFile::encodeName(newName) +
|
||||
":" + errMsg.toUtf8());
|
||||
QPluginLoader loader(newName);
|
||||
QCOMPARE(loader.load(), loads);
|
||||
if (loads)
|
||||
loader.unload();
|
||||
}
|
||||
|
||||
QTEST_MAIN(tst_QPlugin)
|
||||
#include "tst_qplugin.moc"
|
2
tests/auto/corelib/plugin/qpluginloader/BLACKLIST
Normal file
2
tests/auto/corelib/plugin/qpluginloader/BLACKLIST
Normal file
@ -0,0 +1,2 @@
|
||||
[loadMachO]
|
||||
macos cmake
|
13
tests/auto/corelib/plugin/qpluginloader/CMakeLists.txt
Normal file
13
tests/auto/corelib/plugin/qpluginloader/CMakeLists.txt
Normal file
@ -0,0 +1,13 @@
|
||||
# Copyright (C) 2022 The Qt Company Ltd.
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
add_subdirectory(lib)
|
||||
add_subdirectory(staticplugin)
|
||||
add_subdirectory(theplugin)
|
||||
add_subdirectory(tst)
|
||||
if(UNIX AND NOT ANDROID AND NOT APPLE)
|
||||
add_subdirectory(almostplugin)
|
||||
endif()
|
||||
if(MACOS AND QT_FEATURE_private_tests AND TARGET Qt::Gui)
|
||||
add_subdirectory(machtest)
|
||||
endif()
|
@ -0,0 +1,18 @@
|
||||
# Copyright (C) 2022 The Qt Company Ltd.
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
#####################################################################
|
||||
## almostplugin Generic Library:
|
||||
#####################################################################
|
||||
|
||||
qt_internal_add_cmake_library(almostplugin
|
||||
MODULE
|
||||
INSTALL_DIRECTORY "${INSTALL_TESTSDIR}/tst_qpluginloader/bin"
|
||||
OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/../bin"
|
||||
SOURCES
|
||||
almostplugin.cpp almostplugin.h
|
||||
LIBRARIES
|
||||
Qt::Core
|
||||
)
|
||||
|
||||
qt_autogen_tools_initial_setup(almostplugin)
|
@ -0,0 +1,11 @@
|
||||
// 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 <QtCore/QString>
|
||||
#include "almostplugin.h"
|
||||
#include <QtCore/qplugin.h>
|
||||
|
||||
QString AlmostPlugin::pluginName() const
|
||||
{
|
||||
unresolvedSymbol();
|
||||
return QLatin1String("Plugin ok");
|
||||
}
|
@ -0,0 +1,21 @@
|
||||
// Copyright (C) 2016 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
|
||||
#ifndef ALMOSTPLUGIN_H
|
||||
#define ALMOSTPLUGIN_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QtPlugin>
|
||||
#include "../theplugin/plugininterface.h"
|
||||
|
||||
class AlmostPlugin : public QObject, public PluginInterface
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PLUGIN_METADATA(IID "org.qt-project.Qt.autotests.plugininterface" FILE "../empty.json")
|
||||
Q_INTERFACES(PluginInterface)
|
||||
|
||||
public:
|
||||
QString pluginName() const override;
|
||||
void unresolvedSymbol() const;
|
||||
};
|
||||
|
||||
#endif // ALMOSTPLUGIN_H
|
BIN
tests/auto/corelib/plugin/qpluginloader/elftest/debugobj.so
Normal file
BIN
tests/auto/corelib/plugin/qpluginloader/elftest/debugobj.so
Normal file
Binary file not shown.
1
tests/auto/corelib/plugin/qpluginloader/empty.json
Normal file
1
tests/auto/corelib/plugin/qpluginloader/empty.json
Normal file
@ -0,0 +1 @@
|
||||
{}
|
57
tests/auto/corelib/plugin/qpluginloader/fakeplugin.cpp
Normal file
57
tests/auto/corelib/plugin/qpluginloader/fakeplugin.cpp
Normal file
@ -0,0 +1,57 @@
|
||||
// Copyright (C) 2021 Intel Corporation.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
|
||||
#ifndef QT_VERSION_MAJOR
|
||||
# include <QtCore/qglobal.h>
|
||||
#endif
|
||||
|
||||
extern "C" void *qt_plugin_instance()
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
#ifdef QT_DEBUG
|
||||
static constexpr bool IsDebug = true;
|
||||
#else
|
||||
static constexpr bool IsDebug = false;
|
||||
#endif
|
||||
|
||||
#ifndef PLUGIN_VERSION
|
||||
# define PLUGIN_VERSION (QT_VERSION_MAJOR >= 7 ? 1 : 0)
|
||||
#endif
|
||||
#if PLUGIN_VERSION == 1
|
||||
# define PLUGIN_HEADER 1, QT_VERSION_MAJOR, 0, IsDebug ? 0x80 : 0
|
||||
#else
|
||||
# define PLUGIN_HEADER 0, QT_VERSION_MAJOR, 0, IsDebug
|
||||
#endif
|
||||
|
||||
#if defined(__ELF__) && PLUGIN_VERSION >= 1
|
||||
// GCC will produce:
|
||||
// fakeplugin.cpp:64:3: warning: ‘no_sanitize’ attribute ignored [-Wattributes]
|
||||
__attribute__((section(".note.qt.metadata"), used, no_sanitize("address"), aligned(sizeof(void*))))
|
||||
static const struct {
|
||||
unsigned n_namesz = sizeof(name);
|
||||
unsigned n_descsz = sizeof(payload);
|
||||
unsigned n_type = 0x74510001;
|
||||
char name[12] = "qt-project!";
|
||||
alignas(unsigned) unsigned char payload[2 + 4] = {
|
||||
PLUGIN_HEADER,
|
||||
0xbf,
|
||||
0xff,
|
||||
};
|
||||
} qtnotemetadata;
|
||||
#elif PLUGIN_VERSION >= 0
|
||||
# ifdef _MSC_VER
|
||||
# pragma section(".qtmetadata",read,shared)
|
||||
__declspec(allocate(".qtmetadata"))
|
||||
# elif defined(__APPLE__)
|
||||
__attribute__ ((section ("__TEXT,qtmetadata"), used))
|
||||
# else
|
||||
__attribute__ ((section(".qtmetadata"), used))
|
||||
# endif
|
||||
static const unsigned char qtmetadata[] = {
|
||||
'Q', 'T', 'M', 'E', 'T', 'A', 'D', 'A', 'T', 'A', ' ', '!',
|
||||
PLUGIN_HEADER,
|
||||
0xbf,
|
||||
0xff,
|
||||
};
|
||||
#endif
|
34
tests/auto/corelib/plugin/qpluginloader/lib/CMakeLists.txt
Normal file
34
tests/auto/corelib/plugin/qpluginloader/lib/CMakeLists.txt
Normal file
@ -0,0 +1,34 @@
|
||||
# Copyright (C) 2022 The Qt Company Ltd.
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
#####################################################################
|
||||
## tst_qpluginloaderlib Generic Library:
|
||||
#####################################################################
|
||||
|
||||
qt_internal_add_cmake_library(tst_qpluginloaderlib
|
||||
SHARED
|
||||
INSTALL_DIRECTORY "${INSTALL_TESTSDIR}/tst_qpluginloader/bin"
|
||||
OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/../bin"
|
||||
SOURCES
|
||||
mylib.c
|
||||
LIBRARIES
|
||||
Qt::Core
|
||||
)
|
||||
|
||||
if(WIN32)
|
||||
# CMake sets for Windows-GNU platforms the suffix "lib"
|
||||
set_property(TARGET tst_qpluginloaderlib PROPERTY PREFIX "")
|
||||
endif()
|
||||
|
||||
## Scopes:
|
||||
#####################################################################
|
||||
|
||||
qt_internal_extend_target(tst_qpluginloaderlib CONDITION MSVC
|
||||
DEFINES
|
||||
WIN32_MSVC
|
||||
)
|
||||
|
||||
set_target_properties(tst_qpluginloaderlib PROPERTIES
|
||||
C_VISIBILITY_PRESET "default"
|
||||
CXX_VISIBILITY_PRESET "default"
|
||||
)
|
28
tests/auto/corelib/plugin/qpluginloader/lib/mylib.c
Normal file
28
tests/auto/corelib/plugin/qpluginloader/lib/mylib.c
Normal file
@ -0,0 +1,28 @@
|
||||
// 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 <qglobal.h>
|
||||
|
||||
#if defined(Q_CC_MSVC) || defined(Q_CC_MSVC_NET) || defined(Q_CC_BOR)
|
||||
#define LIB_EXPORT __declspec(dllexport)
|
||||
#else
|
||||
#define LIB_EXPORT
|
||||
#endif
|
||||
|
||||
#if defined(Q_CC_BOR)
|
||||
# define BORLAND_STDCALL __stdcall
|
||||
#else
|
||||
# define BORLAND_STDCALL
|
||||
#endif
|
||||
|
||||
static int pluginVariable = 0xc0ffee;
|
||||
LIB_EXPORT int *pointerAddress()
|
||||
{
|
||||
return &pluginVariable;
|
||||
}
|
||||
|
||||
LIB_EXPORT int BORLAND_STDCALL version()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
@ -0,0 +1 @@
|
||||
|
171
tests/auto/corelib/plugin/qpluginloader/machtest/generate-bad.pl
Normal file
171
tests/auto/corelib/plugin/qpluginloader/machtest/generate-bad.pl
Normal file
@ -0,0 +1,171 @@
|
||||
#!/usr/bin/perl
|
||||
# Copyright (C) 2016 Intel Corporation.
|
||||
# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
|
||||
|
||||
use strict;
|
||||
use constant FAT_MAGIC => 0xcafebabe;
|
||||
use constant MH_MAGIC => 0xfeedface;
|
||||
use constant MH_MAGIC_64 => 0xfeedfacf;
|
||||
use constant CPU_TYPE_X86 => 7;
|
||||
use constant CPU_TYPE_X86_64 => CPU_TYPE_X86 | 0x01000000;
|
||||
use constant CPU_SUBTYPE_I386_ALL => 3;
|
||||
use constant MH_DYLIB => 6;
|
||||
use constant LC_SEGMENT => 1;
|
||||
use constant LC_SEGMENT_64 => 0x19;
|
||||
|
||||
my $good = pack("(L7 L2 Z16 L8 Z16 Z16 L9 . L)>",
|
||||
MH_MAGIC, CPU_TYPE_X86, CPU_SUBTYPE_I386_ALL, MH_DYLIB, # 0-3
|
||||
1, # 4: ncmds
|
||||
4 * (37 - 6), # 5: sizeofcmds
|
||||
0, # 6: flags
|
||||
|
||||
LC_SEGMENT, # 7: cmd
|
||||
4 * (37 - 6), # 8: cmdsize
|
||||
'__TEXT', # 9-12: segname
|
||||
0, # 13: vmaddr
|
||||
0x1000, # 14: vmsize
|
||||
0, # 15: fileoff
|
||||
0x204, # 16: filesize
|
||||
7, # 17: maxprot (rwx)
|
||||
5, # 18: initprot (r-x)
|
||||
1, # 19: nsects
|
||||
0, # 20: flags
|
||||
|
||||
'qtmetadata', # 21-24: sectname
|
||||
'__TEXT', # 25-28: segname
|
||||
0x200, # 29: addr
|
||||
4, # 30: size
|
||||
0x200, # 31: offset
|
||||
2, # 32: align (2^2)
|
||||
0, # 33: reloff
|
||||
0, # 34: nreloc
|
||||
0, # 35: flags
|
||||
0, # 36: reserved1
|
||||
0, # 37: reserved2
|
||||
|
||||
0x200,
|
||||
0xc0ffee # data
|
||||
);
|
||||
|
||||
my $good64 = pack("(L8 L2 Z16 Q4 L4 Z16 Z16 Q2 L8 . Q)>",
|
||||
MH_MAGIC_64, CPU_TYPE_X86_64, CPU_SUBTYPE_I386_ALL, MH_DYLIB, # 0-3
|
||||
1, # 4: ncmds
|
||||
4 * (45 - 7), # 5: sizeofcmds
|
||||
0, # 6: flags
|
||||
0, # 7: reserved
|
||||
|
||||
LC_SEGMENT_64, # 8: cmd
|
||||
4 * (45 - 7), # 9: cmdsize
|
||||
'__TEXT', # 10-13: segname
|
||||
0, # 14-15: vmaddr
|
||||
0x1000, # 16-17: vmsize
|
||||
0, # 18-19: fileoff
|
||||
0x208, # 20-21: filesize
|
||||
7, # 22: maxprot (rwx)
|
||||
5, # 23: initprot (r-x)
|
||||
1, # 24: nsects
|
||||
0, # 25: flags
|
||||
|
||||
'qtmetadata', # 26-29: sectname
|
||||
'__TEXT', # 30-33: segname
|
||||
0x200, # 34-35: addr
|
||||
4, # 36-37: size
|
||||
0x200, # 38: offset
|
||||
3, # 39: align (2^3)
|
||||
0, # 40: reloff
|
||||
0, # 41: nreloc
|
||||
0, # 42: flags
|
||||
0, # 43: reserved1
|
||||
0, # 44: reserved2
|
||||
0, # 45: reserved3
|
||||
|
||||
0x200,
|
||||
0xc0ffeec0ffee # data
|
||||
);
|
||||
|
||||
my $fat = pack("L>*",
|
||||
FAT_MAGIC, # 1: magic
|
||||
2, # 2: nfat_arch
|
||||
|
||||
CPU_TYPE_X86, # 3: cputype
|
||||
CPU_SUBTYPE_I386_ALL, # 4: cpusubtype
|
||||
0x1000, # 5: offset
|
||||
0x1000, # 6: size
|
||||
12, # 7: align (2^12)
|
||||
|
||||
CPU_TYPE_X86_64, # 8: cputype
|
||||
CPU_SUBTYPE_I386_ALL, # 9: cpusubtype
|
||||
0x2000, # 10: offset
|
||||
0x1000, # 11: size
|
||||
12, # 12: align (2^12)
|
||||
);
|
||||
|
||||
my $buffer;
|
||||
|
||||
our $badcount = 1;
|
||||
sub generate($) {
|
||||
open OUT, ">", "bad$badcount.dylib" or die("Could not open file bad$badcount.dylib: $!\n");
|
||||
binmode OUT;
|
||||
print OUT $_[0];
|
||||
close OUT;
|
||||
++$badcount;
|
||||
}
|
||||
|
||||
# Bad file 1-2
|
||||
# Except that the cmdsize fields are null
|
||||
$buffer = $good;
|
||||
vec($buffer, 5, 32) = 0;
|
||||
generate $buffer;
|
||||
|
||||
$buffer = $good;
|
||||
vec($buffer, 8, 32) = 0;
|
||||
generate $buffer;
|
||||
|
||||
# Bad file 3-4: same as above but 64-bit
|
||||
$buffer = $good64;
|
||||
vec($buffer, 5, 32) = 0;
|
||||
generate $buffer;
|
||||
|
||||
$buffer = $good64;
|
||||
vec($buffer, 9, 32) = 0;
|
||||
generate $buffer;
|
||||
|
||||
# Bad file 5-8: same as 1-4, but set cmdsize to bigger than file
|
||||
$buffer = $good;
|
||||
vec($buffer, 5, 32) = 0x1000;
|
||||
generate $buffer;
|
||||
|
||||
$buffer = $good;
|
||||
vec($buffer, 8, 32) = 0x1000;
|
||||
generate $buffer;
|
||||
|
||||
$buffer = $good64;
|
||||
vec($buffer, 5, 32) = 0x1000;
|
||||
generate $buffer;
|
||||
|
||||
$buffer = $good64;
|
||||
vec($buffer, 9, 32) = 0x1000;
|
||||
generate $buffer;
|
||||
|
||||
# Bad file 9-10: overflow size+offset
|
||||
$buffer = $good;
|
||||
vec($buffer, 30, 32) = 0xffffffe0;
|
||||
generate $buffer;
|
||||
|
||||
$buffer = $good64;
|
||||
vec($buffer, 36, 32) = 0xffffffff;
|
||||
vec($buffer, 37, 32) = 0xffffffe0;
|
||||
generate $buffer;
|
||||
|
||||
# Bad file 11: FAT binary with just the header
|
||||
generate $fat;
|
||||
|
||||
# Bad file 12: FAT binary where the Mach contents don't match the FAT directory
|
||||
$buffer = pack("a4096 a4096 a4096", $fat, $good64, $good);
|
||||
generate $buffer;
|
||||
|
||||
# Bad file 13: FAT binary with overflowing size
|
||||
$buffer = pack("a4096 a4096 a4096", $fat, $good, $good64);
|
||||
vec($buffer, 5, 32) = 0xfffffffe0;
|
||||
vec($buffer, 10, 32) = 0xfffffffe0;
|
||||
generate $buffer;
|
@ -0,0 +1,74 @@
|
||||
#!/usr/bin/perl
|
||||
# Copyright (C) 2016 Intel Corporation.
|
||||
# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
|
||||
|
||||
# Changes the Mach-O file type header to PowerPC.
|
||||
#
|
||||
# The header is (from mach-o/loader.h):
|
||||
# struct mach_header {
|
||||
# uint32_t magic; /* mach magic number identifier */
|
||||
# cpu_type_t cputype; /* cpu specifier */
|
||||
# cpu_subtype_t cpusubtype; /* machine specifier */
|
||||
# uint32_t filetype; /* type of file */
|
||||
# uint32_t ncmds; /* number of load commands */
|
||||
# uint32_t sizeofcmds; /* the size of all the load commands */
|
||||
# uint32_t flags; /* flags */
|
||||
# };
|
||||
#
|
||||
# The 64-bit header is identical in the first three fields, except for a different
|
||||
# magic number. We will not touch the magic number, we'll just reset the cputype
|
||||
# field to the PowerPC type and the subtype field to zero.
|
||||
#
|
||||
# We will not change the file's endianness. That means we might create a little-endian
|
||||
# PowerPC binary, which could not be run in real life.
|
||||
#
|
||||
# We will also not change the 64-bit ABI flag, which is found in the cputype's high
|
||||
# byte. That means we'll create a PPC64 binary if fed a 64-bit input.
|
||||
#
|
||||
use strict;
|
||||
use constant MH_MAGIC => 0xfeedface;
|
||||
use constant MH_CIGAM => 0xcefaedfe;
|
||||
use constant MH_MAGIC_64 => 0xfeedfacf;
|
||||
use constant MH_CIGAM_64 => 0xcffaedfe;
|
||||
use constant CPU_TYPE_POWERPC => 18;
|
||||
use constant CPU_SUBTYPE_POWERPC_ALL => 0;
|
||||
|
||||
my $infile = shift @ARGV or die("Missing input filename");
|
||||
my $outfile = shift @ARGV or die("Missing output filename");
|
||||
|
||||
open IN, "<$infile" or die("Can't open $infile for reading: $!\n");
|
||||
open OUT, ">$outfile" or die("Can't open $outfile for writing: $!\n");
|
||||
|
||||
binmode IN;
|
||||
binmode OUT;
|
||||
|
||||
# Read the first 12 bytes, which includes the interesting fields of the header
|
||||
my $buffer;
|
||||
read(IN, $buffer, 12);
|
||||
|
||||
my $magic = vec($buffer, 0, 32);
|
||||
if ($magic == MH_MAGIC || $magic == MH_MAGIC_64) {
|
||||
# Big endian
|
||||
# The low byte of cputype is at offset 7
|
||||
vec($buffer, 7, 8) = CPU_TYPE_POWERPC;
|
||||
} elsif ($magic == MH_CIGAM || $magic == MH_CIGAM_64) {
|
||||
# Little endian
|
||||
# The low byte of cpytype is at offset 4
|
||||
vec($buffer, 4, 8) = CPU_TYPE_POWERPC;
|
||||
} else {
|
||||
$magic = '';
|
||||
$magic .= sprintf("%02X ", $_) for unpack("CCCC", $buffer);
|
||||
die("Invalid input. Unknown magic $magic\n");
|
||||
}
|
||||
vec($buffer, 2, 32) = CPU_SUBTYPE_POWERPC_ALL;
|
||||
|
||||
print OUT $buffer;
|
||||
|
||||
# Copy the rest
|
||||
while (!eof(IN)) {
|
||||
read(IN, $buffer, 4096) and
|
||||
print OUT $buffer or
|
||||
die("Problem copying: $!\n");
|
||||
}
|
||||
close(IN);
|
||||
close(OUT);
|
@ -0,0 +1 @@
|
||||
void dummy() {}
|
@ -0,0 +1,25 @@
|
||||
# Copyright (C) 2022 The Qt Company Ltd.
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
#####################################################################
|
||||
## staticplugin Generic Library:
|
||||
#####################################################################
|
||||
|
||||
qt_internal_add_cmake_library(staticplugin
|
||||
STATIC
|
||||
SOURCES
|
||||
main.cpp
|
||||
LIBRARIES
|
||||
Qt::Core
|
||||
MOC_OPTIONS
|
||||
"-M"
|
||||
"ExtraMetaData=StaticPlugin"
|
||||
"-M"
|
||||
"ExtraMetaData=foo"
|
||||
)
|
||||
|
||||
# TEMPLATE = "lib"
|
||||
|
||||
qt_autogen_tools_initial_setup(staticplugin)
|
||||
|
||||
target_compile_definitions(staticplugin PRIVATE QT_STATICPLUGIN)
|
@ -0,0 +1,14 @@
|
||||
// Copyright (C) 2018 Intel Corporation.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
|
||||
#include <QtPlugin>
|
||||
#include <QObject>
|
||||
|
||||
class StaticPlugin : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PLUGIN_METADATA(IID "SomeIID" URI "qt.test.pluginloader.staticplugin")
|
||||
public:
|
||||
StaticPlugin() {}
|
||||
};
|
||||
|
||||
#include "main.moc"
|
@ -0,0 +1,32 @@
|
||||
# Copyright (C) 2022 The Qt Company Ltd.
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
qt_internal_add_cmake_library(theplugin
|
||||
MODULE
|
||||
INSTALL_DIRECTORY "${INSTALL_TESTSDIR}/tst_qpluginloader/bin"
|
||||
OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/../bin"
|
||||
SOURCES
|
||||
theplugin.cpp theplugin.h
|
||||
LIBRARIES
|
||||
Qt::Core
|
||||
)
|
||||
qt_autogen_tools_initial_setup(theplugin)
|
||||
|
||||
if (UNIX AND NOT APPLE)
|
||||
qt_internal_add_cmake_library(theoldplugin
|
||||
MODULE
|
||||
INSTALL_DIRECTORY "${INSTALL_TESTSDIR}/tst_qpluginloader/bin"
|
||||
OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/../bin"
|
||||
SOURCES
|
||||
theoldplugin.cpp theoldplugin.h
|
||||
LIBRARIES
|
||||
Qt::Core
|
||||
)
|
||||
qt_autogen_tools_initial_setup(theoldplugin)
|
||||
|
||||
# Force unoptimized builds with debugging information so some "QTMETADATA !"
|
||||
# strings appear elsewhere in the binary.
|
||||
target_compile_options(theplugin PRIVATE -O0 -g3)
|
||||
target_compile_options(theoldplugin PRIVATE -O0 -g3)
|
||||
endif()
|
||||
|
@ -0,0 +1,22 @@
|
||||
// Copyright (C) 2016 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
|
||||
#ifndef PLUGININTERFACE_H
|
||||
#define PLUGININTERFACE_H
|
||||
|
||||
#include <QtCore/QtGlobal>
|
||||
|
||||
struct PluginInterface {
|
||||
virtual ~PluginInterface() {}
|
||||
virtual QString pluginName() const = 0;
|
||||
};
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
#define PluginInterface_iid "org.qt-project.Qt.autotests.plugininterface"
|
||||
|
||||
Q_DECLARE_INTERFACE(PluginInterface, PluginInterface_iid)
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#endif // PLUGININTERFACE_H
|
||||
|
@ -0,0 +1,80 @@
|
||||
// Copyright (C) 2021 Intel Corporation.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
|
||||
#include "theoldplugin.h"
|
||||
#include <QtCore/QString>
|
||||
#include <QtCore/qplugin.h>
|
||||
|
||||
QString TheOldPlugin::pluginName() const
|
||||
{
|
||||
return QLatin1String("Plugin ok");
|
||||
}
|
||||
|
||||
static int pluginVariable = 0xc0ffee;
|
||||
extern "C" Q_DECL_EXPORT int *pointerAddress()
|
||||
{
|
||||
return &pluginVariable;
|
||||
}
|
||||
|
||||
// This hardcodes the old plugin metadata from before Qt 6.2
|
||||
QT_PLUGIN_METADATA_SECTION
|
||||
static constexpr unsigned char qt_pluginMetaData_ThePlugin[] = {
|
||||
'Q', 'T', 'M', 'E', 'T', 'A', 'D', 'A', 'T', 'A', ' ', '!',
|
||||
// metadata version, Qt version, architectural requirements
|
||||
0, QT_VERSION_MAJOR, QT_VERSION_MINOR, qPluginArchRequirements(),
|
||||
0xbf,
|
||||
// "IID"
|
||||
0x02, 0x78, 0x2b, 'o', 'r', 'g', '.', 'q',
|
||||
't', '-', 'p', 'r', 'o', 'j', 'e', 'c',
|
||||
't', '.', 'Q', 't', '.', 'a', 'u', 't',
|
||||
'o', 't', 'e', 's', 't', 's', '.', 'p',
|
||||
'l', 'u', 'g', 'i', 'n', 'i', 'n', 't',
|
||||
'e', 'r', 'f', 'a', 'c', 'e',
|
||||
// "className"
|
||||
0x03, 0x69, 'T', 'h', 'e', 'P', 'l', 'u',
|
||||
'g', 'i', 'n',
|
||||
// "MetaData"
|
||||
0x04, 0xa2, 0x67, 'K', 'P', 'l', 'u', 'g',
|
||||
'i', 'n', 0xa8, 0x64, 'N', 'a', 'm', 'e',
|
||||
0x6e, 'W', 'i', 'n', 'd', 'o', 'w', 'G',
|
||||
'e', 'o', 'm', 'e', 't', 'r', 'y', 0x68,
|
||||
'N', 'a', 'm', 'e', '[', 'm', 'r', ']',
|
||||
0x78, 0x1f, uchar('\xe0'), uchar('\xa4'), uchar('\x9a'), uchar('\xe0'), uchar('\xa5'), uchar('\x8c'),
|
||||
uchar('\xe0'), uchar('\xa4'), uchar('\x95'), uchar('\xe0'), uchar('\xa4'), uchar('\x9f'), ' ', uchar('\xe0'),
|
||||
uchar('\xa4'), uchar('\xad'), uchar('\xe0'), uchar('\xa5'), uchar('\x82'), uchar('\xe0'), uchar('\xa4'), uchar('\xae'),
|
||||
uchar('\xe0'), uchar('\xa4'), uchar('\xbf'), uchar('\xe0'), uchar('\xa4'), uchar('\xa4'), uchar('\xe0'), uchar('\xa5'),
|
||||
uchar('\x80'), 0x68, 'N', 'a', 'm', 'e', '[', 'p',
|
||||
'a', ']', 0x78, 0x24, uchar('\xe0'), uchar('\xa8'), uchar('\xb5'), uchar('\xe0'),
|
||||
uchar('\xa8'), uchar('\xbf'), uchar('\xe0'), uchar('\xa9'), uchar('\xb0'), uchar('\xe0'), uchar('\xa8'), uchar('\xa1'),
|
||||
uchar('\xe0'), uchar('\xa9'), uchar('\x8b'), uchar('\xe0'), uchar('\xa8'), uchar('\x9c'), uchar('\xe0'), uchar('\xa9'),
|
||||
uchar('\x81'), uchar('\xe0'), uchar('\xa8'), uchar('\xae'), uchar('\xe0'), uchar('\xa9'), uchar('\x88'), uchar('\xe0'),
|
||||
uchar('\xa8'), uchar('\x9f'), uchar('\xe0'), uchar('\xa8'), uchar('\xb0'), uchar('\xe0'), uchar('\xa9'), uchar('\x80'),
|
||||
0x68, 'N', 'a', 'm', 'e', '[', 't', 'h',
|
||||
']', 0x78, 0x39, uchar('\xe0'), uchar('\xb8'), uchar('\xa1'), uchar('\xe0'), uchar('\xb8'),
|
||||
uchar('\xb4'), uchar('\xe0'), uchar('\xb8'), uchar('\x95'), uchar('\xe0'), uchar('\xb8'), uchar('\xb4'), uchar('\xe0'),
|
||||
uchar('\xb8'), uchar('\x82'), uchar('\xe0'), uchar('\xb8'), uchar('\x99'), uchar('\xe0'), uchar('\xb8'), uchar('\xb2'),
|
||||
uchar('\xe0'), uchar('\xb8'), uchar('\x94'), uchar('\xe0'), uchar('\xb8'), uchar('\x82'), uchar('\xe0'), uchar('\xb8'),
|
||||
uchar('\xad'), uchar('\xe0'), uchar('\xb8'), uchar('\x87'), uchar('\xe0'), uchar('\xb8'), uchar('\xab'), uchar('\xe0'),
|
||||
uchar('\xb8'), uchar('\x99'), uchar('\xe0'), uchar('\xb9'), uchar('\x89'), uchar('\xe0'), uchar('\xb8'), uchar('\xb2'),
|
||||
uchar('\xe0'), uchar('\xb8'), uchar('\x95'), uchar('\xe0'), uchar('\xb9'), uchar('\x88'), uchar('\xe0'), uchar('\xb8'),
|
||||
uchar('\xb2'), uchar('\xe0'), uchar('\xb8'), uchar('\x87'), 0x68, 'N', 'a', 'm',
|
||||
'e', '[', 'u', 'k', ']', 0x78, 0x19, uchar('\xd0'),
|
||||
uchar('\xa0'), uchar('\xd0'), uchar('\xbe'), uchar('\xd0'), uchar('\xb7'), uchar('\xd0'), uchar('\xbc'), uchar('\xd1'),
|
||||
uchar('\x96'), uchar('\xd1'), uchar('\x80'), uchar('\xd0'), uchar('\xb8'), ' ', uchar('\xd0'), uchar('\xb2'),
|
||||
uchar('\xd1'), uchar('\x96'), uchar('\xd0'), uchar('\xba'), uchar('\xd0'), uchar('\xbd'), uchar('\xd0'), uchar('\xb0'),
|
||||
0x6b, 'N', 'a', 'm', 'e', '[', 'z', 'h',
|
||||
'_', 'C', 'N', ']', 0x6c, uchar('\xe7'), uchar('\xaa'), uchar('\x97'),
|
||||
uchar('\xe5'), uchar('\x8f'), uchar('\xa3'), uchar('\xe5'), uchar('\xbd'), uchar('\xa2'), uchar('\xe7'), uchar('\x8a'),
|
||||
uchar('\xb6'), 0x6b, 'N', 'a', 'm', 'e', '[', 'z',
|
||||
'h', '_', 'T', 'W', ']', 0x6c, uchar('\xe8'), uchar('\xa6'),
|
||||
uchar('\x96'), uchar('\xe7'), uchar('\xaa'), uchar('\x97'), uchar('\xe4'), uchar('\xbd'), uchar('\x8d'), uchar('\xe7'),
|
||||
uchar('\xbd'), uchar('\xae'), 0x6c, 'S', 'e', 'r', 'v', 'i',
|
||||
'c', 'e', 'T', 'y', 'p', 'e', 's', 0x81,
|
||||
0x68, 'K', 'C', 'M', 'o', 'd', 'u', 'l',
|
||||
'e', 0x76, 'X', '-', 'K', 'D', 'E', '-',
|
||||
'P', 'a', 'r', 'e', 'n', 't', 'C', 'o',
|
||||
'm', 'p', 'o', 'n', 'e', 'n', 't', 's',
|
||||
0x81, 0x6e, 'w', 'i', 'n', 'd', 'o', 'w',
|
||||
'g', 'e', 'o', 'm', 'e', 't', 'r', 'y',
|
||||
0xff,
|
||||
};
|
||||
QT_MOC_EXPORT_PLUGIN(TheOldPlugin, ThePlugin)
|
@ -0,0 +1,21 @@
|
||||
// Copyright (C) 2021 Intel Corportaion.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
|
||||
#ifndef THEOLDPLUGIN_H
|
||||
#define THEOLDPLUGIN_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QtPlugin>
|
||||
#include "plugininterface.h"
|
||||
|
||||
class TheOldPlugin : public QObject, public PluginInterface
|
||||
{
|
||||
Q_OBJECT
|
||||
// Q_PLUGIN_METADATA intentionally missing
|
||||
Q_INTERFACES(PluginInterface)
|
||||
|
||||
public:
|
||||
virtual QString pluginName() const override;
|
||||
};
|
||||
|
||||
#endif // THEOLDPLUGIN_H
|
||||
|
@ -0,0 +1,16 @@
|
||||
// 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 <QtCore/QString>
|
||||
#include "theplugin.h"
|
||||
#include <QtCore/qplugin.h>
|
||||
|
||||
QString ThePlugin::pluginName() const
|
||||
{
|
||||
return QLatin1String("Plugin ok");
|
||||
}
|
||||
|
||||
static int pluginVariable = 0xc0ffee;
|
||||
extern "C" Q_DECL_EXPORT int *pointerAddress()
|
||||
{
|
||||
return &pluginVariable;
|
||||
}
|
@ -0,0 +1,21 @@
|
||||
// Copyright (C) 2016 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
|
||||
#ifndef THEPLUGIN_H
|
||||
#define THEPLUGIN_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QtPlugin>
|
||||
#include "plugininterface.h"
|
||||
|
||||
class ThePlugin : public QObject, public PluginInterface
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PLUGIN_METADATA(IID "org.qt-project.Qt.autotests.plugininterface" FILE "../utf8_data.json")
|
||||
Q_INTERFACES(PluginInterface)
|
||||
|
||||
public:
|
||||
virtual QString pluginName() const override;
|
||||
};
|
||||
|
||||
#endif // THEPLUGIN_H
|
||||
|
71
tests/auto/corelib/plugin/qpluginloader/tst/CMakeLists.txt
Normal file
71
tests/auto/corelib/plugin/qpluginloader/tst/CMakeLists.txt
Normal file
@ -0,0 +1,71 @@
|
||||
# Copyright (C) 2022 The Qt Company Ltd.
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
#####################################################################
|
||||
## tst_qpluginloader Test:
|
||||
#####################################################################
|
||||
|
||||
# Collect test data
|
||||
list(APPEND test_data "../elftest")
|
||||
list(APPEND test_data "../machtest")
|
||||
|
||||
qt_internal_add_test(tst_qpluginloader
|
||||
OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/../"
|
||||
SOURCES
|
||||
../fakeplugin.cpp
|
||||
../theplugin/plugininterface.h
|
||||
../tst_qpluginloader.cpp
|
||||
LIBRARIES
|
||||
staticplugin
|
||||
TESTDATA ${test_data}
|
||||
)
|
||||
|
||||
add_dependencies(tst_qpluginloader tst_qpluginloaderlib staticplugin theplugin)
|
||||
if (UNIX)
|
||||
if(NOT APPLE)
|
||||
add_dependencies(tst_qpluginloader theoldplugin)
|
||||
endif()
|
||||
if (NOT ANDROID AND NOT APPLE)
|
||||
add_dependencies(tst_qpluginloader almostplugin)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(ANDROID)
|
||||
add_compile_definitions(ANDROID_ARCH="${CMAKE_ANDROID_ARCH_ABI}")
|
||||
set(plugins
|
||||
theplugin
|
||||
theoldplugin
|
||||
tst_qpluginloaderlib
|
||||
)
|
||||
set(extra_libs)
|
||||
foreach(plugin IN LISTS plugins)
|
||||
list(APPEND extra_libs
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/../bin/lib${plugin}_${CMAKE_ANDROID_ARCH_ABI}.so")
|
||||
endforeach()
|
||||
set_target_properties(tst_qpluginloader PROPERTIES
|
||||
QT_ANDROID_EXTRA_LIBS "${extra_libs}"
|
||||
)
|
||||
endif()
|
||||
|
||||
## Scopes:
|
||||
#####################################################################
|
||||
|
||||
qt_internal_extend_target(tst_qpluginloader CONDITION QT_FEATURE_private_tests
|
||||
LIBRARIES
|
||||
Qt::CorePrivate
|
||||
)
|
||||
|
||||
qt_internal_extend_target(tst_qpluginloader CONDITION CMAKE_BUILD_TYPE STREQUAL Debug AND WIN32 AND debug_and_release
|
||||
LIBRARIES
|
||||
# Remove: L../staticplugin/debug
|
||||
)
|
||||
|
||||
qt_internal_extend_target(tst_qpluginloader CONDITION WIN32 AND debug_and_release AND NOT CMAKE_BUILD_TYPE STREQUAL Debug
|
||||
LIBRARIES
|
||||
# Remove: L../staticplugin/release
|
||||
)
|
||||
|
||||
qt_internal_extend_target(tst_qpluginloader CONDITION UNIX OR NOT debug_and_release
|
||||
LIBRARIES
|
||||
# Remove: L../staticplugin
|
||||
)
|
1125
tests/auto/corelib/plugin/qpluginloader/tst_qpluginloader.cpp
Normal file
1125
tests/auto/corelib/plugin/qpluginloader/tst_qpluginloader.cpp
Normal file
File diff suppressed because it is too large
Load Diff
17
tests/auto/corelib/plugin/qpluginloader/utf8_data.json
Normal file
17
tests/auto/corelib/plugin/qpluginloader/utf8_data.json
Normal file
@ -0,0 +1,17 @@
|
||||
{
|
||||
"KPlugin": {
|
||||
"Name": "WindowGeometry",
|
||||
"Name[mr]": "चौकट भूमिती",
|
||||
"Name[pa]": "ਵਿੰਡੋਜੁਮੈਟਰੀ",
|
||||
"Name[th]": "มิติขนาดของหน้าต่าง",
|
||||
"Name[uk]": "Розміри вікна",
|
||||
"Name[zh_CN]": "窗口形状",
|
||||
"Name[zh_TW]": "視窗位置",
|
||||
"ServiceTypes": [
|
||||
"KCModule"
|
||||
]
|
||||
},
|
||||
"X-KDE-ParentComponents": [
|
||||
"windowgeometry"
|
||||
]
|
||||
}
|
5
tests/auto/corelib/plugin/quuid/CMakeLists.txt
Normal file
5
tests/auto/corelib/plugin/quuid/CMakeLists.txt
Normal file
@ -0,0 +1,5 @@
|
||||
# Copyright (C) 2022 The Qt Company Ltd.
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
add_subdirectory(testProcessUniqueness)
|
||||
add_subdirectory(test)
|
26
tests/auto/corelib/plugin/quuid/test/CMakeLists.txt
Normal file
26
tests/auto/corelib/plugin/quuid/test/CMakeLists.txt
Normal file
@ -0,0 +1,26 @@
|
||||
# Copyright (C) 2022 The Qt Company Ltd.
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
#####################################################################
|
||||
## tst_quuid Test:
|
||||
#####################################################################
|
||||
|
||||
qt_internal_add_test(tst_quuid
|
||||
OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/../"
|
||||
SOURCES
|
||||
../tst_quuid.cpp
|
||||
)
|
||||
|
||||
## Scopes:
|
||||
|
||||
qt_internal_extend_target(tst_quuid CONDITION APPLE
|
||||
SOURCES
|
||||
../tst_quuid_darwin.mm
|
||||
LIBRARIES
|
||||
Qt::CorePrivate
|
||||
${FWFoundation}
|
||||
)
|
||||
|
||||
if(QT_FEATURE_process AND NOT ANDROID)
|
||||
add_dependencies(tst_quuid testProcessUniqueness)
|
||||
endif()
|
@ -0,0 +1,15 @@
|
||||
# Copyright (C) 2022 The Qt Company Ltd.
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
#####################################################################
|
||||
## testProcessUniqueness Binary:
|
||||
#####################################################################
|
||||
|
||||
qt_internal_add_executable(testProcessUniqueness
|
||||
INSTALL_DIRECTORY "${INSTALL_TESTSDIR}/tst_quuid/testProcessUniqueness"
|
||||
OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/"
|
||||
SOURCES
|
||||
main.cpp
|
||||
)
|
||||
|
||||
set_target_properties(testProcessUniqueness PROPERTIES MACOSX_BUNDLE TRUE)
|
@ -0,0 +1,21 @@
|
||||
// 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 <stdio.h>
|
||||
#include <QUuid>
|
||||
|
||||
// This is a testcase for QTBUG-11213
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
Q_UNUSED(argc);
|
||||
Q_UNUSED(argv);
|
||||
|
||||
// Now print a few uuids.
|
||||
printf("%s", qPrintable(QUuid::createUuid().toString()));
|
||||
printf("%s", qPrintable(QUuid::createUuid().toString()));
|
||||
printf("%s", qPrintable(QUuid::createUuid().toString()));
|
||||
|
||||
// Done
|
||||
return 0;
|
||||
}
|
||||
|
488
tests/auto/corelib/plugin/quuid/tst_quuid.cpp
Normal file
488
tests/auto/corelib/plugin/quuid/tst_quuid.cpp
Normal file
@ -0,0 +1,488 @@
|
||||
// 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 <QTest>
|
||||
#if QT_CONFIG(process)
|
||||
#include <QProcess>
|
||||
#endif
|
||||
|
||||
#include <qcoreapplication.h>
|
||||
#include <quuid.h>
|
||||
|
||||
class tst_QUuid : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
private slots:
|
||||
void initTestCase();
|
||||
|
||||
void fromChar();
|
||||
void toString();
|
||||
void fromString_data();
|
||||
void fromString();
|
||||
void toByteArray();
|
||||
void fromByteArray();
|
||||
void toRfc4122();
|
||||
void fromRfc4122();
|
||||
void createUuidV3OrV5();
|
||||
void check_QDataStream();
|
||||
void isNull();
|
||||
void equal();
|
||||
void notEqual();
|
||||
void cpp11();
|
||||
|
||||
// Only in Qt > 3.2.x
|
||||
void generate();
|
||||
void less();
|
||||
void more();
|
||||
void variants();
|
||||
void versions();
|
||||
|
||||
void threadUniqueness();
|
||||
void processUniqueness();
|
||||
|
||||
void hash();
|
||||
|
||||
void qvariant();
|
||||
void qvariant_conversion();
|
||||
|
||||
void darwinTypes();
|
||||
|
||||
public:
|
||||
// Variables
|
||||
QUuid uuidNS;
|
||||
QUuid uuidA;
|
||||
QUuid uuidB;
|
||||
QUuid uuidC;
|
||||
QUuid uuidD;
|
||||
};
|
||||
|
||||
void tst_QUuid::initTestCase()
|
||||
{
|
||||
//It's NameSpace_DNS in RFC4122
|
||||
//"{6ba7b810-9dad-11d1-80b4-00c04fd430c8}";
|
||||
uuidNS = QUuid(0x6ba7b810, 0x9dad, 0x11d1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8);
|
||||
|
||||
//"{fc69b59e-cc34-4436-a43c-ee95d128b8c5}";
|
||||
uuidA = QUuid(0xfc69b59e, 0xcc34, 0x4436, 0xa4, 0x3c, 0xee, 0x95, 0xd1, 0x28, 0xb8, 0xc5);
|
||||
|
||||
//"{1ab6e93a-b1cb-4a87-ba47-ec7e99039a7b}";
|
||||
uuidB = QUuid(0x1ab6e93a, 0xb1cb, 0x4a87, 0xba, 0x47, 0xec, 0x7e, 0x99, 0x03, 0x9a, 0x7b);
|
||||
|
||||
#if QT_CONFIG(process)
|
||||
// chdir to the directory containing our testdata, then refer to it with relative paths
|
||||
#ifdef Q_OS_ANDROID
|
||||
QString testdata_dir = QCoreApplication::applicationDirPath();
|
||||
#else // !Q_OS_ANDROID
|
||||
QString testdata_dir = QFileInfo(QFINDTESTDATA("testProcessUniqueness")).absolutePath();
|
||||
#endif
|
||||
QVERIFY2(QDir::setCurrent(testdata_dir), qPrintable("Could not chdir to " + testdata_dir));
|
||||
#endif
|
||||
|
||||
//"{3d813cbb-47fb-32ba-91df-831e1593ac29}"; http://www.rfc-editor.org/errata_search.php?rfc=4122&eid=1352
|
||||
uuidC = QUuid(0x3d813cbb, 0x47fb, 0x32ba, 0x91, 0xdf, 0x83, 0x1e, 0x15, 0x93, 0xac, 0x29);
|
||||
|
||||
//"{21f7f8de-8051-5b89-8680-0195ef798b6a}";
|
||||
uuidD = QUuid(0x21f7f8de, 0x8051, 0x5b89, 0x86, 0x80, 0x01, 0x95, 0xef, 0x79, 0x8b, 0x6a);
|
||||
}
|
||||
|
||||
void tst_QUuid::fromChar()
|
||||
{
|
||||
QCOMPARE(uuidA, QUuid("{fc69b59e-cc34-4436-a43c-ee95d128b8c5}"));
|
||||
QCOMPARE(uuidA, QUuid("fc69b59e-cc34-4436-a43c-ee95d128b8c5}"));
|
||||
QCOMPARE(uuidA, QUuid("{fc69b59e-cc34-4436-a43c-ee95d128b8c5"));
|
||||
QCOMPARE(uuidA, QUuid("fc69b59e-cc34-4436-a43c-ee95d128b8c5"));
|
||||
QCOMPARE(QUuid(), QUuid("{fc69b59e-cc34-4436-a43c-ee95d128b8c"));
|
||||
QCOMPARE(QUuid(), QUuid("{fc69b59e-cc34"));
|
||||
QCOMPARE(QUuid(), QUuid("fc69b59e-cc34-"));
|
||||
QCOMPARE(QUuid(), QUuid("fc69b59e-cc34"));
|
||||
QCOMPARE(QUuid(), QUuid("cc34"));
|
||||
QCOMPARE(QUuid(), QUuid(NULL));
|
||||
|
||||
QCOMPARE(uuidB, QUuid(QString("{1ab6e93a-b1cb-4a87-ba47-ec7e99039a7b}")));
|
||||
}
|
||||
|
||||
void tst_QUuid::toString()
|
||||
{
|
||||
QCOMPARE(uuidA.toString(), QString("{fc69b59e-cc34-4436-a43c-ee95d128b8c5}"));
|
||||
QCOMPARE(uuidA.toString(QUuid::WithoutBraces),
|
||||
QString("fc69b59e-cc34-4436-a43c-ee95d128b8c5"));
|
||||
QCOMPARE(uuidA.toString(QUuid::Id128),
|
||||
QString("fc69b59ecc344436a43cee95d128b8c5"));
|
||||
|
||||
QCOMPARE(uuidB.toString(), QString("{1ab6e93a-b1cb-4a87-ba47-ec7e99039a7b}"));
|
||||
QCOMPARE(uuidB.toString(QUuid::WithoutBraces),
|
||||
QString("1ab6e93a-b1cb-4a87-ba47-ec7e99039a7b"));
|
||||
QCOMPARE(uuidB.toString(QUuid::Id128),
|
||||
QString("1ab6e93ab1cb4a87ba47ec7e99039a7b"));
|
||||
}
|
||||
|
||||
void tst_QUuid::fromString_data()
|
||||
{
|
||||
QTest::addColumn<QUuid>("expected");
|
||||
QTest::addColumn<QString>("input");
|
||||
|
||||
QUuid invalid = {};
|
||||
|
||||
#define ROW(which, string) \
|
||||
QTest::addRow("%-38s -> %s", string, #which) << which << string
|
||||
ROW(uuidA, "{fc69b59e-cc34-4436-a43c-ee95d128b8c5}");
|
||||
ROW(uuidA, "fc69b59e-cc34-4436-a43c-ee95d128b8c5}");
|
||||
ROW(uuidA, "{fc69b59e-cc34-4436-a43c-ee95d128b8c5" );
|
||||
ROW(uuidA, "fc69b59e-cc34-4436-a43c-ee95d128b8c5" );
|
||||
|
||||
ROW(uuidA, "{fc69b59e-cc34-4436-a43c-ee95d128b8c56"); // too long (not an error!)
|
||||
ROW(invalid, "{fc69b59e-cc34-4436-a43c-ee95d128b8c" ); // premature end (within length limits)
|
||||
ROW(invalid, " fc69b59e-cc34-4436-a43c-ee95d128b8c5}"); // leading space
|
||||
ROW(uuidB, "{1ab6e93a-b1cb-4a87-ba47-ec7e99039a7b "); // trailing space (not an error!)
|
||||
ROW(invalid, "{gc69b59e-cc34-4436-a43c-ee95d128b8c5}"); // non-hex digit in 1st group
|
||||
ROW(invalid, "{fc69b59e-cp34-4436-a43c-ee95d128b8c5}"); // non-hex digit in 2nd group
|
||||
ROW(invalid, "{fc69b59e-cc34-44r6-a43c-ee95d128b8c5}"); // non-hex digit in 3rd group
|
||||
ROW(invalid, "{fc69b59e-cc34-4436-a4yc-ee95d128b8c5}"); // non-hex digit in 4th group
|
||||
ROW(invalid, "{fc69b59e-cc34-4436-a43c-ee95d128j8c5}"); // non-hex digit in last group
|
||||
ROW(invalid, "(fc69b59e-cc34-4436-a43c-ee95d128b8c5}"); // wrong initial character
|
||||
ROW(invalid, "{fc69b59e+cc34-4436-a43c-ee95d128b8c5}"); // wrong 1st separator
|
||||
ROW(invalid, "{fc69b59e-cc34*4436-a43c-ee95d128b8c5}"); // wrong 2nd separator
|
||||
ROW(invalid, "{fc69b59e-cc34-44366a43c-ee95d128b8c5}"); // wrong 3rd separator
|
||||
ROW(invalid, "{fc69b59e-cc34-4436-a43c\303\244ee95d128b8c5}"); // wrong 4th separator (ä)
|
||||
ROW(uuidA, "{fc69b59e-cc34-4436-a43c-ee95d128b8c5)"); // wrong final character (not an error!)
|
||||
|
||||
ROW(uuidB, "{1ab6e93a-b1cb-4a87-ba47-ec7e99039a7b}");
|
||||
#undef ROW
|
||||
}
|
||||
|
||||
void tst_QUuid::fromString()
|
||||
{
|
||||
QFETCH(const QUuid, expected);
|
||||
QFETCH(const QString, input);
|
||||
|
||||
const auto inputL1 = input.toLatin1();
|
||||
const auto inputU8 = input.toUtf8();
|
||||
|
||||
QCOMPARE(expected, QUuid(input));
|
||||
QCOMPARE(expected, QUuid(inputU8));
|
||||
QCOMPARE(expected, QUuid(inputL1));
|
||||
|
||||
QCOMPARE(expected, QUuid::fromString(input));
|
||||
|
||||
// for QLatin1String, construct one whose data() is not NUL-terminated:
|
||||
const auto longerInputL1 = inputL1 + '5'; // the '5' makes the premature end check incorrectly succeed
|
||||
const auto inputL1S = QLatin1String(longerInputL1.data(), inputL1.size());
|
||||
QCOMPARE(expected, QUuid::fromString(inputL1S));
|
||||
|
||||
// for QUtf8StringView, too:
|
||||
const auto longerInputU8 = inputU8 + '5'; // the '5' makes the premature end check incorrectly succeed
|
||||
const auto inputU8S = QUtf8StringView(longerInputU8.data(), inputU8.size());
|
||||
QCOMPARE(expected, QUuid::fromString(inputU8S));
|
||||
}
|
||||
|
||||
void tst_QUuid::toByteArray()
|
||||
{
|
||||
QCOMPARE(uuidA.toByteArray(), QByteArray("{fc69b59e-cc34-4436-a43c-ee95d128b8c5}"));
|
||||
QCOMPARE(uuidA.toByteArray(QUuid::WithoutBraces),
|
||||
QByteArray("fc69b59e-cc34-4436-a43c-ee95d128b8c5"));
|
||||
QCOMPARE(uuidA.toByteArray(QUuid::Id128),
|
||||
QByteArray("fc69b59ecc344436a43cee95d128b8c5"));
|
||||
|
||||
QCOMPARE(uuidB.toByteArray(), QByteArray("{1ab6e93a-b1cb-4a87-ba47-ec7e99039a7b}"));
|
||||
QCOMPARE(uuidB.toByteArray(QUuid::WithoutBraces),
|
||||
QByteArray("1ab6e93a-b1cb-4a87-ba47-ec7e99039a7b"));
|
||||
QCOMPARE(uuidB.toByteArray(QUuid::Id128),
|
||||
QByteArray("1ab6e93ab1cb4a87ba47ec7e99039a7b"));
|
||||
}
|
||||
|
||||
void tst_QUuid::fromByteArray()
|
||||
{
|
||||
QCOMPARE(uuidA, QUuid(QByteArray("{fc69b59e-cc34-4436-a43c-ee95d128b8c5}")));
|
||||
QCOMPARE(uuidA, QUuid(QByteArray("fc69b59e-cc34-4436-a43c-ee95d128b8c5}")));
|
||||
QCOMPARE(uuidA, QUuid(QByteArray("{fc69b59e-cc34-4436-a43c-ee95d128b8c5")));
|
||||
QCOMPARE(uuidA, QUuid(QByteArray("fc69b59e-cc34-4436-a43c-ee95d128b8c5")));
|
||||
QCOMPARE(QUuid(), QUuid(QByteArray("{fc69b59e-cc34-4436-a43c-ee95d128b8c")));
|
||||
|
||||
QCOMPARE(uuidB, QUuid(QByteArray("{1ab6e93a-b1cb-4a87-ba47-ec7e99039a7b}")));
|
||||
}
|
||||
|
||||
void tst_QUuid::toRfc4122()
|
||||
{
|
||||
QCOMPARE(uuidA.toRfc4122(), QByteArray::fromHex("fc69b59ecc344436a43cee95d128b8c5"));
|
||||
|
||||
QCOMPARE(uuidB.toRfc4122(), QByteArray::fromHex("1ab6e93ab1cb4a87ba47ec7e99039a7b"));
|
||||
}
|
||||
|
||||
void tst_QUuid::fromRfc4122()
|
||||
{
|
||||
QCOMPARE(uuidA, QUuid::fromRfc4122(QByteArray::fromHex("fc69b59ecc344436a43cee95d128b8c5")));
|
||||
|
||||
QCOMPARE(uuidB, QUuid::fromRfc4122(QByteArray::fromHex("1ab6e93ab1cb4a87ba47ec7e99039a7b")));
|
||||
}
|
||||
|
||||
void tst_QUuid::createUuidV3OrV5()
|
||||
{
|
||||
//"www.widgets.com" is also from RFC4122
|
||||
QCOMPARE(uuidC, QUuid::createUuidV3(uuidNS, QByteArray("www.widgets.com")));
|
||||
QCOMPARE(uuidC, QUuid::createUuidV3(uuidNS, QString("www.widgets.com")));
|
||||
|
||||
QCOMPARE(uuidD, QUuid::createUuidV5(uuidNS, QByteArray("www.widgets.com")));
|
||||
QCOMPARE(uuidD, QUuid::createUuidV5(uuidNS, QString("www.widgets.com")));
|
||||
}
|
||||
|
||||
void tst_QUuid::check_QDataStream()
|
||||
{
|
||||
QUuid tmp;
|
||||
QByteArray ar;
|
||||
{
|
||||
QDataStream out(&ar,QIODevice::WriteOnly);
|
||||
out.setByteOrder(QDataStream::BigEndian);
|
||||
out << uuidA;
|
||||
}
|
||||
{
|
||||
QDataStream in(&ar,QIODevice::ReadOnly);
|
||||
in.setByteOrder(QDataStream::BigEndian);
|
||||
in >> tmp;
|
||||
QCOMPARE(uuidA, tmp);
|
||||
}
|
||||
{
|
||||
QDataStream out(&ar,QIODevice::WriteOnly);
|
||||
out.setByteOrder(QDataStream::LittleEndian);
|
||||
out << uuidA;
|
||||
}
|
||||
{
|
||||
QDataStream in(&ar,QIODevice::ReadOnly);
|
||||
in.setByteOrder(QDataStream::LittleEndian);
|
||||
in >> tmp;
|
||||
QCOMPARE(uuidA, tmp);
|
||||
}
|
||||
}
|
||||
|
||||
void tst_QUuid::isNull()
|
||||
{
|
||||
QVERIFY( !uuidA.isNull() );
|
||||
|
||||
QUuid should_be_null_uuid;
|
||||
QVERIFY( should_be_null_uuid.isNull() );
|
||||
}
|
||||
|
||||
|
||||
void tst_QUuid::equal()
|
||||
{
|
||||
QVERIFY( !(uuidA == uuidB) );
|
||||
|
||||
QUuid copy(uuidA);
|
||||
QCOMPARE(uuidA, copy);
|
||||
|
||||
QUuid assigned;
|
||||
assigned = uuidA;
|
||||
QCOMPARE(uuidA, assigned);
|
||||
}
|
||||
|
||||
|
||||
void tst_QUuid::notEqual()
|
||||
{
|
||||
QVERIFY( uuidA != uuidB );
|
||||
}
|
||||
|
||||
void tst_QUuid::cpp11() {
|
||||
#ifdef Q_COMPILER_UNIFORM_INIT
|
||||
// "{fc69b59e-cc34-4436-a43c-ee95d128b8c5}" cf, initTestCase
|
||||
constexpr QUuid u1{0xfc69b59e, 0xcc34, 0x4436, 0xa4, 0x3c, 0xee, 0x95, 0xd1, 0x28, 0xb8, 0xc5};
|
||||
constexpr QUuid u2 = {0xfc69b59e, 0xcc34, 0x4436, 0xa4, 0x3c, 0xee, 0x95, 0xd1, 0x28, 0xb8, 0xc5};
|
||||
Q_UNUSED(u1);
|
||||
Q_UNUSED(u2);
|
||||
#else
|
||||
QSKIP("This compiler is not in C++11 mode or it doesn't support uniform initialization");
|
||||
#endif
|
||||
}
|
||||
|
||||
void tst_QUuid::generate()
|
||||
{
|
||||
QUuid shouldnt_be_null_uuidA = QUuid::createUuid();
|
||||
QUuid shouldnt_be_null_uuidB = QUuid::createUuid();
|
||||
QVERIFY( !shouldnt_be_null_uuidA.isNull() );
|
||||
QVERIFY( !shouldnt_be_null_uuidB.isNull() );
|
||||
QVERIFY( shouldnt_be_null_uuidA != shouldnt_be_null_uuidB );
|
||||
}
|
||||
|
||||
|
||||
void tst_QUuid::less()
|
||||
{
|
||||
QVERIFY( uuidB < uuidA);
|
||||
QVERIFY( uuidB <= uuidA);
|
||||
QVERIFY(!(uuidA < uuidB) );
|
||||
QVERIFY(!(uuidA <= uuidB));
|
||||
|
||||
QUuid null_uuid;
|
||||
QVERIFY(null_uuid < uuidA); // Null uuid is always less than a valid one
|
||||
QVERIFY(null_uuid <= uuidA);
|
||||
|
||||
QVERIFY(null_uuid <= null_uuid);
|
||||
QVERIFY(uuidA <= uuidA);
|
||||
}
|
||||
|
||||
|
||||
void tst_QUuid::more()
|
||||
{
|
||||
QVERIFY( uuidA > uuidB);
|
||||
QVERIFY( uuidA >= uuidB);
|
||||
QVERIFY(!(uuidB > uuidA));
|
||||
QVERIFY(!(uuidB >= uuidA));
|
||||
|
||||
QUuid null_uuid;
|
||||
QVERIFY(!(null_uuid > uuidA)); // Null uuid is always less than a valid one
|
||||
QVERIFY(!(null_uuid >= uuidA));
|
||||
|
||||
QVERIFY(null_uuid >= null_uuid);
|
||||
QVERIFY(uuidA >= uuidA);
|
||||
}
|
||||
|
||||
|
||||
void tst_QUuid::variants()
|
||||
{
|
||||
QVERIFY( uuidA.variant() == QUuid::DCE );
|
||||
QVERIFY( uuidB.variant() == QUuid::DCE );
|
||||
|
||||
QUuid NCS("{3a2f883c-4000-000d-0000-00fb40000000}");
|
||||
QVERIFY( NCS.variant() == QUuid::NCS );
|
||||
}
|
||||
|
||||
|
||||
void tst_QUuid::versions()
|
||||
{
|
||||
QVERIFY( uuidA.version() == QUuid::Random );
|
||||
QVERIFY( uuidB.version() == QUuid::Random );
|
||||
|
||||
QUuid DCE_time("{406c45a0-3b7e-11d0-80a3-0000c08810a7}");
|
||||
QVERIFY( DCE_time.version() == QUuid::Time );
|
||||
|
||||
QUuid NCS("{3a2f883c-4000-000d-0000-00fb40000000}");
|
||||
QVERIFY( NCS.version() == QUuid::VerUnknown );
|
||||
}
|
||||
|
||||
class UuidThread : public QThread
|
||||
{
|
||||
public:
|
||||
QUuid uuid;
|
||||
|
||||
void run() override
|
||||
{
|
||||
uuid = QUuid::createUuid();
|
||||
}
|
||||
};
|
||||
|
||||
void tst_QUuid::threadUniqueness()
|
||||
{
|
||||
QList<UuidThread *> threads(qMax(2, QThread::idealThreadCount()));
|
||||
for (int i = 0; i < threads.size(); ++i)
|
||||
threads[i] = new UuidThread;
|
||||
for (int i = 0; i < threads.size(); ++i)
|
||||
threads[i]->start();
|
||||
for (int i = 0; i < threads.size(); ++i)
|
||||
QVERIFY(threads[i]->wait(1000));
|
||||
for (int i = 1; i < threads.size(); ++i)
|
||||
QVERIFY(threads[0]->uuid != threads[i]->uuid);
|
||||
qDeleteAll(threads);
|
||||
}
|
||||
|
||||
void tst_QUuid::processUniqueness()
|
||||
{
|
||||
#if !QT_CONFIG(process)
|
||||
QSKIP("No qprocess support", SkipAll);
|
||||
#else
|
||||
#ifdef Q_OS_ANDROID
|
||||
QSKIP("This test crashes on Android");
|
||||
#endif
|
||||
QProcess process;
|
||||
QString processOneOutput;
|
||||
QString processTwoOutput;
|
||||
|
||||
// Start it once
|
||||
#ifdef Q_OS_MAC
|
||||
process.start("testProcessUniqueness/testProcessUniqueness.app");
|
||||
#elif defined(Q_OS_ANDROID)
|
||||
process.start("libtestProcessUniqueness.so");
|
||||
#else
|
||||
process.start("testProcessUniqueness/testProcessUniqueness");
|
||||
#endif
|
||||
QVERIFY(process.waitForFinished());
|
||||
processOneOutput = process.readAllStandardOutput();
|
||||
|
||||
// Start it twice
|
||||
#ifdef Q_OS_MAC
|
||||
process.start("testProcessUniqueness/testProcessUniqueness.app");
|
||||
#elif defined(Q_OS_ANDROID)
|
||||
process.start("libtestProcessUniqueness.so");
|
||||
#else
|
||||
process.start("testProcessUniqueness/testProcessUniqueness");
|
||||
#endif
|
||||
QVERIFY(process.waitForFinished());
|
||||
processTwoOutput = process.readAllStandardOutput();
|
||||
|
||||
// They should be *different*!
|
||||
QVERIFY(processOneOutput != processTwoOutput);
|
||||
#endif
|
||||
}
|
||||
|
||||
void tst_QUuid::hash()
|
||||
{
|
||||
size_t h = qHash(uuidA);
|
||||
QCOMPARE(qHash(uuidA), h);
|
||||
QCOMPARE(qHash(QUuid(uuidA.toString())), h);
|
||||
}
|
||||
|
||||
void tst_QUuid::qvariant()
|
||||
{
|
||||
QUuid uuid = QUuid::createUuid();
|
||||
QVariant v = QVariant::fromValue(uuid);
|
||||
QVERIFY(!v.isNull());
|
||||
QCOMPARE(v.metaType(), QMetaType(QMetaType::QUuid));
|
||||
|
||||
QUuid uuid2 = v.value<QUuid>();
|
||||
QVERIFY(!uuid2.isNull());
|
||||
QCOMPARE(uuid, uuid2);
|
||||
}
|
||||
|
||||
void tst_QUuid::qvariant_conversion()
|
||||
{
|
||||
QUuid uuid = QUuid::createUuid();
|
||||
QVariant v = QVariant::fromValue(uuid);
|
||||
|
||||
// QUuid -> QString
|
||||
QVERIFY(v.canConvert<QString>());
|
||||
QCOMPARE(v.toString(), uuid.toString());
|
||||
QCOMPARE(v.value<QString>(), uuid.toString());
|
||||
|
||||
// QUuid -> QByteArray
|
||||
QVERIFY(v.canConvert<QByteArray>());
|
||||
QCOMPARE(v.toByteArray(), uuid.toByteArray());
|
||||
QCOMPARE(v.value<QByteArray>(), uuid.toByteArray());
|
||||
|
||||
QVERIFY(!v.canConvert<int>());
|
||||
QVERIFY(!v.canConvert<QStringList>());
|
||||
|
||||
// try reverse conversion QString -> QUuid
|
||||
QVariant sv = QVariant::fromValue(uuid.toString());
|
||||
QCOMPARE(sv.metaType(), QMetaType(QMetaType::QString));
|
||||
QVERIFY(sv.canConvert<QUuid>());
|
||||
QCOMPARE(sv.value<QUuid>(), uuid);
|
||||
|
||||
// QString -> QUuid
|
||||
{
|
||||
QVariant sv = QVariant::fromValue(uuid.toByteArray());
|
||||
QCOMPARE(sv.metaType(), QMetaType(QMetaType::QByteArray));
|
||||
QVERIFY(sv.canConvert<QUuid>());
|
||||
QCOMPARE(sv.value<QUuid>(), uuid);
|
||||
}
|
||||
}
|
||||
|
||||
void tst_QUuid::darwinTypes()
|
||||
{
|
||||
#ifndef Q_OS_DARWIN
|
||||
QSKIP("This is a Darwin-only test");
|
||||
#else
|
||||
extern void tst_QUuid_darwinTypes(); // in tst_quuid_darwin.mm
|
||||
tst_QUuid_darwinTypes();
|
||||
#endif
|
||||
}
|
||||
|
||||
QTEST_MAIN(tst_QUuid)
|
||||
#include "tst_quuid.moc"
|
54
tests/auto/corelib/plugin/quuid/tst_quuid_darwin.mm
Normal file
54
tests/auto/corelib/plugin/quuid/tst_quuid_darwin.mm
Normal file
@ -0,0 +1,54 @@
|
||||
// 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 <QtCore/QUuid>
|
||||
#include <QTest>
|
||||
|
||||
#include <QtCore/private/qcore_mac_p.h>
|
||||
|
||||
#include <CoreFoundation/CoreFoundation.h>
|
||||
#include <Foundation/Foundation.h>
|
||||
|
||||
void tst_QUuid_darwinTypes()
|
||||
{
|
||||
// QUuid <-> CFUUID
|
||||
{
|
||||
const auto qtUuid = QUuid::fromString(QLatin1String("0f7169cc-5711-4af9-99d9-fecb2329fdef"));
|
||||
const CFUUIDRef cfuuid = qtUuid.toCFUUID();
|
||||
QCOMPARE(QUuid::fromCFUUID(cfuuid), qtUuid);
|
||||
CFStringRef cfstring = CFUUIDCreateString(0, cfuuid);
|
||||
QCOMPARE(QString::fromCFString(cfstring), qtUuid.toString().mid(1, 36).toUpper());
|
||||
CFRelease(cfstring);
|
||||
CFRelease(cfuuid);
|
||||
}
|
||||
{
|
||||
auto qtUuid = QUuid::fromString(QLatin1String("0f7169cc-5711-4af9-99d9-fecb2329fdef"));
|
||||
const CFUUIDRef cfuuid = qtUuid.toCFUUID();
|
||||
QUuid qtUuidCopy(qtUuid);
|
||||
qtUuid = QUuid::fromString(QLatin1String("93eec131-13c5-4d13-aaea-e456b4c57efa")); // modify
|
||||
QCOMPARE(QUuid::fromCFUUID(cfuuid), qtUuidCopy);
|
||||
CFStringRef cfstring = CFUUIDCreateString(0, cfuuid);
|
||||
QCOMPARE(QString::fromCFString(cfstring), qtUuidCopy.toString().mid(1, 36).toUpper());
|
||||
CFRelease(cfstring);
|
||||
CFRelease(cfuuid);
|
||||
}
|
||||
// QUuid <-> NSUUID
|
||||
{
|
||||
QMacAutoReleasePool pool;
|
||||
|
||||
const auto qtUuid = QUuid::fromString(QLatin1String("0f7169cc-5711-4af9-99d9-fecb2329fdef"));
|
||||
const NSUUID *nsuuid = qtUuid.toNSUUID();
|
||||
QCOMPARE(QUuid::fromNSUUID(nsuuid), qtUuid);
|
||||
QCOMPARE(QString::fromNSString([nsuuid UUIDString]), qtUuid.toString().mid(1, 36).toUpper());
|
||||
}
|
||||
{
|
||||
QMacAutoReleasePool pool;
|
||||
|
||||
auto qtUuid = QUuid::fromString(QLatin1String("0f7169cc-5711-4af9-99d9-fecb2329fdef"));
|
||||
const NSUUID *nsuuid = qtUuid.toNSUUID();
|
||||
QUuid qtUuidCopy(qtUuid);
|
||||
qtUuid = QUuid::fromString(QLatin1String("93eec131-13c5-4d13-aaea-e456b4c57efa")); // modify
|
||||
QCOMPARE(QUuid::fromNSUUID(nsuuid), qtUuidCopy);
|
||||
QCOMPARE(QString::fromNSString([nsuuid UUIDString]), qtUuidCopy.toString().mid(1, 36).toUpper());
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user