add possibility to disable/enable rules

Fixes #58
pull/135/head
Michael Zanetti 2014-12-14 16:42:25 +01:00 committed by Michael Zanetti
parent 66f4a361a1
commit 5cd3154b64
14 changed files with 307 additions and 18 deletions

View File

@ -183,9 +183,9 @@ Rule GuhCore::findRule(const RuleId &ruleId)
return m_ruleEngine->findRule(ruleId);
}
RuleEngine::RuleError GuhCore::addRule(const RuleId &id, const QList<EventDescriptor> &eventDescriptorList, const QList<Action> &actionList)
RuleEngine::RuleError GuhCore::addRule(const RuleId &id, const QList<EventDescriptor> &eventDescriptorList, const QList<Action> &actionList, bool enabled)
{
return m_ruleEngine->addRule(id, eventDescriptorList, actionList);
return m_ruleEngine->addRule(id, eventDescriptorList, actionList, enabled);
}
RuleEngine::RuleError GuhCore::removeRule(const RuleId &id)
@ -198,6 +198,16 @@ QList<RuleId> GuhCore::findRules(const DeviceId &deviceId)
return m_ruleEngine->findRules(deviceId);
}
RuleEngine::RuleError GuhCore::enableRule(const RuleId &ruleId)
{
return m_ruleEngine->enableRule(ruleId);
}
RuleEngine::RuleError GuhCore::disableRule(const RuleId &ruleId)
{
return m_ruleEngine->disableRule(ruleId);
}
/*! Returns a pointer to the \l{DeviceManager} instance owned by GuhCore.*/
DeviceManager *GuhCore::deviceManager() const
{

View File

@ -66,9 +66,11 @@ public:
QList<Rule> rules() const;
QList<RuleId> ruleIds() const;
Rule findRule(const RuleId &ruleId);
RuleEngine::RuleError addRule(const RuleId &id, const QList<EventDescriptor> &eventDescriptorList, const QList<Action> &actionList);
RuleEngine::RuleError addRule(const RuleId &id, const QList<EventDescriptor> &eventDescriptorList, const QList<Action> &actionList, bool enabled = true);
RuleEngine::RuleError removeRule(const RuleId &id);
QList<RuleId> findRules(const DeviceId &deviceId);
RuleEngine::RuleError enableRule(const RuleId &ruleId);
RuleEngine::RuleError disableRule(const RuleId &ruleId);
signals:
void eventTriggered(const Event &event);

View File

@ -139,6 +139,13 @@ QVariantMap JsonHandler::statusToReply(DeviceManager::DeviceError status) const
return returns;
}
QVariantMap JsonHandler::statusToReply(RuleEngine::RuleError status) const
{
QVariantMap returns;
returns.insert("ruleError", JsonTypes::ruleErrorToString(status));
return returns;
}
JsonReply::JsonReply(Type type, JsonHandler *handler, const QString &method, const QVariantMap &data):
m_type(type),

View File

@ -104,6 +104,7 @@ protected:
JsonReply *createReply(const QVariantMap &data) const;
JsonReply *createAsyncReply(const QString &method) const;
QVariantMap statusToReply(DeviceManager::DeviceError status) const;
QVariantMap statusToReply(RuleEngine::RuleError status) const;
private:
QHash<QString, QString> m_descriptions;

View File

@ -42,7 +42,7 @@
#include <QJsonDocument>
#include <QStringList>
#define JSON_PROTOCOL_VERSION 9
#define JSON_PROTOCOL_VERSION 10
JsonRPCServer::JsonRPCServer(QObject *parent):
JsonHandler(parent),

View File

