Cutelee 6.1.0
testgenericcontainers.cpp
1/*
2 This file is part of the Cutelee template system.
3
4 Copyright (c) 2010 Stephen Kelly <steveire@gmail.com>
5
6 This library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Lesser General Public
8 License as published by the Free Software Foundation; either version
9 2.1 of the Licence, or (at your option) any later version.
10
11 This library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
15
16 You should have received a copy of the GNU Lesser General Public
17 License along with this library. If not, see <http://www.gnu.org/licenses/>.
18
19*/
20
21#define MINIMAL_CONTAINER_TESTS
22
23#include "engine.h"
24#include "cutelee_paths.h"
25#include "metatype.h"
26#include "test_macros.h"
27
28#include "coverageobject.h"
29#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
30#include <QtCore/QLinkedList>
31#endif
32#include <QtCore/QQueue>
33#include <QtCore/QStack>
34#include <QtCore/QVariant>
35#include <QtTest/QTest>
36
38{
39 Q_OBJECT
40public:
41 explicit TestGenericContainers(QObject *parent = {});
42
43private Q_SLOTS:
44 void testContainer_Builtins();
45};
46
47TestGenericContainers::TestGenericContainers(QObject *parent)
48 : CoverageObject(parent)
49{
50}
51
52template <typename T> QVector<T> getItems()
53{
54 QVector<T> items;
55 items.push_back(9);
56 items.push_back(7);
57 items.push_back(5);
58 return items;
59}
60
61template <> QVector<QString> getItems<QString>()
62{
63 QVector<QString> items;
64 Q_FOREACH (const int item, getItems<int>())
65 items.push_back(QString::number(item));
66 return items;
67}
68
69template <> QVector<QVariant> getItems<QVariant>()
70{
71 QVector<QVariant> items;
72 Q_FOREACH (const int item, getItems<int>())
73 items.push_back(item);
74 return items;
75}
76
77template <> QVector<QDateTime> getItems<QDateTime>()
78{
79 QVector<QDateTime> items;
80 items.reserve(3);
81 for (auto i = 0; i < 3; ++i) {
82 QDateTime d;
83 d.setMSecsSinceEpoch(0);
84 d = d.addDays(i);
85 items.push_back(d);
86 }
87 return items;
88}
89
90template <> QVector<QObject *> getItems<QObject *>()
91{
92 QVector<QObject *> items;
93 items.reserve(3);
94 for (auto i = 9; i > 4; i -= 2) {
95 auto obj = new QObject;
96
97 obj->setObjectName(QString::number(i));
98 items.push_back(obj);
99 }
100 return items;
101}
102
103template <typename Container> struct ContainerPopulator {
104 static void populateSequential(Container &container)
105 {
106 Q_FOREACH (const typename Container::value_type item,
107 getItems<typename Container::value_type>())
108 container.push_back(item);
109 }
110 static void populateAssociative(Container &container)
111 {
112 auto i = 0;
113 Q_FOREACH (const typename Container::mapped_type item,
114 getItems<typename Container::mapped_type>())
115 container[i++] = item;
116 }
117};
118
119template <typename T> struct ContainerPopulator<QSet<T>> {
120 static void populateSequential(QSet<T> &container)
121 {
122 Q_FOREACH (const T item, getItems<T>())
123 container.insert(item);
124 }
125};
126
127template <typename T> struct ContainerPopulator<QMap<QString, T>> {
128 static void populateAssociative(QMap<QString, T> &container)
129 {
130 auto i = 0;
131 Q_FOREACH (const T item, getItems<T>())
132 container.insert(QString::number(i++), item);
133 }
134};
135
136template <typename T> struct ContainerPopulator<QHash<QString, T>> {
137 static void populateAssociative(QHash<QString, T> &container)
138 {
139 auto i = 0;
140 Q_FOREACH (const T item, getItems<T>())
141 container.insert(QString::number(i++), item);
142 }
143};
144
145template <typename T> struct ContainerPopulator<std::map<QString, T>> {
146 static void populateAssociative(std::map<QString, T> &container)
147 {
148 auto i = 0;
149 Q_FOREACH (const T item, getItems<T>())
150 container[QString::number(i++)] = item;
151 }
152};
153
154template <typename T> QString getTemplate()
155{
156 return QStringLiteral("{{ container.size }};{{ container.count }};{% for "
157 "item in container %}{{ item }},{% endfor %}");
158}
159
160template <> QString getTemplate<QDateTime>()
161{
162 return QStringLiteral("{{ container.size }};{{ container.count }};{% for "
163 "item in container %}{{ item|date }},{% endfor %}");
164}
165
166template <> QString getTemplate<QObject *>()
167{
168 return QStringLiteral(
169 "{{ container.size }};{{ container.count }};{% for item in container "
170 "%}{{ item.objectName }},{% endfor %}");
171}
172
173template <typename T> QString getAssociativeTemplate()
174{
175 return QStringLiteral("{{ container.size }};{{ container.count }};{% for "
176 "item in container.values %}{{ item }},{% endfor %}");
177}
178
179template <> QString getAssociativeTemplate<QDateTime>()
180{
181 return QStringLiteral(
182 "{{ container.size }};{{ container.count }};{% for item in "
183 "container.values %}{{ item|date }},{% endfor %}");
184}
185
186template <> QString getAssociativeTemplate<QObject *>()
187{
188 return QStringLiteral(
189 "{{ container.size }};{{ container.count }};{% for item in "
190 "container.values %}{{ item.objectName }},{% endfor %}");
191}
192
193template <typename T> QStringList getResults()
194{
195 return {QStringLiteral("3;3;"), QStringLiteral("9,"), QStringLiteral("7,"),
196 QStringLiteral("5,")};
197}
198
199template <> QStringList getResults<QDateTime>()
200{
201 return {QStringLiteral("3;3;"), QStringLiteral("Jan. 1, 1970,"),
202 QStringLiteral("Jan. 2, 1970,"), QStringLiteral("Jan. 3, 1970,")};
203}
204
205template <typename Container, typename T = typename Container::value_type>
207 static void clean(Container &) {}
208};
209
210template <typename Container, typename T = typename Container::mapped_type>
212 static void clean(Container &) {}
213};
214
215template <typename Container>
216struct CleanupSequentialContainer<Container, QObject *> {
217 static void clean(Container &c) { qDeleteAll(c); }
218};
219
220template <typename Container>
221struct CleanupAssociativeContainer<Container, QObject *> {
222 static void clean(Container &c) { qDeleteAll(c); }
223};
224
225template <typename T>
226struct CleanupAssociativeContainer<std::map<T, QObject *>, QObject *> {
227 static void clean(std::map<T, QObject *> &c)
228 {
229 typename std::map<T, QObject *>::iterator it = c.begin();
230 const typename std::map<T, QObject *>::iterator end = c.end();
231 for (; it != end; ++it) {
232 delete it->second;
233 it->second = 0;
234 }
235 }
236};
237
238template <typename Container> void cleanupSequential(Container c)
239{
241}
242
243template <typename Container> void cleanupAssociative(Container c)
244{
246}
247
248void testContainer(const QString &stringTemplate,
249 const QVariant &containerVariant,
250 const QStringList &expectedResults, bool unordered)
251{
252 Cutelee::Engine engine;
253
254 engine.setPluginPaths({QStringLiteral(CUTELEE_PLUGIN_PATH)});
255
257 c.insert(QStringLiteral("container"), containerVariant);
258
259 auto t1 = engine.newTemplate(stringTemplate, QStringLiteral("template1"));
260
261 auto result = t1->render(&c);
262 if (!unordered)
263 QCOMPARE(result, expectedResults.join(QString()));
264 else {
265 QVERIFY(result.size() == expectedResults.join(QString()).size());
266 Q_FOREACH (const QString &expectedResult, expectedResults)
267 QVERIFY(result.contains(expectedResult));
268 }
269
270 auto t2 = engine.newTemplate(QStringLiteral("-{{ container.doesnotexist }}-"),
271 QStringLiteral("template2"));
272
273 auto result2 = t2->render(&c);
274
275 QCOMPARE(result2, QStringLiteral("--"));
276}
277
278template <typename Container>
279void doTestSequentialContainer(bool unordered = {})
280{
281 Container container;
283
284 testContainer(getTemplate<typename Container::value_type>(),
285 QVariant::fromValue(container),
286 getResults<typename Container::value_type>(), unordered);
287 cleanupSequential(container);
288}
289
290template <typename Container>
291void doTestAssociativeContainer(bool unordered = {})
292{
293 Container container;
295
296 testContainer(getAssociativeTemplate<typename Container::mapped_type>(),
297 QVariant::fromValue(container),
298 getResults<typename Container::mapped_type>(), unordered);
299 cleanupAssociative(container);
300}
301
302template <typename T> void doTestNonHashableContainers()
303{
304 doTestSequentialContainer<QVector<T>>();
305 doTestSequentialContainer<QList<T>>();
306#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
307 doTestSequentialContainer<QLinkedList<T>>();
308#endif
309 doTestSequentialContainer<QQueue<T>>();
310 doTestSequentialContainer<QStack<T>>();
311 doTestSequentialContainer<std::list<T>>();
312#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
313 doTestAssociativeContainer<QMap<qint32, T>>();
314 doTestAssociativeContainer<std::map<qint32, T>>();
315 doTestAssociativeContainer<QHash<qint32, T>>(true);
316#endif
317#ifndef MINIMAL_CONTAINER_TESTS
318 doTestAssociativeContainer<QMap<qint16, T>>();
319 doTestAssociativeContainer<QMap<qint64, T>>();
320 doTestAssociativeContainer<QMap<quint16, T>>();
321 doTestAssociativeContainer<QMap<quint32, T>>();
322 doTestAssociativeContainer<QMap<quint64, T>>();
323 doTestAssociativeContainer<QMap<QString, T>>();
324 doTestAssociativeContainer<std::map<qint16, T>>();
325 doTestAssociativeContainer<std::map<qint64, T>>();
326 doTestAssociativeContainer<std::map<quint16, T>>();
327 doTestAssociativeContainer<std::map<quint32, T>>();
328 doTestAssociativeContainer<std::map<quint64, T>>();
329 doTestAssociativeContainer<std::map<QString, T>>();
330 doTestAssociativeContainer<QHash<qint16, T>>(true);
331 doTestAssociativeContainer<QHash<qint64, T>>(true);
332 doTestAssociativeContainer<QHash<quint16, T>>(true);
333 doTestAssociativeContainer<QHash<quint32, T>>(true);
334 doTestAssociativeContainer<QHash<quint64, T>>(true);
335 doTestAssociativeContainer<QHash<QString, T>>(true);
336#endif
337}
338
339template <typename T> void doTestContainers()
340{
341 doTestNonHashableContainers<T>();
342 doTestSequentialContainer<QSet<T>>(true);
343}
344
345void TestGenericContainers::testContainer_Builtins()
346{
347 doTestContainers<qint32>();
348#ifndef MINIMAL_CONTAINER_TESTS
349 doTestContainers<qint16>();
350 doTestContainers<qint64>();
351 doTestContainers<quint16>();
352 doTestContainers<quint32>();
353 doTestContainers<quint64>();
354 doTestNonHashableContainers<float>();
355 doTestNonHashableContainers<double>();
356 doTestContainers<QString>();
357 doTestNonHashableContainers<QVariant>();
358 doTestNonHashableContainers<QDateTime>();
359 doTestContainers<QObject *>();
360#endif
361}
362
363QTEST_MAIN(TestGenericContainers)
364#include "testgenericcontainers.moc"
The Context class holds the context to render a Template with.
Definition context.h:119
void insert(const QString &name, QObject *object)
Definition context.cpp:145
Cutelee::Engine is the main entry point for creating Cutelee Templates.
Definition engine.h:121
void setPluginPaths(const QStringList &dirs)
Definition engine.cpp:87
Template newTemplate(const QString &content, const QString &name) const
Definition engine.cpp:391
QString render(Context *c) const
Definition template.cpp:74