File indexing completed on 2024-06-23 10:37:27

0001 /*
0002     This file is part of the KDE project
0003     SPDX-FileCopyrightText: 2013 Frank Reininghaus <frank78ac@googlemail.com>
0004 
0005     SPDX-License-Identifier: LGPL-2.0-or-later
0006 */
0007 
0008 #include "udsentrytest.h"
0009 
0010 #include <QDataStream>
0011 #include <QTemporaryFile>
0012 #include <QTest>
0013 #include <QVector>
0014 #include <qplatformdefs.h>
0015 
0016 #include <kfileitem.h>
0017 #include <udsentry.h>
0018 
0019 #include "kiotesthelper.h"
0020 
0021 struct UDSTestField {
0022     UDSTestField()
0023     {
0024     }
0025 
0026     UDSTestField(uint uds, const QString &value)
0027         : m_uds(uds)
0028         , m_string(value)
0029     {
0030         Q_ASSERT(uds & KIO::UDSEntry::UDS_STRING);
0031     }
0032 
0033     UDSTestField(uint uds, long long value)
0034         : m_uds(uds)
0035         , m_long(value)
0036     {
0037         Q_ASSERT(uds & KIO::UDSEntry::UDS_NUMBER);
0038     }
0039 
0040     uint m_uds;
0041     QString m_string;
0042     long long m_long;
0043 };
0044 
0045 /**
0046  * Test that storing UDSEntries to a stream and then re-loading them works.
0047  */
0048 void UDSEntryTest::testSaveLoad()
0049 {
0050     const QVector<QVector<UDSTestField>> testCases{// Data for 1st UDSEntry.
0051                                                    {UDSTestField(KIO::UDSEntry::UDS_SIZE, 1),
0052                                                     UDSTestField(KIO::UDSEntry::UDS_USER, QStringLiteral("user1")),
0053                                                     UDSTestField(KIO::UDSEntry::UDS_GROUP, QStringLiteral("group1")),
0054                                                     UDSTestField(KIO::UDSEntry::UDS_NAME, QStringLiteral("filename1")),
0055                                                     UDSTestField(KIO::UDSEntry::UDS_MODIFICATION_TIME, 123456),
0056                                                     UDSTestField(KIO::UDSEntry::UDS_CREATION_TIME, 12345),
0057                                                     UDSTestField(KIO::UDSEntry::UDS_DEVICE_ID, 2),
0058                                                     UDSTestField(KIO::UDSEntry::UDS_INODE, 56)},
0059                                                    // 2nd entry: change some of the data.
0060                                                    {UDSTestField(KIO::UDSEntry::UDS_SIZE, 2),
0061                                                     UDSTestField(KIO::UDSEntry::UDS_USER, QStringLiteral("user2")),
0062                                                     UDSTestField(KIO::UDSEntry::UDS_GROUP, QStringLiteral("group1")),
0063                                                     UDSTestField(KIO::UDSEntry::UDS_NAME, QStringLiteral("filename2")),
0064                                                     UDSTestField(KIO::UDSEntry::UDS_MODIFICATION_TIME, 12345),
0065                                                     UDSTestField(KIO::UDSEntry::UDS_CREATION_TIME, 1234),
0066                                                     UDSTestField(KIO::UDSEntry::UDS_DEVICE_ID, 87),
0067                                                     UDSTestField(KIO::UDSEntry::UDS_INODE, 42)},
0068                                                    // 3rd entry: keep the data, but change the order of the entries.
0069                                                    {
0070                                                        UDSTestField(KIO::UDSEntry::UDS_SIZE, 2),
0071                                                        UDSTestField(KIO::UDSEntry::UDS_GROUP, QStringLiteral("group1")),
0072                                                        UDSTestField(KIO::UDSEntry::UDS_USER, QStringLiteral("user2")),
0073                                                        UDSTestField(KIO::UDSEntry::UDS_NAME, QStringLiteral("filename2")),
0074                                                        UDSTestField(KIO::UDSEntry::UDS_MODIFICATION_TIME, 12345),
0075                                                        UDSTestField(KIO::UDSEntry::UDS_DEVICE_ID, 87),
0076                                                        UDSTestField(KIO::UDSEntry::UDS_INODE, 42),
0077                                                        UDSTestField(KIO::UDSEntry::UDS_CREATION_TIME, 1234),
0078                                                    },
0079                                                    // 4th entry: change some of the data and the order of the entries.
0080                                                    {UDSTestField(KIO::UDSEntry::UDS_SIZE, 2),
0081                                                     UDSTestField(KIO::UDSEntry::UDS_USER, QStringLiteral("user4")),
0082                                                     UDSTestField(KIO::UDSEntry::UDS_GROUP, QStringLiteral("group4")),
0083                                                     UDSTestField(KIO::UDSEntry::UDS_MODIFICATION_TIME, 12346),
0084                                                     UDSTestField(KIO::UDSEntry::UDS_DEVICE_ID, 87),
0085                                                     UDSTestField(KIO::UDSEntry::UDS_INODE, 42),
0086                                                     UDSTestField(KIO::UDSEntry::UDS_CREATION_TIME, 1235),
0087                                                     UDSTestField(KIO::UDSEntry::UDS_NAME, QStringLiteral("filename4"))},
0088                                                    // 5th entry: remove one field.
0089                                                    {UDSTestField(KIO::UDSEntry::UDS_SIZE, 2),
0090                                                     UDSTestField(KIO::UDSEntry::UDS_USER, QStringLiteral("user4")),
0091                                                     UDSTestField(KIO::UDSEntry::UDS_GROUP, QStringLiteral("group4")),
0092                                                     UDSTestField(KIO::UDSEntry::UDS_MODIFICATION_TIME, 12346),
0093                                                     UDSTestField(KIO::UDSEntry::UDS_INODE, 42),
0094                                                     UDSTestField(KIO::UDSEntry::UDS_CREATION_TIME, 1235),
0095                                                     UDSTestField(KIO::UDSEntry::UDS_NAME, QStringLiteral("filename4"))},
0096                                                    // 6th entry: add a new field, and change some others.
0097                                                    {UDSTestField(KIO::UDSEntry::UDS_SIZE, 89),
0098                                                     UDSTestField(KIO::UDSEntry::UDS_ICON_NAME, QStringLiteral("icon6")),
0099                                                     UDSTestField(KIO::UDSEntry::UDS_USER, QStringLiteral("user6")),
0100                                                     UDSTestField(KIO::UDSEntry::UDS_GROUP, QStringLiteral("group4")),
0101                                                     UDSTestField(KIO::UDSEntry::UDS_MODIFICATION_TIME, 12346),
0102                                                     UDSTestField(KIO::UDSEntry::UDS_INODE, 32),
0103                                                     UDSTestField(KIO::UDSEntry::UDS_CREATION_TIME, 1235),
0104                                                     UDSTestField(KIO::UDSEntry::UDS_NAME, QStringLiteral("filename6"))}};
0105     // Store the entries in a QByteArray.
0106     QByteArray data;
0107     {
0108         QDataStream stream(&data, QIODevice::WriteOnly);
0109         for (const QVector<UDSTestField> &testCase : testCases) {
0110             KIO::UDSEntry entry;
0111 
0112             for (const UDSTestField &field : testCase) {
0113                 uint uds = field.m_uds;
0114                 if (uds & KIO::UDSEntry::UDS_STRING) {
0115                     entry.fastInsert(uds, field.m_string);
0116                 } else {
0117                     Q_ASSERT(uds & KIO::UDSEntry::UDS_NUMBER);
0118                     entry.fastInsert(uds, field.m_long);
0119                 }
0120             }
0121 
0122             QCOMPARE(entry.count(), testCase.count());
0123             stream << entry;
0124         }
0125     }
0126 
0127     // Re-load the entries and compare with the data in testCases.
0128     {
0129         QDataStream stream(data);
0130         for (const QVector<UDSTestField> &testCase : testCases) {
0131             KIO::UDSEntry entry;
0132             stream >> entry;
0133             QCOMPARE(entry.count(), testCase.count());
0134 
0135             for (const UDSTestField &field : testCase) {
0136                 uint uds = field.m_uds;
0137                 QVERIFY(entry.contains(uds));
0138 
0139                 if (uds & KIO::UDSEntry::UDS_STRING) {
0140                     QCOMPARE(entry.stringValue(uds), field.m_string);
0141                 } else {
0142                     Q_ASSERT(uds & KIO::UDSEntry::UDS_NUMBER);
0143                     QCOMPARE(entry.numberValue(uds), field.m_long);
0144                 }
0145             }
0146         }
0147     }
0148 
0149     // Now: Store the fields manually in the order in which they appear in
0150     // testCases, and re-load them. This ensures that loading the entries
0151     // works no matter in which order the fields appear in the QByteArray.
0152     data.clear();
0153 
0154     {
0155         QDataStream stream(&data, QIODevice::WriteOnly);
0156         for (const QVector<UDSTestField> &testCase : testCases) {
0157             stream << static_cast<quint32>(testCase.count());
0158 
0159             for (const UDSTestField &field : testCase) {
0160                 uint uds = field.m_uds;
0161                 stream << uds;
0162 
0163                 if (uds & KIO::UDSEntry::UDS_STRING) {
0164                     stream << field.m_string;
0165                 } else {
0166                     Q_ASSERT(uds & KIO::UDSEntry::UDS_NUMBER);
0167                     stream << field.m_long;
0168                 }
0169             }
0170         }
0171     }
0172 
0173     {
0174         QDataStream stream(data);
0175         for (const QVector<UDSTestField> &testCase : testCases) {
0176             KIO::UDSEntry entry;
0177             stream >> entry;
0178             QCOMPARE(entry.count(), testCase.count());
0179 
0180             for (const UDSTestField &field : testCase) {
0181                 uint uds = field.m_uds;
0182                 QVERIFY(entry.contains(uds));
0183 
0184                 if (uds & KIO::UDSEntry::UDS_STRING) {
0185                     QCOMPARE(entry.stringValue(uds), field.m_string);
0186                 } else {
0187                     Q_ASSERT(uds & KIO::UDSEntry::UDS_NUMBER);
0188                     QCOMPARE(entry.numberValue(uds), field.m_long);
0189                 }
0190             }
0191         }
0192     }
0193 }
0194 
0195 /**
0196  * Test to verify that move semantics work. This is only useful when ran through callgrind.
0197  */
0198 void UDSEntryTest::testMove()
0199 {
0200     // Create a temporary file. Just to make a UDSEntry further down.
0201     QTemporaryFile file;
0202     QVERIFY(file.open());
0203     const QByteArray filePath = file.fileName().toLocal8Bit();
0204     const QString fileName = QUrl(file.fileName()).fileName(); // QTemporaryFile::fileName returns the full path.
0205     QVERIFY(!fileName.isEmpty());
0206 
0207     // We have a file now. Get the stat data from it to make the UDSEntry.
0208     QT_STATBUF statBuf;
0209     QVERIFY(QT_LSTAT(filePath.constData(), &statBuf) == 0);
0210     KIO::UDSEntry entry(statBuf, fileName);
0211 
0212     // Verify that the name in the UDSEntry is the same as we've got from the fileName var.
0213     QCOMPARE(fileName, entry.stringValue(KIO::UDSEntry::UDS_NAME));
0214 
0215     // That was the boilerplate code. Now for move semantics.
0216     // First: move assignment.
0217     {
0218         // First a copy as we need to keep the entry for the next test.
0219         KIO::UDSEntry entryCopy = entry;
0220 
0221         // Now move-assignment (two lines to prevent compiler optimization)
0222         KIO::UDSEntry movedEntry;
0223         movedEntry = std::move(entryCopy);
0224 
0225         // And verify that this works.
0226         QCOMPARE(fileName, movedEntry.stringValue(KIO::UDSEntry::UDS_NAME));
0227     }
0228 
0229     // Move constructor
0230     {
0231         // First a copy again
0232         KIO::UDSEntry entryCopy = entry;
0233 
0234         // Now move-assignment
0235         KIO::UDSEntry movedEntry(std::move(entryCopy));
0236 
0237         // And verify that this works.
0238         QCOMPARE(fileName, movedEntry.stringValue(KIO::UDSEntry::UDS_NAME));
0239     }
0240 }
0241 
0242 /**
0243  * Test to verify that equal semantics work.
0244  */
0245 void UDSEntryTest::testEquality()
0246 {
0247     KIO::UDSEntry entry;
0248     entry.fastInsert(KIO::UDSEntry::UDS_SIZE, 1);
0249     entry.fastInsert(KIO::UDSEntry::UDS_USER, QStringLiteral("user1"));
0250     entry.fastInsert(KIO::UDSEntry::UDS_GROUP, QStringLiteral("group1"));
0251     entry.fastInsert(KIO::UDSEntry::UDS_NAME, QStringLiteral("filename1"));
0252     entry.fastInsert(KIO::UDSEntry::UDS_MODIFICATION_TIME, 123456);
0253     entry.fastInsert(KIO::UDSEntry::UDS_CREATION_TIME, 12345);
0254     entry.fastInsert(KIO::UDSEntry::UDS_DEVICE_ID, 2);
0255     entry.fastInsert(KIO::UDSEntry::UDS_INODE, 56);
0256 
0257     // Same as entry
0258     KIO::UDSEntry entry2;
0259     entry2.fastInsert(KIO::UDSEntry::UDS_SIZE, 1);
0260     entry2.fastInsert(KIO::UDSEntry::UDS_USER, QStringLiteral("user1"));
0261     entry2.fastInsert(KIO::UDSEntry::UDS_GROUP, QStringLiteral("group1"));
0262     entry2.fastInsert(KIO::UDSEntry::UDS_NAME, QStringLiteral("filename1"));
0263     entry2.fastInsert(KIO::UDSEntry::UDS_MODIFICATION_TIME, 123456);
0264     entry2.fastInsert(KIO::UDSEntry::UDS_CREATION_TIME, 12345);
0265     entry2.fastInsert(KIO::UDSEntry::UDS_DEVICE_ID, 2);
0266     entry2.fastInsert(KIO::UDSEntry::UDS_INODE, 56);
0267 
0268     // 3rd entry: different user.
0269     KIO::UDSEntry entry3;
0270     entry3.fastInsert(KIO::UDSEntry::UDS_SIZE, 1);
0271     entry3.fastInsert(KIO::UDSEntry::UDS_USER, QStringLiteral("other user"));
0272     entry3.fastInsert(KIO::UDSEntry::UDS_GROUP, QStringLiteral("group1"));
0273     entry3.fastInsert(KIO::UDSEntry::UDS_NAME, QStringLiteral("filename1"));
0274     entry3.fastInsert(KIO::UDSEntry::UDS_MODIFICATION_TIME, 123456);
0275     entry3.fastInsert(KIO::UDSEntry::UDS_CREATION_TIME, 12345);
0276     entry3.fastInsert(KIO::UDSEntry::UDS_DEVICE_ID, 2);
0277     entry3.fastInsert(KIO::UDSEntry::UDS_INODE, 56);
0278 
0279     // 4th entry : an additional field
0280     KIO::UDSEntry entry4;
0281     entry4.fastInsert(KIO::UDSEntry::UDS_SIZE, 1);
0282     entry4.fastInsert(KIO::UDSEntry::UDS_USER, QStringLiteral("user1"));
0283     entry4.fastInsert(KIO::UDSEntry::UDS_GROUP, QStringLiteral("group1"));
0284     entry4.fastInsert(KIO::UDSEntry::UDS_NAME, QStringLiteral("filename1"));
0285     entry4.fastInsert(KIO::UDSEntry::UDS_ICON_NAME, QStringLiteral("home"));
0286     entry4.fastInsert(KIO::UDSEntry::UDS_MODIFICATION_TIME, 123456);
0287     entry4.fastInsert(KIO::UDSEntry::UDS_CREATION_TIME, 12345);
0288     entry4.fastInsert(KIO::UDSEntry::UDS_DEVICE_ID, 2);
0289     entry4.fastInsert(KIO::UDSEntry::UDS_INODE, 56);
0290 
0291     // ==
0292     QVERIFY(entry == entry2);
0293     QVERIFY(!(entry == entry3));
0294     QVERIFY(!(entry == entry4));
0295     QVERIFY(!(entry2 == entry3));
0296 
0297     // !=
0298     QVERIFY(!(entry != entry2));
0299     QVERIFY(entry != entry3);
0300     QVERIFY(entry != entry4);
0301     QVERIFY(entry2 != entry3);
0302 
0303     // make entry3 == entry
0304     entry3.replace(KIO::UDSEntry::UDS_USER, QStringLiteral("user1"));
0305 
0306     QVERIFY(entry == entry3);
0307     QVERIFY(entry2 == entry3);
0308     QVERIFY(!(entry != entry3));
0309     QVERIFY(!(entry2 != entry3));
0310 }
0311 
0312 QTEST_MAIN(UDSEntryTest)
0313 
0314 #include "moc_udsentrytest.cpp"