File indexing completed on 2024-06-16 10:05:07

0001 /*
0002     SPDX-FileCopyrightText: 2006 David Faure <faure@kde.org>
0003 
0004     SPDX-License-Identifier: LGPL-2.0-only
0005 */
0006 
0007 #include "kmountpointtest.h"
0008 
0009 #include "kmountpoint.h"
0010 #include <QDebug>
0011 #include <QTest>
0012 #include <qplatformdefs.h>
0013 
0014 QTEST_MAIN(KMountPointTest)
0015 
0016 void KMountPointTest::initTestCase()
0017 {
0018 }
0019 
0020 void KMountPointTest::testCurrentMountPoints()
0021 {
0022     const KMountPoint::List mountPoints = KMountPoint::currentMountPoints(KMountPoint::NeedRealDeviceName);
0023     if (mountPoints.isEmpty()) { // can happen in chroot jails
0024         QSKIP("mtab is empty");
0025         return;
0026     }
0027     KMountPoint::Ptr mountWithDevice;
0028     for (KMountPoint::Ptr mountPoint : mountPoints) {
0029         qDebug() << mountPoint;
0030         QVERIFY(!mountPoint->mountedFrom().isEmpty());
0031         QVERIFY(!mountPoint->mountPoint().isEmpty());
0032         QVERIFY(!mountPoint->mountType().isEmpty());
0033         // old bug, happened because KMountPoint called KStandardDirs::realPath instead of realFilePath
0034         if (mountPoint->realDeviceName().startsWith(QLatin1String("/dev"))) { // skip this check for cifs mounts for instance
0035             QVERIFY(!mountPoint->realDeviceName().endsWith('/'));
0036         }
0037 
0038         // keep one (any) mountpoint with a device name for the test below
0039         if (!mountPoint->realDeviceName().isEmpty() && !mountWithDevice) {
0040             mountWithDevice = mountPoint;
0041         }
0042     }
0043 
0044     if (!mountWithDevice) {
0045         // This happens on build.kde.org (LXC virtualization, mtab points to non-existing device paths)
0046         qWarning() << "Couldn't find any mountpoint with a valid device?";
0047     } else {
0048         // Check findByDevice
0049         KMountPoint::Ptr found = mountPoints.findByDevice(mountWithDevice->mountedFrom());
0050         QVERIFY(found);
0051         QCOMPARE(found->mountPoint(), mountWithDevice->mountPoint());
0052         found = mountPoints.findByDevice(QStringLiteral("/I/Dont/Exist")); // krazy:exclude=spelling
0053         QVERIFY(!found);
0054     }
0055 
0056     // Check findByPath
0057 #ifdef Q_OS_UNIX
0058     const KMountPoint::Ptr rootMountPoint = mountPoints.findByPath(QStringLiteral("/"));
0059     QVERIFY(rootMountPoint);
0060     QCOMPARE(rootMountPoint->mountPoint(), QStringLiteral("/"));
0061     QVERIFY(!rootMountPoint->probablySlow());
0062 
0063     QT_STATBUF rootStatBuff;
0064     QCOMPARE(QT_STAT("/", &rootStatBuff), 0);
0065     QT_STATBUF homeStatBuff;
0066     if (QT_STAT("/home", &homeStatBuff) == 0) {
0067         bool sameDevice = rootStatBuff.st_dev == homeStatBuff.st_dev;
0068         const KMountPoint::Ptr homeMountPoint = mountPoints.findByPath(QStringLiteral("/home"));
0069         QVERIFY(homeMountPoint);
0070         // qDebug() << "Checking the home mount point, sameDevice=" << sameDevice;
0071         if (sameDevice) {
0072             QCOMPARE(homeMountPoint->mountPoint(), QStringLiteral("/"));
0073         } else {
0074             QCOMPARE(homeMountPoint->mountPoint(), QDir(QStringLiteral("/home")).canonicalPath());
0075         }
0076     } else {
0077         qDebug() << "/home doesn't seem to exist, skipping test";
0078     }
0079 #endif
0080 }
0081 
0082 void KMountPointTest::testCurrentMountPointOptions()
0083 {
0084     const KMountPoint::List mountPoints = KMountPoint::currentMountPoints(KMountPoint::NeedRealDeviceName | KMountPoint::NeedMountOptions);
0085     if (mountPoints.isEmpty()) { // can happen in chroot jails
0086         QSKIP("No mountpoints available.");
0087         return;
0088     }
0089 
0090     KMountPoint::Ptr anyZfsMount;
0091     KMountPoint::Ptr mountWithDevice;
0092     KMountPoint::Ptr mountWithOptions;
0093     for (KMountPoint::Ptr mountPoint : mountPoints) {
0094         // keep one (first) mountpoint with a device name
0095         if (!mountWithDevice && !mountPoint->realDeviceName().isEmpty()) {
0096             mountWithDevice = mountPoint;
0097         }
0098 
0099         // keep one (first) ZFS mountpoint
0100         if (!anyZfsMount && mountPoint->mountType() == QLatin1String("zfs")) {
0101             anyZfsMount = mountPoint;
0102         }
0103 
0104         // keep one (first) mountpoint with any options
0105         if (!mountWithOptions && !mountPoint->mountOptions().empty()) {
0106             mountWithOptions = mountPoint;
0107         }
0108     }
0109 
0110     if (!anyZfsMount) {
0111         qDebug() << "No ZFS mounts, skipping test";
0112     } else {
0113         // A ZFS mount doesn't have a "real device" because it comes from a pool
0114         QVERIFY(anyZfsMount->realDeviceName().isEmpty());
0115         // But it does always have a "local" option
0116         QVERIFY(!anyZfsMount->mountOptions().isEmpty());
0117         QVERIFY(anyZfsMount->mountOptions().contains(QLatin1String("local")));
0118         qDebug() << "ZFS mount options" << anyZfsMount->mountOptions();
0119     }
0120 
0121     if (!mountWithDevice) {
0122         qDebug() << "No mountpoint from real device, skipping test";
0123     } else {
0124         // Double-check
0125         QVERIFY(!mountWithDevice->realDeviceName().isEmpty());
0126         qDebug() << "Device mount options" << mountWithDevice->mountOptions();
0127     }
0128 
0129     if (!mountWithOptions) {
0130         qDebug() << "No mount with options, skipping test";
0131     } else {
0132         QVERIFY(!mountWithOptions->mountOptions().isEmpty());
0133         qDebug() << "Options mount options" << mountWithOptions->mountOptions();
0134     }
0135 }
0136 
0137 void KMountPointTest::testPossibleMountPoints()
0138 {
0139     const KMountPoint::List mountPoints = KMountPoint::possibleMountPoints(KMountPoint::NeedRealDeviceName | KMountPoint::NeedMountOptions);
0140     if (mountPoints.isEmpty()) { // can happen in chroot jails
0141         QSKIP("fstab is empty");
0142         return;
0143     }
0144     KMountPoint::Ptr mountWithDevice;
0145     for (KMountPoint::Ptr mountPoint : mountPoints) {
0146         qDebug() << "Possible mount: " << mountPoint->mountedFrom() << " (" << mountPoint->realDeviceName() << ") " << mountPoint->mountPoint() << " "
0147                  << mountPoint->mountType() << " options:" << mountPoint->mountOptions();
0148         QVERIFY(!mountPoint->mountedFrom().isEmpty());
0149         QVERIFY(!mountPoint->mountPoint().isEmpty());
0150         QVERIFY(!mountPoint->mountType().isEmpty());
0151         QVERIFY(!mountPoint->mountOptions().isEmpty());
0152         // old bug, happened because KMountPoint called KStandardDirs::realPath instead of realFilePath
0153         QVERIFY(!mountPoint->realDeviceName().endsWith('/'));
0154 
0155         // keep one (any) mountpoint with a device name for the test below
0156         if (!mountPoint->realDeviceName().isEmpty()) {
0157             mountWithDevice = mountPoint;
0158         }
0159     }
0160 
0161     if (!mountWithDevice) {
0162         qDebug() << "No mountpoint (" << mountPoints.size() << "checked ) has a non-empty real-device-name";
0163     }
0164     QVERIFY(mountWithDevice);
0165 
0166     // BSD CI runs in a container without '/' in fstab, so skip this
0167 #if defined(Q_OS_UNIX) && !defined(Q_OS_FREEBSD)
0168     const KMountPoint::Ptr rootMountPoint = mountPoints.findByPath(QStringLiteral("/"));
0169     QVERIFY(rootMountPoint);
0170     QCOMPARE(rootMountPoint->mountPoint(), QStringLiteral("/"));
0171     QVERIFY(rootMountPoint->realDeviceName().startsWith(QLatin1String("/"))); // Usually /dev, but can be /host/ubuntu/disks/root.disk...
0172     QVERIFY(!rootMountPoint->mountOptions().contains(QLatin1String("noauto"))); // how would this work?
0173     QVERIFY(!rootMountPoint->probablySlow());
0174 #endif
0175 }
0176 
0177 #include "moc_kmountpointtest.cpp"