@ -169,6 +169,7 @@ void JsonTypes::init()
// Rule
s_rule.insert("id", basicTypeToString(Uuid));
s_rule.insert("enabled", basicTypeToString(Bool));
s_rule.insert("eventDescriptors", QVariantList() << eventDescriptorRef());
s_rule.insert("actions", QVariantList() << actionRef());
s_rule.insert("stateEvaluator", stateEvaluatorRef());
@ -447,6 +448,7 @@ QVariantMap JsonTypes::packRule(const Rule &rule)
{
QVariantMap ruleMap;
ruleMap.insert("id", rule.id());
ruleMap.insert("enabled", rule.enabled());
QVariantList eventDescriptorList;
foreach (const EventDescriptor &eventDescriptor, rule.eventDescriptors()) {
eventDescriptorList.append(JsonTypes::packEventDescriptor(eventDescriptor));

View File

@ -44,10 +44,12 @@ RulesHandler::RulesHandler(QObject *parent) :
params.clear(); returns.clear();
setDescription("AddRule", "Add a rule. You can describe rules by one or many EventDesciptors and a StateEvaluator. Note that only"
"one of either eventDescriptor or eventDescriptorList may be passed at a time.");
"one of either eventDescriptor or eventDescriptorList may be passed at a time. A rule can be created but left disabled,"
"meaning it won't actually be executed until set to enabled. If not given, enabled defaults to true.");
params.insert("o:eventDescriptor", JsonTypes::eventDescriptorRef());
params.insert("o:eventDescriptorList", QVariantList() << JsonTypes::eventDescriptorRef());
params.insert("o:stateEvaluator", JsonTypes::stateEvaluatorRef());
params.insert("o:enabled", JsonTypes::basicTypeToString(JsonTypes::Bool));
QVariantList actions;
actions.append(JsonTypes::actionRef());
params.insert("actions", actions);
@ -69,6 +71,20 @@ RulesHandler::RulesHandler(QObject *parent) :
setParams("FindRules", params);
returns.insert("ruleIds", QVariantList() << JsonTypes::basicTypeToString(JsonTypes::Uuid));
setReturns("FindRules", returns);
params.clear(); returns.clear();
setDescription("EnableRule", "Enabled a rule that has previously been disabled.");
params.insert("ruleId", JsonTypes::basicTypeToString(JsonTypes::Uuid));
setParams("EnableRule", params);
returns.insert("ruleError", JsonTypes::ruleErrorRef());
setReturns("EnableRule", returns);
params.clear(); returns.clear();
setDescription("DisableRule", "Disable a rule. The rule won't be triggered by it's events or state changes while it is disabled.");
params.insert("ruleId", JsonTypes::basicTypeToString(JsonTypes::Uuid));
setParams("DisableRule", params);
returns.insert("ruleError", JsonTypes::ruleErrorRef());
setReturns("DisableRule", returns);
}
QString RulesHandler::name() const
@ -136,8 +152,10 @@ JsonReply* RulesHandler::AddRule(const QVariantMap &params)
return createReply(returns);
}
bool enabled = params.value("enabled", true).toBool();
RuleId newRuleId = RuleId::createRuleId();
RuleEngine::RuleError status = GuhCore::instance()->addRule(newRuleId, eventDescriptorList, actions);
RuleEngine::RuleError status = GuhCore::instance()->addRule(newRuleId, eventDescriptorList, actions, enabled);
if (status == RuleEngine::RuleErrorNoError) {
returns.insert("ruleId", newRuleId.toString());
}
@ -168,3 +186,13 @@ JsonReply *RulesHandler::FindRules(const QVariantMap &params)
returns.insert("ruleIds", rulesList);
return createReply(returns);
}
JsonReply *RulesHandler::EnableRule(const QVariantMap &params)
{
return createReply(statusToReply(GuhCore::instance()->enableRule(RuleId(params.value("ruleId").toString()))));
}
JsonReply *RulesHandler::DisableRule(const QVariantMap &params)
{
return createReply(statusToReply(GuhCore::instance()->disableRule(RuleId(params.value("ruleId").toString()))));
}

View File

@ -36,6 +36,8 @@ public:
Q_INVOKABLE JsonReply* RemoveRule(const QVariantMap &params);
Q_INVOKABLE JsonReply* FindRules(const QVariantMap &params);
Q_INVOKABLE JsonReply* EnableRule(const QVariantMap &params);
Q_INVOKABLE JsonReply* DisableRule(const QVariantMap &params);
};
#endif // RULESHANDLER_H

View File

@ -86,3 +86,15 @@ QList<Action> Rule::actions() const
{
return m_actions;
}
/*! Returns wheter the rule is enabled or not. */
bool Rule::enabled() const {
return m_enabled;
}
/*! Set the disabled flag of this rule. In order to actually disable the rule you still need to
* update the RulesEngine */
void Rule::setEnabled(bool enabled)
{
m_enabled = enabled;
}

View File

@ -37,11 +37,16 @@ public:
StateEvaluator stateEvaluator() const;
QList<Action> actions() const;
bool enabled() const;
void setEnabled(bool enabled);
private:
RuleId m_id;
QList<EventDescriptor> m_eventDescriptors;
StateEvaluator m_stateEvaluator;
QList<Action> m_actions;
bool m_enabled;
};
#endif // RULE_H

View File

