summaryrefslogtreecommitdiffstats
path: root/tests/auto/corelib/io/qfileinfo
diff options
context:
space:
mode:
authorThiago Macieira <thiago.macieira@intel.com>2016-07-23 11:14:57 -0700
committerThiago Macieira <thiago.macieira@intel.com>2017-08-05 16:41:38 +0000
commit6c3a3d498a8797c481a394418fff8f7bf1886c61 (patch)
treeb64407f2b2520d46b42f96495c41600aaae03d3c /tests/auto/corelib/io/qfileinfo
parentdb433bdf65e011e64be51948e79abc02034dddbf (diff)
Filesystem: Use "birth time" to avoid confusion with Unix ctime
The Unix stat fields "st_ctime" and "st_ctim" mean "change time", the last time that the file/inode status fields were changed. It does not mean "creation time". So this commit splits all of the internal API to "birth" and "metadata change" instead of "creation" to avoid the conflict. Change-Id: I149e0540c00745fe8119fffd1463fe78b619649e Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
Diffstat (limited to 'tests/auto/corelib/io/qfileinfo')
-rw-r--r--tests/auto/corelib/io/qfileinfo/tst_qfileinfo.cpp212
1 files changed, 107 insertions, 105 deletions
diff --git a/tests/auto/corelib/io/qfileinfo/tst_qfileinfo.cpp b/tests/auto/corelib/io/qfileinfo/tst_qfileinfo.cpp
index b269e3e1e4..94273e2394 100644
--- a/tests/auto/corelib/io/qfileinfo/tst_qfileinfo.cpp
+++ b/tests/auto/corelib/io/qfileinfo/tst_qfileinfo.cpp
@@ -35,6 +35,7 @@
#include <qtemporarydir.h>
#include <qdir.h>
#include <qfileinfo.h>
+#include <qstorageinfo.h>
#ifdef Q_OS_UNIX
#include <errno.h>
#include <fcntl.h>
@@ -64,84 +65,38 @@
#define Q_NO_SYMLINKS
#endif
-
-#if defined(Q_OS_UNIX) && !defined(Q_OS_VXWORKS)
-inline bool qt_isEvilFsTypeName(const char *name)
-{
- return (qstrncmp(name, "nfs", 3) == 0
- || qstrncmp(name, "autofs", 6) == 0
- || qstrncmp(name, "cachefs", 7) == 0);
-}
-
-#if defined(Q_OS_BSD4) && !defined(Q_OS_NETBSD)
-# include <sys/param.h>
-# include <sys/mount.h>
-
-bool qIsLikelyToBeNfs(int handle)
-{
- struct statfs buf;
- if (fstatfs(handle, &buf) != 0)
- return false;
- return qt_isEvilFsTypeName(buf.f_fstypename);
-}
-
-#elif defined(Q_OS_LINUX) || defined(Q_OS_HURD)
-
-# include <sys/vfs.h>
-# ifdef QT_LINUXBASE
- // LSB 3.2 has fstatfs in sys/statfs.h, sys/vfs.h is just an empty dummy header
-# include <sys/statfs.h>
-# endif
-
-# ifndef NFS_SUPER_MAGIC
-# define NFS_SUPER_MAGIC 0x00006969
-# endif
-# ifndef AUTOFS_SUPER_MAGIC
-# define AUTOFS_SUPER_MAGIC 0x00000187
-# endif
-# ifndef AUTOFSNG_SUPER_MAGIC
-# define AUTOFSNG_SUPER_MAGIC 0x7d92b1a0
-# endif
-
-bool qIsLikelyToBeNfs(int handle)
+inline bool qIsLikelyToBeFat(const QString &path)
{
- struct statfs buf;
- if (fstatfs(handle, &buf) != 0)
- return false;
- return buf.f_type == NFS_SUPER_MAGIC
- || buf.f_type == AUTOFS_SUPER_MAGIC
- || buf.f_type == AUTOFSNG_SUPER_MAGIC;
+ QByteArray name = QStorageInfo(path).fileSystemType().toLower();
+ return name.contains("fat") || name.contains("msdos");
}
-#elif defined(Q_OS_SOLARIS) || defined(Q_OS_IRIX) || defined(Q_OS_AIX) || defined(Q_OS_HPUX) \
- || defined(Q_OS_OSF) || defined(Q_OS_QNX) || defined(Q_OS_SCO) \
- || defined(Q_OS_UNIXWARE) || defined(Q_OS_RELIANT) || defined(Q_OS_NETBSD)
-
-# include <sys/statvfs.h>
-
-bool qIsLikelyToBeNfs(int handle)
+inline bool qIsLikelyToBeNfs(const QString &path)
{
- struct statvfs buf;
- if (fstatvfs(handle, &buf) != 0)
- return false;
-#if defined(Q_OS_NETBSD)
- return qt_isEvilFsTypeName(buf.f_fstypename);
+#ifdef Q_OS_WIN
+ Q_UNUSED(path);
+ return false;
#else
- return qt_isEvilFsTypeName(buf.f_basetype);
+ QByteArray type = QStorageInfo(path).fileSystemType();
+ const char *name = type.constData();
+
+ return (qstrncmp(name, "nfs", 3) == 0
+ || qstrncmp(name, "autofs", 6) == 0
+ || qstrncmp(name, "autofsng", 8) == 0
+ || qstrncmp(name, "cachefs", 7) == 0);
#endif
}
-#else
-inline bool qIsLikelyToBeNfs(int /* handle */)
-{
- return false;
-}
-#endif
-#endif
static QString seedAndTemplate()
{
- qsrand(QDateTime::currentSecsSinceEpoch());
- return QDir::tempPath() + "/tst_qfileinfo-XXXXXX";
+ QString base;
+#if defined(Q_OS_UNIX) && !defined(Q_OS_ANDROID)
+ // use XDG_RUNTIME_DIR as it's a fully-capable FS
+ base = QStandardPaths::writableLocation(QStandardPaths::RuntimeLocation);
+#endif
+ if (base.isEmpty())
+ base = QDir::tempPath();
+ return base + "/tst_qfileinfo-XXXXXX";
}
static QByteArray msgDoesNotExist(const QString &name)
@@ -1129,43 +1084,92 @@ void tst_QFileInfo::fileTimes_data()
void tst_QFileInfo::fileTimes()
{
- int sleepTime = 2000;
+ auto datePairString = [](const QDateTime &actual, const QDateTime &before) {
+ return (actual.toString(Qt::ISODateWithMs) + " (should be >) " + before.toString(Qt::ISODateWithMs))
+ .toLatin1();
+ };
+
QFETCH(QString, fileName);
+ int sleepTime = 100;
+
+ // on Linux and Windows, the filesystem timestamps may be slightly out of
+ // sync with the system clock (maybe they're using CLOCK_REALTIME_COARSE),
+ // so add a margin of error to our comparisons
+ int fsClockSkew = 10;
+#ifdef Q_OS_WIN
+ fsClockSkew = 500;
+#endif
+
+ // NFS clocks may be WAY out of sync
+ if (qIsLikelyToBeNfs(fileName))
+ QSKIP("This test doesn't work on NFS");
+
+ bool noAccessTime = false;
+ {
+ // try to guess if file times on this filesystem round to the second
+ QFileInfo cwd(".");
+ if (cwd.lastModified().toMSecsSinceEpoch() % 1000 == 0
+ && cwd.lastRead().toMSecsSinceEpoch() % 1000 == 0) {
+ fsClockSkew = sleepTime = 1000;
+
+ noAccessTime = qIsLikelyToBeFat(fileName);
+ if (noAccessTime) {
+ // FAT filesystems (but maybe not exFAT) store timestamps with 2-second
+ // granularity and access time with 1-day granularity
+ fsClockSkew = sleepTime = 2000;
+ }
+ }
+ }
+
if (QFile::exists(fileName)) {
QVERIFY(QFile::remove(fileName));
}
- QTest::qSleep(sleepTime);
+
+ QDateTime beforeBirth, beforeWrite, beforeMetadataChange, beforeRead;
+ QDateTime birthTime, writeTime, metadataChangeTime, readTime;
+
+ // --- Create file and write to it
+ beforeBirth = QDateTime::currentDateTime().addMSecs(-fsClockSkew);
{
QFile file(fileName);
QVERIFY(file.open(QFile::WriteOnly | QFile::Text));
-#if defined(Q_OS_UNIX) && !defined(Q_OS_VXWORKS)
- if (qIsLikelyToBeNfs(file.handle()))
- QSKIP("This Test doesn't work on NFS");
-#endif
+ QFileInfo fileInfo(fileName);
+ birthTime = fileInfo.birthTime();
+ QVERIFY2(!birthTime.isValid() || birthTime > beforeBirth,
+ datePairString(birthTime, beforeBirth));
+
+ QTest::qSleep(sleepTime);
+ beforeWrite = QDateTime::currentDateTime().addMSecs(-fsClockSkew);
QTextStream ts(&file);
ts << fileName << endl;
}
- QTest::qSleep(sleepTime);
- QDateTime beforeWrite = QDateTime::currentDateTime();
- QTest::qSleep(sleepTime);
{
QFileInfo fileInfo(fileName);
- QVERIFY(!fileInfo.birthTime().isValid() || fileInfo.birthTime() < beforeWrite);
- QVERIFY(fileInfo.metadataChangeTime() < beforeWrite);
- QVERIFY(fileInfo.created() < beforeWrite);
- QFile file(fileName);
- QVERIFY(file.open(QFile::ReadWrite | QFile::Text));
- QTextStream ts(&file);
- ts << fileName << endl;
+ writeTime = fileInfo.lastModified();
+ QVERIFY2(writeTime > beforeWrite, datePairString(writeTime, beforeWrite));
+ QCOMPARE(fileInfo.birthTime(), birthTime); // mustn't have changed
}
+
+ // --- Change the file's metadata
QTest::qSleep(sleepTime);
- QDateTime beforeRead = QDateTime::currentDateTime();
- QTest::qSleep(sleepTime);
+ beforeMetadataChange = QDateTime::currentDateTime().addMSecs(-fsClockSkew);
+ {
+ QFile file(fileName);
+ file.setPermissions(file.permissions());
+ }
{
QFileInfo fileInfo(fileName);
- QVERIFY(!fileInfo.birthTime().isValid() || fileInfo.birthTime() < beforeWrite);
- QVERIFY(fileInfo.metadataChangeTime() > beforeWrite);
- QVERIFY(fileInfo.lastModified() > beforeWrite);
+ metadataChangeTime = fileInfo.metadataChangeTime();
+ QVERIFY2(metadataChangeTime > beforeMetadataChange,
+ datePairString(metadataChangeTime, beforeMetadataChange));
+ QVERIFY(metadataChangeTime >= writeTime); // not all filesystems can store both times
+ QCOMPARE(fileInfo.birthTime(), birthTime); // mustn't have changed
+ }
+
+ // --- Read the file
+ QTest::qSleep(sleepTime);
+ beforeRead = QDateTime::currentDateTime().addMSecs(-fsClockSkew);
+ {
QFile file(fileName);
QVERIFY(file.open(QFile::ReadOnly | QFile::Text));
QTextStream ts(&file);
@@ -1174,13 +1178,17 @@ void tst_QFileInfo::fileTimes()
}
QFileInfo fileInfo(fileName);
- QVERIFY(!fileInfo.birthTime().isValid() || fileInfo.birthTime() < beforeWrite);
- QVERIFY(fileInfo.metadataChangeTime() > beforeWrite);
-
+ readTime = fileInfo.lastRead();
+ QCOMPARE(fileInfo.lastModified(), writeTime); // mustn't have changed
+ QCOMPARE(fileInfo.birthTime(), birthTime); // mustn't have changed
+ QVERIFY(readTime.isValid());
+
+#if defined(Q_OS_WINRT) || defined(Q_OS_QNX) || defined(Q_OS_ANDROID)
+ noAccessTime = true;
+#elif defined(Q_OS_WIN)
//In Vista the last-access timestamp is not updated when the file is accessed/touched (by default).
//To enable this the HKLM\SYSTEM\CurrentControlSet\Control\FileSystem\NtfsDisableLastAccessUpdate
//is set to 0, in the test machine.
-#if defined(Q_OS_WIN) && !defined(Q_OS_WINRT)
HKEY key;
if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, L"SYSTEM\\CurrentControlSet\\Control\\FileSystem",
0, KEY_READ, &key)) {
@@ -1189,22 +1197,16 @@ void tst_QFileInfo::fileTimes()
LONG error = RegQueryValueEx(key, L"NtfsDisableLastAccessUpdate"
, NULL, NULL, (LPBYTE)&disabledAccessTimes, &size);
if (ERROR_SUCCESS == error && disabledAccessTimes)
- QEXPECT_FAIL("", "File access times are disabled in windows registry (this is the default setting)", Continue);
+ noAccessTime = true;
RegCloseKey(key);
}
#endif
-#if defined(Q_OS_WINRT)
- QEXPECT_FAIL("", "WinRT does not allow timestamp handling change in the filesystem due to sandboxing", Continue);
-#elif defined(Q_OS_QNX)
- QEXPECT_FAIL("", "QNX uses the noatime filesystem option", Continue);
-#elif defined(Q_OS_ANDROID)
- if (fileInfo.lastRead() <= beforeRead)
- QEXPECT_FAIL("", "Android may use relatime or noatime on mounts", Continue);
-#endif
- QVERIFY(fileInfo.lastRead() > beforeRead);
- QVERIFY(fileInfo.lastModified() > beforeWrite);
- QVERIFY(fileInfo.lastModified() < beforeRead);
+ if (noAccessTime)
+ return;
+
+ QVERIFY2(readTime > beforeRead, datePairString(readTime, beforeRead));
+ QVERIFY(writeTime < beforeRead);
}
void tst_QFileInfo::fileTimes_oldFile()