summaryrefslogtreecommitdiffstats
path: root/tests/auto/corelib/io/qfile
diff options
context:
space:
mode:
authorThiago Macieira <thiago.macieira@intel.com>2023-06-08 17:53:29 -0700
committerThiago Macieira <thiago.macieira@intel.com>2023-06-09 20:30:07 -0700
commit01872d06d9a09c83f28b3ecebcb06f0ed81c5622 (patch)
treeee97271ff1269a1c0efdb8462a1b354d6ef3e6d6 /tests/auto/corelib/io/qfile
parent65097e7667c96177c322ebd45f7ac5c74fee7a26 (diff)
tst_QFile: replicate the unixPipe test using FIFOs
Pipes are unnamed FIFOs, so they're basically the same. The difference here is that open() blocks on opening a FIFO until both ends of the FIFO are opened. This helps us in synchronizing the two threads and thus ensuring that that the read() system call deep inside QFile does, indeed, block. We see this with strace -T on Linux: [pid 662956] openat(AT_FDCWD, "/run/user/1000/tst_qfile_fifo.2575572361", O_RDONLY|O_CLOEXEC <unfinished ...> ... aux starts up ... [pid 662957] prctl(PR_SET_NAME, "QThread") = 0 <0.000004> [pid 662957] openat(AT_FDCWD, "/run/user/1000/tst_qfile_fifo.2575572361", O_WRONLY|O_CLOEXEC <unfinished ...> [pid 662956] <... openat resumed>) = 4 <0.000133> [pid 662957] <... openat resumed>) = 6 <0.000011> [pid 662957] clock_nanosleep(CLOCK_REALTIME, 0, {tv_sec=0, tv_nsec=500000000}, <unfinished ...> [pid 662956] read(4, <unfinished ...> [pid 662957] <... clock_nanosleep resumed>NULL) = 0 <0.500183> [pid 662957] write(6, "\2", 1) = 1 <0.000033> [pid 662956] <... read resumed>"\2", 1) = 1 <0.500311> Pick-to: 6.6 Change-Id: I63b988479db546dabffcfffd1766d7a48819b149 Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
Diffstat (limited to 'tests/auto/corelib/io/qfile')
-rw-r--r--tests/auto/corelib/io/qfile/tst_qfile.cpp54
1 files changed, 54 insertions, 0 deletions
diff --git a/tests/auto/corelib/io/qfile/tst_qfile.cpp b/tests/auto/corelib/io/qfile/tst_qfile.cpp
index e2862e321c..64a3687e2a 100644
--- a/tests/auto/corelib/io/qfile/tst_qfile.cpp
+++ b/tests/auto/corelib/io/qfile/tst_qfile.cpp
@@ -13,6 +13,7 @@
#include <QDir>
#include <QFile>
#include <QFileInfo>
+#include <QRandomGenerator>
#include <QTemporaryDir>
#include <QTemporaryFile>
#include <QOperatingSystemVersion>
@@ -227,6 +228,8 @@ private slots:
#ifdef Q_OS_UNIX
void unixPipe_data();
void unixPipe();
+ void unixFifo_data() { unixPipe_data(); }
+ void unixFifo();
void socketPair_data() { unixPipe_data(); }
void socketPair();
#endif
@@ -2679,6 +2682,57 @@ void tst_QFile::unixPipe()
qt_safe_close(pipes[1]);
}
+void tst_QFile::unixFifo()
+{
+ QByteArray fifopath = []() -> QByteArray {
+ QByteArray dir = qgetenv("XDG_RUNTIME_DIR");
+ if (dir.isEmpty())
+ dir = QFile::encodeName(QDir::tempPath());
+
+ // try to create a FIFO
+ for (int attempts = 10; attempts; --attempts) {
+ QByteArray fifopath = dir + "/tst_qfile_fifo." +
+ QByteArray::number(QRandomGenerator::global()->generate());
+ int ret = mkfifo(fifopath, 0600);
+ if (ret == 0)
+ return fifopath;
+ }
+
+ qWarning("Failed to create a FIFO at %s; last error was %s",
+ dir.constData(), strerror(errno));
+ return {};
+ }();
+ if (fifopath.isEmpty())
+ return;
+
+ auto removeFifo = qScopeGuard([&fifopath] { unlink(fifopath); });
+
+ // with a FIFO, the two open() system calls synchronize
+ QScopedPointer<QThread> thr(QThread::create([&fifopath]() {
+ int fd = qt_safe_open(fifopath, O_WRONLY);
+ QTest::qSleep(500);
+ char c = 2;
+ qt_safe_write(fd, &c, 1);
+ qt_safe_close(fd);
+ }));
+ thr->start();
+
+ QFETCH(bool, useStdio);
+ QFile f;
+ if (useStdio) {
+ FILE *fh = fopen(fifopath, "rb");
+ QVERIFY(f.open(fh, QIODevice::ReadOnly | QIODevice::Unbuffered, QFileDevice::AutoCloseHandle));
+ } else {
+ f.setFileName(QFile::decodeName(fifopath));
+ QVERIFY(f.open(QIODevice::ReadOnly | QIODevice::Unbuffered));
+ }
+
+ char c = 0;
+ QCOMPARE(f.read(&c, 1), 1); // this ought to block
+ QCOMPARE(c, '\2');
+ thr->wait();
+}
+
void tst_QFile::socketPair()
{
int pipes[2] = { -1, -1 };