summaryrefslogtreecommitdiffstats
path: root/tests/auto/corelib/plugin/qpluginloader/tst_qpluginloader.cpp
diff options
context:
space:
mode:
authorThiago Macieira <thiago.macieira@intel.com>2021-09-10 20:30:08 -0700
committerThiago Macieira <thiago.macieira@intel.com>2021-10-06 12:12:53 -0700
commit46fc01d7ca10ab95e53206077c7c710d2032b4f0 (patch)
treef238483011dd05e2948b6b49883d9bb85437efc1 /tests/auto/corelib/plugin/qpluginloader/tst_qpluginloader.cpp
parent3abcff49eb962cb087498626d77929a870c82929 (diff)
QElfParser: rewrite using elf.h
This rewrite uses the actual structures supplied by the system's C library, so it should be easier to read. It removes hardcoded constants with little evident meaning in favor of sizeof() and the macros from that header. It also removes advancing the data pointer in favor of having absolute offsets. The resulting implementation is stricter than the original, checking more fields in the header. Because the QPluginLoader and QFactoryLoader users may make decisions based on availability of plugins before attempting to load them, it's better to be stricter here than to fail later when trying to dlopen() them. Debugging and testing are much improved. Instead of stored artifacts, I added a routine to modify a valid plugin to make it invalid, given the conditions we've found so far. If you turn debugging on for this category, you'll see things like: not-elf.fcqdMq.so : Not an ELF file (invalid signature) wrong-word-size.QrnSAx.so : ELF 32-bit LSB (GNU/Linux), version 1, shared library or PIC executable, x86-64 invalid-word-size.bOkXvp.so : Invalid ELF file (class 0), LSB (GNU/Linux) unknown-word-size.ogYKeF.so : Invalid ELF file (class 66), LSB (GNU/Linux) wrong-endian.owiElX.so : ELF 64-bit MSB (GNU/Linux), version 1, shared library or PIC executable, x86-64 invalid-endian.FRxClR.so : ELF 64-bit invalid endianness (0) (GNU/Linux) unknown-endian.FfvRrP.so : ELF 64-bit invalid endianness (65) (GNU/Linux) elf-version-0.gPTdpQ.so : ELF 64-bit LSB (GNU/Linux), file version 0 elf-version-2.jlIUUg.so : ELF 64-bit LSB (GNU/Linux), file version 2 executable.LlXiFp.so : ELF 64-bit LSB (GNU/Linux), version 1, executable, x86-64 relocatable.UsOYuy.so : ELF 64-bit LSB (GNU/Linux), version 1, relocatable, x86-64 core-file.hqvNRz.so : ELF 64-bit LSB (GNU/Linux), version 1, core dump, x86-64 invalid-type.CIJgfS.so : ELF 64-bit LSB (GNU/Linux), version 1, unknown type 259, x86-64 wrong-arch.UcNmgz.so : ELF 64-bit LSB (GNU/Linux), version 1, shared library or PIC executable, AArch64 file-version-0.lZYuda.so : ELF 64-bit LSB (GNU/Linux), version 0, shared library or PIC executable, x86-64 file-version-2.ucfdwL.so : ELF 64-bit LSB (GNU/Linux), version 2, shared library or PIC executable, x86-64 no-sections.rSjsHh.so : ELF 64-bit LSB (GNU/Linux), version 1, shared library or PIC executable, x86-64 no-sections.rSjsHh.so : contains 0 sections of 64 bytes at offset 0 ; section header string table (shstrtab) is entry 0 no-sections.rSjsHh.so : no section table present, not able to find Qt metadata qtmetadata-executable.vrxcIf.so : ELF 64-bit LSB (GNU/Linux), version 1, shared library or PIC executable, x86-64 qtmetadata-executable.vrxcIf.so : contains 42 sections of 64 bytes at offset 997256 ; section header string table (shstrtab) is entry 41 qtmetadata-executable.vrxcIf.so : shstrtab section is located at offset 996831 size 423 qtmetadata-executable.vrxcIf.so : section 0 name "" type NULL flags X offset 0x0 size 0x0 qtmetadata-executable.vrxcIf.so : section 1 name ".note.gnu.property" type NOTE flags AX offset 0x2a8 size 0x30 qtmetadata-executable.vrxcIf.so : section 2 name ".note.gnu.build-id" type NOTE flags AX offset 0x2d8 size 0x24 qtmetadata-executable.vrxcIf.so : section 3 name ".hash" type HASH flags AX offset 0x300 size 0x44c qtmetadata-executable.vrxcIf.so : section 4 name ".gnu.hash" type 0x6ffffff6 flags AX offset 0x750 size 0x3b8 qtmetadata-executable.vrxcIf.so : section 5 name ".dynsym" type DYNSYM flags AX offset 0xb08 size 0xd50 qtmetadata-executable.vrxcIf.so : section 6 name ".dynstr" type STRTAB flags AX offset 0x1858 size 0x15d8 qtmetadata-executable.vrxcIf.so : section 7 name ".gnu.version" type 0x6fffffff flags AX offset 0x2e30 size 0x11c qtmetadata-executable.vrxcIf.so : section 8 name ".gnu.version_r" type 0x6ffffffe flags AX offset 0x2f50 size 0xb0 qtmetadata-executable.vrxcIf.so : section 9 name ".rela.dyn" type RELA flags AX offset 0x3000 size 0x480 qtmetadata-executable.vrxcIf.so : section 10 name ".rela.plt" type RELA flags AX offset 0x3480 size 0x7e0 qtmetadata-executable.vrxcIf.so : section 11 name ".init" type PROGBITS flags AX offset 0x4000 size 0x1b qtmetadata-executable.vrxcIf.so : section 12 name ".plt" type PROGBITS flags AX offset 0x4020 size 0x550 qtmetadata-executable.vrxcIf.so : section 13 name ".plt.got" type PROGBITS flags AX offset 0x4570 size 0x8 qtmetadata-executable.vrxcIf.so : section 14 name ".text" type PROGBITS flags AX offset 0x4580 size 0x110e qtmetadata-executable.vrxcIf.so : section 15 name ".fini" type PROGBITS flags AX offset 0x5690 size 0xd qtmetadata-executable.vrxcIf.so : section 16 name ".rodata" type PROGBITS flags AX offset 0x6000 size 0x473 qtmetadata-executable.vrxcIf.so : section 17 name ".qtversion" type PROGBITS flags AX offset 0x6478 size 0x10 qtmetadata-executable.vrxcIf.so : section 18 name ".qtmetadata" type PROGBITS flags AX offset 0x64a0 size 0x19b qtmetadata-executable.vrxcIf.so : found .qtmetadata section qtmetadata-writable.stzwrk.so : ELF 64-bit LSB (GNU/Linux), version 1, shared library or PIC executable, x86-64 Change-Id: I42eb903a916645db9900fffd16a4437af9728eea Reviewed-by: Lars Knoll <lars.knoll@qt.io>
Diffstat (limited to 'tests/auto/corelib/plugin/qpluginloader/tst_qpluginloader.cpp')
-rw-r--r--tests/auto/corelib/plugin/qpluginloader/tst_qpluginloader.cpp363
1 files changed, 317 insertions, 46 deletions
diff --git a/tests/auto/corelib/plugin/qpluginloader/tst_qpluginloader.cpp b/tests/auto/corelib/plugin/qpluginloader/tst_qpluginloader.cpp
index 53fc0b80e3..bab3544946 100644
--- a/tests/auto/corelib/plugin/qpluginloader/tst_qpluginloader.cpp
+++ b/tests/auto/corelib/plugin/qpluginloader/tst_qpluginloader.cpp
@@ -1,7 +1,7 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Copyright (C) 2018 Intel Corporation.
+** Copyright (C) 2020 The Qt Company Ltd.
+** Copyright (C) 2021 Intel Corporation.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the test suite of the Qt Toolkit.
@@ -31,7 +31,10 @@
#include <QSignalSpy>
#include <QJsonArray>
#include <qdir.h>
+#include <qendian.h>
#include <qpluginloader.h>
+#include <qprocess.h>
+#include <qtemporaryfile.h>
#include "theplugin/plugininterface.h"
#if defined(QT_BUILD_INTERNAL) && defined(Q_OF_MACH_O)
@@ -91,6 +94,84 @@
# define PREFIX "lib"
#endif
+#if defined(Q_OF_ELF)
+# include <elf.h>
+# include <memory>
+# include <functional>
+
+# ifdef _LP64
+using ElfHeader = Elf64_Ehdr;
+using ElfShdr = Elf64_Shdr;
+# else
+using ElfHeader = Elf32_Ehdr;
+using ElfShdr = Elf32_Shdr;
+# endif
+
+struct ElfPatcher
+{
+ using FullPatcher = void(ElfHeader *, QFile *);
+ FullPatcher *f;
+
+ ElfPatcher(FullPatcher *f = nullptr) : f(f) {}
+
+ template <typename T> using IsSingleArg = std::is_invocable<T, ElfHeader *>;
+ template <typename T> static std::enable_if_t<IsSingleArg<T>::value, ElfPatcher> fromLambda(T &&t)
+ {
+ using WithoutQFile = void(*)(ElfHeader *);
+ static const WithoutQFile f = t;
+ return { [](ElfHeader *h, QFile *) { f(h);} };
+ }
+ template <typename T> static std::enable_if_t<!IsSingleArg<T>::value, ElfPatcher> fromLambda(T &&t)
+ {
+ return { t };
+ }
+};
+
+Q_DECLARE_METATYPE(ElfPatcher)
+
+static std::unique_ptr<QTemporaryFile> patchElf(const QString &source, ElfPatcher patcher)
+{
+ std::unique_ptr<QTemporaryFile> tmplib;
+
+ bool ok = false;
+ [&]() {
+ QFile srclib(source);
+ QVERIFY2(srclib.open(QIODevice::ReadOnly), qPrintable(srclib.errorString()));
+ qint64 srcsize = srclib.size();
+ const uchar *srcdata = srclib.map(0, srcsize, QFile::MapPrivateOption);
+ QVERIFY2(srcdata, qPrintable(srclib.errorString()));
+
+ // copy our source plugin so we can modify it
+ tmplib.reset(new QTemporaryFile(QTest::currentDataTag() + QString(".XXXXXX" SUFFIX)));
+ QVERIFY2(tmplib->open(), qPrintable(tmplib->errorString()));
+
+ // sanity-check
+ QByteArray magic = QByteArray::fromRawData(reinterpret_cast<const char *>(srcdata), SELFMAG);
+ QCOMPARE(magic, QByteArray(ELFMAG));
+
+ // copy everything via mmap()
+ QVERIFY2(tmplib->resize(srcsize), qPrintable(tmplib->errorString()));
+ uchar *dstdata = tmplib->map(0, srcsize);
+ memcpy(dstdata, srcdata, srcsize);
+
+ // now patch the file
+ patcher.f(reinterpret_cast<ElfHeader *>(dstdata), tmplib.get());
+
+ ok = true;
+ }();
+ if (!ok)
+ tmplib.reset();
+ return tmplib;
+}
+
+// All ELF systems are expected to support GCC expression statements
+#define patchElf(source, patcher) __extension__({ \
+ auto r = patchElf(source, patcher); \
+ if (QTest::currentTestFailed()) return; \
+ std::move(r); \
+ })
+#endif
+
static QString sys_qualifiedLibraryName(const QString &fileName)
{
QString name = QLatin1String("bin/") + QLatin1String(PREFIX) + fileName + QLatin1String(SUFFIX);
@@ -111,13 +192,13 @@ private slots:
void errorString();
void loadHints();
void deleteinstanceOnUnload();
+#if defined (__ELF__)
void loadDebugObj();
+ void loadCorruptElf_data();
void loadCorruptElf();
+#endif
void loadMachO_data();
void loadMachO();
-#if defined (Q_OS_UNIX)
- void loadGarbage();
-#endif
void relativePath();
void absolutePath();
void reloadPlugin();
@@ -289,48 +370,253 @@ void tst_QPluginLoader::deleteinstanceOnUnload()
}
}
+#if defined (__ELF__)
void tst_QPluginLoader::loadDebugObj()
{
#if !defined(QT_SHARED)
QSKIP("This test requires a shared build of Qt, as QPluginLoader::setFileName is a no-op in static builds");
#endif
-#if defined (__ELF__)
QVERIFY(QFile::exists(QFINDTESTDATA("elftest/debugobj.so")));
QPluginLoader lib1(QFINDTESTDATA("elftest/debugobj.so"));
QCOMPARE(lib1.load(), false);
-#endif
}
-void tst_QPluginLoader::loadCorruptElf()
+void tst_QPluginLoader::loadCorruptElf_data()
{
#if !defined(QT_SHARED)
QSKIP("This test requires a shared build of Qt, as QPluginLoader::setFileName is a no-op in static builds");
#endif
-#if defined (__ELF__)
- if (sizeof(void*) == 8) {
- QVERIFY(QFile::exists(QFINDTESTDATA("elftest/corrupt1.elf64.so")));
-
- QPluginLoader lib1(QFINDTESTDATA("elftest/corrupt1.elf64.so"));
- QCOMPARE(lib1.load(), false);
- QVERIFY2(lib1.errorString().contains("not an ELF object"), qPrintable(lib1.errorString()));
-
- QPluginLoader lib2(QFINDTESTDATA("elftest/corrupt2.elf64.so"));
- QCOMPARE(lib2.load(), false);
- QVERIFY2(lib2.errorString().contains("invalid"), qPrintable(lib2.errorString()));
-
- QPluginLoader lib3(QFINDTESTDATA("elftest/corrupt3.elf64.so"));
- QCOMPARE(lib3.load(), false);
- QVERIFY2(lib3.errorString().contains("invalid"), qPrintable(lib3.errorString()));
- } else if (sizeof(void*) == 4) {
- QPluginLoader libW(QFINDTESTDATA("elftest/corrupt3.elf64.so"));
- QCOMPARE(libW.load(), false);
- QVERIFY2(libW.errorString().contains("architecture"), qPrintable(libW.errorString()));
- } else {
- QFAIL("Please port QElfParser to this platform or blacklist this test.");
- }
-#endif
+ QTest::addColumn<QString>("snippet");
+ QTest::addColumn<ElfPatcher>("patcher");
+ auto newRow = [](const char *rowname, QString &&snippet, auto patcher) {
+ QTest::newRow(rowname) << std::move(snippet) << ElfPatcher::fromLambda(patcher);
+ };
+
+ using H = ElfHeader *; // because I'm lazy
+ newRow("not-elf", "invalid signature", [](H h) {
+ h->e_ident[EI_MAG0] = 'Q';
+ h->e_ident[EI_MAG1] = 't';
+ });
+
+ newRow("wrong-word-size", "file is for a different word size", [](H h) {
+ h->e_ident[EI_CLASS] = sizeof(void *) == 8 ? ELFCLASS32 : ELFCLASS64;
+
+ // unnecessary, but we're doing it anyway
+# ifdef _LP64
+ Elf32_Ehdr o;
+ o.e_phentsize = sizeof(Elf32_Phdr);
+ o.e_shentsize = sizeof(Elf32_Shdr);
+# else
+ Elf64_Ehdr o;
+ o.e_phentsize = sizeof(Elf64_Phdr);
+ o.e_shentsize = sizeof(Elf64_Shdr);
+# endif
+ memcpy(o.e_ident, h->e_ident, EI_NIDENT);
+ o.e_type = h->e_type;
+ o.e_machine = h->e_machine;
+ o.e_version = h->e_version;
+ o.e_entry = h->e_entry;
+ o.e_phoff = h->e_phoff;
+ o.e_shoff = h->e_shoff;
+ o.e_flags = h->e_flags;
+ o.e_ehsize = sizeof(o);
+ o.e_phnum = h->e_phnum;
+ o.e_shnum = h->e_shnum;
+ o.e_shstrndx = h->e_shstrndx;
+ memcpy(h, &o, sizeof(o));
+ });
+ newRow("invalid-word-size", "file is for a different word size", [](H h) {
+ h->e_ident[EI_CLASS] = ELFCLASSNONE;;
+ });
+ newRow("unknown-word-size", "file is for a different word size", [](H h) {
+ h->e_ident[EI_CLASS] |= 0x40;
+ });
+
+ newRow("wrong-endian", "file is for the wrong endianness", [](H h) {
+ h->e_ident[EI_DATA] = QSysInfo::ByteOrder == QSysInfo::LittleEndian ? ELFDATA2MSB : ELFDATA2LSB;
+
+ // unnecessary, but we're doing it anyway
+ h->e_type = qbswap(h->e_type);
+ h->e_machine = qbswap(h->e_machine);
+ h->e_version = qbswap(h->e_version);
+ h->e_entry = qbswap(h->e_entry);
+ h->e_phoff = qbswap(h->e_phoff);
+ h->e_shoff = qbswap(h->e_shoff);
+ h->e_flags = qbswap(h->e_flags);
+ h->e_ehsize = qbswap(h->e_ehsize);
+ h->e_phnum = qbswap(h->e_phnum);
+ h->e_phentsize = qbswap(h->e_phentsize);
+ h->e_shnum = qbswap(h->e_shnum);
+ h->e_shentsize = qbswap(h->e_shentsize);
+ h->e_shstrndx = qbswap(h->e_shstrndx);
+ });
+ newRow("invalid-endian", "file is for the wrong endianness", [](H h) {
+ h->e_ident[EI_DATA] = ELFDATANONE;
+ });
+ newRow("unknown-endian", "file is for the wrong endianness", [](H h) {
+ h->e_ident[EI_DATA] |= 0x40;
+ });
+
+ newRow("elf-version-0", "file has an unknown ELF version", [](H h) {
+ --h->e_ident[EI_VERSION];
+ });
+ newRow("elf-version-2", "file has an unknown ELF version", [](H h) {
+ ++h->e_ident[EI_VERSION];
+ });
+
+ newRow("executable", "file is not a shared object", [](H h) {
+ h->e_type = ET_EXEC;
+ });
+ newRow("relocatable", "file is not a shared object", [](H h) {
+ h->e_type = ET_REL;
+ });
+ newRow("core-file", "file is not a shared object", [](H h) {
+ h->e_type = ET_CORE;
+ });
+ newRow("invalid-type", "file is not a shared object", [](H h) {
+ h->e_type |= 0x100;
+ });
+
+ newRow("wrong-arch", "file is for a different processor", [](H h) {
+ // could just ++h->e_machine...
+# if defined(Q_PROCESSOR_X86_64)
+ h->e_machine = EM_AARCH64;
+# elif defined(Q_PROCESSOR_ARM_64)
+ h->e_machine = EM_X86_64;
+# elif defined(Q_PROCESSOR_X86_32)
+ h->e_machine = EM_ARM;
+# elif defined(Q_PROCESSOR_ARM)
+ h->e_machine = EM_386;
+# elif defined(Q_PROCESSOR_MIPS_64)
+ h->e_machine = EM_PPC64;
+# elif defined(Q_PROCESSOR_MIPS_32)
+ h->e_machine = EM_PPC;
+# elif defined(Q_PROCESSOR_POWER_64)
+ h->e_machine = EM_S390;
+# elif defined(Q_PROCESSOR_POWER_32)
+ h->e_machine = EM_MIPS;
+# endif
+ });
+
+ newRow("file-version-0", "file has an unknown ELF version", [](H h) {
+ --h->e_version;
+ });
+ newRow("file-version-2", "file has an unknown ELF version", [](H h) {
+ ++h->e_version;
+ });
+
+ newRow("section-entry-size-zero", "unexpected section entry size", [](H h) {
+ h->e_shentsize = 0;
+ });
+ newRow("section-entry-small", "unexpected section entry size", [](H h) {
+ h->e_shentsize = alignof(ElfShdr);
+ });
+ newRow("section-entry-misaligned", "unexpected section entry size", [](H h) {
+ ++h->e_shentsize;
+ });
+ newRow("no-sections", "is not a Qt plugin (.qtmetadata section not found)", [](H h){
+ h->e_shnum = h->e_shoff = h->e_shstrndx = 0;
+ });
+
+ // section table tests
+ newRow("section-table-starts-past-eof", "section table extends past the end of the file",
+ [](H h, QFile *f) {
+ h->e_shoff = f->size();
+ });
+ newRow("section-table-ends-past-eof", "section table extends past the end of the file",
+ [](H h, QFile *f) {
+ h->e_shoff = f->size() + 1 - h->e_shentsize * h->e_shnum;
+ });
+
+ static auto getSection = +[](H h, int index) {
+ auto sections = reinterpret_cast<ElfShdr *>(h->e_shoff + reinterpret_cast<uchar *>(h));
+ return sections + index;
+ };
+
+ // arbitrary section bounds checks
+ // section index = 0 is usually a NULL section, so we try 1
+ newRow("section1-starts-past-eof", "a section data extends past the end of the file",
+ [](H h, QFile *f) {
+ ElfShdr *s = getSection(h, 1);
+ s->sh_offset = f->size();
+ });
+ newRow("section1-ends-past-eof", "a section data extends past the end of the file",
+ [](H h, QFile *f) {
+ ElfShdr *s = getSection(h, 1);
+ s->sh_size = f->size() + 1 - s->sh_offset;
+ });
+ newRow("section1-bounds-overflow", "a section data extends past the end of the file", [](H h) {
+ ElfShdr *s = getSection(h, 1);
+ s->sh_size = -sizeof(*s);
+ });
+
+ // section header string table tests
+ newRow("shstrndx-invalid", "e_shstrndx greater than the number of sections", [](H h) {
+ h->e_shstrndx = h->e_shnum;
+ });
+ newRow("shstrtab-starts-past-eof", "section header string table extends past the end of the file",
+ [](H h, QFile *f) {
+ ElfShdr *s = getSection(h, h->e_shstrndx);
+ s->sh_offset = f->size();
+ });
+ newRow("shstrtab-ends-past-eof", "section header string table extends past the end of the file",
+ [](H h, QFile *f) {
+ ElfShdr *s = getSection(h, h->e_shstrndx);
+ s->sh_size = f->size() + 1 - s->sh_offset;
+ });
+ newRow("shstrtab-bounds-overflow", "section header string table extends past the end of the file", [](H h) {
+ ElfShdr *s = getSection(h, h->e_shstrndx);
+ s->sh_size = -sizeof(*s);
+ });
+ newRow("section-name-past-eof", "section name extends past the end of the file", [](H h, QFile *f) {
+ ElfShdr *section1 = getSection(h, 1);
+ ElfShdr *shstrtab = getSection(h, h->e_shstrndx);
+ section1->sh_name = f->size() - shstrtab->sh_offset;
+ });
+ newRow("section-name-past-end-of-shstrtab", "section name extends past the end of the file", [](H h) {
+ ElfShdr *section1 = getSection(h, 1);
+ ElfShdr *shstrtab = getSection(h, h->e_shstrndx);
+ section1->sh_name = shstrtab->sh_size;
+ });
+
+ newRow("debug-symbols", ".qtmetadata section not found", [](H h) {
+ // attempt to make it look like extracted debug info
+ for (int i = 1; i < h->e_shnum; ++i) {
+ ElfShdr *s = getSection(h, i);
+ if (s->sh_type == SHT_NOBITS)
+ break;
+ if (s->sh_type != SHT_NOTE && s->sh_flags & SHF_ALLOC)
+ s->sh_type = SHT_NOBITS;
+ }
+ });
+
+ // we don't know which section is .qtmetadata, so we just apply to all of them
+ static auto applyToAllSectionFlags = +[](H h, int flag) {
+ for (int i = 0; i < h->e_shnum; ++i)
+ getSection(h, i)->sh_flags |= flag;
+ };
+ newRow("qtmetadata-executable", ".qtmetadata section is executable", [](H h) {
+ applyToAllSectionFlags(h, SHF_EXECINSTR);
+ });
+ newRow("qtmetadata-writable", ".qtmetadata section is writable", [](H h) {
+ applyToAllSectionFlags(h, SHF_WRITE);
+ });
}
+void tst_QPluginLoader::loadCorruptElf()
+{
+ QFETCH(QString, snippet);
+ QFETCH(ElfPatcher, patcher);
+
+ std::unique_ptr<QTemporaryFile> tmplib =
+ patchElf(sys_qualifiedLibraryName("theplugin"), patcher);
+
+ QPluginLoader lib(tmplib->fileName());
+ QVERIFY(!lib.load());
+ QVERIFY2(lib.errorString().contains(snippet), qPrintable(lib.errorString()));
+}
+#endif // __ELF__
+
void tst_QPluginLoader::loadMachO_data()
{
#if defined(QT_BUILD_INTERNAL) && defined(Q_OF_MACH_O)
@@ -404,21 +690,6 @@ void tst_QPluginLoader::loadMachO()
#endif
}
-#if defined (Q_OS_UNIX)
-void tst_QPluginLoader::loadGarbage()
-{
-#if !defined(QT_SHARED)
- QSKIP("This test requires a shared build of Qt, as QPluginLoader::setFileName is a no-op in static builds");
-#endif
- for (int i=0; i<5; i++) {
- const QString name = QLatin1String("elftest/garbage") + QString::number(i + 1) + QLatin1String(".so");
- QPluginLoader lib(QFINDTESTDATA(name));
- QCOMPARE(lib.load(), false);
- QVERIFY(lib.errorString() != QString("Unknown error"));
- }
-}
-#endif
-
void tst_QPluginLoader::relativePath()
{
#if !defined(QT_SHARED)