keepassxc

Форк
0
/
TestGroup.cpp 
1321 строка · 44.9 Кб
1
/*
2
 *  Copyright (C) 2023 KeePassXC Team <team@keepassxc.org>
3
 *  Copyright (C) 2010 Felix Geyer <debfx@fobos.de>
4
 *
5
 *  This program is free software: you can redistribute it and/or modify
6
 *  it under the terms of the GNU General Public License as published by
7
 *  the Free Software Foundation, either version 2 or (at your option)
8
 *  version 3 of the License.
9
 *
10
 *  This program is distributed in the hope that it will be useful,
11
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 *  GNU General Public License for more details.
14
 *
15
 *  You should have received a copy of the GNU General Public License
16
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
17
 */
18

19
#include "TestGroup.h"
20
#include "mock/MockClock.h"
21

22
#include <QSet>
23
#include <QSignalSpy>
24
#include <QtTestGui>
25

26
#include "core/Group.h"
27
#include "core/Metadata.h"
28
#include "crypto/Crypto.h"
29

30
QTEST_GUILESS_MAIN(TestGroup)
31

32
namespace
33
{
34
    MockClock* m_clock = nullptr;
35
}
36

37
void TestGroup::initTestCase()
38
{
39
    qRegisterMetaType<Entry*>("Entry*");
40
    qRegisterMetaType<Group*>("Group*");
41
    QVERIFY(Crypto::init());
42
}
43

44
void TestGroup::init()
45
{
46
    Q_ASSERT(m_clock == nullptr);
47
    m_clock = new MockClock(2010, 5, 5, 10, 30, 10);
48
    MockClock::setup(m_clock);
49
}
50

51
void TestGroup::cleanup()
52
{
53
    MockClock::teardown();
54
    m_clock = nullptr;
55
}
56

57
void TestGroup::testParenting()
58
{
59
    auto db = new Database();
60
    QPointer<Group> rootGroup = db->rootGroup();
61
    auto tmpRoot = new Group();
62

63
    QPointer<Group> g1 = new Group();
64
    QPointer<Group> g2 = new Group();
65
    QPointer<Group> g3 = new Group();
66
    QPointer<Group> g4 = new Group();
67

68
    g1->setParent(tmpRoot);
69
    g2->setParent(tmpRoot);
70
    g3->setParent(tmpRoot);
71
    g4->setParent(tmpRoot);
72

73
    g2->setParent(g1);
74
    g4->setParent(g3);
75
    g3->setParent(g1);
76
    g1->setParent(db->rootGroup());
77

78
    QVERIFY(g1->parent() == rootGroup);
79
    QVERIFY(g2->parent() == g1);
80
    QVERIFY(g3->parent() == g1);
81
    QVERIFY(g4->parent() == g3);
82

83
    QVERIFY(g1->database() == db);
84
    QVERIFY(g2->database() == db);
85
    QVERIFY(g3->database() == db);
86
    QVERIFY(g4->database() == db);
87

88
    QCOMPARE(tmpRoot->children().size(), 0);
89
    QCOMPARE(rootGroup->children().size(), 1);
90
    QCOMPARE(g1->children().size(), 2);
91
    QCOMPARE(g2->children().size(), 0);
92
    QCOMPARE(g3->children().size(), 1);
93
    QCOMPARE(g4->children().size(), 0);
94

95
    QVERIFY(rootGroup->children().at(0) == g1);
96
    QVERIFY(rootGroup->children().at(0) == g1);
97
    QVERIFY(g1->children().at(0) == g2);
98
    QVERIFY(g1->children().at(1) == g3);
99
    QVERIFY(g3->children().contains(g4));
100

101
    auto g5 = new Group();
102
    auto g6 = new Group();
103
    g5->setParent(db->rootGroup());
104
    g6->setParent(db->rootGroup());
105
    QVERIFY(db->rootGroup()->children().at(1) == g5);
106
    QVERIFY(db->rootGroup()->children().at(2) == g6);
107

108
    g5->setParent(db->rootGroup());
109
    QVERIFY(db->rootGroup()->children().at(1) == g6);
110
    QVERIFY(db->rootGroup()->children().at(2) == g5);
111

112
    QSignalSpy spy(db, SIGNAL(groupDataChanged(Group*)));
113
    g2->setName("test");
114
    g4->setName("test");
115
    g3->setName("test");
116
    g1->setName("test");
117
    g3->setIcon(QUuid::createUuid());
118
    g1->setIcon(2);
119
    QCOMPARE(spy.count(), 6);
120
    delete db;
121

122
    QVERIFY(rootGroup.isNull());
123
    QVERIFY(g1.isNull());
124
    QVERIFY(g2.isNull());
125
    QVERIFY(g3.isNull());
126
    QVERIFY(g4.isNull());
127
    delete tmpRoot;
128
}
129

