1 | /**************************************************************************** |
2 | ** |
3 | ** Copyright (C) 2015 Klaralvdalens Datakonsult AB (KDAB). |
4 | ** Contact: https://www.qt.io/licensing/ |
5 | ** |
6 | ** This file is part of the Qt3D module of the Qt Toolkit. |
7 | ** |
8 | ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ |
9 | ** Commercial License Usage |
10 | ** Licensees holding valid commercial Qt licenses may use this file in |
11 | ** accordance with the commercial license agreement provided with the |
12 | ** Software or, alternatively, in accordance with the terms contained in |
13 | ** a written agreement between you and The Qt Company. For licensing terms |
14 | ** and conditions see https://www.qt.io/terms-conditions. For further |
15 | ** information use the contact form at https://www.qt.io/contact-us. |
16 | ** |
17 | ** GNU General Public License Usage |
18 | ** Alternatively, this file may be used under the terms of the GNU |
19 | ** General Public License version 3 as published by the Free Software |
20 | ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT |
21 | ** included in the packaging of this file. Please review the following |
22 | ** information to ensure the GNU General Public License requirements will |
23 | ** be met: https://www.gnu.org/licenses/gpl-3.0.html. |
24 | ** |
25 | ** $QT_END_LICENSE$ |
26 | ** |
27 | ****************************************************************************/ |
28 | |
29 | #include <QtTest/QTest> |
30 | #include <Qt3DCore/private/qnode_p.h> |
31 | #include <Qt3DCore/private/qscene_p.h> |
32 | #include <Qt3DCore/qentity.h> |
33 | #include <Qt3DCore/private/qnodecreatedchangegenerator_p.h> |
34 | |
35 | #include <Qt3DRender/qtechniquefilter.h> |
36 | #include <Qt3DRender/private/qtechniquefilter_p.h> |
37 | #include <Qt3DRender/qparameter.h> |
38 | #include <Qt3DRender/qfilterkey.h> |
39 | |
40 | #include "testpostmanarbiter.h" |
41 | |
42 | class tst_QTechniqueFilter: public QObject |
43 | { |
44 | Q_OBJECT |
45 | |
46 | private Q_SLOTS: |
47 | |
48 | void checkSaneDefaults() |
49 | { |
50 | QScopedPointer<Qt3DRender::QTechniqueFilter> defaulttechniqueFilter(new Qt3DRender::QTechniqueFilter); |
51 | |
52 | QCOMPARE(defaulttechniqueFilter->matchAll().count(), 0); |
53 | QCOMPARE(defaulttechniqueFilter->parameters().count(), 0); |
54 | } |
55 | |
56 | void checkCloning_data() |
57 | { |
58 | QTest::addColumn<Qt3DRender::QTechniqueFilter *>(name: "techniqueFilter" ); |
59 | QTest::addColumn<QVector<Qt3DRender::QParameter *> >(name: "parameters" ); |
60 | QTest::addColumn<QVector<Qt3DRender::QFilterKey *> >(name: "filterKeys" ); |
61 | |
62 | Qt3DRender::QTechniqueFilter *defaultConstructed = new Qt3DRender::QTechniqueFilter(); |
63 | QTest::newRow(dataTag: "defaultConstructed" ) << defaultConstructed << QVector<Qt3DRender::QParameter *>() << QVector<Qt3DRender::QFilterKey *>(); |
64 | |
65 | Qt3DRender::QTechniqueFilter *techniqueFilterWithParams = new Qt3DRender::QTechniqueFilter(); |
66 | Qt3DRender::QParameter *parameter1 = new Qt3DRender::QParameter(QStringLiteral("displacement" ), 454.0f); |
67 | Qt3DRender::QParameter *parameter2 = new Qt3DRender::QParameter(QStringLiteral("torque" ), 650); |
68 | QVector<Qt3DRender::QParameter *> params1 = QVector<Qt3DRender::QParameter *>() << parameter1 << parameter2; |
69 | techniqueFilterWithParams->addParameter(p: parameter1); |
70 | techniqueFilterWithParams->addParameter(p: parameter2); |
71 | QTest::newRow(dataTag: "techniqueFilterWithParams" ) << techniqueFilterWithParams << params1 << QVector<Qt3DRender::QFilterKey *>(); |
72 | |
73 | Qt3DRender::QTechniqueFilter *techniqueFilterWithAnnotations = new Qt3DRender::QTechniqueFilter(); |
74 | Qt3DRender::QFilterKey *filterKey1 = new Qt3DRender::QFilterKey(); |
75 | Qt3DRender::QFilterKey *filterKey2 = new Qt3DRender::QFilterKey(); |
76 | filterKey1->setName(QStringLiteral("hasSuperCharger" )); |
77 | filterKey1->setValue(true); |
78 | filterKey1->setName(QStringLiteral("hasNitroKit" )); |
79 | filterKey1->setValue(false); |
80 | QVector<Qt3DRender::QFilterKey *> filterKeys1 = QVector<Qt3DRender::QFilterKey *>() << filterKey1 << filterKey2; |
81 | techniqueFilterWithAnnotations->addMatch(filterKey: filterKey1); |
82 | techniqueFilterWithAnnotations->addMatch(filterKey: filterKey2); |
83 | QTest::newRow(dataTag: "techniqueFilterWithAnnotations" ) << techniqueFilterWithAnnotations << QVector<Qt3DRender::QParameter *>() << filterKeys1; |
84 | |
85 | Qt3DRender::QTechniqueFilter *techniqueFilterWithParamsAndAnnotations = new Qt3DRender::QTechniqueFilter(); |
86 | Qt3DRender::QParameter *parameter3 = new Qt3DRender::QParameter(QStringLiteral("displacement" ), 383.0f); |
87 | Qt3DRender::QParameter *parameter4 = new Qt3DRender::QParameter(QStringLiteral("torque" ), 555); |
88 | Qt3DRender::QFilterKey *filterKey3 = new Qt3DRender::QFilterKey(); |
89 | Qt3DRender::QFilterKey *filterKey4 = new Qt3DRender::QFilterKey(); |
90 | filterKey3->setName(QStringLiteral("hasSuperCharger" )); |
91 | filterKey3->setValue(false); |
92 | filterKey4->setName(QStringLiteral("hasNitroKit" )); |
93 | filterKey4->setValue(true); |
94 | QVector<Qt3DRender::QParameter *> params2 = QVector<Qt3DRender::QParameter *>() << parameter3 << parameter4; |
95 | QVector<Qt3DRender::QFilterKey *> filterKeys2 = QVector<Qt3DRender::QFilterKey *>() << filterKey3 << filterKey4; |
96 | techniqueFilterWithParamsAndAnnotations->addParameter(p: parameter3); |
97 | techniqueFilterWithParamsAndAnnotations->addParameter(p: parameter4); |
98 | techniqueFilterWithParamsAndAnnotations->addMatch(filterKey: filterKey3); |
99 | techniqueFilterWithParamsAndAnnotations->addMatch(filterKey: filterKey4); |
100 | QTest::newRow(dataTag: "techniqueFilterWithParamsAndAnnotations" ) << techniqueFilterWithParamsAndAnnotations << params2 << filterKeys2; |
101 | } |
102 | |
103 | void checkCloning() |
104 | { |
105 | // GIVEN |
106 | QFETCH(Qt3DRender::QTechniqueFilter*, techniqueFilter); |
107 | QFETCH(QVector<Qt3DRender::QParameter *>, parameters); |
108 | QFETCH(QVector<Qt3DRender::QFilterKey *>, filterKeys); |
109 | |
110 | // THEN |
111 | QCOMPARE(techniqueFilter->parameters(), parameters); |
112 | QCOMPARE(techniqueFilter->matchAll(), filterKeys); |
113 | |
114 | // WHEN |
115 | Qt3DCore::QNodeCreatedChangeGenerator creationChangeGenerator(techniqueFilter); |
116 | QVector<Qt3DCore::QNodeCreatedChangeBasePtr> creationChanges = creationChangeGenerator.creationChanges(); |
117 | |
118 | // THEN |
119 | QCOMPARE(creationChanges.size(), 1 + parameters.size() + filterKeys.size()); |
120 | |
121 | const Qt3DCore::QNodeCreatedChangePtr<Qt3DRender::QTechniqueFilterData> creationChangeData = |
122 | qSharedPointerCast<Qt3DCore::QNodeCreatedChange<Qt3DRender::QTechniqueFilterData>>(src: creationChanges.first()); |
123 | const Qt3DRender::QTechniqueFilterData &cloneData = creationChangeData->data; |
124 | |
125 | QCOMPARE(techniqueFilter->id(), creationChangeData->subjectId()); |
126 | QCOMPARE(techniqueFilter->isEnabled(), creationChangeData->isNodeEnabled()); |
127 | QCOMPARE(techniqueFilter->metaObject(), creationChangeData->metaObject()); |
128 | |
129 | QCOMPARE(techniqueFilter->matchAll().count(), cloneData.matchIds.count()); |
130 | QCOMPARE(techniqueFilter->parameters().count(), cloneData.parameterIds.count()); |
131 | |
132 | for (int i = 0, m = parameters.count(); i < m; ++i) { |
133 | Qt3DRender::QParameter *pOrig = parameters.at(i); |
134 | QCOMPARE(pOrig->id(), cloneData.parameterIds.at(i)); |
135 | } |
136 | |
137 | for (int i = 0, m = filterKeys.count(); i < m; ++i) { |
138 | Qt3DRender::QFilterKey *aOrig = filterKeys.at(i); |
139 | QCOMPARE(aOrig->id(), cloneData.matchIds.at(i)); |
140 | } |
141 | |
142 | delete techniqueFilter; |
143 | } |
144 | |
145 | void checkPropertyUpdates() |
146 | { |
147 | // GIVEN |
148 | TestArbiter arbiter; |
149 | QScopedPointer<Qt3DRender::QTechniqueFilter> techniqueFilter(new Qt3DRender::QTechniqueFilter()); |
150 | arbiter.setArbiterOnNode(techniqueFilter.data()); |
151 | |
152 | // WHEN |
153 | Qt3DRender::QParameter *param1 = new Qt3DRender::QParameter(); |
154 | techniqueFilter->addParameter(p: param1); |
155 | QCoreApplication::processEvents(); |
156 | |
157 | // THEN |
158 | QCOMPARE(arbiter.events.size(), 0); |
159 | QCOMPARE(arbiter.dirtyNodes.size(), 1); |
160 | QCOMPARE(arbiter.dirtyNodes.front(), techniqueFilter.data()); |
161 | arbiter.dirtyNodes.clear(); |
162 | |
163 | |
164 | // WHEN |
165 | techniqueFilter->addParameter(p: param1); |
166 | QCoreApplication::processEvents(); |
167 | |
168 | // THEN |
169 | QCOMPARE(arbiter.events.size(), 0); |
170 | QCOMPARE(arbiter.dirtyNodes.size(), 0); |
171 | |
172 | // WHEN |
173 | techniqueFilter->removeParameter(p: param1); |
174 | QCoreApplication::processEvents(); |
175 | |
176 | // THEN |
177 | QCOMPARE(arbiter.events.size(), 0); |
178 | QCOMPARE(arbiter.dirtyNodes.size(), 1); |
179 | QCOMPARE(arbiter.dirtyNodes.front(), techniqueFilter.data()); |
180 | arbiter.dirtyNodes.clear(); |
181 | |
182 | // WHEN |
183 | Qt3DRender::QFilterKey *filterKey1 = new Qt3DRender::QFilterKey(); |
184 | techniqueFilter->addMatch(filterKey: filterKey1); |
185 | QCoreApplication::processEvents(); |
186 | |
187 | // THEN |
188 | QCOMPARE(arbiter.events.size(), 0); |
189 | QCOMPARE(arbiter.dirtyNodes.size(), 1); |
190 | QCOMPARE(arbiter.dirtyNodes.front(), techniqueFilter.data()); |
191 | arbiter.dirtyNodes.clear(); |
192 | |
193 | // WHEN |
194 | techniqueFilter->addMatch(filterKey: filterKey1); |
195 | QCoreApplication::processEvents(); |
196 | |
197 | // THEN |
198 | QCOMPARE(arbiter.events.size(), 0); |
199 | QCOMPARE(arbiter.dirtyNodes.size(), 0); |
200 | |
201 | // WHEN |
202 | techniqueFilter->removeMatch(filterKey: filterKey1); |
203 | QCoreApplication::processEvents(); |
204 | |
205 | // THEN |
206 | QCOMPARE(arbiter.events.size(), 0); |
207 | QCOMPARE(arbiter.dirtyNodes.size(), 1); |
208 | QCOMPARE(arbiter.dirtyNodes.front(), techniqueFilter.data()); |
209 | arbiter.dirtyNodes.clear(); |
210 | } |
211 | |
212 | void checkParameterBookkeeping() |
213 | { |
214 | // GIVEN |
215 | QScopedPointer<Qt3DRender::QTechniqueFilter> techniqueFilter(new Qt3DRender::QTechniqueFilter); |
216 | { |
217 | // WHEN |
218 | Qt3DRender::QParameter param; |
219 | techniqueFilter->addParameter(p: ¶m); |
220 | |
221 | // THEN |
222 | QCOMPARE(param.parent(), techniqueFilter.data()); |
223 | QCOMPARE(techniqueFilter->parameters().size(), 1); |
224 | } |
225 | // THEN (Should not crash and parameter be unset) |
226 | QVERIFY(techniqueFilter->parameters().empty()); |
227 | |
228 | { |
229 | // WHEN |
230 | Qt3DRender::QTechniqueFilter someOtherTechniqueFilter; |
231 | QScopedPointer<Qt3DRender::QParameter> param(new Qt3DRender::QParameter(&someOtherTechniqueFilter)); |
232 | techniqueFilter->addParameter(p: param.data()); |
233 | |
234 | // THEN |
235 | QCOMPARE(param->parent(), &someOtherTechniqueFilter); |
236 | QCOMPARE(techniqueFilter->parameters().size(), 1); |
237 | |
238 | // WHEN |
239 | techniqueFilter.reset(); |
240 | param.reset(); |
241 | |
242 | // THEN Should not crash when the parameter is destroyed (tests for failed removal of destruction helper) |
243 | } |
244 | } |
245 | |
246 | void checkFilterKeyBookkeeping() |
247 | { |
248 | // GIVEN |
249 | QScopedPointer<Qt3DRender::QTechniqueFilter> techniqueFilter(new Qt3DRender::QTechniqueFilter); |
250 | { |
251 | // WHEN |
252 | Qt3DRender::QFilterKey filterKey; |
253 | techniqueFilter->addMatch(filterKey: &filterKey); |
254 | |
255 | // THEN |
256 | QCOMPARE(filterKey.parent(), techniqueFilter.data()); |
257 | QCOMPARE(techniqueFilter->matchAll().size(), 1); |
258 | } |
259 | // THEN (Should not crash and parameter be unset) |
260 | QVERIFY(techniqueFilter->matchAll().empty()); |
261 | |
262 | { |
263 | // WHEN |
264 | Qt3DRender::QTechniqueFilter someOtherTechniqueFilter; |
265 | QScopedPointer<Qt3DRender::QFilterKey> filterKey(new Qt3DRender::QFilterKey(&someOtherTechniqueFilter)); |
266 | techniqueFilter->addMatch(filterKey: filterKey.data()); |
267 | |
268 | // THEN |
269 | QCOMPARE(filterKey->parent(), &someOtherTechniqueFilter); |
270 | QCOMPARE(techniqueFilter->matchAll().size(), 1); |
271 | |
272 | // WHEN |
273 | techniqueFilter.reset(); |
274 | filterKey.reset(); |
275 | |
276 | // THEN Should not crash when the filterKey is destroyed (tests for failed removal of destruction helper) |
277 | } |
278 | } |
279 | }; |
280 | |
281 | QTEST_MAIN(tst_QTechniqueFilter) |
282 | |
283 | #include "tst_qtechniquefilter.moc" |
284 | |