diff --git a/src/corelib/tools/qregularexpression.cpp b/src/corelib/tools/qregularexpression.cpp index 29ad578013..4388fe5712 100644 --- a/src/corelib/tools/qregularexpression.cpp +++ b/src/corelib/tools/qregularexpression.cpp @@ -43,7 +43,7 @@ #include #include -#include +#include #include #include #include @@ -720,21 +720,14 @@ QT_BEGIN_NAMESPACE to the \c{/u} modifier in Perl regular expressions. \value OptimizeOnFirstUsageOption - The regular expression will be optimized (and possibly - JIT-compiled) on its first usage, instead of after a certain (undefined) - number of usages. See also \l{QRegularExpression::}{optimize()}. - This enum value has been introduced in Qt 5.4. + This option is ignored. A regular expression is automatically optimized + (including JIT compiling) the first time it is used. This enum value + was introduced in Qt 5.4. \value DontAutomaticallyOptimizeOption - Regular expressions are automatically optimized after a - certain number of usages; setting this option prevents such - optimizations, therefore avoiding possible unpredictable spikes in - CPU and memory usage. If both this option and the - \c{OptimizeOnFirstUsageOption} option are set, then this option takes - precedence. Note: this option will still let the regular expression - to be optimized by manually calling - \l{QRegularExpression::}{optimize()}. This enum value has been - introduced in Qt 5.4. + This option is ignored. A regular expression is automatically optimized + (including JIT compiling) the first time it is used. This enum value + was introduced in Qt 5.4. */ /*! @@ -791,14 +784,6 @@ QT_BEGIN_NAMESPACE Qt 5.4. */ -// after how many usages we optimize the regexp -#ifdef QT_BUILD_INTERNAL -Q_AUTOTEST_EXPORT unsigned int qt_qregularexpression_optimize_after_use_count = 10; -#else -static const unsigned int qt_qregularexpression_optimize_after_use_count = 10; -#endif // QT_BUILD_INTERNAL - - namespace QtPrivate { /*! internal @@ -924,13 +909,7 @@ struct QRegularExpressionPrivate : QSharedData void cleanCompiledPattern(); void compilePattern(); void getPatternInfo(); - - enum OptimizePatternOption { - LazyOptimizeOption, - ImmediateOptimizeOption - }; - - void optimizePattern(OptimizePatternOption option); + void optimizePattern(); enum CheckSubjectStringOption { CheckSubjectString, @@ -955,7 +934,7 @@ struct QRegularExpressionPrivate : QSharedData // *All* of the following members are managed while holding this mutex, // except for isDirty which is set to true by QRegularExpression setters // (right after a detach happened). - mutable QReadWriteLock mutex; + mutable QMutex mutex; // The PCRE code pointer is reference-counted by the QRegularExpressionPrivate // objects themselves; when the private is copied (i.e. a detach happened) @@ -964,7 +943,6 @@ struct QRegularExpressionPrivate : QSharedData int errorCode; int errorOffset; int capturingCount; - unsigned int usedCount; bool usingCrLfNewlines; bool isDirty; }; @@ -1033,7 +1011,6 @@ QRegularExpressionPrivate::QRegularExpressionPrivate() errorCode(0), errorOffset(-1), capturingCount(0), - usedCount(0), usingCrLfNewlines(false), isDirty(true) { @@ -1065,7 +1042,6 @@ QRegularExpressionPrivate::QRegularExpressionPrivate(const QRegularExpressionPri errorCode(0), errorOffset(-1), capturingCount(0), - usedCount(0), usingCrLfNewlines(false), isDirty(true) { @@ -1081,7 +1057,6 @@ void QRegularExpressionPrivate::cleanCompiledPattern() errorCode = 0; errorOffset = -1; capturingCount = 0; - usedCount = 0; usingCrLfNewlines = false; } @@ -1090,7 +1065,7 @@ void QRegularExpressionPrivate::cleanCompiledPattern() */ void QRegularExpressionPrivate::compilePattern() { - const QWriteLocker lock(&mutex); + const QMutexLocker lock(&mutex); if (!isDirty) return; @@ -1117,6 +1092,7 @@ void QRegularExpressionPrivate::compilePattern() errorCode = 0; } + optimizePattern(); getPatternInfo(); } @@ -1217,15 +1193,10 @@ static bool isJitEnabled() The purpose of the function is to call pcre2_jit_compile_16, which JIT-compiles the pattern. - It gets called by doMatch() every time a match is performed. - - As of now, the optimizations on the pattern are performed after a certain - number of usages (i.e. the qt_qregularexpression_optimize_after_use_count - constant) unless the DontAutomaticallyOptimizeOption option is set on the - QRegularExpression object, or anyhow by calling optimize() (which will pass - ImmediateOptimizeOption). + It gets called when a pattern is recompiled by us (in compilePattern()), + under mutex protection. */ -void QRegularExpressionPrivate::optimizePattern(OptimizePatternOption option) +void QRegularExpressionPrivate::optimizePattern() { Q_ASSERT(compiledPattern); @@ -1234,11 +1205,6 @@ void QRegularExpressionPrivate::optimizePattern(OptimizePatternOption option) if (!enableJit) return; - const QWriteLocker lock(&mutex); - - if ((option == LazyOptimizeOption) && (++usedCount != qt_qregularexpression_optimize_after_use_count)) - return; - pcre2_jit_compile_16(compiledPattern, PCRE2_JIT_COMPLETE | PCRE2_JIT_PARTIAL_SOFT | PCRE2_JIT_PARTIAL_HARD); } @@ -1344,22 +1310,12 @@ QRegularExpressionMatchPrivate *QRegularExpressionPrivate::doMatch(const QString return priv; } - // skip optimizing and doing the actual matching if NoMatch type was requested + // skip doing the actual matching if NoMatch type was requested if (matchType == QRegularExpression::NoMatch) { priv->isValid = true; return priv; } - if (!(patternOptions & QRegularExpression::DontAutomaticallyOptimizeOption)) { - const OptimizePatternOption optimizePatternOption = - (patternOptions & QRegularExpression::OptimizeOnFirstUsageOption) - ? ImmediateOptimizeOption - : LazyOptimizeOption; - - // this is mutex protected - const_cast(this)->optimizePattern(optimizePatternOption); - } - int pcreOptions = convertToPcreOptions(matchOptions); if (matchType == QRegularExpression::PartialPreferCompleteMatch) @@ -1384,8 +1340,6 @@ QRegularExpressionMatchPrivate *QRegularExpressionPrivate::doMatch(const QString int result; - QReadLocker lock(&mutex); - if (!previousMatchWasEmpty) { result = safe_pcre2_match_16(compiledPattern, subjectUtf16, subjectLength, @@ -1417,8 +1371,6 @@ QRegularExpressionMatchPrivate *QRegularExpressionPrivate::doMatch(const QString } } - lock.unlock(); - #ifdef QREGULAREXPRESSION_DEBUG qDebug() << "Matching" << pattern << "against" << subject << "starting at" << subjectStart << "len" << subjectLength @@ -1928,22 +1880,14 @@ QRegularExpressionMatchIterator QRegularExpression::globalMatch(const QStringRef /*! \since 5.4 - Forces an immediate optimization of the pattern, including - JIT-compiling it (if the JIT compiler is enabled). + Compiles the pattern immediately, including JIT compiling it (if + the JIT is enabled) for optimization. - Patterns are normally optimized only after a certain number of usages. - If you can predict that this QRegularExpression object is going to be - used for several matches, it may be convenient to optimize it in - advance by calling this function. - - \sa QRegularExpression::OptimizeOnFirstUsageOption + \sa isValid(), {Debugging Code that Uses QRegularExpression} */ void QRegularExpression::optimize() const { - if (!isValid()) // will compile the pattern - return; - - d->optimizePattern(QRegularExpressionPrivate::ImmediateOptimizeOption); + d.data()->compilePattern(); } /*! diff --git a/src/corelib/tools/qregularexpression.h b/src/corelib/tools/qregularexpression.h index f26f52d427..d0f90b90b3 100644 --- a/src/corelib/tools/qregularexpression.h +++ b/src/corelib/tools/qregularexpression.h @@ -73,8 +73,8 @@ public: InvertedGreedinessOption = 0x0010, DontCaptureOption = 0x0020, UseUnicodePropertiesOption = 0x0040, - OptimizeOnFirstUsageOption = 0x0080, - DontAutomaticallyOptimizeOption = 0x0100 + OptimizeOnFirstUsageOption Q_DECL_ENUMERATOR_DEPRECATED_X("This option does not have any effect since Qt 5.12") = 0x0080, + DontAutomaticallyOptimizeOption Q_DECL_ENUMERATOR_DEPRECATED_X("This option does not have any effect since Qt 5.12") = 0x0100, }; Q_DECLARE_FLAGS(PatternOptions, PatternOption) diff --git a/tests/auto/corelib/tools/qregularexpression/alwaysoptimize/alwaysoptimize.pro b/tests/auto/corelib/tools/qregularexpression/alwaysoptimize/alwaysoptimize.pro deleted file mode 100644 index a27286ff20..0000000000 --- a/tests/auto/corelib/tools/qregularexpression/alwaysoptimize/alwaysoptimize.pro +++ /dev/null @@ -1,7 +0,0 @@ -CONFIG += testcase -TARGET = tst_qregularexpression_alwaysoptimize -QT = core testlib -HEADERS = ../tst_qregularexpression.h -SOURCES = \ - tst_qregularexpression_alwaysoptimize.cpp \ - ../tst_qregularexpression.cpp diff --git a/tests/auto/corelib/tools/qregularexpression/alwaysoptimize/tst_qregularexpression_alwaysoptimize.cpp b/tests/auto/corelib/tools/qregularexpression/alwaysoptimize/tst_qregularexpression_alwaysoptimize.cpp deleted file mode 100644 index 6d2ae48235..0000000000 --- a/tests/auto/corelib/tools/qregularexpression/alwaysoptimize/tst_qregularexpression_alwaysoptimize.cpp +++ /dev/null @@ -1,51 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2012 Giuseppe D'Angelo . -** 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 "../tst_qregularexpression.h" - -class tst_QRegularExpression_AlwaysOptimize : public tst_QRegularExpression -{ - Q_OBJECT - -private slots: - void initTestCase(); -}; - -QT_BEGIN_NAMESPACE -extern Q_CORE_EXPORT unsigned int qt_qregularexpression_optimize_after_use_count; // from qregularexpression.cpp -QT_END_NAMESPACE - -void tst_QRegularExpression_AlwaysOptimize::initTestCase() -{ - qt_qregularexpression_optimize_after_use_count = 1; -} - -QTEST_APPLESS_MAIN(tst_QRegularExpression_AlwaysOptimize) - -#include "tst_qregularexpression_alwaysoptimize.moc" diff --git a/tests/auto/corelib/tools/qregularexpression/defaultoptimize/defaultoptimize.pro b/tests/auto/corelib/tools/qregularexpression/defaultoptimize/defaultoptimize.pro deleted file mode 100644 index 0b36c79c1b..0000000000 --- a/tests/auto/corelib/tools/qregularexpression/defaultoptimize/defaultoptimize.pro +++ /dev/null @@ -1,7 +0,0 @@ -CONFIG += testcase -TARGET = tst_qregularexpression_defaultoptimize -QT = core testlib -HEADERS = ../tst_qregularexpression.h -SOURCES = \ - tst_qregularexpression_defaultoptimize.cpp \ - ../tst_qregularexpression.cpp diff --git a/tests/auto/corelib/tools/qregularexpression/defaultoptimize/tst_qregularexpression_defaultoptimize.cpp b/tests/auto/corelib/tools/qregularexpression/defaultoptimize/tst_qregularexpression_defaultoptimize.cpp deleted file mode 100644 index a815c6cab9..0000000000 --- a/tests/auto/corelib/tools/qregularexpression/defaultoptimize/tst_qregularexpression_defaultoptimize.cpp +++ /dev/null @@ -1,39 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2012 Giuseppe D'Angelo . -** 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 "../tst_qregularexpression.h" - -class tst_QRegularExpression_DefaultOptimize : public tst_QRegularExpression -{ - Q_OBJECT -}; - -QTEST_APPLESS_MAIN(tst_QRegularExpression_DefaultOptimize) - -#include "tst_qregularexpression_defaultoptimize.moc" diff --git a/tests/auto/corelib/tools/qregularexpression/forceoptimize/forceoptimize.pro b/tests/auto/corelib/tools/qregularexpression/forceoptimize/forceoptimize.pro deleted file mode 100644 index 1db77781dd..0000000000 --- a/tests/auto/corelib/tools/qregularexpression/forceoptimize/forceoptimize.pro +++ /dev/null @@ -1,8 +0,0 @@ -CONFIG += testcase -TARGET = tst_qregularexpression_forceoptimize -QT = core testlib -HEADERS = ../tst_qregularexpression.h -SOURCES = \ - tst_qregularexpression_forceoptimize.cpp \ - ../tst_qregularexpression.cpp -DEFINES += forceOptimize=true diff --git a/tests/auto/corelib/tools/qregularexpression/forceoptimize/tst_qregularexpression_forceoptimize.cpp b/tests/auto/corelib/tools/qregularexpression/forceoptimize/tst_qregularexpression_forceoptimize.cpp deleted file mode 100644 index 38a3a64fa3..0000000000 --- a/tests/auto/corelib/tools/qregularexpression/forceoptimize/tst_qregularexpression_forceoptimize.cpp +++ /dev/null @@ -1,39 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2014 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Giuseppe D'Angelo -** 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 "../tst_qregularexpression.h" - -class tst_QRegularExpression_ForceOptimize : public tst_QRegularExpression -{ - Q_OBJECT -}; - -QTEST_APPLESS_MAIN(tst_QRegularExpression_ForceOptimize) - -#include "tst_qregularexpression_forceoptimize.moc" diff --git a/tests/auto/corelib/tools/qregularexpression/qregularexpression.pro b/tests/auto/corelib/tools/qregularexpression/qregularexpression.pro index e1840808ff..ec8189717e 100644 --- a/tests/auto/corelib/tools/qregularexpression/qregularexpression.pro +++ b/tests/auto/corelib/tools/qregularexpression/qregularexpression.pro @@ -1,3 +1,4 @@ -TEMPLATE = subdirs -SUBDIRS = defaultoptimize forceoptimize -qtConfig(private_tests): SUBDIRS += alwaysoptimize +CONFIG += testcase +TARGET = tst_qregularexpression +QT = core testlib +SOURCES = tst_qregularexpression.cpp diff --git a/tests/auto/corelib/tools/qregularexpression/tst_qregularexpression.cpp b/tests/auto/corelib/tools/qregularexpression/tst_qregularexpression.cpp index ec495fd272..1a6fdaaa61 100644 --- a/tests/auto/corelib/tools/qregularexpression/tst_qregularexpression.cpp +++ b/tests/auto/corelib/tools/qregularexpression/tst_qregularexpression.cpp @@ -33,11 +33,60 @@ #include #include -#include "tst_qregularexpression.h" +#include +#include +#include -#ifndef forceOptimize -#define forceOptimize false -#endif +Q_DECLARE_METATYPE(QRegularExpression::PatternOptions) +Q_DECLARE_METATYPE(QRegularExpression::MatchType) +Q_DECLARE_METATYPE(QRegularExpression::MatchOptions) + +class tst_QRegularExpression : public QObject +{ + Q_OBJECT + +private slots: + void defaultConstructors(); + void gettersSetters_data(); + void gettersSetters(); + void escape_data(); + void escape(); + void validity_data(); + void validity(); + void patternOptions_data(); + void patternOptions(); + void normalMatch_data(); + void normalMatch(); + void partialMatch_data(); + void partialMatch(); + void globalMatch_data(); + void globalMatch(); + void serialize_data(); + void serialize(); + void operatoreq_data(); + void operatoreq(); + void captureCount_data(); + void captureCount(); + void captureNames_data(); + void captureNames(); + void pcreJitStackUsage_data(); + void pcreJitStackUsage(); + void regularExpressionMatch_data(); + void regularExpressionMatch(); + void JOptionUsage_data(); + void JOptionUsage(); + void QStringAndQStringRefEquivalence(); + void threadSafety_data(); + void threadSafety(); + + void wildcard_data(); + void wildcard(); + void testInvalidWildcard_data(); + void testInvalidWildcard(); + +private: + void provideRegularExpressions(); +}; struct Match { @@ -292,9 +341,6 @@ static void testMatch(const QRegularExpression ®exp, QRegularExpression::MatchOptions matchOptions, const Result &result) { - if (forceOptimize) - regexp.optimize(); - // test with QString as subject type testMatchImpl(regexp, matchingMethodForString, subject, offset, matchType, matchOptions, result); @@ -401,30 +447,22 @@ void tst_QRegularExpression::gettersSetters() { QRegularExpression re; re.setPattern(pattern); - if (forceOptimize) - re.optimize(); QCOMPARE(re.pattern(), pattern); QCOMPARE(re.patternOptions(), QRegularExpression::NoPatternOption); } { QRegularExpression re; re.setPatternOptions(patternOptions); - if (forceOptimize) - re.optimize(); QCOMPARE(re.pattern(), QString()); QCOMPARE(re.patternOptions(), patternOptions); } { QRegularExpression re(pattern); - if (forceOptimize) - re.optimize(); QCOMPARE(re.pattern(), pattern); QCOMPARE(re.patternOptions(), QRegularExpression::NoPatternOption); } { QRegularExpression re(pattern, patternOptions); - if (forceOptimize) - re.optimize(); QCOMPARE(re.pattern(), pattern); QCOMPARE(re.patternOptions(), patternOptions); } @@ -465,8 +503,6 @@ void tst_QRegularExpression::escape() QFETCH(QString, escaped); QCOMPARE(QRegularExpression::escape(string), escaped); QRegularExpression re(escaped); - if (forceOptimize) - re.optimize(); QCOMPARE(re.isValid(), true); } @@ -497,8 +533,6 @@ void tst_QRegularExpression::validity() QFETCH(QString, pattern); QFETCH(bool, validity); QRegularExpression re(pattern); - if (forceOptimize) - re.optimize(); QCOMPARE(re.isValid(), validity); if (!validity) QTest::ignoreMessage(QtWarningMsg, "QRegularExpressionPrivate::doMatch(): called on an invalid QRegularExpression object"); @@ -585,9 +619,6 @@ void tst_QRegularExpression::patternOptions() QFETCH(QString, subject); QFETCH(Match, match); - if (forceOptimize) - regexp.optimize(); - QRegularExpressionMatch m = regexp.match(subject); consistencyCheck(m); QVERIFY(m == match); @@ -1403,9 +1434,6 @@ void tst_QRegularExpression::serialize() QFETCH(QRegularExpression::PatternOptions, patternOptions); QRegularExpression outRe(pattern, patternOptions); - if (forceOptimize) - outRe.optimize(); - QByteArray buffer; { QDataStream out(&buffer, QIODevice::WriteOnly); @@ -1468,33 +1496,18 @@ void tst_QRegularExpression::operatoreq() QRegularExpression re1(pattern); QRegularExpression re2(pattern); - if (forceOptimize) - re1.optimize(); - if (forceOptimize) - re2.optimize(); - verifyEquality(re1, re2); } { QRegularExpression re1(QString(), patternOptions); QRegularExpression re2(QString(), patternOptions); - if (forceOptimize) - re1.optimize(); - if (forceOptimize) - re2.optimize(); - verifyEquality(re1, re2); } { QRegularExpression re1(pattern, patternOptions); QRegularExpression re2(pattern, patternOptions); - if (forceOptimize) - re1.optimize(); - if (forceOptimize) - re2.optimize(); - verifyEquality(re1, re2); } } @@ -1524,9 +1537,6 @@ void tst_QRegularExpression::captureCount() QFETCH(QString, pattern); QRegularExpression re(pattern); - if (forceOptimize) - re.optimize(); - QTEST(re.captureCount(), "captureCount"); if (!re.isValid()) QCOMPARE(re.captureCount(), -1); @@ -1595,9 +1605,6 @@ void tst_QRegularExpression::captureNames() QRegularExpression re(pattern); - if (forceOptimize) - re.optimize(); - QStringList namedCaptureGroups = re.namedCaptureGroups(); int namedCaptureGroupsCount = namedCaptureGroups.size(); @@ -1633,9 +1640,6 @@ void tst_QRegularExpression::pcreJitStackUsage() QRegularExpression re(pattern); - if (forceOptimize) - re.optimize(); - QVERIFY(re.isValid()); QRegularExpressionMatch match = re.match(subject); consistencyCheck(match); @@ -1663,9 +1667,6 @@ void tst_QRegularExpression::regularExpressionMatch() QRegularExpression re(pattern); - if (forceOptimize) - re.optimize(); - QVERIFY(re.isValid()); QRegularExpressionMatch match = re.match(subject); consistencyCheck(match); @@ -1705,8 +1706,6 @@ void tst_QRegularExpression::JOptionUsage() QRegularExpression re(pattern); if (isValid && JOptionUsed) QTest::ignoreMessage(QtWarningMsg, qPrintable(warningMessage.arg(pattern))); - if (forceOptimize) - re.optimize(); QCOMPARE(re.isValid(), isValid); } @@ -2067,6 +2066,92 @@ void tst_QRegularExpression::QStringAndQStringRefEquivalence() } } +class MatcherThread : public QThread +{ +public: + explicit MatcherThread(const QRegularExpression &re, const QString &subject, QObject *parent = nullptr) + : QThread(parent), + m_re(re), + m_subject(subject) + { + } + +private: + static const int MATCH_ITERATIONS = 50; + + void run() override + { + yieldCurrentThread(); + for (int i = 0; i < MATCH_ITERATIONS; ++i) + m_re.match(m_subject); + } + + const QRegularExpression &m_re; + const QString &m_subject; +}; + +void tst_QRegularExpression::threadSafety_data() +{ + QTest::addColumn("pattern"); + QTest::addColumn("subject"); + + int i = 0; + QTest::addRow("pattern%d", ++i) << "ab.*cd" << "abcd"; + QTest::addRow("pattern%d", ++i) << "ab.*cd" << "abd"; + QTest::addRow("pattern%d", ++i) << "ab.*cd" << "abbbbcccd"; + QTest::addRow("pattern%d", ++i) << "ab.*cd" << "abababcd"; + QTest::addRow("pattern%d", ++i) << "ab.*cd" << "abcabcd"; + QTest::addRow("pattern%d", ++i) << "ab.*cd" << "abccccccababd"; + + { + QString subject(512*1024, QLatin1Char('x')); + QTest::addRow("pattern%d", ++i) << "ab.*cd" << subject; + } + + { + QString subject = "ab"; + subject.append(QString(512*1024, QLatin1Char('x'))); + subject.append("c"); + QTest::addRow("pattern%d", ++i) << "ab.*cd" << subject; + } + + { + QString subject = "ab"; + subject.append(QString(512*1024, QLatin1Char('x'))); + subject.append("cd"); + QTest::addRow("pattern%d", ++i) << "ab.*cd" << subject; + } + + QTest::addRow("pattern%d", ++i) << "(?(R)a*(?1)|((?R))b)" << "aaaabcde"; + QTest::addRow("pattern%d", ++i) << "(?(R)a*(?1)|((?R))b)" << "aaaaaaabcde"; +} + +void tst_QRegularExpression::threadSafety() +{ + QFETCH(QString, pattern); + QFETCH(QString, subject); + + static const int THREAD_SAFETY_ITERATIONS = 50; + + const int threadCount = qMax(QThread::idealThreadCount(), 4); + + for (int threadSafetyIteration = 0; threadSafetyIteration < THREAD_SAFETY_ITERATIONS; ++threadSafetyIteration) { + QRegularExpression re(pattern); + + QVector threads; + for (int i = 0; i < threadCount; ++i) { + MatcherThread *thread = new MatcherThread(re, subject); + thread->start(); + threads.push_back(thread); + } + + for (int i = 0; i < threadCount; ++i) + threads[i]->wait(); + + qDeleteAll(threads); + } +} + void tst_QRegularExpression::wildcard_data() { QTest::addColumn("pattern"); @@ -2108,8 +2193,6 @@ void tst_QRegularExpression::wildcard() QRegularExpression re; re.setWildcardPattern(pattern); - if (forceOptimize) - re.optimize(); QRegularExpressionMatch match = re.match(string); @@ -2137,9 +2220,11 @@ void tst_QRegularExpression::testInvalidWildcard() QRegularExpression re; re.setWildcardPattern(pattern); - if (forceOptimize) - re.optimize(); QFETCH(bool, isValid); QCOMPARE(re.isValid(), isValid); } + +QTEST_APPLESS_MAIN(tst_QRegularExpression) + +#include "tst_qregularexpression.moc" diff --git a/tests/auto/corelib/tools/qregularexpression/tst_qregularexpression.h b/tests/auto/corelib/tools/qregularexpression/tst_qregularexpression.h deleted file mode 100644 index db5b15be66..0000000000 --- a/tests/auto/corelib/tools/qregularexpression/tst_qregularexpression.h +++ /dev/null @@ -1,79 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2012 Giuseppe D'Angelo . -** 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 - -Q_DECLARE_METATYPE(QRegularExpression::PatternOptions) -Q_DECLARE_METATYPE(QRegularExpression::MatchType) -Q_DECLARE_METATYPE(QRegularExpression::MatchOptions) - -class tst_QRegularExpression : public QObject -{ - Q_OBJECT - -private slots: - void defaultConstructors(); - void gettersSetters_data(); - void gettersSetters(); - void escape_data(); - void escape(); - void validity_data(); - void validity(); - void patternOptions_data(); - void patternOptions(); - void normalMatch_data(); - void normalMatch(); - void partialMatch_data(); - void partialMatch(); - void globalMatch_data(); - void globalMatch(); - void serialize_data(); - void serialize(); - void operatoreq_data(); - void operatoreq(); - void captureCount_data(); - void captureCount(); - void captureNames_data(); - void captureNames(); - void pcreJitStackUsage_data(); - void pcreJitStackUsage(); - void regularExpressionMatch_data(); - void regularExpressionMatch(); - void JOptionUsage_data(); - void JOptionUsage(); - void QStringAndQStringRefEquivalence(); - - void wildcard_data(); - void wildcard(); - void testInvalidWildcard_data(); - void testInvalidWildcard(); - -private: - void provideRegularExpressions(); -};