130
void TestGroup::testSignals()
131
{
132
    auto db = new Database();
133
    auto db2 = new Database();
134
    QPointer<Group> root = db->rootGroup();
135

136
    QSignalSpy spyAboutToAdd(db, SIGNAL(groupAboutToAdd(Group*, int)));
137
    QSignalSpy spyAdded(db, SIGNAL(groupAdded()));
138
    QSignalSpy spyAboutToRemove(db, SIGNAL(groupAboutToRemove(Group*)));
139
    QSignalSpy spyRemoved(db, SIGNAL(groupRemoved()));
140
    QSignalSpy spyAboutToMove(db, SIGNAL(groupAboutToMove(Group*, Group*, int)));
141
    QSignalSpy spyMoved(db, SIGNAL(groupMoved()));
142

143
    QSignalSpy spyAboutToAdd2(db2, SIGNAL(groupAboutToAdd(Group*, int)));
144
    QSignalSpy spyAdded2(db2, SIGNAL(groupAdded()));
145
    QSignalSpy spyAboutToRemove2(db2, SIGNAL(groupAboutToRemove(Group*)));
146
    QSignalSpy spyRemoved2(db2, SIGNAL(groupRemoved()));
147
    QSignalSpy spyAboutToMove2(db2, SIGNAL(groupAboutToMove(Group*, Group*, int)));
148
    QSignalSpy spyMoved2(db2, SIGNAL(groupMoved()));
149

150
    auto g1 = new Group();
151
    auto g2 = new Group();
152

153
    g1->setParent(root);
154
    QCOMPARE(spyAboutToAdd.count(), 1);
155
    QCOMPARE(spyAdded.count(), 1);
156
    QCOMPARE(spyAboutToRemove.count(), 0);
157
    QCOMPARE(spyRemoved.count(), 0);
158
    QCOMPARE(spyAboutToMove.count(), 0);
159
    QCOMPARE(spyMoved.count(), 0);
160

161
    g2->setParent(root);
162
    QCOMPARE(spyAboutToAdd.count(), 2);
163
    QCOMPARE(spyAdded.count(), 2);
164
    QCOMPARE(spyAboutToRemove.count(), 0);
165
    QCOMPARE(spyRemoved.count(), 0);
166
    QCOMPARE(spyAboutToMove.count(), 0);
167
    QCOMPARE(spyMoved.count(), 0);
168

169
    g2->setParent(root);
170
    QCOMPARE(spyAboutToAdd.count(), 2);
171
    QCOMPARE(spyAdded.count(), 2);
172
    QCOMPARE(spyAboutToRemove.count(), 0);
173
    QCOMPARE(spyRemoved.count(), 0);
174
    QCOMPARE(spyAboutToMove.count(), 0);
175
    QCOMPARE(spyMoved.count(), 0);
176

177
    g2->setParent(root, 0);
178
    QCOMPARE(spyAboutToAdd.count(), 2);
179
    QCOMPARE(spyAdded.count(), 2);
180
    QCOMPARE(spyAboutToRemove.count(), 0);
181
    QCOMPARE(spyRemoved.count(), 0);
182
    QCOMPARE(spyAboutToMove.count(), 1);
183
    QCOMPARE(spyMoved.count(), 1);
184

185
    g1->setParent(g2);
186
    QCOMPARE(spyAboutToAdd.count(), 2);
187
    QCOMPARE(spyAdded.count(), 2);
188
    QCOMPARE(spyAboutToRemove.count(), 0);
189
    QCOMPARE(spyRemoved.count(), 0);
190
    QCOMPARE(spyAboutToMove.count(), 2);
191
    QCOMPARE(spyMoved.count(), 2);
192

193
    delete g1;
194
    QCOMPARE(spyAboutToAdd.count(), 2);
195
    QCOMPARE(spyAdded.count(), 2);
196
    QCOMPARE(spyAboutToRemove.count(), 1);
197
    QCOMPARE(spyRemoved.count(), 1);
198
    QCOMPARE(spyAboutToMove.count(), 2);
199
    QCOMPARE(spyMoved.count(), 2);
200

201
    g2->setParent(db2->rootGroup());
202
    QCOMPARE(spyAboutToAdd.count(), 2);
203
    QCOMPARE(spyAdded.count(), 2);
204
    QCOMPARE(spyAboutToRemove.count(), 2);
205
    QCOMPARE(spyRemoved.count(), 2);
206
    QCOMPARE(spyAboutToMove.count(), 2);
207
    QCOMPARE(spyMoved.count(), 2);
208
    QCOMPARE(spyAboutToAdd2.count(), 1);
209
    QCOMPARE(spyAdded2.count(), 1);
210
    QCOMPARE(spyAboutToRemove2.count(), 0);
211
    QCOMPARE(spyRemoved2.count(), 0);
212
    QCOMPARE(spyAboutToMove2.count(), 0);
213
    QCOMPARE(spyMoved2.count(), 0);
214

215
    auto g3 = new Group();
216
    auto g4 = new Group();
217

218
    g3->setParent(root);
219
    QCOMPARE(spyAboutToAdd.count(), 3);
220
    QCOMPARE(spyAdded.count(), 3);
221
    QCOMPARE(spyAboutToRemove.count(), 2);
222
    QCOMPARE(spyRemoved.count(), 2);
223
    QCOMPARE(spyAboutToMove.count(), 2);
224
    QCOMPARE(spyMoved.count(), 2);
225

226
    g4->setParent(root);
227
    QCOMPARE(spyAboutToAdd.count(), 4);
228
    QCOMPARE(spyAdded.count(), 4);
229
    QCOMPARE(spyAboutToRemove.count(), 2);
230
    QCOMPARE(spyRemoved.count(), 2);
231
    QCOMPARE(spyAboutToMove.count(), 2);
232
    QCOMPARE(spyMoved.count(), 2);
233

234
    g3->setParent(root);
235
    QCOMPARE(spyAboutToAdd.count(), 4);
236
    QCOMPARE(spyAdded.count(), 4);
237
    QCOMPARE(spyAboutToRemove.count(), 2);
238
    QCOMPARE(spyRemoved.count(), 2);
239
    QCOMPARE(spyAboutToMove.count(), 3);
240
    QCOMPARE(spyMoved.count(), 3);
241

242
    delete db;
243
    delete db2;
244

245
    QVERIFY(root.isNull());
246
}
247

248
void TestGroup::testEntries()
249
{
250
    auto group = new Group();
251

252
    QPointer<Entry> entry1 = new Entry();
253
    entry1->setGroup(group);
254

255
    QPointer<Entry> entry2 = new Entry();
256
    entry2->setGroup(group);
257

258
    QCOMPARE(group->entries().size(), 2);
259
    QVERIFY(group->entries().at(0) == entry1);
260
    QVERIFY(group->entries().at(1) == entry2);
261

262
    delete group;
263

264
    QVERIFY(entry1.isNull());
265
    QVERIFY(entry2.isNull());
266
}
267

268
void TestGroup::testDeleteSignals()
269
{
270
    QScopedPointer<Database> db(new Database());
271
    Group* groupRoot = db->rootGroup();
272
    auto groupChild = new Group();
273
    auto groupChildChild = new Group();
274
    groupRoot->setObjectName("groupRoot");
275
    groupChild->setObjectName("groupChild");
276
    groupChildChild->setObjectName("groupChildChild");
277
    groupChild->setParent(groupRoot);
278
    groupChildChild->setParent(groupChild);
279
    QSignalSpy spyAboutToRemove(db.data(), SIGNAL(groupAboutToRemove(Group*)));
280
    QSignalSpy spyRemoved(db.data(), SIGNAL(groupRemoved()));
281

282
    delete groupChild;
283
    QVERIFY(groupRoot->children().isEmpty());
284
    QCOMPARE(spyAboutToRemove.count(), 2);
285
    QCOMPARE(spyRemoved.count(), 2);
286

287
    auto group = new Group();
288
    auto entry = new Entry();
289
    entry->setGroup(group);
290
    QSignalSpy spyEntryAboutToRemove(group, SIGNAL(entryAboutToRemove(Entry*)));
291
    QSignalSpy spyEntryRemoved(group, SIGNAL(entryRemoved(Entry*)));
292

293
    delete entry;
294
    QVERIFY(group->entries().isEmpty());
295
    QCOMPARE(spyEntryAboutToRemove.count(), 1);
296
    QCOMPARE(spyEntryRemoved.count(), 1);
297
    delete group;
298

299
    QScopedPointer<Database> db2(new Database());
300
    Group* groupRoot2 = db2->rootGroup();
301
    auto group2 = new Group();
302
    group2->setParent(groupRoot2);
303
    auto entry2 = new Entry();
304
    entry2->setGroup(group2);
305
    QSignalSpy spyEntryAboutToRemove2(group2, SIGNAL(entryAboutToRemove(Entry*)));
306
    QSignalSpy spyEntryRemoved2(group2, SIGNAL(entryRemoved(Entry*)));
307

308
    delete group2;
309
    QCOMPARE(spyEntryAboutToRemove2.count(), 1);
310
    QCOMPARE(spyEntryRemoved2.count(), 1);
311
}
312

313
void TestGroup::testCopyCustomIcon()
314
{
315
    QScopedPointer<Database> dbSource(new Database());
316

317
    QUuid groupIconUuid = QUuid::createUuid();
318
    QByteArray groupIcon("group icon");
319
    QString groupIconName("group icon");
320
    dbSource->metadata()->addCustomIcon(groupIconUuid, groupIcon, groupIconName);
321

322
    QUuid entryIconUuid = QUuid::createUuid();
323
    QByteArray entryIcon("entry icon");
324
    QString entryIconName("entry icon");
325
    dbSource->metadata()->addCustomIcon(entryIconUuid, entryIcon, entryIconName);
326

327
    auto* group = new Group();
328
    group->setParent(dbSource->rootGroup());
329
    group->setIcon(groupIconUuid);
330
    QCOMPARE(group->database()->metadata()->customIcon(groupIconUuid).data, groupIcon);
331
    QCOMPARE(group->database()->metadata()->customIcon(groupIconUuid).name, groupIconName);
332

333
    auto* entry = new Entry();
334
    entry->setGroup(dbSource->rootGroup());
335
    entry->setIcon(entryIconUuid);
336
    QCOMPARE(entry->database()->metadata()->customIcon(entryIconUuid).data, entryIcon);
337
    QCOMPARE(entry->database()->metadata()->customIcon(entryIconUuid).name, entryIconName);
338

339
    QScopedPointer<Database> dbTarget(new Database());
340

341
    group->setParent(dbTarget->rootGroup());
342
    QVERIFY(dbTarget->metadata()->hasCustomIcon(groupIconUuid));
343
    QCOMPARE(dbTarget->metadata()->customIcon(groupIconUuid).data, groupIcon);
344
    QCOMPARE(dbTarget->metadata()->customIcon(groupIconUuid).name, groupIconName);
345

346
    entry->setGroup(dbTarget->rootGroup());
347
    QVERIFY(dbTarget->metadata()->hasCustomIcon(entryIconUuid));
348
    QCOMPARE(dbTarget->metadata()->customIcon(entryIconUuid).data, entryIcon);
349
    QCOMPARE(dbTarget->metadata()->customIcon(entryIconUuid).name, entryIconName);
350
}
351

