/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Copyright (C) 2021 Igor Kushnir ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the test suite of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include #include namespace { struct MatchModeInfo { QMimeDatabase::MatchMode mode; const char *name; }; constexpr MatchModeInfo matchModes[] = { { QMimeDatabase::MatchDefault, "Default" }, { QMimeDatabase::MatchExtension, "Extension" }, { QMimeDatabase::MatchContent, "Content" } }; void addFileRows(const char *tag, const QString &fileName, const QStringList &expectedMimeNames) { QCOMPARE(static_cast(expectedMimeNames.size()), std::size(matchModes)); for (int i = 0; i < expectedMimeNames.size(); ++i) { QTest::addRow(qPrintable(tag + QStringLiteral(" - %s")), matchModes[i].name) << fileName << matchModes[i].mode << expectedMimeNames[i]; } } void addExistentFileRows(const char *tag, const QString &fileName, const QStringList &expectedMimeNames) { const QString filePath = QFINDTESTDATA("files/" + fileName); QVERIFY2(!filePath.isEmpty(), qPrintable(QStringLiteral("Cannot find test file %1 in files/").arg(fileName))); addFileRows(tag, filePath, expectedMimeNames); } } class tst_QMimeDatabase: public QObject { Q_OBJECT private slots: void inheritsPerformance(); void benchMimeTypeForName(); void benchMimeTypeForFile_data(); void benchMimeTypeForFile(); }; void tst_QMimeDatabase::inheritsPerformance() { // Check performance of inherits(). // This benchmark (which started in 2009 in kmimetypetest.cpp) uses 40 mimetypes. QStringList mimeTypes; mimeTypes << QLatin1String("image/jpeg") << QLatin1String("image/png") << QLatin1String("image/tiff") << QLatin1String("text/plain") << QLatin1String("text/html"); mimeTypes += mimeTypes; mimeTypes += mimeTypes; mimeTypes += mimeTypes; QCOMPARE(mimeTypes.count(), 40); QMimeDatabase db; QMimeType mime = db.mimeTypeForName(QString::fromLatin1("text/x-chdr")); QVERIFY(mime.isValid()); QBENCHMARK { QString match; foreach (const QString &mt, mimeTypes) { if (mime.inherits(mt)) { match = mt; // of course there would normally be a "break" here, but we're testing worse-case // performance here } } QCOMPARE(match, QString::fromLatin1("text/plain")); } // Numbers from 2011, in release mode: // KDE 4.7 numbers: 0.21 msec / 494,000 ticks / 568,345 instr. loads per iteration // QMimeBinaryProvider (with Qt 5): 0.16 msec / NA / 416,049 instr. reads per iteration // QMimeXmlProvider (with Qt 5): 0.062 msec / NA / 172,889 instr. reads per iteration // (but the startup time is way higher) // And memory usage is flat at 200K with QMimeBinaryProvider, while it peaks at 6 MB when // parsing XML, and then keeps being around 4.5 MB for all the in-memory hashes. } void tst_QMimeDatabase::benchMimeTypeForName() { QMimeDatabase db; QBENCHMARK { const auto s = db.mimeTypeForName(QStringLiteral("text/plain")); QVERIFY(s.isValid()); } } void tst_QMimeDatabase::benchMimeTypeForFile_data() { QTest::addColumn("fileName"); QTest::addColumn("mode"); QTest::addColumn("expectedMimeName"); addFileRows("archive", "a.tar.gz", { "application/x-compressed-tar", "application/x-compressed-tar", "application/octet-stream" }); addFileRows("OpenDocument Text", "b.odt", { "application/vnd.oasis.opendocument.text", "application/vnd.oasis.opendocument.text", "application/octet-stream" }); addExistentFileRows( "existent archive with extension", "N.tar.gz", { "application/x-compressed-tar", "application/x-compressed-tar", "application/gzip" }); addExistentFileRows("existent C with extension", "t.c", { "text/x-csrc", "text/x-csrc", "text/plain" }); addExistentFileRows("existent text file with extension", "u.txt", { "text/plain", "text/plain", "text/plain" }); addExistentFileRows("existent C w/o extension", "X", { "text/x-csrc", "application/octet-stream", "text/x-csrc" }); addExistentFileRows("existent patch w/o extension", "y", { "text/x-patch", "application/octet-stream", "text/x-patch" }); addExistentFileRows("existent archive w/o extension", "z", { "application/gzip", "application/octet-stream", "application/gzip" }); } void tst_QMimeDatabase::benchMimeTypeForFile() { QFETCH(const QString, fileName); QFETCH(const QMimeDatabase::MatchMode, mode); QFETCH(const QString, expectedMimeName); QMimeDatabase db; QBENCHMARK { const auto mimeType = db.mimeTypeForFile(fileName, mode); QCOMPARE(mimeType.name(), expectedMimeName); } } QTEST_MAIN(tst_QMimeDatabase) #include "tst_bench_qmimedatabase.moc"