Cutelee 6.2.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#include <QtCore/QQueue>
30#include <QtCore/QStack>
31#include <QtCore/QVariant>
32#include <QtTest/QTest>
33
34class TestGenericContainers : public CoverageObject
35{
37public:
38 explicit TestGenericContainers(QObject *parent = {});
39
40private Q_SLOTS:
41 void testContainer_Builtins();
42};
43
44TestGenericContainers::TestGenericContainers(QObject *parent)
45 : CoverageObject(parent)
46{
47}
48
49template <typename T> QVector<T> getItems()
50{
51 QVector<T> items;
52 items.push_back(9);
53 items.push_back(7);
54 items.push_back(5);
55 return items;
56}
57
58template <> QVector<QString> getItems<QString>()
59{
60 QVector<QString> items;
61 Q_FOREACH (const int item, getItems<int>())
62 items.push_back(QString::number(item));
63 return items;
64}
65
66template <> QVector<QVariant> getItems<QVariant>()
67{
69 Q_FOREACH (const int item, getItems<int>())
70 items.push_back(item);
71 return items;
72}
73
74template <> QVector<QDateTime> getItems<QDateTime>()
75{
77 items.reserve(3);
78 for (auto i = 0; i < 3; ++i) {
79 QDateTime d;
81 d = d.addDays(i);
82 items.push_back(d);
83 }
84 return items;
85}
86
87template <> QVector<QObject *> getItems<QObject *>()
88{
90 items.reserve(3);
91 for (auto i = 9; i > 4; i -= 2) {
92 auto obj = new QObject;
93
95 items.push_back(obj);
96 }
97 return items;
98}
99
100template <typename Container> struct ContainerPopulator {
101 static void populateSequential(Container &container)
102 {
103 Q_FOREACH (const typename Container::value_type item,
104 getItems<typename Container::value_type>())
105 container.push_back(item);
106 }
107 static void populateAssociative(Container &container)
108 {
109 auto i = 0;
110 Q_FOREACH (const typename Container::mapped_type item,
111 getItems<typename Container::mapped_type>())
112 container[i++] = item;
113 }
114};
115
116template <typename T> struct ContainerPopulator<QSet<T>> {
117 static void populateSequential(QSet<T> &container)
118 {
119 Q_FOREACH (const T item, getItems<T>())
120 container.insert(item);
121 }
122};
123
124template <typename T> struct ContainerPopulator<QMap<QString, T>> {
125 static void populateAssociative(QMap<QString, T> &container)
126 {
127 auto i = 0;
128 Q_FOREACH (const T item, getItems<T>())
129 container.insert(QString::number(i++), item);
130 }
131};
132
133template <typename T> struct ContainerPopulator<QHash<QString, T>> {
134 static void populateAssociative(QHash<QString, T> &container)
135 {
136 auto i = 0;
137 Q_FOREACH (const T item, getItems<T>())
138 container.insert(QString::number(i++), item);
139 }
140};
141
142template <typename T> struct ContainerPopulator<std::map<QString, T>> {
143 static void populateAssociative(std::map<QString, T> &container)
144 {
145 auto i = 0;
146 Q_FOREACH (const T item, getItems<T>())
147 container[QString::number(i++)] = item;
148 }
149};
150
151template <typename T> QString getTemplate()
152{
153 return QStringLiteral("{{ container.size }};{{ container.count }};{% for "
154 "item in container %}{{ item }},{% endfor %}");
155}
156
157template <> QString getTemplate<QDateTime>()
158{
159 return QStringLiteral("{{ container.size }};{{ container.count }};{% for "
160 "item in container %}{{ item|date }},{% endfor %}");
161}
162
163template <> QString getTemplate<QObject *>()
164{
165 return QStringLiteral(
166 "{{ container.size }};{{ container.count }};{% for item in container "
167 "%}{{ item.objectName }},{% endfor %}");
168}
169
170template <typename T> QString getAssociativeTemplate()
171{
172 return QStringLiteral("{{ container.size }};{{ container.count }};{% for "
173 "item in container.values %}{{ item }},{% endfor %}");
174}
175
176template <> QString getAssociativeTemplate<QDateTime>()
177{
178 return QStringLiteral(
179 "{{ container.size }};{{ container.count }};{% for item in "
180 "container.values %}{{ item|date }},{% endfor %}");
181}
182
183template <> QString getAssociativeTemplate<QObject *>()
184{
185 return QStringLiteral(
186 "{{ container.size }};{{ container.count }};{% for item in "
187 "container.values %}{{ item.objectName }},{% endfor %}");
188}
189
190template <typename T> QStringList getResults()
191{
192 return {QStringLiteral("3;3;"), QStringLiteral("9,"), QStringLiteral("7,"),
193 QStringLiteral("5,")};
194}
195
196template <> QStringList getResults<QDateTime>()
197{
198 return {QStringLiteral("3;3;"), QStringLiteral("Jan. 1, 1970,"),
199 QStringLiteral("Jan. 2, 1970,"), QStringLiteral("Jan. 3, 1970,")};
200}
201
202template <typename Container, typename T = typename Container::value_type>
204 static void clean(Container &) {}
205};
206
207template <typename Container, typename T = typename Container::mapped_type>
209 static void clean(Container &) {}
210};
211
212template <typename Container>
214 static void clean(Container &c) { qDeleteAll(c); }
215};
216
217template <typename Container>
219 static void clean(Container &c) { qDeleteAll(c); }
220};
221
222template <typename T>
223struct CleanupAssociativeContainer<std::map<T, QObject *>, QObject *> {
224 static void clean(std::map<T, QObject *> &c)
225 {
226 typename std::map<T, QObject *>::iterator it = c.begin();
227 const typename std::map<T, QObject *>::iterator end = c.end();
228 for (; it != end; ++it) {
229 delete it->second;
230 it->second = 0;
231 }
232 }
233};
234
235template <typename Container> void cleanupSequential(Container c)
236{
237 CleanupSequentialContainer<Container>::clean(c);
238}
239
240template <typename Container> void cleanupAssociative(Container c)
241{
242 CleanupAssociativeContainer<Container>::clean(c);
243}
244
245void testContainer(const QString &stringTemplate,
246 const QVariant &containerVariant,
247 const QStringList &expectedResults, bool unordered)
248{
249 Cutelee::Engine engine;
250
251 engine.setPluginPaths({QStringLiteral(CUTELEE_PLUGIN_PATH)});
252
254 c.insert(QStringLiteral("container"), containerVariant);
255
256 auto t1 = engine.newTemplate(stringTemplate, QStringLiteral("template1"));
257
258 auto result = t1->render(&c);
259 if (!unordered)
260 QCOMPARE(result, expectedResults.join(QString()));
261 else {
262 QVERIFY(result.size() == expectedResults.join(QString()).size());
263 Q_FOREACH (const QString &expectedResult, expectedResults)
264 QVERIFY(result.contains(expectedResult));
265 }
266
267 auto t2 = engine.newTemplate(QStringLiteral("-{{ container.doesnotexist }}-"),
268 QStringLiteral("template2"));
269
270 auto result2 = t2->render(&c);
271
272 QCOMPARE(result2, QStringLiteral("--"));
273}
274
275template <typename Container>
276void doTestSequentialContainer(bool unordered = {})
277{
278 Container container;
279 ContainerPopulator<Container>::populateSequential(container);
280
281 testContainer(getTemplate<typename Container::value_type>(),
282 QVariant::fromValue(container),
283 getResults<typename Container::value_type>(), unordered);
284 cleanupSequential(container);
285}
286
287template <typename Container>
288void doTestAssociativeContainer(bool unordered = {})
289{
290 Container container;
291 ContainerPopulator<Container>::populateAssociative(container);
292
293 testContainer(getAssociativeTemplate<typename Container::mapped_type>(),
294 QVariant::fromValue(container),
295 getResults<typename Container::mapped_type>(), unordered);
296 cleanupAssociative(container);
297}
298
299template <typename T> void doTestNonHashableContainers()
300{
301 doTestSequentialContainer<QVector<T>>();
302 doTestSequentialContainer<QList<T>>();
303 doTestSequentialContainer<QQueue<T>>();
304 doTestSequentialContainer<QStack<T>>();
305 doTestSequentialContainer<std::list<T>>();
306#ifndef MINIMAL_CONTAINER_TESTS
307 doTestAssociativeContainer<QMap<qint16, T>>();
308 doTestAssociativeContainer<QMap<qint64, T>>();
309 doTestAssociativeContainer<QMap<quint16, T>>();
310 doTestAssociativeContainer<QMap<quint32, T>>();
311 doTestAssociativeContainer<QMap<quint64, T>>();
312 doTestAssociativeContainer<QMap<QString, T>>();
313 doTestAssociativeContainer<std::map<qint16, T>>();
314 doTestAssociativeContainer<std::map<qint64, T>>();
315 doTestAssociativeContainer<std::map<quint16, T>>();
316 doTestAssociativeContainer<std::map<quint32, T>>();
317 doTestAssociativeContainer<std::map<quint64, T>>();
318 doTestAssociativeContainer<std::map<QString, T>>();
319 doTestAssociativeContainer<QHash<qint16, T>>(true);
320 doTestAssociativeContainer<QHash<qint64, T>>(true);
321 doTestAssociativeContainer<QHash<quint16, T>>(true);
322 doTestAssociativeContainer<QHash<quint32, T>>(true);
323 doTestAssociativeContainer<QHash<quint64, T>>(true);
324 doTestAssociativeContainer<QHash<QString, T>>(true);
325#endif
326}
327
328template <typename T> void doTestContainers()
329{
330 doTestNonHashableContainers<T>();
331 doTestSequentialContainer<QSet<T>>(true);
332}
333
334void TestGenericContainers::testContainer_Builtins()
335{
336 doTestContainers<qint32>();
337#ifndef MINIMAL_CONTAINER_TESTS
338 doTestContainers<qint16>();
339 doTestContainers<qint64>();
340 doTestContainers<quint16>();
341 doTestContainers<quint32>();
342 doTestContainers<quint64>();
343 doTestNonHashableContainers<float>();
344 doTestNonHashableContainers<double>();
345 doTestContainers<QString>();
346 doTestNonHashableContainers<QVariant>();
347 doTestNonHashableContainers<QDateTime>();
348 doTestContainers<QObject *>();
349#endif
350}
351
352QTEST_MAIN(TestGenericContainers)
353#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
QDateTime addDays(qint64 ndays) const const
void setMSecsSinceEpoch(qint64 msecs)
QHash< Key, T >::iterator insert(Key &&key, T &&value)
void push_back(QList< T >::parameter_type value)
void reserve(qsizetype size)
QMap< Key, T >::iterator insert(QMap< Key, T >::const_iterator pos, const Key &key, const T &value)
QObject(QObject *parent)
Q_OBJECTQ_OBJECT
Q_SLOTSQ_SLOTS
QObject * parent() const const
void setObjectName(QAnyStringView name)
QSet< T >::iterator insert(QSet< T >::const_iterator it, const T &value)
QString number(double n, char format, int precision)
QString join(QChar separator) const const
QVariant fromValue(T &&value)