OSDN Git Service

add thread-safety test for QFontDatabase
authorIvailo Monev <xakepa10@gmail.com>
Wed, 16 Nov 2022 14:01:25 +0000 (16:01 +0200)
committerIvailo Monev <xakepa10@gmail.com>
Wed, 16 Nov 2022 14:01:25 +0000 (16:01 +0200)
it basically tests fontconfig thread-safety but QFontDatabase is documented
as thread-safe (as it should be) so why not add test case for it

Signed-off-by: Ivailo Monev <xakepa10@gmail.com>
src/gui/text/qfontdatabase.cpp
tests/auto/qfontdatabase/tst_qfontdatabase.cpp

index fd4b24c..e8e8ce3 100644 (file)
@@ -1084,13 +1084,13 @@ bool QFontDatabase::supportsThreadedFontRendering()
 }
 
 /*!
-  \internal
+    \internal
 
-  This makes sense of the font family name:
+    This makes sense of the font family name:
 
-  if the family name contains a '[' and a ']', then we take the text
-  between the square brackets as the foundry, and the text before the
-  square brackets as the family (ie. "FreeSans [GNU]")
+    if the family name contains a '[' and a ']', then we take the text
+    between the square brackets as the foundry, and the text before the
+    square brackets as the family (ie. "FreeSans [GNU]")
 */
 void QFontDatabasePrivate::parseFontName(const QString &name, QString &foundry, QString &family)
 {
index 10cf604..a618956 100644 (file)
 #include <QtTest/QtTest>
 
 #include <qfontdatabase.h>
-#include <qdir.h>
+#include <qthread.h>
 #include <qdebug.h>
 
+#include <unistd.h>
+
 //TESTED_CLASS=
 //TESTED_FILES=
 
+// this default is somewhat safe
+static int s_threadcount = 100;
+
+class QFontDatabaseThread : public QThread
+{
+public:
+    QFontDatabaseThread(QObject *parent, const int threadnum);
+
+protected:
+    void run() final;
+
+private:
+    const int m_threadnum;
+};
+
+QFontDatabaseThread::QFontDatabaseThread(QObject *parent, const int threadnum)
+    : QThread(parent),
+    m_threadnum(threadnum)
+{
+}
+
+void QFontDatabaseThread::run()
+{
+    // qDebug("Thread running: %d", m_threadnum);
+
+    const QString fontfamily("FreeSans");
+    const QString fontstyle("Bold");
+
+    (void)QFontDatabase().isSmoothlyScalable(fontfamily, fontstyle);
+    (void)QFontDatabase().isScalable(fontfamily, fontstyle);
+    (void)QFontDatabase().isFixedPitch(fontfamily, fontstyle);
+}
+
 class tst_QFontDatabase : public QObject
 {
     Q_OBJECT
@@ -46,6 +81,8 @@ private slots:
     void resolveFamily();
 
     void styleString();
+
+    void threadSafety();
 };
 
 void tst_QFontDatabase::styles_data()
@@ -165,6 +202,36 @@ void tst_QFontDatabase::styleString()
     QVERIFY(fdb.styleString(family) != QLatin1String("Normal"));
 }
 
+void tst_QFontDatabase::threadSafety()
+{
+#ifdef _SC_THREAD_THREADS_MAX
+    const long threadmax = ::sysconf(_SC_THREAD_THREADS_MAX);
+    // should be bellow the limit
+    if (threadmax > 10) {
+        s_threadcount = (threadmax - 10);
+    }
+    qDebug("Starting %d threads (max %d)", s_threadcount, threadmax);
+#else
+    qDebug("Starting %d threads", s_threadcount);
+#endif
+
+    QList<QFontDatabaseThread*> fdbthreads;
+    for (int i = 0; i < s_threadcount; i++) {
+        QFontDatabaseThread* fdbthread = new QFontDatabaseThread(this, i);
+        fdbthreads.append(fdbthread);
+        fdbthread->start();
+    }
+
+    qDebug("Waiting for threads");
+    for (int i = 0; i < s_threadcount; i++) {
+        QFontDatabaseThread* fdbthread = fdbthreads.at(i);
+        while (!fdbthread->isFinished()) {
+            QApplication::processEvents();
+        }
+    }
+    qDebug("Done waiting");
+}
+
 QTEST_MAIN(tst_QFontDatabase)
 
 #include "moc_tst_qfontdatabase.cpp"