From 8b0e279c0cb66ea945fda20382209ddbcd42f9d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20St=C3=BCrz?= Date: Fri, 31 Jul 2015 00:03:07 +0200 Subject: [PATCH] add more tests for REST resources --- server/rest/devicesresource.cpp | 2 +- server/rest/pluginsresource.cpp | 5 +- server/rest/restserver.cpp | 90 ++--- server/rest/restserver.h | 2 + tests/auto/auto.pro | 15 +- .../restdeviceclasses/restdeviceclasses.pro | 5 + .../testrestdeviceclasses.cpp | 317 ++++++++++++++++++ tests/auto/restplugins/restplugins.pro | 5 + tests/auto/restplugins/temp | 0 tests/auto/restplugins/testrestplugins.cpp | 239 +++++++++++++ tests/auto/restvendors/restvendors.pro | 5 + tests/auto/restvendors/temp | 0 tests/auto/restvendors/testrestvendors.cpp | 92 +++++ 13 files changed, 704 insertions(+), 73 deletions(-) create mode 100644 tests/auto/restdeviceclasses/restdeviceclasses.pro create mode 100644 tests/auto/restdeviceclasses/testrestdeviceclasses.cpp create mode 100644 tests/auto/restplugins/restplugins.pro create mode 100644 tests/auto/restplugins/temp create mode 100644 tests/auto/restplugins/testrestplugins.cpp create mode 100644 tests/auto/restvendors/restvendors.pro create mode 100644 tests/auto/restvendors/temp create mode 100644 tests/auto/restvendors/testrestvendors.cpp diff --git a/server/rest/devicesresource.cpp b/server/rest/devicesresource.cpp index 5fde6feb..48a82ce1 100644 --- a/server/rest/devicesresource.cpp +++ b/server/rest/devicesresource.cpp @@ -282,7 +282,7 @@ HttpReply *DevicesResource::addConfiguredDevice(const QByteArray &payload) const qCDebug(dcRest) << "Adding device with " << deviceParams; status = GuhCore::instance()->addConfiguredDevice(deviceClassId, deviceParams, newDeviceId); } else { - qCDebug(dcRest) << "Adding discovered device"; + qCDebug(dcRest) << "Adding discovered device with DeviceDescriptorId" << deviceDescriptorId.toString(); status = GuhCore::instance()->addConfiguredDevice(deviceClassId, deviceDescriptorId, newDeviceId); } if (status == DeviceManager::DeviceErrorAsync) { diff --git a/server/rest/pluginsresource.cpp b/server/rest/pluginsresource.cpp index 6a0298c7..bddcf4eb 100644 --- a/server/rest/pluginsresource.cpp +++ b/server/rest/pluginsresource.cpp @@ -150,8 +150,9 @@ HttpReply *PluginsResource::setPluginConfiguration(const PluginId &pluginId, con if (!verification.first) return createErrorReply(HttpReply::BadRequest); - QVariantMap params = verification.second.toMap(); - ParamList pluginParams = JsonTypes::unpackParams(params.value("configuration").toList()); + QVariantList configuration = verification.second.toList(); + ParamList pluginParams = JsonTypes::unpackParams(configuration); + qCDebug(dcRest) << pluginParams; DeviceManager::DeviceError result = GuhCore::instance()->setPluginConfig(pluginId, pluginParams); if (result != DeviceManager::DeviceErrorNoError) diff --git a/server/rest/restserver.cpp b/server/rest/restserver.cpp index c8d26191..29fb9a04 100644 --- a/server/rest/restserver.cpp +++ b/server/rest/restserver.cpp @@ -49,6 +49,12 @@ void RestServer::setup() m_vendorsResource = new VendorsResource(this); m_pluginsResource = new PluginsResource(this); m_rulesResource = new RulesResource(this); + + m_resources.insert(m_deviceResource->name(), m_deviceResource); + m_resources.insert(m_deviceClassesResource->name(), m_deviceClassesResource); + m_resources.insert(m_vendorsResource->name(), m_vendorsResource); + m_resources.insert(m_pluginsResource->name(), m_pluginsResource); + m_resources.insert(m_rulesResource->name(), m_rulesResource); } void RestServer::clientConnected(const QUuid &clientId) @@ -68,91 +74,37 @@ void RestServer::processHttpRequest(const QUuid &clientId, const HttpRequest &re QStringList urlTokens = request.url().path().split("/"); urlTokens.removeAll(QString()); - qCDebug(dcRest) << urlTokens; - + // check token count if (urlTokens.count() < 3) { - HttpReply *reply = new HttpReply(HttpReply::BadRequest, HttpReply::TypeSync, this); + HttpReply *reply = RestResource::createErrorReply(HttpReply::BadRequest); reply->setClientId(clientId); m_webserver->sendHttpReply(reply); reply->deleteLater(); return; } - // TODO: make generic with resource name - - if (urlTokens.at(2) == "devices") { - HttpReply *reply = m_deviceResource->proccessRequest(request, urlTokens); + // check resource + QString resourceName = urlTokens.at(2); + if (!m_resources.contains(resourceName)) { + HttpReply *reply = RestResource::createErrorReply(HttpReply::BadRequest); reply->setClientId(clientId); - if (reply->type() == HttpReply::TypeAsync) { - connect(reply, &HttpReply::finished, this, &RestServer::asyncReplyFinished); - m_asyncReplies.insert(clientId, reply); - reply->startWait(); - return; - } m_webserver->sendHttpReply(reply); reply->deleteLater(); - return; } - if (urlTokens.at(2) == "deviceclasses") { - HttpReply *reply = m_deviceClassesResource->proccessRequest(request, urlTokens); - reply->setClientId(clientId); - if (reply->type() == HttpReply::TypeAsync) { - connect(reply, &HttpReply::finished, this, &RestServer::asyncReplyFinished); - m_asyncReplies.insert(clientId, reply); - reply->startWait(); - return; - } - m_webserver->sendHttpReply(reply); - reply->deleteLater(); + // process request in corresponding resource + RestResource *resource = m_resources.value(resourceName); + HttpReply *reply = resource->proccessRequest(request, urlTokens); + reply->setClientId(clientId); + if (reply->type() == HttpReply::TypeAsync) { + connect(reply, &HttpReply::finished, this, &RestServer::asyncReplyFinished); + m_asyncReplies.insert(clientId, reply); + reply->startWait(); return; } - - if (urlTokens.at(2) == "vendors") { - HttpReply *reply = m_vendorsResource->proccessRequest(request, urlTokens); - reply->setClientId(clientId); - if (reply->type() == HttpReply::TypeAsync) { - connect(reply, &HttpReply::finished, this, &RestServer::asyncReplyFinished); - m_asyncReplies.insert(clientId, reply); - reply->startWait(); - return; - } - m_webserver->sendHttpReply(reply); - reply->deleteLater(); - return; - } - - if (urlTokens.at(2) == "plugins") { - HttpReply *reply = m_pluginsResource->proccessRequest(request, urlTokens); - reply->setClientId(clientId); - if (reply->type() == HttpReply::TypeAsync) { - connect(reply, &HttpReply::finished, this, &RestServer::asyncReplyFinished); - m_asyncReplies.insert(clientId, reply); - reply->startWait(); - return; - } - m_webserver->sendHttpReply(reply); - reply->deleteLater(); - return; - } - - if (urlTokens.at(2) == "rules") { - HttpReply *reply = m_rulesResource->proccessRequest(request, urlTokens); - reply->setClientId(clientId); - if (reply->type() == HttpReply::TypeAsync) { - connect(reply, &HttpReply::finished, this, &RestServer::asyncReplyFinished); - m_asyncReplies.insert(clientId, reply); - reply->startWait(); - return; - } - m_webserver->sendHttpReply(reply); - reply->deleteLater(); - return; - } - - HttpReply *reply = RestResource::createErrorReply(HttpReply::BadRequest); m_webserver->sendHttpReply(reply); reply->deleteLater(); + return; } void RestServer::asyncReplyFinished() diff --git a/server/rest/restserver.h b/server/rest/restserver.h index e7827a94..fb40d5f2 100644 --- a/server/rest/restserver.h +++ b/server/rest/restserver.h @@ -46,6 +46,8 @@ public: private: WebServer *m_webserver; QList m_clientList; + QHash m_resources; + QHash m_asyncReplies; DevicesResource *m_deviceResource; diff --git a/tests/auto/auto.pro b/tests/auto/auto.pro index 07956968..589fbea3 100644 --- a/tests/auto/auto.pro +++ b/tests/auto/auto.pro @@ -1,2 +1,15 @@ TEMPLATE=subdirs -SUBDIRS=versioning devices jsonrpc events states actions rules plugins webserver restdevices + +SUBDIRS=versioning \ + devices \ + jsonrpc \ + events \ + states \ + actions \ + rules \ + plugins \ + webserver \ + restdevices \ + restdeviceclasses \ + restplugins \ + restvendors \ diff --git a/tests/auto/restdeviceclasses/restdeviceclasses.pro b/tests/auto/restdeviceclasses/restdeviceclasses.pro new file mode 100644 index 00000000..887d952e --- /dev/null +++ b/tests/auto/restdeviceclasses/restdeviceclasses.pro @@ -0,0 +1,5 @@ +include(../../../guh.pri) +include(../autotests.pri) + +TARGET = restdeviceclasses +SOURCES += testrestdeviceclasses.cpp diff --git a/tests/auto/restdeviceclasses/testrestdeviceclasses.cpp b/tests/auto/restdeviceclasses/testrestdeviceclasses.cpp new file mode 100644 index 00000000..de2c5598 --- /dev/null +++ b/tests/auto/restdeviceclasses/testrestdeviceclasses.cpp @@ -0,0 +1,317 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * Copyright (C) 2015 Simon Stuerz * + * * + * This file is part of guh. * + * * + * Guh is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, version 2 of the License. * + * * + * Guh 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 General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with guh. If not, see . * + * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +#include "guhtestbase.h" +#include "guhcore.h" +#include "devicemanager.h" +#include "mocktcpserver.h" +#include "webserver.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace guhserver; + +class TestRestDeviceClasses: public GuhTestBase +{ + Q_OBJECT + +private slots: + void getSupportedDevices(); + + void getActionTypes_data(); + void getActionTypes(); + + void getStateTypes_data(); + void getStateTypes(); + + void getEventTypes_data(); + void getEventTypes(); + + void discoverDevices_data(); + void discoverDevices(); + +}; + + + +#include "testrestdeviceclasses.moc" + + +void TestRestDeviceClasses::getSupportedDevices() +{ + QNetworkAccessManager *nam = new QNetworkAccessManager(this); + QSignalSpy clientSpy(nam, SIGNAL(finished(QNetworkReply*))); + + // Get all devices + QNetworkRequest request; + request.setUrl(QUrl("http://localhost:3000/api/v1/deviceclasses")); + QNetworkReply *reply = nam->get(request); + clientSpy.wait(); + QVERIFY2(clientSpy.count() == 1, "expected exactly 1 response from webserver"); + QByteArray data = reply->readAll(); + reply->deleteLater(); + + QJsonParseError error; + QJsonDocument jsonDoc = QJsonDocument::fromJson(data, &error); + QCOMPARE(error.error, QJsonParseError::NoError); + QVariantList deviceClassesList = jsonDoc.toVariant().toList(); + QVERIFY2(deviceClassesList.count() >= 1, "not enought deviceclasses."); + + // Get each of thouse devices individualy + foreach (const QVariant &deviceClass, deviceClassesList) { + QVariantMap deviceClassMap = deviceClass.toMap(); + QNetworkRequest request; + request.setHeader(QNetworkRequest::ContentTypeHeader, "text/json"); + request.setUrl(QUrl(QString("http://localhost:3000/api/v1/deviceclasses/%1").arg(deviceClassMap.value("id").toString()))); + clientSpy.clear(); + QNetworkReply *reply = nam->get(request); + clientSpy.wait(); + QVERIFY2(clientSpy.count() == 1, "expected exactly 1 response from webserver"); + jsonDoc = QJsonDocument::fromJson(reply->readAll(), &error); + QCOMPARE(error.error, QJsonParseError::NoError); + reply->deleteLater(); + } + nam->deleteLater(); +} + +void TestRestDeviceClasses::getActionTypes_data() +{ + QTest::addColumn("deviceClassId"); + QTest::addColumn("actionTypeId"); + QTest::addColumn("expectedStatusCode"); + + QTest::newRow("all ActionTypes") << mockDeviceClassId << ActionTypeId() << 200; + QTest::newRow("ActionType async") << mockDeviceClassId << mockActionIdAsync << 200; + QTest::newRow("ActionType no params") << mockDeviceClassId << mockActionIdNoParams << 200; + QTest::newRow("ActionType failing") << mockDeviceClassId << mockActionIdFailing << 200; + QTest::newRow("ActionType with params") << mockDeviceClassId << mockActionIdWithParams << 200; + QTest::newRow("invalid DeviceClassId") << DeviceClassId::createDeviceClassId() << mockActionIdNoParams << 404; + QTest::newRow("invalid ActionTypeId") << mockDeviceClassId << ActionTypeId::createActionTypeId() << 404; +} + +void TestRestDeviceClasses::getActionTypes() +{ + QFETCH(DeviceClassId, deviceClassId); + QFETCH(ActionTypeId, actionTypeId); + QFETCH(int, expectedStatusCode); + + QNetworkAccessManager *nam = new QNetworkAccessManager(); + QSignalSpy clientSpy(nam, SIGNAL(finished(QNetworkReply*))); + + QNetworkRequest request; + if (!actionTypeId.isNull()) { + request.setUrl(QUrl(QString("http://localhost:3000/api/v1/deviceclasses/%1/actiontypes/%2").arg(deviceClassId.toString()).arg(actionTypeId.toString()))); + } else { + // Get all actiontypes + request.setUrl(QUrl(QString("http://localhost:3000/api/v1/deviceclasses/%1/actiontypes").arg(deviceClassId.toString()))); + } + + QNetworkReply *reply = nam->get(request); + clientSpy.wait(); + QCOMPARE(clientSpy.count(), 1); + int statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); + QCOMPARE(statusCode, expectedStatusCode); + reply->deleteLater(); +} + +void TestRestDeviceClasses::getStateTypes_data() +{ + QTest::addColumn("deviceClassId"); + QTest::addColumn("stateTypeId"); + QTest::addColumn("expectedStatusCode"); + + QTest::newRow("all ActionTypes") << mockDeviceClassId << StateTypeId() << 200; + QTest::newRow("StateType bool") << mockDeviceClassId << mockBoolStateId << 200; + QTest::newRow("StateType int") << mockDeviceClassId << mockIntStateId << 200; + QTest::newRow("invalid DeviceClassId") << DeviceClassId::createDeviceClassId() << mockBoolStateId << 404; + QTest::newRow("invalid StateTypeId") << mockDeviceClassId << StateTypeId::createStateTypeId() << 404; +} + +void TestRestDeviceClasses::getStateTypes() +{ + QFETCH(DeviceClassId, deviceClassId); + QFETCH(StateTypeId, stateTypeId); + QFETCH(int, expectedStatusCode); + + QNetworkAccessManager *nam = new QNetworkAccessManager(); + QSignalSpy clientSpy(nam, SIGNAL(finished(QNetworkReply*))); + + QNetworkRequest request; + if (!stateTypeId.isNull()) { + request.setUrl(QUrl(QString("http://localhost:3000/api/v1/deviceclasses/%1/statetypes/%2").arg(deviceClassId.toString()).arg(stateTypeId.toString()))); + } else { + // Get all actiontypes + request.setUrl(QUrl(QString("http://localhost:3000/api/v1/deviceclasses/%1/statetypes").arg(deviceClassId.toString()))); + } + + QNetworkReply *reply = nam->get(request); + clientSpy.wait(); + QCOMPARE(clientSpy.count(), 1); + int statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); + QCOMPARE(statusCode, expectedStatusCode); + reply->deleteLater(); +} + +void TestRestDeviceClasses::getEventTypes_data() +{ + QTest::addColumn("deviceClassId"); + QTest::addColumn("eventTypeId"); + QTest::addColumn("expectedStatusCode"); + + QTest::newRow("all ActionTypes") << mockDeviceClassId << EventTypeId() << 200; + QTest::newRow("EventType 1") << mockDeviceClassId << mockEvent1Id << 200; + QTest::newRow("EventType 2") << mockDeviceClassId << mockEvent2Id << 200; + QTest::newRow("invalid DeviceClassId") << DeviceClassId::createDeviceClassId() << mockEvent2Id << 404; + QTest::newRow("invalid EventTypeId") << mockDeviceClassId << EventTypeId::createEventTypeId() << 404; +} + +void TestRestDeviceClasses::getEventTypes() +{ + QFETCH(DeviceClassId, deviceClassId); + QFETCH(EventTypeId, eventTypeId); + QFETCH(int, expectedStatusCode); + + QNetworkAccessManager *nam = new QNetworkAccessManager(); + QSignalSpy clientSpy(nam, SIGNAL(finished(QNetworkReply*))); + + QNetworkRequest request; + if (!eventTypeId.isNull()) { + request.setUrl(QUrl(QString("http://localhost:3000/api/v1/deviceclasses/%1/eventtypes/%2").arg(deviceClassId.toString()).arg(eventTypeId.toString()))); + } else { + // Get all actiontypes + request.setUrl(QUrl(QString("http://localhost:3000/api/v1/deviceclasses/%1/eventtypes").arg(deviceClassId.toString()))); + } + + QNetworkReply *reply = nam->get(request); + clientSpy.wait(); + QCOMPARE(clientSpy.count(), 1); + int statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); + QCOMPARE(statusCode, expectedStatusCode); + reply->deleteLater(); +} + +void TestRestDeviceClasses::discoverDevices_data() +{ + QTest::addColumn("deviceClassId"); + QTest::addColumn("resultCount"); + QTest::addColumn("discoveryParams"); + QTest::addColumn("expectedStatusCode"); + + QVariantList discoveryParams; + QVariantMap resultCountParam; + resultCountParam.insert("name", "resultCount"); + resultCountParam.insert("value", 1); + discoveryParams.append(resultCountParam); + + QTest::newRow("valid deviceClassId without params") << mockDeviceClassId << 2 << QVariantList() << 200; + QTest::newRow("valid deviceClassId with params") << mockDeviceClassId << 1 << discoveryParams << 200; + QTest::newRow("invalid deviceClassId") << DeviceClassId::createDeviceClassId() << 0 << QVariantList() << 404; +} + +void TestRestDeviceClasses::discoverDevices() +{ + QFETCH(DeviceClassId, deviceClassId); + QFETCH(int, resultCount); + QFETCH(QVariantList, discoveryParams); + QFETCH(int, expectedStatusCode); + + QVariantMap params; + params.insert("deviceClassId", deviceClassId); + params.insert("discoveryParams", discoveryParams); + + QNetworkAccessManager *nam = new QNetworkAccessManager(); + QSignalSpy clientSpy(nam, SIGNAL(finished(QNetworkReply*))); + + QUrl url(QString("http://localhost:3000/api/v1/deviceclasses/%1/discover").arg(deviceClassId.toString())); + + if (!discoveryParams.isEmpty()) { + QUrlQuery query; + query.addQueryItem("params", QJsonDocument::fromVariant(discoveryParams).toJson(QJsonDocument::Compact)); + url.setQuery(query); + } + + QNetworkRequest request(url); + QNetworkReply *reply = nam->get(request); + clientSpy.wait(); + QCOMPARE(clientSpy.count(), 1); + int statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); + QCOMPARE(statusCode, expectedStatusCode); + QByteArray data = reply->readAll(); + reply->deleteLater(); + + if (expectedStatusCode != 200) + return; + + // check response + QJsonParseError error; + QJsonDocument jsonDoc = QJsonDocument::fromJson(data, &error); + QCOMPARE(error.error, QJsonParseError::NoError); + QVariantList foundDevices = jsonDoc.toVariant().toList(); + QCOMPARE(foundDevices.count(), resultCount); + + qDebug() << jsonDoc.toJson(); + + // add the discovered device + request.setUrl(QUrl("http://localhost:3000/api/v1/devices")); + DeviceDescriptorId descriptorId = DeviceDescriptorId(foundDevices.first().toMap().value("id").toString()); + qDebug() << descriptorId; + params.clear(); + params.insert("deviceClassId", deviceClassId); + params.insert("deviceDescriptorId", descriptorId.toString()); + + clientSpy.clear(); + QByteArray payload = QJsonDocument::fromVariant(params).toJson(QJsonDocument::Compact); + reply = nam->post(request, payload); + clientSpy.wait(); + QCOMPARE(clientSpy.count(), 1); + data = reply->readAll(); + qDebug() << reply->rawHeaderList(); + statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); + reply->deleteLater(); + QCOMPARE(statusCode, expectedStatusCode); + + // remove added device + jsonDoc = QJsonDocument::fromJson(data, &error); + QCOMPARE(error.error, QJsonParseError::NoError); + QVariantMap response = jsonDoc.toVariant().toMap(); + + DeviceId deviceId = DeviceId(response.value("deviceId").toString()); + + request = QNetworkRequest(QUrl(QString("http://localhost:3000/api/v1/devices/%1").arg(deviceId.toString()))); + clientSpy.clear(); + reply = nam->deleteResource(request); + clientSpy.wait(); + QVERIFY2(clientSpy.count() == 1, "expected exactly 1 response from webserver"); + statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); + reply->deleteLater(); + QCOMPARE(statusCode, expectedStatusCode); + nam->deleteLater(); +} + +QTEST_MAIN(TestRestDeviceClasses) diff --git a/tests/auto/restplugins/restplugins.pro b/tests/auto/restplugins/restplugins.pro new file mode 100644 index 00000000..e9ae148f --- /dev/null +++ b/tests/auto/restplugins/restplugins.pro @@ -0,0 +1,5 @@ +include(../../../guh.pri) +include(../autotests.pri) + +TARGET = restplugins +SOURCES += testrestplugins.cpp diff --git a/tests/auto/restplugins/temp b/tests/auto/restplugins/temp new file mode 100644 index 00000000..e69de29b diff --git a/tests/auto/restplugins/testrestplugins.cpp b/tests/auto/restplugins/testrestplugins.cpp new file mode 100644 index 00000000..d37dee32 --- /dev/null +++ b/tests/auto/restplugins/testrestplugins.cpp @@ -0,0 +1,239 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * Copyright (C) 2015 Simon Stuerz * + * * + * This file is part of guh. * + * * + * Guh is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, version 2 of the License. * + * * + * Guh 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 General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with guh. If not, see . * + * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +#include "guhtestbase.h" +#include "guhcore.h" +#include "devicemanager.h" +#include "mocktcpserver.h" +#include "webserver.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace guhserver; + +class TestRestDeviceClasses: public GuhTestBase +{ + Q_OBJECT + +private slots: + void getPlugins(); + + void getPluginConfiguration(); + + void setPluginConfiguration_data(); + void setPluginConfiguration(); +}; + +void TestRestDeviceClasses::getPlugins() +{ + QNetworkAccessManager *nam = new QNetworkAccessManager(this); + QSignalSpy clientSpy(nam, SIGNAL(finished(QNetworkReply*))); + + // Get all plugins + QNetworkRequest request; + request.setUrl(QUrl("http://localhost:3000/api/v1/plugins")); + QNetworkReply *reply = nam->get(request); + clientSpy.wait(); + QVERIFY2(clientSpy.count() == 1, "expected exactly 1 response from webserver"); + + QByteArray data = reply->readAll(); + reply->deleteLater(); + + QJsonParseError error; + QJsonDocument jsonDoc = QJsonDocument::fromJson(data, &error); + QCOMPARE(error.error, QJsonParseError::NoError); + QVariantList pluginList = jsonDoc.toVariant().toList(); + QVERIFY2(pluginList.count() >= 1, "there should be at least one plugin."); + + // Get each of thouse devices individualy + foreach (const QVariant &plugin, pluginList) { + QVariantMap pluginMap = plugin.toMap(); + QNetworkRequest request(QUrl(QString("http://localhost:3000/api/v1/plugins/%1").arg(pluginMap.value("id").toString()))); + request.setHeader(QNetworkRequest::ContentTypeHeader, "text/json"); + clientSpy.clear(); + QNetworkReply *reply = nam->get(request); + clientSpy.wait(); + QVERIFY2(clientSpy.count() == 1, "expected exactly 1 response from webserver"); + jsonDoc = QJsonDocument::fromJson(reply->readAll(), &error); + QCOMPARE(error.error, QJsonParseError::NoError); + + reply->deleteLater(); + } + nam->deleteLater(); +} + +void TestRestDeviceClasses::getPluginConfiguration() +{ + QNetworkAccessManager *nam = new QNetworkAccessManager(this); + QSignalSpy clientSpy(nam, SIGNAL(finished(QNetworkReply*))); + + // Get all plugins + QNetworkRequest request; + request.setUrl(QUrl(QString("http://localhost:3000/api/v1/plugins/%1/configuration").arg(mockPluginId.toString()))); + QNetworkReply *reply = nam->get(request); + clientSpy.wait(); + QVERIFY2(clientSpy.count() == 1, "expected exactly 1 response from webserver"); + + QByteArray data = reply->readAll(); + reply->deleteLater(); + + QJsonParseError error; + QJsonDocument jsonDoc = QJsonDocument::fromJson(data, &error); + QCOMPARE(error.error, QJsonParseError::NoError); + QVariantList configurations = jsonDoc.toVariant().toList(); + QVERIFY2(configurations.count() == 2, "there should be 2 configurations"); +} + +void TestRestDeviceClasses::setPluginConfiguration_data() +{ + + QTest::addColumn("pluginId"); + QTest::addColumn("newConfigurations"); + QTest::addColumn("expectedStatusCode"); + + QVariantMap validIntParam; + validIntParam.insert("name","configParamInt"); + validIntParam.insert("value", 5); + QVariantMap validBoolParam; + validBoolParam.insert("name","configParamBool"); + validBoolParam.insert("value", false); + QVariantMap invalidIntParam; + invalidIntParam.insert("name","configParamInt"); + invalidIntParam.insert("value", 69); + QVariantMap invalidIntParam2; + invalidIntParam2.insert("name","configParamInt"); + invalidIntParam2.insert("value", -1); + + QVariantList validConfigurations; + validConfigurations.append(validIntParam); + validConfigurations.append(validBoolParam); + + QVariantList invalidConfigurations; + invalidConfigurations.append(invalidIntParam); + + QVariantList invalidConfigurations2; + invalidConfigurations2.append(invalidIntParam2); + + QTest::newRow("valid plugin configuration") << mockPluginId << validConfigurations << 200; + QTest::newRow("invalid plugin id") << PluginId::createPluginId() << validConfigurations << 404; + QTest::newRow("invalid plugin configuration") << mockPluginId << invalidConfigurations << 400; + QTest::newRow("invalid plugin configuration 2") << mockPluginId << invalidConfigurations2 << 400; +} + +void TestRestDeviceClasses::setPluginConfiguration() +{ + QFETCH(PluginId, pluginId); + QFETCH(QVariantList, newConfigurations); + QFETCH(int, expectedStatusCode); + + QNetworkAccessManager *nam = new QNetworkAccessManager(this); + QSignalSpy clientSpy(nam, SIGNAL(finished(QNetworkReply*))); + + // Get plugin configuration + QNetworkRequest request; + request.setUrl(QUrl(QString("http://localhost:3000/api/v1/plugins/%1/configuration").arg(pluginId.toString()))); + QNetworkReply *reply = nam->get(request); + clientSpy.wait(); + QVERIFY2(clientSpy.count() == 1, "expected exactly 1 response from webserver"); + int statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); + reply->deleteLater(); + + if (expectedStatusCode != 404) { + QCOMPARE(statusCode, 200); + } else { + QCOMPARE(statusCode, expectedStatusCode); + return; + } + + QByteArray data = reply->readAll(); + reply->deleteLater(); + QJsonParseError error; + QJsonDocument jsonDoc = QJsonDocument::fromJson(data, &error); + QCOMPARE(error.error, QJsonParseError::NoError); + QVariantList originalConfigurations = jsonDoc.toVariant().toList(); + QVERIFY2(originalConfigurations.count() == 2, "there should be 2 configurations"); + + // Set new configuration + clientSpy.clear(); + request.setUrl(QUrl(QString("http://localhost:3000/api/v1/plugins/%1/configuration").arg(pluginId.toString()))); + reply = nam->put(request, QJsonDocument::fromVariant(newConfigurations).toJson(QJsonDocument::Compact)); + clientSpy.wait(); + QVERIFY2(clientSpy.count() == 1, "expected exactly 1 response from webserver"); + statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); + QCOMPARE(statusCode, expectedStatusCode); + reply->deleteLater(); + + if (expectedStatusCode != 200) + return; + + // check new configurations + clientSpy.clear(); + request.setUrl(QUrl(QString("http://localhost:3000/api/v1/plugins/%1/configuration").arg(pluginId.toString()))); + reply = nam->get(request); + clientSpy.wait(); + QVERIFY2(clientSpy.count() == 1, "expected exactly 1 response from webserver"); + statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); + QCOMPARE(statusCode, expectedStatusCode); + data = reply->readAll(); + reply->deleteLater(); + + jsonDoc = QJsonDocument::fromJson(data, &error); + QCOMPARE(error.error, QJsonParseError::NoError); + QVariantList checkConfigurations = jsonDoc.toVariant().toList(); + QVERIFY2(checkConfigurations.count() == 2, "there should be 2 configurations"); + + // verify new configurations + verifyParams(newConfigurations, checkConfigurations); + + restartServer(); + + // check new configurations after restart + clientSpy.clear(); + request.setUrl(QUrl(QString("http://localhost:3000/api/v1/plugins/%1/configuration").arg(pluginId.toString()))); + reply = nam->get(request); + clientSpy.wait(); + QVERIFY2(clientSpy.count() == 1, "expected exactly 1 response from webserver"); + statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); + QCOMPARE(statusCode, 200); + data = reply->readAll(); + reply->deleteLater(); + + jsonDoc = QJsonDocument::fromJson(data, &error); + QCOMPARE(error.error, QJsonParseError::NoError); + checkConfigurations = jsonDoc.toVariant().toList(); + QVERIFY2(checkConfigurations.count() == 2, "there should be 2 configurations"); + + // verify new configurations + verifyParams(newConfigurations, checkConfigurations); + + nam->deleteLater(); +} + +#include "testrestplugins.moc" +QTEST_MAIN(TestRestDeviceClasses) diff --git a/tests/auto/restvendors/restvendors.pro b/tests/auto/restvendors/restvendors.pro new file mode 100644 index 00000000..1b27ceb5 --- /dev/null +++ b/tests/auto/restvendors/restvendors.pro @@ -0,0 +1,5 @@ +include(../../../guh.pri) +include(../autotests.pri) + +TARGET = restvendors +SOURCES += testrestvendors.cpp diff --git a/tests/auto/restvendors/temp b/tests/auto/restvendors/temp new file mode 100644 index 00000000..e69de29b diff --git a/tests/auto/restvendors/testrestvendors.cpp b/tests/auto/restvendors/testrestvendors.cpp new file mode 100644 index 00000000..9e39d02f --- /dev/null +++ b/tests/auto/restvendors/testrestvendors.cpp @@ -0,0 +1,92 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * Copyright (C) 2015 Simon Stuerz * + * * + * This file is part of guh. * + * * + * Guh is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, version 2 of the License. * + * * + * Guh 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 General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with guh. If not, see . * + * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +#include "guhtestbase.h" +#include "guhcore.h" +#include "devicemanager.h" +#include "mocktcpserver.h" +#include "webserver.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace guhserver; + +class TestRestVendors: public GuhTestBase +{ + Q_OBJECT + +private slots: + void getVendors(); +}; + +void TestRestVendors::getVendors() +{ + QNetworkAccessManager *nam = new QNetworkAccessManager(this); + QSignalSpy clientSpy(nam, SIGNAL(finished(QNetworkReply*))); + + // Get all vendors + QNetworkRequest request; + request.setUrl(QUrl("http://localhost:3000/api/v1/vendors")); + QNetworkReply *reply = nam->get(request); + clientSpy.wait(); + QVERIFY2(clientSpy.count() == 1, "expected exactly 1 response from webserver"); + int statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); + QCOMPARE(statusCode, 200); + QByteArray data = reply->readAll(); + reply->deleteLater(); + + QJsonParseError error; + QJsonDocument jsonDoc = QJsonDocument::fromJson(data, &error); + QCOMPARE(error.error, QJsonParseError::NoError); + QVariantList vendorList = jsonDoc.toVariant().toList(); + QVERIFY2(vendorList.count() >= 1, "there should be at least one vendor."); + + + // Get each of thouse vendors individualy + foreach (const QVariant &vendor, vendorList) { + QVariantMap vendorMap = vendor.toMap(); + QNetworkRequest request(QUrl(QString("http://localhost:3000/api/v1/vendors/%1").arg(vendorMap.value("id").toString()))); + request.setHeader(QNetworkRequest::ContentTypeHeader, "text/json"); + clientSpy.clear(); + QNetworkReply *reply = nam->get(request); + clientSpy.wait(); + QVERIFY2(clientSpy.count() == 1, "expected exactly 1 response from webserver"); + int statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); + QCOMPARE(statusCode, 200); + jsonDoc = QJsonDocument::fromJson(reply->readAll(), &error); + QCOMPARE(error.error, QJsonParseError::NoError); + reply->deleteLater(); + + } + nam->deleteLater(); +} + + +#include "testrestvendors.moc" +QTEST_MAIN(TestRestVendors)