mirror of
https://github.com/crystalidea/qt6windows7.git
synced 2025-07-05 08:45:25 +08:00
qt 6.5.1 original
This commit is contained in:
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"
|
Reference in New Issue
Block a user