352
void TestGroup::testClone()
353
{
354
    QScopedPointer<Database> db(new Database());
355

356
    QScopedPointer<Group> originalGroup(new Group());
357
    originalGroup->setParent(db->rootGroup());
358
    originalGroup->setName("Group");
359
    originalGroup->setIcon(42);
360

361
    QScopedPointer<Entry> originalGroupEntry(new Entry());
362
    originalGroupEntry->setGroup(originalGroup.data());
363
    originalGroupEntry->setTitle("GroupEntryOld");
364
    originalGroupEntry->setIcon(43);
365
    originalGroupEntry->beginUpdate();
366
    originalGroupEntry->setTitle("GroupEntry");
367
    originalGroupEntry->endUpdate();
368

369
    QScopedPointer<Group> subGroup(new Group());
370
    subGroup->setParent(originalGroup.data());
371
    subGroup->setName("SubGroup");
372

373
    QScopedPointer<Entry> subGroupEntry(new Entry());
374
    subGroupEntry->setGroup(subGroup.data());
375
    subGroupEntry->setTitle("SubGroupEntry");
376

377
    QScopedPointer<Group> clonedGroup(originalGroup->clone());
378
    QVERIFY(!clonedGroup->parentGroup());
379
    QVERIFY(!clonedGroup->database());
380
    QVERIFY(clonedGroup->uuid() != originalGroup->uuid());
381
    QCOMPARE(clonedGroup->name(), QString("Group"));
382
    QCOMPARE(clonedGroup->iconNumber(), 42);
383
    QCOMPARE(clonedGroup->children().size(), 1);
384
    QCOMPARE(clonedGroup->entries().size(), 1);
385

386
    Entry* clonedGroupEntry = clonedGroup->entries().at(0);
387
    QVERIFY(clonedGroupEntry->uuid() != originalGroupEntry->uuid());
388
    QCOMPARE(clonedGroupEntry->title(), QString("GroupEntry"));
389
    QCOMPARE(clonedGroupEntry->iconNumber(), 43);
390
    QCOMPARE(clonedGroupEntry->historyItems().size(), 0);
391

392
    Group* clonedSubGroup = clonedGroup->children().at(0);
393
    QVERIFY(clonedSubGroup->uuid() != subGroup->uuid());
394
    QCOMPARE(clonedSubGroup->name(), QString("SubGroup"));
395
    QCOMPARE(clonedSubGroup->children().size(), 0);
396
    QCOMPARE(clonedSubGroup->entries().size(), 1);
397

398
    Entry* clonedSubGroupEntry = clonedSubGroup->entries().at(0);
399
    QVERIFY(clonedSubGroupEntry->uuid() != subGroupEntry->uuid());
400
    QCOMPARE(clonedSubGroupEntry->title(), QString("SubGroupEntry"));
401

402
    QScopedPointer<Group> clonedGroupKeepUuid(originalGroup->clone(Entry::CloneNoFlags));
403
    QCOMPARE(clonedGroupKeepUuid->entries().at(0)->uuid(), originalGroupEntry->uuid());
404
    QCOMPARE(clonedGroupKeepUuid->children().at(0)->entries().at(0)->uuid(), subGroupEntry->uuid());
405

406
    QScopedPointer<Group> clonedGroupNoFlags(originalGroup->clone(Entry::CloneNoFlags, Group::CloneNoFlags));
407
    QCOMPARE(clonedGroupNoFlags->entries().size(), 0);
408
    QVERIFY(clonedGroupNoFlags->uuid() == originalGroup->uuid());
409

410
    QScopedPointer<Group> clonedGroupNewUuid(originalGroup->clone(Entry::CloneNoFlags, Group::CloneNewUuid));
411
    QCOMPARE(clonedGroupNewUuid->entries().size(), 0);
412
    QVERIFY(clonedGroupNewUuid->uuid() != originalGroup->uuid());
413

414
    // Making sure the new modification date is not the same.
415
    m_clock->advanceSecond(1);
416

417
    QScopedPointer<Group> clonedGroupResetTimeInfo(
418
        originalGroup->clone(Entry::CloneNoFlags, Group::CloneNewUuid | Group::CloneResetTimeInfo));
419
    QCOMPARE(clonedGroupResetTimeInfo->entries().size(), 0);
420
    QVERIFY(clonedGroupResetTimeInfo->uuid() != originalGroup->uuid());
421
    QVERIFY(clonedGroupResetTimeInfo->timeInfo().lastModificationTime()
422
            != originalGroup->timeInfo().lastModificationTime());
423
}
424

425
void TestGroup::testCopyCustomIcons()
426
{
427
    QScopedPointer<Database> dbSource(new Database());
428
    QScopedPointer<Database> dbTarget(new Database());
429

430
    Metadata::CustomIconData icon1 = {QByteArray("icon 1"), "icon 1", Clock::currentDateTimeUtc()};
431
    Metadata::CustomIconData icon2 = {QByteArray("icon 2"), "icon 2", Clock::currentDateTimeUtc()};
432

433
    QScopedPointer<Group> group1(new Group());
434
    group1->setParent(dbSource->rootGroup());
435
    QUuid group1Icon = QUuid::createUuid();
436
    dbSource->metadata()->addCustomIcon(group1Icon, icon1);
437
    group1->setIcon(group1Icon);
438

439
    QScopedPointer<Group> group2(new Group());
440
    group2->setParent(group1.data());
441
    QUuid group2Icon = QUuid::createUuid();
442
    dbSource->metadata()->addCustomIcon(group2Icon, icon1);
443
    group2->setIcon(group2Icon);
444

445
    QScopedPointer<Entry> entry1(new Entry());
446
    entry1->setGroup(group2.data());
447
    QUuid entry1IconOld = QUuid::createUuid();
448
    dbSource->metadata()->addCustomIcon(entry1IconOld, icon1);
449
    entry1->setIcon(entry1IconOld);
450

451
    // add history item
452
    entry1->beginUpdate();
453
    QUuid entry1IconNew = QUuid::createUuid();
454
    dbSource->metadata()->addCustomIcon(entry1IconNew, icon1);
455
    entry1->setIcon(entry1IconNew);
456
    entry1->endUpdate();
457

458
    // test that we don't overwrite icons
459
    dbTarget->metadata()->addCustomIcon(group2Icon, icon1);
460

461
    dbTarget->metadata()->copyCustomIcons(group1->customIconsRecursive(), dbSource->metadata());
462

463
    Metadata* metaTarget = dbTarget->metadata();
464

465
    QCOMPARE(metaTarget->customIconsOrder().size(), 4);
466
    QVERIFY(metaTarget->hasCustomIcon(group1Icon));
467
    QVERIFY(metaTarget->hasCustomIcon(group2Icon));
468
    QVERIFY(metaTarget->hasCustomIcon(entry1IconOld));
469
    QVERIFY(metaTarget->hasCustomIcon(entry1IconNew));
470

471
    QCOMPARE(metaTarget->customIcon(group1Icon), icon1);
472
    QCOMPARE(metaTarget->customIcon(group2Icon), icon1);
473
}
474

