1 #include "catch.hpp" 2 3 #include <QString> 4 #include <cmath> 5 #include <iostream> 6 #include <tuple> 7 #include <unordered_set> 8 9 #define private public 10 #define protected public 11 #include "abstractmodel/abstracttreemodel.hpp" 12 #include "abstractmodel/treeitem.hpp" 13 14 TEST_CASE("Basic tree testing", "[TreeModel]") 15 { 16 auto model = AbstractTreeModel::construct(); 17 18 REQUIRE(model->checkConsistency()); 19 REQUIRE(model->rowCount() == 0); 20 21 SECTION("Item creation Test") 22 { 23 auto item = TreeItem::construct(QList<QVariant>{QString("test")}, model, false); 24 int id = item->getId(); 25 REQUIRE(item->depth() == 0); 26 REQUIRE(model->checkConsistency()); 27 28 // check that a valid Id has been assigned 29 REQUIRE(id != -1); 30 31 // check that the item is not yet registered (not valid parent) 32 REQUIRE(model->m_allItems.size() == 1); 33 34 // Assign this to a parent 35 model->getRoot()->appendChild(item); 36 REQUIRE(model->checkConsistency()); 37 // Now the item should be registered, we query it 38 REQUIRE(model->m_allItems.size() == 2); 39 REQUIRE(model->getItemById(id) == item); 40 REQUIRE(item->depth() == 1); 41 REQUIRE(model->rowCount() == 1); 42 REQUIRE(model->rowCount(model->getIndexFromItem(item)) == 0); 43 44 // Retrieve data member 45 REQUIRE(model->data(model->getIndexFromItem(item), 0) == QStringLiteral("test")); 46 47 // Try joint creation / assignation 48 auto item2 = item->appendChild(QList<QVariant>{QString("test2")}); __anona3b2930b0102() 49 auto state = [&]() { 50 REQUIRE(model->checkConsistency()); 51 REQUIRE(item->depth() == 1); 52 REQUIRE(item2->depth() == 2); 53 REQUIRE(model->rowCount() == 1); 54 REQUIRE(item->row() == 0); 55 REQUIRE(item2->row() == 0); 56 REQUIRE(model->data(model->getIndexFromItem(item2), 0) == QStringLiteral("test2")); 57 REQUIRE(model->rowCount(model->getIndexFromItem(item2)) == 0); 58 }; 59 state(); 60 REQUIRE(model->rowCount(model->getIndexFromItem(item)) == 1); 61 REQUIRE(model->m_allItems.size() == 3); 62 63 // Add a second child to item to check if everything collapses 64 auto item3 = item->appendChild(QList<QVariant>{QString("test3")}); 65 state(); 66 REQUIRE(model->rowCount(model->getIndexFromItem(item3)) == 0); 67 REQUIRE(model->rowCount(model->getIndexFromItem(item)) == 2); 68 REQUIRE(model->m_allItems.size() == 4); 69 REQUIRE(item3->depth() == 2); 70 REQUIRE(item3->row() == 1); 71 REQUIRE(model->data(model->getIndexFromItem(item3), 0) == QStringLiteral("test3")); 72 } 73 74 SECTION("Invalid moves") 75 { 76 auto item = model->getRoot()->appendChild(QList<QVariant>{QString("test")}); __anona3b2930b0202() 77 auto state = [&]() { 78 REQUIRE(model->checkConsistency()); 79 REQUIRE(model->rowCount() == 1); 80 REQUIRE(item->depth() == 1); 81 REQUIRE(item->row() == 0); 82 REQUIRE(model->data(model->getIndexFromItem(item), 0) == QStringLiteral("test")); 83 }; 84 state(); 85 REQUIRE(model->rowCount(model->getIndexFromItem(item)) == 0); 86 87 // Try to move the root 88 REQUIRE_FALSE(item->appendChild(model->getRoot())); 89 state(); 90 REQUIRE(model->rowCount(model->getIndexFromItem(item)) == 0); 91 92 auto item2 = item->appendChild(QList<QVariant>{QString("test2")}); 93 auto item3 = item2->appendChild(QList<QVariant>{QString("test3")}); 94 auto item4 = item3->appendChild(QList<QVariant>{QString("test4")}); __anona3b2930b0302() 95 auto state2 = [&]() { 96 state(); 97 REQUIRE(item2->depth() == 2); 98 REQUIRE(item2->row() == 0); 99 REQUIRE(model->data(model->getIndexFromItem(item2), 0) == QStringLiteral("test2")); 100 REQUIRE(item3->depth() == 3); 101 REQUIRE(item3->row() == 0); 102 REQUIRE(model->data(model->getIndexFromItem(item3), 0) == QStringLiteral("test3")); 103 REQUIRE(item4->depth() == 4); 104 REQUIRE(item4->row() == 0); 105 REQUIRE(model->data(model->getIndexFromItem(item4), 0) == QStringLiteral("test4")); 106 }; 107 state2(); 108 109 // Try to make a loop 110 REQUIRE_FALSE(item->changeParent(item3)); 111 state2(); 112 REQUIRE_FALSE(item->changeParent(item4)); 113 state2(); 114 115 // Try to append a child that already have a parent 116 REQUIRE_FALSE(item->appendChild(item4)); 117 state2(); 118 119 // valid move 120 REQUIRE(item4->changeParent(item2)); 121 REQUIRE(model->checkConsistency()); 122 } 123 124 SECTION("Deregistration tests") 125 { 126 // we construct a non trivial structure 127 auto item = model->getRoot()->appendChild(QList<QVariant>{QString("test")}); 128 auto item2 = item->appendChild(QList<QVariant>{QString("test2")}); 129 auto item3 = item2->appendChild(QList<QVariant>{QString("test3")}); 130 auto item4 = item3->appendChild(QList<QVariant>{QString("test4")}); 131 auto item5 = item2->appendChild(QList<QVariant>{QString("test5")}); __anona3b2930b0402() 132 auto state = [&]() { 133 REQUIRE(model->checkConsistency()); 134 REQUIRE(model->rowCount() == 1); 135 REQUIRE(item->depth() == 1); 136 REQUIRE(item->row() == 0); 137 REQUIRE(model->data(model->getIndexFromItem(item), 0) == QStringLiteral("test")); 138 REQUIRE(model->rowCount(model->getIndexFromItem(item)) == 1); 139 REQUIRE(item2->depth() == 2); 140 REQUIRE(item2->row() == 0); 141 REQUIRE(model->data(model->getIndexFromItem(item2), 0) == QStringLiteral("test2")); 142 REQUIRE(model->rowCount(model->getIndexFromItem(item2)) == 2); 143 REQUIRE(item3->depth() == 3); 144 REQUIRE(item3->row() == 0); 145 REQUIRE(model->data(model->getIndexFromItem(item3), 0) == QStringLiteral("test3")); 146 REQUIRE(model->rowCount(model->getIndexFromItem(item3)) == 1); 147 REQUIRE(item4->depth() == 4); 148 REQUIRE(item4->row() == 0); 149 REQUIRE(model->data(model->getIndexFromItem(item4), 0) == QStringLiteral("test4")); 150 REQUIRE(model->rowCount(model->getIndexFromItem(item4)) == 0); 151 REQUIRE(item5->depth() == 3); 152 REQUIRE(item5->row() == 1); 153 REQUIRE(model->data(model->getIndexFromItem(item5), 0) == QStringLiteral("test5")); 154 REQUIRE(model->rowCount(model->getIndexFromItem(item5)) == 0); 155 REQUIRE(model->m_allItems.size() == 6); 156 REQUIRE(item->isInModel()); 157 REQUIRE(item2->isInModel()); 158 REQUIRE(item3->isInModel()); 159 REQUIRE(item4->isInModel()); 160 REQUIRE(item5->isInModel()); 161 }; 162 state(); 163 164 // deregister the topmost item, should also deregister its children 165 item->changeParent(std::shared_ptr<TreeItem>()); 166 REQUIRE(model->m_allItems.size() == 1); 167 REQUIRE(model->rowCount() == 0); 168 REQUIRE(!item->isInModel()); 169 REQUIRE(!item2->isInModel()); 170 REQUIRE(!item3->isInModel()); 171 REQUIRE(!item4->isInModel()); 172 REQUIRE(!item5->isInModel()); 173 174 // reinsert 175 REQUIRE(model->getRoot()->appendChild(item)); 176 state(); 177 178 item2->removeChild(item5); 179 REQUIRE(!item5->isInModel()); 180 REQUIRE(model->rowCount(model->getIndexFromItem(item2)) == 1); 181 REQUIRE(model->m_allItems.size() == 5); 182 183 // reinsert 184 REQUIRE(item5->changeParent(item2)); 185 state(); 186 } 187 } 188