summaryrefslogtreecommitdiffstats
path: root/tests/auto/corelib/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'tests/auto/corelib/kernel')
-rw-r--r--tests/auto/corelib/kernel/qmetatype/tst_qmetatype.cpp2
-rw-r--r--tests/auto/corelib/kernel/qobject/tst_qobject.cpp83
-rw-r--r--tests/auto/corelib/kernel/qsharedmemory/tst_qsharedmemory.cpp22
-rw-r--r--tests/auto/corelib/kernel/qsystemsemaphore/tst_qsystemsemaphore.cpp9
-rw-r--r--tests/auto/corelib/kernel/qtimer/BLACKLIST3
-rw-r--r--tests/auto/corelib/kernel/qtimer/tst_qtimer.cpp65
-rw-r--r--tests/auto/corelib/kernel/qtranslator/android_testdata.qrc8
-rw-r--r--tests/auto/corelib/kernel/qtranslator/qtranslator.qrc2
-rw-r--r--tests/auto/corelib/kernel/qtranslator/tst_qtranslator.cpp121
9 files changed, 254 insertions, 61 deletions
diff --git a/tests/auto/corelib/kernel/qmetatype/tst_qmetatype.cpp b/tests/auto/corelib/kernel/qmetatype/tst_qmetatype.cpp
index 19b3289390..2e2209ac5d 100644
--- a/tests/auto/corelib/kernel/qmetatype/tst_qmetatype.cpp
+++ b/tests/auto/corelib/kernel/qmetatype/tst_qmetatype.cpp
@@ -369,7 +369,7 @@ protected:
const char *nm = name.constData();
int tp = qRegisterMetaType<Bar>(nm);
#if defined(Q_OS_LINUX) && !defined(Q_OS_ANDROID)
- pthread_yield();
+ sched_yield();
#endif
QMetaType info(tp);
if (!info.isValid()) {
diff --git a/tests/auto/corelib/kernel/qobject/tst_qobject.cpp b/tests/auto/corelib/kernel/qobject/tst_qobject.cpp
index 9bd66c0835..471d73e512 100644
--- a/tests/auto/corelib/kernel/qobject/tst_qobject.cpp
+++ b/tests/auto/corelib/kernel/qobject/tst_qobject.cpp
@@ -158,6 +158,7 @@ private slots:
void nullReceiver();
void functorReferencesConnection();
void disconnectDisconnects();
+ void declarativeData();
};
struct QObjectCreatedOnShutdown
@@ -3024,6 +3025,16 @@ void tst_QObject::recursiveSignalEmission()
QSKIP("No qprocess support", SkipAll);
#else
QProcess proc;
+
+ // Add the executable's directory to path so that we can find the test helper next to it
+ // in a cross-platform way. We must do this because the CWD is not pointing to this directory
+ // in debug-and-release builds.
+ QByteArray pathEnv = qgetenv("PATH");
+ qputenv("PATH",
+ pathEnv + QDir::listSeparator().toLatin1()
+ + QCoreApplication::applicationDirPath().toLocal8Bit());
+ auto restore = qScopeGuard([&] { qputenv("PATH", pathEnv); });
+
// signalbug helper app should always be next to this test binary
const QString path = QStringLiteral("signalbug_helper");
proc.start(path);
@@ -7679,5 +7690,77 @@ void tst_QObject::disconnectDisconnects()
Q_STATIC_ASSERT(QtPrivate::HasQ_OBJECT_Macro<tst_QObject>::Value);
Q_STATIC_ASSERT(!QtPrivate::HasQ_OBJECT_Macro<SiblingDeleter>::Value);
+#ifdef QT_BUILD_INTERNAL
+/*
+ Since QObjectPrivate stores the declarativeData pointer in a union with the pointer
+ to the currently destroyed child, calls to the QtDeclarative handlers need to be
+ correctly guarded. QTBUG-105286
+*/
+namespace QtDeclarative {
+static QAbstractDeclarativeData *theData;
+
+static void destroyed(QAbstractDeclarativeData *data, QObject *)
+{
+ QCOMPARE(data, theData);
+}
+static void signalEmitted(QAbstractDeclarativeData *data, QObject *, int, void **)
+{
+ QCOMPARE(data, theData);
+}
+// we can't use QCOMPARE in the next two functions, as they don't return void
+static int receivers(QAbstractDeclarativeData *data, const QObject *, int)
+{
+ QTest::qCompare(data, theData, "data", "theData", __FILE__, __LINE__);
+ return 0;
+}
+static bool isSignalConnected(QAbstractDeclarativeData *data, const QObject *, int)
+{
+ QTest::qCompare(data, theData, "data", "theData", __FILE__, __LINE__);
+ return true;
+}
+
+class Object : public QObject
+{
+ Q_OBJECT
+public:
+ using QObject::QObject;
+ ~Object()
+ {
+ if (Object *p = static_cast<Object *>(parent()))
+ p->emitSignal();
+ }
+
+ void emitSignal()
+ {
+ emit theSignal();
+ }
+
+signals:
+ void theSignal();
+};
+
+}
+#endif
+
+void tst_QObject::declarativeData()
+{
+#ifdef QT_BUILD_INTERNAL
+ QAbstractDeclarativeData::destroyed = QtDeclarative::destroyed;
+ QAbstractDeclarativeData::signalEmitted = QtDeclarative::signalEmitted;
+ QAbstractDeclarativeData::receivers = QtDeclarative::receivers;
+ QAbstractDeclarativeData::isSignalConnected = QtDeclarative::isSignalConnected;
+
+ QtDeclarative::Object p;
+ QObjectPrivate *priv = QObjectPrivate::get(&p);
+ priv->declarativeData = QtDeclarative::theData = new QAbstractDeclarativeData;
+
+ connect(&p, &QtDeclarative::Object::theSignal, &p, []{
+ });
+
+ QtDeclarative::Object *child = new QtDeclarative::Object;
+ child->setParent(&p);
+#endif
+}
+
QTEST_MAIN(tst_QObject)
#include "tst_qobject.moc"
diff --git a/tests/auto/corelib/kernel/qsharedmemory/tst_qsharedmemory.cpp b/tests/auto/corelib/kernel/qsharedmemory/tst_qsharedmemory.cpp
index fa2d5e3723..6be2744f3e 100644
--- a/tests/auto/corelib/kernel/qsharedmemory/tst_qsharedmemory.cpp
+++ b/tests/auto/corelib/kernel/qsharedmemory/tst_qsharedmemory.cpp
@@ -35,6 +35,7 @@
#include <QTest>
#include <QThread>
#include <QElapsedTimer>
+#include <QScopeGuard>
#define EXISTING_SHARE "existing"
#define EXISTING_SIZE 1024
@@ -444,8 +445,20 @@ void tst_QSharedMemory::readOnly()
QSKIP("No qprocess support", SkipAll);
#elif defined(Q_OS_MACOS)
QSKIP("QTBUG-59936: Times out on macOS", SkipAll);
+#elif defined(__SANITIZE_ADDRESS__) || __has_feature(address_sanitizer)
+ QSKIP("ASan prevents the crash this test is looking for.", SkipAll);
#else
rememberKey("readonly_segfault");
+
+ // Add the executable's directory to path so that we can find the test helper next to it
+ // in a cross-platform way. We must do this because the CWD is not pointing to this directory
+ // in debug-and-release builds.
+ QByteArray path = qgetenv("PATH");
+ qputenv("PATH",
+ path + QDir::listSeparator().toLatin1()
+ + QCoreApplication::applicationDirPath().toLocal8Bit());
+ auto restore = qScopeGuard([&] { qputenv("PATH", path); });
+
// ### on windows disable the popup somehow
QProcess p;
p.start(m_helperBinary, QStringList("readonly_segfault"));
@@ -747,6 +760,15 @@ void tst_QSharedMemory::simpleProcessProducerConsumer()
rememberKey("market");
+ // Add the executable's directory to path so that we can find the test helper next to it
+ // in a cross-platform way. We must do this because the CWD is not pointing to this directory
+ // in debug-and-release builds.
+ QByteArray path = qgetenv("PATH");
+ qputenv("PATH",
+ path + QDir::listSeparator().toLatin1()
+ + QCoreApplication::applicationDirPath().toLocal8Bit());
+ auto restore = qScopeGuard([&] { qputenv("PATH", path); });
+
QProcess producer;
producer.start(m_helperBinary, QStringList("producer"));
QVERIFY2(producer.waitForStarted(), "Could not start helper binary");
diff --git a/tests/auto/corelib/kernel/qsystemsemaphore/tst_qsystemsemaphore.cpp b/tests/auto/corelib/kernel/qsystemsemaphore/tst_qsystemsemaphore.cpp
index 5f010ae3d1..a73d806067 100644
--- a/tests/auto/corelib/kernel/qsystemsemaphore/tst_qsystemsemaphore.cpp
+++ b/tests/auto/corelib/kernel/qsystemsemaphore/tst_qsystemsemaphore.cpp
@@ -70,7 +70,14 @@ private:
};
tst_QSystemSemaphore::tst_QSystemSemaphore()
- : m_helperBinary("acquirerelease_helper")
+ :
+#ifdef Q_OS_WIN
+ // On windows the CWD is not the same as the test binary, so we cannot use the ./ path.
+ m_helperBinary("acquirerelease_helper")
+#else
+ // But on Unix we *must*
+ m_helperBinary("./acquirerelease_helper")
+#endif
{
}
diff --git a/tests/auto/corelib/kernel/qtimer/BLACKLIST b/tests/auto/corelib/kernel/qtimer/BLACKLIST
new file mode 100644
index 0000000000..2af0df9432
--- /dev/null
+++ b/tests/auto/corelib/kernel/qtimer/BLACKLIST
@@ -0,0 +1,3 @@
+[zeroTimer]
+ubuntu-20.04
+
diff --git a/tests/auto/corelib/kernel/qtimer/tst_qtimer.cpp b/tests/auto/corelib/kernel/qtimer/tst_qtimer.cpp
index 1bd27cd0ce..3c0adda5de 100644
--- a/tests/auto/corelib/kernel/qtimer/tst_qtimer.cpp
+++ b/tests/auto/corelib/kernel/qtimer/tst_qtimer.cpp
@@ -135,24 +135,53 @@ void tst_QTimer::timeout()
void tst_QTimer::remainingTime()
{
- QTimer timer;
- QSignalSpy timeoutSpy(&timer, &QTimer::timeout);
- timer.setTimerType(Qt::PreciseTimer);
- timer.start(200);
-
- QCOMPARE(timeoutSpy.count(), 0);
- QTest::qWait(50);
- QCOMPARE(timeoutSpy.count(), 0);
-
- int remainingTime = timer.remainingTime();
- QVERIFY2(remainingTime >= 50 && remainingTime <= 200, qPrintable(QString::number(remainingTime)));
-
- QVERIFY(timeoutSpy.wait());
- QCOMPARE(timeoutSpy.count(), 1);
-
- // the timer is still active, so it should have a non-zero remaining time
- remainingTime = timer.remainingTime();
- QVERIFY2(remainingTime >= 50, qPrintable(QString::number(remainingTime)));
+ QTimer tested;
+ tested.setTimerType(Qt::PreciseTimer);
+
+ QTimer tester;
+ tester.setTimerType(Qt::PreciseTimer);
+ tester.setSingleShot(true);
+
+ const int testedInterval = 200;
+ const int testerInterval = 50;
+ const int expectedRemainingTime = testedInterval - testerInterval;
+
+ int testIteration = 0;
+ const int desiredTestCount = 2;
+
+ auto connection = QObject::connect(&tested, &QTimer::timeout, [&tester]() {
+ // We let tested (which isn't a single-shot) run repeatedly, to verify
+ // it *does* repeat, and check that the single-shot tester, starting
+ // at the same time, does finish first each time, by about the right duration.
+ tester.start(); // Start tester again.
+ });
+
+ QObject::connect(&tester, &QTimer::timeout, [&]() {
+ const int remainingTime = tested.remainingTime();
+ // We expect that remainingTime is at most 150 and not overdue.
+ const bool remainingTimeInRange = remainingTime > 0
+ && remainingTime <= expectedRemainingTime;
+ if (remainingTimeInRange)
+ ++testIteration;
+ else
+ testIteration = desiredTestCount; // We are going to fail on QVERIFY2()
+ // below, so we don't want to iterate
+ // anymore and quickly exit the QTRY_...()
+ // with this failure.
+ if (testIteration == desiredTestCount)
+ QObject::disconnect(connection); // Last iteration, don't start tester again.
+ QVERIFY2(remainingTimeInRange, qPrintable("Remaining time "
+ + QByteArray::number(remainingTime) + "ms outside expected range (0ms, "
+ + QByteArray::number(expectedRemainingTime) + "ms]"));
+ });
+
+ tested.start(testedInterval);
+ tester.start(testerInterval); // Start tester for the 1st time.
+
+ // Test it desiredTestCount times, give it reasonable amount of time
+ // (twice as much as needed).
+ QTRY_COMPARE_WITH_TIMEOUT(testIteration, desiredTestCount,
+ testedInterval * desiredTestCount * 2);
}
void tst_QTimer::remainingTimeInitial_data()
diff --git a/tests/auto/corelib/kernel/qtranslator/android_testdata.qrc b/tests/auto/corelib/kernel/qtranslator/android_testdata.qrc
deleted file mode 100644
index 39b85db664..0000000000
--- a/tests/auto/corelib/kernel/qtranslator/android_testdata.qrc
+++ /dev/null
@@ -1,8 +0,0 @@
-<RCC>
- <qresource prefix="/android_testdata">
- <file>hellotr_la.qm</file>
- <file>hellotr_empty.qm</file>
- <file>msgfmt_from_po.qm</file>
- <file>dependencies_la.qm</file>
- </qresource>
-</RCC>
diff --git a/tests/auto/corelib/kernel/qtranslator/qtranslator.qrc b/tests/auto/corelib/kernel/qtranslator/qtranslator.qrc
index cb82c6cc95..6c99335215 100644
--- a/tests/auto/corelib/kernel/qtranslator/qtranslator.qrc
+++ b/tests/auto/corelib/kernel/qtranslator/qtranslator.qrc
@@ -1,6 +1,8 @@
<RCC>
<qresource prefix="/tst_qtranslator">
+ <file>dependencies_la.qm</file>
<file>hellotr_la.qm</file>
<file>hellotr_empty.qm</file>
+ <file>msgfmt_from_po.qm</file>
</qresource>
</RCC>
diff --git a/tests/auto/corelib/kernel/qtranslator/tst_qtranslator.cpp b/tests/auto/corelib/kernel/qtranslator/tst_qtranslator.cpp
index 9fde7da816..9f4e1773c8 100644
--- a/tests/auto/corelib/kernel/qtranslator/tst_qtranslator.cpp
+++ b/tests/auto/corelib/kernel/qtranslator/tst_qtranslator.cpp
@@ -29,6 +29,7 @@
#include <QtTest/QtTest>
#include <qtranslator.h>
#include <qfile.h>
+#include <qtemporarydir.h>
class tst_QTranslator : public QObject
{
@@ -40,9 +41,11 @@ protected:
bool eventFilter(QObject *obj, QEvent *event);
private slots:
void initTestCase();
+ void init();
void load_data();
void load();
+ void loadLocale();
void threadLoad();
void testLanguageChange();
void plural();
@@ -64,38 +67,14 @@ tst_QTranslator::tst_QTranslator()
void tst_QTranslator::initTestCase()
{
-#if defined(Q_OS_ANDROID) && !defined(Q_OS_ANDROID_EMBEDDED)
- QString sourceDir(":/android_testdata/");
- QDirIterator it(sourceDir, QDirIterator::Subdirectories);
- while (it.hasNext()) {
- it.next();
-
- QFileInfo sourceFileInfo = it.fileInfo();
- if (!sourceFileInfo.isDir()) {
- QFileInfo destinationFileInfo(QStandardPaths::writableLocation(QStandardPaths::CacheLocation) + QLatin1Char('/') + sourceFileInfo.filePath().mid(sourceDir.length()));
-
- if (!destinationFileInfo.exists()) {
- QVERIFY(QDir().mkpath(destinationFileInfo.path()));
- QVERIFY(QFile::copy(sourceFileInfo.filePath(), destinationFileInfo.filePath()));
- }
- }
- }
-
- QDir::setCurrent(QStandardPaths::writableLocation(QStandardPaths::CacheLocation));
-#endif
-
- // chdir into the directory containing our testdata,
- // to make the code simpler (load testdata via relative paths)
-#ifdef Q_OS_WINRT
- // ### TODO: Use this for all platforms in 5.7
- dataDir = QEXTRACTTESTDATA(QStringLiteral("/"));
+ dataDir = QEXTRACTTESTDATA(QStringLiteral("/tst_qtranslator"));
QVERIFY2(!dataDir.isNull(), qPrintable("Could not extract test data"));
- QVERIFY2(QDir::setCurrent(dataDir->path()), qPrintable("Could not chdir to " + dataDir->path()));
-#else // !Q_OS_WINRT
- QString testdata_dir = QFileInfo(QFINDTESTDATA("hellotr_la.qm")).absolutePath();
- QVERIFY2(QDir::setCurrent(testdata_dir), qPrintable("Could not chdir to " + testdata_dir));
-#endif // !Q_OS_WINRT
+}
+void tst_QTranslator::init()
+{
+ QVERIFY2(QDir::setCurrent(dataDir->path()),
+ qPrintable("Could not chdir to " + dataDir->path()));
}
bool tst_QTranslator::eventFilter(QObject *, QEvent *event)
@@ -155,6 +134,73 @@ void tst_QTranslator::load()
}
}
+void tst_QTranslator::loadLocale()
+{
+ QLocale locale;
+ auto localeName = locale.uiLanguages().value(0).replace('-', '_');
+ if (localeName.isEmpty())
+ QSKIP("This test requires at least one available UI language.");
+
+ QByteArray ba;
+ {
+ QFile file(":/tst_qtranslator/hellotr_la.qm");
+ QVERIFY2(file.open(QFile::ReadOnly), qPrintable(file.errorString()));
+ ba = file.readAll();
+ QVERIFY(!ba.isEmpty());
+ }
+
+ QTemporaryDir dir;
+ QVERIFY(dir.isValid());
+
+ auto path = dir.path();
+ QFile file(path + "/dummy");
+ QVERIFY2(file.open(QFile::WriteOnly), qPrintable(file.errorString()));
+ QCOMPARE(file.write(ba), ba.size());
+ file.close();
+
+ /*
+ Test the following order:
+
+ /tmp/tmpDir/foo-en_US.qm
+ /tmp/tmpDir/foo-en_US
+ /tmp/tmpDir/foo-en.qm
+ /tmp/tmpDir/foo-en
+ /tmp/tmpDir/foo.qm
+ /tmp/tmpDir/foo-
+ /tmp/tmpDir/foo
+ */
+
+ QStringList files;
+ while (true) {
+ files.append(path + "/foo-" + localeName + ".qm");
+ QVERIFY2(file.copy(files.last()), qPrintable(file.errorString()));
+
+ files.append(path + "/foo-" + localeName);
+ QVERIFY2(file.copy(files.last()), qPrintable(file.errorString()));
+
+ int rightmost = localeName.lastIndexOf(QLatin1Char('_'));
+ if (rightmost <= 0)
+ break;
+ localeName.truncate(rightmost);
+ }
+
+ files.append(path + "/foo.qm");
+ QVERIFY2(file.copy(files.last()), qPrintable(file.errorString()));
+
+ files.append(path + "/foo-");
+ QVERIFY2(file.copy(files.last()), qPrintable(file.errorString()));
+
+ files.append(path + "/foo");
+ QVERIFY2(file.rename(files.last()), qPrintable(file.errorString()));
+
+ QTranslator tor;
+ for (const auto &filePath : files) {
+ QVERIFY(tor.load(locale, "foo", "-", path, ".qm"));
+ QCOMPARE(tor.filePath(), filePath);
+ QVERIFY2(file.remove(filePath), qPrintable(file.errorString()));
+ }
+}
+
class TranslatorThread : public QThread
{
void run() {
@@ -307,6 +353,15 @@ void tst_QTranslator::dependencies()
QVERIFY(!tor.isEmpty());
QCOMPARE(tor.translate("QPushButton", "Hello world!"), QLatin1String("Hallo Welt!"));
}
+
+ {
+ // Test resolution of paths relative to main file
+ const QString absoluteFile = QFileInfo("dependencies_la").absoluteFilePath();
+ QDir::setCurrent(QDir::tempPath());
+ QTranslator tor;
+ QVERIFY(tor.load(absoluteFile));
+ QVERIFY(!tor.isEmpty());
+ }
}
struct TranslateThread : public QThread
@@ -346,9 +401,9 @@ void tst_QTranslator::translationInThreadWhileInstallingTranslator()
thread.runningCondition.wait(&thread.startupLock);
- QTranslator *tor = new QTranslator;
- tor->load("hellotr_la");
- QCoreApplication::installTranslator(tor);
+ QTranslator tor;
+ tor.load("hellotr_la");
+ QCoreApplication::installTranslator(&tor);
++thread.terminate;