fix tricky regression noticed by Vyacheslav Tokarev on Google Reader.
[kdelibs.git] / solid / tests / solidhwtest.cpp
blob335a8d6a48ed8afec3c686c33cae401205f949b5
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>
36 #include <stdlib.h>
38 #ifndef FAKE_COMPUTER_XML
39 #error "FAKE_COMPUTER_XML not set. An XML file describing a computer is required for this test"
40 #endif
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
57 // in the backend.
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());
92 // Query properties
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);
115 // Query parent
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));
237 QVERIFY(iface!=0);
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>();
245 QVERIFY(p!=0);
246 fakeManager->unplug("/org/kde/solid/fakehw/acpi_CPU0");
247 QVERIFY(p==0);
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>();
255 QVERIFY(v!=0);
257 Solid::Device partition2("/org/kde/solid/fakehw/volume_uuid_f00ba7");
258 v2 = partition2.as<Solid::StorageVolume>();
259 QVERIFY(v2!=0);
260 QVERIFY(v==v2);
262 QVERIFY(v!=0);
263 QVERIFY(v2!=0);
265 QVERIFY(v!=0);
266 QVERIFY(v2!=0);
267 fakeManager->unplug("/org/kde/solid/fakehw/volume_uuid_f00ba7");
268 QVERIFY(v==0);
269 QVERIFY(v2==0);
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);
297 QFETCH(int, value);
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)
311 QSet<QString> res;
313 foreach (const Solid::Device &device, list) {
314 res << device.udi();
317 return res;
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);
362 // Invalid predicate
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"));
383 parentUdi.clear();
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]",
404 parentUdi);
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]",
409 parentUdi);
410 QCOMPARE(list.size(), 10);
412 //make sure predicate case-insensitiveness is sane
413 list = Solid::Device::listFromQuery("[Processor.number==1 or is StorageVolume]",
414 parentUdi);
415 QCOMPARE(list.size(), 10);
416 list = Solid::Device::listFromQuery("[Processor.number==1 oR Is StorageVolume]",
417 parentUdi);
418 QCOMPARE(list.size(), 10);
420 QSet<QString> set;
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]",
435 parentUdi);
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)));
462 access->teardown();
464 QCOMPARE(spy.count(), 1);
465 args = spy.takeFirst();
466 QCOMPARE(args.at(0).toBool(), false);
468 access->setup();
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"