/* * SPDX-FileCopyrightText: 2019 Manuel Weichselbaumer * * SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL */ #include "mediatransporttest.h" #include "a2dp-codecs.h" #include "autotests.h" #include "initmanagerjob.h" #include "pendingcall.h" #include "services.h" #include #include namespace BluezQt { extern void bluezqt_initFakeBluezTestRun(); } using namespace BluezQt; Q_DECLARE_METATYPE(MediaTransport::State) static a2dp_sbc_t sbcConfiguration; static a2dp_aac_t aacConfiguration; static AudioCodec charToCodec(uchar value) { switch (value) { case A2DP_CODEC_SBC: return AudioCodec::Sbc; break; case A2DP_CODEC_MPEG24: return AudioCodec::Aac; break; } return AudioCodec::Invalid; } static AudioSampleRate byteArrayToSampleRate(AudioCodec codec, const QByteArray &buffer) { switch (codec) { case AudioCodec::Sbc: { if (buffer.size() != sizeof(a2dp_sbc_t)) { return AudioSampleRate::Invalid; } a2dp_sbc_t sbcConfig = *reinterpret_cast(buffer.constData()); switch (sbcConfig.frequency) { case SBC_SAMPLING_FREQ_44100: return AudioSampleRate::Rate44100; break; case SBC_SAMPLING_FREQ_48000: return AudioSampleRate::Rate48000; break; } break; } case AudioCodec::Aac: { if (buffer.size() != sizeof(a2dp_aac_t)) { return AudioSampleRate::Invalid; } a2dp_aac_t aacConfig = *reinterpret_cast(buffer.constData()); switch (AAC_GET_FREQUENCY(aacConfig)) { case AAC_SAMPLING_FREQ_44100: return AudioSampleRate::Rate44100; break; case AAC_SAMPLING_FREQ_48000: return AudioSampleRate::Rate48000; break; } break; } } return AudioSampleRate::Invalid; } QString stateString(MediaTransport::State state) { switch (state) { case MediaTransport::State::Idle: return QStringLiteral("idle"); case MediaTransport::State::Pending: return QStringLiteral("pending"); case MediaTransport::State::Active: return QStringLiteral("active"); } return {}; } MediaTransportTest::MediaTransportTest() : m_manager(nullptr) { Autotests::registerMetatypes(); qRegisterMetaType("State"); sbcConfiguration.frequency = SBC_SAMPLING_FREQ_44100; AAC_SET_FREQUENCY(aacConfiguration, AAC_SAMPLING_FREQ_48000); } void MediaTransportTest::initTestCase() { bluezqt_initFakeBluezTestRun(); FakeBluez::start(); FakeBluez::runTest(QStringLiteral("bluez-standard")); // Create adapter QString adapter = QStringLiteral("/org/bluez/hci0"); QVariantMap adapterProps; adapterProps[QStringLiteral("Path")] = QVariant::fromValue(QDBusObjectPath(adapter)); adapterProps[QStringLiteral("Address")] = QStringLiteral("1C:E5:C3:BC:94:7E"); adapterProps[QStringLiteral("Name")] = QStringLiteral("TestAdapter"); FakeBluez::runAction(QStringLiteral("devicemanager"), QStringLiteral("create-adapter"), adapterProps); // Create devices QVariantMap deviceProps; QVariantMap mediaTransportProps; QString device1 = adapter + QLatin1String("/dev_40_79_6A_0C_39_75"); deviceProps[QStringLiteral("Path")] = QVariant::fromValue(QDBusObjectPath(device1)); deviceProps[QStringLiteral("Adapter")] = QVariant::fromValue(QDBusObjectPath(adapter)); deviceProps[QStringLiteral("Address")] = QStringLiteral("40:79:6A:0C:39:75"); deviceProps[QStringLiteral("Name")] = QStringLiteral("TestDevice"); deviceProps[QStringLiteral("UUIDs")] = QStringList(Services::AudioSink); mediaTransportProps[QStringLiteral("Path")] = QVariant::fromValue(QDBusObjectPath(device1 + QLatin1String("/fd0"))); mediaTransportProps[QStringLiteral("Device")] = QVariant::fromValue(QDBusObjectPath(device1)); mediaTransportProps[QStringLiteral("UUID")] = Services::AudioSink; mediaTransportProps[QStringLiteral("Codec")] = QVariant::fromValue(quint8(A2DP_CODEC_SBC)); // SBC mediaTransportProps[QStringLiteral("Configuration")] = QVariant::fromValue(QByteArray(reinterpret_cast(&sbcConfiguration), sizeof(sbcConfiguration))); mediaTransportProps[QStringLiteral("State")] = QStringLiteral("pending"); mediaTransportProps[QStringLiteral("Volume")] = QVariant::fromValue(quint16(63)); deviceProps[QStringLiteral("MediaTransport")] = mediaTransportProps; FakeBluez::runAction(QStringLiteral("devicemanager"), QStringLiteral("create-device"), deviceProps); QString device2 = adapter + QLatin1String("/dev_50_79_6A_0C_39_75"); deviceProps[QStringLiteral("Path")] = QVariant::fromValue(QDBusObjectPath(device2)); deviceProps[QStringLiteral("Adapter")] = QVariant::fromValue(QDBusObjectPath(adapter)); deviceProps[QStringLiteral("Address")] = QStringLiteral("50:79:6A:0C:39:75"); deviceProps[QStringLiteral("Name")] = QStringLiteral("TestDevice2"); deviceProps[QStringLiteral("UUIDs")] = QStringList(Services::AudioSink); mediaTransportProps[QStringLiteral("Path")] = QVariant::fromValue(QDBusObjectPath(device2 + QLatin1String("/fd0"))); mediaTransportProps[QStringLiteral("Device")] = QVariant::fromValue(QDBusObjectPath(device2)); mediaTransportProps[QStringLiteral("UUID")] = Services::AudioSink; mediaTransportProps[QStringLiteral("Codec")] = QVariant::fromValue(quint8(A2DP_CODEC_MPEG24)); // AAC mediaTransportProps[QStringLiteral("Configuration")] = QVariant::fromValue(QByteArray(reinterpret_cast(&aacConfiguration), sizeof(aacConfiguration))); mediaTransportProps[QStringLiteral("State")] = QStringLiteral("active"); mediaTransportProps[QStringLiteral("Volume")] = QVariant::fromValue(quint16(127)); deviceProps[QStringLiteral("MediaTransport")] = mediaTransportProps; FakeBluez::runAction(QStringLiteral("devicemanager"), QStringLiteral("create-device"), deviceProps); m_manager = new Manager(); InitManagerJob *initJob = m_manager->init(); initJob->exec(); QVERIFY(!initJob->error()); QCOMPARE(m_manager->adapters().count(), 1); QCOMPARE(m_manager->devices().count(), 2); } void MediaTransportTest::cleanupTestCase() { for (const MediaTransportUnit &unit : m_units) { delete unit.dbusMediaTransport; delete unit.dbusProperties; } delete m_manager; FakeBluez::stop(); } void MediaTransportTest::connectTest() { for (DevicePtr device : m_manager->devices()) { QVERIFY(!device->ubi().isEmpty()); QVERIFY(!device->mediaTransport()); QSignalSpy deviceSpy(device.data(), SIGNAL(mediaTransportChanged(MediaTransportPtr))); device->connectToDevice(); QTRY_COMPARE(deviceSpy.count(), 1); QVERIFY(device->mediaTransport()); } } void MediaTransportTest::disconnectTest() { for (DevicePtr device : m_manager->devices()) { QVERIFY(device->mediaTransport()); QSignalSpy deviceSpy(device.data(), SIGNAL(mediaTransportChanged(MediaTransportPtr))); device->disconnectFromDevice(); QTRY_COMPARE(deviceSpy.count(), 1); QVERIFY(!device->mediaTransport()); } } void MediaTransportTest::connectProfileTest() { QDBusConnection connection = QDBusConnection::sessionBus(); QString service = QStringLiteral("org.kde.bluezqt.fakebluez"); for (DevicePtr device : m_manager->devices()) { QVERIFY(!device->ubi().isEmpty()); QVERIFY(!device->mediaTransport()); QSignalSpy deviceSpy(device.data(), SIGNAL(mediaTransportChanged(MediaTransportPtr))); device->connectProfile(Services::AudioSink); QTRY_COMPARE(deviceSpy.count(), 1); QVERIFY(device->mediaTransport()); QString path = device->ubi() + QLatin1String("/fd0"); MediaTransportUnit unit; unit.device = device; unit.dbusMediaTransport = new org::bluez::MediaTransport1(service, path, connection, this); unit.dbusProperties = new org::freedesktop::DBus::Properties(service, path, connection, this); m_units.append(unit); } } void MediaTransportTest::getPropertiesTest() { for (const MediaTransportUnit &unit : m_units) { QCOMPARE(unit.device->mediaTransport()->audioConfiguration().codec, charToCodec(unit.dbusMediaTransport->codec())); QCOMPARE(unit.device->mediaTransport()->audioConfiguration().sampleRate, byteArrayToSampleRate(unit.device->mediaTransport()->audioConfiguration().codec, unit.dbusMediaTransport->configuration())); QCOMPARE(stateString(unit.device->mediaTransport()->state()), unit.dbusMediaTransport->state()); QCOMPARE(unit.device->mediaTransport()->volume(), unit.dbusMediaTransport->volume()); } } void MediaTransportTest::disconnectProfileTest() { for (const MediaTransportUnit &unit : m_units) { QVERIFY(unit.device->mediaTransport()); QSignalSpy deviceSpy(unit.device.data(), SIGNAL(mediaTransportChanged(MediaTransportPtr))); unit.device->disconnectProfile(Services::AudioSink); QTRY_COMPARE(deviceSpy.count(), 1); QVERIFY(!unit.device->mediaTransport()); } } QTEST_MAIN(MediaTransportTest) #include "moc_mediatransporttest.cpp"