475
void TestGroup::testFindEntry()
476
{
477
    QScopedPointer<Database> db(new Database());
478

479
    auto entry1 = new Entry();
480
    entry1->setTitle(QString("entry1"));
481
    entry1->setGroup(db->rootGroup());
482
    entry1->setUuid(QUuid::createUuid());
483

484
    auto group1 = new Group();
485
    group1->setName("group1");
486

487
    auto entry2 = new Entry();
488

489
    entry2->setTitle(QString("entry2"));
490
    entry2->setGroup(group1);
491
    entry2->setUuid(QUuid::createUuid());
492

493
    group1->setParent(db->rootGroup());
494

495
    Entry* entry;
496

497
    entry = db->rootGroup()->findEntryByUuid(entry1->uuid());
498
    QVERIFY(entry);
499
    QCOMPARE(entry->title(), QString("entry1"));
500

501
    entry = db->rootGroup()->findEntryByPath(QString("entry1"));
502
    QVERIFY(entry);
503
    QCOMPARE(entry->title(), QString("entry1"));
504

505
    // We also can find the entry with the leading slash.
506
    entry = db->rootGroup()->findEntryByPath(QString("/entry1"));
507
    QVERIFY(entry);
508
    QCOMPARE(entry->title(), QString("entry1"));
509

510
    // But two slashes should not be accepted.
511
    entry = db->rootGroup()->findEntryByPath(QString("//entry1"));
512
    QVERIFY(!entry);
513

514
    entry = db->rootGroup()->findEntryByUuid(entry2->uuid());
515
    QVERIFY(entry);
516
    QCOMPARE(entry->title(), QString("entry2"));
517

518
    entry = db->rootGroup()->findEntryByPath(QString("group1/entry2"));
519
    QVERIFY(entry);
520
    QCOMPARE(entry->title(), QString("entry2"));
521

522
    entry = db->rootGroup()->findEntryByPath(QString("/entry2"));
523
    QVERIFY(!entry);
524

525
    // We also can find the entry with the leading slash.
526
    entry = db->rootGroup()->findEntryByPath(QString("/group1/entry2"));
527
    QVERIFY(entry);
528
    QCOMPARE(entry->title(), QString("entry2"));
529

530
    // Should also find the entry only by title.
531
    entry = db->rootGroup()->findEntryByPath(QString("entry2"));
532
    QVERIFY(entry);
533
    QCOMPARE(entry->title(), QString("entry2"));
534

535
    entry = db->rootGroup()->findEntryByPath(QString("invalid/path/to/entry2"));
536
    QVERIFY(!entry);
537

538
    entry = db->rootGroup()->findEntryByPath(QString("entry27"));
539
    QVERIFY(!entry);
540

541
    // A valid UUID that does not exist in this database.
542
    entry = db->rootGroup()->findEntryByUuid(QUuid("febfb01ebcdf9dbd90a3f1579dc75281"));
543
    QVERIFY(!entry);
544

545
    // An invalid UUID.
546
    entry = db->rootGroup()->findEntryByUuid(QUuid("febfb01ebcdf9dbd90a3f1579dc"));
547
    QVERIFY(!entry);
548

549
    // Empty strings
550
    entry = db->rootGroup()->findEntryByUuid({});
551
    QVERIFY(!entry);
552

553
    entry = db->rootGroup()->findEntryByPath({});
554
    QVERIFY(!entry);
555
}
556

557
void TestGroup::testFindGroupByPath()
558
{
559
    QScopedPointer<Database> db(new Database());
560

561
    auto group1 = new Group();
562
    group1->setName("group1");
563
    group1->setParent(db->rootGroup());
564

565
    auto group2 = new Group();
566
    group2->setName("group2");
567
    group2->setParent(group1);
568

569
    Group* group;
570

571
    group = db->rootGroup()->findGroupByPath("/");
572
    QVERIFY(group);
573
    QCOMPARE(group->uuid(), db->rootGroup()->uuid());
574

575
    // We also accept it if the leading slash is missing.
576
    group = db->rootGroup()->findGroupByPath("");
577
    QVERIFY(group);
578
    QCOMPARE(group->uuid(), db->rootGroup()->uuid());
579

580
    group = db->rootGroup()->findGroupByPath("/group1/");
581
    QVERIFY(group);
582
    QCOMPARE(group->uuid(), group1->uuid());
583

584
    // We also accept it if the leading slash is missing.
585
    group = db->rootGroup()->findGroupByPath("group1/");
586
    QVERIFY(group);
587
    QCOMPARE(group->uuid(), group1->uuid());
588

589
    // Too many slashes at the end
590
    group = db->rootGroup()->findGroupByPath("group1//");
591
    QVERIFY(!group);
592

593
    // Missing a slash at the end.
594
    group = db->rootGroup()->findGroupByPath("/group1");
595
    QVERIFY(group);
596
    QCOMPARE(group->uuid(), group1->uuid());
597

598
    // Too many slashes at the start
599
    group = db->rootGroup()->findGroupByPath("//group1");
600
    QVERIFY(!group);
601

602
    group = db->rootGroup()->findGroupByPath("/group1/group2/");
603
    QVERIFY(group);
604
    QCOMPARE(group->uuid(), group2->uuid());
605

606
    // We also accept it if the leading slash is missing.
607
    group = db->rootGroup()->findGroupByPath("group1/group2/");
608
    QVERIFY(group);
609
    QCOMPARE(group->uuid(), group2->uuid());
610

611
    group = db->rootGroup()->findGroupByPath("group1/group2");
612
    QVERIFY(group);
613
    QCOMPARE(group->uuid(), group2->uuid());
614

615
    group = db->rootGroup()->findGroupByPath("invalid");
616
    QVERIFY(!group);
617
}
618

619
void TestGroup::testPrint()
620
{
621
    QScopedPointer<Database> db(new Database());
622

623
    QString output = db->rootGroup()->print();
624
    QCOMPARE(output, QString("[empty]\n"));
625

626
    output = db->rootGroup()->print(true);
627
    QCOMPARE(output, QString("[empty]\n"));
628

629
    auto entry1 = new Entry();
630
    entry1->setTitle(QString("entry1"));
631
    entry1->setGroup(db->rootGroup());
632
    entry1->setUuid(QUuid::createUuid());
633

634
    output = db->rootGroup()->print();
635
    QCOMPARE(output, QString("entry1\n"));
636

637
    auto group1 = new Group();
638
    group1->setName("group1");
639
    group1->setParent(db->rootGroup());
640

641
    auto entry2 = new Entry();
642
    entry2->setTitle(QString("entry2"));
643
    entry2->setGroup(group1);
644
    entry2->setUuid(QUuid::createUuid());
645

646
    auto group2 = new Group();
647
    group2->setName("group2");
648
    group2->setParent(db->rootGroup());
649

650
    auto subGroup = new Group();
651
    subGroup->setName("subgroup");
652
    subGroup->setParent(group2);
653

654
    auto entry3 = new Entry();
655
    entry3->setTitle(QString("entry3"));
656
    entry3->setGroup(subGroup);
657
    entry3->setUuid(QUuid::createUuid());
658

659
    output = db->rootGroup()->print();
660
    QVERIFY(output.contains(QString("entry1\n")));
661
    QVERIFY(output.contains(QString("group1/\n")));
662
    QVERIFY(!output.contains(QString("  entry2\n")));
663
    QVERIFY(output.contains(QString("group2/\n")));
664
    QVERIFY(!output.contains(QString("  subgroup\n")));
665

666
    output = db->rootGroup()->print(true);
667
    QVERIFY(output.contains(QString("entry1\n")));
668
    QVERIFY(output.contains(QString("group1/\n")));
669
    QVERIFY(output.contains(QString("  entry2\n")));
670
    QVERIFY(output.contains(QString("group2/\n")));
671
    QVERIFY(output.contains(QString("  subgroup/\n")));
672
    QVERIFY(output.contains(QString("    entry3\n")));
673

674
    output = db->rootGroup()->print(true, true);
675
    QVERIFY(output.contains(QString("entry1\n")));
676
    QVERIFY(output.contains(QString("group1/\n")));
677
    QVERIFY(output.contains(QString("group1/entry2\n")));
678
    QVERIFY(output.contains(QString("group2/\n")));
679
    QVERIFY(output.contains(QString("group2/subgroup/\n")));
680
    QVERIFY(output.contains(QString("group2/subgroup/entry3\n")));
681

682
    output = group1->print();
683
    QVERIFY(!output.contains(QString("group1/\n")));
684
    QVERIFY(output.contains(QString("entry2\n")));
685

686
    output = group2->print(true, true);
687
    QVERIFY(!output.contains(QString("group2/\n")));
688
    QVERIFY(output.contains(QString("subgroup/\n")));
689
    QVERIFY(output.contains(QString("subgroup/entry3\n")));
690
}
691

