qobjectrace test: Don't hardcode the number of threads

Use QThread::idealThreadCount instead. This requires that we use
QVarLengthArray, as MSVC doesn't allow us to allocate arrays with a
non-constexpr size on the stack.

By using as many threads as the system has cores, we are more likely
to detect race conditions reliably. On systems with fewer cores (in
particular on qemu platforms like QNX, where this test has been
failing a lot), we'll less likely end up with false negatives due
to timeouts.

Pick-to: 6.4 6.3 6.2
Change-Id: Ie8631aef544ca7b53c06a0729d05459016745486
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
This commit is contained in:
Volker Hilsheimer 2022-07-10 22:22:13 +02:00
parent 7de0f3e9cc
commit 0dadb951b5

View File

@ -1,4 +1,4 @@
// Copyright (C) 2016 The Qt Company Ltd. // Copyright (C) 2022 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 WITH Qt-GPL-exception-1.0
@ -21,12 +21,20 @@ struct Functor
class tst_QObjectRace: public QObject class tst_QObjectRace: public QObject
{ {
Q_OBJECT Q_OBJECT
public:
tst_QObjectRace()
: ThreadCount(QThread::idealThreadCount())
{}
private slots: private slots:
void moveToThreadRace(); void moveToThreadRace();
void destroyRace(); void destroyRace();
void blockingQueuedDestroyRace(); void blockingQueuedDestroyRace();
void disconnectRace(); void disconnectRace();
void disconnectRace2(); void disconnectRace2();
private:
const int ThreadCount;
}; };
class RaceObject : public QObject class RaceObject : public QObject
@ -110,8 +118,7 @@ void tst_QObjectRace::moveToThreadRace()
{ {
RaceObject *object = new RaceObject; RaceObject *object = new RaceObject;
enum { ThreadCount = 6 }; QVarLengthArray<RaceThread *, 16> threads(ThreadCount);
RaceThread *threads[ThreadCount];
for (int i = 0; i < ThreadCount; ++i) { for (int i = 0; i < ThreadCount; ++i) {
threads[i] = new RaceThread; threads[i] = new RaceThread;
threads[i]->setObject(object); threads[i]->setObject(object);
@ -241,10 +248,10 @@ void tst_QObjectRace::destroyRace()
if (QTestPrivate::isRunningArmOnX86()) if (QTestPrivate::isRunningArmOnX86())
QSKIP("Test is too slow to run on emulator"); QSKIP("Test is too slow to run on emulator");
enum { ThreadCount = 10, ObjectCountPerThread = 2777, constexpr int ObjectCountPerThread = 2777;
ObjectCount = ThreadCount * ObjectCountPerThread }; const int ObjectCount = ThreadCount * ObjectCountPerThread;
MyObject *objects[ObjectCount]; QVarLengthArray<MyObject *, ObjectCountPerThread * 10> objects(ObjectCount);
for (int i = 0; i < ObjectCount; ++i) for (int i = 0; i < ObjectCount; ++i)
objects[i] = new MyObject; objects[i] = new MyObject;
@ -261,10 +268,10 @@ void tst_QObjectRace::destroyRace()
objects[((i+5)*79) % ObjectCount], Functor() ); objects[((i+5)*79) % ObjectCount], Functor() );
} }
DestroyThread *threads[ThreadCount]; QVarLengthArray<DestroyThread *, 16> threads(ThreadCount);
for (int i = 0; i < ThreadCount; ++i) { for (int i = 0; i < ThreadCount; ++i) {
threads[i] = new DestroyThread; threads[i] = new DestroyThread;
threads[i]->setObjects(objects + i*ObjectCountPerThread, ObjectCountPerThread); threads[i]->setObjects(objects.data() + i*ObjectCountPerThread, ObjectCountPerThread);
} }
for (int i = 0; i < ThreadCount; ++i) for (int i = 0; i < ThreadCount; ++i)
@ -477,7 +484,7 @@ public:
void tst_QObjectRace::disconnectRace() void tst_QObjectRace::disconnectRace()
{ {
enum { ThreadCount = 20, TimeLimit = 3000 }; enum { TimeLimit = 3000 };
QCOMPARE(countedStructObjectsCount.loadRelaxed(), 0u); QCOMPARE(countedStructObjectsCount.loadRelaxed(), 0u);
@ -487,7 +494,7 @@ void tst_QObjectRace::disconnectRace()
senderThread->start(); senderThread->start();
sender->moveToThread(senderThread.data()); sender->moveToThread(senderThread.data());
DisconnectRaceThread *threads[ThreadCount]; QVarLengthArray<DisconnectRaceThread *, 16> threads(ThreadCount);
for (int i = 0; i < ThreadCount; ++i) { for (int i = 0; i < ThreadCount; ++i) {
threads[i] = new DisconnectRaceThread(sender.data(), !(i % 10)); threads[i] = new DisconnectRaceThread(sender.data(), !(i % 10));
threads[i]->start(); threads[i]->start();
@ -513,7 +520,7 @@ void tst_QObjectRace::disconnectRace()
senderThread->start(); senderThread->start();
sender->moveToThread(senderThread.data()); sender->moveToThread(senderThread.data());
DeleteReceiverRaceReceiverThread *threads[ThreadCount]; QVarLengthArray<DeleteReceiverRaceReceiverThread *, 16> threads(ThreadCount);
for (int i = 0; i < ThreadCount; ++i) { for (int i = 0; i < ThreadCount; ++i) {
threads[i] = new DeleteReceiverRaceReceiverThread(sender.data()); threads[i] = new DeleteReceiverRaceReceiverThread(sender.data());
threads[i]->start(); threads[i]->start();