1 | /* |
2 | * SPDX-FileCopyrightText: 2014-2015 David Rosca <nowrep@gmail.com> |
3 | * |
4 | * SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL |
5 | */ |
6 | |
7 | #include "managertest.h" |
8 | #include "adapter.h" |
9 | #include "autotests.h" |
10 | #include "device.h" |
11 | #include "initmanagerjob.h" |
12 | #include "manager.h" |
13 | |
14 | #include <QDBusObjectPath> |
15 | #include <QSignalSpy> |
16 | #include <QTest> |
17 | |
18 | namespace BluezQt |
19 | { |
20 | extern void bluezqt_initFakeBluezTestRun(); |
21 | } |
22 | |
23 | using namespace BluezQt; |
24 | |
25 | void ManagerTest::initTestCase() |
26 | { |
27 | bluezqt_initFakeBluezTestRun(); |
28 | FakeBluez::start(); // to check that it works |
29 | Autotests::registerMetatypes(); |
30 | } |
31 | |
32 | void ManagerTest::cleanup() |
33 | { |
34 | FakeBluez::stop(); |
35 | } |
36 | |
37 | void ManagerTest::bluezNotRunningTest() |
38 | { |
39 | // org.bluez is not running at all |
40 | // expected: init successful |
41 | auto manager = std::make_unique<Manager>(); |
42 | InitManagerJob *job = manager->init(); |
43 | job->exec(); |
44 | |
45 | QVERIFY(!job->error()); |
46 | QVERIFY(manager->isInitialized()); |
47 | QVERIFY(!manager->isOperational()); |
48 | QVERIFY(!manager->isBluetoothOperational()); |
49 | } |
50 | |
51 | void ManagerTest::bluezNotExportingInterfacesTest() |
52 | { |
53 | // org.bluez is running, but it does not export any interfaces |
54 | // expected: init error |
55 | FakeBluez::start(); |
56 | FakeBluez::runTest(QStringLiteral("bluez-not-exporting-interfaces" )); |
57 | |
58 | auto manager = std::make_unique<Manager>(); |
59 | InitManagerJob *job = manager->init(); |
60 | job->exec(); |
61 | |
62 | QVERIFY(job->error()); |
63 | QVERIFY(!manager->isInitialized()); |
64 | QVERIFY(!manager->isOperational()); |
65 | QVERIFY(!manager->isBluetoothOperational()); |
66 | } |
67 | |
68 | void ManagerTest::bluezEmptyManagedObjectsTest() |
69 | { |
70 | // org.bluez exports ObjectManager, but there is no AgentManager1 |
71 | // expected: init error |
72 | FakeBluez::start(); |
73 | FakeBluez::runTest(QStringLiteral("bluez-empty-managed-objects" )); |
74 | |
75 | auto manager = std::make_unique<Manager>(); |
76 | InitManagerJob *job = manager->init(); |
77 | job->exec(); |
78 | |
79 | QVERIFY(job->error()); |
80 | QVERIFY(!manager->isInitialized()); |
81 | QVERIFY(!manager->isOperational()); |
82 | QVERIFY(!manager->isBluetoothOperational()); |
83 | } |
84 | |
85 | void ManagerTest::bluezNoAdaptersTest() |
86 | { |
87 | // org.bluez exports ObjectManager with AgentManager1, but there are no adapters |
88 | // expected: init successful |
89 | FakeBluez::start(); |
90 | FakeBluez::runTest(QStringLiteral("bluez-no-adapters" )); |
91 | |
92 | auto manager = std::make_unique<Manager>(); |
93 | InitManagerJob *job = manager->init(); |
94 | job->exec(); |
95 | |
96 | QVERIFY(!job->error()); |
97 | QVERIFY(manager->isInitialized()); |
98 | QVERIFY(manager->isOperational()); |
99 | QVERIFY(!manager->isBluetoothOperational()); |
100 | } |
101 | |
102 | void ManagerTest::bluezShutdownTest() |
103 | { |
104 | // tests whether the adapter/device removed signals work correctly |
105 | |
106 | FakeBluez::start(); |
107 | FakeBluez::runTest(QStringLiteral("bluez-standard" )); |
108 | |
109 | // Create adapters |
110 | QDBusObjectPath adapter1path = QDBusObjectPath(QStringLiteral("/org/bluez/hci0" )); |
111 | QVariantMap adapterProps; |
112 | adapterProps[QStringLiteral("Path" )] = QVariant::fromValue(adapter1path); |
113 | adapterProps[QStringLiteral("Address" )] = QStringLiteral("1C:E5:C3:BC:94:7E" ); |
114 | adapterProps[QStringLiteral("Name" )] = QStringLiteral("TestAdapter" ); |
115 | adapterProps[QStringLiteral("Powered" )] = true; |
116 | FakeBluez::runAction(QStringLiteral("devicemanager" ), QStringLiteral("create-adapter" ), adapterProps); |
117 | |
118 | QDBusObjectPath adapter2path = QDBusObjectPath(QStringLiteral("/org/bluez/hci1" )); |
119 | adapterProps[QStringLiteral("Path" )] = QVariant::fromValue(adapter2path); |
120 | adapterProps[QStringLiteral("Address" )] = QStringLiteral("2E:3A:C3:BC:85:7C" ); |
121 | adapterProps[QStringLiteral("Name" )] = QStringLiteral("TestAdapter2" ); |
122 | FakeBluez::runAction(QStringLiteral("devicemanager" ), QStringLiteral("create-adapter" ), adapterProps); |
123 | |
124 | // Create devices |
125 | QVariantMap deviceProps; |
126 | deviceProps[QStringLiteral("Path" )] = QVariant::fromValue(QDBusObjectPath("/org/bluez/hci0/dev_40_79_6A_0C_39_75" )); |
127 | deviceProps[QStringLiteral("Adapter" )] = QVariant::fromValue(adapter1path); |
128 | deviceProps[QStringLiteral("Address" )] = QStringLiteral("40:79:6A:0C:39:75" ); |
129 | deviceProps[QStringLiteral("Name" )] = QStringLiteral("TestDevice" ); |
130 | FakeBluez::runAction(QStringLiteral("devicemanager" ), QStringLiteral("create-device" ), deviceProps); |
131 | |
132 | deviceProps[QStringLiteral("Path" )] = QVariant::fromValue(QDBusObjectPath("/org/bluez/hci1/dev_50_79_6A_0C_39_75" )); |
133 | deviceProps[QStringLiteral("Adapter" )] = QVariant::fromValue(adapter2path); |
134 | deviceProps[QStringLiteral("Address" )] = QStringLiteral("50:79:6A:0C:39:75" ); |
135 | deviceProps[QStringLiteral("Name" )] = QStringLiteral("TestDevice2" ); |
136 | FakeBluez::runAction(QStringLiteral("devicemanager" ), QStringLiteral("create-device" ), deviceProps); |
137 | |
138 | auto manager = std::make_unique<Manager>(); |
139 | |
140 | QSignalSpy btOperationalChangedSpy(manager.get(), SIGNAL(bluetoothOperationalChanged(bool))); |
141 | |
142 | InitManagerJob *job = manager->init(); |
143 | job->exec(); |
144 | |
145 | QVERIFY(!job->error()); |
146 | QVERIFY(manager->isInitialized()); |
147 | QVERIFY(manager->isOperational()); |
148 | QVERIFY(manager->isBluetoothOperational()); |
149 | QCOMPARE(manager->adapters().count(), 2); |
150 | QCOMPARE(manager->devices().count(), 2); |
151 | |
152 | QCOMPARE(btOperationalChangedSpy.count(), 1); |
153 | QCOMPARE(btOperationalChangedSpy.first().first().toBool(), true); |
154 | |
155 | AdapterPtr adapter1 = manager->adapterForAddress(QStringLiteral("1C:E5:C3:BC:94:7E" )); |
156 | AdapterPtr adapter2 = manager->adapterForAddress(QStringLiteral("2E:3A:C3:BC:85:7C" )); |
157 | DevicePtr device1 = manager->deviceForAddress(QStringLiteral("40:79:6A:0C:39:75" )); |
158 | DevicePtr device2 = manager->deviceForAddress(QStringLiteral("50:79:6A:0C:39:75" )); |
159 | |
160 | QVERIFY(adapter1); |
161 | QVERIFY(adapter2); |
162 | QVERIFY(device1); |
163 | QVERIFY(device2); |
164 | |
165 | QSignalSpy allAdaptersRemovedSpy(manager.get(), SIGNAL(allAdaptersRemoved())); |
166 | QSignalSpy adapterRemovedSpy(manager.get(), SIGNAL(adapterRemoved(AdapterPtr))); |
167 | QSignalSpy device1RemovedSpy(adapter1.data(), SIGNAL(deviceRemoved(DevicePtr))); |
168 | QSignalSpy device2RemovedSpy(adapter2.data(), SIGNAL(deviceRemoved(DevicePtr))); |
169 | |
170 | btOperationalChangedSpy.clear(); |
171 | FakeBluez::stop(); |
172 | |
173 | // allAdaptersRemoved will be last signal |
174 | QTRY_COMPARE(allAdaptersRemovedSpy.count(), 1); |
175 | |
176 | QCOMPARE(adapterRemovedSpy.count(), 2); |
177 | QCOMPARE(device1RemovedSpy.count(), 1); |
178 | QCOMPARE(device2RemovedSpy.count(), 1); |
179 | |
180 | QCOMPARE(btOperationalChangedSpy.count(), 1); |
181 | QCOMPARE(btOperationalChangedSpy.first().first().toBool(), false); |
182 | } |
183 | |
184 | void ManagerTest::usableAdapterTest() |
185 | { |
186 | FakeBluez::start(); |
187 | FakeBluez::runTest(QStringLiteral("bluez-standard" )); |
188 | |
189 | // Create adapters |
190 | QDBusObjectPath adapter1path = QDBusObjectPath(QStringLiteral("/org/bluez/hci0" )); |
191 | QVariantMap adapterProps; |
192 | adapterProps[QStringLiteral("Path" )] = QVariant::fromValue(adapter1path); |
193 | adapterProps[QStringLiteral("Address" )] = QStringLiteral("1C:E5:C3:BC:94:7E" ); |
194 | adapterProps[QStringLiteral("Name" )] = QStringLiteral("TestAdapter" ); |
195 | adapterProps[QStringLiteral("Powered" )] = false; |
196 | FakeBluez::runAction(QStringLiteral("devicemanager" ), QStringLiteral("create-adapter" ), adapterProps); |
197 | |
198 | QDBusObjectPath adapter2path = QDBusObjectPath(QStringLiteral("/org/bluez/hci1" )); |
199 | adapterProps[QStringLiteral("Path" )] = QVariant::fromValue(adapter2path); |
200 | adapterProps[QStringLiteral("Address" )] = QStringLiteral("2E:3A:C3:BC:85:7C" ); |
201 | adapterProps[QStringLiteral("Name" )] = QStringLiteral("TestAdapter2" ); |
202 | adapterProps[QStringLiteral("Powered" )] = false; |
203 | FakeBluez::runAction(QStringLiteral("devicemanager" ), QStringLiteral("create-adapter" ), adapterProps); |
204 | |
205 | auto manager = std::make_unique<Manager>(); |
206 | |
207 | QSignalSpy usableAdapterChangedSpy(manager.get(), SIGNAL(usableAdapterChanged(AdapterPtr))); |
208 | |
209 | InitManagerJob *job = manager->init(); |
210 | job->exec(); |
211 | |
212 | QVERIFY(!job->error()); |
213 | QVERIFY(manager->isInitialized()); |
214 | QVERIFY(manager->isOperational()); |
215 | QVERIFY(!manager->isBluetoothOperational()); |
216 | QCOMPARE(usableAdapterChangedSpy.count(), 0); |
217 | QCOMPARE(manager->adapters().count(), 2); |
218 | QCOMPARE(manager->devices().count(), 0); |
219 | |
220 | QVariantMap properties; |
221 | properties[QStringLiteral("Path" )] = QVariant::fromValue(adapter1path); |
222 | properties[QStringLiteral("Name" )] = QStringLiteral("Powered" ); |
223 | properties[QStringLiteral("Value" )] = true; |
224 | FakeBluez::runAction(QStringLiteral("devicemanager" ), QStringLiteral("change-adapter-property" ), properties); |
225 | |
226 | QTRY_COMPARE(usableAdapterChangedSpy.count(), 1); |
227 | QCOMPARE(manager->usableAdapter()->ubi(), adapter1path.path()); |
228 | |
229 | usableAdapterChangedSpy.clear(); |
230 | |
231 | properties[QStringLiteral("Value" )] = false; |
232 | FakeBluez::runAction(QStringLiteral("devicemanager" ), QStringLiteral("change-adapter-property" ), properties); |
233 | |
234 | QTRY_COMPARE(usableAdapterChangedSpy.count(), 1); |
235 | QVERIFY(manager->usableAdapter().isNull()); |
236 | |
237 | usableAdapterChangedSpy.clear(); |
238 | |
239 | properties[QStringLiteral("Path" )] = QVariant::fromValue(adapter2path); |
240 | properties[QStringLiteral("Value" )] = true; |
241 | FakeBluez::runAction(QStringLiteral("devicemanager" ), QStringLiteral("change-adapter-property" ), properties); |
242 | |
243 | QTRY_COMPARE(usableAdapterChangedSpy.count(), 1); |
244 | QCOMPARE(manager->usableAdapter()->ubi(), adapter2path.path()); |
245 | } |
246 | |
247 | void ManagerTest::deviceForAddressTest() |
248 | { |
249 | // tests whether the deviceForAddress correctly prefer powered adapters |
250 | |
251 | FakeBluez::start(); |
252 | FakeBluez::runTest(QStringLiteral("bluez-standard" )); |
253 | |
254 | // Create adapters |
255 | QDBusObjectPath adapter1path = QDBusObjectPath(QStringLiteral("/org/bluez/hci0" )); |
256 | QVariantMap adapterProps; |
257 | adapterProps[QStringLiteral("Path" )] = QVariant::fromValue(adapter1path); |
258 | adapterProps[QStringLiteral("Address" )] = QStringLiteral("1C:E5:C3:BC:94:7E" ); |
259 | adapterProps[QStringLiteral("Name" )] = QStringLiteral("TestAdapter" ); |
260 | adapterProps[QStringLiteral("Powered" )] = false; |
261 | FakeBluez::runAction(QStringLiteral("devicemanager" ), QStringLiteral("create-adapter" ), adapterProps); |
262 | |
263 | QDBusObjectPath adapter2path = QDBusObjectPath(QStringLiteral("/org/bluez/hci1" )); |
264 | adapterProps[QStringLiteral("Path" )] = QVariant::fromValue(adapter2path); |
265 | adapterProps[QStringLiteral("Address" )] = QStringLiteral("2E:3A:C3:BC:85:7C" ); |
266 | adapterProps[QStringLiteral("Name" )] = QStringLiteral("TestAdapter2" ); |
267 | adapterProps[QStringLiteral("Powered" )] = true; |
268 | FakeBluez::runAction(QStringLiteral("devicemanager" ), QStringLiteral("create-adapter" ), adapterProps); |
269 | |
270 | // Create devices |
271 | QVariantMap deviceProps; |
272 | deviceProps[QStringLiteral("Path" )] = QVariant::fromValue(QDBusObjectPath("/org/bluez/hci0/dev_40_79_6A_0C_39_75" )); |
273 | deviceProps[QStringLiteral("Adapter" )] = QVariant::fromValue(adapter1path); |
274 | deviceProps[QStringLiteral("Address" )] = QStringLiteral("40:79:6A:0C:39:75" ); |
275 | deviceProps[QStringLiteral("Name" )] = QStringLiteral("TestDevice" ); |
276 | FakeBluez::runAction(QStringLiteral("devicemanager" ), QStringLiteral("create-device" ), deviceProps); |
277 | |
278 | deviceProps[QStringLiteral("Path" )] = QVariant::fromValue(QDBusObjectPath("/org/bluez/hci1/dev_40_79_6A_0C_39_75" )); |
279 | deviceProps[QStringLiteral("Adapter" )] = QVariant::fromValue(adapter2path); |
280 | FakeBluez::runAction(QStringLiteral("devicemanager" ), QStringLiteral("create-device" ), deviceProps); |
281 | |
282 | auto manager = std::make_unique<Manager>(); |
283 | |
284 | InitManagerJob *job = manager->init(); |
285 | job->exec(); |
286 | |
287 | QVERIFY(!job->error()); |
288 | |
289 | QString address(QStringLiteral("40:79:6A:0C:39:75" )); |
290 | AdapterPtr adapter1 = manager->adapterForUbi(QStringLiteral("/org/bluez/hci0" )); |
291 | AdapterPtr adapter2 = manager->adapterForUbi(QStringLiteral("/org/bluez/hci1" )); |
292 | |
293 | QVERIFY(adapter1); |
294 | QVERIFY(adapter2); |
295 | |
296 | QSignalSpy adapter1Spy(adapter1.data(), SIGNAL(poweredChanged(bool))); |
297 | QSignalSpy adapter2Spy(adapter2.data(), SIGNAL(poweredChanged(bool))); |
298 | |
299 | QCOMPARE(manager->deviceForAddress(address)->adapter(), adapter2); |
300 | |
301 | QVariantMap properties; |
302 | properties[QStringLiteral("Path" )] = QVariant::fromValue(adapter1path); |
303 | properties[QStringLiteral("Name" )] = QStringLiteral("Powered" ); |
304 | properties[QStringLiteral("Value" )] = true; |
305 | FakeBluez::runAction(QStringLiteral("devicemanager" ), QStringLiteral("change-adapter-property" ), properties); |
306 | |
307 | properties[QStringLiteral("Path" )] = QVariant::fromValue(adapter2path); |
308 | properties[QStringLiteral("Value" )] = false; |
309 | FakeBluez::runAction(QStringLiteral("devicemanager" ), QStringLiteral("change-adapter-property" ), properties); |
310 | |
311 | QTRY_COMPARE(adapter1Spy.count(), 1); |
312 | QTRY_COMPARE(adapter2Spy.count(), 1); |
313 | |
314 | QCOMPARE(manager->deviceForAddress(address)->adapter(), adapter1); |
315 | |
316 | properties[QStringLiteral("Path" )] = QVariant::fromValue(adapter1path); |
317 | properties[QStringLiteral("Value" )] = false; |
318 | FakeBluez::runAction(QStringLiteral("devicemanager" ), QStringLiteral("change-adapter-property" ), properties); |
319 | |
320 | QTRY_COMPARE(adapter1Spy.count(), 2); |
321 | QVERIFY(manager->deviceForAddress(address)); |
322 | } |
323 | |
324 | void ManagerTest::adapterWithDevicesRemovedTest() |
325 | { |
326 | // tests whether the devices are always removed from the adapter before removing adapter |
327 | |
328 | FakeBluez::start(); |
329 | FakeBluez::runTest(QStringLiteral("bluez-standard" )); |
330 | |
331 | // Create adapters |
332 | QDBusObjectPath adapter1path = QDBusObjectPath(QStringLiteral("/org/bluez/hci0" )); |
333 | QVariantMap adapterProps; |
334 | adapterProps[QStringLiteral("Path" )] = QVariant::fromValue(adapter1path); |
335 | adapterProps[QStringLiteral("Address" )] = QStringLiteral("1C:E5:C3:BC:94:7E" ); |
336 | adapterProps[QStringLiteral("Name" )] = QStringLiteral("TestAdapter" ); |
337 | adapterProps[QStringLiteral("Powered" )] = false; |
338 | FakeBluez::runAction(QStringLiteral("devicemanager" ), QStringLiteral("create-adapter" ), adapterProps); |
339 | |
340 | // Create devices |
341 | QVariantMap deviceProps; |
342 | deviceProps[QStringLiteral("Path" )] = QVariant::fromValue(QDBusObjectPath("/org/bluez/hci0/dev_40_79_6A_0C_39_75" )); |
343 | deviceProps[QStringLiteral("Adapter" )] = QVariant::fromValue(adapter1path); |
344 | deviceProps[QStringLiteral("Address" )] = QStringLiteral("40:79:6A:0C:39:75" ); |
345 | deviceProps[QStringLiteral("Name" )] = QStringLiteral("TestDevice" ); |
346 | FakeBluez::runAction(QStringLiteral("devicemanager" ), QStringLiteral("create-device" ), deviceProps); |
347 | |
348 | deviceProps[QStringLiteral("Path" )] = QVariant::fromValue(QDBusObjectPath("/org/bluez/hci0/dev_50_79_6A_0C_39_75" )); |
349 | deviceProps[QStringLiteral("Adapter" )] = QVariant::fromValue(adapter1path); |
350 | deviceProps[QStringLiteral("Address" )] = QStringLiteral("50:79:6A:0C:39:75" ); |
351 | deviceProps[QStringLiteral("Name" )] = QStringLiteral("TestDevice2" ); |
352 | FakeBluez::runAction(QStringLiteral("devicemanager" ), QStringLiteral("create-device" ), deviceProps); |
353 | |
354 | auto manager = std::make_unique<Manager>(); |
355 | |
356 | InitManagerJob *job = manager->init(); |
357 | job->exec(); |
358 | |
359 | QVERIFY(!job->error()); |
360 | |
361 | AdapterPtr adapter = manager->adapterForAddress(QStringLiteral("1C:E5:C3:BC:94:7E" )); |
362 | DevicePtr device1 = manager->deviceForAddress(QStringLiteral("40:79:6A:0C:39:75" )); |
363 | DevicePtr device2 = manager->deviceForAddress(QStringLiteral("50:79:6A:0C:39:75" )); |
364 | |
365 | QVERIFY(adapter); |
366 | QVERIFY(device1); |
367 | QVERIFY(device2); |
368 | |
369 | QSignalSpy adapterRemovedSpy(manager.get(), SIGNAL(adapterRemoved(AdapterPtr))); |
370 | QSignalSpy deviceRemovedSpy(manager.get(), SIGNAL(deviceRemoved(DevicePtr))); |
371 | |
372 | QVariantMap properties; |
373 | properties[QStringLiteral("Path" )] = QVariant::fromValue(adapter1path); |
374 | FakeBluez::runAction(QStringLiteral("devicemanager" ), QStringLiteral("remove-adapter" ), properties); |
375 | |
376 | QTRY_COMPARE(adapterRemovedSpy.count(), 1); |
377 | QTRY_COMPARE(deviceRemovedSpy.count(), 2); |
378 | QCOMPARE(manager->adapters().count(), 0); |
379 | QCOMPARE(manager->devices().count(), 0); |
380 | QCOMPARE(adapter->devices().count(), 0); |
381 | } |
382 | |
383 | void ManagerTest::bug364416() |
384 | { |
385 | // Bug 364416: Crash when device is added with adapter that is unknown to Manager |
386 | |
387 | FakeBluez::start(); |
388 | FakeBluez::runTest(QStringLiteral("bluez-standard" )); |
389 | |
390 | auto manager = std::make_unique<Manager>(); |
391 | |
392 | InitManagerJob *job = manager->init(); |
393 | job->exec(); |
394 | |
395 | QVERIFY(!job->error()); |
396 | |
397 | // Add device to invalid adapter |
398 | QVariantMap deviceProps; |
399 | deviceProps[QStringLiteral("Path" )] = QVariant::fromValue(QDBusObjectPath("/org/bluez/hci0/dev_40_79_6A_0C_39_75" )); |
400 | deviceProps[QStringLiteral("Adapter" )] = QVariant::fromValue(QDBusObjectPath(QStringLiteral("/org/bluez/hci0" ))); |
401 | deviceProps[QStringLiteral("Address" )] = QStringLiteral("40:79:6A:0C:39:75" ); |
402 | deviceProps[QStringLiteral("Name" )] = QStringLiteral("TestDevice" ); |
403 | FakeBluez::runAction(QStringLiteral("devicemanager" ), QStringLiteral("create-device" ), deviceProps); |
404 | |
405 | // Wait for Manager to receive the interfacesAdded signal |
406 | QTest::qWait(100); |
407 | } |
408 | |
409 | void ManagerTest::bug377405() |
410 | { |
411 | // Bug 377405: Property changes immediately after adapter is added are lost |
412 | |
413 | FakeBluez::start(); |
414 | FakeBluez::runTest(QStringLiteral("bluez-standard" )); |
415 | |
416 | auto manager = std::make_unique<Manager>(); |
417 | |
418 | InitManagerJob *job = manager->init(); |
419 | job->exec(); |
420 | |
421 | QVERIFY(!job->error()); |
422 | |
423 | FakeBluez::runAction(QStringLiteral("devicemanager" ), QStringLiteral("bug377405" )); |
424 | |
425 | // Adapter property Powered is changed to true immediately after being added |
426 | QTRY_COMPARE(manager->isBluetoothOperational(), true); |
427 | } |
428 | |
429 | QTEST_MAIN(ManagerTest) |
430 | |
431 | #include "moc_managertest.cpp" |
432 | |