692
void TestGroup::testAddEntryWithPath()
693
{
694
    auto db = new Database();
695

696
    auto group1 = new Group();
697
    group1->setName("group1");
698
    group1->setParent(db->rootGroup());
699

700
    auto group2 = new Group();
701
    group2->setName("group2");
702
    group2->setParent(group1);
703

704
    Entry* entry = db->rootGroup()->addEntryWithPath("entry1");
705
    QVERIFY(entry);
706
    QVERIFY(!entry->uuid().isNull());
707

708
    entry = db->rootGroup()->addEntryWithPath("entry1");
709
    QVERIFY(!entry);
710

711
    entry = db->rootGroup()->addEntryWithPath("/entry1");
712
    QVERIFY(!entry);
713

714
    entry = db->rootGroup()->addEntryWithPath("entry2");
715
    QVERIFY(entry);
716
    QVERIFY(entry->title() == "entry2");
717
    QVERIFY(!entry->uuid().isNull());
718

719
    entry = db->rootGroup()->addEntryWithPath("/entry3");
720
    QVERIFY(entry);
721
    QVERIFY(entry->title() == "entry3");
722
    QVERIFY(!entry->uuid().isNull());
723

724
    entry = db->rootGroup()->addEntryWithPath("/group1/entry4");
725
    QVERIFY(entry);
726
    QVERIFY(entry->title() == "entry4");
727
    QVERIFY(!entry->uuid().isNull());
728

729
    entry = db->rootGroup()->addEntryWithPath("/group1/group2/entry5");
730
    QVERIFY(entry);
731
    QVERIFY(entry->title() == "entry5");
732
    QVERIFY(!entry->uuid().isNull());
733

734
    entry = db->rootGroup()->addEntryWithPath("/group1/invalid_group/entry6");
735
    QVERIFY(!entry);
736

737
    delete db;
738
}
739

740
void TestGroup::testIsRecycled()
741
{
742
    Database db;
743
    db.metadata()->setRecycleBinEnabled(true);
744

745
    auto group1 = new Group();
746
    group1->setName("group1");
747
    group1->setParent(db.rootGroup());
748

749
    auto group2 = new Group();
750
    group2->setName("group2");
751
    group2->setParent(db.rootGroup());
752

753
    auto group3 = new Group();
754
    group3->setName("group3");
755
    group3->setParent(group2);
756

757
    auto group4 = new Group();
758
    group4->setName("group4");
759
    group4->setParent(db.rootGroup());
760

761
    db.recycleGroup(group2);
762

763
    QVERIFY(!group1->isRecycled());
764
    QVERIFY(group2->isRecycled());
765
    QVERIFY(group3->isRecycled());
766
    QVERIFY(!group4->isRecycled());
767

768
    db.recycleGroup(group4);
769
    QVERIFY(group4->isRecycled());
770
}
771

772
void TestGroup::testCopyDataFrom()
773
{
774
    QScopedPointer<Group> group(new Group());
775
    group->setName("TestGroup");
776

777
    QScopedPointer<Group> group2(new Group());
778
    group2->setName("TestGroup2");
779

780
    QScopedPointer<Group> group3(new Group());
781
    group3->setName("TestGroup3");
782
    group3->customData()->set("testKey", "value");
783

784
    QSignalSpy spyGroupModified(group.data(), SIGNAL(modified()));
785
    QSignalSpy spyGroupDataChanged(group.data(), SIGNAL(groupDataChanged(Group*)));
786

787
    group->copyDataFrom(group2.data());
788
    QCOMPARE(spyGroupModified.count(), 1);
789
    QCOMPARE(spyGroupDataChanged.count(), 1);
790

791
    // if no change, no signals
792
    spyGroupModified.clear();
793
    spyGroupDataChanged.clear();
794
    group->copyDataFrom(group2.data());
795
    QCOMPARE(spyGroupModified.count(), 0);
796
    QCOMPARE(spyGroupDataChanged.count(), 0);
797

798
    // custom data change triggers a separate modified signal
799
    spyGroupModified.clear();
800
    spyGroupDataChanged.clear();
801
    group->copyDataFrom(group3.data());
802
    QCOMPARE(spyGroupDataChanged.count(), 1);
803
    QCOMPARE(spyGroupModified.count(), 2);
804
}
805

806
void TestGroup::testEquals()
807
{
808
    QScopedPointer<Group> group(new Group());
809
    group->setName("TestGroup");
810

811
    QVERIFY(group->equals(group.data(), CompareItemDefault));
812
}
813

