From ba423261cd9abedda8b732c82371515003d385ce Mon Sep 17 00:00:00 2001 From: Svenn-Arne Dragly Date: Tue, 5 Sep 2017 15:02:20 +0200 Subject: Improve performance in QThreadPool When many runnables are executed, this improves the performance by not resizing the queue for each runnable, which was the case in the previous version, because of many calls to QVector::takeFirst(). Also add a test that makes sure tryTake() is safe to call and does not leave the queue in a bad state that tries to use nullptr entries. Change-Id: I608134ecfa9cfc03db4878dcbd6f9c1107e13e90 Reviewed-by: Lars Knoll --- .../corelib/thread/qthreadpool/tst_qthreadpool.cpp | 64 ++++++++++++++++++++++ 1 file changed, 64 insertions(+) (limited to 'tests/auto/corelib') diff --git a/tests/auto/corelib/thread/qthreadpool/tst_qthreadpool.cpp b/tests/auto/corelib/thread/qthreadpool/tst_qthreadpool.cpp index fdc4ecb5c8..66853a88d8 100644 --- a/tests/auto/corelib/thread/qthreadpool/tst_qthreadpool.cpp +++ b/tests/auto/corelib/thread/qthreadpool/tst_qthreadpool.cpp @@ -93,6 +93,7 @@ private slots: void waitForDoneTimeout(); void destroyingWaitsForTasksToFinish(); void stressTest(); + void takeAllAndIncreaseMaxThreadCount(); private: QMutex m_functionTestMutex; @@ -1199,5 +1200,68 @@ void tst_QThreadPool::stressTest() } } +void tst_QThreadPool::takeAllAndIncreaseMaxThreadCount() { + class Task : public QRunnable + { + public: + Task(QSemaphore *mainBarrier, QSemaphore *threadBarrier) + : m_mainBarrier(mainBarrier) + , m_threadBarrier(threadBarrier) + { + setAutoDelete(false); + } + + void run() { + m_mainBarrier->release(); + m_threadBarrier->acquire(); + } + private: + QSemaphore *m_mainBarrier; + QSemaphore *m_threadBarrier; + }; + + QSemaphore mainBarrier; + QSemaphore taskBarrier; + + QThreadPool threadPool; + threadPool.setMaxThreadCount(1); + + Task *task1 = new Task(&mainBarrier, &taskBarrier); + Task *task2 = new Task(&mainBarrier, &taskBarrier); + Task *task3 = new Task(&mainBarrier, &taskBarrier); + + threadPool.start(task1); + threadPool.start(task2); + threadPool.start(task3); + + mainBarrier.acquire(1); + + QCOMPARE(threadPool.activeThreadCount(), 1); + + QVERIFY(!threadPool.tryTake(task1)); + QVERIFY(threadPool.tryTake(task2)); + QVERIFY(threadPool.tryTake(task3)); + + // A bad queue implementation can segfault here because two consecutive items in the queue + // have been taken + threadPool.setMaxThreadCount(4); + + // Even though we increase the max thread count, there should only be one job to run + QCOMPARE(threadPool.activeThreadCount(), 1); + + // Make sure jobs 2 and 3 never started + QCOMPARE(mainBarrier.available(), 0); + + taskBarrier.release(1); + + threadPool.waitForDone(); + + QCOMPARE(threadPool.activeThreadCount(), 0); + + delete task1; + delete task2; + delete task3; +} + QTEST_MAIN(tst_QThreadPool); #include "tst_qthreadpool.moc" -- cgit v1.2.3 From f62768d046528636789f901ac79e2cfa1843a7b7 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Thu, 21 Sep 2017 13:27:51 -0700 Subject: QUrl: re-fix the setPath("//path") case leading to scheme://path Commits aba336c2b4ad8926dc8a000718bbb7f8a6d5a72d (in Qt 5.2) and aba336c2b4ad8926dc8a000718bbb7f8a6d5a72d (in 5.6) both tried to deal with this problem, with different levels of success. This is the third attempt (and hopefully the charm). Instead of modifying the path that the user provides, go straight ahead and declare it invalid. This is supported by RFC 3986, which declares this expansion impossible: relative-part = "//" authority path-abempty / path-absolute / path-noscheme / path-empty path-abempty = *( "/" segment ) path-absolute = "/" [ segment-nz *( "/" segment ) ] path-noscheme = segment-nz-nc *( "/" segment ) The "path-abempty" and "path-noscheme" cases are the two issues we already handle. This commit adds the third one: path-absolute, which requires that the first segment of the path be of non-zero length. That is, it is now possible again to have http://example.com//path constructed piece-wise, without it producing http://example.com/path. Additionally, it catches the case of http://example.com//path parsed from full URL then followed by setAuthority(""). Change-Id: I69f37f9304f24709a823fffd14e67a5e7212ddcd Reviewed-by: David Faure --- tests/auto/corelib/io/qurl/tst_qurl.cpp | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) (limited to 'tests/auto/corelib') diff --git a/tests/auto/corelib/io/qurl/tst_qurl.cpp b/tests/auto/corelib/io/qurl/tst_qurl.cpp index c5647752fd..1ff85fc6dc 100644 --- a/tests/auto/corelib/io/qurl/tst_qurl.cpp +++ b/tests/auto/corelib/io/qurl/tst_qurl.cpp @@ -2074,6 +2074,14 @@ void tst_QUrl::isValid() QVERIFY(url.errorString().contains("Path component is relative and authority is present")); } + { + QUrl url("http:"); + url.setPath("//example.com"); + QVERIFY(!url.isValid()); + QVERIFY(url.toString().isEmpty()); + QVERIFY(url.errorString().contains("Path component starts with '//' and authority is absent")); + } + { QUrl url; url.setPath("http://example.com"); @@ -3649,12 +3657,12 @@ void tst_QUrl::setComponents_data() QTest::newRow("path-%3A-before-slash") << QUrl() << int(Path) << "c%3A/" << Tolerant << true << PrettyDecoded << "c%3A/" << "c%3A/"; - QTest::newRow("path-doubleslash") << QUrl("trash:/") + QTest::newRow("path-doubleslash") << QUrl("http://example.com") << int(Path) << "//path" << Tolerant << true - << PrettyDecoded << "/path" << "trash:/path"; + << PrettyDecoded << "//path" << "http://example.com//path"; QTest::newRow("path-withdotdot") << QUrl("file:///tmp") << int(Path) << "//tmp/..///root/." << Tolerant << true - << PrettyDecoded << "/tmp/..///root/." << "file:///tmp/..///root/."; + << PrettyDecoded << "//tmp/..///root/." << "file:////tmp/..///root/."; // the other fields can be present and be empty // that is, their delimiters would be present, but there would be nothing to one side @@ -3777,6 +3785,9 @@ void tst_QUrl::setComponents_data() QTest::newRow("invalid-path-2") << QUrl("http://example.com") << int(Path) << "relative" << Strict << false << PrettyDecoded << "relative" << ""; + QTest::newRow("invalid-path-3") << QUrl("trash:/") + << int(Path) << "//path" << Tolerant << false + << PrettyDecoded << "//path" << ""; // -- test bad percent encoding -- // unnecessary to test the scheme, since percent-decoding is not performed in it; -- cgit v1.2.3 From 0354ba816ff479791f43226aeb30ef35086148b5 Mon Sep 17 00:00:00 2001 From: Orgad Shaneh Date: Mon, 28 Aug 2017 08:32:47 +0300 Subject: Clean dynamic function resolving done for XP in QFileInfo tests Change-Id: I15364b1e8c4f4406fef2be68ca221a8867d0dcfa Reviewed-by: Thiago Macieira --- tests/auto/corelib/io/qfileinfo/tst_qfileinfo.cpp | 54 +++++++---------------- 1 file changed, 15 insertions(+), 39 deletions(-) (limited to 'tests/auto/corelib') diff --git a/tests/auto/corelib/io/qfileinfo/tst_qfileinfo.cpp b/tests/auto/corelib/io/qfileinfo/tst_qfileinfo.cpp index 8945daff4a..44e79985d4 100644 --- a/tests/auto/corelib/io/qfileinfo/tst_qfileinfo.cpp +++ b/tests/auto/corelib/io/qfileinfo/tst_qfileinfo.cpp @@ -48,7 +48,6 @@ #endif #ifdef Q_OS_WIN #include -#include #if !defined(Q_OS_WINRT) #include #endif @@ -684,18 +683,12 @@ void tst_QFileInfo::canonicalFilePath() #endif #if defined(Q_OS_WIN) && !defined(Q_OS_WINRT) - typedef BOOL (WINAPI *PtrCreateSymbolicLink)(LPTSTR, LPTSTR, DWORD); - PtrCreateSymbolicLink ptrCreateSymbolicLink = - (PtrCreateSymbolicLink)QLibrary::resolve(QLatin1String("kernel32"), "CreateSymbolicLinkW"); - - if (!ptrCreateSymbolicLink) { - QSKIP("Symbolic links aren't supported by FS"); - } else { + { // CreateSymbolicLink can return TRUE & still fail to create the link, // the error code in that case is ERROR_PRIVILEGE_NOT_HELD (1314) SetLastError(0); const QString linkTarget = QStringLiteral("res"); - BOOL ret = ptrCreateSymbolicLink((wchar_t*)linkTarget.utf16(), (wchar_t*)m_resourcesDir.utf16(), 1); + BOOL ret = CreateSymbolicLink((wchar_t*)linkTarget.utf16(), (wchar_t*)m_resourcesDir.utf16(), 1); DWORD dwErr = GetLastError(); if (!ret) QSKIP("Symbolic links aren't supported by FS"); @@ -1443,16 +1436,6 @@ void tst_QFileInfo::ntfsJunctionPointsAndSymlinks_data() QDir pwd; pwd.mkdir("target"); - QLibrary kernel32("kernel32"); - typedef BOOLEAN (WINAPI *PtrCreateSymbolicLink)(LPCWSTR, LPCWSTR, DWORD); - PtrCreateSymbolicLink createSymbolicLinkW = 0; - createSymbolicLinkW = (PtrCreateSymbolicLink) kernel32.resolve("CreateSymbolicLinkW"); - if (!createSymbolicLinkW) { - //we need at least one data set for the test not to fail when skipping _data function - QDir target("target"); - QTest::newRow("dummy") << target.path() << false << "" << target.canonicalPath(); - QSKIP("symbolic links not supported by operating system"); - } { //Directory symlinks QDir target("target"); @@ -1472,10 +1455,10 @@ void tst_QFileInfo::ntfsJunctionPointsAndSymlinks_data() DWORD err = ERROR_SUCCESS ; if (!pwd.exists("abs_symlink")) - if (!createSymbolicLinkW((wchar_t*)absSymlink.utf16(),(wchar_t*)absTarget.utf16(),0x1)) + if (!CreateSymbolicLink((wchar_t*)absSymlink.utf16(),(wchar_t*)absTarget.utf16(),0x1)) err = GetLastError(); if (err == ERROR_SUCCESS && !pwd.exists(relSymlink)) - if (!createSymbolicLinkW((wchar_t*)relSymlink.utf16(),(wchar_t*)relTarget.utf16(),0x1)) + if (!CreateSymbolicLink((wchar_t*)relSymlink.utf16(),(wchar_t*)relTarget.utf16(),0x1)) err = GetLastError(); if (err != ERROR_SUCCESS) { wchar_t errstr[0x100]; @@ -1505,10 +1488,9 @@ void tst_QFileInfo::ntfsJunctionPointsAndSymlinks_data() QString relSymlink = "rel_symlink.cpp"; QString relToRelTarget = QDir::toNativeSeparators(relativeDir.relativeFilePath(target.absoluteFilePath())); QString relToRelSymlink = "relative/rel_symlink"; - QVERIFY(pwd.exists("abs_symlink.cpp") || createSymbolicLinkW((wchar_t*)absSymlink.utf16(),(wchar_t*)absTarget.utf16(),0x0)); - QVERIFY(pwd.exists(relSymlink) || createSymbolicLinkW((wchar_t*)relSymlink.utf16(),(wchar_t*)relTarget.utf16(),0x0)); - QVERIFY(pwd.exists(relToRelSymlink) - || createSymbolicLinkW((wchar_t*)relToRelSymlink.utf16(), (wchar_t*)relToRelTarget.utf16(),0x0)); + QVERIFY(pwd.exists("abs_symlink.cpp") || CreateSymbolicLink((wchar_t*)absSymlink.utf16(),(wchar_t*)absTarget.utf16(),0x0)); + QVERIFY(pwd.exists(relSymlink) || CreateSymbolicLink((wchar_t*)relSymlink.utf16(),(wchar_t*)relTarget.utf16(),0x0)); + QVERIFY(pwd.exists(relToRelSymlink) || CreateSymbolicLink((wchar_t*)relToRelSymlink.utf16(), (wchar_t*)relToRelTarget.utf16(),0x0)); QTest::newRow("absolute file symlink") << absSymlink << true << QDir::fromNativeSeparators(absTarget) << target.canonicalFilePath(); QTest::newRow("relative file symlink") << relSymlink << true << QDir::fromNativeSeparators(absTarget) << target.canonicalFilePath(); QTest::newRow("relative to relative file symlink") << relToRelSymlink << true << QDir::fromNativeSeparators(absTarget) << target.canonicalFilePath(); @@ -1535,20 +1517,14 @@ void tst_QFileInfo::ntfsJunctionPointsAndSymlinks_data() QTest::newRow("junction_root") << junction << false << QString() << QString(); //Mountpoint - typedef BOOLEAN (WINAPI *PtrGetVolumeNameForVolumeMountPointW)(LPCWSTR, LPWSTR, DWORD); - PtrGetVolumeNameForVolumeMountPointW getVolumeNameForVolumeMountPointW = 0; - getVolumeNameForVolumeMountPointW = (PtrGetVolumeNameForVolumeMountPointW) kernel32.resolve("GetVolumeNameForVolumeMountPointW"); - if(getVolumeNameForVolumeMountPointW) - { - wchar_t buffer[MAX_PATH]; - QString rootPath = QDir::toNativeSeparators(QDir::rootPath()); - QVERIFY(getVolumeNameForVolumeMountPointW((wchar_t*)rootPath.utf16(), buffer, MAX_PATH)); - QString rootVolume = QString::fromWCharArray(buffer); - junction = "mountpoint"; - rootVolume.replace("\\\\?\\","\\??\\"); - FileSystem::createNtfsJunction(rootVolume, junction); - QTest::newRow("mountpoint") << junction << false << QString() << QString(); - } + wchar_t buffer[MAX_PATH]; + QString rootPath = QDir::toNativeSeparators(QDir::rootPath()); + QVERIFY(GetVolumeNameForVolumeMountPoint((wchar_t*)rootPath.utf16(), buffer, MAX_PATH)); + QString rootVolume = QString::fromWCharArray(buffer); + junction = "mountpoint"; + rootVolume.replace("\\\\?\\","\\??\\"); + FileSystem::createNtfsJunction(rootVolume, junction); + QTest::newRow("mountpoint") << junction << false << QString() << QString(); } void tst_QFileInfo::ntfsJunctionPointsAndSymlinks() -- cgit v1.2.3 From c90d9f95d27cf12747446ce8f7ee1cefe1f0f818 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Thu, 12 Oct 2017 13:40:18 -0700 Subject: QRandomGenerator: improve floating-point random generation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The previous version was good, just not optimal. Because the input was an unsigned 64-bit number, compilers needed to generate extra code to deal with HW instructions that only convert 64-bit signed input. And that was useless because a double uniformly distributed from 0 to 1 can only have 53 bits of randomness. The previous implementation did exactly what the Microsoft libstdc++ and libc++ implementations do. In my opinion, those implementations have an imperfect distribution, which is corrected in this commit. In those, all random input bigger than 0x20000000000000 has a different frequency compared to input below that mark. For example, both 0x20000000000000 and 0x20000000000001 produce the same result (4.8828125e-4). What's more, for the libc++ and MSVC implementations, input between 0xfffffffffffff001 and 0xffffffffffffffff results in 1.0 (probability 1 in 2⁵³), even though the Standard is very clear that the result should be strictly less than 1. GCC 7's libstdc++ doesn't have this issue, whereas the versions before would enter an infinite loop. Change-Id: Ib17dde1a1dbb49a7bba8fffd14eced3c375dd2ec Reviewed-by: Lars Knoll Reviewed-by: Edward Welbourne --- .../qrandomgenerator/tst_qrandomgenerator.cpp | 50 +++++++++++++++++++++- 1 file changed, 49 insertions(+), 1 deletion(-) (limited to 'tests/auto/corelib') diff --git a/tests/auto/corelib/global/qrandomgenerator/tst_qrandomgenerator.cpp b/tests/auto/corelib/global/qrandomgenerator/tst_qrandomgenerator.cpp index 2195bf8ec8..d1c0c8e965 100644 --- a/tests/auto/corelib/global/qrandomgenerator/tst_qrandomgenerator.cpp +++ b/tests/auto/corelib/global/qrandomgenerator/tst_qrandomgenerator.cpp @@ -97,6 +97,8 @@ private slots: void generateReal_data() { generate32_data(); } void generateReal(); + void qualityReal_data() { generate32_data(); } + void qualityReal(); void seedStdRandomEngines(); void stdUniformIntDistribution_data(); @@ -445,7 +447,7 @@ void tst_QRandomGenerator::generateReal() for (int i = 0; i < 4; ++i) { QVERIFY_3TIMES([] { qreal value = QRandomGenerator::generateDouble(); - return value > 0 && value < 1 && value != RandomValueFP; + return value >= 0 && value < 1 && value != RandomValueFP; }()); } @@ -454,6 +456,52 @@ void tst_QRandomGenerator::generateReal() QVERIFY_3TIMES(QRandomGenerator::generateDouble() != QRandomGenerator::generateDouble()); } +void tst_QRandomGenerator::qualityReal() +{ + QFETCH(uint, control); + setRNGControl(control); + + enum { + SampleSize = 160, + + // Expected value: sample size times proportion of the range: + PerfectOctile = SampleSize / 8, + PerfectHalf = SampleSize / 2, + + // Variance is (1 - proportion of range) * expected; sqrt() for standard deviations. + // Should usually be within twice that and almost never outside four times: + RangeHalf = 25, // floor(4 * sqrt((1 - 0.5) * PerfectHalf)) + RangeOctile = 16 // floor(4 * sqrt((1 - 0.125) * PerfectOctile)) + }; + + double data[SampleSize]; + std::generate(std::begin(data), std::end(data), &QRandomGenerator::generateDouble); + + int aboveHalf = 0; + int belowOneEighth = 0; + int aboveSevenEighths = 0; + for (double x : data) { + aboveHalf += x >= 0.5; + belowOneEighth += x < 0.125; + aboveSevenEighths += x >= 0.875; + + // these are strict requirements + QVERIFY(x >= 0); + QVERIFY(x < 1); + } + + qInfo("Halfway distribution: %.1f - %.1f", 100. * aboveHalf / SampleSize, 100 - 100. * aboveHalf / SampleSize); + qInfo("%.1f below 1/8 (expected 12.5%% ideally)", 100. * belowOneEighth / SampleSize); + qInfo("%.1f above 7/8 (expected 12.5%% ideally)", 100. * aboveSevenEighths / SampleSize); + + QVERIFY(aboveHalf < PerfectHalf + RangeHalf); + QVERIFY(aboveHalf > PerfectHalf - RangeHalf); + QVERIFY(aboveSevenEighths < PerfectOctile + RangeOctile); + QVERIFY(aboveSevenEighths > PerfectOctile - RangeOctile); + QVERIFY(belowOneEighth < PerfectOctile + RangeOctile); + QVERIFY(belowOneEighth > PerfectOctile - RangeOctile); +} + template void seedStdRandomEngine() { QRandomGenerator rd; -- cgit v1.2.3 From 9c58dd15885d813aeb5d83d2869c0f3a3ee5fcfe Mon Sep 17 00:00:00 2001 From: Sami Nurmenniemi Date: Fri, 20 Oct 2017 16:09:29 +0300 Subject: Blacklist and skip failing tests for Boot2Qt / 64 bit arm MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Task-number: QTBUG-60263 Change-Id: I05978915b5bb7ae31069e8e9ae1dc273e483ddb0 Reviewed-by: Tony Sarajärvi --- tests/auto/corelib/global/qlogging/BLACKLIST | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 tests/auto/corelib/global/qlogging/BLACKLIST (limited to 'tests/auto/corelib') diff --git a/tests/auto/corelib/global/qlogging/BLACKLIST b/tests/auto/corelib/global/qlogging/BLACKLIST new file mode 100644 index 0000000000..1dcee92361 --- /dev/null +++ b/tests/auto/corelib/global/qlogging/BLACKLIST @@ -0,0 +1,3 @@ +[qMessagePattern:backtrace depth,separator] +# QTBUG-63915 +b2qt 64bit -- cgit v1.2.3