From e070138e4bfda99cde5f67f3542f3d79604c5d6d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20St=C3=BCrz?= Date: Wed, 23 Sep 2015 14:44:18 +0200 Subject: [PATCH] add tests for push button mock device --- libguh/devicemanager.cpp | 1 + .../deviceplugins/mock/devicepluginmock.cpp | 57 ++++++--- server/rest/devicesresource.cpp | 16 ++- tests/auto/devices/testdevices.cpp | 68 ++++++++++ tests/auto/guhtestbase.cpp | 1 + tests/auto/guhtestbase.h | 1 + tests/auto/restdevices/testrestdevices.cpp | 118 ++++++++++++++++++ 7 files changed, 233 insertions(+), 29 deletions(-) diff --git a/libguh/devicemanager.cpp b/libguh/devicemanager.cpp index f45e60c3..57c5792b 100644 --- a/libguh/devicemanager.cpp +++ b/libguh/devicemanager.cpp @@ -599,6 +599,7 @@ DeviceManager::DeviceError DeviceManager::confirmPairing(const PairingTransactio switch (status) { case DeviceSetupStatusSuccess: m_pairingsDiscovery.remove(pairingTransactionId); + // TODO: setup the device if the pairing status can be fetched directly return DeviceErrorNoError; case DeviceSetupStatusFailure: m_pairingsDiscovery.remove(pairingTransactionId); diff --git a/plugins/deviceplugins/mock/devicepluginmock.cpp b/plugins/deviceplugins/mock/devicepluginmock.cpp index 3469c6a1..f7d8d888 100644 --- a/plugins/deviceplugins/mock/devicepluginmock.cpp +++ b/plugins/deviceplugins/mock/devicepluginmock.cpp @@ -27,6 +27,7 @@ #include "plugininfo.h" #include +#include #include @@ -137,7 +138,7 @@ DeviceManager::DeviceSetupStatus DevicePluginMock::confirmPairing(const PairingT return DeviceManager::DeviceSetupStatusFailure; } if (!m_pushbuttonPressed) { - qCDebug(dcMockDevice) << "Push button not pressed yet!"; + qCDebug(dcMockDevice) << "PushButton not pressed yet!"; return DeviceManager::DeviceSetupStatusFailure; } @@ -161,21 +162,38 @@ QList DevicePluginMock::configurationDescription() const DeviceManager::DeviceError DevicePluginMock::executeAction(Device *device, const Action &action) { - if (!myDevices().contains(device)) - return DeviceManager::DeviceErrorDeviceNotFound; + if (device->deviceClassId() == mockDeviceClassId || device->deviceClassId() == mockDeviceAutoDeviceClassId) { + if (!myDevices().contains(device)) + return DeviceManager::DeviceErrorDeviceNotFound; - if (action.actionTypeId() == mockAsyncActionTypeId || action.actionTypeId() == mockAsyncFailingActionTypeId) { - m_asyncActions.append(qMakePair(action, device)); - QTimer::singleShot(1000, this, SLOT(emitActionExecuted())); - return DeviceManager::DeviceErrorAsync; + if (action.actionTypeId() == mockAsyncActionTypeId || action.actionTypeId() == mockAsyncFailingActionTypeId) { + m_asyncActions.append(qMakePair(action, device)); + QTimer::singleShot(1000, this, SLOT(emitActionExecuted())); + return DeviceManager::DeviceErrorAsync; + } + + if (action.actionTypeId() == mockFailingActionTypeId) + return DeviceManager::DeviceErrorSetupFailed; + + m_daemons.value(device)->actionExecuted(action.actionTypeId()); + return DeviceManager::DeviceErrorNoError; + } else if (device->deviceClassId() == mockPushButtonDeviceClassId) { + if (action.actionTypeId() == colorActionTypeId) { + QString colorString = action.param("color").value().toString(); + QColor color(colorString); + if (!color.isValid()) { + qCWarning(dcMockDevice) << "Invalid color parameter"; + return DeviceManager::DeviceErrorInvalidParameter; + } + device->setStateValue(colorStateTypeId, colorString); + return DeviceManager::DeviceErrorNoError; + } else if (action.actionTypeId() == percentageActionTypeId) { + device->setStateValue(percentageStateTypeId, action.param("percentage").value().toInt()); + return DeviceManager::DeviceErrorNoError; + } + return DeviceManager::DeviceErrorActionTypeNotFound; } - - if (action.actionTypeId() == mockFailingActionTypeId) - return DeviceManager::DeviceErrorSetupFailed; - - - m_daemons.value(device)->actionExecuted(action.actionTypeId()); - return DeviceManager::DeviceErrorNoError; + return DeviceManager::DeviceErrorDeviceClassNotFound; } void DevicePluginMock::setState(const StateTypeId &stateTypeId, const QVariant &value) @@ -191,9 +209,8 @@ void DevicePluginMock::setState(const StateTypeId &stateTypeId, const QVariant & void DevicePluginMock::triggerEvent(const EventTypeId &id) { HttpDaemon *daemon = qobject_cast(sender()); - if (!daemon) { + if (!daemon) return; - } Device *device = m_daemons.key(daemon); @@ -253,23 +270,23 @@ void DevicePluginMock::emitPushButtonDevicesDiscovered() d2.setParams(params); deviceDescriptors.append(d2); } + emit devicesDiscovered(mockPushButtonDeviceClassId, deviceDescriptors); m_pushbuttonPressed = false; QTimer::singleShot(3000, this, SLOT(onPushButtonPressed())); qDebug() << "Start PushButton timer (will be pressed in 3 second)"; - emit devicesDiscovered(mockPushButtonDeviceClassId, deviceDescriptors); } void DevicePluginMock::onPushButtonPressed() { - qCDebug(dcMockDevice) << "PushButton pressed"; + qCDebug(dcMockDevice) << "PushButton pressed (automatically)"; m_pushbuttonPressed = true; } void DevicePluginMock::emitDeviceSetupFinished() { - qCDebug(dcMockDevice) << "emitting setup finised"; + qCDebug(dcMockDevice) << "Emitting setup finised"; Device *device = m_asyncSetupDevices.takeFirst(); if (device->paramValue("broken").toBool()) { emit deviceSetupFinished(device, DeviceManager::DeviceSetupStatusFailure); @@ -291,6 +308,6 @@ void DevicePluginMock::emitActionExecuted() void DevicePluginMock::onPushButtonPairingFinished() { - qCDebug(dcMockDevice) << "Pairing finished"; + qCDebug(dcMockDevice) << "Pairing PushButton Device finished"; emit pairingFinished(m_pairingId, DeviceManager::DeviceSetupStatusSuccess); } diff --git a/server/rest/devicesresource.cpp b/server/rest/devicesresource.cpp index add8b938..13d33ca5 100644 --- a/server/rest/devicesresource.cpp +++ b/server/rest/devicesresource.cpp @@ -500,18 +500,16 @@ void DevicesResource::pairingFinished(const PairingTransactionId &pairingTransac return; // Not the device pairing we are waiting for. HttpReply *reply = m_asyncPairingRequests.take(pairingTransactionId); - if (status == DeviceManager::DeviceErrorNoError) { - qCDebug(dcRest) << "Pairing device finished successfully"; - QVariant result = JsonTypes::packDevice(GuhCore::instance()->findConfiguredDevice(deviceId)); - reply->setHeader(HttpReply::ContentTypeHeader, "application/json; charset=\"utf-8\";"); - reply->setPayload(QJsonDocument::fromVariant(result).toJson()); - reply->setHttpStatusCode(HttpReply::Ok); - } else { - qCDebug(dcRest) << "Pairing device finished with error" << status; + if (status != DeviceManager::DeviceErrorNoError) { + qCDebug(dcRest) << "Pairing device finished with error."; reply->setHttpStatusCode(HttpReply::InternalServerError); + reply->finished(); + return; } + qCDebug(dcRest) << "Pairing device finished successfully"; - reply->finished(); + // Add device to async device addtions + m_asyncDeviceAdditions.insert(deviceId, reply); } } diff --git a/tests/auto/devices/testdevices.cpp b/tests/auto/devices/testdevices.cpp index 13e585ed..5a86a9dd 100644 --- a/tests/auto/devices/testdevices.cpp +++ b/tests/auto/devices/testdevices.cpp @@ -61,6 +61,9 @@ private slots: void discoverDevices_data(); void discoverDevices(); + void addPushButtonDevices_data(); + void addPushButtonDevices(); + void getActionTypes_data(); void getActionTypes(); @@ -398,6 +401,71 @@ void TestDevices::discoverDevices() } } +void TestDevices::addPushButtonDevices_data() +{ + QTest::addColumn("deviceClassId"); + QTest::addColumn("error"); + QTest::addColumn("waitForButtonPressed"); + + QTest::newRow("Valid: Add PushButton device") << mockPushButtonDeviceClassId << DeviceManager::DeviceErrorNoError << true; + QTest::newRow("Invalid: Add PushButton device (press to early)") << mockPushButtonDeviceClassId << DeviceManager::DeviceErrorSetupFailed << false; +} + +void TestDevices::addPushButtonDevices() +{ + QFETCH(DeviceClassId, deviceClassId); + QFETCH(DeviceManager::DeviceError, error); + QFETCH(bool, waitForButtonPressed); + + // Discover device + QVariantList discoveryParams; + QVariantMap resultCountParam; + resultCountParam.insert("name", "resultCount"); + resultCountParam.insert("value", 1); + discoveryParams.append(resultCountParam); + + QVariantMap params; + params.insert("deviceClassId", deviceClassId); + params.insert("discoveryParams", discoveryParams); + QVariant response = injectAndWait("Devices.GetDiscoveredDevices", params); + + verifyDeviceError(response, DeviceManager::DeviceErrorNoError); + QCOMPARE(response.toMap().value("params").toMap().value("deviceDescriptors").toList().count(), 1); + + + // Pair device + DeviceDescriptorId descriptorId = DeviceDescriptorId(response.toMap().value("params").toMap().value("deviceDescriptors").toList().first().toMap().value("id").toString()); + params.clear(); + params.insert("deviceClassId", deviceClassId); + params.insert("deviceDescriptorId", descriptorId.toString()); + response = injectAndWait("Devices.PairDevice", params); + + verifyDeviceError(response); + + PairingTransactionId pairingTransactionId(response.toMap().value("params").toMap().value("pairingTransactionId").toString()); + QString displayMessage = response.toMap().value("params").toMap().value("displayMessage").toString(); + + qDebug() << "displayMessage" << displayMessage; + + if (waitForButtonPressed) + QTest::qWait(3500); + + // Confirm pairing + params.clear(); + params.insert("pairingTransactionId", pairingTransactionId.toString()); + response = injectAndWait("Devices.ConfirmPairing", params); + + verifyDeviceError(response, error); + + if (error == DeviceManager::DeviceErrorNoError) { + DeviceId deviceId(response.toMap().value("params").toMap().value("deviceId").toString()); + params.clear(); + params.insert("deviceId", deviceId.toString()); + response = injectAndWait("Devices.RemoveConfiguredDevice", params); + verifyDeviceError(response); + } +} + void TestDevices::getActionTypes_data() { QTest::addColumn("deviceClassId"); diff --git a/tests/auto/guhtestbase.cpp b/tests/auto/guhtestbase.cpp index 7f156200..28725f0b 100644 --- a/tests/auto/guhtestbase.cpp +++ b/tests/auto/guhtestbase.cpp @@ -40,6 +40,7 @@ PluginId mockPluginId = PluginId("727a4a9a-c187-446f-aadf-f1b2220607d1"); VendorId guhVendorId = VendorId("2062d64d-3232-433c-88bc-0d33c0ba2ba6"); DeviceClassId mockDeviceClassId = DeviceClassId("753f0d32-0468-4d08-82ed-1964aab03298"); DeviceClassId mockDeviceAutoClassId = DeviceClassId("ab4257b3-7548-47ee-9bd4-7dc3004fd197"); +DeviceClassId mockPushButtonDeviceClassId = DeviceClassId("9e03144c-e436-4eea-82d9-ccb33ef778db"); DeviceClassId mockDeviceDiscoveryClassId = DeviceClassId("1bbaf751-36b7-4d3d-b05a-58dab2a3be8c"); DeviceClassId mockDeviceAsyncSetupClassId = DeviceClassId("c08a8b27-8200-413d-b96b-4cff78b864d9"); DeviceClassId mockDeviceBrokenClassId = DeviceClassId("ba5fb404-c9ce-4db4-8cd4-f48c61c24b13"); diff --git a/tests/auto/guhtestbase.h b/tests/auto/guhtestbase.h index 212d7bc3..746dadbf 100644 --- a/tests/auto/guhtestbase.h +++ b/tests/auto/guhtestbase.h @@ -36,6 +36,7 @@ extern DeviceClassId mockDeviceClassId; extern DeviceClassId mockDeviceAutoClassId; +extern DeviceClassId mockPushButtonDeviceClassId; extern DeviceClassId mockDeviceDiscoveryClassId; extern DeviceClassId mockDeviceAsyncSetupClassId; extern DeviceClassId mockDeviceBrokenClassId; diff --git a/tests/auto/restdevices/testrestdevices.cpp b/tests/auto/restdevices/testrestdevices.cpp index 80cac772..bc08517b 100644 --- a/tests/auto/restdevices/testrestdevices.cpp +++ b/tests/auto/restdevices/testrestdevices.cpp @@ -47,6 +47,9 @@ private slots: void addConfiguredDevice_data(); void addConfiguredDevice(); + void addPushButtonDevices_data(); + void addPushButtonDevices(); + void executeAction_data(); void executeAction(); @@ -217,6 +220,121 @@ void TestRestDevices::addConfiguredDevice() nam->deleteLater(); } +void TestRestDevices::addPushButtonDevices_data() +{ + QTest::addColumn("deviceClassId"); + QTest::addColumn("expectedStatusCode"); + QTest::addColumn("waitForButtonPressed"); + + QTest::newRow("Valid: Add PushButton device") << mockPushButtonDeviceClassId << 200 << true; + QTest::newRow("Invalid: Add PushButton device (press to early)") << mockPushButtonDeviceClassId << 500 << false; +} + +void TestRestDevices::addPushButtonDevices() +{ + QFETCH(DeviceClassId, deviceClassId); + QFETCH(int, expectedStatusCode); + QFETCH(bool, waitForButtonPressed); + + // Discover device + QVariantList discoveryParams; + QVariantMap resultCountParam; + resultCountParam.insert("name", "resultCount"); + resultCountParam.insert("value", 1); + discoveryParams.append(resultCountParam); + + // Discover + QVariantMap params; + params.insert("deviceClassId", deviceClassId); + params.insert("discoveryParams", discoveryParams); + + QNetworkAccessManager *nam = new QNetworkAccessManager(this); + QSignalSpy clientSpy(nam, SIGNAL(finished(QNetworkReply*))); + + QUrl url(QString("http://localhost:3333/api/v1/deviceclasses/%1/discover").arg(deviceClassId.toString())); + + QUrlQuery query; + query.addQueryItem("params", QJsonDocument::fromVariant(discoveryParams).toJson(QJsonDocument::Compact)); + url.setQuery(query); + + clientSpy.clear(); + QNetworkRequest request(url); + QNetworkReply *reply = nam->get(request); + clientSpy.wait(); + QCOMPARE(clientSpy.count(), 1); + int statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); + QCOMPARE(statusCode, 200); + QByteArray data = reply->readAll(); + reply->deleteLater(); + + // check response + QJsonParseError error; + QJsonDocument jsonDoc = QJsonDocument::fromJson(data, &error); + QCOMPARE(error.error, QJsonParseError::NoError); + QVariantList foundDevices = jsonDoc.toVariant().toList(); + QCOMPARE(foundDevices.count(), 1); + + DeviceDescriptorId deviceDescriptoId(foundDevices.first().toMap().value("id").toString()); + + // Pair + params.clear(); + params.insert("deviceClassId", deviceClassId.toString()); + params.insert("deviceDescriptorId", deviceDescriptoId); + + QNetworkRequest pairRequest(QUrl("http://localhost:3333/api/v1/devices/pair")); + clientSpy.clear(); + reply = nam->post(pairRequest, QJsonDocument::fromVariant(params).toJson(QJsonDocument::Compact)); + clientSpy.wait(); + QCOMPARE(clientSpy.count(), 1); + statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); + QCOMPARE(statusCode, 200); + data = reply->readAll(); + reply->deleteLater(); + + + // check response + jsonDoc = QJsonDocument::fromJson(data, &error); + QCOMPARE(error.error, QJsonParseError::NoError); + PairingTransactionId pairingTransactionId(jsonDoc.toVariant().toMap().value("pairingTransactionId").toString()); + QString displayMessage = jsonDoc.toVariant().toMap().value("displayMessage").toString(); + + qDebug() << "displayMessage" << displayMessage; + + if (waitForButtonPressed) + QTest::qWait(3500); + + // Confirm pairing + params.clear(); + params.insert("pairingTransactionId", pairingTransactionId.toString()); + + QNetworkRequest confirmPairingRequest(QUrl("http://localhost:3333/api/v1/devices/confirmpairing")); + clientSpy.clear(); + reply = nam->post(confirmPairingRequest, QJsonDocument::fromVariant(params).toJson(QJsonDocument::Compact)); + clientSpy.wait(); + QCOMPARE(clientSpy.count(), 1); + statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); + QCOMPARE(statusCode, expectedStatusCode); + data = reply->readAll(); + reply->deleteLater(); + + if (expectedStatusCode == 200) { + jsonDoc = QJsonDocument::fromJson(data, &error); + QCOMPARE(error.error, QJsonParseError::NoError); + + DeviceId deviceId(jsonDoc.toVariant().toMap().value("id").toString()); + // delete it + request.setUrl(QUrl(QString("http://localhost:3333/api/v1/devices/%1").arg(deviceId.toString()))); + clientSpy.clear(); + reply = nam->deleteResource(request); + clientSpy.wait(); + QCOMPARE(clientSpy.count(), 1); + statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); + reply->deleteLater(); + QCOMPARE(statusCode, 200); + } + nam->deleteLater(); +} + void TestRestDevices::executeAction_data() { QTest::addColumn("deviceId");