814
void TestGroup::testChildrenSort()
815
{
816
    auto createTestGroupWithUnorderedChildren = []() -> Group* {
817
        auto parent = new Group();
818

819
        auto group1 = new Group();
820
        group1->setName("B");
821
        group1->setParent(parent);
822
        auto group2 = new Group();
823
        group2->setName("e");
824
        group2->setParent(parent);
825
        auto group3 = new Group();
826
        group3->setName("Test999");
827
        group3->setParent(parent);
828
        auto group4 = new Group();
829
        group4->setName("A");
830
        group4->setParent(parent);
831
        auto group5 = new Group();
832
        group5->setName("z");
833
        group5->setParent(parent);
834
        auto group6 = new Group();
835
        group6->setName("045");
836
        group6->setParent(parent);
837
        auto group7 = new Group();
838
        group7->setName("60");
839
        group7->setParent(parent);
840
        auto group8 = new Group();
841
        group8->setName("04test");
842
        group8->setParent(parent);
843
        auto group9 = new Group();
844
        group9->setName("Test12");
845
        group9->setParent(parent);
846
        auto group10 = new Group();
847
        group10->setName("i");
848
        group10->setParent(parent);
849

850
        auto subGroup1 = new Group();
851
        subGroup1->setName("sub_xte");
852
        subGroup1->setParent(group10);
853
        auto subGroup2 = new Group();
854
        subGroup2->setName("sub_010");
855
        subGroup2->setParent(group10);
856
        auto subGroup3 = new Group();
857
        subGroup3->setName("sub_000");
858
        subGroup3->setParent(group10);
859
        auto subGroup4 = new Group();
860
        subGroup4->setName("sub_M");
861
        subGroup4->setParent(group10);
862
        auto subGroup5 = new Group();
863
        subGroup5->setName("sub_p");
864
        subGroup5->setParent(group10);
865
        auto subGroup6 = new Group();
866
        subGroup6->setName("sub_45p");
867
        subGroup6->setParent(group10);
868
        auto subGroup7 = new Group();
869
        subGroup7->setName("sub_6p");
870
        subGroup7->setParent(group10);
871
        auto subGroup8 = new Group();
872
        subGroup8->setName("sub_tt");
873
        subGroup8->setParent(group10);
874
        auto subGroup9 = new Group();
875
        subGroup9->setName("sub_t0");
876
        subGroup9->setParent(group10);
877

878
        return parent;
879
    };
880

881
    Group* parent = createTestGroupWithUnorderedChildren();
882
    Group* subParent = parent->children().last();
883
    parent->sortChildrenRecursively();
884
    QList<Group*> children = parent->children();
885
    QCOMPARE(children.size(), 10);
886
    QCOMPARE(children[0]->name(), QString("045"));
887
    QCOMPARE(children[1]->name(), QString("04test"));
888
    QCOMPARE(children[2]->name(), QString("60"));
889
    QCOMPARE(children[3]->name(), QString("A"));
890
    QCOMPARE(children[4]->name(), QString("B"));
891
    QCOMPARE(children[5]->name(), QString("e"));
892
    QCOMPARE(children[6]->name(), QString("i"));
893
    QCOMPARE(children[7]->name(), QString("Test12"));
894
    QCOMPARE(children[8]->name(), QString("Test999"));
895
    QCOMPARE(children[9]->name(), QString("z"));
896
    children = subParent->children();
897
    QCOMPARE(children.size(), 9);
898
    QCOMPARE(children[0]->name(), QString("sub_000"));
899
    QCOMPARE(children[1]->name(), QString("sub_010"));
900
    QCOMPARE(children[2]->name(), QString("sub_45p"));
901
    QCOMPARE(children[3]->name(), QString("sub_6p"));
902
    QCOMPARE(children[4]->name(), QString("sub_M"));
903
    QCOMPARE(children[5]->name(), QString("sub_p"));
904
    QCOMPARE(children[6]->name(), QString("sub_t0"));
905
    QCOMPARE(children[7]->name(), QString("sub_tt"));
906
    QCOMPARE(children[8]->name(), QString("sub_xte"));
907
    delete parent;
908

909
    parent = createTestGroupWithUnorderedChildren();
910
    subParent = parent->children().last();
911
    parent->sortChildrenRecursively(true);
912
    children = parent->children();
913
    QCOMPARE(children.size(), 10);
914
    QCOMPARE(children[0]->name(), QString("z"));
915
    QCOMPARE(children[1]->name(), QString("Test999"));
916
    QCOMPARE(children[2]->name(), QString("Test12"));
917
    QCOMPARE(children[3]->name(), QString("i"));
918
    QCOMPARE(children[4]->name(), QString("e"));
919
    QCOMPARE(children[5]->name(), QString("B"));
920
    QCOMPARE(children[6]->name(), QString("A"));
921
    QCOMPARE(children[7]->name(), QString("60"));
922
    QCOMPARE(children[8]->name(), QString("04test"));
923
    QCOMPARE(children[9]->name(), QString("045"));
924
    children = subParent->children();
925
    QCOMPARE(children.size(), 9);
926
    QCOMPARE(children[0]->name(), QString("sub_xte"));
927
    QCOMPARE(children[1]->name(), QString("sub_tt"));
928
    QCOMPARE(children[2]->name(), QString("sub_t0"));
929
    QCOMPARE(children[3]->name(), QString("sub_p"));
930
    QCOMPARE(children[4]->name(), QString("sub_M"));
931
    QCOMPARE(children[5]->name(), QString("sub_6p"));
932
    QCOMPARE(children[6]->name(), QString("sub_45p"));
933
    QCOMPARE(children[7]->name(), QString("sub_010"));
934
    QCOMPARE(children[8]->name(), QString("sub_000"));
935
    delete parent;
936

937
    parent = createTestGroupWithUnorderedChildren();
938
    subParent = parent->children().last();
939
    subParent->sortChildrenRecursively();
940
    children = parent->children();
941
    QCOMPARE(children.size(), 10);
942
    QCOMPARE(children[0]->name(), QString("B"));
943
    QCOMPARE(children[1]->name(), QString("e"));
944
    QCOMPARE(children[2]->name(), QString("Test999"));
945
    QCOMPARE(children[3]->name(), QString("A"));
946
    QCOMPARE(children[4]->name(), QString("z"));
947
    QCOMPARE(children[5]->name(), QString("045"));
948
    QCOMPARE(children[6]->name(), QString("60"));
949
    QCOMPARE(children[7]->name(), QString("04test"));
950
    QCOMPARE(children[8]->name(), QString("Test12"));
951
    QCOMPARE(children[9]->name(), QString("i"));
952
    children = subParent->children();
953
    QCOMPARE(children.size(), 9);
954
    QCOMPARE(children[0]->name(), QString("sub_000"));
955
    QCOMPARE(children[1]->name(), QString("sub_010"));
956
    QCOMPARE(children[2]->name(), QString("sub_45p"));
957
    QCOMPARE(children[3]->name(), QString("sub_6p"));
958
    QCOMPARE(children[4]->name(), QString("sub_M"));
959
    QCOMPARE(children[5]->name(), QString("sub_p"));
960
    QCOMPARE(children[6]->name(), QString("sub_t0"));
961
    QCOMPARE(children[7]->name(), QString("sub_tt"));
962
    QCOMPARE(children[8]->name(), QString("sub_xte"));
963
    delete parent;
964

965
    parent = createTestGroupWithUnorderedChildren();
966
    subParent = parent->children().last();
967
    subParent->sortChildrenRecursively(true);
968
    children = parent->children();
969
    QCOMPARE(children.size(), 10);
970
    QCOMPARE(children[0]->name(), QString("B"));
971
    QCOMPARE(children[1]->name(), QString("e"));
972
    QCOMPARE(children[2]->name(), QString("Test999"));
973
    QCOMPARE(children[3]->name(), QString("A"));
974
    QCOMPARE(children[4]->name(), QString("z"));
975
    QCOMPARE(children[5]->name(), QString("045"));
976
    QCOMPARE(children[6]->name(), QString("60"));
977
    QCOMPARE(children[7]->name(), QString("04test"));
978
    QCOMPARE(children[8]->name(), QString("Test12"));
979
    QCOMPARE(children[9]->name(), QString("i"));
980
    children = subParent->children();
981
    QCOMPARE(children.size(), 9);
982
    QCOMPARE(children[0]->name(), QString("sub_xte"));
983
    QCOMPARE(children[1]->name(), QString("sub_tt"));
984
    QCOMPARE(children[2]->name(), QString("sub_t0"));
985
    QCOMPARE(children[3]->name(), QString("sub_p"));
986
    QCOMPARE(children[4]->name(), QString("sub_M"));
987
    QCOMPARE(children[5]->name(), QString("sub_6p"));
988
    QCOMPARE(children[6]->name(), QString("sub_45p"));
989
    QCOMPARE(children[7]->name(), QString("sub_010"));
990
    QCOMPARE(children[8]->name(), QString("sub_000"));
991
    delete parent;
992
}
993

994
void TestGroup::testHierarchy()
995
{
996
    Group group1;
997
    group1.setName("group1");
998

999
    auto group2 = new Group();
1000
    group2->setName("group2");
1001
    group2->setParent(&group1);
1002

1003
    auto group3 = new Group();
1004
    group3->setName("group3");
1005
    group3->setParent(group2);
1006

1007
    QStringList hierarchy = group3->hierarchy();
1008
    QVERIFY(hierarchy.size() == 3);
1009
    QVERIFY(hierarchy.contains("group1"));
1010
    QVERIFY(hierarchy.contains("group2"));
1011
    QVERIFY(hierarchy.contains("group3"));
1012

1013
    hierarchy = group3->hierarchy(0);
1014
    QVERIFY(hierarchy.isEmpty());
1015

1016
    hierarchy = group3->hierarchy(1);
1017
    QVERIFY(hierarchy.size() == 1);
1018
    QVERIFY(hierarchy.contains("group3"));
1019

1020
    hierarchy = group3->hierarchy(2);
1021
    QVERIFY(hierarchy.size() == 2);
1022
    QVERIFY(hierarchy.contains("group2"));
1023
    QVERIFY(hierarchy.contains("group3"));
1024
}
1025

