1 /* This file is part of the KDE project
2 SPDX-FileCopyrightText: 2010 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.net>
3 SPDX-FileContributor: Kevin Krammer <krake@kdab.com>
4
5 SPDX-License-Identifier: LGPL-2.0-or-later
6 */
7
8 #include "mixedmaildirstore.h"
9
10 #include "filestore/collectiondeletejob.h"
11
12 #include "libmaildir/maildir.h"
13
14 #include <QTemporaryDir>
15
16 #include <QDir>
17 #include <QFileInfo>
18 #include <QTest>
19
20 using namespace Akonadi;
21
22 class CollectionDeleteTest : public QObject
23 {
24 Q_OBJECT
25
26 public:
CollectionDeleteTest()27 CollectionDeleteTest()
28 : QObject()
29 , mStore(nullptr)
30 , mDir(nullptr)
31 {
32 }
33
~CollectionDeleteTest()34 ~CollectionDeleteTest() override
35 {
36 delete mStore;
37 delete mDir;
38 }
39
40 private:
41 MixedMaildirStore *mStore = nullptr;
42 QTemporaryDir *mDir = nullptr;
43
44 private Q_SLOTS:
45 void init();
46 void cleanup();
47 void testNonExisting();
48 void testLeaves();
49 void testSubTrees();
50 };
51
init()52 void CollectionDeleteTest::init()
53 {
54 mStore = new MixedMaildirStore;
55
56 mDir = new QTemporaryDir;
57 QVERIFY(mDir->isValid());
58 QVERIFY(QDir(mDir->path()).exists());
59 }
60
cleanup()61 void CollectionDeleteTest::cleanup()
62 {
63 delete mStore;
64 mStore = nullptr;
65 delete mDir;
66 mDir = nullptr;
67 }
68
testNonExisting()69 void CollectionDeleteTest::testNonExisting()
70 {
71 KPIM::Maildir topLevelMd(mDir->path(), true);
72 QVERIFY(topLevelMd.isValid(false));
73
74 KPIM::Maildir md1(topLevelMd.addSubFolder(QStringLiteral("collection1")), false);
75 KPIM::Maildir md1_2(md1.addSubFolder(QStringLiteral("collection1_2")), false);
76
77 KPIM::Maildir md2(topLevelMd.addSubFolder(QStringLiteral("collection2")), false);
78
79 // simulate mbox
80 QFileInfo fileInfo1(mDir->path(), QStringLiteral("collection3"));
81 QFile file1(fileInfo1.absoluteFilePath());
82 file1.open(QIODevice::WriteOnly);
83 file1.close();
84 QVERIFY(fileInfo1.exists());
85
86 // simulate mbox with empty subtree
87 QFileInfo fileInfo2(mDir->path(), QStringLiteral("collection4"));
88 QFile file2(fileInfo2.absoluteFilePath());
89 file2.open(QIODevice::WriteOnly);
90 file2.close();
91 QVERIFY(fileInfo2.exists());
92
93 QFileInfo subDirInfo2(KPIM::Maildir::subDirPathForFolderPath(fileInfo2.absoluteFilePath()));
94 QDir topDir(mDir->path());
95 QVERIFY(topDir.mkpath(subDirInfo2.absoluteFilePath()));
96
97 mStore->setPath(mDir->path());
98
99 FileStore::CollectionDeleteJob *job = nullptr;
100
101 // test fail of deleting first level collection
102 Collection collection5;
103 collection5.setName(QStringLiteral("collection5"));
104 collection5.setRemoteId(QStringLiteral("collection5"));
105 collection5.setParentCollection(mStore->topLevelCollection());
106 job = mStore->deleteCollection(collection5);
107 QVERIFY(job != nullptr);
108
109 QVERIFY(!job->exec());
110 QCOMPARE(job->error(), (int)FileStore::Job::InvalidJobContext);
111
112 QCOMPARE(topLevelMd.subFolderList(), QStringList() << QStringLiteral("collection1") << QStringLiteral("collection2"));
113 QVERIFY(fileInfo1.exists());
114
115 // test fail of deleting second level collection in maildir leaf parent
116 Collection collection2;
117 collection2.setName(QStringLiteral("collection2"));
118 collection2.setRemoteId(QStringLiteral("collection2"));
119 collection2.setParentCollection(mStore->topLevelCollection());
120
121 Collection collection2_1;
122 collection2_1.setName(QStringLiteral("collection2_1"));
123 collection2_1.setRemoteId(QStringLiteral("collection2_1"));
124 collection2_1.setParentCollection(collection2);
125 job = mStore->deleteCollection(collection2_1);
126 QVERIFY(job != nullptr);
127
128 QVERIFY(!job->exec());
129 QCOMPARE(job->error(), (int)FileStore::Job::InvalidJobContext);
130
131 QCOMPARE(topLevelMd.subFolderList(), QStringList() << QStringLiteral("collection1") << QStringLiteral("collection2"));
132
133 // test fail of deleting second level collection in maildir parent with subtree
134 Collection collection1;
135 collection1.setName(QStringLiteral("collection1"));
136 collection1.setRemoteId(QStringLiteral("collection1"));
137 collection1.setParentCollection(mStore->topLevelCollection());
138
139 Collection collection1_1;
140 collection1_1.setName(QStringLiteral("collection1_1"));
141 collection1_1.setRemoteId(QStringLiteral("collection1_1"));
142 collection1_1.setParentCollection(collection1);
143 job = mStore->deleteCollection(collection1_1);
144 QVERIFY(job != nullptr);
145
146 QVERIFY(!job->exec());
147 QCOMPARE(job->error(), (int)FileStore::Job::InvalidJobContext);
148
149 QCOMPARE(topLevelMd.subFolderList(), QStringList() << QStringLiteral("collection1") << QStringLiteral("collection2"));
150 QCOMPARE(md1.subFolderList(), QStringList() << QStringLiteral("collection1_2"));
151
152 // test fail of deleting second level collection in mbox leaf parent
153 Collection collection3;
154 collection3.setName(QStringLiteral("collection3"));
155 collection3.setRemoteId(QStringLiteral("collection3"));
156 collection3.setParentCollection(mStore->topLevelCollection());
157
158 Collection collection3_1;
159 collection3_1.setName(QStringLiteral("collection3_1"));
160 collection3_1.setRemoteId(QStringLiteral("collection3_1"));
161 collection3_1.setParentCollection(collection3);
162 job = mStore->deleteCollection(collection3_1);
163 QVERIFY(job != nullptr);
164
165 QVERIFY(!job->exec());
166 QCOMPARE(job->error(), (int)FileStore::Job::InvalidJobContext);
167
168 QVERIFY(fileInfo1.exists());
169
170 // test fail of deleting second level collection in mbox parent with subtree
171 Collection collection4;
172 collection4.setName(QStringLiteral("collection4"));
173 collection4.setRemoteId(QStringLiteral("collection4"));
174 collection4.setParentCollection(mStore->topLevelCollection());
175
176 Collection collection4_1;
177 collection4_1.setName(QStringLiteral("collection4_1"));
178 collection4_1.setRemoteId(QStringLiteral("collection4_1"));
179 collection4_1.setParentCollection(collection4);
180 job = mStore->deleteCollection(collection4_1);
181 QVERIFY(job != nullptr);
182
183 QVERIFY(!job->exec());
184 QCOMPARE(job->error(), (int)FileStore::Job::InvalidJobContext);
185
186 QVERIFY(fileInfo2.exists());
187 QVERIFY(subDirInfo2.exists());
188
189 // test fail of deleting second level collection with non existent parent
190 Collection collection5_1;
191 collection5_1.setName(QStringLiteral("collection5_1"));
192 collection5_1.setRemoteId(QStringLiteral("collection5_1"));
193 collection5_1.setParentCollection(collection5);
194 job = mStore->deleteCollection(collection5_1);
195 QVERIFY(job != nullptr);
196
197 QVERIFY(!job->exec());
198 QCOMPARE(job->error(), (int)FileStore::Job::InvalidJobContext);
199
200 QCOMPARE(topLevelMd.subFolderList(), QStringList() << QStringLiteral("collection1") << QStringLiteral("collection2"));
201 QVERIFY(fileInfo1.exists());
202 QCOMPARE(md1.subFolderList(), QStringList() << QStringLiteral("collection1_2"));
203 }
204
testLeaves()205 void CollectionDeleteTest::testLeaves()
206 {
207 KPIM::Maildir topLevelMd(mDir->path(), true);
208 QVERIFY(topLevelMd.isValid(false));
209
210 QDir topDir(mDir->path());
211
212 KPIM::Maildir md1(topLevelMd.addSubFolder(QStringLiteral("collection1")), false);
213 KPIM::Maildir md1_2(md1.addSubFolder(QStringLiteral("collection1_2")), false);
214
215 // simulate second level mbox in maildir parent
216 QFileInfo fileInfo1_1(KPIM::Maildir::subDirPathForFolderPath(md1.path()), QStringLiteral("collection1_1"));
217 QFile file1_1(fileInfo1_1.absoluteFilePath());
218 file1_1.open(QIODevice::WriteOnly);
219 file1_1.close();
220 QVERIFY(fileInfo1_1.exists());
221
222 KPIM::Maildir md2(topLevelMd.addSubFolder(QStringLiteral("collection2")), false);
223
224 // simulate first level mbox
225 QFileInfo fileInfo3(mDir->path(), QStringLiteral("collection3"));
226 QFile file3(fileInfo3.absoluteFilePath());
227 file3.open(QIODevice::WriteOnly);
228 file3.close();
229 QVERIFY(fileInfo3.exists());
230
231 // simulate first level mbox with subtree
232 QFileInfo fileInfo4(mDir->path(), QStringLiteral("collection4"));
233 QFile file4(fileInfo4.absoluteFilePath());
234 file4.open(QIODevice::WriteOnly);
235 file4.close();
236 QVERIFY(fileInfo4.exists());
237
238 QFileInfo subDirInfo4(KPIM::Maildir::subDirPathForFolderPath(fileInfo4.absoluteFilePath()));
239 QVERIFY(topDir.mkpath(subDirInfo4.absoluteFilePath()));
240
241 KPIM::Maildir md4(subDirInfo4.absoluteFilePath(), true);
242 KPIM::Maildir md4_1(md4.addSubFolder(QStringLiteral("collection4_1")), false);
243
244 // simulate second level mbox in mbox parent
245 QFileInfo fileInfo4_2(subDirInfo4.absoluteFilePath(), QStringLiteral("collection4_2"));
246 QFile file4_2(fileInfo4_2.absoluteFilePath());
247 file4_2.open(QIODevice::WriteOnly);
248 file4_2.close();
249 QVERIFY(fileInfo4_2.exists());
250
251 mStore->setPath(mDir->path());
252
253 FileStore::CollectionDeleteJob *job = nullptr;
254
255 // test second level leaves in maildir parent
256 Collection collection1;
257 collection1.setName(QStringLiteral("collection1"));
258 collection1.setRemoteId(QStringLiteral("collection1"));
259 collection1.setParentCollection(mStore->topLevelCollection());
260
261 Collection collection1_1;
262 collection1_1.setName(QStringLiteral("collection1_1"));
263 collection1_1.setRemoteId(QStringLiteral("collection1_1"));
264 collection1_1.setParentCollection(collection1);
265 job = mStore->deleteCollection(collection1_1);
266 QVERIFY(job != nullptr);
267
268 QVERIFY(job->exec());
269 QCOMPARE(job->error(), 0);
270
271 fileInfo1_1.refresh();
272 QVERIFY(!fileInfo1_1.exists());
273
274 Collection collection1_2;
275 collection1_2.setName(QStringLiteral("collection1_2"));
276 collection1_2.setRemoteId(QStringLiteral("collection1_2"));
277 collection1_2.setParentCollection(collection1);
278 job = mStore->deleteCollection(collection1_2);
279 QVERIFY(job != nullptr);
280
281 QVERIFY(job->exec());
282 QCOMPARE(job->error(), 0);
283
284 QVERIFY(!md1_2.isValid(false));
285 QCOMPARE(md1.subFolderList(), QStringList());
286
287 // test second level leaves in mbox parent
288 Collection collection4;
289 collection4.setName(QStringLiteral("collection4"));
290 collection4.setRemoteId(QStringLiteral("collection4"));
291 collection4.setParentCollection(mStore->topLevelCollection());
292
293 Collection collection4_1;
294 collection4_1.setName(QStringLiteral("collection4_1"));
295 collection4_1.setRemoteId(QStringLiteral("collection4_1"));
296 collection4_1.setParentCollection(collection4);
297 job = mStore->deleteCollection(collection4_1);
298 QVERIFY(job != nullptr);
299
300 QVERIFY(job->exec());
301 QCOMPARE(job->error(), 0);
302
303 QVERIFY(!md4_1.isValid(false));
304 QCOMPARE(md4.subFolderList(), QStringList());
305
306 Collection collection4_2;
307 collection4_2.setName(QStringLiteral("collection4_2"));
308 collection4_2.setRemoteId(QStringLiteral("collection4_2"));
309 collection4_2.setParentCollection(collection4);
310 job = mStore->deleteCollection(collection4_2);
311 QVERIFY(job != nullptr);
312
313 QVERIFY(job->exec());
314 QCOMPARE(job->error(), 0);
315
316 fileInfo4_2.refresh();
317 QVERIFY(!fileInfo4_2.exists());
318
319 // test deleting of first level leaves
320 Collection collection2;
321 collection2.setName(QStringLiteral("collection2"));
322 collection2.setRemoteId(QStringLiteral("collection2"));
323 collection2.setParentCollection(mStore->topLevelCollection());
324
325 job = mStore->deleteCollection(collection2);
326 QVERIFY(job != nullptr);
327
328 QVERIFY(job->exec());
329 QCOMPARE(job->error(), 0);
330
331 QVERIFY(!md2.isValid(false));
332 QCOMPARE(topLevelMd.subFolderList(), QStringList() << QStringLiteral("collection1"));
333
334 Collection collection3;
335 collection3.setName(QStringLiteral("collection3"));
336 collection3.setRemoteId(QStringLiteral("collection3"));
337 collection3.setParentCollection(mStore->topLevelCollection());
338
339 job = mStore->deleteCollection(collection3);
340 QVERIFY(job != nullptr);
341
342 QVERIFY(job->exec());
343 QCOMPARE(job->error(), 0);
344
345 fileInfo3.refresh();
346 QVERIFY(!fileInfo3.exists());
347
348 // test deleting of first level leaves with empty subtrees
349 QFileInfo subDirInfo1(KPIM::Maildir::subDirPathForFolderPath(md1.path()));
350 QVERIFY(subDirInfo1.exists());
351
352 job = mStore->deleteCollection(collection1);
353 QVERIFY(job != nullptr);
354
355 QVERIFY(job->exec());
356 QCOMPARE(job->error(), 0);
357
358 QVERIFY(!md1.isValid(false));
359 subDirInfo1.refresh();
360 QVERIFY(!subDirInfo1.exists());
361 QCOMPARE(topLevelMd.subFolderList(), QStringList());
362
363 job = mStore->deleteCollection(collection4);
364 QVERIFY(job != nullptr);
365
366 QVERIFY(job->exec());
367 QCOMPARE(job->error(), 0);
368
369 fileInfo4.refresh();
370 QVERIFY(!fileInfo4.exists());
371 subDirInfo4.refresh();
372 QVERIFY(!subDirInfo4.exists());
373 }
374
testSubTrees()375 void CollectionDeleteTest::testSubTrees()
376 {
377 KPIM::Maildir topLevelMd(mDir->path(), true);
378 QVERIFY(topLevelMd.isValid(false));
379
380 QDir topDir(mDir->path());
381
382 KPIM::Maildir md1(topLevelMd.addSubFolder(QStringLiteral("collection1")), false);
383 KPIM::Maildir md1_2(md1.addSubFolder(QStringLiteral("collection1_2")), false);
384
385 // simulate second level mbox in maildir parent
386 QFileInfo fileInfo1_1(KPIM::Maildir::subDirPathForFolderPath(md1.path()), QStringLiteral("collection1_1"));
387 QFile file1_1(fileInfo1_1.absoluteFilePath());
388 file1_1.open(QIODevice::WriteOnly);
389 file1_1.close();
390 QVERIFY(fileInfo1_1.exists());
391
392 // simulate first level mbox with subtree
393 QFileInfo fileInfo2(mDir->path(), QStringLiteral("collection2"));
394 QFile file2(fileInfo2.absoluteFilePath());
395 file2.open(QIODevice::WriteOnly);
396 file2.close();
397 QVERIFY(fileInfo2.exists());
398
399 QFileInfo subDirInfo2(KPIM::Maildir::subDirPathForFolderPath(fileInfo2.absoluteFilePath()));
400 QVERIFY(topDir.mkpath(subDirInfo2.absoluteFilePath()));
401
402 KPIM::Maildir md2(subDirInfo2.absoluteFilePath(), true);
403 KPIM::Maildir md2_1(md2.addSubFolder(QStringLiteral("collection2_1")), false);
404
405 // simulate second level mbox in mbox parent
406 QFileInfo fileInfo2_2(subDirInfo2.absoluteFilePath(), QStringLiteral("collection2_2"));
407 QFile file2_2(fileInfo2_2.absoluteFilePath());
408 file2_2.open(QIODevice::WriteOnly);
409 file2_2.close();
410 QVERIFY(fileInfo2_2.exists());
411
412 mStore->setPath(mDir->path());
413
414 FileStore::CollectionDeleteJob *job = nullptr;
415
416 // test deleting maildir subtree
417 QFileInfo subDirInfo1(KPIM::Maildir::subDirPathForFolderPath(md1.path()));
418 QVERIFY(subDirInfo1.exists());
419
420 Collection collection1;
421 collection1.setName(QStringLiteral("collection1"));
422 collection1.setRemoteId(QStringLiteral("collection1"));
423 collection1.setParentCollection(mStore->topLevelCollection());
424
425 job = mStore->deleteCollection(collection1);
426
427 QVERIFY(job->exec());
428 QCOMPARE(job->error(), 0);
429
430 QVERIFY(!md1.isValid(false));
431 QVERIFY(!md1_2.isValid(false));
432 fileInfo1_1.refresh();
433 QVERIFY(!fileInfo1_1.exists());
434
435 // test deleting mbox subtree
436 Collection collection2;
437 collection2.setName(QStringLiteral("collection2"));
438 collection2.setRemoteId(QStringLiteral("collection2"));
439 collection2.setParentCollection(mStore->topLevelCollection());
440
441 job = mStore->deleteCollection(collection2);
442
443 QVERIFY(job->exec());
444 QCOMPARE(job->error(), 0);
445
446 fileInfo2.refresh();
447 QVERIFY(!fileInfo2.exists());
448 QVERIFY(!md2_1.isValid(false));
449 fileInfo2_2.refresh();
450 QVERIFY(!fileInfo2_2.exists());
451 QVERIFY(!subDirInfo2.exists());
452 }
453
454 QTEST_MAIN(CollectionDeleteTest)
455
456 #include "collectiondeletetest.moc"
457