/* Copyright 2005 Kevin Ottens This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) version 3, or any later version accepted by the membership of KDE e.V. (or its successor approved by the membership of KDE e.V.), which shall act as a proxy defined in Section 6 of version 3 of the license. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library. If not, see . */ #include "solidhwtest.h" #include #include #include #include #include #include #include #include #include "solid/managerbase_p.h" #include #include #include #ifndef FAKE_COMPUTER_XML #error "FAKE_COMPUTER_XML not set. An XML file describing a computer is required for this test" #endif QTEST_MAIN(SolidHwTest) void SolidHwTest::initTestCase() { setenv("SOLID_FAKEHW", FAKE_COMPUTER_XML, 1); Solid::ManagerBasePrivate *manager = dynamic_cast(Solid::DeviceNotifier::instance()); fakeManager = qobject_cast(manager->managerBackends().first()); } void SolidHwTest::testAllDevices() { QList devices = Solid::Device::allDevices(); // Verify that the framework reported correctly the devices available // in the backend. QSet expected_udis, received_udis; expected_udis = QSet::fromList(fakeManager->allDevices()); foreach (const Solid::Device &dev , devices) { received_udis << dev.udi(); } QCOMPARE(expected_udis, received_udis); } void SolidHwTest::testDeviceBasicFeatures() { // Retrieve a valid Device object Solid::Device valid_dev("/org/kde/solid/fakehw/storage_model_solid_writer"); QCOMPARE(valid_dev.isValid(), true); // A few attempts at creating invalid Device objects Solid::Device invalid_dev("uhoh? doesn't exist, I guess"); QCOMPARE(invalid_dev.isValid(), false); invalid_dev = Solid::Device(QString()); QCOMPARE(invalid_dev.isValid(), false); invalid_dev = Solid::Device(); QCOMPARE(invalid_dev.isValid(), false); QCOMPARE(valid_dev.udi(), QString("/org/kde/solid/fakehw/storage_model_solid_writer")); QCOMPARE(invalid_dev.udi(), QString()); // Query properties QCOMPARE(valid_dev.as()->propertyExists("name"), true); QCOMPARE(valid_dev.as()->propertyExists("foo.bar"), false); QCOMPARE((QObject *)invalid_dev.as(), (QObject *)0); QCOMPARE(valid_dev.as()->property("name"), QVariant("Solid IDE DVD Writer")); QVERIFY(!valid_dev.as()->property("foo.bar").isValid()); Solid::Backends::Fake::FakeDevice *fake_device = fakeManager->findDevice("/org/kde/solid/fakehw/storage_model_solid_writer"); QMap expected_properties = fake_device->allProperties(); QCOMPARE(valid_dev.as()->allProperties(), expected_properties); // Query device interfaces QCOMPARE(valid_dev.isDeviceInterface(Solid::DeviceInterface::StorageDrive), true); QCOMPARE(valid_dev.isDeviceInterface(Solid::DeviceInterface::OpticalDrive), true); QCOMPARE(valid_dev.isDeviceInterface(Solid::DeviceInterface::StorageVolume), false); QCOMPARE(invalid_dev.isDeviceInterface(Solid::DeviceInterface::Unknown), false); QCOMPARE(invalid_dev.isDeviceInterface(Solid::DeviceInterface::StorageDrive), false); // Query parent QCOMPARE(valid_dev.parentUdi(), QString("/org/kde/solid/fakehw/pci_002_ide_1_0")); QCOMPARE(valid_dev.parent().udi(), Solid::Device("/org/kde/solid/fakehw/pci_002_ide_1_0").udi()); QVERIFY(!invalid_dev.parent().isValid()); QVERIFY(invalid_dev.parentUdi().isEmpty()); // Query vendor/product QCOMPARE(valid_dev.vendor(), QString("Acme Corporation")); QCOMPARE(valid_dev.product(), QString("Solid IDE DVD Writer")); QCOMPARE(invalid_dev.vendor(), QString()); QCOMPARE(invalid_dev.product(), QString()); } void SolidHwTest::testManagerSignals() { fakeManager->unplug("/org/kde/solid/fakehw/acpi_CPU0"); // Heh, we missed a processor in this system ;-) // We're going to add this device, and check that the signal has been // properly emitted by the manager QSignalSpy added(Solid::DeviceNotifier::instance(), SIGNAL(deviceAdded(QString))); fakeManager->plug("/org/kde/solid/fakehw/acpi_CPU0"); QCOMPARE(added.count(), 1); QCOMPARE(added.at(0).at(0).toString(), QString("/org/kde/solid/fakehw/acpi_CPU0")); // Moreover we check that the device is really available Solid::Device cpu("/org/kde/solid/fakehw/acpi_CPU0"); QVERIFY(cpu.isValid()); // Finally we remove the device and spy the corresponding signal again QSignalSpy removed(Solid::DeviceNotifier::instance(), SIGNAL(deviceRemoved(QString))); fakeManager->unplug("/org/kde/solid/fakehw/acpi_CPU0"); QCOMPARE(added.count(), 1); QCOMPARE(added.at(0).at(0).toString(), QString("/org/kde/solid/fakehw/acpi_CPU0")); // The Device object should become automatically invalid QVERIFY(!cpu.isValid()); // Restore original state fakeManager->plug("/org/kde/solid/fakehw/acpi_CPU0"); } void SolidHwTest::testDeviceSignals() { // A button is a nice device for testing state changes, isn't it? Solid::Backends::Fake::FakeDevice *fake = fakeManager->findDevice("/org/kde/solid/fakehw/acpi_LID0"); Solid::Device device("/org/kde/solid/fakehw/acpi_LID0"); // We'll spy our button connect(device.as(), SIGNAL(propertyChanged(QMap)), this, SLOT(slotPropertyChanged(QMap))); QSignalSpy condition_raised(device.as(), SIGNAL(conditionRaised(QString,QString))); fake->setProperty("stateValue", true); // The button is now pressed (modified property) fake->raiseCondition("Lid Closed", "Why not?"); // Since it's a LID we notify this change fake->setProperty("hactar", 42); // We add a property fake->removeProperty("hactar"); // We remove a property // 3 property changes occurred in the device QCOMPARE(m_changesList.count(), 3); QMap changes; // First one is a "PropertyModified" for "button.state" changes = m_changesList.at(0); QCOMPARE(changes.count(), 1); QVERIFY(changes.contains("stateValue")); QCOMPARE(changes["stateValue"], (int)Solid::GenericInterface::PropertyModified); // Second one is a "PropertyAdded" for "hactar" changes = m_changesList.at(1); QCOMPARE(changes.count(), 1); QVERIFY(changes.contains("hactar")); QCOMPARE(changes["hactar"], (int)Solid::GenericInterface::PropertyAdded); // Third one is a "PropertyRemoved" for "hactar" changes = m_changesList.at(2); QCOMPARE(changes.count(), 1); QVERIFY(changes.contains("hactar")); QCOMPARE(changes["hactar"], (int)Solid::GenericInterface::PropertyRemoved); // Only one condition has been raised in the device QCOMPARE(condition_raised.count(), 1); // It must be identical to the condition we raised by hand QCOMPARE(condition_raised.at(0).at(0).toString(), QString("Lid Closed")); QCOMPARE(condition_raised.at(0).at(1).toString(), QString("Why not?")); } void SolidHwTest::testDeviceExistence() { QCOMPARE(Solid::Device("/org/kde/solid/fakehw/acpi_LID0").isValid(), true); QCOMPARE(Solid::Device("/org/kde/solid/fakehw/volume_label_SOLIDMAN_BEGINS").isValid(), true); // Note the extra space QCOMPARE(Solid::Device("/org/kde/solid/fakehw/computer ").isValid(), false); QCOMPARE(Solid::Device("#'({(]").isValid(), false); QCOMPARE(Solid::Device(QString()).isValid(), false); // Now try to see if isValid() changes on plug/unplug events Solid::Device cpu("/org/kde/solid/fakehw/acpi_CPU0"); QVERIFY(cpu.isValid()); fakeManager->unplug("/org/kde/solid/fakehw/acpi_CPU0"); QVERIFY(!cpu.isValid()); fakeManager->plug("/org/kde/solid/fakehw/acpi_CPU0"); QVERIFY(cpu.isValid()); } void SolidHwTest::testDeviceInterfaces() { Solid::Device cpu("/org/kde/solid/fakehw/acpi_CPU0"); Solid::DeviceInterface *iface = cpu.asDeviceInterface(Solid::DeviceInterface::Processor); Solid::DeviceInterface *processor = cpu.as(); QVERIFY(cpu.isDeviceInterface(Solid::DeviceInterface::Processor)); QVERIFY(iface!=0); QCOMPARE(iface, processor); Solid::Device cpu2("/org/kde/solid/fakehw/acpi_CPU0"); QCOMPARE(cpu.as(), cpu2.as()); QCOMPARE(cpu.as(), cpu2.as()); QPointer p = cpu.as(); QVERIFY(p!=0); fakeManager->unplug("/org/kde/solid/fakehw/acpi_CPU0"); QVERIFY(p==0); fakeManager->plug("/org/kde/solid/fakehw/acpi_CPU0"); QPointer v; QPointer v2; { Solid::Device partition("/org/kde/solid/fakehw/volume_uuid_f00ba7"); v = partition.as(); QVERIFY(v!=0); { Solid::Device partition2("/org/kde/solid/fakehw/volume_uuid_f00ba7"); v2 = partition2.as(); QVERIFY(v2!=0); QVERIFY(v==v2); } QVERIFY(v!=0); QVERIFY(v2!=0); } QVERIFY(v!=0); QVERIFY(v2!=0); fakeManager->unplug("/org/kde/solid/fakehw/volume_uuid_f00ba7"); QVERIFY(v==0); QVERIFY(v2==0); fakeManager->plug("/org/kde/solid/fakehw/volume_uuid_f00ba7"); } void SolidHwTest::testDeviceInterfaceIntrospection_data() { QTest::addColumn("name"); QTest::addColumn("value"); QTest::newRow("DeviceInterface: Unknown") << "Unknown" << (int)Solid::DeviceInterface::Unknown; QTest::newRow("DeviceInterface: Processor") << "Processor" << (int)Solid::DeviceInterface::Processor; QTest::newRow("DeviceInterface: Block") << "Block" << (int)Solid::DeviceInterface::Block; QTest::newRow("DeviceInterface: StorageDrive") << "StorageDrive" << (int)Solid::DeviceInterface::StorageDrive; QTest::newRow("DeviceInterface: OpticalDrive") << "OpticalDrive" << (int)Solid::DeviceInterface::OpticalDrive; QTest::newRow("DeviceInterface: StorageVolume") << "StorageVolume" << (int)Solid::DeviceInterface::StorageVolume; QTest::newRow("DeviceInterface: OpticalDisc") << "OpticalDisc" << (int)Solid::DeviceInterface::OpticalDisc; QTest::newRow("DeviceInterface: Camera") << "Camera" << (int)Solid::DeviceInterface::Camera; QTest::newRow("DeviceInterface: PortableMediaPlayer") << "PortableMediaPlayer" << (int)Solid::DeviceInterface::PortableMediaPlayer; QTest::newRow("DeviceInterface: NetworkInterface") << "NetworkInterface" << (int)Solid::DeviceInterface::NetworkInterface; QTest::newRow("DeviceInterface: AcAdapter") << "AcAdapter" << (int)Solid::DeviceInterface::AcAdapter; QTest::newRow("DeviceInterface: Battery") << "Battery" << (int)Solid::DeviceInterface::Battery; QTest::newRow("DeviceInterface: Button") << "Button" << (int)Solid::DeviceInterface::Button; QTest::newRow("DeviceInterface: AudioInterface") << "AudioInterface" << (int)Solid::DeviceInterface::AudioInterface; } void SolidHwTest::testDeviceInterfaceIntrospection() { QFETCH(QString, name); QFETCH(int, value); QCOMPARE(Solid::DeviceInterface::typeToString((Solid::DeviceInterface::Type)value), name); QCOMPARE((int)Solid::DeviceInterface::stringToType(name), value); } void SolidHwTest::testDeviceInterfaceIntrospectionCornerCases() { QCOMPARE(Solid::DeviceInterface::typeToString((Solid::DeviceInterface::Type)-1), QString()); QCOMPARE((int)Solid::DeviceInterface::stringToType("blup"), -1); } static QSet to_string_set(const QList &list) { QSet res; foreach (const Solid::Device &device, list) { res << device.udi(); } return res; } void SolidHwTest::testPredicate() { Solid::Device dev("/org/kde/solid/fakehw/acpi_CPU0"); Solid::Predicate p1 = Solid::Predicate(Solid::DeviceInterface::Processor, "maxSpeed", 3200) & Solid::Predicate(Solid::DeviceInterface::Processor, "canChangeFrequency", true); Solid::Predicate p2 = Solid::Predicate(Solid::DeviceInterface::Processor, "maxSpeed", 3200) & Solid::Predicate(Solid::DeviceInterface::Processor, "canChangeFrequency", false); Solid::Predicate p3 = Solid::Predicate(Solid::DeviceInterface::Processor, "maxSpeed", 3201) | Solid::Predicate(Solid::DeviceInterface::Processor, "canChangeFrequency", true); Solid::Predicate p4 = Solid::Predicate(Solid::DeviceInterface::Processor, "maxSpeed", 3201) | Solid::Predicate(Solid::DeviceInterface::Processor, "canChangeFrequency", false); Solid::Predicate p5 = Solid::Predicate::fromString("[[Processor.maxSpeed == 3201 AND Processor.canChangeFrequency == false] OR StorageVolume.mountPoint == '/media/blup']"); QVERIFY(p1.matches(dev)); QVERIFY(!p2.matches(dev)); QVERIFY(p3.matches(dev)); QVERIFY(!p4.matches(dev)); Solid::Predicate p6 = Solid::Predicate::fromString("StorageVolume.usage == 'Other'"); Solid::Predicate p7 = Solid::Predicate::fromString(QString("StorageVolume.usage == %1").arg((int)Solid::StorageVolume::Other)); QVERIFY(!p6.matches(dev)); QVERIFY(!p7.matches(dev)); dev = Solid::Device("/org/kde/solid/fakehw/volume_part2_size_1024"); QVERIFY(p6.matches(dev)); QVERIFY(p7.matches(dev)); Solid::Predicate p8 = Solid::Predicate::fromString("AudioInterface.deviceType == 'AudioInput|AudioOutput'"); Solid::Predicate p9 = Solid::Predicate::fromString("AudioInterface.deviceType == 'AudioInput'"); Solid::Predicate p10 = Solid::Predicate::fromString("AudioInterface.deviceType & 'AudioInput'"); Solid::Predicate p11 = Solid::Predicate::fromString("AudioInterface.deviceType & 'foobar'"); QVERIFY(!p8.matches(dev)); QVERIFY(!p9.matches(dev)); QVERIFY(!p10.matches(dev)); QVERIFY(!p11.matches(dev)); dev = Solid::Device("/org/kde/solid/fakehw/pci_8086_266e_oss_pcm_0"); QVERIFY(p8.matches(dev)); QVERIFY(!p9.matches(dev)); QVERIFY(p10.matches(dev)); QVERIFY(!p11.matches(dev)); QString str_pred = "[[Processor.maxSpeed == 3201 AND Processor.canChangeFrequency == false] OR StorageVolume.mountPoint == '/media/blup']"; // Since str_pred is canonicalized, fromString().toString() should be invariant QCOMPARE(Solid::Predicate::fromString(str_pred).toString(), str_pred); // Invalid predicate str_pred = "[StorageVolume.ignored == false AND OpticalDisc.isBlank == true AND OpticalDisc.discType & 'CdRecordable|CdRewritable']"; QVERIFY(!Solid::Predicate::fromString(str_pred).isValid()); QString parentUdi = "/org/kde/solid/fakehw/storage_model_solid_reader"; Solid::DeviceInterface::Type ifaceType = Solid::DeviceInterface::Unknown; QCOMPARE(fakeManager->devicesFromQuery(parentUdi, ifaceType).size(), 1); QCOMPARE(fakeManager->devicesFromQuery(parentUdi, ifaceType).at(0), QString("/org/kde/solid/fakehw/volume_label_SOLIDMAN_BEGINS")); ifaceType = Solid::DeviceInterface::Processor; QCOMPARE(fakeManager->devicesFromQuery(parentUdi, ifaceType).size(), 0); parentUdi = "/org/kde/solid/fakehw/computer"; QCOMPARE(fakeManager->devicesFromQuery(parentUdi, ifaceType).size(), 2); QCOMPARE(fakeManager->devicesFromQuery(parentUdi, ifaceType).at(0), QString("/org/kde/solid/fakehw/acpi_CPU0")); QCOMPARE(fakeManager->devicesFromQuery(parentUdi, ifaceType).at(1), QString("/org/kde/solid/fakehw/acpi_CPU1")); parentUdi.clear(); ifaceType = Solid::DeviceInterface::Unknown; QList list; list = Solid::Device::listFromQuery(p1, parentUdi); QCOMPARE(list.size(), 2); QCOMPARE(list.at(0).udi(), QString("/org/kde/solid/fakehw/acpi_CPU0")); QCOMPARE(list.at(1).udi(), QString("/org/kde/solid/fakehw/acpi_CPU1")); list = Solid::Device::listFromQuery(p2, parentUdi); QCOMPARE(list.size(), 0); list = Solid::Device::listFromQuery(p3, parentUdi); QCOMPARE(list.size(), 2); QCOMPARE(list.at(0).udi(), QString("/org/kde/solid/fakehw/acpi_CPU0")); QCOMPARE(list.at(1).udi(), QString("/org/kde/solid/fakehw/acpi_CPU1")); list = Solid::Device::listFromQuery(p4, parentUdi); QCOMPARE(list.size(), 0); list = Solid::Device::listFromQuery("[Processor.canChangeFrequency==true AND Processor.number==1]", parentUdi); QCOMPARE(list.size(), 1); QCOMPARE(list.at(0).udi(), QString("/org/kde/solid/fakehw/acpi_CPU1")); list = Solid::Device::listFromQuery("[Processor.number==1 OR IS StorageVolume]", parentUdi); QCOMPARE(list.size(), 10); //make sure predicate case-insensitiveness is sane list = Solid::Device::listFromQuery("[Processor.number==1 or is StorageVolume]", parentUdi); QCOMPARE(list.size(), 10); list = Solid::Device::listFromQuery("[Processor.number==1 oR Is StorageVolume]", parentUdi); QCOMPARE(list.size(), 10); QSet set; QCOMPARE(list.size(), 10); set << "/org/kde/solid/fakehw/acpi_CPU1" << "/org/kde/solid/fakehw/platform_floppy_0_storage_virt_volume" << "/org/kde/solid/fakehw/volume_label_SOLIDMAN_BEGINS" << "/org/kde/solid/fakehw/volume_part1_size_993284096" << "/org/kde/solid/fakehw/volume_part2_size_1024" << "/org/kde/solid/fakehw/volume_part5_size_1048576" << "/org/kde/solid/fakehw/volume_uuid_5011" << "/org/kde/solid/fakehw/volume_uuid_c0ffee" << "/org/kde/solid/fakehw/volume_uuid_f00ba7" << "/org/kde/solid/fakehw/volume_uuid_feedface"; QCOMPARE(set, to_string_set(list)); list = Solid::Device::listFromQuery("[IS Processor OR IS StorageVolume]", parentUdi); QCOMPARE(list.size(), 11); set << "/org/kde/solid/fakehw/acpi_CPU0"; QCOMPARE(set, to_string_set(list)); ifaceType = Solid::DeviceInterface::Processor; list = Solid::Device::listFromType(ifaceType, parentUdi); QCOMPARE(list.size(), 2); QCOMPARE(list.at(0).udi(), QString("/org/kde/solid/fakehw/acpi_CPU0")); QCOMPARE(list.at(1).udi(), QString("/org/kde/solid/fakehw/acpi_CPU1")); ifaceType = Solid::DeviceInterface::Unknown; list = Solid::Device::listFromQuery("blup", parentUdi); QCOMPARE(list.size(), 0); } void SolidHwTest::testSetupTeardown() { Solid::StorageAccess *access; { Solid::Device device("/org/kde/solid/fakehw/volume_part1_size_993284096"); access = device.as(); } QList args; QSignalSpy spy(access, SIGNAL(accessibilityChanged(bool,QString))); access->teardown(); QCOMPARE(spy.count(), 1); args = spy.takeFirst(); QCOMPARE(args.at(0).toBool(), false); access->setup(); QCOMPARE(spy.count(), 1); args = spy.takeFirst(); QCOMPARE(args.at(0).toBool(), true); } void SolidHwTest::slotPropertyChanged(const QMap &changes) { m_changesList << changes; } #include "moc_solidhwtest.cpp"