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