fix stateevaluator bug where it would not properly use the OR operator

This commit is contained in:
Michael Zanetti 2018-03-11 21:39:16 +01:00
parent 84854868ea
commit 0f46245230
5 changed files with 63 additions and 15 deletions

View File

@ -99,28 +99,44 @@ void StateEvaluator::setOperatorType(Types::StateOperator operatorType)
/*! Returns true, if all child evaluator conditions are true depending on the \l {Types::StateOperator}{StateOperator}.*/
bool StateEvaluator::evaluate() const
{
qCDebug(dcRuleEngineDebug()) << "Evaluating StateEvaluator." << this << "Operator type" << m_operatorType << "Valid descriptor:" << m_stateDescriptor.isValid() << "Childs:" << m_childEvaluators.count();
bool descriptorMatching = true;
if (m_stateDescriptor.isValid()) {
Device *device = NymeaCore::instance()->deviceManager()->findConfiguredDevice(m_stateDescriptor.deviceId());
if (!device) {
qCWarning(dcRuleEngine) << "Device not existing!";
return false;
}
if (!device->hasState(m_stateDescriptor.stateTypeId())) {
qCWarning(dcRuleEngine) << "Device found, but it does not appear to have such a state!";
return false;
}
if (m_stateDescriptor != device->state(m_stateDescriptor.stateTypeId())) {
// state not matching
return false;
descriptorMatching = false;
} else {
DeviceClass deviceClass = NymeaCore::instance()->deviceManager()->findDeviceClass(device->deviceClassId());
if (!device->hasState(m_stateDescriptor.stateTypeId())) {
qCWarning(dcRuleEngine) << "Device found, but it does not appear to have such a state!";
descriptorMatching = false;
}
if (m_stateDescriptor != device->state(m_stateDescriptor.stateTypeId())) {
// state not matching
qCDebug(dcRuleEngineDebug()) << "State" << device->name() << deviceClass.stateTypes().findById(m_stateDescriptor.stateTypeId()).name() << "not matching:" << m_stateDescriptor.stateValue() << "!=" << device->stateValue(m_stateDescriptor.stateTypeId());
descriptorMatching = false;
}
}
}
if (m_operatorType == Types::StateOperatorOr) {
if (m_stateDescriptor.isValid() && descriptorMatching) {
qCDebug(dcRuleEngineDebug()) << "Descriptor is matching. Operator is OR => Evaluation result: true";
return true;
}
foreach (const StateEvaluator &stateEvaluator, m_childEvaluators) {
if (stateEvaluator.evaluate()) {
qCDebug(dcRuleEngineDebug()) << "Child evaluator evaluated to true. Operator is OR => Evaluation result: true";
return true;
}
}
qCDebug(dcRuleEngineDebug()) << "No child evaluator evaluated to true => Evaluation result: false";
return false;
}
if (!descriptorMatching) {
qCDebug(dcRuleEngineDebug()) << "Operator is AND => Evaluation result: false";
return false;
}

View File

@ -300,7 +300,7 @@ void DeviceClass::setBasicTags(const QList<DeviceClass::BasicTag> &basicTags)
/*! Returns the statesTypes of this DeviceClass. \{Device}{Devices} created
from this \l{DeviceClass} must have their states matching to this template. */
QList<StateType> DeviceClass::stateTypes() const
StateTypes DeviceClass::stateTypes() const
{
return m_stateTypes;
}

View File

@ -147,7 +147,7 @@ public:
QList<BasicTag> basicTags() const;
void setBasicTags(const QList<BasicTag> &basicTags);
QList<StateType> stateTypes() const;
StateTypes stateTypes() const;
StateType getStateType(const StateTypeId &stateTypeId);
void setStateTypes(const QList<StateType> &stateTypes);
bool hasStateType(const StateTypeId &stateTypeId);

View File

@ -63,10 +63,6 @@ DECLARE_TYPE_ID(PairingTransaction)
class LIBNYMEA_EXPORT Types
{
Q_GADGET
Q_ENUMS(InputType)
Q_ENUMS(Unit)
Q_ENUMS(StateOperator)
Q_ENUMS(ValueOperator)
public:
enum InputType {
@ -81,6 +77,7 @@ public:
InputTypeUrl,
InputTypeMacAddress
};
Q_ENUM(InputType)
enum Unit {
UnitNone,
@ -134,6 +131,7 @@ public:
UnitVoltAmpereReactive,
UnitAmpereHour
};
Q_ENUM(Unit)
enum ValueOperator {
ValueOperatorEquals,
@ -143,10 +141,13 @@ public:
ValueOperatorLessOrEqual,
ValueOperatorGreaterOrEqual
};
Q_ENUM(ValueOperator)
enum StateOperator {
StateOperatorAnd,
StateOperatorOr
};
Q_ENUM(StateOperator)
};

View File

@ -86,6 +86,9 @@ private slots:
void testStateEvaluator2_data();
void testStateEvaluator2();
void testStateEvaluator3_data();
void testStateEvaluator3();
void testChildEvaluator_data();
void testChildEvaluator();
@ -1647,6 +1650,34 @@ void TestRules::testStateEvaluator2()
QVERIFY2(mainEvaluator.evaluate() == shouldMatch, shouldMatch ? "State should match" : "State shouldn't match");
}
void TestRules::testStateEvaluator3_data()
{
testStateEvaluator2_data();
}
void TestRules::testStateEvaluator3()
{
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 childEvaluator(descriptor1);
QList<StateEvaluator> childEvaluators;
childEvaluators.append(childEvaluator);
StateDescriptor descriptor2(mockBoolStateId, m_mockDeviceId, boolValue, boolOperator);
StateEvaluator mainEvaluator(descriptor2);
mainEvaluator.setChildEvaluators(childEvaluators);
mainEvaluator.setOperatorType(stateOperator);
QVERIFY2(mainEvaluator.evaluate() == shouldMatch, shouldMatch ? "State should match" : "State shouldn't match");
}
void TestRules::testChildEvaluator_data()
{
cleanup();