mirror of https://github.com/nymea/nymea.git
1598 lines
76 KiB
C++
1598 lines
76 KiB
C++
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
|
* *
|
|
* Copyright (C) 2015 Simon Stuerz <simon.stuerz@guh.guru> *
|
|
* Copyright (C) 2014 Michael Zanetti <michael_zanetti@gmx.net> *
|
|
* *
|
|
* 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 <http://www.gnu.org/licenses/>. *
|
|
* *
|
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
|
|
|
#include "guhtestbase.h"
|
|
#include "guhcore.h"
|
|
#include "devicemanager.h"
|
|
#include "mocktcpserver.h"
|
|
|
|
#include <QtTest/QtTest>
|
|
#include <QCoreApplication>
|
|
#include <QTcpSocket>
|
|
#include <QNetworkAccessManager>
|
|
#include <QNetworkRequest>
|
|
#include <QNetworkReply>
|
|
#include <QCoreApplication>
|
|
|
|
using namespace guhserver;
|
|
|
|
class TestRules: public GuhTestBase
|
|
{
|
|
Q_OBJECT
|
|
|
|
private:
|
|
void cleanupMockHistory();
|
|
void cleanupRules();
|
|
|
|
void verifyRuleExecuted(const ActionTypeId &actionTypeId);
|
|
void verifyRuleNotExecuted();
|
|
|
|
QVariant validIntStateBasedRule(const QString &name, const bool &executable, const bool &enabled);
|
|
|
|
private slots:
|
|
|
|
void cleanup();
|
|
void emptyRule();
|
|
void getInvalidRule();
|
|
|
|
void addRemoveRules_data();
|
|
void addRemoveRules();
|
|
|
|
void editRules_data();
|
|
void editRules();
|
|
|
|
void executeRuleActions_data();
|
|
void executeRuleActions();
|
|
|
|
void findRule();
|
|
|
|
void removeInvalidRule();
|
|
|
|
void loadStoreConfig();
|
|
|
|
void evaluateEvent();
|
|
|
|
void testStateEvaluator_data();
|
|
void testStateEvaluator();
|
|
|
|
void testStateEvaluator2_data();
|
|
void testStateEvaluator2();
|
|
|
|
void testStateChange();
|
|
|
|
void enableDisableRule();
|
|
|
|
void testEventBasedAction();
|
|
|
|
void testRuleActionParams_data();
|
|
void testRuleActionParams();
|
|
};
|
|
|
|
void TestRules::cleanupMockHistory() {
|
|
QNetworkAccessManager nam;
|
|
QSignalSpy spy(&nam, SIGNAL(finished(QNetworkReply*)));
|
|
QNetworkRequest request(QUrl(QString("http://localhost:%1/clearactionhistory").arg(m_mockDevice1Port).arg(mockEvent1Id.toString())));
|
|
QNetworkReply *reply = nam.get(request);
|
|
spy.wait(500);
|
|
QCOMPARE(spy.count(), 1);
|
|
reply->deleteLater();
|
|
}
|
|
|
|
void TestRules::cleanupRules() {
|
|
QVariant response = injectAndWait("Rules.GetRules");
|
|
foreach (const QVariant &ruleDescription, response.toMap().value("params").toMap().value("ruleDescriptions").toList()) {
|
|
QVariantMap params;
|
|
params.insert("ruleId", ruleDescription.toMap().value("id").toString());
|
|
verifyRuleError(injectAndWait("Rules.RemoveRule", params));
|
|
}
|
|
}
|
|
|
|
void TestRules::cleanup() {
|
|
cleanupMockHistory();
|
|
cleanupRules();
|
|
}
|
|
|
|
void TestRules::emptyRule()
|
|
{
|
|
QVariantMap params;
|
|
params.insert("name", QString());
|
|
params.insert("actions", QVariantList());
|
|
QVariant response = injectAndWait("Rules.AddRule", params);
|
|
verifyRuleError(response, RuleEngine::RuleErrorMissingParameter);
|
|
}
|
|
|
|
void TestRules::getInvalidRule()
|
|
{
|
|
QVariantMap params;
|
|
params.insert("ruleId", QUuid::createUuid());
|
|
QVariant response = injectAndWait("Rules.GetRuleDetails", params);
|
|
verifyRuleError(response, RuleEngine::RuleErrorRuleNotFound);
|
|
}
|
|
|
|
void TestRules::verifyRuleExecuted(const ActionTypeId &actionTypeId)
|
|
{
|
|
// Verify rule got executed
|
|
QNetworkAccessManager nam;
|
|
QSignalSpy spy(&nam, SIGNAL(finished(QNetworkReply*)));
|
|
QNetworkRequest request(QUrl(QString("http://localhost:%1/actionhistory").arg(m_mockDevice1Port)));
|
|
QNetworkReply *reply = nam.get(request);
|
|
spy.wait(500);
|
|
QCOMPARE(spy.count(), 1);
|
|
|
|
QByteArray actionHistory = reply->readAll();
|
|
qDebug() << "have action history" << actionHistory;
|
|
QVERIFY2(actionTypeId == ActionTypeId(actionHistory), "Action not triggered");
|
|
reply->deleteLater();
|
|
|
|
}
|
|
|
|
void TestRules::verifyRuleNotExecuted()
|
|
{
|
|
QNetworkAccessManager nam;
|
|
QSignalSpy spy(&nam, SIGNAL(finished(QNetworkReply*)));
|
|
QNetworkRequest request(QUrl(QString("http://localhost:%1/actionhistory").arg(m_mockDevice1Port)));
|
|
QNetworkReply *reply = nam.get(request);
|
|
spy.wait();
|
|
QCOMPARE(spy.count(), 1);
|
|
|
|
QByteArray actionHistory = reply->readAll();
|
|
qDebug() << "have action history" << actionHistory;
|
|
QVERIFY2(actionHistory.isEmpty(), "Action is triggered while it should not have been.");
|
|
reply->deleteLater();
|
|
|
|
}
|
|
|
|
|
|
QVariant TestRules::validIntStateBasedRule(const QString &name, const bool &executable, const bool &enabled)
|
|
{
|
|
QVariantMap params;
|
|
|
|
// StateDescriptor
|
|
QVariantMap stateDescriptor;
|
|
stateDescriptor.insert("stateTypeId", mockIntStateId);
|
|
stateDescriptor.insert("deviceId", m_mockDeviceId);
|
|
stateDescriptor.insert("operator", JsonTypes::valueOperatorToString(Types::ValueOperatorLess));
|
|
stateDescriptor.insert("value", 25);
|
|
|
|
// StateEvaluator
|
|
QVariantMap stateEvaluator;
|
|
stateEvaluator.insert("stateDescriptor", stateDescriptor);
|
|
stateEvaluator.insert("operator", JsonTypes::stateOperatorToString(Types::StateOperatorAnd));
|
|
|
|
// RuleAction
|
|
QVariantMap action;
|
|
action.insert("actionTypeId", mockActionIdWithParams);
|
|
QVariantList actionParams;
|
|
QVariantMap param1;
|
|
param1.insert("name", "mockActionParam1");
|
|
param1.insert("value", 5);
|
|
actionParams.append(param1);
|
|
QVariantMap param2;
|
|
param2.insert("name", "mockActionParam2");
|
|
param2.insert("value", true);
|
|
actionParams.append(param2);
|
|
action.insert("deviceId", m_mockDeviceId);
|
|
action.insert("ruleActionParams", actionParams);
|
|
|
|
// RuleExitAction
|
|
QVariantMap exitAction;
|
|
exitAction.insert("actionTypeId", mockActionIdNoParams);
|
|
exitAction.insert("deviceId", m_mockDeviceId);
|
|
exitAction.insert("ruleActionParams", QVariantList());
|
|
|
|
params.insert("name", name);
|
|
params.insert("enabled", enabled);
|
|
params.insert("executable", executable);
|
|
params.insert("stateEvaluator", stateEvaluator);
|
|
params.insert("actions", QVariantList() << action);
|
|
params.insert("exitActions", QVariantList() << exitAction);
|
|
|
|
return params;
|
|
}
|
|
|
|
void TestRules::addRemoveRules_data()
|
|
{
|
|
// RuleAction
|
|
QVariantMap validActionNoParams;
|
|
validActionNoParams.insert("actionTypeId", mockActionIdNoParams);
|
|
validActionNoParams.insert("deviceId", m_mockDeviceId);
|
|
validActionNoParams.insert("ruleActionParams", QVariantList());
|
|
|
|
QVariantMap validActionWithParams;
|
|
validActionWithParams.insert("actionTypeId", mockActionIdNoParams);
|
|
validActionWithParams.insert("deviceId", m_mockDeviceId);
|
|
validActionWithParams.insert("ruleActionParams", QVariantList());
|
|
|
|
QVariantMap invalidAction;
|
|
invalidAction.insert("actionTypeId", ActionTypeId());
|
|
invalidAction.insert("deviceId", m_mockDeviceId);
|
|
invalidAction.insert("ruleActionParams", QVariantList());
|
|
|
|
// RuleExitAction
|
|
QVariantMap validExitActionNoParams;
|
|
validExitActionNoParams.insert("actionTypeId", mockActionIdNoParams);
|
|
validExitActionNoParams.insert("deviceId", m_mockDeviceId);
|
|
validExitActionNoParams.insert("ruleActionParams", QVariantList());
|
|
|
|
QVariantMap invalidExitAction;
|
|
invalidExitAction.insert("actionTypeId", ActionTypeId());
|
|
invalidExitAction.insert("deviceId", m_mockDeviceId);
|
|
invalidExitAction.insert("ruleActionParams", QVariantList());
|
|
|
|
// StateDescriptor
|
|
QVariantMap stateDescriptor;
|
|
stateDescriptor.insert("stateTypeId", mockIntStateId);
|
|
stateDescriptor.insert("deviceId", m_mockDeviceId);
|
|
stateDescriptor.insert("operator", JsonTypes::valueOperatorToString(Types::ValueOperatorLess));
|
|
stateDescriptor.insert("value", "20");
|
|
|
|
// StateEvaluator
|
|
QVariantMap validStateEvaluator;
|
|
validStateEvaluator.insert("stateDescriptor", stateDescriptor);
|
|
validStateEvaluator.insert("operator", JsonTypes::stateOperatorToString(Types::StateOperatorAnd));
|
|
|
|
QVariantMap invalidStateEvaluator;
|
|
stateDescriptor.remove("deviceId");
|
|
invalidStateEvaluator.insert("stateDescriptor", stateDescriptor);
|
|
|
|
// EventDescriptor
|
|
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);
|
|
QVariantList params;
|
|
QVariantMap param1;
|
|
param1.insert("name", "mockParamInt");
|
|
param1.insert("value", 3);
|
|
param1.insert("operator", JsonTypes::valueOperatorToString(Types::ValueOperatorEquals));
|
|
params.append(param1);
|
|
validEventDescriptor2.insert("paramDescriptors", params);
|
|
|
|
QVariantMap validEventDescriptor3;
|
|
validEventDescriptor3.insert("eventTypeId", mockEvent2Id);
|
|
validEventDescriptor3.insert("deviceId", m_mockDeviceId);
|
|
validEventDescriptor3.insert("paramDescriptors", QVariantList());
|
|
|
|
// EventDescriptorList
|
|
QVariantList eventDescriptorList;
|
|
eventDescriptorList.append(validEventDescriptor1);
|
|
eventDescriptorList.append(validEventDescriptor2);
|
|
|
|
QVariantMap invalidEventDescriptor;
|
|
invalidEventDescriptor.insert("eventTypeId", mockEvent1Id);
|
|
invalidEventDescriptor.insert("deviceId", DeviceId());
|
|
invalidEventDescriptor.insert("paramDescriptors", QVariantList());
|
|
|
|
// RuleAction event based
|
|
QVariantMap validActionEventBased;
|
|
validActionEventBased.insert("actionTypeId", mockActionIdWithParams);
|
|
validActionEventBased.insert("deviceId", m_mockDeviceId);
|
|
QVariantMap validActionEventBasedParam1;
|
|
validActionEventBasedParam1.insert("name", "mockActionParam1");
|
|
validActionEventBasedParam1.insert("eventTypeId", mockEvent2Id);
|
|
validActionEventBasedParam1.insert("eventParamName", "mockParamInt");
|
|
QVariantMap validActionEventBasedParam2;
|
|
validActionEventBasedParam2.insert("name", "mockActionParam2");
|
|
validActionEventBasedParam2.insert("value", false);
|
|
validActionEventBased.insert("ruleActionParams", QVariantList() << validActionEventBasedParam1 << validActionEventBasedParam2);
|
|
|
|
QVariantMap invalidActionEventBased;
|
|
invalidActionEventBased.insert("actionTypeId", mockActionIdNoParams);
|
|
invalidActionEventBased.insert("deviceId", m_mockDeviceId);
|
|
validActionEventBasedParam1.insert("value", 10);
|
|
invalidActionEventBased.insert("ruleActionParams", QVariantList() << validActionEventBasedParam1);
|
|
|
|
QVariantMap invalidActionEventBased2;
|
|
invalidActionEventBased2.insert("actionTypeId", mockActionIdWithParams);
|
|
invalidActionEventBased2.insert("deviceId", m_mockDeviceId);
|
|
QVariantMap invalidActionEventBasedParam2;
|
|
invalidActionEventBasedParam2.insert("name", "mockActionParam1");
|
|
invalidActionEventBasedParam2.insert("eventTypeId", mockEvent1Id);
|
|
invalidActionEventBasedParam2.insert("eventParamName", "value");
|
|
QVariantMap invalidActionEventBasedParam3;
|
|
invalidActionEventBasedParam3.insert("name", "mockActionParam2");
|
|
invalidActionEventBasedParam3.insert("value", 2);
|
|
invalidActionEventBased2.insert("ruleActionParams", QVariantList() << invalidActionEventBasedParam2 << invalidActionEventBasedParam3);
|
|
|
|
QVariantMap invalidActionEventBased3;
|
|
invalidActionEventBased3.insert("actionTypeId", mockActionIdWithParams);
|
|
invalidActionEventBased3.insert("deviceId", m_mockDeviceId);
|
|
QVariantMap invalidActionEventBasedParam4;
|
|
invalidActionEventBasedParam4.insert("name", "mockActionParam1");
|
|
invalidActionEventBasedParam4.insert("eventTypeId", mockEvent1Id);
|
|
invalidActionEventBasedParam4.insert("eventParamName", "mockParamInt");
|
|
invalidActionEventBased3.insert("ruleActionParams", QVariantList() << invalidActionEventBasedParam4);
|
|
|
|
|
|
QTest::addColumn<bool>("enabled");
|
|
QTest::addColumn<QVariantMap>("action1");
|
|
QTest::addColumn<QVariantMap>("exitAction1");
|
|
QTest::addColumn<QVariantMap>("eventDescriptor");
|
|
QTest::addColumn<QVariantList>("eventDescriptorList");
|
|
QTest::addColumn<QVariantMap>("stateEvaluator");
|
|
QTest::addColumn<RuleEngine::RuleError>("error");
|
|
QTest::addColumn<bool>("jsonError");
|
|
QTest::addColumn<QString>("name");
|
|
|
|
// Rules with event based actions
|
|
QTest::newRow("valid rule. enabled, 1 Action (eventBased), 1 EventDescriptor, name") << true << validActionEventBased << QVariantMap() << validEventDescriptor3 << QVariantList() << QVariantMap() << RuleEngine::RuleErrorNoError << true << "ActionEventRule1";
|
|
QTest::newRow("invalid rule. enabled, 1 Action (eventBased), 1 EventDescriptor, name") << true << invalidActionEventBased2 << QVariantMap() << validEventDescriptor3 << QVariantList() << QVariantMap() << RuleEngine::RuleErrorInvalidRuleActionParameter << false << "TestRule";
|
|
|
|
QTest::newRow("invalid rule. enabled, 1 Action (eventBased), types not matching, name") << true << invalidActionEventBased3 << QVariantMap() << validEventDescriptor1 << QVariantList() << QVariantMap() << RuleEngine::RuleErrorTypesNotMatching << false << "TestRule";
|
|
|
|
QTest::newRow("invalid rule. enabled, 1 Action (eventBased), 1 EventDescriptor, name") << true << invalidActionEventBased << QVariantMap() << validEventDescriptor2 << QVariantList() << QVariantMap() << RuleEngine::RuleErrorInvalidRuleActionParameter << false << "TestRule";
|
|
QTest::newRow("invalid rule. enabled, 1 Action (eventBased), 1 StateEvaluator, name") << true << validActionEventBased << QVariantMap() << QVariantMap() << QVariantList() << validStateEvaluator << RuleEngine::RuleErrorInvalidRuleActionParameter << false << "TestRule";
|
|
QTest::newRow("invalid rule. enabled, 1 Action (eventBased), 1 EventDescriptor, name") << true << validActionEventBased << validActionEventBased << validEventDescriptor2 << QVariantList() << QVariantMap() << RuleEngine::RuleErrorInvalidRuleFormat << false << "TestRule";
|
|
QTest::newRow("invalid rule. enabled, 1 Action, 1 ExitAction (EventBased), name") << true << validActionNoParams << validActionEventBased << validEventDescriptor2 << QVariantList() << QVariantMap() << RuleEngine::RuleErrorInvalidRuleFormat << false << "TestRule";
|
|
|
|
// Rules with exit actions
|
|
QTest::newRow("valid rule. enabled, 1 Action, 1 Exit Action, 1 StateEvaluator, name") << true << validActionNoParams << validExitActionNoParams << QVariantMap() << QVariantList() << validStateEvaluator << RuleEngine::RuleErrorNoError << true << "TestRule";
|
|
QTest::newRow("valid rule. disabled, 1 Action, 1 Exit Action, 1 StateEvaluator, name") << false << validActionNoParams << validExitActionNoParams << QVariantMap() << QVariantList() << validStateEvaluator << RuleEngine::RuleErrorNoError << true << "TestRule";
|
|
QTest::newRow("invalid rule. disabled, 1 Action, 1 invalid Exit Action, 1 StateEvaluator, name") << false << validActionNoParams << invalidExitAction << QVariantMap() << QVariantList() << validStateEvaluator << RuleEngine::RuleErrorActionTypeNotFound << false << "TestRule";
|
|
QTest::newRow("invalid rule. 1 Action, 1 Exit Action, 1 EventDescriptor, 1 StateEvaluator, name") << true << validActionNoParams << validExitActionNoParams << validEventDescriptor1 << QVariantList() << validStateEvaluator << RuleEngine::RuleErrorInvalidRuleFormat << false << "TestRule";
|
|
QTest::newRow("invalid rule. 1 Action, 1 Exit Action, eventDescriptorList, 1 StateEvaluator, name") << true << validActionNoParams << validExitActionNoParams << QVariantMap() << eventDescriptorList << validStateEvaluator << RuleEngine::RuleErrorInvalidRuleFormat << false << "TestRule";
|
|
|
|
// Rules without exit actions
|
|
QTest::newRow("valid rule. enabled, 1 EventDescriptor, StateEvaluator, 1 Action, name") << true << validActionNoParams << QVariantMap() << validEventDescriptor1 << QVariantList() << validStateEvaluator << RuleEngine::RuleErrorNoError << true << "TestRule";
|
|
QTest::newRow("valid rule. diabled, 1 EventDescriptor, StateEvaluator, 1 Action, name") << false << validActionNoParams << QVariantMap() << validEventDescriptor1 << QVariantList() << validStateEvaluator << RuleEngine::RuleErrorNoError << true << "TestRule";
|
|
QTest::newRow("valid rule. 2 EventDescriptors, 1 Action, name") << true << validActionNoParams << QVariantMap() << QVariantMap() << eventDescriptorList << validStateEvaluator << RuleEngine::RuleErrorNoError << true << "TestRule";
|
|
QTest::newRow("invalid rule: eventDescriptor and eventDescriptorList used") << true << validActionNoParams << QVariantMap() << validEventDescriptor1 << eventDescriptorList << validStateEvaluator << RuleEngine::RuleErrorInvalidParameter << false << "TestRule";
|
|
QTest::newRow("invalid action") << true << invalidAction << QVariantMap() << validEventDescriptor1 << QVariantList() << validStateEvaluator << RuleEngine::RuleErrorActionTypeNotFound << false << "TestRule";
|
|
QTest::newRow("invalid event descriptor") << true << validActionNoParams << QVariantMap() << invalidEventDescriptor << QVariantList() << validStateEvaluator << RuleEngine::RuleErrorDeviceNotFound << false << "TestRule";
|
|
QTest::newRow("invalid StateDescriptor") << true << validActionNoParams << QVariantMap() << validEventDescriptor1 << QVariantList() << invalidStateEvaluator << RuleEngine::RuleErrorInvalidParameter << true << "TestRule";
|
|
}
|
|
|
|
void TestRules::addRemoveRules()
|
|
{
|
|
QFETCH(bool, enabled);
|
|
QFETCH(QVariantMap, action1);
|
|
QFETCH(QVariantMap, exitAction1);
|
|
QFETCH(QVariantMap, eventDescriptor);
|
|
QFETCH(QVariantList, eventDescriptorList);
|
|
QFETCH(QVariantMap, stateEvaluator);
|
|
QFETCH(RuleEngine::RuleError, error);
|
|
QFETCH(bool, jsonError);
|
|
QFETCH(QString, name);
|
|
|
|
QVariantMap params;
|
|
params.insert("name", name);
|
|
|
|
QVariantList actions;
|
|
actions.append(action1);
|
|
params.insert("actions", actions);
|
|
|
|
if (!eventDescriptor.isEmpty()) {
|
|
params.insert("eventDescriptor", eventDescriptor);
|
|
}
|
|
if (!eventDescriptorList.isEmpty()) {
|
|
params.insert("eventDescriptorList", eventDescriptorList);
|
|
}
|
|
QVariantList exitActions;
|
|
if (!exitAction1.isEmpty()) {
|
|
exitActions.append(exitAction1);
|
|
params.insert("exitActions", exitActions);
|
|
}
|
|
params.insert("stateEvaluator", stateEvaluator);
|
|
if (!enabled) {
|
|
params.insert("enabled", enabled);
|
|
}
|
|
QVariant response = injectAndWait("Rules.AddRule", params);
|
|
if (!jsonError) {
|
|
verifyRuleError(response, error);
|
|
}
|
|
|
|
RuleId newRuleId = RuleId(response.toMap().value("params").toMap().value("ruleId").toString());
|
|
|
|
response = injectAndWait("Rules.GetRules");
|
|
QVariantList rules = response.toMap().value("params").toMap().value("ruleDescriptions").toList();
|
|
|
|
if (error != RuleEngine::RuleErrorNoError) {
|
|
QVERIFY2(rules.count() == 0, "There should be no rules.");
|
|
return;
|
|
}
|
|
|
|
QVERIFY2(rules.count() == 1, "There should be exactly one rule");
|
|
QCOMPARE(RuleId(rules.first().toMap().value("id").toString()), newRuleId);
|
|
|
|
params.clear();
|
|
params.insert("ruleId", newRuleId);
|
|
response = injectAndWait("Rules.GetRuleDetails", params);
|
|
// verifySuccess(response);
|
|
|
|
QVariantMap rule = response.toMap().value("params").toMap().value("rule").toMap();
|
|
|
|
qDebug() << rule.value("name").toString();
|
|
QVERIFY2(rule.value("enabled").toBool() == enabled, "Rule enabled state doesn't match");
|
|
QVariantList eventDescriptors = rule.value("eventDescriptors").toList();
|
|
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");
|
|
}
|
|
}
|
|
QVERIFY2(found, "Missing event descriptor");
|
|
}
|
|
}
|
|
|
|
QVariantList replyActions = rule.value("actions").toList();
|
|
QVERIFY2(actions == replyActions, "Actions don't match");
|
|
|
|
QVariantList replyExitActions = rule.value("exitActions").toList();
|
|
QVERIFY2(exitActions == replyExitActions, "ExitActions don't match");
|
|
|
|
params.clear();
|
|
params.insert("ruleId", newRuleId);
|
|
response = injectAndWait("Rules.RemoveRule", params);
|
|
verifyRuleError(response);
|
|
|
|
response = injectAndWait("Rules.GetRules");
|
|
rules = response.toMap().value("params").toMap().value("ruleDescriptions").toList();
|
|
QVERIFY2(rules.count() == 0, "There should be no rules.");
|
|
}
|
|
|
|
void TestRules::editRules_data()
|
|
{
|
|
// RuleAction
|
|
QVariantMap validActionNoParams;
|
|
validActionNoParams.insert("actionTypeId", mockActionIdNoParams);
|
|
validActionNoParams.insert("deviceId", m_mockDeviceId);
|
|
validActionNoParams.insert("ruleActionParams", QVariantList());
|
|
|
|
QVariantMap invalidAction;
|
|
invalidAction.insert("actionTypeId", ActionTypeId());
|
|
invalidAction.insert("deviceId", m_mockDeviceId);
|
|
invalidAction.insert("ruleActionParams", QVariantList());
|
|
|
|
// RuleExitAction
|
|
QVariantMap validExitActionNoParams;
|
|
validExitActionNoParams.insert("actionTypeId", mockActionIdNoParams);
|
|
validExitActionNoParams.insert("deviceId", m_mockDeviceId);
|
|
validExitActionNoParams.insert("ruleActionParams", QVariantList());
|
|
|
|
QVariantMap invalidExitAction;
|
|
invalidExitAction.insert("actionTypeId", ActionTypeId());
|
|
invalidExitAction.insert("deviceId", m_mockDeviceId);
|
|
invalidExitAction.insert("ruleActionParams", QVariantList());
|
|
|
|
// StateDescriptor
|
|
QVariantMap stateDescriptor;
|
|
stateDescriptor.insert("stateTypeId", mockIntStateId);
|
|
stateDescriptor.insert("deviceId", m_mockDeviceId);
|
|
stateDescriptor.insert("operator", JsonTypes::valueOperatorToString(Types::ValueOperatorLess));
|
|
stateDescriptor.insert("value", "20");
|
|
|
|
// StateEvaluator
|
|
QVariantMap validStateEvaluator;
|
|
validStateEvaluator.insert("stateDescriptor", stateDescriptor);
|
|
validStateEvaluator.insert("operator", JsonTypes::stateOperatorToString(Types::StateOperatorAnd));
|
|
|
|
QVariantMap invalidStateEvaluator;
|
|
stateDescriptor.remove("deviceId");
|
|
invalidStateEvaluator.insert("stateDescriptor", stateDescriptor);
|
|
|
|
// EventDescriptor
|
|
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);
|
|
QVariantList params;
|
|
QVariantMap param1;
|
|
param1.insert("name", "mockParamInt");
|
|
param1.insert("value", 3);
|
|
param1.insert("operator", JsonTypes::valueOperatorToString(Types::ValueOperatorEquals));
|
|
params.append(param1);
|
|
validEventDescriptor2.insert("paramDescriptors", params);
|
|
|
|
QVariantMap validEventDescriptor3;
|
|
validEventDescriptor3.insert("eventTypeId", mockEvent2Id);
|
|
validEventDescriptor3.insert("deviceId", m_mockDeviceId);
|
|
validEventDescriptor3.insert("paramDescriptors", QVariantList());
|
|
|
|
// EventDescriptorList
|
|
QVariantList eventDescriptorList;
|
|
eventDescriptorList.append(validEventDescriptor1);
|
|
eventDescriptorList.append(validEventDescriptor2);
|
|
|
|
QVariantMap invalidEventDescriptor;
|
|
invalidEventDescriptor.insert("eventTypeId", mockEvent1Id);
|
|
invalidEventDescriptor.insert("deviceId", DeviceId());
|
|
invalidEventDescriptor.insert("paramDescriptors", QVariantList());
|
|
|
|
// RuleAction event based
|
|
QVariantMap validActionEventBased;
|
|
validActionEventBased.insert("actionTypeId", mockActionIdWithParams);
|
|
validActionEventBased.insert("deviceId", m_mockDeviceId);
|
|
QVariantMap validActionEventBasedParam1;
|
|
validActionEventBasedParam1.insert("name", "mockActionParam1");
|
|
validActionEventBasedParam1.insert("eventTypeId", mockEvent2Id);
|
|
validActionEventBasedParam1.insert("eventParamName", "mockParamInt");
|
|
QVariantMap validActionEventBasedParam2;
|
|
validActionEventBasedParam2.insert("name", "mockActionParam2");
|
|
validActionEventBasedParam2.insert("value", false);
|
|
validActionEventBased.insert("ruleActionParams", QVariantList() << validActionEventBasedParam1 << validActionEventBasedParam2);
|
|
|
|
QVariantMap invalidActionEventBased;
|
|
invalidActionEventBased.insert("actionTypeId", mockActionIdNoParams);
|
|
invalidActionEventBased.insert("deviceId", m_mockDeviceId);
|
|
validActionEventBasedParam1.insert("value", 10);
|
|
invalidActionEventBased.insert("ruleActionParams", QVariantList() << validActionEventBasedParam1);
|
|
|
|
QVariantMap invalidActionEventBased2;
|
|
invalidActionEventBased2.insert("actionTypeId", mockActionIdWithParams);
|
|
invalidActionEventBased2.insert("deviceId", m_mockDeviceId);
|
|
QVariantMap invalidActionEventBasedParam2;
|
|
invalidActionEventBasedParam2.insert("name", "mockActionParam1");
|
|
invalidActionEventBasedParam2.insert("eventTypeId", mockEvent1Id);
|
|
invalidActionEventBasedParam2.insert("eventParamName", "value");
|
|
QVariantMap invalidActionEventBasedParam3;
|
|
invalidActionEventBasedParam3.insert("name", "mockActionParam2");
|
|
invalidActionEventBasedParam3.insert("value", 2);
|
|
invalidActionEventBased2.insert("ruleActionParams", QVariantList() << invalidActionEventBasedParam2 << invalidActionEventBasedParam3);
|
|
|
|
QVariantMap invalidActionEventBased3;
|
|
invalidActionEventBased3.insert("actionTypeId", mockActionIdWithParams);
|
|
invalidActionEventBased3.insert("deviceId", m_mockDeviceId);
|
|
QVariantMap invalidActionEventBasedParam4;
|
|
invalidActionEventBasedParam4.insert("name", "mockActionParam1");
|
|
invalidActionEventBasedParam4.insert("eventTypeId", mockEvent1Id);
|
|
invalidActionEventBasedParam4.insert("eventParamName", "mockParamInt");
|
|
invalidActionEventBased3.insert("ruleActionParams", QVariantList() << invalidActionEventBasedParam4);
|
|
|
|
QTest::addColumn<bool>("enabled");
|
|
QTest::addColumn<QVariantMap>("action");
|
|
QTest::addColumn<QVariantMap>("exitAction");
|
|
QTest::addColumn<QVariantMap>("eventDescriptor");
|
|
QTest::addColumn<QVariantList>("eventDescriptorList");
|
|
QTest::addColumn<QVariantMap>("stateEvaluator");
|
|
QTest::addColumn<RuleEngine::RuleError>("error");
|
|
QTest::addColumn<QString>("name");
|
|
|
|
// Rules with event based actions
|
|
QTest::newRow("valid rule. enabled, 1 Action (eventBased), 1 EventDescriptor, name") << true << validActionEventBased << QVariantMap() << validEventDescriptor3 << QVariantList() << QVariantMap() << RuleEngine::RuleErrorNoError << "ActionEventRule1";
|
|
QTest::newRow("invalid rule. enabled, 1 Action (eventBased), 1 EventDescriptor, name") << true << invalidActionEventBased2 << QVariantMap() << validEventDescriptor3 << QVariantList() << QVariantMap() << RuleEngine::RuleErrorInvalidRuleActionParameter << "TestRule";
|
|
|
|
QTest::newRow("invalid rule. enabled, 1 Action (eventBased), types not matching, name") << true << invalidActionEventBased3 << QVariantMap() << validEventDescriptor1 << QVariantList() << QVariantMap() << RuleEngine::RuleErrorTypesNotMatching << "TestRule";
|
|
|
|
QTest::newRow("invalid rule. enabled, 1 Action (eventBased), 1 EventDescriptor, name") << true << invalidActionEventBased << QVariantMap() << validEventDescriptor2 << QVariantList() << QVariantMap() << RuleEngine::RuleErrorInvalidRuleActionParameter << "TestRule";
|
|
QTest::newRow("invalid rule. enabled, 1 Action (eventBased), 1 StateEvaluator, name") << true << validActionEventBased << QVariantMap() << QVariantMap() << QVariantList() << validStateEvaluator << RuleEngine::RuleErrorInvalidRuleActionParameter << "TestRule";
|
|
QTest::newRow("invalid rule. enabled, 1 Action (eventBased), 1 EventDescriptor, name") << true << validActionEventBased << validActionEventBased << validEventDescriptor2 << QVariantList() << QVariantMap() << RuleEngine::RuleErrorInvalidRuleFormat << "TestRule";
|
|
QTest::newRow("invalid rule. enabled, 1 Action, 1 ExitAction (EventBased), name") << true << validActionNoParams << validActionEventBased << validEventDescriptor2 << QVariantList() << QVariantMap() << RuleEngine::RuleErrorInvalidRuleFormat << "TestRule";
|
|
|
|
// Rules with exit actions
|
|
QTest::newRow("valid rule. enabled, 1 Action, 1 Exit Action, 1 StateEvaluator, name") << true << validActionNoParams << validExitActionNoParams << QVariantMap() << QVariantList() << validStateEvaluator << RuleEngine::RuleErrorNoError << "TestRule";
|
|
QTest::newRow("valid rule. disabled, 1 Action, 1 Exit Action, 1 StateEvaluator, name") << false << validActionNoParams << validExitActionNoParams << QVariantMap() << QVariantList() << validStateEvaluator << RuleEngine::RuleErrorNoError << "TestRule";
|
|
QTest::newRow("invalid rule. 1 Action, 1 Exit Action, 1 EventDescriptor, 1 StateEvaluator, name") << true << validActionNoParams << validExitActionNoParams << validEventDescriptor1 << QVariantList() << validStateEvaluator << RuleEngine::RuleErrorInvalidRuleFormat << "TestRule";
|
|
QTest::newRow("invalid rule. 1 Action, 1 Exit Action, eventDescriptorList, 1 StateEvaluator, name") << true << validActionNoParams << validExitActionNoParams << QVariantMap() << eventDescriptorList << validStateEvaluator << RuleEngine::RuleErrorInvalidRuleFormat << "TestRule";
|
|
|
|
// Rules without exit actions
|
|
QTest::newRow("valid rule. enabled, 1 EventDescriptor, StateEvaluator, 1 Action, name") << true << validActionNoParams << QVariantMap() << validEventDescriptor1 << QVariantList() << validStateEvaluator << RuleEngine::RuleErrorNoError << "TestRule";
|
|
QTest::newRow("valid rule. diabled, 1 EventDescriptor, StateEvaluator, 1 Action, name") << false << validActionNoParams << QVariantMap() << validEventDescriptor1 << QVariantList() << validStateEvaluator << RuleEngine::RuleErrorNoError << "TestRule";
|
|
QTest::newRow("valid rule. 2 EventDescriptors, 1 Action, name") << true << validActionNoParams << QVariantMap() << QVariantMap() << eventDescriptorList << validStateEvaluator << RuleEngine::RuleErrorNoError << "TestRule";
|
|
QTest::newRow("invalid rule: eventDescriptor and eventDescriptorList used") << true << validActionNoParams << QVariantMap() << validEventDescriptor1 << eventDescriptorList << validStateEvaluator << RuleEngine::RuleErrorInvalidParameter << "TestRule";
|
|
}
|
|
|
|
void TestRules::editRules()
|
|
{
|
|
QFETCH(bool, enabled);
|
|
QFETCH(QVariantMap, action);
|
|
QFETCH(QVariantMap, exitAction);
|
|
QFETCH(QVariantMap, eventDescriptor);
|
|
QFETCH(QVariantList, eventDescriptorList);
|
|
QFETCH(QVariantMap, stateEvaluator);
|
|
QFETCH(RuleEngine::RuleError, error);
|
|
QFETCH(QString, name);
|
|
|
|
// Add the rule we want to edit
|
|
QVariantList eventParamDescriptors;
|
|
QVariantMap eventDescriptor1;
|
|
eventDescriptor1.insert("eventTypeId", mockEvent1Id);
|
|
eventDescriptor1.insert("deviceId", m_mockDeviceId);
|
|
eventDescriptor1.insert("paramDescriptors", QVariantList());
|
|
QVariantMap eventDescriptor2;
|
|
eventDescriptor2.insert("eventTypeId", mockEvent2Id);
|
|
eventDescriptor2.insert("deviceId", m_mockDeviceId);
|
|
eventDescriptor2.insert("paramDescriptors", QVariantList());
|
|
QVariantMap eventParam1;
|
|
eventParam1.insert("name", "mockParamInt");
|
|
eventParam1.insert("value", 3);
|
|
eventParam1.insert("operator", JsonTypes::valueOperatorToString(Types::ValueOperatorEquals));
|
|
eventParamDescriptors.append(eventParam1);
|
|
eventDescriptor2.insert("paramDescriptors", eventParamDescriptors);
|
|
|
|
QVariantList eventDescriptorList1;
|
|
eventDescriptorList1.append(eventDescriptor1);
|
|
eventDescriptorList1.append(eventDescriptor2);
|
|
|
|
QVariantMap stateEvaluator0;
|
|
QVariantMap stateDescriptor1;
|
|
stateDescriptor1.insert("deviceId", m_mockDeviceId);
|
|
stateDescriptor1.insert("operator", JsonTypes::valueOperatorToString(Types::ValueOperatorEquals));
|
|
stateDescriptor1.insert("stateTypeId", mockIntStateId);
|
|
stateDescriptor1.insert("value", 1);
|
|
QVariantMap stateDescriptor2;
|
|
stateDescriptor2.insert("deviceId", m_mockDeviceId);
|
|
stateDescriptor2.insert("operator", JsonTypes::valueOperatorToString(Types::ValueOperatorEquals));
|
|
stateDescriptor2.insert("stateTypeId", mockBoolStateId);
|
|
stateDescriptor2.insert("value", true);
|
|
QVariantMap stateEvaluator1;
|
|
stateEvaluator1.insert("stateDescriptor", stateDescriptor1);
|
|
stateEvaluator1.insert("operator", JsonTypes::stateOperatorToString(Types::StateOperatorAnd));
|
|
QVariantMap stateEvaluator2;
|
|
stateEvaluator2.insert("stateDescriptor", stateDescriptor2);
|
|
stateEvaluator2.insert("operator", JsonTypes::stateOperatorToString(Types::StateOperatorAnd));
|
|
QVariantList childEvaluators;
|
|
childEvaluators.append(stateEvaluator1);
|
|
childEvaluators.append(stateEvaluator2);
|
|
stateEvaluator0.insert("childEvaluators", childEvaluators);
|
|
stateEvaluator0.insert("operator", JsonTypes::stateOperatorToString(Types::StateOperatorAnd));
|
|
|
|
QVariantMap action1;
|
|
action1.insert("actionTypeId", mockActionIdNoParams);
|
|
action1.insert("deviceId", m_mockDeviceId);
|
|
action1.insert("ruleActionParams", QVariantList());
|
|
QVariantMap action2;
|
|
action2.insert("actionTypeId", mockActionIdWithParams);
|
|
qDebug() << "got action id" << mockActionIdWithParams;
|
|
action2.insert("deviceId", m_mockDeviceId);
|
|
QVariantList action2Params;
|
|
QVariantMap action2Param1;
|
|
action2Param1.insert("name", "mockActionParam1");
|
|
action2Param1.insert("value", 5);
|
|
action2Params.append(action2Param1);
|
|
QVariantMap action2Param2;
|
|
action2Param2.insert("name", "mockActionParam2");
|
|
action2Param2.insert("value", true);
|
|
action2Params.append(action2Param2);
|
|
action2.insert("ruleActionParams", action2Params);
|
|
|
|
// RuleAction event based
|
|
QVariantMap validActionEventBased;
|
|
validActionEventBased.insert("actionTypeId", mockActionIdWithParams);
|
|
validActionEventBased.insert("deviceId", m_mockDeviceId);
|
|
QVariantMap validActionEventBasedParam1;
|
|
validActionEventBasedParam1.insert("name", "mockActionParam1");
|
|
validActionEventBasedParam1.insert("eventTypeId", mockEvent2Id);
|
|
validActionEventBasedParam1.insert("eventParamName", "mockParamInt");
|
|
QVariantMap validActionEventBasedParam2;
|
|
validActionEventBasedParam2.insert("name", "mockActionParam2");
|
|
validActionEventBasedParam2.insert("value", false);
|
|
validActionEventBased.insert("ruleActionParams", QVariantList() << validActionEventBasedParam1 << validActionEventBasedParam2);
|
|
|
|
QVariantList validEventDescriptors3;
|
|
QVariantMap validEventDescriptor3;
|
|
validEventDescriptor3.insert("eventTypeId", mockEvent2Id);
|
|
validEventDescriptor3.insert("deviceId", m_mockDeviceId);
|
|
validEventDescriptor3.insert("paramDescriptors", QVariantList());
|
|
validEventDescriptors3.append(validEventDescriptor3);
|
|
|
|
QVariantMap params;
|
|
QVariantList actions;
|
|
actions.append(action1);
|
|
actions.append(action2);
|
|
params.insert("actions", actions);
|
|
params.insert("eventDescriptorList", eventDescriptorList1);
|
|
params.insert("stateEvaluator", stateEvaluator0);
|
|
params.insert("name", "TestRule");
|
|
QVariant response = injectAndWait("Rules.AddRule", params);
|
|
|
|
RuleId ruleId = RuleId(response.toMap().value("params").toMap().value("ruleId").toString());
|
|
verifyRuleError(response);
|
|
|
|
// enable notifications
|
|
QCOMPARE(enableNotifications(), true);
|
|
|
|
// now create the new rule and edit the original one
|
|
params.clear();
|
|
params.insert("ruleId", ruleId.toString());
|
|
params.insert("name", name);
|
|
|
|
if (!eventDescriptor.isEmpty()) {
|
|
params.insert("eventDescriptor", eventDescriptor);
|
|
}
|
|
if (!eventDescriptorList.isEmpty()) {
|
|
params.insert("eventDescriptorList", eventDescriptorList);
|
|
}
|
|
actions.clear();
|
|
actions.append(action);
|
|
params.insert("actions", actions);
|
|
|
|
QVariantList exitActions;
|
|
if (!exitAction.isEmpty()) {
|
|
exitActions.append(exitAction);
|
|
params.insert("exitActions", exitActions);
|
|
}
|
|
params.insert("stateEvaluator", stateEvaluator);
|
|
if (!enabled) {
|
|
params.insert("enabled", enabled);
|
|
}
|
|
|
|
// Setup connection to mock client
|
|
QSignalSpy clientSpy(m_mockTcpServer, SIGNAL(outgoingData(QUuid,QByteArray)));
|
|
response.clear();
|
|
response = injectAndWait("Rules.EditRule", params);
|
|
verifyRuleError(response, error);
|
|
if (error == RuleEngine::RuleErrorNoError){
|
|
clientSpy.wait(500);
|
|
QVariant notification = checkNotification(clientSpy, "Rules.RuleConfigurationChanged");
|
|
QVERIFY2(notification != QVariant(), "not received \"Rules.RuleConfigurationChanged\" notification");
|
|
|
|
// now check if the received rule matches the our new rule
|
|
QVariantMap rule = response.toMap().value("params").toMap().value("rule").toMap();
|
|
|
|
QVERIFY2(rule.value("enabled").toBool() == enabled, "Rule enabled state doesn't match");
|
|
QVariantList eventDescriptors = rule.value("eventDescriptors").toList();
|
|
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");
|
|
}
|
|
}
|
|
QVERIFY2(found, "Missing event descriptor");
|
|
}
|
|
}
|
|
|
|
QVariantList replyActions = rule.value("actions").toList();
|
|
QVERIFY2(actions == replyActions, "Actions don't match");
|
|
|
|
QVariantList replyExitActions = rule.value("exitActions").toList();
|
|
QVERIFY2(exitActions == replyExitActions, "ExitActions don't match");
|
|
}
|
|
|
|
// Remove the rule
|
|
params.clear();
|
|
params.insert("ruleId", ruleId);
|
|
response = injectAndWait("Rules.RemoveRule", params);
|
|
verifyRuleError(response);
|
|
|
|
// check if removed
|
|
response = injectAndWait("Rules.GetRules");
|
|
QVariantList rules = response.toMap().value("params").toMap().value("rules").toList();
|
|
QVERIFY2(rules.count() == 0, "There should be no rules.");
|
|
}
|
|
|
|
void TestRules::executeRuleActions_data()
|
|
{
|
|
QTest::addColumn<QVariantMap>("params");
|
|
QTest::addColumn<RuleEngine::RuleError>("ruleError");
|
|
|
|
QTest::newRow("executable rule, enabled") << validIntStateBasedRule("Executeable", true, true).toMap() << RuleEngine::RuleErrorNoError;
|
|
QTest::newRow("executable rule, disabled") << validIntStateBasedRule("Executeable", true, false).toMap() << RuleEngine::RuleErrorNoError;
|
|
QTest::newRow("not executable rule, enabled") << validIntStateBasedRule("Not Executable", false, true).toMap() << RuleEngine::RuleErrorNotExecutable;
|
|
QTest::newRow("not executable rule, disabled") << validIntStateBasedRule("Not Executable", false, false).toMap() << RuleEngine::RuleErrorNotExecutable;
|
|
}
|
|
|
|
void TestRules::executeRuleActions()
|
|
{
|
|
QFETCH(QVariantMap, params);
|
|
QFETCH(RuleEngine::RuleError, ruleError);
|
|
|
|
// ADD rule
|
|
QVariant response = injectAndWait("Rules.AddRule", params);
|
|
verifyRuleError(response);
|
|
|
|
RuleId ruleId = RuleId(response.toMap().value("params").toMap().value("ruleId").toString());
|
|
QVERIFY(!ruleId.isNull());
|
|
|
|
cleanupMockHistory();
|
|
|
|
// EXECUTE actions
|
|
QVariantMap executeParams;
|
|
executeParams.insert("ruleId", ruleId.toString());
|
|
response = injectAndWait("Rules.ExecuteActions", executeParams);
|
|
verifyRuleError(response, ruleError);
|
|
|
|
if (ruleError == RuleEngine::RuleErrorNoError) {
|
|
verifyRuleExecuted(mockActionIdWithParams);
|
|
} else {
|
|
verifyRuleNotExecuted();
|
|
}
|
|
|
|
cleanupMockHistory();
|
|
|
|
// EXECUTE exit actions
|
|
response = injectAndWait("Rules.ExecuteExitActions", executeParams);
|
|
verifyRuleError(response, ruleError);
|
|
|
|
if (ruleError == RuleEngine::RuleErrorNoError) {
|
|
verifyRuleExecuted(mockActionIdNoParams);
|
|
} else {
|
|
verifyRuleNotExecuted();
|
|
}
|
|
|
|
cleanupMockHistory();
|
|
|
|
// REMOVE rule
|
|
QVariantMap removeParams;
|
|
removeParams.insert("ruleId", ruleId);
|
|
response = injectAndWait("Rules.RemoveRule", removeParams);
|
|
verifyRuleError(response);
|
|
}
|
|
|
|
void TestRules::findRule()
|
|
{
|
|
// ADD rule
|
|
QVariantMap params = validIntStateBasedRule("Executeable", true, true).toMap();
|
|
QVariant response = injectAndWait("Rules.AddRule", params);
|
|
verifyRuleError(response);
|
|
|
|
RuleId ruleId = RuleId(response.toMap().value("params").toMap().value("ruleId").toString());
|
|
QVERIFY(!ruleId.isNull());
|
|
|
|
params.clear();
|
|
params.insert("deviceId", m_mockDeviceId);
|
|
response = injectAndWait("Rules.FindRules", params);
|
|
|
|
QCOMPARE(response.toMap().value("params").toMap().value("ruleIds").toList().count(), 1);
|
|
QCOMPARE(response.toMap().value("params").toMap().value("ruleIds").toList().first().toString(), ruleId.toString());
|
|
|
|
// REMOVE rule
|
|
QVariantMap removeParams;
|
|
removeParams.insert("ruleId", ruleId);
|
|
response = injectAndWait("Rules.RemoveRule", removeParams);
|
|
verifyRuleError(response);
|
|
|
|
}
|
|
|
|
void TestRules::removeInvalidRule()
|
|
{
|
|
QVariantMap params;
|
|
params.insert("ruleId", RuleId::createRuleId());
|
|
QVariant response = injectAndWait("Rules.RemoveRule", params);
|
|
verifyRuleError(response, RuleEngine::RuleErrorRuleNotFound);
|
|
}
|
|
|
|
void TestRules::loadStoreConfig()
|
|
{
|
|
QVariantMap eventDescriptor1;
|
|
eventDescriptor1.insert("eventTypeId", mockEvent1Id);
|
|
eventDescriptor1.insert("deviceId", m_mockDeviceId);
|
|
eventDescriptor1.insert("paramDescriptors", QVariantList());
|
|
|
|
QVariantMap eventDescriptor2;
|
|
eventDescriptor2.insert("eventTypeId", mockEvent2Id);
|
|
eventDescriptor2.insert("deviceId", m_mockDeviceId);
|
|
eventDescriptor2.insert("paramDescriptors", QVariantList());
|
|
QVariantList eventParamDescriptors;
|
|
QVariantMap eventParam1;
|
|
eventParam1.insert("name", "mockParamInt");
|
|
eventParam1.insert("value", 3);
|
|
eventParam1.insert("operator", JsonTypes::valueOperatorToString(Types::ValueOperatorEquals));
|
|
eventParamDescriptors.append(eventParam1);
|
|
eventDescriptor2.insert("paramDescriptors", eventParamDescriptors);
|
|
|
|
QVariantList eventDescriptorList;
|
|
eventDescriptorList.append(eventDescriptor1);
|
|
eventDescriptorList.append(eventDescriptor2);
|
|
|
|
QVariantMap stateEvaluator1;
|
|
QVariantList childEvaluators;
|
|
|
|
QVariantMap stateDescriptor2;
|
|
stateDescriptor2.insert("deviceId", m_mockDeviceId);
|
|
stateDescriptor2.insert("operator", JsonTypes::valueOperatorToString(Types::ValueOperatorEquals));
|
|
stateDescriptor2.insert("stateTypeId", mockIntStateId);
|
|
stateDescriptor2.insert("value", 1);
|
|
QVariantMap stateEvaluator2;
|
|
stateEvaluator2.insert("stateDescriptor", stateDescriptor2);
|
|
stateEvaluator2.insert("operator", JsonTypes::stateOperatorToString(Types::StateOperatorAnd));
|
|
|
|
|
|
QVariantMap stateDescriptor3;
|
|
stateDescriptor3.insert("deviceId", m_mockDeviceId);
|
|
stateDescriptor3.insert("operator", JsonTypes::valueOperatorToString(Types::ValueOperatorEquals));
|
|
stateDescriptor3.insert("stateTypeId", mockBoolStateId);
|
|
stateDescriptor3.insert("value", true);
|
|
|
|
QVariantMap stateEvaluator3;
|
|
stateEvaluator3.insert("stateDescriptor", stateDescriptor3);
|
|
stateEvaluator3.insert("operator", JsonTypes::stateOperatorToString(Types::StateOperatorAnd));
|
|
|
|
childEvaluators.append(stateEvaluator2);
|
|
childEvaluators.append(stateEvaluator3);
|
|
stateEvaluator1.insert("childEvaluators", childEvaluators);
|
|
stateEvaluator1.insert("operator", JsonTypes::stateOperatorToString(Types::StateOperatorAnd));
|
|
|
|
QVariantMap action1;
|
|
action1.insert("actionTypeId", mockActionIdNoParams);
|
|
action1.insert("deviceId", m_mockDeviceId);
|
|
action1.insert("ruleActionParams", QVariantList());
|
|
|
|
QVariantMap action2;
|
|
action2.insert("actionTypeId", mockActionIdWithParams);
|
|
qDebug() << "got action id" << mockActionIdWithParams;
|
|
action2.insert("deviceId", m_mockDeviceId);
|
|
QVariantList action2Params;
|
|
QVariantMap action2Param1;
|
|
action2Param1.insert("name", "mockActionParam1");
|
|
action2Param1.insert("value", 5);
|
|
action2Params.append(action2Param1);
|
|
QVariantMap action2Param2;
|
|
action2Param2.insert("name", "mockActionParam2");
|
|
action2Param2.insert("value", true);
|
|
action2Params.append(action2Param2);
|
|
action2.insert("ruleActionParams", action2Params);
|
|
|
|
// RuleAction event based
|
|
QVariantMap validActionEventBased;
|
|
validActionEventBased.insert("actionTypeId", mockActionIdWithParams);
|
|
validActionEventBased.insert("deviceId", m_mockDeviceId);
|
|
QVariantMap validActionEventBasedParam1;
|
|
validActionEventBasedParam1.insert("name", "mockActionParam1");
|
|
validActionEventBasedParam1.insert("eventTypeId", mockEvent2Id);
|
|
validActionEventBasedParam1.insert("eventParamName", "mockParamInt");
|
|
QVariantMap validActionEventBasedParam2;
|
|
validActionEventBasedParam2.insert("name", "mockActionParam2");
|
|
validActionEventBasedParam2.insert("value", false);
|
|
validActionEventBased.insert("ruleActionParams", QVariantList() << validActionEventBasedParam1 << validActionEventBasedParam2);
|
|
|
|
|
|
QVariantList validEventDescriptors3;
|
|
QVariantMap validEventDescriptor3;
|
|
validEventDescriptor3.insert("eventTypeId", mockEvent2Id);
|
|
validEventDescriptor3.insert("deviceId", m_mockDeviceId);
|
|
validEventDescriptor3.insert("paramDescriptors", QVariantList());
|
|
validEventDescriptors3.append(validEventDescriptor3);
|
|
|
|
// rule 1
|
|
QVariantMap params;
|
|
QVariantList actions;
|
|
actions.append(action1);
|
|
actions.append(action2);
|
|
params.insert("actions", actions);
|
|
params.insert("eventDescriptorList", eventDescriptorList);
|
|
params.insert("stateEvaluator", stateEvaluator1);
|
|
params.insert("name", "TestRule");
|
|
QVariant response = injectAndWait("Rules.AddRule", params);
|
|
|
|
RuleId newRuleId = RuleId(response.toMap().value("params").toMap().value("ruleId").toString());
|
|
verifyRuleError(response);
|
|
|
|
// rule 2
|
|
QVariantMap params2;
|
|
QVariantList actions2;
|
|
actions2.append(action1);
|
|
QVariantList exitActions2;
|
|
exitActions2.append(action2);
|
|
params2.insert("actions", actions2);
|
|
params2.insert("exitActions", exitActions2);
|
|
params2.insert("stateEvaluator", stateEvaluator1);
|
|
params2.insert("name", "TestRule2");
|
|
QVariant response2 = injectAndWait("Rules.AddRule", params2);
|
|
|
|
RuleId newRuleId2 = RuleId(response2.toMap().value("params").toMap().value("ruleId").toString());
|
|
verifyRuleError(response2);
|
|
|
|
// rule 3
|
|
QVariantMap params3;
|
|
QVariantList actions3;
|
|
actions3.append(validActionEventBased);
|
|
params3.insert("actions", actions3);
|
|
params3.insert("eventDescriptorList", validEventDescriptors3);
|
|
params3.insert("name", "TestRule3");
|
|
QVariant response3 = injectAndWait("Rules.AddRule", params3);
|
|
|
|
RuleId newRuleId3 = RuleId(response3.toMap().value("params").toMap().value("ruleId").toString());
|
|
verifyRuleError(response3);
|
|
|
|
restartServer();
|
|
|
|
response = injectAndWait("Rules.GetRules");
|
|
|
|
QVariantList rules = response.toMap().value("params").toMap().value("ruleDescriptions").toList();
|
|
|
|
QVERIFY2(rules.count() == 3, "There should be exactly three rule.");
|
|
|
|
QStringList idList;
|
|
foreach (const QVariant &ruleDescription, rules) {
|
|
idList.append(ruleDescription.toMap().value("id").toString());
|
|
}
|
|
|
|
QVERIFY2(idList.contains(newRuleId.toString()), "Rule 1 should be in ruleIds list.");
|
|
QVERIFY2(idList.contains(newRuleId2.toString()), "Rule 2 should be in ruleIds list.");
|
|
QVERIFY2(idList.contains(newRuleId3.toString()), "Rule 3 should be in ruleIds list.");
|
|
|
|
// Rule 1
|
|
params.clear();
|
|
params.insert("ruleId", newRuleId);
|
|
response.clear();
|
|
response = injectAndWait("Rules.GetRuleDetails", params);
|
|
|
|
QVariantMap rule1 = response.toMap().value("params").toMap().value("rule").toMap();
|
|
|
|
QVariantList eventDescriptors = rule1.value("eventDescriptors").toList();
|
|
QVERIFY2(eventDescriptors.count() == 2, "There shoud be exactly 2 eventDescriptors");
|
|
foreach (const QVariant &expectedEventDescriptorVariant, eventDescriptorList) {
|
|
bool found = false;
|
|
foreach (const QVariant &replyEventDescriptorVariant, eventDescriptors) {
|
|
if (expectedEventDescriptorVariant.toMap().value("eventTypeId") == replyEventDescriptorVariant.toMap().value("eventTypeId") &&
|
|
expectedEventDescriptorVariant.toMap().value("deviceId") == replyEventDescriptorVariant.toMap().value("deviceId")) {
|
|
found = true;
|
|
QVERIFY2(replyEventDescriptorVariant == expectedEventDescriptorVariant, "EventDescriptor doesn't match");
|
|
}
|
|
}
|
|
QVERIFY2(found, "missing eventdescriptor");
|
|
}
|
|
|
|
QVERIFY2(rule1.value("name").toString() == "TestRule", "Loaded wrong name for rule");
|
|
QVariantMap replyStateEvaluator= rule1.value("stateEvaluator").toMap();
|
|
QVariantList replyChildEvaluators = replyStateEvaluator.value("childEvaluators").toList();
|
|
QVERIFY2(replyStateEvaluator.value("operator") == "StateOperatorAnd", "There should be the AND operator.");
|
|
QVERIFY2(replyChildEvaluators.count() == 2, "There shoud be exactly 2 childEvaluators");
|
|
|
|
foreach (const QVariant &childEvaluator, replyChildEvaluators) {
|
|
QVERIFY2(childEvaluator.toMap().contains("stateDescriptor"), "StateDescriptor missing in StateEvaluator");
|
|
QVariantMap stateDescriptor = childEvaluator.toMap().value("stateDescriptor").toMap();
|
|
QVERIFY2(stateDescriptor.value("deviceId") == m_mockDeviceId, "DeviceId of stateDescriptor does not match");
|
|
QVERIFY2(stateDescriptor.value("stateTypeId") == mockIntStateId || stateDescriptor.value("stateTypeId") == mockBoolStateId, "StateTypeId of stateDescriptor doesn't match");
|
|
}
|
|
|
|
QVariantList replyActions = rule1.value("actions").toList();
|
|
foreach (const QVariant &actionVariant, actions) {
|
|
bool found = false;
|
|
foreach (const QVariant &replyActionVariant, replyActions) {
|
|
if (actionVariant.toMap().value("actionTypeId") == replyActionVariant.toMap().value("actionTypeId") &&
|
|
actionVariant.toMap().value("deviceId") == replyActionVariant.toMap().value("deviceId")) {
|
|
found = true;
|
|
QJsonDocument bDoc = QJsonDocument::fromVariant(actionVariant);
|
|
QString bString = bDoc.toJson();
|
|
QJsonDocument aDoc = QJsonDocument::fromVariant(replyActionVariant);
|
|
QString aString = aDoc.toJson();
|
|
QVERIFY2(actionVariant == replyActionVariant, QString("Action doesn't match after loading from config.\nBefore storing: %1\nAfter storing:%2").arg(bString).arg(aString).toUtf8().data());
|
|
}
|
|
}
|
|
QVERIFY2(found, "Action not found after loading from config.");
|
|
}
|
|
|
|
// Rule 2
|
|
params.clear();
|
|
params.insert("ruleId", newRuleId2);
|
|
response.clear();
|
|
response = injectAndWait("Rules.GetRuleDetails", params);
|
|
|
|
QVariantMap rule2 = response.toMap().value("params").toMap().value("rule").toMap();
|
|
|
|
QVERIFY2(rule2.value("name").toString() == "TestRule2", "Loaded wrong name for rule");
|
|
QVariantMap replyStateEvaluator2= rule2.value("stateEvaluator").toMap();
|
|
QVariantList replyChildEvaluators2 = replyStateEvaluator.value("childEvaluators").toList();
|
|
QVERIFY2(replyStateEvaluator2.value("operator") == "StateOperatorAnd", "There should be the AND operator.");
|
|
QVERIFY2(replyChildEvaluators2.count() == 2, "There shoud be exactly 2 childEvaluators");
|
|
|
|
foreach (const QVariant &childEvaluator, replyChildEvaluators2) {
|
|
QVERIFY2(childEvaluator.toMap().contains("stateDescriptor"), "StateDescriptor missing in StateEvaluator");
|
|
QVariantMap stateDescriptor = childEvaluator.toMap().value("stateDescriptor").toMap();
|
|
QVERIFY2(stateDescriptor.value("deviceId") == m_mockDeviceId, "DeviceId of stateDescriptor does not match");
|
|
QVERIFY2(stateDescriptor.value("stateTypeId") == mockIntStateId || stateDescriptor.value("stateTypeId") == mockBoolStateId, "StateTypeId of stateDescriptor doesn't match");
|
|
}
|
|
|
|
QVariantList replyActions2 = rule2.value("actions").toList();
|
|
QVERIFY2(replyActions2.count() == 1, "Rule 2 should have exactly 1 action");
|
|
foreach (const QVariant &actionVariant, actions2) {
|
|
bool found = false;
|
|
foreach (const QVariant &replyActionVariant, replyActions2) {
|
|
if (actionVariant.toMap().value("actionTypeId") == replyActionVariant.toMap().value("actionTypeId") &&
|
|
actionVariant.toMap().value("deviceId") == replyActionVariant.toMap().value("deviceId")) {
|
|
found = true;
|
|
QJsonDocument bDoc = QJsonDocument::fromVariant(actionVariant);
|
|
QString bString = bDoc.toJson();
|
|
QJsonDocument aDoc = QJsonDocument::fromVariant(replyActionVariant);
|
|
QString aString = aDoc.toJson();
|
|
QVERIFY2(actionVariant == replyActionVariant, QString("Action doesn't match after loading from config.\nBefore storing: %1\nAfter storing:%2").arg(bString).arg(aString).toUtf8().data());
|
|
}
|
|
}
|
|
QVERIFY2(found, "Action not found after loading from config.");
|
|
}
|
|
|
|
QVariantList replyExitActions2 = rule2.value("exitActions").toList();
|
|
QVERIFY2(replyExitActions2.count() == 1, "Rule 2 should have exactly 1 exitAction");
|
|
foreach (const QVariant &exitActionVariant, replyExitActions2) {
|
|
bool found = false;
|
|
foreach (const QVariant &replyActionVariant, replyExitActions2) {
|
|
if (exitActionVariant.toMap().value("actionTypeId") == replyActionVariant.toMap().value("actionTypeId") &&
|
|
exitActionVariant.toMap().value("deviceId") == replyActionVariant.toMap().value("deviceId")) {
|
|
found = true;
|
|
QJsonDocument bDoc = QJsonDocument::fromVariant(exitActionVariant);
|
|
QString bString = bDoc.toJson();
|
|
QJsonDocument aDoc = QJsonDocument::fromVariant(replyActionVariant);
|
|
QString aString = aDoc.toJson();
|
|
QVERIFY2(exitActionVariant == replyActionVariant, QString("Action doesn't match after loading from config.\nBefore storing: %1\nAfter storing:%2").arg(bString).arg(aString).toUtf8().data());
|
|
}
|
|
}
|
|
QVERIFY2(found, "Exit Action not found after loading from config.");
|
|
}
|
|
|
|
// Rule 3
|
|
params.clear();
|
|
params.insert("ruleId", newRuleId3);
|
|
response.clear();
|
|
response = injectAndWait("Rules.GetRuleDetails", params);
|
|
|
|
QVariantMap rule3 = response.toMap().value("params").toMap().value("rule").toMap();
|
|
|
|
qDebug() << rule3;
|
|
|
|
QVariantList eventDescriptors3 = rule3.value("eventDescriptors").toList();
|
|
QVERIFY2(eventDescriptors3.count() == 1, "There shoud be exactly 1 eventDescriptor");
|
|
QVariantMap eventDescriptor = eventDescriptors3.first().toMap();
|
|
QVERIFY2(eventDescriptor.value("eventTypeId").toString() == mockEvent2Id.toString(), "Loaded the wrong eventTypeId in rule 3");
|
|
QVERIFY2(eventDescriptor.value("deviceId").toString() == m_mockDeviceId.toString(), "Loaded the wrong deviceId from eventDescriptor in rule 3");
|
|
|
|
QVariantList replyExitActions3 = rule3.value("exitActions").toList();
|
|
QVERIFY2(replyExitActions3.isEmpty(), "Rule 3 should not have any exitAction");
|
|
|
|
QVariantList replyActions3 = rule3.value("actions").toList();
|
|
QVERIFY2(replyActions3.count() == 1, "Rule 3 should have exactly 1 action");
|
|
foreach (const QVariant &actionVariant, actions3) {
|
|
bool found = false;
|
|
foreach (const QVariant &replyActionVariant, replyActions3) {
|
|
if (actionVariant.toMap().value("actionTypeId") == replyActionVariant.toMap().value("actionTypeId") &&
|
|
actionVariant.toMap().value("deviceId") == replyActionVariant.toMap().value("deviceId")) {
|
|
found = true;
|
|
QJsonDocument bDoc = QJsonDocument::fromVariant(actionVariant);
|
|
QString bString = bDoc.toJson();
|
|
QJsonDocument aDoc = QJsonDocument::fromVariant(replyActionVariant);
|
|
QString aString = aDoc.toJson();
|
|
QVERIFY2(actionVariant == replyActionVariant, QString("Action doesn't match after loading from config.\nBefore storing: %1\nAfter storing:%2").arg(bString).arg(aString).toUtf8().data());
|
|
}
|
|
}
|
|
QVERIFY2(found, "Action not found after loading from config.");
|
|
}
|
|
|
|
// Remove Rule1
|
|
params.clear();
|
|
params.insert("ruleId", newRuleId);
|
|
response = injectAndWait("Rules.RemoveRule", params);
|
|
verifyRuleError(response);
|
|
|
|
// Remove Rule2
|
|
params2.clear();
|
|
params2.insert("ruleId", newRuleId2);
|
|
response = injectAndWait("Rules.RemoveRule", params2);
|
|
verifyRuleError(response);
|
|
|
|
// Remove Rule2
|
|
params3.clear();
|
|
params3.insert("ruleId", newRuleId3);
|
|
response = injectAndWait("Rules.RemoveRule", params3);
|
|
verifyRuleError(response);
|
|
|
|
restartServer();
|
|
|
|
response = injectAndWait("Rules.GetRules");
|
|
rules = response.toMap().value("params").toMap().value("rules").toList();
|
|
QVERIFY2(rules.count() == 0, "There should be no rules.");
|
|
}
|
|
|
|
void TestRules::evaluateEvent()
|
|
{
|
|
// Add a rule
|
|
QVariantMap addRuleParams;
|
|
addRuleParams.insert("name", "TestRule");
|
|
|
|
QVariantList events;
|
|
QVariantMap event1;
|
|
event1.insert("eventTypeId", mockEvent1Id);
|
|
event1.insert("deviceId", m_mockDeviceId);
|
|
events.append(event1);
|
|
addRuleParams.insert("eventDescriptorList", events);
|
|
|
|
QVariantList actions;
|
|
QVariantMap action;
|
|
action.insert("actionTypeId", mockActionIdNoParams);
|
|
action.insert("deviceId", m_mockDeviceId);
|
|
actions.append(action);
|
|
addRuleParams.insert("actions", actions);
|
|
QVariant response = injectAndWait("Rules.AddRule", addRuleParams);
|
|
verifyRuleError(response);
|
|
|
|
// Trigger an event
|
|
QNetworkAccessManager nam;
|
|
QSignalSpy spy(&nam, SIGNAL(finished(QNetworkReply*)));
|
|
|
|
// trigger event in mock device
|
|
QNetworkRequest request(QUrl(QString("http://localhost:%1/generateevent?eventtypeid=%2").arg(m_mockDevice1Port).arg(mockEvent1Id.toString())));
|
|
QNetworkReply *reply = nam.get(request);
|
|
spy.wait();
|
|
QCOMPARE(spy.count(), 1);
|
|
reply->deleteLater();
|
|
|
|
verifyRuleExecuted(mockActionIdNoParams);
|
|
}
|
|
|
|
void TestRules::testStateChange() {
|
|
// Add a rule
|
|
QVariantMap addRuleParams;
|
|
QVariantMap stateEvaluator;
|
|
QVariantMap stateDescriptor;
|
|
stateDescriptor.insert("deviceId", m_mockDeviceId);
|
|
stateDescriptor.insert("operator", JsonTypes::valueOperatorToString(Types::ValueOperatorGreaterOrEqual));
|
|
stateDescriptor.insert("stateTypeId", mockIntStateId);
|
|
stateDescriptor.insert("value", 42);
|
|
stateEvaluator.insert("stateDescriptor", stateDescriptor);
|
|
addRuleParams.insert("stateEvaluator", stateEvaluator);
|
|
addRuleParams.insert("name", "TestRule");
|
|
|
|
QVariantList actions;
|
|
QVariantMap action;
|
|
action.insert("actionTypeId", mockActionIdNoParams);
|
|
action.insert("deviceId", m_mockDeviceId);
|
|
actions.append(action);
|
|
addRuleParams.insert("actions", actions);
|
|
QVariant response = injectAndWait("Rules.AddRule", addRuleParams);
|
|
verifyRuleError(response);
|
|
|
|
|
|
// Change the state
|
|
QNetworkAccessManager nam;
|
|
QSignalSpy spy(&nam, SIGNAL(finished(QNetworkReply*)));
|
|
|
|
// state state to 42
|
|
qDebug() << "setting mock int state to 42";
|
|
QNetworkRequest request(QUrl(QString("http://localhost:%1/setstate?%2=%3").arg(m_mockDevice1Port).arg(mockIntStateId.toString()).arg(42)));
|
|
QNetworkReply *reply = nam.get(request);
|
|
spy.wait();
|
|
QCOMPARE(spy.count(), 1);
|
|
reply->deleteLater();
|
|
|
|
verifyRuleExecuted(mockActionIdNoParams);
|
|
|
|
cleanupMockHistory();
|
|
|
|
// set state to 45
|
|
qDebug() << "setting mock int state to 45";
|
|
spy.clear();
|
|
request.setUrl(QUrl(QString("http://localhost:%1/setstate?%2=%3").arg(m_mockDevice1Port).arg(mockIntStateId.toString()).arg(45)));
|
|
reply = nam.get(request);
|
|
spy.wait();
|
|
QCOMPARE(spy.count(), 1);
|
|
reply->deleteLater();
|
|
|
|
verifyRuleNotExecuted();
|
|
|
|
cleanupMockHistory();
|
|
|
|
// set state to 30
|
|
qDebug() << "setting mock int state to 30";
|
|
spy.clear();
|
|
request.setUrl(QUrl(QString("http://localhost:%1/setstate?%2=%3").arg(m_mockDevice1Port).arg(mockIntStateId.toString()).arg(30)));
|
|
reply = nam.get(request);
|
|
spy.wait();
|
|
QCOMPARE(spy.count(), 1);
|
|
reply->deleteLater();
|
|
|
|
verifyRuleNotExecuted();
|
|
|
|
cleanupMockHistory();
|
|
|
|
// set state to 100
|
|
qDebug() << "setting mock int state to 100";
|
|
spy.clear();
|
|
request.setUrl(QUrl(QString("http://localhost:%1/setstate?%2=%3").arg(m_mockDevice1Port).arg(mockIntStateId.toString()).arg(100)));
|
|
reply = nam.get(request);
|
|
spy.wait();
|
|
QCOMPARE(spy.count(), 1);
|
|
|
|
verifyRuleExecuted(mockActionIdNoParams);
|
|
reply->deleteLater();
|
|
}
|
|
|
|
void TestRules::testStateEvaluator_data()
|
|
{
|
|
QTest::addColumn<DeviceId>("deviceId");
|
|
QTest::addColumn<StateTypeId>("stateTypeId");
|
|
QTest::addColumn<QVariant>("value");
|
|
QTest::addColumn<Types::ValueOperator>("operatorType");
|
|
QTest::addColumn<bool>("shouldMatch");
|
|
|
|
QTest::newRow("invalid stateId") << m_mockDeviceId << StateTypeId::createStateTypeId() << QVariant(10) << Types::ValueOperatorEquals << false;
|
|
QTest::newRow("invalid deviceId") << DeviceId::createDeviceId() << mockIntStateId << QVariant(10) << Types::ValueOperatorEquals << false;
|
|
|
|
QTest::newRow("equals, not matching") << m_mockDeviceId << mockIntStateId << QVariant(7777) << Types::ValueOperatorEquals << false;
|
|
QTest::newRow("equals, matching") << m_mockDeviceId << mockIntStateId << QVariant(10) << Types::ValueOperatorEquals << true;
|
|
|
|
QTest::newRow("not equal, not matching") << m_mockDeviceId << mockIntStateId << QVariant(10) << Types::ValueOperatorNotEquals << false;
|
|
QTest::newRow("not equal, matching") << m_mockDeviceId << mockIntStateId << QVariant(7777) << Types::ValueOperatorNotEquals << true;
|
|
|
|
QTest::newRow("Greater, not matching") << m_mockDeviceId << mockIntStateId << QVariant(7777) << Types::ValueOperatorGreater << false;
|
|
QTest::newRow("Greater, matching") << m_mockDeviceId << mockIntStateId << QVariant(2) << Types::ValueOperatorGreater << true;
|
|
QTest::newRow("GreaterOrEqual, not matching") << m_mockDeviceId << mockIntStateId << QVariant(7777) << Types::ValueOperatorGreaterOrEqual << false;
|
|
QTest::newRow("GreaterOrEqual, matching (greater)") << m_mockDeviceId << mockIntStateId << QVariant(2) << Types::ValueOperatorGreaterOrEqual << true;
|
|
QTest::newRow("GreaterOrEqual, matching (equals)") << m_mockDeviceId << mockIntStateId << QVariant(10) << Types::ValueOperatorGreaterOrEqual << true;
|
|
|
|
QTest::newRow("Less, not matching") << m_mockDeviceId << mockIntStateId << QVariant(2) << Types::ValueOperatorLess << false;
|
|
QTest::newRow("Less, matching") << m_mockDeviceId << mockIntStateId << QVariant(7777) << Types::ValueOperatorLess << true;
|
|
QTest::newRow("LessOrEqual, not matching") << m_mockDeviceId << mockIntStateId << QVariant(2) << Types::ValueOperatorLessOrEqual << false;
|
|
QTest::newRow("LessOrEqual, matching (less)") << m_mockDeviceId << mockIntStateId << QVariant(777) << Types::ValueOperatorLessOrEqual << true;
|
|
QTest::newRow("LessOrEqual, matching (equals)") << m_mockDeviceId << mockIntStateId << QVariant(10) << Types::ValueOperatorLessOrEqual << true;
|
|
}
|
|
|
|
void TestRules::testStateEvaluator()
|
|
{
|
|
QFETCH(DeviceId, deviceId);
|
|
QFETCH(StateTypeId, stateTypeId);
|
|
QFETCH(QVariant, value);
|
|
QFETCH(Types::ValueOperator, operatorType);
|
|
QFETCH(bool, shouldMatch);
|
|
|
|
StateDescriptor descriptor(stateTypeId, deviceId, value, operatorType);
|
|
StateEvaluator evaluator(descriptor);
|
|
|
|
QVERIFY2(evaluator.evaluate() == shouldMatch, shouldMatch ? "State should match" : "State shouldn't match");
|
|
}
|
|
|
|
void TestRules::testStateEvaluator2_data()
|
|
{
|
|
QTest::addColumn<int>("intValue");
|
|
QTest::addColumn<Types::ValueOperator>("intOperator");
|
|
|
|
QTest::addColumn<bool>("boolValue");
|
|
QTest::addColumn<Types::ValueOperator>("boolOperator");
|
|
|
|
QTest::addColumn<Types::StateOperator>("stateOperator");
|
|
|
|
QTest::addColumn<bool>("shouldMatch");
|
|
|
|
QTest::newRow("Y: 10 && false") << 10 << Types::ValueOperatorEquals << false << Types::ValueOperatorEquals << Types::StateOperatorAnd << true;
|
|
QTest::newRow("N: 10 && true") << 10 << Types::ValueOperatorEquals << true << Types::ValueOperatorEquals << Types::StateOperatorAnd << false;
|
|
QTest::newRow("N: 11 && false") << 11 << Types::ValueOperatorEquals << false << Types::ValueOperatorEquals << Types::StateOperatorAnd << false;
|
|
QTest::newRow("Y: 11 || false") << 11 << Types::ValueOperatorEquals << false << Types::ValueOperatorEquals << Types::StateOperatorOr << true;
|
|
QTest::newRow("Y: 10 || false") << 10 << Types::ValueOperatorEquals << false << Types::ValueOperatorEquals << Types::StateOperatorOr << true;
|
|
QTest::newRow("Y: 10 || true") << 10 << Types::ValueOperatorEquals << true << Types::ValueOperatorEquals << Types::StateOperatorOr << true;
|
|
QTest::newRow("N: 11 || true") << 11 << Types::ValueOperatorEquals << true << Types::ValueOperatorEquals << Types::StateOperatorOr << false;
|
|
}
|
|
|
|
void TestRules::testStateEvaluator2()
|
|
{
|
|
QFETCH(int, intValue);
|
|
QFETCH(Types::ValueOperator, intOperator);
|
|
QFETCH(bool, boolValue);
|
|
QFETCH(Types::ValueOperator, boolOperator);
|
|
QFETCH(Types::StateOperator, stateOperator);
|
|
QFETCH(bool, shouldMatch);
|
|
|
|
StateDescriptor descriptor1(mockIntStateId, m_mockDeviceId, intValue, intOperator);
|
|
StateEvaluator evaluator1(descriptor1);
|
|
|
|
StateDescriptor descriptor2(mockBoolStateId, m_mockDeviceId, boolValue, boolOperator);
|
|
StateEvaluator evaluator2(descriptor2);
|
|
|
|
QList<StateEvaluator> childEvaluators;
|
|
childEvaluators.append(evaluator1);
|
|
childEvaluators.append(evaluator2);
|
|
|
|
StateEvaluator mainEvaluator(childEvaluators);
|
|
mainEvaluator.setOperatorType(stateOperator);
|
|
|
|
QVERIFY2(mainEvaluator.evaluate() == shouldMatch, shouldMatch ? "State should match" : "State shouldn't match");
|
|
}
|
|
|
|
void TestRules::enableDisableRule()
|
|
{
|
|
// Add a rule
|
|
QVariantMap addRuleParams;
|
|
QVariantList events;
|
|
QVariantMap event1;
|
|
event1.insert("eventTypeId", mockEvent1Id);
|
|
event1.insert("deviceId", m_mockDeviceId);
|
|
events.append(event1);
|
|
addRuleParams.insert("eventDescriptorList", events);
|
|
addRuleParams.insert("name", "TestRule");
|
|
|
|
QVariantList actions;
|
|
QVariantMap action;
|
|
action.insert("actionTypeId", mockActionIdNoParams);
|
|
action.insert("deviceId", m_mockDeviceId);
|
|
actions.append(action);
|
|
addRuleParams.insert("actions", actions);
|
|
QVariant response = injectAndWait("Rules.AddRule", addRuleParams);
|
|
verifyRuleError(response);
|
|
RuleId id = RuleId(response.toMap().value("params").toMap().value("ruleId").toString());
|
|
|
|
// Trigger an event
|
|
QNetworkAccessManager nam;
|
|
QSignalSpy spy(&nam, SIGNAL(finished(QNetworkReply*)));
|
|
|
|
// trigger event in mock device
|
|
QNetworkRequest request(QUrl(QString("http://localhost:%1/generateevent?eventtypeid=%2").arg(m_mockDevice1Port).arg(mockEvent1Id.toString())));
|
|
QNetworkReply *reply = nam.get(request);
|
|
spy.wait();
|
|
QCOMPARE(spy.count(), 1);
|
|
reply->deleteLater();
|
|
|
|
verifyRuleExecuted(mockActionIdNoParams);
|
|
|
|
cleanupMockHistory();
|
|
|
|
// Now disable the rule
|
|
QVariantMap disableParams;
|
|
disableParams.insert("ruleId", id.toString());
|
|
response = injectAndWait("Rules.DisableRule", disableParams);
|
|
verifyRuleError(response);
|
|
|
|
|
|
// trigger event in mock device
|
|
spy.clear();
|
|
request = QNetworkRequest(QUrl(QString("http://localhost:%1/generateevent?eventtypeid=%2").arg(m_mockDevice1Port).arg(mockEvent1Id.toString())));
|
|
reply = nam.get(request);
|
|
spy.wait();
|
|
QCOMPARE(spy.count(), 1);
|
|
reply->deleteLater();
|
|
|
|
verifyRuleNotExecuted();
|
|
|
|
cleanupMockHistory();
|
|
|
|
// Now enable the rule again
|
|
response = injectAndWait("Rules.EnableRule", disableParams);
|
|
verifyRuleError(response);
|
|
|
|
|
|
// trigger event in mock device
|
|
spy.clear();
|
|
request = QNetworkRequest(QUrl(QString("http://localhost:%1/generateevent?eventtypeid=%2").arg(m_mockDevice1Port).arg(mockEvent1Id.toString())));
|
|
reply = nam.get(request);
|
|
spy.wait();
|
|
QCOMPARE(spy.count(), 1);
|
|
reply->deleteLater();
|
|
|
|
verifyRuleExecuted(mockActionIdNoParams);
|
|
}
|
|
|
|
void TestRules::testEventBasedAction()
|
|
{
|
|
// Add a rule
|
|
QVariantMap addRuleParams;
|
|
QVariantMap eventDescriptor;
|
|
eventDescriptor.insert("eventTypeId", mockIntStateId);
|
|
eventDescriptor.insert("deviceId", m_mockDeviceId);
|
|
addRuleParams.insert("eventDescriptor", eventDescriptor);
|
|
addRuleParams.insert("name", "TestRule");
|
|
addRuleParams.insert("enabled", true);
|
|
|
|
QVariantList actions;
|
|
QVariantMap action;
|
|
QVariantList ruleActionParams;
|
|
QVariantMap param1;
|
|
param1.insert("name", "mockActionParam1");
|
|
param1.insert("eventTypeId", mockIntStateId);
|
|
param1.insert("eventParamName", "value");
|
|
QVariantMap param2;
|
|
param2.insert("name", "mockActionParam2");
|
|
param2.insert("value", true);
|
|
ruleActionParams.append(param1);
|
|
ruleActionParams.append(param2);
|
|
action.insert("actionTypeId", mockActionIdWithParams);
|
|
action.insert("deviceId", m_mockDeviceId);
|
|
action.insert("ruleActionParams", ruleActionParams);
|
|
actions.append(action);
|
|
addRuleParams.insert("actions", actions);
|
|
|
|
qDebug() << addRuleParams;
|
|
|
|
QVariant response = injectAndWait("Rules.AddRule", addRuleParams);
|
|
verifyRuleError(response);
|
|
|
|
// Change the state
|
|
QNetworkAccessManager nam;
|
|
QSignalSpy spy(&nam, SIGNAL(finished(QNetworkReply*)));
|
|
|
|
// state state to 42
|
|
qDebug() << "setting mock int state to 42";
|
|
QNetworkRequest request(QUrl(QString("http://localhost:%1/setstate?%2=%3").arg(m_mockDevice1Port).arg(mockIntStateId.toString()).arg(42)));
|
|
QNetworkReply *reply = nam.get(request);
|
|
spy.wait();
|
|
QCOMPARE(spy.count(), 1);
|
|
reply->deleteLater();
|
|
|
|
verifyRuleExecuted(mockActionIdWithParams);
|
|
// TODO: check if this action was realy executed with the int state value 42
|
|
}
|
|
|
|
void TestRules::testRuleActionParams_data()
|
|
{
|
|
QVariantMap action;
|
|
QVariantList ruleActionParams;
|
|
QVariantMap param1;
|
|
param1.insert("name", "mockActionParam1");
|
|
param1.insert("value", 4);
|
|
QVariantMap param2;
|
|
param2.insert("name", "mockActionParam2");
|
|
param2.insert("value", true);
|
|
ruleActionParams.append(param1);
|
|
ruleActionParams.append(param2);
|
|
action.insert("actionTypeId", mockActionIdWithParams);
|
|
action.insert("deviceId", m_mockDeviceId);
|
|
action.insert("ruleActionParams", ruleActionParams);
|
|
|
|
QVariantMap invalidAction1;
|
|
invalidAction1.insert("actionTypeId", mockActionIdWithParams);
|
|
invalidAction1.insert("deviceId", m_mockDeviceId);
|
|
invalidAction1.insert("ruleActionParams", QVariantList() << param2);
|
|
|
|
QVariantMap invalidAction2;
|
|
invalidAction2.insert("actionTypeId", mockActionIdWithParams);
|
|
invalidAction2.insert("deviceId", m_mockDeviceId);
|
|
invalidAction2.insert("ruleActionParams", QVariantList() << param1);
|
|
|
|
|
|
QTest::addColumn<QVariantMap>("action");
|
|
QTest::addColumn<QVariantMap>("exitAction");
|
|
QTest::addColumn<RuleEngine::RuleError>("error");
|
|
|
|
QTest::newRow("valid action params") << action << QVariantMap() << RuleEngine::RuleErrorNoError;
|
|
QTest::newRow("valid action and exit action params") << action << action << RuleEngine::RuleErrorNoError;
|
|
QTest::newRow("invalid action params1") << invalidAction1 << QVariantMap() << RuleEngine::RuleErrorInvalidRuleActionParameter;
|
|
QTest::newRow("invalid action params2") << invalidAction2 << QVariantMap() << RuleEngine::RuleErrorInvalidRuleActionParameter;
|
|
QTest::newRow("valid action and invalid exit action params1") << action << invalidAction1 << RuleEngine::RuleErrorInvalidRuleActionParameter;
|
|
QTest::newRow("valid action and invalid exit action params2") << action << invalidAction2 << RuleEngine::RuleErrorInvalidRuleActionParameter;
|
|
|
|
}
|
|
|
|
void TestRules::testRuleActionParams()
|
|
{
|
|
|
|
QFETCH(QVariantMap, action);
|
|
QFETCH(QVariantMap, exitAction);
|
|
QFETCH(RuleEngine::RuleError, error);
|
|
|
|
|
|
// Add a rule
|
|
QVariantMap addRuleParams;
|
|
addRuleParams.insert("name", "TestRule");
|
|
addRuleParams.insert("enabled", true);
|
|
if (!action.isEmpty())
|
|
addRuleParams.insert("actions", QVariantList() << action);
|
|
if (!exitAction.isEmpty())
|
|
addRuleParams.insert("exitActions", QVariantList() << exitAction);
|
|
|
|
QVariant response = injectAndWait("Rules.AddRule", addRuleParams);
|
|
verifyRuleError(response, error);
|
|
|
|
|
|
|
|
}
|
|
|
|
#include "testrules.moc"
|
|
QTEST_MAIN(TestRules)
|