diff --git a/debian/changelog b/debian/changelog index 8fb6a1d6..56ef93f6 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +guh (0.1.8) utopic; urgency=medium + + * allow calling AddRule with a single eventDescriptor but also with a list + + -- Michael Zanetti Sun, 15 Jun 2014 00:33:36 +0200 + guh (0.1.7) utopic; urgency=medium * implement StateEvaluators diff --git a/server/jsonrpc/jsontypes.cpp b/server/jsonrpc/jsontypes.cpp index b53d3259..fd9cd25f 100644 --- a/server/jsonrpc/jsontypes.cpp +++ b/server/jsonrpc/jsontypes.cpp @@ -478,6 +478,15 @@ QList JsonTypes::unpackParamDescriptors(const QVariantList &par return params; } +EventDescriptor JsonTypes::unpackEventDescriptor(const QVariantMap &eventDescriptorMap) +{ + EventTypeId eventTypeId(eventDescriptorMap.value("eventTypeId").toString()); + DeviceId eventDeviceId(eventDescriptorMap.value("deviceId").toString()); + QList eventParams = JsonTypes::unpackParamDescriptors(eventDescriptorMap.value("paramDescriptors").toList()); + EventDescriptor eventDescriptor(EventDescriptorId::createEventDescriptorId(), eventTypeId, eventDeviceId, eventParams); + return eventDescriptor; +} + QPair JsonTypes::validateMap(const QVariantMap &templateMap, const QVariantMap &map) { s_lastError.clear(); diff --git a/server/jsonrpc/jsontypes.h b/server/jsonrpc/jsontypes.h index 58c10958..7394c209 100644 --- a/server/jsonrpc/jsontypes.h +++ b/server/jsonrpc/jsontypes.h @@ -110,6 +110,7 @@ public: static QList unpackParams(const QVariantList ¶mList); static ParamDescriptor unpackParamDescriptor(const QVariantMap ¶mDescriptorMap); static QList unpackParamDescriptors(const QVariantList ¶mDescriptorList); + static EventDescriptor unpackEventDescriptor(const QVariantMap &eventDescriptorMap); static QPair validateMap(const QVariantMap &templateMap, const QVariantMap &map); static QPair validateProperty(const QVariant &templateValue, const QVariant &value); diff --git a/server/jsonrpc/ruleshandler.cpp b/server/jsonrpc/ruleshandler.cpp index 099bd4e3..13315b91 100644 --- a/server/jsonrpc/ruleshandler.cpp +++ b/server/jsonrpc/ruleshandler.cpp @@ -81,12 +81,23 @@ JsonReply* RulesHandler::GetRules(const QVariantMap ¶ms) JsonReply* RulesHandler::AddRule(const QVariantMap ¶ms) { - QVariantMap eventMap = params.value("eventDescriptor").toMap(); + if (params.contains("eventDescriptor") && params.contains("eventDescriptorList")) { + QVariantMap returns; + returns.insert("success", false); + returns.insert("errorMessage", "Only one of \"eventDescriptor\" and \"eventDescriptorList\" may be used."); + return createReply(returns); + } - EventTypeId eventTypeId(eventMap.value("eventTypeId").toString()); - DeviceId eventDeviceId(eventMap.value("deviceId").toString()); - QList eventParams = JsonTypes::unpackParamDescriptors(eventMap.value("paramDescriptors").toList()); - EventDescriptor eventDescriptor(EventDescriptorId::createEventDescriptorId(), eventTypeId, eventDeviceId, eventParams); + QList eventDescriptorList; + if (params.contains("eventDescriptor")) { + QVariantMap eventMap = params.value("eventDescriptor").toMap(); + eventDescriptorList.append(JsonTypes::unpackEventDescriptor(eventMap)); + } else if (params.contains("eventDescriptorList")) { + foreach (const QVariant &eventVariant, params.value("eventDescriptorList").toList()) { + QVariantMap eventMap = eventVariant.toMap(); + eventDescriptorList.append(JsonTypes::unpackEventDescriptor(eventMap)); + } + } QList actions; QVariantList actionList = params.value("actions").toList(); @@ -105,7 +116,7 @@ JsonReply* RulesHandler::AddRule(const QVariantMap ¶ms) } RuleId newRuleId = RuleId::createRuleId(); - switch(GuhCore::instance()->ruleEngine()->addRule(newRuleId, eventDescriptor, actions)) { + switch(GuhCore::instance()->ruleEngine()->addRule(newRuleId, eventDescriptorList, actions)) { case RuleEngine::RuleErrorNoError: returns.insert("success", true); returns.insert("errorMessage", ""); diff --git a/server/ruleengine.cpp b/server/ruleengine.cpp index 69c28d0a..51e23518 100644 --- a/server/ruleengine.cpp +++ b/server/ruleengine.cpp @@ -160,12 +160,10 @@ QList RuleEngine::evaluateEvent(const Event &event) return actions; } -/*! Add a new \l{Rule} with the given \a event and \a actions to the engine. +/*! Add a new \l{Rule} with the given \a EventDescriptorList and \a actions to the engine. For convenience, this creates a Rule without any \l{State} comparison. */ -RuleEngine::RuleError RuleEngine::addRule(const RuleId &ruleId, const EventDescriptor &eventDescriptor, const QList &actions) +RuleEngine::RuleError RuleEngine::addRule(const RuleId &ruleId, const QList &eventDescriptorList, const QList &actions) { - QList eventDescriptorList; - eventDescriptorList.append(eventDescriptor); return addRule(ruleId, eventDescriptorList, StateEvaluator(StateEvaluatorId::createStateEvaluatorId()), actions); } diff --git a/server/ruleengine.h b/server/ruleengine.h index e5390c27..a09dfc16 100644 --- a/server/ruleengine.h +++ b/server/ruleengine.h @@ -44,7 +44,7 @@ public: QList evaluateEvent(const Event &event); - RuleError addRule(const RuleId &ruleId, const EventDescriptor &eventDescriptor, const QList &actions); + RuleError addRule(const RuleId &ruleId, const QList &eventDescriptorList, const QList &actions); RuleError addRule(const RuleId &ruleId, const QList &eventDescriptorList, const StateEvaluator &stateEvaluator, const QList &actions); QList rules() const; diff --git a/tests/auto/api.json b/tests/auto/api.json index 576dde3f..9b7a3eaf 100644 --- a/tests/auto/api.json +++ b/tests/auto/api.json @@ -1,4 +1,4 @@ -0.1.7 +0.1.8 { "methods": { "Actions.ExecuteAction": { @@ -214,12 +214,15 @@ } }, "Rules.AddRule": { - "description": "Add a rule", + "description": "Add a rule.", "params": { "actions": [ "$ref:Action" ], - "eventDescriptor": "$ref:EventDescriptor" + "o:eventDescriptor": "$ref:EventDescriptor", + "o:eventDescriptorList": [ + "$ref:EventDescriptor" + ] }, "returns": { "errorMessage": "string", diff --git a/tests/auto/devices/testdevices.cpp b/tests/auto/devices/testdevices.cpp index 94ebbcd3..badd6543 100644 --- a/tests/auto/devices/testdevices.cpp +++ b/tests/auto/devices/testdevices.cpp @@ -245,7 +245,7 @@ void TestDevices::removeDevice() QFETCH(DeviceId, deviceId); QFETCH(bool, success); - QSettings settings; + QSettings settings(m_deviceSettings); settings.beginGroup("DeviceConfig"); if (success) { settings.beginGroup(m_mockDeviceId.toString()); diff --git a/tests/auto/guhtestbase.cpp b/tests/auto/guhtestbase.cpp index 7435f63f..a3263925 100644 --- a/tests/auto/guhtestbase.cpp +++ b/tests/auto/guhtestbase.cpp @@ -38,15 +38,17 @@ GuhTestBase::GuhTestBase(QObject *parent) : m_mockDevice2Port = 7331; QCoreApplication::instance()->setOrganizationName("guh-test"); + m_rulesSettings = QCoreApplication::instance()->organizationName() + "/rules"; + m_deviceSettings = QCoreApplication::instance()->organizationName() + "/devices"; } void GuhTestBase::initTestCase() { // If testcase asserts cleanup won't do. Lets clear any previous test run settings leftovers - QSettings rulesSettings(QCoreApplication::instance()->organizationName() + "/rules"); + QSettings rulesSettings(m_rulesSettings); rulesSettings.clear(); - QSettings deviceSettings(QCoreApplication::instance()->organizationName() + "/devices"); + QSettings deviceSettings(m_deviceSettings); deviceSettings.clear(); GuhCore::instance(); diff --git a/tests/auto/guhtestbase.h b/tests/auto/guhtestbase.h index 4c316253..4a05dbeb 100644 --- a/tests/auto/guhtestbase.h +++ b/tests/auto/guhtestbase.h @@ -41,6 +41,7 @@ extern ActionTypeId mockActionIdAsync; extern ActionTypeId mockActionIdFailing; extern ActionTypeId mockActionIdAsyncFailing; extern EventTypeId mockEvent1Id; +extern EventTypeId mockEvent2Id; extern StateTypeId mockIntStateId; class MockTcpServer; @@ -70,6 +71,8 @@ protected: DeviceId m_mockDeviceId; + QString m_deviceSettings; + QString m_rulesSettings; }; #endif // GUHTESTBASE_H diff --git a/tests/auto/rules/testrules.cpp b/tests/auto/rules/testrules.cpp index 79f502e3..315cda6d 100644 --- a/tests/auto/rules/testrules.cpp +++ b/tests/auto/rules/testrules.cpp @@ -52,10 +52,19 @@ void TestRules::addRules_data() invalidAction.insert("deviceId", m_mockDeviceId); invalidAction.insert("params", QVariantList()); - QVariantMap validEventDescriptor; - validEventDescriptor.insert("eventTypeId", mockEvent1Id); - validEventDescriptor.insert("deviceId", m_mockDeviceId); - validEventDescriptor.insert("paramDescriptors", QVariantList()); + QVariantMap validEventDescriptor1; + validEventDescriptor1.insert("eventTypeId", mockEvent1Id); + validEventDescriptor1.insert("deviceId", m_mockDeviceId); + validEventDescriptor1.insert("paramDescriptors", QVariantList()); + + QVariantMap validEventDescriptor2; + validEventDescriptor2.insert("eventTypeId", mockEvent2Id); + validEventDescriptor2.insert("deviceId", m_mockDeviceId); + validEventDescriptor2.insert("paramDescriptors", QVariantList()); + + QVariantList eventDescriptorList; + eventDescriptorList.append(validEventDescriptor1); + eventDescriptorList.append(validEventDescriptor2); QVariantMap invalidEventDescriptor; invalidEventDescriptor.insert("eventTypeId", mockEvent1Id); @@ -63,26 +72,37 @@ void TestRules::addRules_data() invalidEventDescriptor.insert("paramDescriptors", QVariantList()); QTest::addColumn("action1"); - QTest::addColumn("eventDescriptor1"); + QTest::addColumn("eventDescriptor"); + QTest::addColumn("eventDescriptorList"); QTest::addColumn("success"); - QTest::newRow("valid rule") << validAction << validEventDescriptor << true; - QTest::newRow("invalid action") << invalidAction << validEventDescriptor << false; - QTest::newRow("invalid event descriptor") << validAction << invalidEventDescriptor << false; + + QTest::newRow("valid rule. 1 EventDescriptor, 1 Action") << validAction << validEventDescriptor1 << QVariantList() << true; + QTest::newRow("valid rule. 2 EventDescriptors, 1 Action") << validAction << QVariantMap() << eventDescriptorList << true; + QTest::newRow("invalid rule: eventDescriptor and eventDescriptorList used") << validAction << validEventDescriptor1 << eventDescriptorList << false; + QTest::newRow("invalid action") << invalidAction << validEventDescriptor1 << QVariantList() << false; + QTest::newRow("invalid event descriptor") << validAction << invalidEventDescriptor << QVariantList() << false; } void TestRules::addRules() { QFETCH(QVariantMap, action1); - QFETCH(QVariantMap, eventDescriptor1); + QFETCH(QVariantMap, eventDescriptor); + QFETCH(QVariantList, eventDescriptorList); QFETCH(bool, success); QVariantMap params; QVariantList actions; actions.append(action1); params.insert("actions", actions); - params.insert("eventDescriptor", eventDescriptor1); + + if (!eventDescriptor.isEmpty()) { + params.insert("eventDescriptor", eventDescriptor); + } + if (!eventDescriptorList.isEmpty()) { + params.insert("eventDescriptorList", eventDescriptorList); + } QVariant response = injectAndWait("Rules.AddRule", params); RuleId newRuleId = RuleId(response.toMap().value("params").toMap().value("ruleId").toString()); @@ -99,9 +119,24 @@ void TestRules::addRules() QVERIFY2(rules.count() == 1, "There should be exactly one rule"); QCOMPARE(RuleId(rules.first().toMap().value("id").toString()), newRuleId); + QVariantList eventDescriptors = rules.first().toMap().value("eventDescriptors").toList(); - QVERIFY2(eventDescriptors.count() == 1, "There shoud be exactly one eventDescriptor"); - QVERIFY2(eventDescriptors.first().toMap() == eventDescriptor1, "Event descriptor doesn't match"); + if (!eventDescriptor.isEmpty()) { + QVERIFY2(eventDescriptors.count() == 1, "There shoud be exactly one eventDescriptor"); + QVERIFY2(eventDescriptors.first().toMap() == eventDescriptor, "Event descriptor doesn't match"); + } else if (eventDescriptorList.isEmpty()){ + QVERIFY2(eventDescriptors.count() == eventDescriptorList.count(), QString("There shoud be exactly %1 eventDescriptor").arg(eventDescriptorList.count()).toLatin1().data()); + foreach (const QVariant &eventDescriptorVariant, eventDescriptorList) { + bool found = false; + foreach (const QVariant &replyEventDescriptorVariant, eventDescriptors) { + if (eventDescriptorVariant.toMap().value("deviceId") == replyEventDescriptorVariant.toMap().value("deviceId") && + eventDescriptorVariant.toMap().value("eventTypeId") == replyEventDescriptorVariant.toMap().value("eventTypeId")) { + found = true; + QVERIFY2(eventDescriptorVariant == replyEventDescriptorVariant, "Event descriptor doesn't match"); + } + } + } + } QVariantList replyActions = rules.first().toMap().value("actions").toList(); QVERIFY2(actions == replyActions, "Actions don't match"); diff --git a/tests/auto/versioning/testversioning.cpp b/tests/auto/versioning/testversioning.cpp index 46794f7a..6a0d5c61 100644 --- a/tests/auto/versioning/testversioning.cpp +++ b/tests/auto/versioning/testversioning.cpp @@ -79,10 +79,6 @@ void TestVersioning::apiChangeBumpsVersion() return; } - if (oldVersion == newVersionStripped && oldApi != newApi) { - QVERIFY2(false, "JSONRPC API has changed but version is still the same. You need to bump the API version."); - } - QFile newApiFile(newFilePath); QVERIFY(newApiFile.open(QIODevice::ReadWrite)); if (newApiFile.size() > 0) { @@ -94,9 +90,15 @@ void TestVersioning::apiChangeBumpsVersion() newApiFile.flush(); QProcess p; - p.execute("diff", QStringList() << "-u" << oldFilePath << newFilePath); + p.start("diff", QStringList() << "-u" << oldFilePath << newFilePath); p.waitForFinished(); - qDebug() << p.readAll(); + QByteArray apiDiff = p.readAll(); + + qDebug() << "API Differences:" << endl << apiDiff; + + if (oldVersion == newVersionStripped && oldApi != newApi) { + QVERIFY2(false, "JSONRPC API has changed but version is still the same. You need to bump the API version."); + } if (oldVersion != newVersionStripped && oldApi == newApi) { QVERIFY2(false, QString("Version has changed. Update %1.").arg(oldFilePath).toLatin1().data());