Fix an issue where Rules might not be initialized properly at startup
This commit is contained in:
parent
6f1e22546a
commit
15938cafb3
@ -767,6 +767,8 @@ void NymeaCore::onDeviceDisappeared(const DeviceId &deviceId)
|
||||
|
||||
void NymeaCore::deviceManagerLoaded()
|
||||
{
|
||||
m_ruleEngine->initRuleStates();
|
||||
|
||||
// Do some houskeeping...
|
||||
qCDebug(dcApplication()) << "Starting housekeeping...";
|
||||
QDateTime startTime = QDateTime::currentDateTime();
|
||||
|
||||
@ -396,7 +396,6 @@ RuleEngine::RuleEngine(QObject *parent) :
|
||||
rule.setExitActions(exitActions);
|
||||
rule.setEnabled(enabled);
|
||||
rule.setExecutable(executable);
|
||||
rule.setStatesActive(rule.stateEvaluator().evaluate());
|
||||
appendRule(rule);
|
||||
settings.endGroup();
|
||||
}
|
||||
@ -467,7 +466,7 @@ QList<Rule> RuleEngine::evaluateEvent(const Event &event)
|
||||
qCDebug(dcRuleEngine).nospace().noquote() << "Rule " << rule.name() << " (" + rule.id().toString() << ") contains event" << event.eventId() << "and all states match.";
|
||||
rules.append(rule);
|
||||
} else {
|
||||
qCDebug(dcRuleEngine).nospace().noquote() << "Rule " << rule.name() << " (" + rule.id().toString() << ") contains event" << event.eventId() << "but state are not matching.";
|
||||
qCDebug(dcRuleEngine).nospace().noquote() << "Rule " << rule.name() << " (" + rule.id().toString() << ") contains event" << event.eventId() << "and states are not matching.";
|
||||
rules.append(rule);
|
||||
}
|
||||
}
|
||||
@ -1515,4 +1514,11 @@ void RuleEngine::saveRule(const Rule &rule)
|
||||
qCDebug(dcRuleEngineDebug()) << "Saved rule to config:" << rule;
|
||||
}
|
||||
|
||||
void RuleEngine::initRuleStates()
|
||||
{
|
||||
foreach (const RuleId &ruleId, m_rules.keys()) {
|
||||
m_rules[ruleId].setStatesActive(m_rules[ruleId].stateEvaluator().evaluate());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -68,8 +68,9 @@ public:
|
||||
RemovePolicyUpdate
|
||||
};
|
||||
|
||||
explicit RuleEngine(QObject *parent = 0);
|
||||
explicit RuleEngine(QObject *parent = nullptr);
|
||||
~RuleEngine();
|
||||
void initRuleStates();
|
||||
|
||||
QList<Rule> evaluateEvent(const Event &event);
|
||||
QList<Rule> evaluateTime(const QDateTime &dateTime);
|
||||
|
||||
@ -802,7 +802,7 @@ Device *DeviceManager::findConfiguredDevice(const DeviceId &id) const
|
||||
return device;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/*! Returns all configured \{Device}{Devices} in the system. */
|
||||
|
||||
@ -233,7 +233,13 @@ DeviceManager::DeviceError DevicePluginMock::executeAction(Device *device, const
|
||||
if (action.actionTypeId() == mockMockFailingActionTypeId)
|
||||
return DeviceManager::DeviceErrorSetupFailed;
|
||||
|
||||
if (action.actionTypeId() == mockPowerActionTypeId) {
|
||||
qCDebug(dcMockDevice()) << "Setting power to" << action.param(mockPowerActionPowerParamTypeId).value().toBool();
|
||||
device->setStateValue(mockPowerStateTypeId, action.param(mockPowerActionPowerParamTypeId).value().toBool());
|
||||
return DeviceManager::DeviceErrorNoError;
|
||||
}
|
||||
m_daemons.value(device)->actionExecuted(action.actionTypeId());
|
||||
|
||||
return DeviceManager::DeviceErrorNoError;
|
||||
} else if (device->deviceClassId() == mockDeviceAutoDeviceClassId) {
|
||||
if (action.actionTypeId() == mockDeviceAutoMockActionAsyncActionTypeId || action.actionTypeId() == mockDeviceAutoMockActionAsyncBrokenActionTypeId) {
|
||||
|
||||
@ -44,6 +44,7 @@ StateTypeId mockIntStateId = StateTypeId("80baec19-54de-4948-ac46-31eabfaceb83")
|
||||
StateTypeId mockBoolStateId = StateTypeId("9dd6a97c-dfd1-43dc-acbd-367932742310");
|
||||
StateTypeId mockDoubleStateId = StateTypeId("7cac53ee-7048-4dc9-b000-7b585390f34c");
|
||||
StateTypeId mockBatteryCriticalStateId = StateTypeId("580bc611-1a55-41f3-996f-8d3ccf543db3");
|
||||
StateTypeId mockPowerStateTypeId = StateTypeId("064aed0d-da4c-49d4-b236-60f97e98ff84");
|
||||
ActionTypeId mockActionIdPower = ActionTypeId("064aed0d-da4c-49d4-b236-60f97e98ff84");
|
||||
ActionTypeId mockActionIdWithParams = ActionTypeId("dea0f4e1-65e3-4981-8eaa-2701c53a9185");
|
||||
ActionTypeId mockActionIdNoParams = ActionTypeId("defd3ed6-1a0d-400b-8879-a0202cf39935");
|
||||
|
||||
@ -51,6 +51,7 @@ extern StateTypeId mockIntStateId;
|
||||
extern StateTypeId mockDoubleStateId;
|
||||
extern StateTypeId mockBatteryCriticalStateId;
|
||||
extern StateTypeId mockBoolStateId;
|
||||
extern StateTypeId mockPowerStateTypeId;
|
||||
|
||||
// ParamTypes from mock devices
|
||||
extern ParamTypeId configParamIntParamTypeId;
|
||||
|
||||
@ -46,8 +46,12 @@ private:
|
||||
|
||||
QVariant validIntStateBasedRule(const QString &name, const bool &executable, const bool &enabled);
|
||||
|
||||
void generateEvent(const EventTypeId &eventTypeId);
|
||||
|
||||
private slots:
|
||||
|
||||
void initTestCase();
|
||||
|
||||
void cleanup();
|
||||
void emptyRule();
|
||||
void getInvalidRule();
|
||||
@ -101,6 +105,8 @@ private slots:
|
||||
void testRuleActionPAramsFromEventParameter_data();
|
||||
void testRuleActionPAramsFromEventParameter();
|
||||
|
||||
void testInitStatesActive();
|
||||
|
||||
void testInterfaceBasedEventRule();
|
||||
|
||||
void testInterfaceBasedStateRule();
|
||||
@ -349,6 +355,27 @@ QVariant TestRules::validIntStateBasedRule(const QString &name, const bool &exec
|
||||
return params;
|
||||
}
|
||||
|
||||
void TestRules::generateEvent(const EventTypeId &eventTypeId)
|
||||
{
|
||||
// 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(eventTypeId.toString())));
|
||||
QNetworkReply *reply = nam.get(request);
|
||||
spy.wait();
|
||||
QCOMPARE(spy.count(), 1);
|
||||
reply->deleteLater();
|
||||
|
||||
}
|
||||
|
||||
void TestRules::initTestCase()
|
||||
{
|
||||
NymeaTestBase::initTestCase();
|
||||
QLoggingCategory::setFilterRules("*.debug=false\nRuleEngine.debug=true\nRuleEngineDebug.debug=true\nMockDevice.*=true");
|
||||
}
|
||||
|
||||
void TestRules::addRemoveRules_data()
|
||||
{
|
||||
// RuleAction
|
||||
@ -2525,6 +2552,101 @@ void TestRules::testRuleActionPAramsFromEventParameter()
|
||||
verifyRuleError(response, error);
|
||||
}
|
||||
|
||||
void TestRules::testInitStatesActive()
|
||||
{
|
||||
|
||||
// Create a rule to toggle the power state on event 1
|
||||
QVariantMap params;
|
||||
params.insert("name", "testrule");
|
||||
|
||||
QVariantMap eventDescriptor;
|
||||
eventDescriptor.insert("deviceId", m_mockDeviceId);
|
||||
eventDescriptor.insert("eventTypeId", mockEvent1Id);
|
||||
QVariantList eventDescriptors;
|
||||
eventDescriptors.append(eventDescriptor);
|
||||
params.insert("eventDescriptors", eventDescriptors);
|
||||
|
||||
QVariantMap stateEvaluator;
|
||||
QVariantMap stateDescriptor;
|
||||
stateDescriptor.insert("stateTypeId", mockPowerStateTypeId);
|
||||
stateDescriptor.insert("operator", "ValueOperatorEquals");
|
||||
stateDescriptor.insert("value", false);
|
||||
stateDescriptor.insert("deviceId", m_mockDeviceId);
|
||||
stateEvaluator.insert("stateDescriptor", stateDescriptor);
|
||||
params.insert("stateEvaluator", stateEvaluator);
|
||||
|
||||
QVariantList actions;
|
||||
QVariantMap action;
|
||||
action.insert("actionTypeId", mockActionIdPower);
|
||||
action.insert("deviceId", m_mockDeviceId);
|
||||
QVariantList actionParams;
|
||||
QVariantMap actionParam;
|
||||
actionParam.insert("paramTypeId", mockActionIdPower);
|
||||
actionParam.insert("value", true);
|
||||
actionParams.append(actionParam);
|
||||
action.insert("ruleActionParams", actionParams);
|
||||
actions.append(action);
|
||||
params.insert("actions", actions);
|
||||
|
||||
QVariantList exitActions;
|
||||
QVariantMap exitAction;
|
||||
exitAction.insert("actionTypeId", mockActionIdPower);
|
||||
exitAction.insert("deviceId", m_mockDeviceId);
|
||||
QVariantList exitActionParams;
|
||||
QVariantMap exitActionParam;
|
||||
exitActionParam.insert("paramTypeId", mockActionIdPower);
|
||||
exitActionParam.insert("value", false);
|
||||
exitActionParams.append(exitActionParam);
|
||||
exitAction.insert("ruleActionParams", exitActionParams);
|
||||
exitActions.append(exitAction);
|
||||
params.insert("exitActions", exitActions);
|
||||
|
||||
QVariant response = injectAndWait("Rules.AddRule", params);
|
||||
RuleId ruleId = RuleId::fromUuid(response.toMap().value("params").toMap().value("ruleId").toUuid());
|
||||
QVERIFY2(!ruleId.isNull(), "Error adding rule");
|
||||
|
||||
// Get the current state value, make sure it's false
|
||||
params.clear();
|
||||
params.insert("deviceId", m_mockDeviceId);
|
||||
params.insert("stateTypeId", mockPowerStateTypeId);
|
||||
|
||||
response = injectAndWait("Devices.GetStateValue", params);
|
||||
QVERIFY2(response.toMap().value("params").toMap().value("value").toBool() == false, "State initially true while it should be false");
|
||||
|
||||
|
||||
// Trigger the event
|
||||
generateEvent(mockEvent1Id);
|
||||
|
||||
|
||||
// Make sure the value changed after the event has triggered
|
||||
response = injectAndWait("Devices.GetStateValue", params);
|
||||
QVERIFY2(response.toMap().value("params").toMap().value("value").toBool() == true, "State is false while it should have changed to true");
|
||||
|
||||
|
||||
// Trigger the event again...
|
||||
generateEvent(mockEvent1Id);
|
||||
|
||||
|
||||
// ... and make sure the value changed back to false
|
||||
response = injectAndWait("Devices.GetStateValue", params);
|
||||
QVERIFY2(response.toMap().value("params").toMap().value("value").toBool() == false, "State is true while it should have changed to false");
|
||||
|
||||
restartServer();
|
||||
|
||||
// Make sure the value changed is still false
|
||||
response = injectAndWait("Devices.GetStateValue", params);
|
||||
QVERIFY2(response.toMap().value("params").toMap().value("value").toBool() == false, "State is true while it should have changed to false");
|
||||
|
||||
// Trigger the event
|
||||
generateEvent(mockEvent1Id);
|
||||
|
||||
|
||||
// Make sure the value changed after the event has triggered
|
||||
response = injectAndWait("Devices.GetStateValue", params);
|
||||
QVERIFY2(response.toMap().value("params").toMap().value("value").toBool() == true, "State is false while it should have changed to true");
|
||||
|
||||
}
|
||||
|
||||
void TestRules::testInterfaceBasedEventRule()
|
||||
{
|
||||
QNetworkAccessManager nam;
|
||||
|
||||
Reference in New Issue
Block a user