1026
void TestGroup::testApplyGroupIconRecursively()
1027
{
1028
    // Create a database with two nested groups with one entry each
1029
    Database database;
1030

1031
    auto subgroup = new Group();
1032
    subgroup->setName("Subgroup");
1033
    subgroup->setParent(database.rootGroup());
1034
    QVERIFY(subgroup);
1035

1036
    auto subsubgroup = new Group();
1037
    subsubgroup->setName("Subsubgroup");
1038
    subsubgroup->setParent(subgroup);
1039
    QVERIFY(subsubgroup);
1040

1041
    Entry* subgroupEntry = subgroup->addEntryWithPath("Subgroup entry");
1042
    QVERIFY(subgroupEntry);
1043
    subgroup->setIcon(1);
1044

1045
    Entry* subsubgroupEntry = subsubgroup->addEntryWithPath("Subsubgroup entry");
1046
    QVERIFY(subsubgroupEntry);
1047
    subsubgroup->setIcon(2);
1048

1049
    // Set an icon per number to the root group and apply recursively
1050
    // -> all groups and entries have the same icon
1051
    const int rootIconNumber = 42;
1052
    database.rootGroup()->setIcon(rootIconNumber);
1053
    QVERIFY(database.rootGroup()->iconNumber() == rootIconNumber);
1054
    database.rootGroup()->applyGroupIconToChildGroups();
1055
    database.rootGroup()->applyGroupIconToChildEntries();
1056
    QVERIFY(subgroup->iconNumber() == rootIconNumber);
1057
    QVERIFY(subgroupEntry->iconNumber() == rootIconNumber);
1058
    QVERIFY(subsubgroup->iconNumber() == rootIconNumber);
1059
    QVERIFY(subsubgroupEntry->iconNumber() == rootIconNumber);
1060

1061
    // Set an icon per number to the subsubgroup and apply recursively
1062
    // -> only the subsubgroup related groups and entries have updated icons
1063
    const int subsubgroupIconNumber = 24;
1064
    subsubgroup->setIcon(subsubgroupIconNumber);
1065
    QVERIFY(subsubgroup->iconNumber() == subsubgroupIconNumber);
1066
    subsubgroup->applyGroupIconToChildGroups();
1067
    subsubgroup->applyGroupIconToChildEntries();
1068
    QVERIFY(database.rootGroup()->iconNumber() == rootIconNumber);
1069
    QVERIFY(subgroup->iconNumber() == rootIconNumber);
1070
    QVERIFY(subgroupEntry->iconNumber() == rootIconNumber);
1071
    QVERIFY(subsubgroup->iconNumber() == subsubgroupIconNumber);
1072
    QVERIFY(subsubgroupEntry->iconNumber() == subsubgroupIconNumber);
1073

1074
    // Set an icon per UUID to the subgroup and apply recursively
1075
    // -> all groups and entries except the root group have the same icon
1076
    const QUuid subgroupIconUuid = QUuid::createUuid();
1077
    QByteArray subgroupIcon("subgroup icon");
1078

1079
    database.metadata()->addCustomIcon(subgroupIconUuid, subgroupIcon);
1080
    subgroup->setIcon(subgroupIconUuid);
1081
    subgroup->applyGroupIconToChildGroups();
1082
    subgroup->applyGroupIconToChildEntries();
1083
    QVERIFY(database.rootGroup()->iconNumber() == rootIconNumber);
1084
    QCOMPARE(subgroup->iconUuid(), subgroupIconUuid);
1085
    QCOMPARE(subgroupEntry->iconUuid(), subgroupIconUuid);
1086
    QCOMPARE(subsubgroup->iconUuid(), subgroupIconUuid);
1087
    QCOMPARE(subsubgroupEntry->iconUuid(), subgroupIconUuid);
1088
    QCOMPARE(subgroup->database()->metadata()->customIcon(subgroupIconUuid).data, subgroupIcon);
1089

1090
    // Reset all icons to root icon
1091
    database.rootGroup()->setIcon(rootIconNumber);
1092
    QVERIFY(database.rootGroup()->iconNumber() == rootIconNumber);
1093
    database.rootGroup()->applyGroupIconToChildGroups();
1094
    database.rootGroup()->applyGroupIconToChildEntries();
1095
    QVERIFY(subgroup->iconNumber() == rootIconNumber);
1096
    QVERIFY(subgroupEntry->iconNumber() == rootIconNumber);
1097
    QVERIFY(subsubgroup->iconNumber() == rootIconNumber);
1098
    QVERIFY(subsubgroupEntry->iconNumber() == rootIconNumber);
1099

1100
    // Apply only for child groups
1101
    const int iconForGroups = 10;
1102
    database.rootGroup()->setIcon(iconForGroups);
1103
    QVERIFY(database.rootGroup()->iconNumber() == iconForGroups);
1104
    database.rootGroup()->applyGroupIconToChildGroups();
1105
    QVERIFY(database.rootGroup()->iconNumber() == iconForGroups);
1106
    QVERIFY(subgroup->iconNumber() == iconForGroups);
1107
    QVERIFY(subgroupEntry->iconNumber() == rootIconNumber);
1108
    QVERIFY(subsubgroup->iconNumber() == iconForGroups);
1109
    QVERIFY(subsubgroupEntry->iconNumber() == rootIconNumber);
1110

1111
    // Apply only for child entries
1112
    const int iconForEntries = 20;
1113
    database.rootGroup()->setIcon(iconForEntries);
1114
    QVERIFY(database.rootGroup()->iconNumber() == iconForEntries);
1115
    database.rootGroup()->applyGroupIconToChildEntries();
1116
    QVERIFY(database.rootGroup()->iconNumber() == iconForEntries);
1117
    QVERIFY(subgroup->iconNumber() == iconForGroups);
1118
    QVERIFY(subgroupEntry->iconNumber() == iconForEntries);
1119
    QVERIFY(subsubgroup->iconNumber() == iconForGroups);
1120
    QVERIFY(subsubgroupEntry->iconNumber() == iconForEntries);
1121
}
1122

1123
void TestGroup::testUsernamesRecursive()
1124
{
1125
    Database database;
1126

1127
    // Create a subgroup
1128
    auto subgroup = new Group();
1129
    subgroup->setName("Subgroup");
1130
    subgroup->setParent(database.rootGroup());
1131

1132
    // Generate entries in the root group and the subgroup
1133
    Entry* rootGroupEntry = database.rootGroup()->addEntryWithPath("Root group entry");
1134
    rootGroupEntry->setUsername("Name1");
1135

1136
    Entry* subgroupEntry = subgroup->addEntryWithPath("Subgroup entry");
1137
    subgroupEntry->setUsername("Name2");
1138

1139
    Entry* subgroupEntryReusingUsername = subgroup->addEntryWithPath("Another subgroup entry");
1140
    subgroupEntryReusingUsername->setUsername("Name2");
1141

1142
    QList<QString> usernames = database.rootGroup()->usernamesRecursive();
1143
    QCOMPARE(usernames.size(), 2);
1144
    QVERIFY(usernames.contains("Name1"));
1145
    QVERIFY(usernames.contains("Name2"));
1146
    QVERIFY(usernames.indexOf("Name2") < usernames.indexOf("Name1"));
1147
}
1148