@ -79,6 +79,8 @@ RuleEngine::RuleEngine(QObject *parent) :
settings.beginGroup(idString);
bool enabled = settings.value("enabled", true).toBool();
QList<EventDescriptor> eventDescriptorList;
settings.beginGroup("events");
@ -133,6 +135,7 @@ RuleEngine::RuleEngine(QObject *parent) :
settings.endGroup();
Rule rule = Rule(RuleId(idString), eventDescriptorList, stateEvaluator, actions);
rule.setEnabled(enabled);
appendRule(rule);
}
@ -151,6 +154,11 @@ QList<Action> RuleEngine::evaluateEvent(const Event &event)
QList<Action> actions;
foreach (const RuleId &id, m_ruleIds) {
Rule rule = m_rules.value(id);
if (!rule.enabled()) {
qDebug() << "Not triggering rule because it is disabled:" << rule.id();
continue;
}
if (containsEvent(rule, event)) {
if (rule.stateEvaluator().evaluate()) {
qDebug() << "states matching!";
@ -164,13 +172,13 @@ QList<Action> RuleEngine::evaluateEvent(const Event &event)
/*! 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 QList<EventDescriptor> &eventDescriptorList, const QList<Action> &actions)
RuleEngine::RuleError RuleEngine::addRule(const RuleId &ruleId, const QList<EventDescriptor> &eventDescriptorList, const QList<Action> &actions, bool enabled)
{
return addRule(ruleId, eventDescriptorList, StateEvaluator(), actions);
return addRule(ruleId, eventDescriptorList, StateEvaluator(), actions, enabled);
}
/*! Add a new \l{Rule} with the given \a event, \a states and \a actions to the engine. */
RuleEngine::RuleError RuleEngine::addRule(const RuleId &ruleId, const QList<EventDescriptor> &eventDescriptorList, const StateEvaluator &stateEvaluator, const QList<Action> &actions)
RuleEngine::RuleError RuleEngine::addRule(const RuleId &ruleId, const QList<EventDescriptor> &eventDescriptorList, const StateEvaluator &stateEvaluator, const QList<Action> &actions, bool enabled)
{
if (ruleId.isNull()) {
return RuleErrorInvalidRuleId;
@ -220,11 +228,13 @@ RuleEngine::RuleError RuleEngine::addRule(const RuleId &ruleId, const QList<Even
}
Rule rule = Rule(ruleId, eventDescriptorList, stateEvaluator, actions);
rule.setEnabled(enabled);
appendRule(rule);
emit ruleAdded(rule.id());
QSettings settings(m_settingsFile);
settings.beginGroup(rule.id().toString());
settings.setValue("enabled", enabled);
settings.beginGroup("events");
for (int i = 0; i < eventDescriptorList.count(); i++) {
const EventDescriptor &eventDescriptor = eventDescriptorList.at(i);
@ -300,6 +310,50 @@ RuleEngine::RuleError RuleEngine::removeRule(const RuleId &ruleId)
return RuleErrorNoError;
}
/*! Enables a rule that has been previously disabled.
\sa disableRule */
RuleEngine::RuleError RuleEngine::enableRule(const RuleId &ruleId)
{
if (!m_rules.contains(ruleId)) {
qWarning() << "Rule not found. Can't enable it";
return RuleErrorRuleNotFound;
}
Rule rule = m_rules.value(ruleId);
rule.setEnabled(true);
m_rules[ruleId] = rule;
QSettings settings(m_settingsFile);
settings.beginGroup(ruleId.toString());
if (!settings.value("enabled", true).toBool()) {
settings.setValue("enabled", true);
emit ruleChanged(ruleId);
}
settings.endGroup();
return RuleErrorNoError;
}
/*! Disables a rule. Disabled rules won't be triggered.
\sa enableRule */
RuleEngine::RuleError RuleEngine::disableRule(const RuleId &ruleId)
{
if (!m_rules.contains(ruleId)) {
qWarning() << "Rule not found. Can't disable it";
return RuleErrorRuleNotFound;
}
Rule rule = m_rules.value(ruleId);
rule.setEnabled(false);
m_rules[ruleId] = rule;
QSettings settings(m_settingsFile);
settings.beginGroup(ruleId.toString());
if (settings.value("enabled", true).toBool()) {
settings.setValue("enabled", false);
emit ruleChanged(ruleId);
}
settings.endGroup();
return RuleErrorNoError;
}
Rule RuleEngine::findRule(const RuleId &ruleId)
{
foreach (const Rule &rule, m_rules) {

View File

@ -53,13 +53,16 @@ public:
QList<Action> evaluateEvent(const Event &event);
RuleError addRule(const RuleId &ruleId, const QList<EventDescriptor> &eventDescriptorList, const QList<Action> &actions);
RuleError addRule(const RuleId &ruleId, const QList<EventDescriptor> &eventDescriptorList, const StateEvaluator &stateEvaluator, const QList<Action> &actions);
RuleError addRule(const RuleId &ruleId, const QList<EventDescriptor> &eventDescriptorList, const QList<Action> &actions, bool enabled = true);
RuleError addRule(const RuleId &ruleId, const QList<EventDescriptor> &eventDescriptorList, const StateEvaluator &stateEvaluator, const QList<Action> &actions, bool enabled = true);
QList<Rule> rules() const;
QList<RuleId> ruleIds() const;
RuleError removeRule(const RuleId &ruleId);
RuleError enableRule(const RuleId &ruleId);
RuleError disableRule(const RuleId &ruleId);
Rule findRule(const RuleId &ruleId);
QList<RuleId> findRules(const DeviceId &deviceId);
@ -68,6 +71,7 @@ public:
signals:
void ruleAdded(const RuleId &ruleId);
void ruleRemoved(const RuleId &ruleId);
void ruleChanged(const RuleId &ruleId);
private:
bool containsEvent(const Rule &rule, const Event &event);

View File

@ -1,4 +1,4 @@
9
10
{
"methods": {
"Actions.ExecuteAction": {
@ -263,11 +263,12 @@
}
},
"Rules.AddRule": {
"description": "Add a rule. You can describe rules by one or many EventDesciptors and a StateEvaluator. Note that onlyone of either eventDescriptor or eventDescriptorList may be passed at a time.",
"description": "Add a rule. You can describe rules by one or many EventDesciptors and a StateEvaluator. Note that onlyone of either eventDescriptor or eventDescriptorList may be passed at a time. A rule can be created but left disabled,meaning it won't actually be executed until set to enabled. If not given, enabled defaults to true.",
"params": {
"actions": [
"$ref:Action"
],
"o:enabled": "Bool",
"o:eventDescriptor": "$ref:EventDescriptor",
"o:eventDescriptorList": [
"$ref:EventDescriptor"
@ -279,6 +280,24 @@
"ruleError": "$ref:RuleError"
}
},
"Rules.DisableRule": {
"description": "Disable a rule. The rule won't be triggered by it's events or state changes while it is disabled.",
"params": {
"ruleId": "Uuid"
},
"returns": {
"ruleError": "$ref:RuleError"
}
},
"Rules.EnableRule": {
"description": "Enabled a rule that has previously been disabled.",
"params": {
"ruleId": "Uuid"
},
"returns": {
"ruleError": "$ref:RuleError"
}
},
"Rules.FindRules": {
"description": "Find a list of rules containing any of the given parameters.",
"params": {
@ -478,6 +497,7 @@
"actions": [
"$ref:Action"
],
"enabled": "Bool",
"eventDescriptors": [
"$ref:EventDescriptor"
],

View File

@ -33,7 +33,14 @@ class TestRules: public GuhTestBase
{
Q_OBJECT
private:
void cleanupMockHistory();
void cleanupRules();
private slots:
void cleanup();
void addRemoveRules_data();
void addRemoveRules();
@ -48,8 +55,34 @@ private slots:
void testStateEvaluator2_data();
void testStateEvaluator2();
void enableDisableRule();
};
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();
QCOMPARE(spy.count(), 1);
reply->deleteLater();
}
void TestRules::cleanupRules() {
QVariant response = injectAndWait("Rules.GetRules");
foreach (const QVariant &ruleId, response.toMap().value("params").toMap().value("ruleIds").toList()) {
QVariantMap params;
params.insert("ruleId", ruleId.toString());
verifyRuleError(injectAndWait("Rules.RemoveRule", params));
}
}
void TestRules::cleanup() {
cleanupMockHistory();
cleanupRules();
}
void TestRules::addRemoveRules_data()
{
QVariantMap validActionNoParams;
@ -100,6 +133,7 @@ void TestRules::addRemoveRules_data()
invalidEventDescriptor.insert("deviceId", DeviceId());
invalidEventDescriptor.insert("paramDescriptors", QVariantList());
QTest::addColumn<bool>("enabled");
QTest::addColumn<QVariantMap>("action1");
QTest::addColumn<QVariantMap>("eventDescriptor");
QTest::addColumn<QVariantList>("eventDescriptorList");
@ -107,17 +141,19 @@ void TestRules::addRemoveRules_data()
QTest::addColumn<RuleEngine::RuleError>("error");
QTest::newRow("valid rule. 1 EventDescriptor, StateEvaluator, 1 Action") << validActionNoParams << validEventDescriptor1 << QVariantList() << validStateEvaluator << RuleEngine::RuleErrorNoError;
QTest::newRow("valid rule. 2 EventDescriptors, 1 Action") << validActionNoParams << QVariantMap() << eventDescriptorList << validStateEvaluator << RuleEngine::RuleErrorNoError;
QTest::newRow("invalid rule: eventDescriptor and eventDescriptorList used") << validActionNoParams << validEventDescriptor1 << eventDescriptorList << validStateEvaluator << RuleEngine::RuleErrorInvalidParameter;
QTest::newRow("invalid action") << invalidAction << validEventDescriptor1 << QVariantList() << validStateEvaluator << RuleEngine::RuleErrorActionTypeNotFound;
QTest::newRow("invalid event descriptor") << validActionNoParams << invalidEventDescriptor << QVariantList() << validStateEvaluator << RuleEngine::RuleErrorDeviceNotFound;
QTest::newRow("valid rule. 1 EventDescriptor, StateEvaluator, 1 Action, enabled") << true << validActionNoParams << validEventDescriptor1 << QVariantList() << validStateEvaluator << RuleEngine::RuleErrorNoError;
QTest::newRow("valid rule. 1 EventDescriptor, StateEvaluator, 1 Action, diabled") << false << validActionNoParams << validEventDescriptor1 << QVariantList() << validStateEvaluator << RuleEngine::RuleErrorNoError;
QTest::newRow("valid rule. 2 EventDescriptors, 1 Action") << true << validActionNoParams << QVariantMap() << eventDescriptorList << validStateEvaluator << RuleEngine::RuleErrorNoError;
QTest::newRow("invalid rule: eventDescriptor and eventDescriptorList used") << true << validActionNoParams << validEventDescriptor1 << eventDescriptorList << validStateEvaluator << RuleEngine::RuleErrorInvalidParameter;
QTest::newRow("invalid action") << true << invalidAction << validEventDescriptor1 << QVariantList() << validStateEvaluator << RuleEngine::RuleErrorActionTypeNotFound;
QTest::newRow("invalid event descriptor") <<true << validActionNoParams << invalidEventDescriptor << QVariantList() << validStateEvaluator << RuleEngine::RuleErrorDeviceNotFound;
// QTest::newRow("invalid state evaluator") << validActionNoParams << invalidEventDescriptor << QVariantList() << invalidStateEvaluator << false;
}
void TestRules::addRemoveRules()
{
QFETCH(bool, enabled);
QFETCH(QVariantMap, action1);
QFETCH(QVariantMap, eventDescriptor);
QFETCH(QVariantList, eventDescriptorList);
@ -136,6 +172,9 @@ void TestRules::addRemoveRules()
params.insert("eventDescriptorList", eventDescriptorList);
}
params.insert("stateEvaluator", stateEvaluator);
if (!enabled) {
params.insert("enabled", enabled);
}
QVariant response = injectAndWait("Rules.AddRule", params);
verifyRuleError(response, error);
@ -159,6 +198,7 @@ void TestRules::addRemoveRules()
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");
@ -443,5 +483,107 @@ void TestRules::testStateEvaluator2()
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);
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();
// Verify rule got executed
spy.clear();
request.setUrl(QUrl(QString("http://localhost:%1/actionhistory").arg(m_mockDevice1Port)));
reply = nam.get(request);
spy.wait();
QCOMPARE(spy.count(), 1);
QByteArray actionHistory = reply->readAll();
qDebug() << "have action history" << actionHistory;
QVERIFY2(mockActionIdNoParams == ActionTypeId(actionHistory), "Action not triggered");
reply->deleteLater();
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();
// Verify rule got *NOT* executed
spy.clear();
request.setUrl(QUrl(QString("http://localhost:%1/actionhistory").arg(m_mockDevice1Port)));
reply = nam.get(request);
spy.wait();
QCOMPARE(spy.count(), 1);
actionHistory = reply->readAll();
qDebug() << "have action history" << actionHistory;
QVERIFY2(actionHistory.isEmpty(), "Action is triggered while rule is disabled");
reply->deleteLater();
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();
// Verify rule got executed
spy.clear();
request.setUrl(QUrl(QString("http://localhost:%1/actionhistory").arg(m_mockDevice1Port)));
reply = nam.get(request);
spy.wait();
QCOMPARE(spy.count(), 1);
actionHistory = reply->readAll();
qDebug() << "have action history" << actionHistory;
QVERIFY2(mockActionIdNoParams == ActionTypeId(actionHistory), "Action not triggered");
reply->deleteLater();
}
#include "testrules.moc"
QTEST_MAIN(TestRules)