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/private/qnodecreatedchangegenerator_p.h>
33
34#include <Qt3DInput/QLogicalDevice>
35#include <Qt3DInput/private/qlogicaldevice_p.h>
36#include <Qt3DInput/QAxis>
37#include <Qt3DInput/QAction>
38
39#include "testpostmanarbiter.h"
40
41class tst_QLogicalDevice: public QObject
42{
43 Q_OBJECT
44public:
45 tst_QLogicalDevice()
46 {
47 qRegisterMetaType<Qt3DCore::QNode *>();
48 }
49
50private Q_SLOTS:
51
52 void checkCloning_data()
53 {
54 QTest::addColumn<Qt3DInput::QLogicalDevice *>(name: "logicalDevice");
55
56 Qt3DInput::QLogicalDevice *defaultConstructed = new Qt3DInput::QLogicalDevice();
57 QTest::newRow(dataTag: "defaultConstructed") << defaultConstructed;
58
59 Qt3DInput::QLogicalDevice *logicalDeviceWithActions = new Qt3DInput::QLogicalDevice();
60 logicalDeviceWithActions->addAction(action: new Qt3DInput::QAction());
61 logicalDeviceWithActions->addAction(action: new Qt3DInput::QAction());
62 logicalDeviceWithActions->addAction(action: new Qt3DInput::QAction());
63 QTest::newRow(dataTag: "logicalDeviceWithActions") << logicalDeviceWithActions;
64
65 Qt3DInput::QLogicalDevice *logicalDeviceWithAxes = new Qt3DInput::QLogicalDevice();
66 logicalDeviceWithAxes->addAxis(axis: new Qt3DInput::QAxis());
67 logicalDeviceWithAxes->addAxis(axis: new Qt3DInput::QAxis());
68 logicalDeviceWithAxes->addAxis(axis: new Qt3DInput::QAxis());
69 QTest::newRow(dataTag: "logicalDeviceWithAxes") << logicalDeviceWithAxes;
70 }
71
72 void checkCloning()
73 {
74 // GIVEN
75 QFETCH(Qt3DInput::QLogicalDevice *, logicalDevice);
76
77 // WHEN
78 Qt3DCore::QNodeCreatedChangeGenerator creationChangeGenerator(logicalDevice);
79 QVector<Qt3DCore::QNodeCreatedChangeBasePtr> creationChanges = creationChangeGenerator.creationChanges();
80
81 const int axesCount = logicalDevice->axes().count();
82 const int actionsCount = logicalDevice->actions().count();
83
84 // THEN
85 QCOMPARE(creationChanges.size(), 1 + axesCount + actionsCount);
86
87 const Qt3DCore::QNodeCreatedChangePtr<Qt3DInput::QLogicalDeviceData> creationChangeData =
88 qSharedPointerCast<Qt3DCore::QNodeCreatedChange<Qt3DInput::QLogicalDeviceData>>(src: creationChanges.first());
89 const Qt3DInput::QLogicalDeviceData &cloneData = creationChangeData->data;
90
91 // THEN
92 QCOMPARE(logicalDevice->id(), creationChangeData->subjectId());
93 QCOMPARE(logicalDevice->isEnabled(), creationChangeData->isNodeEnabled());
94 QCOMPARE(logicalDevice->metaObject(), creationChangeData->metaObject());
95 QCOMPARE(axesCount, cloneData.axisIds.count());
96 QCOMPARE(actionsCount, cloneData.actionIds.count());
97
98 for (int i = 0; i < axesCount; ++i)
99 QCOMPARE(logicalDevice->axes().at(i)->id(), cloneData.axisIds.at(i));
100
101 for (int i = 0; i < actionsCount; ++i)
102 QCOMPARE(logicalDevice->actions().at(i)->id(), cloneData.actionIds.at(i));
103 }
104
105 void checkPropertyUpdates()
106 {
107 // GIVEN
108 TestArbiter arbiter;
109 QScopedPointer<Qt3DInput::QLogicalDevice> logicalDevice(new Qt3DInput::QLogicalDevice());
110 arbiter.setArbiterOnNode(logicalDevice.data());
111
112 // WHEN
113 Qt3DInput::QAction *action = new Qt3DInput::QAction(logicalDevice.data());
114 QCoreApplication::processEvents();
115 arbiter.events.clear();
116
117 logicalDevice->addAction(action);
118 QCoreApplication::processEvents();
119
120 // THEN
121 QCOMPARE(arbiter.events.size(), 0);
122 QCOMPARE(arbiter.dirtyNodes.size(), 1);
123 QCOMPARE(arbiter.dirtyNodes.front(), logicalDevice.data());
124
125 arbiter.dirtyNodes.clear();
126
127 // WHEN
128 logicalDevice->removeAction(action);
129 QCoreApplication::processEvents();
130
131 // THEN
132 QCOMPARE(arbiter.events.size(), 0);
133 QCOMPARE(arbiter.dirtyNodes.size(), 1);
134 QCOMPARE(arbiter.dirtyNodes.front(), logicalDevice.data());
135
136 arbiter.dirtyNodes.clear();
137
138 // WHEN
139 Qt3DInput::QAxis *axis = new Qt3DInput::QAxis(logicalDevice.data());
140 QCoreApplication::processEvents();
141 arbiter.dirtyNodes.clear();
142
143 logicalDevice->addAxis(axis);
144 QCoreApplication::processEvents();
145
146 // THEN
147 QCOMPARE(arbiter.events.size(), 0);
148 QCOMPARE(arbiter.dirtyNodes.size(), 1);
149 QCOMPARE(arbiter.dirtyNodes.front(), logicalDevice.data());
150
151 arbiter.dirtyNodes.clear();
152
153 // WHEN
154 logicalDevice->removeAxis(axis);
155 QCoreApplication::processEvents();
156
157 // THEN
158 QCOMPARE(arbiter.events.size(), 0);
159 QCOMPARE(arbiter.dirtyNodes.size(), 1);
160 QCOMPARE(arbiter.dirtyNodes.front(), logicalDevice.data());
161
162 arbiter.dirtyNodes.clear();
163 }
164
165 void checkAxisBookkeeping()
166 {
167 // GIVEN
168 QScopedPointer<Qt3DInput::QLogicalDevice> device(new Qt3DInput::QLogicalDevice);
169 {
170 // WHEN
171 Qt3DInput::QAxis axis;
172 device->addAxis(axis: &axis);
173
174 // THEN
175 QCOMPARE(axis.parent(), device.data());
176 QCOMPARE(device->axes().size(), 1);
177 }
178 // THEN (Should not crash and parameter be unset)
179 QVERIFY(device->axes().empty());
180
181 {
182 // WHEN
183 Qt3DInput::QLogicalDevice someOtherDevice;
184 QScopedPointer<Qt3DInput::QAxis> axis(new Qt3DInput::QAxis(&someOtherDevice));
185 device->addAxis(axis: axis.data());
186
187 // THEN
188 QCOMPARE(axis->parent(), &someOtherDevice);
189 QCOMPARE(device->axes().size(), 1);
190
191 // WHEN
192 device.reset();
193 axis.reset();
194
195 // THEN Should not crash when the axis is destroyed (tests for failed removal of destruction helper)
196 }
197 }
198
199 void checkActionBookkeeping()
200 {
201 // GIVEN
202 QScopedPointer<Qt3DInput::QLogicalDevice> device(new Qt3DInput::QLogicalDevice);
203 {
204 // WHEN
205 Qt3DInput::QAction action;
206 device->addAction(action: &action);
207
208 // THEN
209 QCOMPARE(action.parent(), device.data());
210 QCOMPARE(device->actions().size(), 1);
211 }
212 // THEN (Should not crash and parameter be unset)
213 QVERIFY(device->actions().empty());
214
215 {
216 // WHEN
217 Qt3DInput::QLogicalDevice someOtherDevice;
218 QScopedPointer<Qt3DInput::QAction> action(new Qt3DInput::QAction(&someOtherDevice));
219 device->addAction(action: action.data());
220
221 // THEN
222 QCOMPARE(action->parent(), &someOtherDevice);
223 QCOMPARE(device->actions().size(), 1);
224
225 // WHEN
226 device.reset();
227 action.reset();
228
229 // THEN Should not crash when the action is destroyed (tests for failed removal of destruction helper)
230 }
231 }
232};
233
234QTEST_MAIN(tst_QLogicalDevice)
235
236#include "tst_qlogicaldevice.moc"
237

source code of qt3d/tests/auto/input/qlogicaldevice/tst_qlogicaldevice.cpp