mirror of https://github.com/nymea/nymea.git
Fix processing of rule action params and make tests pass again
parent
694d78225d
commit
299052d2f7
|
|
@ -383,184 +383,18 @@ RuleEngine::RuleError RuleEngine::addRule(const Rule &rule, bool fromEdit)
|
||||||
|
|
||||||
|
|
||||||
// Check actions
|
// Check actions
|
||||||
foreach (const RuleAction &action, rule.actions()) {
|
foreach (const RuleAction &ruleAction, rule.actions()) {
|
||||||
if (!action.isValid()) {
|
RuleError ruleActionError = checkRuleAction(ruleAction, rule);
|
||||||
qWarning(dcRuleEngine()) << "Action is incomplete. It must have either actionTypeId and deviceId, or interface and interfaceAction";
|
if (ruleActionError != RuleErrorNoError) {
|
||||||
return RuleErrorActionTypeNotFound;
|
return ruleActionError;
|
||||||
}
|
|
||||||
if (action.type() == RuleAction::TypeDevice) {
|
|
||||||
Device *device = NymeaCore::instance()->deviceManager()->findConfiguredDevice(action.deviceId());
|
|
||||||
if (!device) {
|
|
||||||
qCWarning(dcRuleEngine) << "Cannot create rule. No configured device for action with actionTypeId" << action.actionTypeId();
|
|
||||||
return RuleErrorDeviceNotFound;
|
|
||||||
}
|
|
||||||
|
|
||||||
DeviceClass deviceClass = NymeaCore::instance()->deviceManager()->findDeviceClass(device->deviceClassId());
|
|
||||||
if (!deviceClass.hasActionType(action.actionTypeId())) {
|
|
||||||
qCWarning(dcRuleEngine) << "Cannot create rule. Device " + device->name() + " has no action type:" << action.actionTypeId();
|
|
||||||
return RuleErrorActionTypeNotFound;
|
|
||||||
}
|
|
||||||
|
|
||||||
} else { // Is TypeInterface
|
|
||||||
Interface iface = NymeaCore::instance()->deviceManager()->supportedInterfaces().findByName(action.interface());
|
|
||||||
if (!iface.isValid()) {
|
|
||||||
qCWarning(dcRuleEngine()) << "Cannot create rule. No such interface:" << action.interface();
|
|
||||||
return RuleError::RuleErrorInterfaceNotFound;
|
|
||||||
}
|
|
||||||
ActionType ifaceActionType = iface.actionTypes().findByName(action.interfaceAction());
|
|
||||||
if (ifaceActionType.name().isEmpty()) {
|
|
||||||
qCWarning(dcRuleEngine()) << "Cannot create rule. Interface" << iface.name() << "does not implement action" << action.interfaceAction();
|
|
||||||
return RuleError::RuleErrorActionTypeNotFound;
|
|
||||||
}
|
|
||||||
foreach (const ParamType &ifaceActionParamType, ifaceActionType.paramTypes()) {
|
|
||||||
if (!action.ruleActionParams().hasParam(ifaceActionParamType.name())) {
|
|
||||||
qCWarning(dcRuleEngine()) << "Cannot create rule. Interface action" << iface.name() << ":" << action.interfaceAction() << "requires a" << ifaceActionParamType.name() << "param of type" << QVariant::typeToName(static_cast<int>(ifaceActionParamType.type()));
|
|
||||||
return RuleError::RuleErrorMissingParameter;
|
|
||||||
}
|
|
||||||
if (!action.ruleActionParam(ifaceActionParamType.name()).value().canConvert(static_cast<int>(ifaceActionParamType.type()))) {
|
|
||||||
qCWarning(dcRuleEngine()) << "Cannot create rule. Interface action parameter" << iface.name() << ":" << action.interfaceAction() << ":" << ifaceActionParamType.name() << "has wrong type. Expected" << QVariant::typeToName(static_cast<int>(ifaceActionParamType.type()));
|
|
||||||
return RuleError::RuleErrorInvalidParameter;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (const RuleActionParam &ruleActionParam, action.ruleActionParams()) {
|
|
||||||
if (ruleActionParam.isEventBased()) {
|
|
||||||
// We have an eventTypeId, see if the rule actually has such a event
|
|
||||||
if (rule.eventDescriptors().isEmpty() || !checkEventDescriptors(rule.eventDescriptors(), ruleActionParam.eventTypeId())) {
|
|
||||||
qCWarning(dcRuleEngine) << "Cannot create rule. EventTypeId from RuleAction" << action.actionTypeId() << "not in eventDescriptors.";
|
|
||||||
return RuleErrorInvalidRuleActionParameter;
|
|
||||||
}
|
|
||||||
|
|
||||||
// check if the param type of the event and the action match
|
|
||||||
QVariant::Type eventParamType = getEventParamType(ruleActionParam.eventTypeId(), ruleActionParam.eventParamTypeId());
|
|
||||||
QVariant v(eventParamType);
|
|
||||||
QVariant::Type actionParamType = getActionParamType(action.actionTypeId(), ruleActionParam.paramTypeId());
|
|
||||||
if (eventParamType != actionParamType && !v.canConvert(static_cast<int>(actionParamType))) {
|
|
||||||
qCWarning(dcRuleEngine) << "Cannot create rule. RuleActionParam" << ruleActionParam.paramTypeId().toString() << " and given event param " << ruleActionParam.eventParamTypeId().toString() << "have not the same type:";
|
|
||||||
qCWarning(dcRuleEngine) << " -> actionParamType:" << actionParamType;
|
|
||||||
qCWarning(dcRuleEngine) << " -> eventParamType:" << eventParamType;
|
|
||||||
return RuleErrorTypesNotMatching;
|
|
||||||
}
|
|
||||||
} else if (ruleActionParam.isStateBased()) {
|
|
||||||
Device *d = NymeaCore::instance()->deviceManager()->findConfiguredDevice(ruleActionParam.stateDeviceId());
|
|
||||||
if (!d) {
|
|
||||||
qCWarning(dcRuleEngine()) << "Cannot create Rule. DeviceId from RuleAction" << action.actionTypeId() << "not found in system.";
|
|
||||||
return RuleErrorDeviceNotFound;
|
|
||||||
}
|
|
||||||
DeviceClass stateDeviceClass = NymeaCore::instance()->deviceManager()->findDeviceClass(d->deviceClassId());
|
|
||||||
StateType stateType = stateDeviceClass.stateTypes().findById(ruleActionParam.stateTypeId());
|
|
||||||
QVariant::Type actionParamType = getActionParamType(action.actionTypeId(), ruleActionParam.paramTypeId());
|
|
||||||
QVariant v(stateType.type());
|
|
||||||
if (actionParamType != stateType.type() && !v.canConvert(static_cast<int>(actionParamType))) {
|
|
||||||
qCWarning(dcRuleEngine) << "Cannot create rule. RuleActionParam" << ruleActionParam.paramTypeId().toString() << " and given state based param " << ruleActionParam.stateTypeId().toString() << "have not the same type:";
|
|
||||||
qCWarning(dcRuleEngine) << " -> actionParamType:" << actionParamType;
|
|
||||||
qCWarning(dcRuleEngine) << " -> stateType:" << stateType.type();
|
|
||||||
return RuleErrorTypesNotMatching;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (ruleActionParam.value().isNull()) {
|
|
||||||
qCDebug(dcRuleEngine()) << "Cannot create rule. No param value given for action:" << ruleActionParam.paramTypeId().toString();
|
|
||||||
return RuleErrorInvalidRuleActionParameter;
|
|
||||||
}
|
|
||||||
QVariant::Type actionParamType = getActionParamType(action.actionTypeId(), ruleActionParam.paramTypeId());
|
|
||||||
if (ruleActionParam.value().type() != actionParamType && !ruleActionParam.value().canConvert(static_cast<int>(actionParamType))) {
|
|
||||||
qCDebug(dcRuleEngine()) << "Cannot create rule. Given param value for action" << ruleActionParam.paramTypeId().toString() << "does not match type";
|
|
||||||
return RuleErrorInvalidRuleActionParameter;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (const RuleActionParam &ruleActionParam, action.ruleActionParams()) {
|
|
||||||
if (!ruleActionParam.isValid()) {
|
|
||||||
qCWarning(dcRuleEngine) << "Cannot create rule. There must be only one out of \"value\", \"eventTypeId/eventParamTypeID\" or \"deviceId/stateTypeId\".";
|
|
||||||
return RuleEngine::RuleErrorInvalidRuleActionParameter;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check exit actions
|
// Check exit actions
|
||||||
foreach (const RuleAction &ruleExitAction, rule.exitActions()) {
|
foreach (const RuleAction &ruleExitAction, rule.exitActions()) {
|
||||||
if (!ruleExitAction.isValid()) {
|
RuleError ruleActionError = checkRuleAction(ruleExitAction, rule);
|
||||||
qWarning(dcRuleEngine()) << "Exit Action is incomplete. It must have either actionTypeId and deviceId, or interface and interfaceAction";
|
if (ruleActionError != RuleErrorNoError) {
|
||||||
return RuleErrorActionTypeNotFound;
|
return ruleActionError;
|
||||||
}
|
|
||||||
|
|
||||||
if (ruleExitAction.type() == RuleAction::TypeDevice) {
|
|
||||||
Device *device = NymeaCore::instance()->deviceManager()->findConfiguredDevice(ruleExitAction.deviceId());
|
|
||||||
if (!device) {
|
|
||||||
qCWarning(dcRuleEngine) << "Cannot create rule. No configured device for exit action with actionTypeId" << ruleExitAction.actionTypeId();
|
|
||||||
return RuleErrorDeviceNotFound;
|
|
||||||
}
|
|
||||||
|
|
||||||
DeviceClass deviceClass = NymeaCore::instance()->deviceManager()->findDeviceClass(device->deviceClassId());
|
|
||||||
if (!deviceClass.hasActionType(ruleExitAction.actionTypeId())) {
|
|
||||||
qCWarning(dcRuleEngine) << "Cannot create rule. Device " + device->name() + " has no action type:" << ruleExitAction.actionTypeId();
|
|
||||||
return RuleErrorActionTypeNotFound;
|
|
||||||
}
|
|
||||||
|
|
||||||
} else { // Is TypeInterface
|
|
||||||
Interface iface = NymeaCore::instance()->deviceManager()->supportedInterfaces().findByName(ruleExitAction.interface());
|
|
||||||
if (!iface.isValid()) {
|
|
||||||
qCWarning(dcRuleEngine()) << "Cannot create rule. No such interface:" << ruleExitAction.interface();
|
|
||||||
return RuleError::RuleErrorInterfaceNotFound;
|
|
||||||
}
|
|
||||||
ActionType ifaceActionType = iface.actionTypes().findByName(ruleExitAction.interfaceAction());
|
|
||||||
if (ifaceActionType.name().isEmpty()) {
|
|
||||||
qCWarning(dcRuleEngine()) << "Cannot create rule. Interface" << iface.name() << "does not implement action" << ruleExitAction.interfaceAction();
|
|
||||||
return RuleError::RuleErrorActionTypeNotFound;
|
|
||||||
}
|
|
||||||
foreach (const ParamType &ifaceActionParamType, ifaceActionType.paramTypes()) {
|
|
||||||
if (!ruleExitAction.ruleActionParams().hasParam(ifaceActionParamType.name())) {
|
|
||||||
qCWarning(dcRuleEngine()) << "Cannot create rule. Interface action" << iface.name() << ":" << ruleExitAction.interfaceAction() << "requires a" << ifaceActionParamType.name() << "param of type" << QVariant::typeToName(static_cast<int>(ifaceActionParamType.type()));
|
|
||||||
return RuleError::RuleErrorMissingParameter;
|
|
||||||
}
|
|
||||||
if (!ruleExitAction.ruleActionParam(ifaceActionParamType.name()).value().canConvert(static_cast<int>(ifaceActionParamType.type()))) {
|
|
||||||
qCWarning(dcRuleEngine()) << "Cannot create rule. Interface action parameter" << iface.name() << ":" << ruleExitAction.interfaceAction() << ":" << ifaceActionParamType.name() << "has wrong type. Expected" << QVariant::typeToName(static_cast<int>(ifaceActionParamType.type()));
|
|
||||||
return RuleError::RuleErrorInvalidParameter;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (const RuleActionParam &ruleActionParam, ruleExitAction.ruleActionParams()) {
|
|
||||||
if (ruleActionParam.isEventBased()) {
|
|
||||||
// We have an eventTypeId, see if the rule actually has such a event
|
|
||||||
qCWarning(dcRuleEngine) << "Cannot create rule. Exit actions cannot be event based.";
|
|
||||||
return RuleErrorInvalidRuleActionParameter;
|
|
||||||
} else if (ruleActionParam.isStateBased()) {
|
|
||||||
Device *d = NymeaCore::instance()->deviceManager()->findConfiguredDevice(ruleActionParam.stateDeviceId());
|
|
||||||
if (!d) {
|
|
||||||
qCWarning(dcRuleEngine()) << "Cannot create Rule. DeviceId from RuleAction" << ruleExitAction.actionTypeId() << "not found in system.";
|
|
||||||
return RuleErrorDeviceNotFound;
|
|
||||||
}
|
|
||||||
DeviceClass stateDeviceClass = NymeaCore::instance()->deviceManager()->findDeviceClass(d->deviceClassId());
|
|
||||||
StateType stateType = stateDeviceClass.stateTypes().findById(ruleActionParam.stateTypeId());
|
|
||||||
QVariant::Type actionParamType = getActionParamType(ruleExitAction.actionTypeId(), ruleActionParam.paramTypeId());
|
|
||||||
QVariant v(stateType.type());
|
|
||||||
if (actionParamType != stateType.type() && !v.canConvert(static_cast<int>(actionParamType))) {
|
|
||||||
qCWarning(dcRuleEngine) << "Cannot create rule. RuleActionParam" << ruleActionParam.paramTypeId().toString() << " and given state based param " << ruleActionParam.stateTypeId().toString() << "have not the same type:";
|
|
||||||
qCWarning(dcRuleEngine) << " -> actionParamType:" << actionParamType;
|
|
||||||
qCWarning(dcRuleEngine) << " -> stateType:" << stateType.type();
|
|
||||||
return RuleErrorTypesNotMatching;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (ruleActionParam.value().isNull()) {
|
|
||||||
qCDebug(dcRuleEngine()) << "Cannot create rule. No param value given for action:" << ruleActionParam.paramTypeId().toString();
|
|
||||||
return RuleErrorInvalidRuleActionParameter;
|
|
||||||
}
|
|
||||||
QVariant::Type actionParamType = getActionParamType(ruleExitAction.actionTypeId(), ruleActionParam.paramTypeId());
|
|
||||||
if (ruleActionParam.value().type() != actionParamType && !ruleActionParam.value().canConvert(static_cast<int>(actionParamType))) {
|
|
||||||
qCDebug(dcRuleEngine()) << "Cannot create rule. Given param value for action" << ruleActionParam.paramTypeId().toString() << "does not match type";
|
|
||||||
return RuleErrorInvalidRuleActionParameter;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (const RuleActionParam &ruleActionParam, ruleExitAction.ruleActionParams()) {
|
|
||||||
if (!ruleActionParam.isValid()) {
|
|
||||||
qCWarning(dcRuleEngine) << "Cannot create rule. There must be only one out of \"value\", \"eventTypeId/eventParamTypeID\" or \"deviceId/stateTypeId\".";
|
|
||||||
return RuleEngine::RuleErrorInvalidRuleActionParameter;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1074,15 +908,133 @@ bool RuleEngine::containsState(const StateEvaluator &stateEvaluator, const Event
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool RuleEngine::checkEventDescriptors(const QList<EventDescriptor> eventDescriptors, const EventTypeId &eventTypeId)
|
RuleEngine::RuleError RuleEngine::checkRuleAction(const RuleAction &ruleAction, const Rule &rule)
|
||||||
{
|
{
|
||||||
foreach (const EventDescriptor eventDescriptor, eventDescriptors) {
|
if (!ruleAction.isValid()) {
|
||||||
if (eventDescriptor.eventTypeId() == eventTypeId) {
|
qWarning(dcRuleEngine()) << "Action is incomplete. It must have either actionTypeId and deviceId, or interface and interfaceAction";
|
||||||
return true;
|
return RuleErrorActionTypeNotFound;
|
||||||
|
}
|
||||||
|
|
||||||
|
ActionType actionType;
|
||||||
|
if (ruleAction.type() == RuleAction::TypeDevice) {
|
||||||
|
Device *device = NymeaCore::instance()->deviceManager()->findConfiguredDevice(ruleAction.deviceId());
|
||||||
|
if (!device) {
|
||||||
|
qCWarning(dcRuleEngine) << "Cannot create rule. No configured device for action with actionTypeId" << ruleAction.actionTypeId();
|
||||||
|
return RuleErrorDeviceNotFound;
|
||||||
|
}
|
||||||
|
|
||||||
|
DeviceClass deviceClass = NymeaCore::instance()->deviceManager()->findDeviceClass(device->deviceClassId());
|
||||||
|
if (!deviceClass.hasActionType(ruleAction.actionTypeId())) {
|
||||||
|
qCWarning(dcRuleEngine) << "Cannot create rule. Device " + device->name() + " has no action type:" << ruleAction.actionTypeId();
|
||||||
|
return RuleErrorActionTypeNotFound;
|
||||||
|
}
|
||||||
|
|
||||||
|
actionType = deviceClass.actionTypes().findById(ruleAction.actionTypeId());
|
||||||
|
} else if (ruleAction.type() == RuleAction::TypeInterface) {
|
||||||
|
Interface iface = NymeaCore::instance()->deviceManager()->supportedInterfaces().findByName(ruleAction.interface());
|
||||||
|
if (!iface.isValid()) {
|
||||||
|
qCWarning(dcRuleEngine()) << "Cannot create rule. No such interface:" << ruleAction.interface();
|
||||||
|
return RuleError::RuleErrorInterfaceNotFound;
|
||||||
|
}
|
||||||
|
actionType = iface.actionTypes().findByName(ruleAction.interfaceAction());
|
||||||
|
if (actionType.name().isEmpty()) {
|
||||||
|
qCWarning(dcRuleEngine()) << "Cannot create rule. Interface" << iface.name() << "does not implement action" << ruleAction.interfaceAction();
|
||||||
|
return RuleError::RuleErrorActionTypeNotFound;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return RuleErrorActionTypeNotFound;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify given params
|
||||||
|
foreach (const RuleActionParam &ruleActionParam, ruleAction.ruleActionParams()) {
|
||||||
|
RuleError ruleActionParamError = checkRuleActionParam(ruleActionParam, actionType, rule);
|
||||||
|
if (ruleActionParamError != RuleErrorNoError) {
|
||||||
|
return ruleActionParamError;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
// Verify all required params are given
|
||||||
|
foreach (const ParamType ¶mType, actionType.paramTypes()) {
|
||||||
|
bool found = false;
|
||||||
|
foreach (const RuleActionParam &ruleActionParam, ruleAction.ruleActionParams()) {
|
||||||
|
if (ruleActionParam.paramTypeId() == paramType.id()
|
||||||
|
|| ruleActionParam.paramName() == paramType.name()) {
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!found) {
|
||||||
|
return RuleErrorMissingParameter;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return RuleErrorNoError;
|
||||||
|
}
|
||||||
|
|
||||||
|
RuleEngine::RuleError RuleEngine::checkRuleActionParam(const RuleActionParam &ruleActionParam, const ActionType &actionType, const Rule &rule)
|
||||||
|
{
|
||||||
|
// Check param identifier (either paramTypeId or paramName)
|
||||||
|
ParamType paramType;
|
||||||
|
if (!ruleActionParam.paramTypeId().isNull()) {
|
||||||
|
paramType = actionType.paramTypes().findById(ruleActionParam.paramTypeId());
|
||||||
|
} else if (!ruleActionParam.paramName().isEmpty()) {
|
||||||
|
paramType = actionType.paramTypes().findByName(ruleActionParam.paramName());
|
||||||
|
} else {
|
||||||
|
return RuleErrorInvalidRuleActionParameter;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ruleActionParam.isEventBased()) {
|
||||||
|
// We have an eventTypeId, see if the rule actually has such a event
|
||||||
|
bool found = false;
|
||||||
|
foreach (const EventDescriptor &ed, rule.eventDescriptors()) {
|
||||||
|
if (ed.eventTypeId() == ruleActionParam.eventTypeId()) {
|
||||||
|
found = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!found) {
|
||||||
|
qCWarning(dcRuleEngine) << "Cannot create rule. EventTypeId" << ruleActionParam.eventTypeId() << "not found in rule's eventDescriptors.";
|
||||||
|
return RuleErrorInvalidRuleActionParameter;
|
||||||
|
}
|
||||||
|
|
||||||
|
// check if the param type of the event and the action match
|
||||||
|
QVariant::Type eventParamType = getEventParamType(ruleActionParam.eventTypeId(), ruleActionParam.eventParamTypeId());
|
||||||
|
QVariant v(eventParamType);
|
||||||
|
if (eventParamType != paramType.type() && !v.canConvert(static_cast<int>(paramType.type()))) {
|
||||||
|
qCWarning(dcRuleEngine) << "Cannot create rule. RuleActionParam" << ruleActionParam.paramTypeId().toString() << " and given event param " << ruleActionParam.eventParamTypeId().toString() << "have not the same type:";
|
||||||
|
qCWarning(dcRuleEngine) << " -> actionParamType:" << paramType.type();
|
||||||
|
qCWarning(dcRuleEngine) << " -> eventParamType:" << eventParamType;
|
||||||
|
return RuleErrorTypesNotMatching;
|
||||||
|
}
|
||||||
|
} else if (ruleActionParam.isStateBased()) {
|
||||||
|
Device *d = NymeaCore::instance()->deviceManager()->findConfiguredDevice(ruleActionParam.stateDeviceId());
|
||||||
|
if (!d) {
|
||||||
|
qCWarning(dcRuleEngine()) << "Cannot create Rule. DeviceId from RuleActionParam" << ruleActionParam.paramTypeId() << "not found in system.";
|
||||||
|
return RuleErrorDeviceNotFound;
|
||||||
|
}
|
||||||
|
DeviceClass stateDeviceClass = NymeaCore::instance()->deviceManager()->findDeviceClass(d->deviceClassId());
|
||||||
|
StateType stateType = stateDeviceClass.stateTypes().findById(ruleActionParam.stateTypeId());
|
||||||
|
QVariant::Type actionParamType = getActionParamType(actionType.id(), ruleActionParam.paramTypeId());
|
||||||
|
QVariant v(stateType.type());
|
||||||
|
if (actionParamType != stateType.type() && !v.canConvert(static_cast<int>(actionParamType))) {
|
||||||
|
qCWarning(dcRuleEngine) << "Cannot create rule. RuleActionParam" << ruleActionParam.paramTypeId().toString() << " and given state based param " << ruleActionParam.stateTypeId().toString() << "have not the same type:";
|
||||||
|
qCWarning(dcRuleEngine) << " -> actionParamType:" << actionParamType;
|
||||||
|
qCWarning(dcRuleEngine) << " -> stateType:" << stateType.type();
|
||||||
|
return RuleErrorTypesNotMatching;
|
||||||
|
}
|
||||||
|
} else { // Is value based
|
||||||
|
if (ruleActionParam.value().isNull()) {
|
||||||
|
qCDebug(dcRuleEngine()) << "Cannot create rule. No param value given for action:" << ruleActionParam.paramTypeId().toString();
|
||||||
|
return RuleErrorInvalidRuleActionParameter;
|
||||||
|
}
|
||||||
|
if (paramType.type() != ruleActionParam.value().type() && !ruleActionParam.value().canConvert(static_cast<int>(paramType.type()))) {
|
||||||
|
qCWarning(dcRuleEngine) << "Cannot create rule. RuleActionParam" << ruleActionParam.paramTypeId().toString() << " and given state based param " << ruleActionParam.stateTypeId().toString() << "have not the same type:";
|
||||||
|
qCWarning(dcRuleEngine) << " -> actionParamType:" << paramType.type();
|
||||||
|
qCWarning(dcRuleEngine) << " -> stateType:" << ruleActionParam.value().type();
|
||||||
|
return RuleErrorTypesNotMatching;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return RuleErrorNoError;
|
||||||
}
|
}
|
||||||
|
|
||||||
QVariant::Type RuleEngine::getActionParamType(const ActionTypeId &actionTypeId, const ParamTypeId ¶mTypeId)
|
QVariant::Type RuleEngine::getActionParamType(const ActionTypeId &actionTypeId, const ParamTypeId ¶mTypeId)
|
||||||
|
|
|
||||||
|
|
@ -104,7 +104,9 @@ private:
|
||||||
bool containsEvent(const Rule &rule, const Event &event, const DeviceClassId &deviceClassId);
|
bool containsEvent(const Rule &rule, const Event &event, const DeviceClassId &deviceClassId);
|
||||||
bool containsState(const StateEvaluator &stateEvaluator, const Event &stateChangeEvent);
|
bool containsState(const StateEvaluator &stateEvaluator, const Event &stateChangeEvent);
|
||||||
|
|
||||||
bool checkEventDescriptors(const QList<EventDescriptor> eventDescriptors, const EventTypeId &eventTypeId);
|
RuleError checkRuleAction(const RuleAction &ruleAction, const Rule &rule);
|
||||||
|
RuleError checkRuleActionParam(const RuleActionParam &ruleActionParam, const ActionType &actionType, const Rule &rule);
|
||||||
|
|
||||||
QVariant::Type getActionParamType(const ActionTypeId &actionTypeId, const ParamTypeId ¶mTypeId);
|
QVariant::Type getActionParamType(const ActionTypeId &actionTypeId, const ParamTypeId ¶mTypeId);
|
||||||
QVariant::Type getEventParamType(const EventTypeId &eventTypeId, const ParamTypeId ¶mTypeId);
|
QVariant::Type getEventParamType(const EventTypeId &eventTypeId, const ParamTypeId ¶mTypeId);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,7 @@
|
||||||
class LIBNYMEA_EXPORT ActionType
|
class LIBNYMEA_EXPORT ActionType
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ActionType(const ActionTypeId &id);
|
ActionType(const ActionTypeId &id = ActionTypeId());
|
||||||
|
|
||||||
ActionTypeId id() const;
|
ActionTypeId id() const;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -49,6 +49,11 @@
|
||||||
|
|
||||||
#include "eventdescriptor.h"
|
#include "eventdescriptor.h"
|
||||||
|
|
||||||
|
EventDescriptor::EventDescriptor()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/*! Constructs an EventDescriptor describing an \l{Event} with the given \a eventTypeId, \a deviceId and the given \a paramDescriptors. */
|
/*! Constructs an EventDescriptor describing an \l{Event} with the given \a eventTypeId, \a deviceId and the given \a paramDescriptors. */
|
||||||
EventDescriptor::EventDescriptor(const EventTypeId &eventTypeId, const DeviceId &deviceId, const QList<ParamDescriptor> ¶mDescriptors):
|
EventDescriptor::EventDescriptor(const EventTypeId &eventTypeId, const DeviceId &deviceId, const QList<ParamDescriptor> ¶mDescriptors):
|
||||||
m_eventTypeId(eventTypeId),
|
m_eventTypeId(eventTypeId),
|
||||||
|
|
|
||||||
|
|
@ -41,6 +41,7 @@ public:
|
||||||
TypeInterface
|
TypeInterface
|
||||||
};
|
};
|
||||||
|
|
||||||
|
EventDescriptor();
|
||||||
EventDescriptor(const EventTypeId &eventTypeId, const DeviceId &deviceId, const QList<ParamDescriptor> ¶mDescriptors = QList<ParamDescriptor>());
|
EventDescriptor(const EventTypeId &eventTypeId, const DeviceId &deviceId, const QList<ParamDescriptor> ¶mDescriptors = QList<ParamDescriptor>());
|
||||||
EventDescriptor(const QString &interface, const QString &interfaceEvent, const QList<ParamDescriptor> ¶mDescriptors = QList<ParamDescriptor>());
|
EventDescriptor(const QString &interface, const QString &interfaceEvent, const QList<ParamDescriptor> ¶mDescriptors = QList<ParamDescriptor>());
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1149,7 +1149,6 @@ void TestRules::loadStoreConfig()
|
||||||
|
|
||||||
QVariantMap action2;
|
QVariantMap action2;
|
||||||
action2.insert("actionTypeId", mockActionIdWithParams);
|
action2.insert("actionTypeId", mockActionIdWithParams);
|
||||||
qDebug() << "got action id" << mockActionIdWithParams;
|
|
||||||
action2.insert("deviceId", m_mockDeviceId);
|
action2.insert("deviceId", m_mockDeviceId);
|
||||||
QVariantList action2Params;
|
QVariantList action2Params;
|
||||||
QVariantMap action2Param1;
|
QVariantMap action2Param1;
|
||||||
|
|
@ -1221,6 +1220,7 @@ void TestRules::loadStoreConfig()
|
||||||
actionsInterfaces.append(actionInterfaces);
|
actionsInterfaces.append(actionInterfaces);
|
||||||
|
|
||||||
// rule 1
|
// rule 1
|
||||||
|
qCDebug(dcTests()) << "Adding rule 1";
|
||||||
QVariantMap params;
|
QVariantMap params;
|
||||||
QVariantList actions;
|
QVariantList actions;
|
||||||
actions.append(action1);
|
actions.append(action1);
|
||||||
|
|
@ -1235,6 +1235,7 @@ void TestRules::loadStoreConfig()
|
||||||
verifyRuleError(response);
|
verifyRuleError(response);
|
||||||
|
|
||||||
// rule 2
|
// rule 2
|
||||||
|
qCDebug(dcTests()) << "Adding rule 2";
|
||||||
QVariantMap params2;
|
QVariantMap params2;
|
||||||
QVariantList actions2;
|
QVariantList actions2;
|
||||||
actions2.append(action1);
|
actions2.append(action1);
|
||||||
|
|
@ -1250,6 +1251,7 @@ void TestRules::loadStoreConfig()
|
||||||
verifyRuleError(response2);
|
verifyRuleError(response2);
|
||||||
|
|
||||||
// rule 3
|
// rule 3
|
||||||
|
qCDebug(dcTests()) << "Adding rule 3";
|
||||||
QVariantMap params3;
|
QVariantMap params3;
|
||||||
QVariantList actions3;
|
QVariantList actions3;
|
||||||
actions3.append(validActionEventBased);
|
actions3.append(validActionEventBased);
|
||||||
|
|
@ -1262,6 +1264,7 @@ void TestRules::loadStoreConfig()
|
||||||
verifyRuleError(response3);
|
verifyRuleError(response3);
|
||||||
|
|
||||||
// rule 4, interface based
|
// rule 4, interface based
|
||||||
|
qCDebug(dcTests()) << "Adding rule 4";
|
||||||
QVariantMap params4;
|
QVariantMap params4;
|
||||||
params4.insert("name", "TestRule4 - Interface based");
|
params4.insert("name", "TestRule4 - Interface based");
|
||||||
params4.insert("eventDescriptors", eventDescriptorsInterfaces);
|
params4.insert("eventDescriptors", eventDescriptorsInterfaces);
|
||||||
|
|
@ -1272,10 +1275,12 @@ void TestRules::loadStoreConfig()
|
||||||
RuleId newRuleId4 = RuleId(response4.toMap().value("params").toMap().value("ruleId").toString());
|
RuleId newRuleId4 = RuleId(response4.toMap().value("params").toMap().value("ruleId").toString());
|
||||||
verifyRuleError(response4);
|
verifyRuleError(response4);
|
||||||
|
|
||||||
|
qCDebug(dcTests()) << "Getting rules";
|
||||||
response = injectAndWait("Rules.GetRules");
|
response = injectAndWait("Rules.GetRules");
|
||||||
QVariantList rules = response.toMap().value("params").toMap().value("ruleDescriptions").toList();
|
QVariantList rules = response.toMap().value("params").toMap().value("ruleDescriptions").toList();
|
||||||
qDebug() << "GetRules before server shutdown:" << response;
|
qDebug() << "GetRules before server shutdown:" << response;
|
||||||
|
|
||||||
|
qCDebug(dcTests()) << "Restarting server";
|
||||||
restartServer();
|
restartServer();
|
||||||
|
|
||||||
response = injectAndWait("Rules.GetRules");
|
response = injectAndWait("Rules.GetRules");
|
||||||
|
|
@ -2249,11 +2254,11 @@ void TestRules::testStateBasedAction()
|
||||||
QVariantList ruleActionParams;
|
QVariantList ruleActionParams;
|
||||||
QVariantMap param1;
|
QVariantMap param1;
|
||||||
param1.insert("paramTypeId", mockActionParam1ParamTypeId);
|
param1.insert("paramTypeId", mockActionParam1ParamTypeId);
|
||||||
param1.insert("deviceId", m_mockDeviceId);
|
param1.insert("stateDeviceId", m_mockDeviceId);
|
||||||
param1.insert("stateTypeId", mockIntStateId);
|
param1.insert("stateTypeId", mockIntStateId);
|
||||||
QVariantMap param2;
|
QVariantMap param2;
|
||||||
param2.insert("paramTypeId", mockActionParam2ParamTypeId);
|
param2.insert("paramTypeId", mockActionParam2ParamTypeId);
|
||||||
param2.insert("deviceId", m_mockDeviceId);
|
param2.insert("stateDeviceId", m_mockDeviceId);
|
||||||
param2.insert("stateTypeId", mockBoolStateId);
|
param2.insert("stateTypeId", mockBoolStateId);
|
||||||
ruleActionParams.append(param1);
|
ruleActionParams.append(param1);
|
||||||
ruleActionParams.append(param2);
|
ruleActionParams.append(param2);
|
||||||
|
|
@ -2265,7 +2270,7 @@ void TestRules::testStateBasedAction()
|
||||||
actions.append(action);
|
actions.append(action);
|
||||||
addRuleParams.insert("actions", actions);
|
addRuleParams.insert("actions", actions);
|
||||||
|
|
||||||
qDebug() << addRuleParams;
|
qCDebug(dcTests) << "Adding rule";
|
||||||
|
|
||||||
QVariant response = injectAndWait("Rules.AddRule", addRuleParams);
|
QVariant response = injectAndWait("Rules.AddRule", addRuleParams);
|
||||||
verifyRuleError(response);
|
verifyRuleError(response);
|
||||||
|
|
@ -2469,6 +2474,7 @@ void TestRules::removePolicyUpdateRendersUselessRule()
|
||||||
params.insert("deviceClassId", mockParentDeviceClassId);
|
params.insert("deviceClassId", mockParentDeviceClassId);
|
||||||
params.insert("name", "Parent device");
|
params.insert("name", "Parent device");
|
||||||
|
|
||||||
|
qCDebug(dcTests()) << "Adding device";
|
||||||
QVariant response = injectAndWait("Devices.AddConfiguredDevice", params);
|
QVariant response = injectAndWait("Devices.AddConfiguredDevice", params);
|
||||||
verifyDeviceError(response);
|
verifyDeviceError(response);
|
||||||
|
|
||||||
|
|
@ -2476,6 +2482,7 @@ void TestRules::removePolicyUpdateRendersUselessRule()
|
||||||
QVERIFY(!parentDeviceId.isNull());
|
QVERIFY(!parentDeviceId.isNull());
|
||||||
|
|
||||||
// find child device
|
// find child device
|
||||||
|
qCDebug(dcTests()) << "Gettin devices";
|
||||||
response = injectAndWait("Devices.GetConfiguredDevices");
|
response = injectAndWait("Devices.GetConfiguredDevices");
|
||||||
|
|
||||||
QVariantList devices = response.toMap().value("params").toMap().value("devices").toList();
|
QVariantList devices = response.toMap().value("params").toMap().value("devices").toList();
|
||||||
|
|
@ -2506,26 +2513,34 @@ void TestRules::removePolicyUpdateRendersUselessRule()
|
||||||
QVariantMap action;
|
QVariantMap action;
|
||||||
action.insert("deviceId", childDeviceId);
|
action.insert("deviceId", childDeviceId);
|
||||||
action.insert("actionTypeId", mockParentChildActionId);
|
action.insert("actionTypeId", mockParentChildActionId);
|
||||||
|
QVariantMap ruleActionParam;
|
||||||
|
ruleActionParam.insert("paramTypeId", mockParentChildActionId);
|
||||||
|
ruleActionParam.insert("value", true);
|
||||||
|
action.insert("ruleActionParams", QVariantList() << ruleActionParam);
|
||||||
params.insert("actions", QVariantList() << action);
|
params.insert("actions", QVariantList() << action);
|
||||||
|
|
||||||
|
qCDebug(dcTests()) << "Adding Rule";
|
||||||
response = injectAndWait("Rules.AddRule", params);
|
response = injectAndWait("Rules.AddRule", params);
|
||||||
verifyRuleError(response);
|
verifyRuleError(response);
|
||||||
RuleId ruleId = RuleId(response.toMap().value("params").toMap().value("ruleId").toString());
|
RuleId ruleId = RuleId(response.toMap().value("params").toMap().value("ruleId").toString());
|
||||||
QVERIFY2(!ruleId.isNull(), "Could not get ruleId");
|
QVERIFY2(!ruleId.isNull(), "Could not get ruleId");
|
||||||
|
|
||||||
// Try to remove child device
|
// Try to remove child device
|
||||||
|
qCDebug(dcTests()) << "Removing device (expecing failure - device is child)";
|
||||||
params.clear(); response.clear();
|
params.clear(); response.clear();
|
||||||
params.insert("deviceId", childDeviceId);
|
params.insert("deviceId", childDeviceId);
|
||||||
response = injectAndWait("Devices.RemoveConfiguredDevice", params);
|
response = injectAndWait("Devices.RemoveConfiguredDevice", params);
|
||||||
verifyDeviceError(response, DeviceManager::DeviceErrorDeviceIsChild);
|
verifyDeviceError(response, DeviceManager::DeviceErrorDeviceIsChild);
|
||||||
|
|
||||||
// Try to remove child device
|
// Try to remove child device
|
||||||
|
qCDebug(dcTests()) << "Removing device (expeciting failure - device in use)";
|
||||||
params.clear(); response.clear();
|
params.clear(); response.clear();
|
||||||
params.insert("deviceId", parentDeviceId);
|
params.insert("deviceId", parentDeviceId);
|
||||||
response = injectAndWait("Devices.RemoveConfiguredDevice", params);
|
response = injectAndWait("Devices.RemoveConfiguredDevice", params);
|
||||||
verifyDeviceError(response, DeviceManager::DeviceErrorDeviceInRule);
|
verifyDeviceError(response, DeviceManager::DeviceErrorDeviceInRule);
|
||||||
|
|
||||||
// Remove policy
|
// Remove policy
|
||||||
|
qCDebug(dcTests()) << "Removing device with update policy";
|
||||||
params.clear(); response.clear();
|
params.clear(); response.clear();
|
||||||
params.insert("deviceId", parentDeviceId);
|
params.insert("deviceId", parentDeviceId);
|
||||||
params.insert("removePolicy", "RemovePolicyUpdate");
|
params.insert("removePolicy", "RemovePolicyUpdate");
|
||||||
|
|
@ -2533,6 +2548,7 @@ void TestRules::removePolicyUpdateRendersUselessRule()
|
||||||
verifyDeviceError(response);
|
verifyDeviceError(response);
|
||||||
|
|
||||||
// get updated rule. It should've been deleted given it ended up with no actions
|
// get updated rule. It should've been deleted given it ended up with no actions
|
||||||
|
qCDebug(dcTests()) << "Getting details";
|
||||||
params.clear();
|
params.clear();
|
||||||
params.insert("ruleId", ruleId);
|
params.insert("ruleId", ruleId);
|
||||||
response = injectAndWait("Rules.GetRuleDetails", params);
|
response = injectAndWait("Rules.GetRuleDetails", params);
|
||||||
|
|
@ -2572,10 +2588,10 @@ void TestRules::testRuleActionParams_data()
|
||||||
|
|
||||||
QTest::newRow("valid action params") << action << QVariantMap() << RuleEngine::RuleErrorNoError;
|
QTest::newRow("valid action params") << action << QVariantMap() << RuleEngine::RuleErrorNoError;
|
||||||
QTest::newRow("valid action and exit action params") << action << action << 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 params1") << invalidAction1 << QVariantMap() << RuleEngine::RuleErrorMissingParameter;
|
||||||
QTest::newRow("invalid action params2") << invalidAction2 << QVariantMap() << RuleEngine::RuleErrorInvalidRuleActionParameter;
|
QTest::newRow("invalid action params2") << invalidAction2 << QVariantMap() << RuleEngine::RuleErrorMissingParameter;
|
||||||
QTest::newRow("valid action and invalid exit action params1") << action << invalidAction1 << RuleEngine::RuleErrorInvalidRuleActionParameter;
|
QTest::newRow("valid action and invalid exit action params1") << action << invalidAction1 << RuleEngine::RuleErrorMissingParameter;
|
||||||
QTest::newRow("valid action and invalid exit action params2") << action << invalidAction2 << RuleEngine::RuleErrorInvalidRuleActionParameter;
|
QTest::newRow("valid action and invalid exit action params2") << action << invalidAction2 << RuleEngine::RuleErrorMissingParameter;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TestRules::testRuleActionParams()
|
void TestRules::testRuleActionParams()
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue