mirror of https://github.com/nymea/nymea.git
add much more test coverage
parent
c027bb1481
commit
34ab701f95
|
|
@ -125,7 +125,6 @@ QList<Vendor> DeviceManager::supportedVendors() const
|
|||
Optionally filtered by vendorId. */
|
||||
QList<DeviceClass> DeviceManager::supportedDevices(const VendorId &vendorId) const
|
||||
{
|
||||
qDebug() << "returning devices" << vendorId;
|
||||
QList<DeviceClass> ret;
|
||||
if (vendorId.isNull()) {
|
||||
ret = m_supportedDevices.values();
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@
|
|||
#include <QStringList>
|
||||
|
||||
VendorId guhVendorId = VendorId("2062d64d-3232-433c-88bc-0d33c0ba2ba6");
|
||||
DeviceClassId mockDeviceId = DeviceClassId("753f0d32-0468-4d08-82ed-1964aab03298");
|
||||
DeviceClassId mockDeviceClassId = DeviceClassId("753f0d32-0468-4d08-82ed-1964aab03298");
|
||||
EventTypeId mockEvent1Id = EventTypeId("45bf3752-0fc6-46b9-89fd-ffd878b5b22b");
|
||||
EventTypeId mockEvent2Id = EventTypeId("863d5920-b1cf-4eb9-88bd-8f7b8583b1cf");
|
||||
StateTypeId mockIntStateId = StateTypeId("80baec19-54de-4948-ac46-31eabfaceb83");
|
||||
|
|
@ -50,7 +50,7 @@ QList<DeviceClass> DevicePluginMock::supportedDevices() const
|
|||
{
|
||||
QList<DeviceClass> ret;
|
||||
|
||||
DeviceClass deviceClassMock(pluginId(), guhVendorId, mockDeviceId);
|
||||
DeviceClass deviceClassMock(pluginId(), guhVendorId, mockDeviceClassId);
|
||||
deviceClassMock.setName("Mock Device");
|
||||
|
||||
QVariantList mockParams;
|
||||
|
|
|
|||
|
|
@ -53,7 +53,6 @@ void HttpDaemon::readClient()
|
|||
QByteArray data = socket->readLine();
|
||||
QStringList tokens = QString(data).split(QRegExp("[ \r\n][ \r\n]*"));
|
||||
qDebug() << "incoming data" << tokens[1];
|
||||
if (tokens[1].contains('?')) {
|
||||
QUrl url("http://foo.bar" + tokens[1]);
|
||||
QUrlQuery query(url);
|
||||
qDebug() << "query is" << url.path();
|
||||
|
|
@ -62,7 +61,17 @@ void HttpDaemon::readClient()
|
|||
} else if (url.path() == "/generateevent") {
|
||||
qDebug() << "got generateevent" << query.queryItemValue("eventid");
|
||||
emit triggerEvent(EventTypeId(query.queryItemValue("eventid")));
|
||||
} else if (url.path() == "/actionhistory") {
|
||||
QTextStream os(socket);
|
||||
os.setAutoDetectUnicode(true);
|
||||
os << generateHeader();
|
||||
for (int i = 0; i < m_actionList.count(); ++i) {
|
||||
os << m_actionList.at(i).first.toString() << '\n';
|
||||
}
|
||||
socket->close();
|
||||
return;
|
||||
} else if (url.path() == "/clearactionhistory") {
|
||||
m_actionList.clear();
|
||||
}
|
||||
if (tokens[0] == "GET") {
|
||||
QTextStream os(socket);
|
||||
|
|
@ -88,15 +97,19 @@ void HttpDaemon::discardClient()
|
|||
qDebug() << "Connection closed";
|
||||
}
|
||||
|
||||
QString HttpDaemon::generateWebPage()
|
||||
QString HttpDaemon::generateHeader()
|
||||
{
|
||||
DeviceClass deviceClass = m_plugin->supportedDevices().first();
|
||||
|
||||
QString contentHeader(
|
||||
"HTTP/1.0 200 Ok\r\n"
|
||||
"Content-Type: text/html; charset=\"utf-8\"\r\n"
|
||||
"\r\n"
|
||||
);
|
||||
return contentHeader;
|
||||
}
|
||||
|
||||
QString HttpDaemon::generateWebPage()
|
||||
{
|
||||
DeviceClass deviceClass = m_plugin->supportedDevices().first();
|
||||
|
||||
QString body = QString(
|
||||
"<html>"
|
||||
|
|
@ -169,5 +182,5 @@ QString HttpDaemon::generateWebPage()
|
|||
|
||||
body.append("</body></html>\n");
|
||||
|
||||
return contentHeader + body;
|
||||
return generateHeader() + body;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@ private slots:
|
|||
void discardClient();
|
||||
|
||||
private:
|
||||
QString generateHeader();
|
||||
QString generateWebPage();
|
||||
|
||||
private:
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ ActionHandler::ActionHandler(QObject *parent) :
|
|||
setDescription("ExecuteAction", "Execute a single action.");
|
||||
params.insert("actionTypeId", "uuid");
|
||||
params.insert("deviceId", "uuid");
|
||||
params.insert("params", JsonTypes::paramTypeRef());
|
||||
params.insert("o:params", JsonTypes::paramTypeRef());
|
||||
setParams("ExecuteAction", JsonTypes::actionDescription());
|
||||
returns.insert("success", "bool");
|
||||
returns.insert("errorMessage", "string");
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ DeviceHandler::DeviceHandler(QObject *parent) :
|
|||
|
||||
params.clear(); returns.clear();
|
||||
setDescription("GetSupportedDevices", "Returns a list of supported Device classes, optionally filtered by vendorId.");
|
||||
params.insert("vendorId", "o:uuid");
|
||||
params.insert("o:vendorId", "uuid");
|
||||
setParams("GetSupportedDevices", params);
|
||||
QVariantList deviceClasses;
|
||||
deviceClasses.append(JsonTypes::deviceClassRef());
|
||||
|
|
@ -74,7 +74,7 @@ DeviceHandler::DeviceHandler(QObject *parent) :
|
|||
setParams("AddConfiguredDevice", params);
|
||||
returns.insert("success", "bool");
|
||||
returns.insert("errorMessage", "string");
|
||||
returns.insert("deviceId", "o:uuid");
|
||||
returns.insert("o:deviceId", "uuid");
|
||||
setReturns("AddConfiguredDevice", returns);
|
||||
|
||||
params.clear(); returns.clear();
|
||||
|
|
@ -117,7 +117,7 @@ DeviceHandler::DeviceHandler(QObject *parent) :
|
|||
setParams("GetStateTypes", params);
|
||||
QVariantList states;
|
||||
states.append(JsonTypes::stateTypeRef());
|
||||
returns.insert("stateTypes", actions);
|
||||
returns.insert("stateTypes", states);
|
||||
setReturns("GetStateTypes", returns);
|
||||
|
||||
params.clear(); returns.clear();
|
||||
|
|
@ -127,7 +127,7 @@ DeviceHandler::DeviceHandler(QObject *parent) :
|
|||
setParams("GetStateValue", params);
|
||||
returns.insert("success", "bool");
|
||||
returns.insert("errorMessage", "string");
|
||||
returns.insert("value", "o:variant");
|
||||
returns.insert("o:value", "variant");
|
||||
setReturns("GetStateValue", returns);
|
||||
|
||||
// Notifications
|
||||
|
|
|
|||
|
|
@ -89,7 +89,7 @@ void JsonTypes::init()
|
|||
// Action
|
||||
s_action.insert("actionTypeId", "uuid");
|
||||
s_action.insert("deviceId", "uuid");
|
||||
s_action.insert("params", QVariantList() << paramRef());
|
||||
s_action.insert("o:params", QVariantList() << paramRef());
|
||||
|
||||
// Pugin
|
||||
s_plugin.insert("id", "uuid");
|
||||
|
|
@ -263,28 +263,32 @@ QPair<bool, QString> JsonTypes::validateMap(const QVariantMap &templateMap, cons
|
|||
{
|
||||
s_lastError.clear();
|
||||
foreach (const QString &key, templateMap.keys()) {
|
||||
if (templateMap.value(key).toString().startsWith("o:")) {
|
||||
continue;
|
||||
}
|
||||
if (!map.contains(key)) {
|
||||
QString strippedKey = key;
|
||||
strippedKey.remove(QRegExp("^o:"));
|
||||
|
||||
if (!key.startsWith("o:") && !map.contains(strippedKey)) {
|
||||
qDebug() << "missing key" << key << templateMap << map;
|
||||
QJsonDocument jsonDoc = QJsonDocument::fromVariant(map);
|
||||
return report(false, QString("Missing key \"%1\" in %2").arg(key).arg(QString(jsonDoc.toJson())));
|
||||
}
|
||||
QPair<bool, QString> result = validateVariant(templateMap.value(key), map.value(key));
|
||||
if (map.contains(strippedKey)) {
|
||||
QPair<bool, QString> result = validateVariant(templateMap.value(key), map.value(strippedKey));
|
||||
if (!result.first) {
|
||||
qDebug() << "Object not matching template";
|
||||
qDebug() << "Object not matching template or object not matching" << templateMap.value(key) << map.value(strippedKey);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
return report(true, "");
|
||||
}
|
||||
|
||||
QPair<bool, QString> JsonTypes::validateProperty(const QVariant &templateValue, const QVariant &value)
|
||||
{
|
||||
QString strippedTemplateValue = templateValue.toString();
|
||||
strippedTemplateValue.remove(QRegExp("^o:"));
|
||||
|
||||
if (strippedTemplateValue == "variant") {
|
||||
return report(true, "");
|
||||
}
|
||||
if (strippedTemplateValue == "uuid") {
|
||||
QString errorString = QString("Param %1 is not a uuid.").arg(value.toString());
|
||||
return report(value.canConvert(QVariant::Uuid), errorString);
|
||||
|
|
@ -307,8 +311,6 @@ QPair<bool, QString> JsonTypes::validateList(const QVariantList &templateList, c
|
|||
Q_ASSERT(templateList.count() == 1);
|
||||
QVariant entryTemplate = templateList.first();
|
||||
|
||||
qDebug() << "validating list" << templateList;
|
||||
|
||||
for (int i = 0; i < list.count(); ++i) {
|
||||
QVariant listEntry = list.at(i);
|
||||
QPair<bool, QString> result = validateVariant(entryTemplate, listEntry);
|
||||
|
|
|
|||
|
|
@ -33,6 +33,10 @@ int mockDevice1Port = 1337;
|
|||
int mockDevice2Port = 7331;
|
||||
|
||||
extern VendorId guhVendorId;
|
||||
extern DeviceClassId mockDeviceClassId;
|
||||
extern ActionTypeId mockAction1Id;
|
||||
extern EventTypeId mockEvent1Id;
|
||||
extern StateTypeId mockIntStateId;
|
||||
|
||||
class TestJSONRPC: public QObject
|
||||
{
|
||||
|
|
@ -49,6 +53,19 @@ private slots:
|
|||
|
||||
void getSupportedDevices_data();
|
||||
void getSupportedDevices();
|
||||
void getConfiguredDevices();
|
||||
|
||||
void executeAction_data();
|
||||
void executeAction();
|
||||
|
||||
void getActionTypes_data();
|
||||
void getActionTypes();
|
||||
|
||||
void getEventTypes_data();
|
||||
void getEventTypes();
|
||||
|
||||
void getStateTypes_data();
|
||||
void getStateTypes();
|
||||
|
||||
void enableDisableNotifications_data();
|
||||
void enableDisableNotifications();
|
||||
|
|
@ -65,7 +82,7 @@ private:
|
|||
MockTcpServer *m_mockTcpServer;
|
||||
QUuid m_clientId;
|
||||
int m_commandId;
|
||||
QUuid m_mockDeviceId;
|
||||
DeviceId m_mockDeviceId;
|
||||
};
|
||||
|
||||
void TestJSONRPC::initTestcase()
|
||||
|
|
@ -95,7 +112,7 @@ void TestJSONRPC::initTestcase()
|
|||
|
||||
QCOMPARE(response.toMap().value("params").toMap().value("success").toBool(), true);
|
||||
|
||||
m_mockDeviceId = response.toMap().value("params").toMap().value("deviceId").toUuid();
|
||||
m_mockDeviceId = DeviceId(response.toMap().value("params").toMap().value("deviceId").toString());
|
||||
QVERIFY2(!m_mockDeviceId.isNull(), "Newly created mock device must not be null.");
|
||||
}
|
||||
|
||||
|
|
@ -248,6 +265,137 @@ void TestJSONRPC::getSupportedDevices()
|
|||
}
|
||||
}
|
||||
|
||||
void TestJSONRPC::getConfiguredDevices()
|
||||
{
|
||||
QVariant response = injectAndWait("Devices.GetConfiguredDevices");
|
||||
|
||||
QVariantList devices = response.toMap().value("params").toMap().value("devices").toList();
|
||||
QCOMPARE(devices.count(), 1);
|
||||
}
|
||||
|
||||
void TestJSONRPC::executeAction_data()
|
||||
{
|
||||
QTest::addColumn<DeviceId>("deviceId");
|
||||
QTest::addColumn<ActionTypeId>("actionTypeId");
|
||||
QTest::addColumn<bool>("success");
|
||||
|
||||
QTest::newRow("valid action") << m_mockDeviceId << mockAction1Id << true;
|
||||
QTest::newRow("invalid device TypeId") << DeviceId("f2965936-0dd0-4014-8f31-4c2ef7fc5952") << mockAction1Id << false;
|
||||
QTest::newRow("invalid action TypeId") << m_mockDeviceId << ActionTypeId("f2965936-0dd0-4014-8f31-4c2ef7fc5952") << false;
|
||||
}
|
||||
|
||||
void TestJSONRPC::executeAction()
|
||||
{
|
||||
QFETCH(DeviceId, deviceId);
|
||||
QFETCH(ActionTypeId, actionTypeId);
|
||||
QFETCH(bool, success);
|
||||
|
||||
QVariantMap params;
|
||||
params.insert("actionTypeId", actionTypeId);
|
||||
params.insert("deviceId", deviceId);
|
||||
QVariant response = injectAndWait("Actions.ExecuteAction", params);
|
||||
QCOMPARE(response.toMap().value("params").toMap().value("success").toBool(), success);
|
||||
|
||||
// Fetch action execution history from mock device
|
||||
QNetworkAccessManager nam;
|
||||
QSignalSpy spy(&nam, SIGNAL(finished(QNetworkReply*)));
|
||||
|
||||
QNetworkRequest request(QUrl(QString("http://localhost:%1/actionhistory").arg(mockDevice1Port)));
|
||||
QNetworkReply *reply = nam.get(request);
|
||||
spy.wait();
|
||||
QCOMPARE(spy.count(), 1);
|
||||
reply->deleteLater();
|
||||
|
||||
if (success) {
|
||||
QCOMPARE(actionTypeId, ActionTypeId(reply->readAll()));
|
||||
} else {
|
||||
QCOMPARE(reply->readAll().length(), 0);
|
||||
}
|
||||
|
||||
// cleanup for the next run
|
||||
spy.clear();
|
||||
request.setUrl(QUrl(QString("http://localhost:%1/clearactionhistory").arg(mockDevice1Port)));
|
||||
reply = nam.get(request);
|
||||
spy.wait();
|
||||
QCOMPARE(spy.count(), 1);
|
||||
reply->deleteLater();
|
||||
}
|
||||
|
||||
void TestJSONRPC::getActionTypes_data()
|
||||
{
|
||||
QTest::addColumn<DeviceClassId>("deviceClassId");
|
||||
QTest::addColumn<int>("resultCount");
|
||||
|
||||
QTest::newRow("valid deviceclass") << mockDeviceClassId << 2;
|
||||
QTest::newRow("invalid deviceclass") << DeviceClassId("094f8024-5caa-48c1-ab6a-de486a92088f") << 0;
|
||||
}
|
||||
|
||||
void TestJSONRPC::getActionTypes()
|
||||
{
|
||||
QFETCH(DeviceClassId, deviceClassId);
|
||||
QFETCH(int, resultCount);
|
||||
|
||||
QVariantMap params;
|
||||
params.insert("deviceClassId", deviceClassId);
|
||||
QVariant response = injectAndWait("Devices.GetActionTypes", params);
|
||||
|
||||
QVariantList actionTypes = response.toMap().value("params").toMap().value("actionTypes").toList();
|
||||
QCOMPARE(actionTypes.count(), resultCount);
|
||||
if (resultCount > 0) {
|
||||
QCOMPARE(actionTypes.first().toMap().value("id").toString(), mockAction1Id.toString());
|
||||
}
|
||||
}
|
||||
|
||||
void TestJSONRPC::getEventTypes_data()
|
||||
{
|
||||
QTest::addColumn<DeviceClassId>("deviceClassId");
|
||||
QTest::addColumn<int>("resultCount");
|
||||
|
||||
QTest::newRow("valid deviceclass") << mockDeviceClassId << 2;
|
||||
QTest::newRow("invalid deviceclass") << DeviceClassId("094f8024-5caa-48c1-ab6a-de486a92088f") << 0;
|
||||
}
|
||||
|
||||
void TestJSONRPC::getEventTypes()
|
||||
{
|
||||
QFETCH(DeviceClassId, deviceClassId);
|
||||
QFETCH(int, resultCount);
|
||||
|
||||
QVariantMap params;
|
||||
params.insert("deviceClassId", deviceClassId);
|
||||
QVariant response = injectAndWait("Devices.GetEventTypes", params);
|
||||
|
||||
QVariantList eventTypes = response.toMap().value("params").toMap().value("eventTypes").toList();
|
||||
QCOMPARE(eventTypes.count(), resultCount);
|
||||
if (resultCount > 0) {
|
||||
QCOMPARE(eventTypes.first().toMap().value("id").toString(), mockEvent1Id.toString());
|
||||
}
|
||||
}
|
||||
|
||||
void TestJSONRPC::getStateTypes_data()
|
||||
{
|
||||
QTest::addColumn<DeviceClassId>("deviceClassId");
|
||||
QTest::addColumn<int>("resultCount");
|
||||
|
||||
QTest::newRow("valid deviceclass") << mockDeviceClassId << 2;
|
||||
QTest::newRow("invalid deviceclass") << DeviceClassId("094f8024-5caa-48c1-ab6a-de486a92088f") << 0;
|
||||
}
|
||||
|
||||
void TestJSONRPC::getStateTypes()
|
||||
{
|
||||
QFETCH(DeviceClassId, deviceClassId);
|
||||
QFETCH(int, resultCount);
|
||||
|
||||
QVariantMap params;
|
||||
params.insert("deviceClassId", deviceClassId);
|
||||
QVariant response = injectAndWait("Devices.GetStateTypes", params);
|
||||
|
||||
QVariantList stateTypes = response.toMap().value("params").toMap().value("stateTypes").toList();
|
||||
QCOMPARE(stateTypes.count(), resultCount);
|
||||
if (resultCount > 0) {
|
||||
QCOMPARE(stateTypes.first().toMap().value("id").toString(), mockIntStateId.toString());
|
||||
}
|
||||
}
|
||||
|
||||
void TestJSONRPC::enableDisableNotifications_data()
|
||||
{
|
||||
QTest::addColumn<QString>("enabled");
|
||||
|
|
|
|||
|
|
@ -0,0 +1,7 @@
|
|||
#!/bin/bash
|
||||
|
||||
if [ -z $1 ]; then
|
||||
echo "usage $0 host"
|
||||
else
|
||||
(echo '{"id":1, "method":"Devices.GetSupportedVendors"}'; sleep 1) | nc $1 1234
|
||||
fi
|
||||
Loading…
Reference in New Issue