File indexing completed on 2025-01-05 04:47:39
0001 /* 0002 * SPDX-FileCopyrightText: 2021 Glen Ditchfield <GJDitchfield@acm.org> 0003 * SPDX-License-Identifier: GPL-2.0-or-later 0004 */ 0005 0006 #include <QList> 0007 #include <QTest> 0008 0009 #include "cellitem.h" 0010 0011 class PlaceItemTest : public QObject 0012 { 0013 Q_OBJECT 0014 private Q_SLOTS: 0015 void soleItemHasNoOverlaps(); 0016 void itemDoesNotOverlapItself(); 0017 void twoItemsShareTheirCell(); 0018 void variousOverlapPositions_data(); 0019 void variousOverlapPositions(); 0020 void fillLeftGap(); 0021 void fillCenterGap(); 0022 void transitiveOverlap(); 0023 }; 0024 0025 using namespace CalendarSupport; 0026 0027 // Skeletal item class, not unlike EventViews::AgendaItem. Instances represent 0028 // a range of cell indexes from startAt up to but not including endBefore. 0029 struct TestItem : public CellItem { 0030 const QString name; 0031 const int startAt, endBefore; 0032 0033 TestItem(const char *n, int s, int e) 0034 : name(QString::fromLatin1(n)) 0035 , startAt(s) 0036 , endBefore(e) 0037 { 0038 } 0039 0040 TestItem(const char *n, int s, int e, int subCell, int subCells) 0041 : name(QString::fromLatin1(n)) 0042 , startAt(s) 0043 , endBefore(e) 0044 { 0045 setSubCell(subCell); 0046 setSubCells(subCells); 0047 } 0048 0049 bool overlaps(CellItem *o) const override 0050 { 0051 auto other = static_cast<TestItem *>(o); 0052 return !(other->endBefore <= startAt || other->startAt >= endBefore); 0053 } 0054 0055 [[nodiscard]] QString label() const override 0056 { 0057 return name; 0058 } 0059 }; 0060 0061 void PlaceItemTest::soleItemHasNoOverlaps() 0062 { 0063 auto item = std::make_unique<TestItem>("i", 1, 3); 0064 const QList<CellItem *> cells; 0065 auto overlappers = CellItem::placeItem(cells, item.get()); 0066 QCOMPARE(overlappers.size(), 0); 0067 QCOMPARE(item->subCell(), 0); 0068 QCOMPARE(item->subCells(), 1); 0069 } 0070 0071 void PlaceItemTest::itemDoesNotOverlapItself() 0072 { 0073 auto item = std::make_unique<TestItem>("i", 1, 3); 0074 const QList<CellItem *> cells({item.get()}); 0075 auto overlappers = CellItem::placeItem(cells, item.get()); 0076 QCOMPARE(overlappers.size(), 0); 0077 QCOMPARE(item->subCell(), 0); 0078 QCOMPARE(item->subCells(), 1); 0079 } 0080 0081 void PlaceItemTest::twoItemsShareTheirCell() 0082 { 0083 auto oldItem = std::make_unique<TestItem>("i1", 1, 2, 0, 1); 0084 const QList<CellItem *> cells({oldItem.get()}); 0085 auto newItem = std::make_unique<TestItem>("i2", 1, 2); 0086 auto overlappers = CellItem::placeItem(cells, newItem.get()); 0087 QCOMPARE(overlappers.size(), 2); 0088 QCOMPARE(oldItem->subCells(), 2); 0089 QCOMPARE(newItem->subCells(), 2); 0090 QVERIFY(oldItem->subCell() != newItem->subCell()); 0091 QVERIFY(oldItem->subCell() < oldItem->subCells()); 0092 QVERIFY(newItem->subCell() < newItem->subCells()); 0093 } 0094 0095 void PlaceItemTest::variousOverlapPositions_data() 0096 { 0097 QTest::addColumn<int>("startAt"); 0098 QTest::addColumn<bool>("shouldOverlap"); 0099 0100 QTest::newRow("before top") << 0 << false; 0101 QTest::newRow("overlaps top") << 1 << true; 0102 QTest::newRow("at top") << 2 << true; 0103 QTest::newRow("inside") << 3 << true; 0104 QTest::newRow("at bottom") << 4 << true; 0105 QTest::newRow("overlaps bottom") << 5 << true; 0106 QTest::newRow("after bottom") << 6 << false; 0107 } 0108 0109 // Evaluate placement of a new item at various positions relative to an existing 0110 // item that covers many cells. 0111 void PlaceItemTest::variousOverlapPositions() 0112 { 0113 QFETCH(int, startAt); 0114 QFETCH(bool, shouldOverlap); 0115 0116 auto oldItem = std::make_unique<TestItem>("old", 2, 6, 0, 1); 0117 const QList<CellItem *> cells({oldItem.get()}); 0118 auto newItem = std::make_unique<TestItem>("new", startAt, startAt + 2); 0119 auto overlappers = CellItem::placeItem(cells, newItem.get()); 0120 QCOMPARE(overlappers.size(), shouldOverlap ? 2 : 0); 0121 QVERIFY(!shouldOverlap || oldItem->subCell() != newItem->subCell()); 0122 QCOMPARE(oldItem->subCells(), shouldOverlap ? 2 : 1); 0123 QCOMPARE(newItem->subCells(), shouldOverlap ? 2 : 1); 0124 } 0125 0126 // |item1| |item1| 0127 // |_____||item2| --> |_____||item2| 0128 // |_____| | new ||_____| 0129 // |_____| 0130 void PlaceItemTest::fillLeftGap() 0131 { 0132 auto item1 = std::make_unique<TestItem>("item1", 0, 2, 0, 2); 0133 auto item2 = std::make_unique<TestItem>("item2", 1, 3, 1, 2); 0134 const QList<CellItem *> cells({item1.get(), item2.get()}); 0135 auto newItem = std::make_unique<TestItem>("new", 2, 4); 0136 (void)CellItem::placeItem(cells, newItem.get()); 0137 QCOMPARE(newItem->subCell(), item1->subCell()); 0138 QCOMPARE(newItem->subCells(), 2); 0139 } 0140 0141 // |item1| |item1| 0142 // |item2||_____||item3| --> |item2||_____||item3| 0143 // |_____| |_____| |_____|| new ||_____| 0144 // |_____| 0145 void PlaceItemTest::fillCenterGap() 0146 { 0147 auto item1 = std::make_unique<TestItem>("item1", 0, 2, 1, 3); 0148 auto item2 = std::make_unique<TestItem>("item2", 1, 3, 0, 3); 0149 auto item3 = std::make_unique<TestItem>("item3", 1, 3, 2, 3); 0150 const QList<CellItem *> cells({item1.get(), item2.get(), item3.get()}); 0151 auto newItem = std::make_unique<TestItem>("new", 2, 4); 0152 (void)CellItem::placeItem(cells, newItem.get()); 0153 QCOMPARE(newItem->subCell(), item1->subCell()); 0154 QCOMPARE(newItem->subCells(), 3); 0155 } 0156 0157 // Items that do not overlap placeItem may also need adjustment. 0158 // See https://bugs.kde.org/show_bug.cgi?id=64603 0159 // |item1 | |item1| 0160 // |________||item3 | --> |_____||item3| 0161 // |item2 ||________| |item2||_____|| new | 0162 // |________| |_____| |_____| 0163 void PlaceItemTest::transitiveOverlap() 0164 { 0165 auto item1 = std::make_unique<TestItem>("item1", 0, 2, 0, 2); 0166 auto item2 = std::make_unique<TestItem>("item2", 2, 4, 0, 2); 0167 auto item3 = std::make_unique<TestItem>("item3", 1, 3, 1, 2); 0168 const QList<CellItem *> cells({item1.get(), item2.get(), item3.get()}); 0169 auto newItem = std::make_unique<TestItem>("new", 2, 4); 0170 (void)CellItem::placeItem(cells, newItem.get()); 0171 QCOMPARE(newItem->subCells(), 3); 0172 QCOMPARE(item1->subCells(), 3); 0173 QCOMPARE(item2->subCells(), 3); 0174 QCOMPARE(item3->subCells(), 3); 0175 } 0176 0177 QTEST_MAIN(PlaceItemTest) 0178 0179 #include "placeitemtest.moc"