diff options
Diffstat (limited to 'tests/auto/corelib/mimetypes')
16 files changed, 447 insertions, 234 deletions
diff --git a/tests/auto/corelib/mimetypes/CMakeLists.txt b/tests/auto/corelib/mimetypes/CMakeLists.txt index 00c7dd7df2..e8c842a410 100644 --- a/tests/auto/corelib/mimetypes/CMakeLists.txt +++ b/tests/auto/corelib/mimetypes/CMakeLists.txt @@ -1,4 +1,5 @@ -# Generated from mimetypes.pro. +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause if(QT_FEATURE_private_tests) add_subdirectory(qmimetype) diff --git a/tests/auto/corelib/mimetypes/qmimedatabase/CMakeLists.txt b/tests/auto/corelib/mimetypes/qmimedatabase/CMakeLists.txt index 14086efd59..26aab786c2 100644 --- a/tests/auto/corelib/mimetypes/qmimedatabase/CMakeLists.txt +++ b/tests/auto/corelib/mimetypes/qmimedatabase/CMakeLists.txt @@ -1,4 +1,5 @@ -# Generated from qmimedatabase.pro. +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause if(TARGET Qt::Concurrent) add_subdirectory(qmimedatabase-xml) diff --git a/tests/auto/corelib/mimetypes/qmimedatabase/add-extension.xml b/tests/auto/corelib/mimetypes/qmimedatabase/add-extension.xml new file mode 100644 index 0000000000..c4141e0f70 --- /dev/null +++ b/tests/auto/corelib/mimetypes/qmimedatabase/add-extension.xml @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="UTF-8"?> +<mime-info xmlns="http://www.freedesktop.org/standards/shared-mime-info"> + <mime-type type="image/jpeg"> + <glob pattern="*.jnewext"/> + <comment>JPEG Image</comment> + </mime-type> +</mime-info> diff --git a/tests/auto/corelib/mimetypes/qmimedatabase/circular-inheritance.xml b/tests/auto/corelib/mimetypes/qmimedatabase/circular-inheritance.xml new file mode 100644 index 0000000000..466f039803 --- /dev/null +++ b/tests/auto/corelib/mimetypes/qmimedatabase/circular-inheritance.xml @@ -0,0 +1,13 @@ +<?xml version="1.0" encoding="UTF-8"?> +<mime-info xmlns="http://www.freedesktop.org/standards/shared-mime-info"> + <mime-type type="application/ecmascript"> + <comment>It's more accurate to say that ECMAScript is a subset of JavaScript</comment> + <sub-class-of type="text/javascript"/> + <glob pattern="*.js"/> + </mime-type> + <mime-type type="text/javascript"> + <comment>than to say that JavaScript is a subset of ECMAScript</comment> + <sub-class-of type="application/ecmascript"/> + <glob pattern="*.js"/> + </mime-type> +</mime-info> diff --git a/tests/auto/corelib/mimetypes/qmimedatabase/qmimedatabase-cache/CMakeLists.txt b/tests/auto/corelib/mimetypes/qmimedatabase/qmimedatabase-cache/CMakeLists.txt index 2d7844493f..a267640a50 100644 --- a/tests/auto/corelib/mimetypes/qmimedatabase/qmimedatabase-cache/CMakeLists.txt +++ b/tests/auto/corelib/mimetypes/qmimedatabase/qmimedatabase-cache/CMakeLists.txt @@ -1,4 +1,11 @@ -# Generated from qmimedatabase-cache.pro. +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qmimedatabase LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() if(NOT QT_FEATURE_private_tests) return() @@ -12,18 +19,19 @@ qt_internal_add_test(tst_qmimedatabase-cache SOURCES ../tst_qmimedatabase.h tst_qmimedatabase-cache.cpp - PUBLIC_LIBRARIES + LIBRARIES + Qt::CorePrivate Qt::Concurrent ) # Resources: -# special case begin # the freedesktop resources are handled manually below via mimetypes_resources.cmake #set(mimetypes_resource_files #"mime/packages/freedesktop.org.xml" #) -# special case end set(testdata_resource_files + "../add-extension.xml" + "../circular-inheritance.xml" "../invalid-magic1.xml" "../invalid-magic2.xml" "../invalid-magic3.xml" @@ -33,6 +41,8 @@ set(testdata_resource_files "../qml-again.xml" "../test.qml" "../text-x-objcsrc.xml" + "../text-plain-subclass.xml" + "../webm-glob-deleteall.xml" "../yast2-metapackage-handler-mimetypes.xml" ) @@ -45,14 +55,17 @@ qt_internal_add_resource(tst_qmimedatabase-cache "testdata" ${testdata_resource_files} ) -# special case begin +qt_internal_add_resource(tst_qmimedatabase-cache "testfiles" + PREFIX + "/files" + FILES + "../test.txt" + "../test.qml" +) + set(corelib_source_dir ../../../../../../src/corelib) include(${corelib_source_dir}/mimetypes/mimetypes_resources.cmake) corelib_add_mimetypes_resources(tst_qmimedatabase-cache) -# special case end - -#### Keys ignored in scope 1:.:.:qmimedatabase-cache.pro:<TRUE>: -# _REQUIREMENTS = "qtConfig(private_tests)" ## Scopes: ##################################################################### diff --git a/tests/auto/corelib/mimetypes/qmimedatabase/qmimedatabase-cache/tst_qmimedatabase-cache.cpp b/tests/auto/corelib/mimetypes/qmimedatabase/qmimedatabase-cache/tst_qmimedatabase-cache.cpp index 8a87d70234..e923cc1d50 100644 --- a/tests/auto/corelib/mimetypes/qmimedatabase/qmimedatabase-cache/tst_qmimedatabase-cache.cpp +++ b/tests/auto/corelib/mimetypes/qmimedatabase/qmimedatabase-cache/tst_qmimedatabase-cache.cpp @@ -1,11 +1,5 @@ // 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 "../tst_qmimedatabase.h" -#include <QDir> -#include <QFile> -#include <QTest> -#include <qstandardpaths.h> +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include "../tst_qmimedatabase.cpp" diff --git a/tests/auto/corelib/mimetypes/qmimedatabase/qmimedatabase-xml/CMakeLists.txt b/tests/auto/corelib/mimetypes/qmimedatabase/qmimedatabase-xml/CMakeLists.txt index 47e9a2f1d7..729ac3933a 100644 --- a/tests/auto/corelib/mimetypes/qmimedatabase/qmimedatabase-xml/CMakeLists.txt +++ b/tests/auto/corelib/mimetypes/qmimedatabase/qmimedatabase-xml/CMakeLists.txt @@ -1,4 +1,11 @@ -# Generated from qmimedatabase-xml.pro. +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qmimedatabase LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() if(NOT QT_FEATURE_private_tests) return() @@ -12,18 +19,19 @@ qt_internal_add_test(tst_qmimedatabase-xml SOURCES ../tst_qmimedatabase.h tst_qmimedatabase-xml.cpp - PUBLIC_LIBRARIES + LIBRARIES Qt::Concurrent + Qt::CorePrivate ) # Resources: -# special case begin # the freedesktop resources are handled manually below via mimetypes_resources.cmake #set(mimetypes_resource_files #"mime/packages/freedesktop.org.xml" #) -# special case end set(testdata_resource_files + "../add-extension.xml" + "../circular-inheritance.xml" "../invalid-magic1.xml" "../invalid-magic2.xml" "../invalid-magic3.xml" @@ -33,6 +41,8 @@ set(testdata_resource_files "../qml-again.xml" "../test.qml" "../text-x-objcsrc.xml" + "../text-plain-subclass.xml" + "../webm-glob-deleteall.xml" "../yast2-metapackage-handler-mimetypes.xml" ) @@ -45,14 +55,17 @@ qt_internal_add_resource(tst_qmimedatabase-xml "testdata" ${testdata_resource_files} ) -# special case begin +qt_internal_add_resource(tst_qmimedatabase-xml "testfiles" + PREFIX + "/files" + FILES + "../test.txt" + "../test.qml" +) + set(corelib_source_dir ../../../../../../src/corelib) include(${corelib_source_dir}/mimetypes/mimetypes_resources.cmake) corelib_add_mimetypes_resources(tst_qmimedatabase-xml) -# special case end - -#### Keys ignored in scope 1:.:.:qmimedatabase-xml.pro:<TRUE>: -# _REQUIREMENTS = "qtConfig(private_tests)" ## Scopes: ##################################################################### diff --git a/tests/auto/corelib/mimetypes/qmimedatabase/qmimedatabase-xml/tst_qmimedatabase-xml.cpp b/tests/auto/corelib/mimetypes/qmimedatabase/qmimedatabase-xml/tst_qmimedatabase-xml.cpp index 72a07595a5..f86c8b8839 100644 --- a/tests/auto/corelib/mimetypes/qmimedatabase/qmimedatabase-xml/tst_qmimedatabase-xml.cpp +++ b/tests/auto/corelib/mimetypes/qmimedatabase/qmimedatabase-xml/tst_qmimedatabase-xml.cpp @@ -1,11 +1,10 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only -#include "../tst_qmimedatabase.h" +#include "../tst_qmimedatabase.cpp" void tst_QMimeDatabase::initTestCaseInternal() { qputenv("QT_NO_MIME_CACHE", "1"); } -#include "../tst_qmimedatabase.cpp" diff --git a/tests/auto/corelib/mimetypes/qmimedatabase/test.qml b/tests/auto/corelib/mimetypes/qmimedatabase/test.qml index 752cf553e9..79a6d01a1e 100644 --- a/tests/auto/corelib/mimetypes/qmimedatabase/test.qml +++ b/tests/auto/corelib/mimetypes/qmimedatabase/test.qml @@ -1,5 +1,5 @@ // Copyright (C) 2012 David Faure <faure@kde.org> -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only import QtQuick 1.1 Item { diff --git a/tests/auto/corelib/mimetypes/qmimedatabase/test.txt b/tests/auto/corelib/mimetypes/qmimedatabase/test.txt new file mode 100644 index 0000000000..79a6d01a1e --- /dev/null +++ b/tests/auto/corelib/mimetypes/qmimedatabase/test.txt @@ -0,0 +1,6 @@ +// Copyright (C) 2012 David Faure <faure@kde.org> +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +import QtQuick 1.1 +Item { +} diff --git a/tests/auto/corelib/mimetypes/qmimedatabase/text-plain-subclass.xml b/tests/auto/corelib/mimetypes/qmimedatabase/text-plain-subclass.xml new file mode 100644 index 0000000000..7b5cb7506d --- /dev/null +++ b/tests/auto/corelib/mimetypes/qmimedatabase/text-plain-subclass.xml @@ -0,0 +1,15 @@ +<?xml version="1.0" encoding="UTF-8"?> +<mime-info xmlns='http://www.freedesktop.org/standards/shared-mime-info'> + <mime-type type="text/x-microdvd"> + <comment>MicroDVD subtitles</comment> + <sub-class-of type="text/plain"/> + <magic priority="50"> + <match type="string" value="{1}" offset="0"/> + <match type="string" value="{0}" offset="0"/> + <match type="string" value="}{" offset="0:6"/> + </magic> + <generic-icon name="text-x-generic"/> + <glob pattern="*.sub"/> + <glob pattern="*.txt"/> + </mime-type> +</mime-info> diff --git a/tests/auto/corelib/mimetypes/qmimedatabase/tst_qmimedatabase.cpp b/tests/auto/corelib/mimetypes/qmimedatabase/tst_qmimedatabase.cpp index fae26f4971..9c7f5fa820 100644 --- a/tests/auto/corelib/mimetypes/qmimedatabase/tst_qmimedatabase.cpp +++ b/tests/auto/corelib/mimetypes/qmimedatabase/tst_qmimedatabase.cpp @@ -1,11 +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 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only +#include "tst_qmimedatabase.h" #include <qmimedatabase.h> #include "qstandardpaths.h" #ifdef Q_OS_UNIX +#include <dirent.h> +#include <fcntl.h> #include <sys/types.h> #include <sys/stat.h> #endif @@ -13,10 +16,12 @@ #include <QtCore/QElapsedTimer> #include <QtCore/QFile> #include <QtCore/QFileInfo> +#include <QtCore/qspan.h> #include <QtCore/QStandardPaths> #include <QtCore/QTemporaryDir> #include <QtCore/QTextStream> #include <QtConcurrent/QtConcurrentRun> +#include <QtCore/private/qduplicatetracker_p.h> #include <QTest> #include <QBuffer> @@ -25,18 +30,30 @@ #include <QProcess> #endif -static const char *const additionalMimeFiles[] = { +using namespace Qt::StringLiterals; + +static const std::array additionalGlobalMimeFiles = { + "yast2-metapackage-handler-mimetypes.xml", + "qml-again.xml", + "magic-and-hierarchy.xml", +}; + +static const std::array additionalLocalMimeFiles = { + "add-extension.xml", // adds *.jnewext to image/jpeg "yast2-metapackage-handler-mimetypes.xml", "qml-again.xml", "text-x-objcsrc.xml", + "text-plain-subclass.xml", "invalid-magic1.xml", "invalid-magic2.xml", "invalid-magic3.xml", "magic-and-hierarchy.xml", - 0 + "circular-inheritance.xml", + "webm-glob-deleteall.xml", }; -#define RESOURCE_PREFIX ":/qt-project.org/qmime/" +static const auto s_resourcePrefix = ":/qt-project.org/qmime/"_L1; +static const auto s_inodeMimetype = "inode/directory"_L1; void initializeLang() { @@ -113,7 +130,6 @@ void tst_QMimeDatabase::initTestCase() if (QDir(m_localMimeDir).exists()) { QVERIFY2(QDir(m_localMimeDir).removeRecursively(), qPrintable(m_localMimeDir + ": " + qt_error_string())); } - QString errorMessage; #ifdef USE_XDG_DATA_DIRS // Create a temporary "global" XDG data dir for later use @@ -129,8 +145,9 @@ void tst_QMimeDatabase::initTestCase() qDebug() << "\nGlobal XDG_DATA_DIRS: " << m_globalXdgDir; const QString freeDesktopXml = QStringLiteral("freedesktop.org.xml"); - const QString xmlFileName = QLatin1String(RESOURCE_PREFIX "packages/") + freeDesktopXml; + const QString xmlFileName = s_resourcePrefix + "packages/"_L1 + freeDesktopXml; const QString xmlTargetFileName = globalPackageDir + QLatin1Char('/') + freeDesktopXml; + QString errorMessage; QVERIFY2(copyResourceFile(xmlFileName, xmlTargetFileName, &errorMessage), qPrintable(errorMessage)); #endif @@ -138,14 +155,6 @@ void tst_QMimeDatabase::initTestCase() if (m_testSuite.isEmpty()) qWarning("%s", qPrintable(testSuiteWarning())); - errorMessage = QString::fromLatin1("Cannot find '%1'"); - for (uint i = 0; i < sizeof additionalMimeFiles / sizeof additionalMimeFiles[0] - 1; i++) { - const QString resourceFilePath = QString::fromLatin1(RESOURCE_PREFIX) + QLatin1String(additionalMimeFiles[i]); - QVERIFY2(QFile::exists(resourceFilePath), qPrintable(errorMessage.arg(resourceFilePath))); - m_additionalMimeFileNames.append(QLatin1String(additionalMimeFiles[i])); - m_additionalMimeFilePaths.append(resourceFilePath); - } - initTestCaseInternal(); m_isUsingCacheProvider = !qEnvironmentVariableIsSet("QT_NO_MIME_CACHE"); } @@ -167,7 +176,7 @@ void tst_QMimeDatabase::mimeTypeForName() QMimeType s0 = db.mimeTypeForName(QString::fromLatin1("application/x-zerosize")); QVERIFY(s0.isValid()); QCOMPARE(s0.name(), QString::fromLatin1("application/x-zerosize")); - QCOMPARE(s0.comment(), QString::fromLatin1("empty document")); + QCOMPARE(s0.comment(), QString::fromLatin1("Empty document")); QMimeType s0Again = db.mimeTypeForName(QString::fromLatin1("application/x-zerosize")); QCOMPARE(s0Again.name(), s0.name()); @@ -175,7 +184,6 @@ void tst_QMimeDatabase::mimeTypeForName() QMimeType s1 = db.mimeTypeForName(QString::fromLatin1("text/plain")); QVERIFY(s1.isValid()); QCOMPARE(s1.name(), QString::fromLatin1("text/plain")); - //qDebug("Comment is %s", qPrintable(s1.comment())); QMimeType krita = db.mimeTypeForName(QString::fromLatin1("application/x-krita")); QVERIFY(krita.isValid()); @@ -187,7 +195,7 @@ void tst_QMimeDatabase::mimeTypeForName() QMimeType bzip2 = db.mimeTypeForName(QString::fromLatin1("application/x-bzip2")); QVERIFY(bzip2.isValid()); - QCOMPARE(bzip2.comment(), QString::fromLatin1("Bzip archive")); + QCOMPARE(bzip2.comment(), QString::fromLatin1("Bzip2 archive")); QMimeType defaultMime = db.mimeTypeForName(QString::fromLatin1("application/octet-stream")); QVERIFY(defaultMime.isValid()); @@ -228,13 +236,15 @@ void tst_QMimeDatabase::mimeTypeForFileName_data() QTest::newRow("case-sensitive uppercase match") << "textfile.C" << "text/x-c++src"; QTest::newRow("case-sensitive lowercase match") << "textfile.c" << "text/x-csrc"; QTest::newRow("case-sensitive long-extension match") << "foo.PS.gz" << "application/x-gzpostscript"; - QTest::newRow("case-sensitive-only match") << "core" << "application/x-core"; - QTest::newRow("case-sensitive-only match") << "Core" << "application/octet-stream"; // #198477 + QTest::newRow("case-sensitive-only-match-core") << "core" << "application/x-core"; + QTest::newRow("case-sensitive-only-match-Core") << "Core" << "application/octet-stream"; // #198477 QTest::newRow("desktop file") << "foo.desktop" << "application/x-desktop"; QTest::newRow("old kdelnk file is x-desktop too") << "foo.kdelnk" << "application/x-desktop"; - QTest::newRow("double-extension file") << "foo.tar.bz2" << "application/x-bzip-compressed-tar"; - QTest::newRow("single-extension file") << "foo.bz2" << "application/x-bzip"; + QTest::newRow("double-extension file") << "foo.tar.bz2" + << "application/x-bzip2-compressed-tar"; + QTest::newRow("single-extension file") << "foo.bz2" + << "application/x-bzip2"; QTest::newRow(".doc should assume msword") << "somefile.doc" << "application/msword"; // #204139 QTest::newRow("glob that uses [] syntax, 1") << "Makefile" << "text/x-makefile"; QTest::newRow("glob that uses [] syntax, 2") << "makefile" << "text/x-makefile"; @@ -245,6 +255,7 @@ void tst_QMimeDatabase::mimeTypeForFileName_data() // fdo bug 15436, needs shared-mime-info >= 0.40 (and this tests the globs2-parsing code). QTest::newRow("glob that ends with *, also matches *.pdf. *.pdf has higher weight") << "README.pdf" << "application/pdf"; QTest::newRow("directory") << "/" << "inode/directory"; + QTest::newRow("resource-directory") << ":/files/" << "inode/directory"; QTest::newRow("doesn't exist, no extension") << "IDontExist" << "application/octet-stream"; QTest::newRow("doesn't exist but has known extension") << "IDontExist.txt" << "text/plain"; QTest::newRow("empty") << "" << "application/octet-stream"; @@ -254,7 +265,7 @@ static inline QByteArray msgMimeTypeForFileNameFailed(const QList<QMimeType> &ac const QString &expected) { QByteArray result = "Actual ("; - foreach (const QMimeType &m, actual) { + for (const QMimeType &m : actual) { result += m.name().toLocal8Bit(); result += ' '; } @@ -272,12 +283,12 @@ void tst_QMimeDatabase::mimeTypeForFileName() QVERIFY(mime.isValid()); QCOMPARE(mime.name(), expectedMimeType); - QList<QMimeType> mimes = db.mimeTypesForFileName(fileName); + const QList<QMimeType> mimes = db.mimeTypesForFileName(fileName); if (expectedMimeType == "application/octet-stream") { QVERIFY(mimes.isEmpty()); } else { QVERIFY2(!mimes.isEmpty(), msgMimeTypeForFileNameFailed(mimes, expectedMimeType).constData()); - QVERIFY2(mimes.count() == 1, msgMimeTypeForFileNameFailed(mimes, expectedMimeType).constData()); + QVERIFY2(mimes.size() == 1, msgMimeTypeForFileNameFailed(mimes, expectedMimeType).constData()); QCOMPARE(mimes.first().name(), expectedMimeType); } } @@ -294,15 +305,22 @@ void tst_QMimeDatabase::mimeTypesForFileName_data() QTest::newRow("non_ascii") << QString::fromUtf8("AİİA.pdf") << (QStringList() << "application/pdf"); } +static QStringList mimeTypeNames(const QList<QMimeType> &mimes) +{ + QStringList mimeNames; + mimeNames.reserve(mimes.size()); + for (const auto &mime : mimes) + mimeNames.append(mime.name()); + return mimeNames; +} + void tst_QMimeDatabase::mimeTypesForFileName() { QFETCH(QString, fileName); QFETCH(QStringList, expectedMimeTypes); QMimeDatabase db; QList<QMimeType> mimes = db.mimeTypesForFileName(fileName); - QStringList mimeNames; - foreach (const QMimeType &mime, mimes) - mimeNames.append(mime.name()); + QStringList mimeNames = mimeTypeNames(mimes); QCOMPARE(mimeNames, expectedMimeTypes); } @@ -326,9 +344,9 @@ void tst_QMimeDatabase::inheritance() QVERIFY(msword.inherits(olestorage.name())); QVERIFY(msword.inherits(QLatin1String("application/octet-stream"))); - const QMimeType directory = db.mimeTypeForName(QString::fromLatin1("inode/directory")); + const QMimeType directory = db.mimeTypeForName(s_inodeMimetype); QVERIFY(directory.isValid()); - QCOMPARE(directory.parentMimeTypes().count(), 0); + QCOMPARE(directory.parentMimeTypes().size(), 0); QVERIFY(!directory.inherits(QLatin1String("application/octet-stream"))); // Check that text/x-patch knows that it inherits from text/plain (it says so explicitly) @@ -349,7 +367,7 @@ void tst_QMimeDatabase::inheritance() const QStringList shellParents = shellscript.parentMimeTypes(); QVERIFY(shellParents.contains(QLatin1String("text/plain"))); QVERIFY(shellParents.contains(QLatin1String("application/x-executable"))); - QCOMPARE(shellParents.count(), 2); // only the above two + QCOMPARE(shellParents.size(), 2); // only the above two const QStringList allShellAncestors = shellscript.allAncestors(); QVERIFY(allShellAncestors.contains(QLatin1String("text/plain"))); QVERIFY(allShellAncestors.contains(QLatin1String("application/x-executable"))); @@ -370,6 +388,13 @@ void tst_QMimeDatabase::inheritance() const QMimeType mswordTemplate = db.mimeTypeForName(QString::fromLatin1("application/msword-template")); QVERIFY(mswordTemplate.isValid()); QVERIFY(mswordTemplate.inherits(QLatin1String("application/msword"))); + + // Check that buggy type definitions that have circular inheritance don't cause an infinite + // loop, especially when resolving a conflict between the file's name and its contents + const QMimeType ecmascript = db.mimeTypeForName(QString::fromLatin1("application/ecmascript")); + QVERIFY(ecmascript.allAncestors().contains("text/plain")); + const QMimeType javascript = db.mimeTypeForFileNameAndData("xml.js", "<?xml?>"); + QVERIFY(javascript.inherits(QString::fromLatin1("text/javascript"))); } void tst_QMimeDatabase::aliases() @@ -420,7 +445,7 @@ void tst_QMimeDatabase::icons() { QMimeDatabase db; QMimeType directory = db.mimeTypeForFile(QString::fromLatin1("/")); - QCOMPARE(directory.name(), QString::fromLatin1("inode/directory")); + QCOMPARE(directory.name(), s_inodeMimetype); QCOMPARE(directory.iconName(), QString::fromLatin1("inode-directory")); QCOMPARE(directory.genericIconName(), QString::fromLatin1("folder")); @@ -439,10 +464,13 @@ void tst_QMimeDatabase::comment() QLocale::setDefault(QLocale("de")); QMimeDatabase db; - QMimeType directory = db.mimeTypeForName(QStringLiteral("inode/directory")); + QMimeType directory = db.mimeTypeForName(s_inodeMimetype); QCOMPARE(directory.comment(), QStringLiteral("Ordner")); QLocale::setDefault(QLocale("fr")); - QCOMPARE(directory.comment(), QStringLiteral("dossier")); + // Missing in s-m-i 2.3 due to case changes + // QCOMPARE(directory.comment(), QStringLiteral("dossier")); + QMimeType cpp = db.mimeTypeForName("text/x-c++src"); + QCOMPARE(cpp.comment(), QStringLiteral("code source C++")); } // In here we do the tests that need some content in a temporary file. @@ -497,6 +525,42 @@ void tst_QMimeDatabase::mimeTypeForFileWithContent() QCOMPARE(mime.name(), QString::fromLatin1("application/smil+xml")); } + // Test what happens with Qt resources (file engines in general) + { + QFile rccFile(":/files/test.txt"); + + mime = db.mimeTypeForFile(rccFile.fileName()); + QCOMPARE(mime.name(), "text/plain"_L1); + + QVERIFY(rccFile.open(QIODevice::ReadOnly)); + mime = db.mimeTypeForData(&rccFile); + QCOMPARE(mime.name(), "text/x-qml"_L1); + QVERIFY(rccFile.isOpen()); + + mime = db.mimeTypeForFile(rccFile.fileName(), QMimeDatabase::MatchContent); + QCOMPARE(mime.name(), "text/x-qml"_L1); + } + + // Directories + { + mime = db.mimeTypeForFile("/"); + QCOMPARE(mime.name(), "inode/directory"_L1); + + QString dirName = QDir::tempPath(); + if (!dirName.endsWith(u'/')) + dirName += u'/'; + mime = db.mimeTypeForFile(dirName); + QCOMPARE(mime.name(), "inode/directory"_L1); + + while (dirName.endsWith(u'/')) + dirName.chop(1); + mime = db.mimeTypeForFile(dirName); + QCOMPARE(mime.name(), "inode/directory"_L1); + + mime = db.mimeTypeForFile(":/files"); + QCOMPARE(mime.name(), "inode/directory"_L1); + } + // Test what happens with an incorrect path mime = db.mimeTypeForFile(QString::fromLatin1("file:///etc/passwd" /* incorrect code, use a path instead */)); QVERIFY(mime.isDefault()); @@ -546,7 +610,7 @@ void tst_QMimeDatabase::mimeTypeForData() QCOMPARE(buffer.pos(), qint64(0)); } -void tst_QMimeDatabase::mimeTypeForFileAndContent_data() +void tst_QMimeDatabase::mimeTypeForFileNameAndData_data() { QTest::addColumn<QString>("name"); QTest::addColumn<QByteArray>("data"); @@ -565,7 +629,7 @@ void tst_QMimeDatabase::mimeTypeForFileAndContent_data() QTest::newRow("text.xls, found by extension, user is in control") << QString::fromLatin1("text.xls") << oleData << "application/vnd.ms-excel"; } -void tst_QMimeDatabase::mimeTypeForFileAndContent() +void tst_QMimeDatabase::mimeTypeForFileNameAndData() { QFETCH(QString, name); QFETCH(QByteArray, data); @@ -584,6 +648,86 @@ void tst_QMimeDatabase::mimeTypeForFileAndContent() QCOMPARE(buffer.pos(), qint64(0)); } +#ifdef Q_OS_UNIX +void tst_QMimeDatabase::mimeTypeForUnixSpecials_data() +{ +#ifndef AT_FDCWD + QSKIP("fdopendir and fstatat are not available"); +#else + QTest::addColumn<QString>("name"); + QTest::addColumn<QString>("expected"); + + static const char * const mimeTypes[] = { + "inode/blockdevice", + "inode/chardevice", + "inode/fifo", + "inode/socket", + }; + enum SpecialType { + FoundBlock = 0, + FoundChar = 1, + FoundFifo = 2, + FoundSocket = 3, + }; + uint found = 0; + auto nothingfound = []() { + QSKIP("No special Unix inode types found!"); + }; + + // on a standard Linux system (systemd), /dev/log is a symlink to a socket + // and /dev/initctl is a symlink to a FIFO + int devfd = open("/dev", O_RDONLY); + DIR *devdir = fdopendir(devfd); // takes ownership + if (!devdir) + return nothingfound(); + + while (struct dirent *ent = readdir(devdir)) { + struct stat statbuf; + if (fstatat(devfd, ent->d_name, &statbuf, 0) < 0) + continue; + + SpecialType type; + if (S_ISBLK(statbuf.st_mode)) { + type = FoundBlock; + } else if (S_ISCHR(statbuf.st_mode)) { + type = FoundChar; + } else if (S_ISFIFO(statbuf.st_mode)) { + type = FoundFifo; + } else if (S_ISSOCK(statbuf.st_mode)) { + type = FoundSocket; + } else { + if (!S_ISREG(statbuf.st_mode) && !S_ISDIR(statbuf.st_mode)) + qWarning("Could not tell what file type '%s' is: %#o'", + ent->d_name, statbuf.st_mode); + continue; + } + + if (found & (1U << type)) + continue; // we've already seen such a type + + const char *mimeType = mimeTypes[type]; + QTest::addRow("%s", mimeType) + << u"/dev/"_s + QFile::decodeName(ent->d_name) << mimeType; + found |= (1U << type); + } + closedir(devdir); + + if (!found) + nothingfound(); +#endif +} + +void tst_QMimeDatabase::mimeTypeForUnixSpecials() +{ + QFETCH(QString, name); + QFETCH(QString, expected); + + qInfo() << "Testing that" << name << "is" << expected; + QMimeDatabase db; + QCOMPARE(db.mimeTypeForFile(name).name(), expected); +} +#endif + void tst_QMimeDatabase::allMimeTypes() { QMimeDatabase db; @@ -591,9 +735,9 @@ void tst_QMimeDatabase::allMimeTypes() QVERIFY(!lst.isEmpty()); // Hardcoding this is the only way to check both providers find the same number of mimetypes. - QCOMPARE(lst.count(), 851); + QCOMPARE(lst.size(), 908); - foreach (const QMimeType &mime, lst) { + for (const QMimeType &mime : lst) { const QString name = mime.name(); QVERIFY(!name.isEmpty()); QCOMPARE(name.count(QLatin1Char('/')), 1); @@ -610,13 +754,15 @@ void tst_QMimeDatabase::suffixes_data() QTest::addColumn<QString>("preferredSuffix"); QTest::newRow("mimetype with a single pattern") << "application/pdf" << "*.pdf" << "pdf"; - QTest::newRow("mimetype with multiple patterns") << "application/x-kpresenter" << "*.kpr;*.kpt" << "kpr"; + QTest::newRow("mimetype-with-multiple-patterns-kpr") << "application/x-kpresenter" << "*.kpr;*.kpt" << "kpr"; // The preferred suffix for image/jpeg is *.jpg, as per https://bugs.kde.org/show_bug.cgi?id=176737 - QTest::newRow("jpeg") << "image/jpeg" << "*.jpe;*.jpg;*.jpeg" << "jpg"; + QTest::newRow("jpeg") << "image/jpeg" + << "*.jfif;*.jpe;*.jpg;*.jpeg" + << "jpg"; QTest::newRow("mimetype with many patterns") << "application/vnd.wordperfect" << "*.wp;*.wp4;*.wp5;*.wp6;*.wpd;*.wpp" << "wp"; QTest::newRow("oasis text mimetype") << "application/vnd.oasis.opendocument.text" << "*.odt" << "odt"; QTest::newRow("oasis presentation mimetype") << "application/vnd.oasis.opendocument.presentation" << "*.odp" << "odp"; - QTest::newRow("mimetype with multiple patterns") << "text/plain" << "*.asc;*.txt;*,v" << "txt"; + QTest::newRow("mimetype-multiple-patterns-text-plain") << "text/plain" << "*.asc;*.txt;*,v" << "txt"; QTest::newRow("mimetype with uncommon pattern") << "text/x-readme" << "README*" << QString(); QTest::newRow("mimetype with no patterns") << "application/x-ole-storage" << QString() << QString(); QTest::newRow("default_mimetype") << "application/octet-stream" << QString() << QString(); @@ -651,6 +797,26 @@ void tst_QMimeDatabase::knownSuffix() QCOMPARE(db.suffixForFileName(QString::fromLatin1("foo.anim2")), QString()); // the glob is anim[0-9], no way to extract the extension without expensive regexp capturing } +void tst_QMimeDatabase::filterString_data() +{ + QTest::addColumn<QString>("mimeType"); + QTest::addColumn<QString>("expectedFilterString"); + + QTest::newRow("single-pattern") << "application/pdf" + << "PDF document (*.pdf)"; + QTest::newRow("multiple-patterns-text-plain") << "text/plain" + << "Plain text document (*.txt *.asc *,v)"; +} + +void tst_QMimeDatabase::filterString() +{ + QFETCH(QString, mimeType); + QFETCH(QString, expectedFilterString); + + QMimeDatabase db; + QCOMPARE(db.mimeTypeForName(mimeType).filterString(), expectedFilterString); +} + void tst_QMimeDatabase::symlinkToFifo() // QTBUG-48529 { #if defined(Q_OS_UNIX) && !defined(Q_OS_INTEGRITY) @@ -690,8 +856,10 @@ void tst_QMimeDatabase::findByFileName_data() QByteArray line(1024, Qt::Uninitialized); + QDuplicateTracker<QString, 800> seen; + while (!f.atEnd()) { - int len = f.readLine(line.data(), 1023); + const qint64 len = f.readLine(line.data(), 1023); if (len <= 2 || line.at(0) == '#') continue; @@ -705,10 +873,16 @@ void tst_QMimeDatabase::findByFileName_data() QString xFail; if (list.size() >= 3) xFail = list.at(2); + QString rowTag = filePath; + if (seen.hasSeen(rowTag)) { + // Two testcases for the same file, e.g. + // test.ogg audio/ogg oxx + // test.ogg audio/x-vorbis+ogg x + rowTag += "_2"; + } - QTest::newRow(filePath.toLatin1().constData()) - << QString(prefix + filePath) - << mimeTypeType << xFail; + QTest::newRow(rowTag.toLatin1().constData()) + << QString(prefix + filePath) << mimeTypeType << xFail; } } @@ -720,28 +894,11 @@ void tst_QMimeDatabase::findByFileName() QMimeDatabase database; - //qDebug() << Q_FUNC_INFO << filePath; - const QMimeType resultMimeType(database.mimeTypeForFile(filePath, QMimeDatabase::MatchExtension)); - if (resultMimeType.isValid()) { - //qDebug() << Q_FUNC_INFO << "MIME type" << resultMimeType.name() << "has generic icon name" << resultMimeType.genericIconName() << "and icon name" << resultMimeType.iconName(); - -// Loading icons depend on the icon theme, we can't enable this test -#if 0 - QCOMPARE(resultMimeType.genericIconName(), QIcon::fromTheme(resultMimeType.genericIconName()).name()); - QVERIFY2(!QIcon::fromTheme(resultMimeType.genericIconName()).isNull(), qPrintable(resultMimeType.genericIconName())); - QVERIFY2(QIcon::hasThemeIcon(resultMimeType.genericIconName()), qPrintable(resultMimeType.genericIconName())); - - QCOMPARE(resultMimeType.iconName(), QIcon::fromTheme(resultMimeType.iconName()).name()); - QVERIFY2(!QIcon::fromTheme(resultMimeType.iconName()).isNull(), qPrintable(resultMimeType.iconName())); - QVERIFY2(QIcon::hasThemeIcon(resultMimeType.iconName()), qPrintable(resultMimeType.iconName())); -#endif - } const QString resultMimeTypeName = resultMimeType.name(); - //qDebug() << Q_FUNC_INFO << "mimeTypeForFile() returned" << resultMimeTypeName; const bool failed = resultMimeTypeName != mimeTypeName; - const bool shouldFail = (xFail.length() >= 1 && xFail.at(0) == QLatin1Char('x')); + const bool shouldFail = (xFail.size() >= 1 && xFail.at(0) == QLatin1Char('x')); if (shouldFail != failed) { // Results are ambiguous when multiple MIME types have the same glob // -> accept the current result if the found MIME type actually @@ -751,7 +908,6 @@ void tst_QMimeDatabase::findByFileName() QVERIFY2(resultMimeType == foundMimeType, qPrintable(resultMimeType.name() + QString::fromLatin1(" vs. ") + foundMimeType.name())); if (foundMimeType.isValid()) { const QString extension = QFileInfo(filePath).suffix(); - //qDebug() << Q_FUNC_INFO << "globPatterns:" << foundMimeType.globPatterns() << "- extension:" << QString() + "*." + extension; if (foundMimeType.globPatterns().contains(QString::fromLatin1("*.") + extension)) return; } @@ -788,7 +944,7 @@ void tst_QMimeDatabase::findByData() QByteArray data = f.read(16384); const QString resultMimeTypeName = database.mimeTypeForData(data).name(); - if (xFail.length() >= 2 && xFail.at(1) == QLatin1Char('x')) { + if (xFail.size() >= 2 && xFail.at(1) == QLatin1Char('x')) { // Expected to fail QVERIFY2(resultMimeTypeName != mimeTypeName, qPrintable(resultMimeTypeName)); } else { @@ -818,8 +974,7 @@ void tst_QMimeDatabase::findByFile() QMimeDatabase database; const QString resultMimeTypeName = database.mimeTypeForFile(filePath).name(); - //qDebug() << Q_FUNC_INFO << filePath << "->" << resultMimeTypeName; - if (xFail.length() >= 3 && xFail.at(2) == QLatin1Char('x')) { + if (xFail.size() >= 3 && xFail.at(2) == QLatin1Char('x')) { // Expected to fail QVERIFY2(resultMimeTypeName != mimeTypeName, qPrintable(resultMimeTypeName)); } else { @@ -886,7 +1041,7 @@ static bool waitAndRunUpdateMimeDatabase(const QString &path) QFileInfo mimeCacheInfo(path + QString::fromLatin1("/mime.cache")); if (mimeCacheInfo.exists()) { // Wait until the beginning of the next second - while (mimeCacheInfo.lastModified().secsTo(QDateTime::currentDateTime()) == 0) { + while (mimeCacheInfo.lastModified(QTimeZone::UTC).secsTo(QDateTime::currentDateTimeUtc()) == 0) { QTest::qSleep(200); } } @@ -900,7 +1055,8 @@ static void checkHasMimeType(const QString &mimeType) QVERIFY(db.mimeTypeForName(mimeType).isValid()); bool found = false; - foreach (const QMimeType &mt, db.allMimeTypes()) { + const auto all = db.allMimeTypes(); + for (const QMimeType &mt : all) { if (mt.name() == mimeType) { found = true; break; @@ -921,6 +1077,30 @@ QT_BEGIN_NAMESPACE extern Q_CORE_EXPORT int qmime_secondsBetweenChecks; // see qmimeprovider.cpp QT_END_NAMESPACE +void copyFiles(const QSpan<const char *const> &additionalMimeFiles, const QString &destDir) +{ + const QString notFoundErrorMessage = QString::fromLatin1("Cannot find '%1'"); + for (const char *mimeFile : additionalMimeFiles) { + const QString resourceFilePath = s_resourcePrefix + QLatin1String(mimeFile); + QVERIFY2(QFile::exists(resourceFilePath), + qPrintable(notFoundErrorMessage.arg(resourceFilePath))); + + const QString destFile = destDir + QLatin1String(mimeFile); + QFile::remove(destFile); + QString errorMessage; + QVERIFY2(copyResourceFile(resourceFilePath, destFile, &errorMessage), + qPrintable(errorMessage)); + } +} + +void deleteFiles(const QSpan<const char *const> &additionalMimeFiles, const QString &destDir) +{ + for (const char *mimeFile : additionalMimeFiles) { + const QString destFile = destDir + QLatin1String(mimeFile); + QFile::remove(destFile); + } +} + void tst_QMimeDatabase::installNewGlobalMimeType() { #if !defined(USE_XDG_DATA_DIRS) @@ -940,41 +1120,28 @@ void tst_QMimeDatabase::installNewGlobalMimeType() if (!QFileInfo(destDir).isDir()) QVERIFY(QDir(m_globalXdgDir).mkpath(destDir)); - QString errorMessage; - for (int i = 0; i < m_additionalMimeFileNames.size(); ++i) { - const QString destFile = destDir + m_additionalMimeFileNames.at(i); - QFile::remove(destFile); - QVERIFY2(copyResourceFile(m_additionalMimeFilePaths.at(i), destFile, &errorMessage), qPrintable(errorMessage)); - } + copyFiles(additionalGlobalMimeFiles, destDir); + QVERIFY(!QTest::currentTestFailed()); if (m_isUsingCacheProvider && !waitAndRunUpdateMimeDatabase(mimeDir)) QSKIP("shared-mime-info not found, skipping mime.cache test"); - if (!m_isUsingCacheProvider) - ignoreInvalidMimetypeWarnings(mimeDir); - QCOMPARE(db.mimeTypeForFile(QLatin1String("foo.ymu"), QMimeDatabase::MatchExtension).name(), QString::fromLatin1("text/x-SuSE-ymu")); QVERIFY(db.mimeTypeForName(QLatin1String("text/x-suse-ymp")).isValid()); checkHasMimeType("text/x-suse-ymp"); // Test that a double-definition of a mimetype doesn't lead to sniffing ("conflicting globs"). - const QString qmlTestFile = QLatin1String(RESOURCE_PREFIX "test.qml"); + const QString qmlTestFile = s_resourcePrefix + "test.qml"_L1; QVERIFY2(!qmlTestFile.isEmpty(), qPrintable(QString::fromLatin1("Cannot find '%1' starting from '%2'"). arg("test.qml", QDir::currentPath()))); QCOMPARE(db.mimeTypeForFile(qmlTestFile).name(), QString::fromLatin1("text/x-qml")); - { - QMimeType objcsrc = db.mimeTypeForName(QStringLiteral("text/x-objcsrc")); - QVERIFY(objcsrc.isValid()); - QCOMPARE(objcsrc.globPatterns(), QStringList()); - } - - const QString fooTestFile = QLatin1String(RESOURCE_PREFIX "magic-and-hierarchy.foo"); + const QString fooTestFile = s_resourcePrefix + "magic-and-hierarchy.foo"_L1; QCOMPARE(db.mimeTypeForFile(fooTestFile).name(), QString::fromLatin1("application/foo")); - const QString fooTestFile2 = QLatin1String(RESOURCE_PREFIX "magic-and-hierarchy2.foo"); + const QString fooTestFile2 = s_resourcePrefix + "magic-and-hierarchy2.foo"_L1; QCOMPARE(db.mimeTypeForFile(fooTestFile2).name(), QString::fromLatin1("application/vnd.qnx.bar-descriptor")); // Test if we can use the default comment @@ -992,8 +1159,7 @@ void tst_QMimeDatabase::installNewGlobalMimeType() } // Now test removing the mimetype definitions again - for (int i = 0; i < m_additionalMimeFileNames.size(); ++i) - QFile::remove(destDir + m_additionalMimeFileNames.at(i)); + deleteFiles(additionalGlobalMimeFiles, destDir); if (m_isUsingCacheProvider && !waitAndRunUpdateMimeDatabase(mimeDir)) QSKIP("shared-mime-info not found, skipping mime.cache test"); QCOMPARE(db.mimeTypeForFile(QLatin1String("foo.ymu"), QMimeDatabase::MatchExtension).name(), @@ -1002,11 +1168,29 @@ void tst_QMimeDatabase::installNewGlobalMimeType() #endif // QT_CONFIG(process) } +void tst_QMimeDatabase::installNewLocalMimeType_data() +{ + QTest::addColumn<bool>("useLocalBinaryCache"); + + // Test mixing the providers: + // * m_isUsingCacheProvider is about the global directory. + // ** when true, we'll test both for the local directory. + // ** when false, we can't, because QT_NO_MIME_CACHE is set, so it's XML+XML only + +#if QT_CONFIG(process) + if (m_isUsingCacheProvider) + QTest::newRow("with_binary_cache") << true; +#endif + QTest::newRow("without_binary_cache") << false; +} + void tst_QMimeDatabase::installNewLocalMimeType() { #if !QT_CONFIG(process) QSKIP("This test requires QProcess support"); #else + QFETCH(bool, useLocalBinaryCache); + qmime_secondsBetweenChecks = 0; QMimeDatabase db; @@ -1017,19 +1201,16 @@ void tst_QMimeDatabase::installNewLocalMimeType() const QString destDir = m_localMimeDir + QLatin1String("/packages/"); QVERIFY(QDir().mkpath(destDir)); - QString errorMessage; - for (int i = 0; i < m_additionalMimeFileNames.size(); ++i) { - const QString destFile = destDir + m_additionalMimeFileNames.at(i); - QFile::remove(destFile); - QVERIFY2(copyResourceFile(m_additionalMimeFilePaths.at(i), destFile, &errorMessage), qPrintable(errorMessage)); - } - if (m_isUsingCacheProvider && !waitAndRunUpdateMimeDatabase(m_localMimeDir)) { + + copyFiles(additionalLocalMimeFiles, destDir); + QVERIFY(!QTest::currentTestFailed()); + if (useLocalBinaryCache && !waitAndRunUpdateMimeDatabase(m_localMimeDir)) { const QString skipWarning = QStringLiteral("shared-mime-info not found, skipping mime.cache test (") + QDir::toNativeSeparators(m_localMimeDir) + QLatin1Char(')'); QSKIP(qPrintable(skipWarning)); } - if (!m_isUsingCacheProvider) + if (!useLocalBinaryCache) ignoreInvalidMimetypeWarnings(m_localMimeDir); QVERIFY(db.mimeTypeForName(QLatin1String("text/x-suse-ymp")).isValid()); @@ -1050,15 +1231,33 @@ void tst_QMimeDatabase::installNewLocalMimeType() QVERIFY(objcsrc.isValid()); QCOMPARE(objcsrc.globPatterns(), QStringList()); } + QCOMPARE(db.mimeTypeForFile(QLatin1String("foo.txt"), QMimeDatabase::MatchExtension).name(), + QString::fromLatin1("text/plain")); // Test that a double-definition of a mimetype doesn't lead to sniffing ("conflicting globs"). - const QString qmlTestFile = QLatin1String(RESOURCE_PREFIX "test.qml"); + const QString qmlTestFile = s_resourcePrefix + "test.qml"_L1; QVERIFY2(!qmlTestFile.isEmpty(), qPrintable(QString::fromLatin1("Cannot find '%1' starting from '%2'"). arg("test.qml", QDir::currentPath()))); QCOMPARE(db.mimeTypeForFile(qmlTestFile).name(), QString::fromLatin1("text/x-qml")); + { // QTBUG-101755 + QList<QMimeType> mimes = db.mimeTypesForFileName(u"foo.webm"_s); + // "*.webm" glob pattern is deleted with "glob-deleteall" + QVERIFY2(mimes.isEmpty(), qPrintable(mimeTypeNames(mimes).join(u','))); + mimes = db.mimeTypesForFileName(u"foo.videowebm"_s); + QCOMPARE(mimes.size(), 1); + QCOMPARE(mimes.at(0).globPatterns(), QStringList{ "*.videowebm" }); + // Custom "*.videowebm" pattern is used instead + QCOMPARE(mimes.at(0).name(), u"video/webm"); + } + + // QTBUG-116905: globPatterns() should merge all locations + // add-extension.xml adds *.jnewext + const QStringList expectedJpegPatterns{ "*.jpg", "*.jpeg", "*.jpe", "*.jfif", "*.jnewext" }; + QCOMPARE(db.mimeTypeForName(QStringLiteral("image/jpeg")).globPatterns(), expectedJpegPatterns); + // Now that we have two directories with mime definitions, check that everything still works inheritance(); if (QTest::currentTestFailed()) @@ -1087,7 +1286,7 @@ void tst_QMimeDatabase::installNewLocalMimeType() // Now test removing local mimetypes for (int i = 1 ; i <= 3 ; ++i) QFile::remove(destDir + QStringLiteral("invalid-magic%1.xml").arg(i)); - if (m_isUsingCacheProvider && !waitAndRunUpdateMimeDatabase(m_localMimeDir)) + if (useLocalBinaryCache && !waitAndRunUpdateMimeDatabase(m_localMimeDir)) QSKIP("shared-mime-info not found, skipping mime.cache test"); QVERIFY(!db.mimeTypeForName(QLatin1String("text/invalid-magic1")).isValid()); // deleted QVERIFY(db.mimeTypeForName(QLatin1String("text/x-suse-ymp")).isValid()); // still present @@ -1102,7 +1301,7 @@ void tst_QMimeDatabase::installNewLocalMimeType() QCOMPARE(db.mimeTypeForFile(QLatin1String("foo.ymu"), QMimeDatabase::MatchExtension).name(), QString::fromLatin1("application/octet-stream")); QVERIFY(!db.mimeTypeForName(QLatin1String("text/x-suse-ymp")).isValid()); -#endif // QT_CONFIG(process) +#endif } QTEST_GUILESS_MAIN(tst_QMimeDatabase) diff --git a/tests/auto/corelib/mimetypes/qmimedatabase/tst_qmimedatabase.h b/tests/auto/corelib/mimetypes/qmimedatabase/tst_qmimedatabase.h index 5818e1b6eb..415c2e3e37 100644 --- a/tests/auto/corelib/mimetypes/qmimedatabase/tst_qmimedatabase.h +++ b/tests/auto/corelib/mimetypes/qmimedatabase/tst_qmimedatabase.h @@ -1,5 +1,5 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #ifndef TST_QMIMEDATABASE_H #define TST_QMIMEDATABASE_H @@ -35,12 +35,18 @@ private slots: void mimeTypeForUrl(); void mimeTypeForData_data(); void mimeTypeForData(); - void mimeTypeForFileAndContent_data(); - void mimeTypeForFileAndContent(); + void mimeTypeForFileNameAndData_data(); + void mimeTypeForFileNameAndData(); +#ifdef Q_OS_UNIX + void mimeTypeForUnixSpecials_data(); + void mimeTypeForUnixSpecials(); +#endif void allMimeTypes(); void suffixes_data(); void suffixes(); void knownSuffix(); + void filterString_data(); + void filterString(); void symlinkToFifo(); void fromThreads(); @@ -58,6 +64,7 @@ private slots: // void installNewGlobalMimeType(); + void installNewLocalMimeType_data(); void installNewLocalMimeType(); private: diff --git a/tests/auto/corelib/mimetypes/qmimedatabase/webm-glob-deleteall.xml b/tests/auto/corelib/mimetypes/qmimedatabase/webm-glob-deleteall.xml new file mode 100644 index 0000000000..05a24de17c --- /dev/null +++ b/tests/auto/corelib/mimetypes/qmimedatabase/webm-glob-deleteall.xml @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="UTF-8"?> +<mime-info xmlns="http://www.freedesktop.org/standards/shared-mime-info"> + <mime-type type="video/webm"> + <glob-deleteall/> + <glob pattern="*.videowebm"/> + </mime-type> +</mime-info> diff --git a/tests/auto/corelib/mimetypes/qmimetype/CMakeLists.txt b/tests/auto/corelib/mimetypes/qmimetype/CMakeLists.txt index bb84fce94f..605cdccc3f 100644 --- a/tests/auto/corelib/mimetypes/qmimetype/CMakeLists.txt +++ b/tests/auto/corelib/mimetypes/qmimetype/CMakeLists.txt @@ -1,12 +1,20 @@ -# Generated from qmimetype.pro. +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## tst_qmimetype Test: ##################################################################### +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qmimetype LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + qt_internal_add_test(tst_qmimetype SOURCES tst_qmimetype.cpp - PUBLIC_LIBRARIES + LIBRARIES Qt::CorePrivate + Qt::TestPrivate ) diff --git a/tests/auto/corelib/mimetypes/qmimetype/tst_qmimetype.cpp b/tests/auto/corelib/mimetypes/qmimetype/tst_qmimetype.cpp index fda12298fe..b96e8feffa 100644 --- a/tests/auto/corelib/mimetypes/qmimetype/tst_qmimetype.cpp +++ b/tests/auto/corelib/mimetypes/qmimetype/tst_qmimetype.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <private/qmimetype_p.h> @@ -8,7 +8,7 @@ #include <QVariantMap> #include <QTest> - +#include <QtTest/private/qcomparisontesthelper_p.h> class tst_qmimetype : public QObject { @@ -17,11 +17,12 @@ class tst_qmimetype : public QObject private slots: void initTestCase(); + void compareCompiles(); void isValid(); + void compareQMimetypes(); void name(); void genericIconName(); void iconName(); - void suffixes(); void gadget(); }; @@ -36,58 +37,43 @@ void tst_qmimetype::initTestCase() static QString qMimeTypeName() { - static const QString result ("No name of the MIME type"); + static const QString result("group/fake-mime"); return result; } -static QString qMimeTypeGenericIconName() -{ - static const QString result ("No file name of an icon image that represents the MIME type"); - return result; -} +// ------------------------------------------------------------------------------------------------ -static QString qMimeTypeIconName() +void tst_qmimetype::compareCompiles() { - static const QString result ("No file name of an icon image that represents the MIME type"); - return result; + QTestPrivate::testEqualityOperatorsCompile<QMimeType>(); } -static QStringList buildQMimeTypeFilenameExtensions() -{ - QStringList result; - result << QString::fromLatin1("*.png"); - return result; -} +// ------------------------------------------------------------------------------------------------ -static QStringList qMimeTypeGlobPatterns() +void tst_qmimetype::compareQMimetypes() { - static const QStringList result (buildQMimeTypeFilenameExtensions()); - return result; -} - -// ------------------------------------------------------------------------------------------------ + QMimeType instantiatedQMimeType{ QMimeTypePrivate(qMimeTypeName()) }; + QMimeType otherQMimeType (instantiatedQMimeType); + QMimeType defaultQMimeType; -QMIMETYPE_BUILDER_FROM_RVALUE_REFS + QVERIFY(!defaultQMimeType.isValid()); + QT_TEST_EQUALITY_OPS(defaultQMimeType, QMimeType(), true); + QT_TEST_EQUALITY_OPS(QMimeType(), QMimeType(), true); + QT_TEST_EQUALITY_OPS(instantiatedQMimeType, QMimeType(), false); + QT_TEST_EQUALITY_OPS(otherQMimeType, defaultQMimeType, false); +} // ------------------------------------------------------------------------------------------------ void tst_qmimetype::isValid() { - QMimeType instantiatedQMimeType ( - buildQMimeType ( - qMimeTypeName(), - qMimeTypeGenericIconName(), - qMimeTypeIconName(), - qMimeTypeGlobPatterns() - ) - ); - + QMimeType instantiatedQMimeType{ QMimeTypePrivate(qMimeTypeName()) }; QVERIFY(instantiatedQMimeType.isValid()); QMimeType otherQMimeType (instantiatedQMimeType); QVERIFY(otherQMimeType.isValid()); - QCOMPARE(instantiatedQMimeType, otherQMimeType); + QT_TEST_EQUALITY_OPS(instantiatedQMimeType, otherQMimeType, true); QMimeType defaultQMimeType; @@ -98,92 +84,36 @@ void tst_qmimetype::isValid() void tst_qmimetype::name() { - QMimeType instantiatedQMimeType ( - buildQMimeType ( - qMimeTypeName(), - qMimeTypeGenericIconName(), - qMimeTypeIconName(), - qMimeTypeGlobPatterns() - ) - ); - - QMimeType otherQMimeType ( - buildQMimeType ( - QString(), - qMimeTypeGenericIconName(), - qMimeTypeIconName(), - qMimeTypeGlobPatterns() - ) - ); + QMimeType instantiatedQMimeType{ QMimeTypePrivate(qMimeTypeName()) }; + QMimeType otherQMimeType{ QMimeTypePrivate(QString()) }; // Verify that the Name is part of the equality test: QCOMPARE(instantiatedQMimeType.name(), qMimeTypeName()); - QVERIFY(instantiatedQMimeType != otherQMimeType); - QVERIFY(!(instantiatedQMimeType == otherQMimeType)); + QT_TEST_EQUALITY_OPS(instantiatedQMimeType, otherQMimeType, false); } // ------------------------------------------------------------------------------------------------ void tst_qmimetype::genericIconName() { - QMimeType instantiatedQMimeType ( - buildQMimeType ( - qMimeTypeName(), - qMimeTypeGenericIconName(), - qMimeTypeIconName(), - qMimeTypeGlobPatterns() - ) - ); - - QCOMPARE(instantiatedQMimeType.genericIconName(), qMimeTypeGenericIconName()); + const QMimeType instantiatedQMimeType{ QMimeTypePrivate(qMimeTypeName()) }; + QCOMPARE(instantiatedQMimeType.genericIconName(), "group-x-generic"); } // ------------------------------------------------------------------------------------------------ void tst_qmimetype::iconName() { - QMimeType instantiatedQMimeType ( - buildQMimeType ( - qMimeTypeName(), - qMimeTypeGenericIconName(), - qMimeTypeIconName(), - qMimeTypeGlobPatterns() - ) - ); - - QCOMPARE(instantiatedQMimeType.iconName(), qMimeTypeIconName()); -} - -// ------------------------------------------------------------------------------------------------ - -void tst_qmimetype::suffixes() -{ - QMimeType instantiatedQMimeType ( - buildQMimeType ( - qMimeTypeName(), - qMimeTypeGenericIconName(), - qMimeTypeIconName(), - qMimeTypeGlobPatterns() - ) - ); - - QCOMPARE(instantiatedQMimeType.globPatterns(), qMimeTypeGlobPatterns()); - QCOMPARE(instantiatedQMimeType.suffixes(), QStringList() << QString::fromLatin1("png")); + const QMimeType instantiatedQMimeType{ QMimeTypePrivate(qMimeTypeName()) }; + QCOMPARE(instantiatedQMimeType.iconName(), "group-fake-mime"); } // ------------------------------------------------------------------------------------------------ void tst_qmimetype::gadget() { - QMimeType instantiatedQMimeType ( - buildQMimeType ( - qMimeTypeName(), - qMimeTypeGenericIconName(), - qMimeTypeIconName(), - qMimeTypeGlobPatterns() - ) - ); + QMimeType instantiatedQMimeType = QMimeDatabase().mimeTypeForName("text/plain"); const QMetaObject *metaObject = &instantiatedQMimeType.staticMetaObject; |