1 /*
2 This file is part of the KDE project
3 SPDX-FileCopyrightText: 2013 Frank Reininghaus <frank78ac@googlemail.com>
4
5 SPDX-License-Identifier: LGPL-2.0-or-later
6 */
7
8 #include "udsentrytest.h"
9
10 #include <QDataStream>
11 #include <QTemporaryFile>
12 #include <QTest>
13 #include <QVector>
14 #include <qplatformdefs.h>
15
16 #include <kfileitem.h>
17 #include <udsentry.h>
18
19 #include "kiotesthelper.h"
20
21 struct UDSTestField {
UDSTestFieldUDSTestField22 UDSTestField()
23 {
24 }
25
UDSTestFieldUDSTestField26 UDSTestField(uint uds, const QString &value)
27 : m_uds(uds)
28 , m_string(value)
29 {
30 Q_ASSERT(uds & KIO::UDSEntry::UDS_STRING);
31 }
32
UDSTestFieldUDSTestField33 UDSTestField(uint uds, long long value)
34 : m_uds(uds)
35 , m_long(value)
36 {
37 Q_ASSERT(uds & KIO::UDSEntry::UDS_NUMBER);
38 }
39
40 uint m_uds;
41 QString m_string;
42 long long m_long;
43 };
44
45 /**
46 * Test that storing UDSEntries to a stream and then re-loading them works.
47 */
testSaveLoad()48 void UDSEntryTest::testSaveLoad()
49 {
50 const QVector<QVector<UDSTestField>> testCases{// Data for 1st UDSEntry.
51 {UDSTestField(KIO::UDSEntry::UDS_SIZE, 1),
52 UDSTestField(KIO::UDSEntry::UDS_USER, QStringLiteral("user1")),
53 UDSTestField(KIO::UDSEntry::UDS_GROUP, QStringLiteral("group1")),
54 UDSTestField(KIO::UDSEntry::UDS_NAME, QStringLiteral("filename1")),
55 UDSTestField(KIO::UDSEntry::UDS_MODIFICATION_TIME, 123456),
56 UDSTestField(KIO::UDSEntry::UDS_CREATION_TIME, 12345),
57 UDSTestField(KIO::UDSEntry::UDS_DEVICE_ID, 2),
58 UDSTestField(KIO::UDSEntry::UDS_INODE, 56)},
59 // 2nd entry: change some of the data.
60 {UDSTestField(KIO::UDSEntry::UDS_SIZE, 2),
61 UDSTestField(KIO::UDSEntry::UDS_USER, QStringLiteral("user2")),
62 UDSTestField(KIO::UDSEntry::UDS_GROUP, QStringLiteral("group1")),
63 UDSTestField(KIO::UDSEntry::UDS_NAME, QStringLiteral("filename2")),
64 UDSTestField(KIO::UDSEntry::UDS_MODIFICATION_TIME, 12345),
65 UDSTestField(KIO::UDSEntry::UDS_CREATION_TIME, 1234),
66 UDSTestField(KIO::UDSEntry::UDS_DEVICE_ID, 87),
67 UDSTestField(KIO::UDSEntry::UDS_INODE, 42)},
68 // 3rd entry: keep the data, but change the order of the entries.
69 {
70 UDSTestField(KIO::UDSEntry::UDS_SIZE, 2),
71 UDSTestField(KIO::UDSEntry::UDS_GROUP, QStringLiteral("group1")),
72 UDSTestField(KIO::UDSEntry::UDS_USER, QStringLiteral("user2")),
73 UDSTestField(KIO::UDSEntry::UDS_NAME, QStringLiteral("filename2")),
74 UDSTestField(KIO::UDSEntry::UDS_MODIFICATION_TIME, 12345),
75 UDSTestField(KIO::UDSEntry::UDS_DEVICE_ID, 87),
76 UDSTestField(KIO::UDSEntry::UDS_INODE, 42),
77 UDSTestField(KIO::UDSEntry::UDS_CREATION_TIME, 1234),
78 },
79 // 4th entry: change some of the data and the order of the entries.
80 {UDSTestField(KIO::UDSEntry::UDS_SIZE, 2),
81 UDSTestField(KIO::UDSEntry::UDS_USER, QStringLiteral("user4")),
82 UDSTestField(KIO::UDSEntry::UDS_GROUP, QStringLiteral("group4")),
83 UDSTestField(KIO::UDSEntry::UDS_MODIFICATION_TIME, 12346),
84 UDSTestField(KIO::UDSEntry::UDS_DEVICE_ID, 87),
85 UDSTestField(KIO::UDSEntry::UDS_INODE, 42),
86 UDSTestField(KIO::UDSEntry::UDS_CREATION_TIME, 1235),
87 UDSTestField(KIO::UDSEntry::UDS_NAME, QStringLiteral("filename4"))},
88 // 5th entry: remove one field.
89 {UDSTestField(KIO::UDSEntry::UDS_SIZE, 2),
90 UDSTestField(KIO::UDSEntry::UDS_USER, QStringLiteral("user4")),
91 UDSTestField(KIO::UDSEntry::UDS_GROUP, QStringLiteral("group4")),
92 UDSTestField(KIO::UDSEntry::UDS_MODIFICATION_TIME, 12346),
93 UDSTestField(KIO::UDSEntry::UDS_INODE, 42),
94 UDSTestField(KIO::UDSEntry::UDS_CREATION_TIME, 1235),
95 UDSTestField(KIO::UDSEntry::UDS_NAME, QStringLiteral("filename4"))},
96 // 6th entry: add a new field, and change some others.
97 {UDSTestField(KIO::UDSEntry::UDS_SIZE, 89),
98 UDSTestField(KIO::UDSEntry::UDS_ICON_NAME, QStringLiteral("icon6")),
99 UDSTestField(KIO::UDSEntry::UDS_USER, QStringLiteral("user6")),
100 UDSTestField(KIO::UDSEntry::UDS_GROUP, QStringLiteral("group4")),
101 UDSTestField(KIO::UDSEntry::UDS_MODIFICATION_TIME, 12346),
102 UDSTestField(KIO::UDSEntry::UDS_INODE, 32),
103 UDSTestField(KIO::UDSEntry::UDS_CREATION_TIME, 1235),
104 UDSTestField(KIO::UDSEntry::UDS_NAME, QStringLiteral("filename6"))}};
105 // Store the entries in a QByteArray.
106 QByteArray data;
107 {
108 QDataStream stream(&data, QIODevice::WriteOnly);
109 for (const QVector<UDSTestField> &testCase : testCases) {
110 KIO::UDSEntry entry;
111
112 for (const UDSTestField &field : testCase) {
113 uint uds = field.m_uds;
114 if (uds & KIO::UDSEntry::UDS_STRING) {
115 entry.fastInsert(uds, field.m_string);
116 } else {
117 Q_ASSERT(uds & KIO::UDSEntry::UDS_NUMBER);
118 entry.fastInsert(uds, field.m_long);
119 }
120 }
121
122 QCOMPARE(entry.count(), testCase.count());
123 stream << entry;
124 }
125 }
126
127 // Re-load the entries and compare with the data in testCases.
128 {
129 QDataStream stream(data);
130 for (const QVector<UDSTestField> &testCase : testCases) {
131 KIO::UDSEntry entry;
132 stream >> entry;
133 QCOMPARE(entry.count(), testCase.count());
134
135 for (const UDSTestField &field : testCase) {
136 uint uds = field.m_uds;
137 QVERIFY(entry.contains(uds));
138
139 if (uds & KIO::UDSEntry::UDS_STRING) {
140 QCOMPARE(entry.stringValue(uds), field.m_string);
141 } else {
142 Q_ASSERT(uds & KIO::UDSEntry::UDS_NUMBER);
143 QCOMPARE(entry.numberValue(uds), field.m_long);
144 }
145 }
146 }
147 }
148
149 // Now: Store the fields manually in the order in which they appear in
150 // testCases, and re-load them. This ensures that loading the entries
151 // works no matter in which order the fields appear in the QByteArray.
152 data.clear();
153
154 {
155 QDataStream stream(&data, QIODevice::WriteOnly);
156 for (const QVector<UDSTestField> &testCase : testCases) {
157 stream << testCase.count();
158
159 for (const UDSTestField &field : testCase) {
160 uint uds = field.m_uds;
161 stream << uds;
162
163 if (uds & KIO::UDSEntry::UDS_STRING) {
164 stream << field.m_string;
165 } else {
166 Q_ASSERT(uds & KIO::UDSEntry::UDS_NUMBER);
167 stream << field.m_long;
168 }
169 }
170 }
171 }
172
173 {
174 QDataStream stream(data);
175 for (const QVector<UDSTestField> &testCase : testCases) {
176 KIO::UDSEntry entry;
177 stream >> entry;
178 QCOMPARE(entry.count(), testCase.count());
179
180 for (const UDSTestField &field : testCase) {
181 uint uds = field.m_uds;
182 QVERIFY(entry.contains(uds));
183
184 if (uds & KIO::UDSEntry::UDS_STRING) {
185 QCOMPARE(entry.stringValue(uds), field.m_string);
186 } else {
187 Q_ASSERT(uds & KIO::UDSEntry::UDS_NUMBER);
188 QCOMPARE(entry.numberValue(uds), field.m_long);
189 }
190 }
191 }
192 }
193 }
194
195 /**
196 * Test to verify that move semantics work. This is only useful when ran through callgrind.
197 */
testMove()198 void UDSEntryTest::testMove()
199 {
200 // Create a temporary file. Just to make a UDSEntry further down.
201 QTemporaryFile file;
202 QVERIFY(file.open());
203 const QByteArray filePath = file.fileName().toLocal8Bit();
204 const QString fileName = QUrl(file.fileName()).fileName(); // QTemporaryFile::fileName returns the full path.
205 QVERIFY(!fileName.isEmpty());
206
207 // We have a file now. Get the stat data from it to make the UDSEntry.
208 QT_STATBUF statBuf;
209 QVERIFY(QT_LSTAT(filePath.constData(), &statBuf) == 0);
210 KIO::UDSEntry entry(statBuf, fileName);
211
212 // Verify that the name in the UDSEntry is the same as we've got from the fileName var.
213 QCOMPARE(fileName, entry.stringValue(KIO::UDSEntry::UDS_NAME));
214
215 // That was the boilerplate code. Now for move semantics.
216 // First: move assignment.
217 {
218 // First a copy as we need to keep the entry for the next test.
219 KIO::UDSEntry entryCopy = entry;
220
221 // Now move-assignment (two lines to prevent compiler optimization)
222 KIO::UDSEntry movedEntry;
223 movedEntry = std::move(entryCopy);
224
225 // And verify that this works.
226 QCOMPARE(fileName, movedEntry.stringValue(KIO::UDSEntry::UDS_NAME));
227 }
228
229 // Move constructor
230 {
231 // First a copy again
232 KIO::UDSEntry entryCopy = entry;
233
234 // Now move-assignment
235 KIO::UDSEntry movedEntry(std::move(entryCopy));
236
237 // And verify that this works.
238 QCOMPARE(fileName, movedEntry.stringValue(KIO::UDSEntry::UDS_NAME));
239 }
240 }
241
242 /**
243 * Test to verify that equal semantics work.
244 */
testEquality()245 void UDSEntryTest::testEquality()
246 {
247 KIO::UDSEntry entry;
248 entry.fastInsert(KIO::UDSEntry::UDS_SIZE, 1);
249 entry.fastInsert(KIO::UDSEntry::UDS_USER, QStringLiteral("user1"));
250 entry.fastInsert(KIO::UDSEntry::UDS_GROUP, QStringLiteral("group1"));
251 entry.fastInsert(KIO::UDSEntry::UDS_NAME, QStringLiteral("filename1"));
252 entry.fastInsert(KIO::UDSEntry::UDS_MODIFICATION_TIME, 123456);
253 entry.fastInsert(KIO::UDSEntry::UDS_CREATION_TIME, 12345);
254 entry.fastInsert(KIO::UDSEntry::UDS_DEVICE_ID, 2);
255 entry.fastInsert(KIO::UDSEntry::UDS_INODE, 56);
256
257 // Same as entry
258 KIO::UDSEntry entry2;
259 entry2.fastInsert(KIO::UDSEntry::UDS_SIZE, 1);
260 entry2.fastInsert(KIO::UDSEntry::UDS_USER, QStringLiteral("user1"));
261 entry2.fastInsert(KIO::UDSEntry::UDS_GROUP, QStringLiteral("group1"));
262 entry2.fastInsert(KIO::UDSEntry::UDS_NAME, QStringLiteral("filename1"));
263 entry2.fastInsert(KIO::UDSEntry::UDS_MODIFICATION_TIME, 123456);
264 entry2.fastInsert(KIO::UDSEntry::UDS_CREATION_TIME, 12345);
265 entry2.fastInsert(KIO::UDSEntry::UDS_DEVICE_ID, 2);
266 entry2.fastInsert(KIO::UDSEntry::UDS_INODE, 56);
267
268 // 3rd entry: different user.
269 KIO::UDSEntry entry3;
270 entry3.fastInsert(KIO::UDSEntry::UDS_SIZE, 1);
271 entry3.fastInsert(KIO::UDSEntry::UDS_USER, QStringLiteral("other user"));
272 entry3.fastInsert(KIO::UDSEntry::UDS_GROUP, QStringLiteral("group1"));
273 entry3.fastInsert(KIO::UDSEntry::UDS_NAME, QStringLiteral("filename1"));
274 entry3.fastInsert(KIO::UDSEntry::UDS_MODIFICATION_TIME, 123456);
275 entry3.fastInsert(KIO::UDSEntry::UDS_CREATION_TIME, 12345);
276 entry3.fastInsert(KIO::UDSEntry::UDS_DEVICE_ID, 2);
277 entry3.fastInsert(KIO::UDSEntry::UDS_INODE, 56);
278
279 // 4th entry : an additional field
280 KIO::UDSEntry entry4;
281 entry4.fastInsert(KIO::UDSEntry::UDS_SIZE, 1);
282 entry4.fastInsert(KIO::UDSEntry::UDS_USER, QStringLiteral("user1"));
283 entry4.fastInsert(KIO::UDSEntry::UDS_GROUP, QStringLiteral("group1"));
284 entry4.fastInsert(KIO::UDSEntry::UDS_NAME, QStringLiteral("filename1"));
285 entry4.fastInsert(KIO::UDSEntry::UDS_ICON_NAME, QStringLiteral("home"));
286 entry4.fastInsert(KIO::UDSEntry::UDS_MODIFICATION_TIME, 123456);
287 entry4.fastInsert(KIO::UDSEntry::UDS_CREATION_TIME, 12345);
288 entry4.fastInsert(KIO::UDSEntry::UDS_DEVICE_ID, 2);
289 entry4.fastInsert(KIO::UDSEntry::UDS_INODE, 56);
290
291 // ==
292 QVERIFY(entry == entry2);
293 QVERIFY(!(entry == entry3));
294 QVERIFY(!(entry == entry4));
295 QVERIFY(!(entry2 == entry3));
296
297 // !=
298 QVERIFY(!(entry != entry2));
299 QVERIFY(entry != entry3);
300 QVERIFY(entry != entry4);
301 QVERIFY(entry2 != entry3);
302
303 // make entry3 == entry
304 entry3.replace(KIO::UDSEntry::UDS_USER, QStringLiteral("user1"));
305
306 QVERIFY(entry == entry3);
307 QVERIFY(entry2 == entry3);
308 QVERIFY(!(entry != entry3));
309 QVERIFY(!(entry2 != entry3));
310 }
311
312 QTEST_MAIN(UDSEntryTest)
313