##// END OF EJS Templates
Adds test cases...
Alexandre Leroux -
r1041:54cb33e3c81c
parent child
Show More
@@ -1,186 +1,186
1 1 #include <DataSource/DataSourceItem.h>
2 2 #include <DataSource/DataSourceItemAction.h>
3 3 #include <DataSource/DataSourceItemMergeHelper.h>
4 4
5 5 #include <QVector>
6 6
7 7 const QString DataSourceItem::NAME_DATA_KEY = QStringLiteral("name");
8 8 const QString DataSourceItem::PLUGIN_DATA_KEY = QStringLiteral("plugin");
9 9
10 10 struct DataSourceItem::DataSourceItemPrivate {
11 11 explicit DataSourceItemPrivate(DataSourceItemType type, QVariantHash data)
12 12 : m_Parent{nullptr}, m_Children{}, m_Type{type}, m_Data{std::move(data)}, m_Actions{}
13 13 {
14 14 }
15 15
16 16 DataSourceItem *m_Parent;
17 17 std::vector<std::unique_ptr<DataSourceItem> > m_Children;
18 18 DataSourceItemType m_Type;
19 19 QVariantHash m_Data;
20 20 std::vector<std::unique_ptr<DataSourceItemAction> > m_Actions;
21 21 };
22 22
23 23 DataSourceItem::DataSourceItem(DataSourceItemType type, const QString &name)
24 24 : DataSourceItem{type, QVariantHash{{NAME_DATA_KEY, name}}}
25 25 {
26 26 }
27 27
28 28 DataSourceItem::DataSourceItem(DataSourceItemType type, QVariantHash data)
29 29 : impl{spimpl::make_unique_impl<DataSourceItemPrivate>(type, std::move(data))}
30 30 {
31 31 }
32 32
33 33 std::unique_ptr<DataSourceItem> DataSourceItem::clone() const
34 34 {
35 35 auto result = std::make_unique<DataSourceItem>(impl->m_Type, impl->m_Data);
36 36
37 37 // Clones children
38 38 for (const auto &child : impl->m_Children) {
39 39 result->appendChild(std::move(child->clone()));
40 40 }
41 41
42 42 // Clones actions
43 43 for (const auto &action : impl->m_Actions) {
44 44 result->addAction(std::move(action->clone()));
45 45 }
46 46
47 47 return result;
48 48 }
49 49
50 50 QVector<DataSourceItemAction *> DataSourceItem::actions() const noexcept
51 51 {
52 52 auto result = QVector<DataSourceItemAction *>{};
53 53
54 54 std::transform(std::cbegin(impl->m_Actions), std::cend(impl->m_Actions),
55 55 std::back_inserter(result), [](const auto &action) { return action.get(); });
56 56
57 57 return result;
58 58 }
59 59
60 60 void DataSourceItem::addAction(std::unique_ptr<DataSourceItemAction> action) noexcept
61 61 {
62 62 action->setDataSourceItem(this);
63 63 impl->m_Actions.push_back(std::move(action));
64 64 }
65 65
66 66 void DataSourceItem::appendChild(std::unique_ptr<DataSourceItem> child) noexcept
67 67 {
68 68 child->impl->m_Parent = this;
69 69 impl->m_Children.push_back(std::move(child));
70 70 }
71 71
72 72 DataSourceItem *DataSourceItem::child(int childIndex) const noexcept
73 73 {
74 74 if (childIndex < 0 || childIndex >= childCount()) {
75 75 return nullptr;
76 76 }
77 77 else {
78 78 return impl->m_Children.at(childIndex).get();
79 79 }
80 80 }
81 81
82 82 int DataSourceItem::childCount() const noexcept
83 83 {
84 84 return impl->m_Children.size();
85 85 }
86 86
87 87 QVariant DataSourceItem::data(const QString &key) const noexcept
88 88 {
89 89 return impl->m_Data.value(key);
90 90 }
91 91
92 92 QVariantHash DataSourceItem::data() const noexcept
93 93 {
94 94 return impl->m_Data;
95 95 }
96 96
97 97 void DataSourceItem::merge(const DataSourceItem &item)
98 98 {
99 99 DataSourceItemMergeHelper::merge(item, *this);
100 100 }
101 101
102 102 bool DataSourceItem::isRoot() const noexcept
103 103 {
104 104 return impl->m_Parent == nullptr;
105 105 }
106 106
107 107 QString DataSourceItem::name() const noexcept
108 108 {
109 109 return data(NAME_DATA_KEY).toString();
110 110 }
111 111
112 112 DataSourceItem *DataSourceItem::parentItem() const noexcept
113 113 {
114 114 return impl->m_Parent;
115 115 }
116 116
117 117 const DataSourceItem &DataSourceItem::rootItem() const noexcept
118 118 {
119 119 return isRoot() ? *this : parentItem()->rootItem();
120 120 }
121 121
122 122 void DataSourceItem::setData(const QString &key, const QVariant &value, bool append) noexcept
123 123 {
124 124 auto it = impl->m_Data.constFind(key);
125 125 if (append && it != impl->m_Data.constEnd()) {
126 126 // Case of an existing value to which we want to add to the new value
127 127 if (it->canConvert<QVariantList>()) {
128 128 auto variantList = it->value<QVariantList>();
129 129 variantList.append(value);
130 130
131 131 impl->m_Data.insert(key, variantList);
132 132 }
133 133 else {
134 134 impl->m_Data.insert(key, QVariantList{*it, value});
135 135 }
136 136 }
137 137 else {
138 138 // Other cases :
139 139 // - new value in map OR
140 140 // - replacement of an existing value (not appending)
141 141 impl->m_Data.insert(key, value);
142 142 }
143 143 }
144 144
145 145 DataSourceItemType DataSourceItem::type() const noexcept
146 146 {
147 147 return impl->m_Type;
148 148 }
149 149
150 150 DataSourceItem *DataSourceItem::findItem(const QVariantHash &data, bool recursive)
151 151 {
152 152 for (const auto &child : impl->m_Children) {
153 153 if (child->impl->m_Data == data) {
154 154 return child.get();
155 155 }
156 156
157 157 if (recursive) {
158 158 if (auto foundItem = child->findItem(data, true)) {
159 159 return foundItem;
160 160 }
161 161 }
162 162 }
163 163
164 164 return nullptr;
165 165 }
166 166
167 167 bool DataSourceItem::operator==(const DataSourceItem &other)
168 168 {
169 169 // Compares items' attributes
170 170 if (std::tie(impl->m_Type, impl->m_Data) == std::tie(other.impl->m_Type, other.impl->m_Data)) {
171 171 // Compares contents of items' children
172 172 return std::equal(std::cbegin(impl->m_Children), std::cend(impl->m_Children),
173 std::cbegin(other.impl->m_Children),
173 std::cbegin(other.impl->m_Children), std::cend(other.impl->m_Children),
174 174 [](const auto &itemChild, const auto &otherChild) {
175 175 return *itemChild == *otherChild;
176 176 });
177 177 }
178 178 else {
179 179 return false;
180 180 }
181 181 }
182 182
183 183 bool DataSourceItem::operator!=(const DataSourceItem &other)
184 184 {
185 185 return !(*this == other);
186 186 }
@@ -1,72 +1,207
1 1 #include <DataSource/DataSourceItem.h>
2 2
3 #include "DataSourceItemBuilder.h"
4
3 5 #include <QObject>
4 6 #include <QtTest>
5 7
6 8 #include <iostream>
7 9
8 10 namespace {
9 11
10 12 void printItem(std::ostream &out, const DataSourceItem &item, int level = 0)
11 13 {
12 14 for (auto i = 0; i < level; ++i) {
13 15 out << " ";
14 16 }
15 17
16 18 out << item.name().toStdString() << "\n";
17 19
18 20 for (auto i = 0, count = item.childCount(); i < count; ++i) {
19 21 printItem(out, *item.child(i), level + 1);
20 22 }
21 23 }
22 24
23 25 std::ostream &operator<<(std::ostream &out, const DataSourceItem &item)
24 26 {
25 27 printItem(out, item, 0);
26 28 return out;
27 29 }
28 30
29 31 } // namespace
30 32
31 33 Q_DECLARE_METATYPE(std::shared_ptr<DataSourceItem>)
32 34
33 35 class TestDataSourceItem : public QObject {
34 36 Q_OBJECT
35 37 private slots:
36 38 void testMerge_data();
37 39 void testMerge();
38 40 };
39 41
40 42 void TestDataSourceItem::testMerge_data()
41 43 {
42 44 QTest::addColumn<std::shared_ptr<DataSourceItem> >("source");
43 45 QTest::addColumn<std::shared_ptr<DataSourceItem> >("dest");
44 46 QTest::addColumn<std::shared_ptr<DataSourceItem> >("expectedResult");
45 47
46 /// @todo ALX: adds test cases
48 QTest::newRow("merge (basic case)") << DataSourceItemBuilder{}
49 .root("A2")
50 .node("- B2")
51 .product("-- P2")
52 .end() // P2
53 .end() // B2
54 .end() // A2
55 .build()
56 << DataSourceItemBuilder{}
57 .root("A1")
58 .node("- B1")
59 .product("-- P1")
60 .end() // P1
61 .end() // B1
62 .end() // A1
63 .build()
64 << DataSourceItemBuilder{}
65 .root("A1")
66 .node("- B1")
67 .product("-- P1")
68 .end() // P1
69 .end() // B1
70 .node("- B2")
71 .product("-- P2")
72 .end() // P2
73 .end() // B2
74 .end() // A1
75 .build();
76
77 QTest::newRow("merge (some of the source and destination trees are identical)")
78 << DataSourceItemBuilder{}
79 .root("A2")
80 .node("- B1")
81 .node("-- C1")
82 .product("--- P2")
83 .end() // P2
84 .end() // C1
85 .node("-- C2")
86 .end() // C2
87 .end() // B1
88 .end() // A2
89 .build()
90 << DataSourceItemBuilder{}
91 .root("A1")
92 .node("- B1")
93 .node("-- C1")
94 .product("--- P1")
95 .end() // P1
96 .end() // C1
97 .end() // B1
98 .end() // A1
99 .build()
100 << DataSourceItemBuilder{}
101 .root("A1")
102 .node("- B1")
103 .node("-- C1")
104 .product("--- P1")
105 .end() // P1
106 .product("--- P2")
107 .end() // P2
108 .end() // C1
109 .node("-- C2")
110 .end() // C2
111 .end() // B1
112 .end() // A1
113 .build();
114
115 QTest::newRow("merge (products with the same name and tree are kept)")
116 << DataSourceItemBuilder{}
117 .root("A2")
118 .node("- B1")
119 .node("-- C1")
120 .product({{"name", "--- P1"}, {"from", "source"}})
121 .end() // P1
122 .end() // C1
123 .end() // B1
124 .end() // A2
125 .build()
126 << DataSourceItemBuilder{}
127 .root("A1")
128 .node("- B1")
129 .node("-- C1")
130 .product({{"name", "--- P1"}, {"from", "dest"}})
131 .end() // P1
132 .end() // C1
133 .end() // B1
134 .end() // A1
135 .build()
136 << DataSourceItemBuilder{}
137 .root("A1")
138 .node("- B1")
139 .node("-- C1")
140 .product({{"name", "--- P1"}, {"from", "dest"}})
141 .end() // P1 (dest)
142 .product({{"name", "--- P1"}, {"from", "source"}})
143 .end() // P1 (source)
144 .end() // C1
145 .end() // B1
146 .end() // A1
147 .build();
148
149 QTest::newRow("merge (for same nodes, metadata of dest node are kept)")
150 << DataSourceItemBuilder{}
151 .root("A2")
152 .node("- B1")
153 .node({{"name", "-- C1"}, {"from", "source"}})
154 .product("--- P2")
155 .end() // P1
156 .end() // C1
157 .end() // B1
158 .end() // A2
159 .build()
160 << DataSourceItemBuilder{}
161 .root("A1")
162 .node("- B1")
163 .node({{"name", "-- C1"}, {"from", "dest"}})
164 .product("--- P1")
165 .end() // P1
166 .end() // C1
167 .end() // B1
168 .end() // A1
169 .build()
170 << DataSourceItemBuilder{}
171 .root("A1")
172 .node("- B1")
173 .node({{"name", "-- C1"}, {"from", "dest"}})
174 .product("--- P1")
175 .end() // P1
176 .product("--- P2")
177 .end() // P2
178 .end() // C1 (dest)
179 .end() // B1
180 .end() // A1
181 .build();
47 182 }
48 183
49 184 void TestDataSourceItem::testMerge()
50 185 {
51 186 QFETCH(std::shared_ptr<DataSourceItem>, source);
52 187 QFETCH(std::shared_ptr<DataSourceItem>, dest);
53 188 QFETCH(std::shared_ptr<DataSourceItem>, expectedResult);
54 189
55 190 // Uncomment to print trees
56 191 // std::cout << "source: \n" << *source << "\n";
57 192 // std::cout << "dest: \n" << *dest << "\n";
58 193
59 194 // Merges source in dest (not taking source root)
60 195 for (auto i = 0, count = source->childCount(); i < count; ++i) {
61 196 dest->merge(*source->child(i));
62 197 }
63 198
64 199 // Uncomment to print trees
65 200 // std::cout << "dest after merge: \n" << *dest << "\n";
66 201
67 202 // Checks merge result
68 203 QVERIFY(*dest == *expectedResult);
69 204 }
70 205
71 206 QTEST_MAIN(TestDataSourceItem)
72 207 #include "TestDataSourceItem.moc"
General Comments 0
You need to be logged in to leave comments. Login now