1149
void TestGroup::testMoveUpDown()
1150
{
1151
    Database database;
1152
    Group* root = database.rootGroup();
1153
    QVERIFY(root);
1154

1155
    auto entry0 = new Entry();
1156
    QVERIFY(entry0);
1157
    entry0->setGroup(root);
1158
    auto entry1 = new Entry();
1159
    QVERIFY(entry1);
1160
    entry1->setGroup(root);
1161
    auto entry2 = new Entry();
1162
    QVERIFY(entry2);
1163
    entry2->setGroup(root);
1164
    auto entry3 = new Entry();
1165
    QVERIFY(entry3);
1166
    entry3->setGroup(root);
1167
    // default order, straight
1168
    QCOMPARE(root->entries().at(0), entry0);
1169
    QCOMPARE(root->entries().at(1), entry1);
1170
    QCOMPARE(root->entries().at(2), entry2);
1171
    QCOMPARE(root->entries().at(3), entry3);
1172

1173
    root->moveEntryDown(entry0);
1174
    QCOMPARE(root->entries().at(0), entry1);
1175
    QCOMPARE(root->entries().at(1), entry0);
1176
    QCOMPARE(root->entries().at(2), entry2);
1177
    QCOMPARE(root->entries().at(3), entry3);
1178

1179
    root->moveEntryDown(entry0);
1180
    QCOMPARE(root->entries().at(0), entry1);
1181
    QCOMPARE(root->entries().at(1), entry2);
1182
    QCOMPARE(root->entries().at(2), entry0);
1183
    QCOMPARE(root->entries().at(3), entry3);
1184

1185
    root->moveEntryDown(entry0);
1186
    QCOMPARE(root->entries().at(0), entry1);
1187
    QCOMPARE(root->entries().at(1), entry2);
1188
    QCOMPARE(root->entries().at(2), entry3);
1189
    QCOMPARE(root->entries().at(3), entry0);
1190

1191
    // no effect
1192
    root->moveEntryDown(entry0);
1193
    QCOMPARE(root->entries().at(0), entry1);
1194
    QCOMPARE(root->entries().at(1), entry2);
1195
    QCOMPARE(root->entries().at(2), entry3);
1196
    QCOMPARE(root->entries().at(3), entry0);
1197

1198
    root->moveEntryUp(entry0);
1199
    QCOMPARE(root->entries().at(0), entry1);
1200
    QCOMPARE(root->entries().at(1), entry2);
1201
    QCOMPARE(root->entries().at(2), entry0);
1202
    QCOMPARE(root->entries().at(3), entry3);
1203

1204
    root->moveEntryUp(entry0);
1205
    QCOMPARE(root->entries().at(0), entry1);
1206
    QCOMPARE(root->entries().at(1), entry0);
1207
    QCOMPARE(root->entries().at(2), entry2);
1208
    QCOMPARE(root->entries().at(3), entry3);
1209

1210
    root->moveEntryUp(entry0);
1211
    QCOMPARE(root->entries().at(0), entry0);
1212
    QCOMPARE(root->entries().at(1), entry1);
1213
    QCOMPARE(root->entries().at(2), entry2);
1214
    QCOMPARE(root->entries().at(3), entry3);
1215

1216
    // no effect
1217
    root->moveEntryUp(entry0);
1218
    QCOMPARE(root->entries().at(0), entry0);
1219
    QCOMPARE(root->entries().at(1), entry1);
1220
    QCOMPARE(root->entries().at(2), entry2);
1221
    QCOMPARE(root->entries().at(3), entry3);
1222

1223
    root->moveEntryUp(entry2);
1224
    QCOMPARE(root->entries().at(0), entry0);
1225
    QCOMPARE(root->entries().at(1), entry2);
1226
    QCOMPARE(root->entries().at(2), entry1);
1227
    QCOMPARE(root->entries().at(3), entry3);
1228

1229
    root->moveEntryDown(entry0);
1230
    QCOMPARE(root->entries().at(0), entry2);
1231
    QCOMPARE(root->entries().at(1), entry0);
1232
    QCOMPARE(root->entries().at(2), entry1);
1233
    QCOMPARE(root->entries().at(3), entry3);
1234

1235
    root->moveEntryUp(entry3);
1236
    QCOMPARE(root->entries().at(0), entry2);
1237
    QCOMPARE(root->entries().at(1), entry0);
1238
    QCOMPARE(root->entries().at(2), entry3);
1239
    QCOMPARE(root->entries().at(3), entry1);
1240

1241
    root->moveEntryUp(entry3);
1242
    QCOMPARE(root->entries().at(0), entry2);
1243
    QCOMPARE(root->entries().at(1), entry3);
1244
    QCOMPARE(root->entries().at(2), entry0);
1245
    QCOMPARE(root->entries().at(3), entry1);
1246

1247
    root->moveEntryDown(entry2);
1248
    QCOMPARE(root->entries().at(0), entry3);
1249
    QCOMPARE(root->entries().at(1), entry2);
1250
    QCOMPARE(root->entries().at(2), entry0);
1251
    QCOMPARE(root->entries().at(3), entry1);
1252

1253
    root->moveEntryUp(entry1);
1254
    QCOMPARE(root->entries().at(0), entry3);
1255
    QCOMPARE(root->entries().at(1), entry2);
1256
    QCOMPARE(root->entries().at(2), entry1);
1257
    QCOMPARE(root->entries().at(3), entry0);
1258
}
1259

1260
void TestGroup::testPreviousParentGroup()
1261
{
1262
    Database db;
1263
    auto* root = db.rootGroup();
1264
    root->setUuid(QUuid::createUuid());
1265
    QVERIFY(!root->uuid().isNull());
1266
    QVERIFY(!root->previousParentGroup());
1267
    QVERIFY(root->previousParentGroupUuid().isNull());
1268

1269
    auto* group1 = new Group();
1270
    group1->setUuid(QUuid::createUuid());
1271
    group1->setParent(root);
1272
    QVERIFY(!group1->uuid().isNull());
1273
    QVERIFY(!group1->previousParentGroup());
1274
    QVERIFY(group1->previousParentGroupUuid().isNull());
1275

1276
    auto* group2 = new Group();
1277
    group2->setParent(root);
1278
    group2->setUuid(QUuid::createUuid());
1279
    QVERIFY(!group2->uuid().isNull());
1280
    QVERIFY(!group2->previousParentGroup());
1281
    QVERIFY(group2->previousParentGroupUuid().isNull());
1282

1283
    group1->setParent(group2);
1284
    QVERIFY(group1->previousParentGroupUuid() == root->uuid());
1285
    QVERIFY(group1->previousParentGroup() == root);
1286

1287
    // Previous parent shouldn't be recorded if new and old parent are the same
1288
    group1->setParent(group2);
1289
    QVERIFY(group1->previousParentGroupUuid() == root->uuid());
1290
    QVERIFY(group1->previousParentGroup() == root);
1291

1292
    group1->setParent(root);
1293
    QVERIFY(group1->previousParentGroupUuid() == group2->uuid());
1294
    QVERIFY(group1->previousParentGroup() == group2);
1295
}
1296

1297
void TestGroup::testAutoTypeState()
1298
{
1299
    Database db;
1300
    auto* root = db.rootGroup();
1301

1302
    auto* entry1 = new Entry();
1303
    entry1->setGroup(root);
1304

1305
    auto subGroup = new Group();
1306
    subGroup->setParent(root);
1307
    auto* entry2 = new Entry();
1308
    entry2->setGroup(subGroup);
1309

1310
    // Disable Auto-Type from root group
1311
    root->setAutoTypeEnabled(Group::TriState::Disable);
1312
    QVERIFY(!entry1->groupAutoTypeEnabled());
1313
    QVERIFY(!entry2->groupAutoTypeEnabled());
1314

1315
    // Enable Auto-Type for sub group
1316
    subGroup->setAutoTypeEnabled(Group::TriState::Enable);
1317
    QVERIFY(root->autoTypeEnabled() == Group::TriState::Disable);
1318
    QVERIFY(subGroup->autoTypeEnabled() == Group::TriState::Enable);
1319
    QVERIFY(!entry1->groupAutoTypeEnabled());
1320
    QVERIFY(entry2->groupAutoTypeEnabled());
1321
}
1322

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.