1 /* This file is part of the KDE project
2 Copyright (C) 2005 Kevin Ottens <ervin@kde.org>
4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Library General Public
6 License version 2 as published by the Free Software Foundation.
8 This library is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 Library General Public License for more details.
13 You should have received a copy of the GNU Library General Public License
14 along with this library; see the file COPYING.LIB. If not, write to
15 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
16 Boston, MA 02110-1301, USA.
20 #include "solidhwtest.h"
22 #include <QtTest/QtTest>
24 #include <solid/devicenotifier.h>
25 #include <solid/device.h>
26 #include <solid/genericinterface.h>
27 #include <solid/processor.h>
28 #include <solid/storageaccess.h>
29 #include <solid/storagevolume.h>
30 #include <solid/predicate.h>
31 #include "solid/managerbase_p.h"
33 #include <fakemanager.h>
34 #include <fakedevice.h>
38 #ifndef FAKE_COMPUTER_XML
39 #error "FAKE_COMPUTER_XML not set. An XML file describing a computer is required for this test"
42 QTEST_MAIN(SolidHwTest
)
44 void SolidHwTest::initTestCase()
46 setenv("SOLID_FAKEHW", FAKE_COMPUTER_XML
, 1);
47 Solid::ManagerBasePrivate
*manager
48 = dynamic_cast<Solid::ManagerBasePrivate
*>(Solid::DeviceNotifier::instance());
49 fakeManager
= qobject_cast
<Solid::Backends::Fake::FakeManager
*>(manager
->managerBackend());
52 void SolidHwTest::testAllDevices()
54 QList
<Solid::Device
> devices
= Solid::Device::allDevices();
56 // Verify that the framework reported correctly the devices available
58 QSet
<QString
> expected_udis
, received_udis
;
60 expected_udis
= QSet
<QString
>::fromList(fakeManager
->allDevices());
62 foreach (const Solid::Device
&dev
, devices
)
64 received_udis
<< dev
.udi();
67 QCOMPARE(expected_udis
, received_udis
);
70 void SolidHwTest::testDeviceBasicFeatures()
72 // Retrieve a valid Device object
73 Solid::Device
valid_dev("/org/kde/solid/fakehw/storage_model_solid_writer");
75 QCOMPARE(valid_dev
.isValid(), true);
78 // A few attempts at creating invalid Device objects
79 Solid::Device
invalid_dev("uhoh? doesn't exist, I guess");
80 QCOMPARE(invalid_dev
.isValid(), false);
81 invalid_dev
= Solid::Device(QString());
82 QCOMPARE(invalid_dev
.isValid(), false);
83 invalid_dev
= Solid::Device();
84 QCOMPARE(invalid_dev
.isValid(), false);
88 QCOMPARE(valid_dev
.udi(), QString("/org/kde/solid/fakehw/storage_model_solid_writer"));
89 QCOMPARE(invalid_dev
.udi(), QString());
93 QCOMPARE(valid_dev
.as
<Solid::GenericInterface
>()->propertyExists("name"), true);
94 QCOMPARE(valid_dev
.as
<Solid::GenericInterface
>()->propertyExists("foo.bar"), false);
95 QCOMPARE((QObject
*)invalid_dev
.as
<Solid::GenericInterface
>(), (QObject
*)0);
97 QCOMPARE(valid_dev
.as
<Solid::GenericInterface
>()->property("name"), QVariant("Solid IDE DVD Writer"));
98 QVERIFY(!valid_dev
.as
<Solid::GenericInterface
>()->property("foo.bar").isValid());
100 Solid::Backends::Fake::FakeDevice
*fake_device
= fakeManager
->findDevice("/org/kde/solid/fakehw/storage_model_solid_writer");
101 QMap
<QString
, QVariant
> expected_properties
= fake_device
->allProperties();
103 QCOMPARE(valid_dev
.as
<Solid::GenericInterface
>()->allProperties(), expected_properties
);
106 // Query device interfaces
107 QCOMPARE(valid_dev
.isDeviceInterface(Solid::DeviceInterface::StorageDrive
), true);
108 QCOMPARE(valid_dev
.isDeviceInterface(Solid::DeviceInterface::OpticalDrive
), true);
109 QCOMPARE(valid_dev
.isDeviceInterface(Solid::DeviceInterface::StorageVolume
), false);
111 QCOMPARE(invalid_dev
.isDeviceInterface(Solid::DeviceInterface::Unknown
), false);
112 QCOMPARE(invalid_dev
.isDeviceInterface(Solid::DeviceInterface::StorageDrive
), false);
116 QCOMPARE(valid_dev
.parentUdi(), QString("/org/kde/solid/fakehw/pci_002_ide_1_0"));
117 QCOMPARE(valid_dev
.parent().udi(), Solid::Device("/org/kde/solid/fakehw/pci_002_ide_1_0").udi());
119 QVERIFY(!invalid_dev
.parent().isValid());
120 QVERIFY(invalid_dev
.parentUdi().isEmpty());
123 // Query vendor/product
124 QCOMPARE(valid_dev
.vendor(), QString("Acme Corporation"));
125 QCOMPARE(valid_dev
.product(), QString("Solid IDE DVD Writer"));
127 QCOMPARE(invalid_dev
.vendor(), QString());
128 QCOMPARE(invalid_dev
.product(), QString());
131 void SolidHwTest::testManagerSignals()
133 fakeManager
->unplug("/org/kde/solid/fakehw/acpi_CPU0");
135 // Heh, we missed a processor in this system ;-)
136 // We're going to add this device, and check that the signal has been
137 // properly emitted by the manager
138 QSignalSpy
added(Solid::DeviceNotifier::instance(), SIGNAL(deviceAdded(QString
)));
139 fakeManager
->plug("/org/kde/solid/fakehw/acpi_CPU0");
140 QCOMPARE(added
.count(), 1);
141 QCOMPARE(added
.at(0).at(0).toString(), QString("/org/kde/solid/fakehw/acpi_CPU0"));
143 // Moreover we check that the device is really available
144 Solid::Device
cpu("/org/kde/solid/fakehw/acpi_CPU0");
145 QVERIFY(cpu
.isValid());
148 // Finally we remove the device and spy the corresponding signal again
149 QSignalSpy
removed(Solid::DeviceNotifier::instance(), SIGNAL(deviceRemoved(QString
)));
150 fakeManager
->unplug("/org/kde/solid/fakehw/acpi_CPU0");
151 QCOMPARE(added
.count(), 1);
152 QCOMPARE(added
.at(0).at(0).toString(), QString("/org/kde/solid/fakehw/acpi_CPU0"));
154 // The Device object should become automatically invalid
155 QVERIFY(!cpu
.isValid());
157 // Restore original state
158 fakeManager
->plug("/org/kde/solid/fakehw/acpi_CPU0");
161 void SolidHwTest::testDeviceSignals()
163 // A button is a nice device for testing state changes, isn't it?
164 Solid::Backends::Fake::FakeDevice
*fake
= fakeManager
->findDevice("/org/kde/solid/fakehw/acpi_LID0");
165 Solid::Device
device("/org/kde/solid/fakehw/acpi_LID0");
167 // We'll spy our button
168 connect(device
.as
<Solid::GenericInterface
>(), SIGNAL(propertyChanged(const QMap
<QString
,int> &)),
169 this, SLOT(slotPropertyChanged(const QMap
<QString
,int> &)));
170 QSignalSpy
condition_raised(device
.as
<Solid::GenericInterface
>(), SIGNAL(conditionRaised(QString
, QString
)));
172 fake
->setProperty("stateValue", true); // The button is now pressed (modified property)
173 fake
->raiseCondition("Lid Closed", "Why not?"); // Since it's a LID we notify this change
174 fake
->setProperty("hactar", 42); // We add a property
175 fake
->removeProperty("hactar"); // We remove a property
177 // 3 property changes occurred in the device
178 QCOMPARE(m_changesList
.count(), 3);
180 QMap
<QString
,int> changes
;
182 // First one is a "PropertyModified" for "button.state"
183 changes
= m_changesList
.at(0);
184 QCOMPARE(changes
.count(), 1);
185 QVERIFY(changes
.contains("stateValue"));
186 QCOMPARE(changes
["stateValue"], (int)Solid::GenericInterface::PropertyModified
);
188 // Second one is a "PropertyAdded" for "hactar"
189 changes
= m_changesList
.at(1);
190 QCOMPARE(changes
.count(), 1);
191 QVERIFY(changes
.contains("hactar"));
192 QCOMPARE(changes
["hactar"], (int)Solid::GenericInterface::PropertyAdded
);
194 // Third one is a "PropertyRemoved" for "hactar"
195 changes
= m_changesList
.at(2);
196 QCOMPARE(changes
.count(), 1);
197 QVERIFY(changes
.contains("hactar"));
198 QCOMPARE(changes
["hactar"], (int)Solid::GenericInterface::PropertyRemoved
);
202 // Only one condition has been raised in the device
203 QCOMPARE(condition_raised
.count(), 1);
205 // It must be identical to the condition we raised by hand
206 QCOMPARE(condition_raised
.at(0).at(0).toString(), QString("Lid Closed"));
207 QCOMPARE(condition_raised
.at(0).at(1).toString(), QString("Why not?"));
210 void SolidHwTest::testDeviceExistence()
212 QCOMPARE(Solid::Device("/org/kde/solid/fakehw/acpi_LID0").isValid(), true);
213 QCOMPARE(Solid::Device("/org/kde/solid/fakehw/volume_label_SOLIDMAN_BEGINS").isValid(), true);
215 // Note the extra space
216 QCOMPARE(Solid::Device("/org/kde/solid/fakehw/computer ").isValid(), false);
217 QCOMPARE(Solid::Device("#'({(Ã ]").isValid(), false);
218 QCOMPARE(Solid::Device(QString()).isValid(), false);
220 // Now try to see if isValid() changes on plug/unplug events
221 Solid::Device
cpu("/org/kde/solid/fakehw/acpi_CPU0");
222 QVERIFY(cpu
.isValid());
223 fakeManager
->unplug("/org/kde/solid/fakehw/acpi_CPU0");
224 QVERIFY(!cpu
.isValid());
225 fakeManager
->plug("/org/kde/solid/fakehw/acpi_CPU0");
226 QVERIFY(cpu
.isValid());
229 void SolidHwTest::testDeviceInterfaces()
231 Solid::Device
cpu("/org/kde/solid/fakehw/acpi_CPU0");
233 Solid::DeviceInterface
*iface
= cpu
.asDeviceInterface(Solid::DeviceInterface::Processor
);
234 Solid::Processor
*processor
= cpu
.as
<Solid::Processor
>();
236 QVERIFY(cpu
.isDeviceInterface(Solid::DeviceInterface::Processor
));
238 QCOMPARE(iface
, processor
);
240 Solid::Device
cpu2("/org/kde/solid/fakehw/acpi_CPU0");
241 QCOMPARE(cpu
.as
<Solid::Processor
>(), cpu2
.as
<Solid::Processor
>());
242 QCOMPARE(cpu
.as
<Solid::GenericInterface
>(), cpu2
.as
<Solid::GenericInterface
>());
244 QPointer
<Solid::Processor
> p
= cpu
.as
<Solid::Processor
>();
246 fakeManager
->unplug("/org/kde/solid/fakehw/acpi_CPU0");
248 fakeManager
->plug("/org/kde/solid/fakehw/acpi_CPU0");
250 QPointer
<Solid::StorageVolume
> v
;
251 QPointer
<Solid::StorageVolume
> v2
;
253 Solid::Device
partition("/org/kde/solid/fakehw/volume_uuid_f00ba7");
254 v
= partition
.as
<Solid::StorageVolume
>();
257 Solid::Device
partition2("/org/kde/solid/fakehw/volume_uuid_f00ba7");
258 v2
= partition2
.as
<Solid::StorageVolume
>();
267 fakeManager
->unplug("/org/kde/solid/fakehw/volume_uuid_f00ba7");
270 fakeManager
->plug("/org/kde/solid/fakehw/volume_uuid_f00ba7");
273 void SolidHwTest::testDeviceInterfaceIntrospection_data()
275 QTest::addColumn
<QString
>("name");
276 QTest::addColumn
<int>("value");
278 QTest::newRow("DeviceInterface: Unknown") << "Unknown" << (int)Solid::DeviceInterface::Unknown
;
279 QTest::newRow("DeviceInterface: Processor") << "Processor" << (int)Solid::DeviceInterface::Processor
;
280 QTest::newRow("DeviceInterface: Block") << "Block" << (int)Solid::DeviceInterface::Block
;
281 QTest::newRow("DeviceInterface: StorageDrive") << "StorageDrive" << (int)Solid::DeviceInterface::StorageDrive
;
282 QTest::newRow("DeviceInterface: OpticalDrive") << "OpticalDrive" << (int)Solid::DeviceInterface::OpticalDrive
;
283 QTest::newRow("DeviceInterface: StorageVolume") << "StorageVolume" << (int)Solid::DeviceInterface::StorageVolume
;
284 QTest::newRow("DeviceInterface: OpticalDisc") << "OpticalDisc" << (int)Solid::DeviceInterface::OpticalDisc
;
285 QTest::newRow("DeviceInterface: Camera") << "Camera" << (int)Solid::DeviceInterface::Camera
;
286 QTest::newRow("DeviceInterface: PortableMediaPlayer") << "PortableMediaPlayer" << (int)Solid::DeviceInterface::PortableMediaPlayer
;
287 QTest::newRow("DeviceInterface: NetworkInterface") << "NetworkInterface" << (int)Solid::DeviceInterface::NetworkInterface
;
288 QTest::newRow("DeviceInterface: AcAdapter") << "AcAdapter" << (int)Solid::DeviceInterface::AcAdapter
;
289 QTest::newRow("DeviceInterface: Battery") << "Battery" << (int)Solid::DeviceInterface::Battery
;
290 QTest::newRow("DeviceInterface: Button") << "Button" << (int)Solid::DeviceInterface::Button
;
291 QTest::newRow("DeviceInterface: AudioInterface") << "AudioInterface" << (int)Solid::DeviceInterface::AudioInterface
;
294 void SolidHwTest::testDeviceInterfaceIntrospection()
296 QFETCH(QString
, name
);
299 QCOMPARE(Solid::DeviceInterface::typeToString((Solid::DeviceInterface::Type
)value
), name
);
300 QCOMPARE((int)Solid::DeviceInterface::stringToType(name
), value
);
303 void SolidHwTest::testDeviceInterfaceIntrospectionCornerCases()
305 QCOMPARE(Solid::DeviceInterface::typeToString((Solid::DeviceInterface::Type
)-1), QString());
306 QCOMPARE((int)Solid::DeviceInterface::stringToType("blup"), -1);
309 static QSet
<QString
> to_string_set(const QList
<Solid::Device
> &list
)
313 foreach (const Solid::Device
&device
, list
) {
320 void SolidHwTest::testPredicate()
322 Solid::Device
dev("/org/kde/solid/fakehw/acpi_CPU0");
324 Solid::Predicate p1
= Solid::Predicate(Solid::DeviceInterface::Processor
, "maxSpeed", 3200)
325 & Solid::Predicate(Solid::DeviceInterface::Processor
, "canChangeFrequency", true);
326 Solid::Predicate p2
= Solid::Predicate(Solid::DeviceInterface::Processor
, "maxSpeed", 3200)
327 & Solid::Predicate(Solid::DeviceInterface::Processor
, "canChangeFrequency", false);
328 Solid::Predicate p3
= Solid::Predicate(Solid::DeviceInterface::Processor
, "maxSpeed", 3201)
329 | Solid::Predicate(Solid::DeviceInterface::Processor
, "canChangeFrequency", true);
330 Solid::Predicate p4
= Solid::Predicate(Solid::DeviceInterface::Processor
, "maxSpeed", 3201)
331 | Solid::Predicate(Solid::DeviceInterface::Processor
, "canChangeFrequency", false);
332 Solid::Predicate p5
= Solid::Predicate::fromString("[[Processor.maxSpeed == 3201 AND Processor.canChangeFrequency == false] OR StorageVolume.mountPoint == '/media/blup']");
334 QVERIFY(p1
.matches(dev
));
335 QVERIFY(!p2
.matches(dev
));
336 QVERIFY(p3
.matches(dev
));
337 QVERIFY(!p4
.matches(dev
));
339 Solid::Predicate p6
= Solid::Predicate::fromString("StorageVolume.usage == 'Other'");
340 Solid::Predicate p7
= Solid::Predicate::fromString(QString("StorageVolume.usage == %1").arg((int)Solid::StorageVolume::Other
));
341 QVERIFY(!p6
.matches(dev
));
342 QVERIFY(!p7
.matches(dev
));
343 dev
= Solid::Device("/org/kde/solid/fakehw/volume_part2_size_1024");
344 QVERIFY(p6
.matches(dev
));
345 QVERIFY(p7
.matches(dev
));
347 Solid::Predicate p8
= Solid::Predicate::fromString("AudioInterface.deviceType == 'AudioInput|AudioOutput'");
348 Solid::Predicate p9
= Solid::Predicate::fromString("AudioInterface.deviceType == 'AudioInput'");
349 Solid::Predicate p10
= Solid::Predicate::fromString("AudioInterface.deviceType & 'AudioInput'");
350 QVERIFY(!p8
.matches(dev
));
351 QVERIFY(!p9
.matches(dev
));
352 QVERIFY(!p10
.matches(dev
));
353 dev
= Solid::Device("/org/kde/solid/fakehw/pci_8086_266e_oss_pcm_0");
354 QVERIFY(p8
.matches(dev
));
355 QVERIFY(!p9
.matches(dev
));
356 QVERIFY(p10
.matches(dev
));
358 QString str_pred
= "[[Processor.maxSpeed == 3201 AND Processor.canChangeFrequency == false] OR StorageVolume.mountPoint == '/media/blup']";
359 // Since str_pred is canonicalized, fromString().toString() should be invariant
360 QCOMPARE(Solid::Predicate::fromString(str_pred
).toString(), str_pred
);
363 str_pred
= "[StorageVolume.ignored == false AND OpticalDisc.isBlank == true AND OpticalDisc.discType & 'CdRecordable|CdRewritable']";
364 QVERIFY(!Solid::Predicate::fromString(str_pred
).isValid());
366 QString parentUdi
= "/org/kde/solid/fakehw/storage_model_solid_reader";
367 Solid::DeviceInterface::Type ifaceType
= Solid::DeviceInterface::Unknown
;
368 QCOMPARE(fakeManager
->devicesFromQuery(parentUdi
, ifaceType
).size(), 1);
369 QCOMPARE(fakeManager
->devicesFromQuery(parentUdi
, ifaceType
).at(0),
370 QString("/org/kde/solid/fakehw/volume_label_SOLIDMAN_BEGINS"));
372 ifaceType
= Solid::DeviceInterface::Processor
;
373 QCOMPARE(fakeManager
->devicesFromQuery(parentUdi
, ifaceType
).size(), 0);
375 parentUdi
= "/org/kde/solid/fakehw/computer";
376 QCOMPARE(fakeManager
->devicesFromQuery(parentUdi
, ifaceType
).size(), 2);
377 QCOMPARE(fakeManager
->devicesFromQuery(parentUdi
, ifaceType
).at(0),
378 QString("/org/kde/solid/fakehw/acpi_CPU0"));
379 QCOMPARE(fakeManager
->devicesFromQuery(parentUdi
, ifaceType
).at(1),
380 QString("/org/kde/solid/fakehw/acpi_CPU1"));
384 ifaceType
= Solid::DeviceInterface::Unknown
;
385 QList
<Solid::Device
> list
;
387 list
= Solid::Device::listFromQuery(p1
, parentUdi
);
388 QCOMPARE(list
.size(), 2);
389 QCOMPARE(list
.at(0).udi(), QString("/org/kde/solid/fakehw/acpi_CPU0"));
390 QCOMPARE(list
.at(1).udi(), QString("/org/kde/solid/fakehw/acpi_CPU1"));
392 list
= Solid::Device::listFromQuery(p2
, parentUdi
);
393 QCOMPARE(list
.size(), 0);
395 list
= Solid::Device::listFromQuery(p3
, parentUdi
);
396 QCOMPARE(list
.size(), 2);
397 QCOMPARE(list
.at(0).udi(), QString("/org/kde/solid/fakehw/acpi_CPU0"));
398 QCOMPARE(list
.at(1).udi(), QString("/org/kde/solid/fakehw/acpi_CPU1"));
400 list
= Solid::Device::listFromQuery(p4
, parentUdi
);
401 QCOMPARE(list
.size(), 0);
403 list
= Solid::Device::listFromQuery("[Processor.canChangeFrequency==true AND Processor.number==1]",
405 QCOMPARE(list
.size(), 1);
406 QCOMPARE(list
.at(0).udi(), QString("/org/kde/solid/fakehw/acpi_CPU1"));
408 list
= Solid::Device::listFromQuery("[Processor.number==1 OR IS StorageVolume]",
410 QCOMPARE(list
.size(), 10);
412 //make sure predicate case-insensitiveness is sane
413 list
= Solid::Device::listFromQuery("[Processor.number==1 or is StorageVolume]",
415 QCOMPARE(list
.size(), 10);
416 list
= Solid::Device::listFromQuery("[Processor.number==1 oR Is StorageVolume]",
418 QCOMPARE(list
.size(), 10);
421 QCOMPARE(list
.size(), 10);
422 set
<< "/org/kde/solid/fakehw/acpi_CPU1"
423 << "/org/kde/solid/fakehw/platform_floppy_0_storage_virt_volume"
424 << "/org/kde/solid/fakehw/volume_label_SOLIDMAN_BEGINS"
425 << "/org/kde/solid/fakehw/volume_part1_size_993284096"
426 << "/org/kde/solid/fakehw/volume_part2_size_1024"
427 << "/org/kde/solid/fakehw/volume_part5_size_1048576"
428 << "/org/kde/solid/fakehw/volume_uuid_5011"
429 << "/org/kde/solid/fakehw/volume_uuid_c0ffee"
430 << "/org/kde/solid/fakehw/volume_uuid_f00ba7"
431 << "/org/kde/solid/fakehw/volume_uuid_feedface";
432 QCOMPARE(set
, to_string_set(list
));
434 list
= Solid::Device::listFromQuery("[IS Processor OR IS StorageVolume]",
436 QCOMPARE(list
.size(), 11);
437 set
<< "/org/kde/solid/fakehw/acpi_CPU0";
438 QCOMPARE(set
, to_string_set(list
));
440 ifaceType
= Solid::DeviceInterface::Processor
;
441 list
= Solid::Device::listFromType(ifaceType
, parentUdi
);
442 QCOMPARE(list
.size(), 2);
443 QCOMPARE(list
.at(0).udi(), QString("/org/kde/solid/fakehw/acpi_CPU0"));
444 QCOMPARE(list
.at(1).udi(), QString("/org/kde/solid/fakehw/acpi_CPU1"));
446 ifaceType
= Solid::DeviceInterface::Unknown
;
447 list
= Solid::Device::listFromQuery("blup", parentUdi
);
448 QCOMPARE(list
.size(), 0);
451 void SolidHwTest::testSetupTeardown()
453 Solid::StorageAccess
*access
;
455 Solid::Device
device("/org/kde/solid/fakehw/volume_part1_size_993284096");
456 access
= device
.as
<Solid::StorageAccess
>();
459 QList
<QVariant
> args
;
460 QSignalSpy
spy(access
, SIGNAL(accessibilityChanged(bool,QString
)));
464 QCOMPARE(spy
.count(), 1);
465 args
= spy
.takeFirst();
466 QCOMPARE(args
.at(0).toBool(), false);
470 QCOMPARE(spy
.count(), 1);
471 args
= spy
.takeFirst();
472 QCOMPARE(args
.at(0).toBool(), true);
476 void SolidHwTest::slotPropertyChanged(const QMap
<QString
,int> &changes
)
478 m_changesList
<< changes
;
482 #include "solidhwtest.moc"