add rule tests and rest resource
This commit is contained in:
parent
1330ed31a3
commit
1f6cfd4527
@ -1,11 +1,13 @@
|
|||||||
[JSONRPC]
|
[JSONRPC]
|
||||||
port=12345
|
port=1234
|
||||||
interfaces="lo","all"
|
interfaces="lo","all"
|
||||||
ip="IPv4", "IPv6"
|
ip="IPv4", "IPv6"
|
||||||
|
|
||||||
[Webserver]
|
[Webserver]
|
||||||
port=3001
|
port=3000
|
||||||
publicFolder=/usr/share/guh-webinterface/
|
publicFolder=/usr/share/guh-webinterface/
|
||||||
|
https=false
|
||||||
|
|
||||||
|
|
||||||
[GPIO]
|
[GPIO]
|
||||||
rf433rx=27
|
rf433rx=27
|
||||||
|
|||||||
3
guh.pri
3
guh.pri
@ -28,9 +28,8 @@ enable433gpio {
|
|||||||
|
|
||||||
# check webserver support
|
# check webserver support
|
||||||
equals(QT_MAJOR_VERSION, 5):greaterThan(QT_MINOR_VERSION, 3) {
|
equals(QT_MAJOR_VERSION, 5):greaterThan(QT_MINOR_VERSION, 3) {
|
||||||
DEFINES += WEBSERVER
|
DEFINES += WEBSOCKET
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
top_srcdir=$$PWD
|
top_srcdir=$$PWD
|
||||||
top_builddir=$$shadowed($$PWD)
|
top_builddir=$$shadowed($$PWD)
|
||||||
|
|||||||
6
guh.pro
6
guh.pro
@ -34,10 +34,10 @@ coverage {
|
|||||||
message("Building coverage.")
|
message("Building coverage.")
|
||||||
}
|
}
|
||||||
|
|
||||||
contains(DEFINES, WEBSERVER){
|
contains(DEFINES, WEBSOCKET){
|
||||||
message("Building guh with webserver.")
|
message("Building guh with websocket.")
|
||||||
} else {
|
} else {
|
||||||
message("Building guh without webserver.")
|
message("Building guh without websocket.")
|
||||||
}
|
}
|
||||||
|
|
||||||
contains(DEFINES, GPIO433){
|
contains(DEFINES, GPIO433){
|
||||||
|
|||||||
@ -1288,6 +1288,168 @@ QPair<bool, QString> JsonTypes::validateBasicType(const QVariant &variant)
|
|||||||
return report(false, QString("Error validating basic type %1.").arg(variant.toString()));
|
return report(false, QString("Error validating basic type %1.").arg(variant.toString()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QVariant::Type JsonTypes::getActionParamType(const ActionTypeId &actionTypeId, const QString ¶mName)
|
||||||
|
{
|
||||||
|
foreach (const DeviceClass &deviceClass, GuhCore::instance()->supportedDevices()) {
|
||||||
|
foreach (const ActionType &actionType, deviceClass.actionTypes()) {
|
||||||
|
if (actionType.id() == actionTypeId) {
|
||||||
|
foreach (const ParamType ¶mType, actionType.paramTypes()) {
|
||||||
|
if (paramType.name() == paramName) {
|
||||||
|
return paramType.type();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return QVariant::Invalid;
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariant::Type JsonTypes::getEventParamType(const EventTypeId &eventTypeId, const QString ¶mName)
|
||||||
|
{
|
||||||
|
foreach (const DeviceClass &deviceClass, GuhCore::instance()->supportedDevices()) {
|
||||||
|
foreach (const EventType &eventType, deviceClass.eventTypes()) {
|
||||||
|
if (eventType.id() == eventTypeId) {
|
||||||
|
foreach (const ParamType ¶mType, eventType.paramTypes()) {
|
||||||
|
// get ParamType of Event
|
||||||
|
if (paramType.name() == paramName) {
|
||||||
|
return paramType.type();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return QVariant::Invalid;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool JsonTypes::checkEventDescriptors(const QList<EventDescriptor> eventDescriptors, const EventTypeId &eventTypeId)
|
||||||
|
{
|
||||||
|
foreach (const EventDescriptor eventDescriptor, eventDescriptors) {
|
||||||
|
if (eventDescriptor.eventTypeId() == eventTypeId) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
RuleEngine::RuleError JsonTypes::verifyRuleConsistency(const QVariantMap ¶ms)
|
||||||
|
{
|
||||||
|
// check if there are an eventDescriptor and an eventDescriptorList
|
||||||
|
if (params.contains("eventDescriptor") && params.contains("eventDescriptorList")) {
|
||||||
|
qCWarning(dcJsonRpc) << "Only one of eventDesciptor or eventDescriptorList may be used.";
|
||||||
|
return RuleEngine::RuleErrorInvalidParameter;
|
||||||
|
}
|
||||||
|
|
||||||
|
// check if this rules is based on any event and contains exit actions
|
||||||
|
if (params.contains("eventDescriptor") || params.contains("eventDescriptorList")) {
|
||||||
|
if (params.contains("exitActions")) {
|
||||||
|
qCWarning(dcJsonRpc) << "The exitActions will never be executed if the rule contains an eventDescriptor.";
|
||||||
|
return RuleEngine::RuleErrorInvalidRuleFormat;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// check if there are any actions
|
||||||
|
if (params.value("actions").toList().isEmpty()) {
|
||||||
|
qCWarning(dcJsonRpc) << "Rule actions missing. A rule without actions has no effect.";
|
||||||
|
return RuleEngine::RuleErrorMissingParameter;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: check if events and stateEvaluators are missing
|
||||||
|
|
||||||
|
return RuleEngine::RuleErrorNoError;
|
||||||
|
}
|
||||||
|
|
||||||
|
QPair<QList<EventDescriptor>, RuleEngine::RuleError> JsonTypes::verifyEventDescriptors(const QVariantMap ¶ms)
|
||||||
|
{
|
||||||
|
// Check and unpack eventDescriptors
|
||||||
|
QList<EventDescriptor> eventDescriptorList = QList<EventDescriptor>();
|
||||||
|
if (params.contains("eventDescriptor")) {
|
||||||
|
QVariantMap eventMap = params.value("eventDescriptor").toMap();
|
||||||
|
qCDebug(dcJsonRpc) << "unpacking eventDescriptor" << eventMap;
|
||||||
|
eventDescriptorList.append(JsonTypes::unpackEventDescriptor(eventMap));
|
||||||
|
} else if (params.contains("eventDescriptorList")) {
|
||||||
|
QVariantList eventDescriptors = params.value("eventDescriptorList").toList();
|
||||||
|
qCDebug(dcJsonRpc) << "unpacking eventDescriptorList:" << eventDescriptors;
|
||||||
|
foreach (const QVariant &eventVariant, eventDescriptors) {
|
||||||
|
QVariantMap eventMap = eventVariant.toMap();
|
||||||
|
eventDescriptorList.append(JsonTypes::unpackEventDescriptor(eventMap));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return QPair<QList<EventDescriptor>, RuleEngine::RuleError>(eventDescriptorList, RuleEngine::RuleErrorNoError);
|
||||||
|
}
|
||||||
|
|
||||||
|
QPair<QList<RuleAction>, RuleEngine::RuleError> JsonTypes::verifyActions(const QVariantMap ¶ms, const QList<EventDescriptor> &eventDescriptorList)
|
||||||
|
{
|
||||||
|
QList<RuleAction> actions;
|
||||||
|
QVariantList actionList = params.value("actions").toList();
|
||||||
|
qCDebug(dcJsonRpc) << "unpacking actions:" << actionList;
|
||||||
|
foreach (const QVariant &actionVariant, actionList) {
|
||||||
|
QVariantMap actionMap = actionVariant.toMap();
|
||||||
|
RuleAction action(ActionTypeId(actionMap.value("actionTypeId").toString()), DeviceId(actionMap.value("deviceId").toString()));
|
||||||
|
RuleActionParamList actionParamList = JsonTypes::unpackRuleActionParams(actionMap.value("ruleActionParams").toList());
|
||||||
|
foreach (const RuleActionParam &ruleActionParam, actionParamList) {
|
||||||
|
if (!ruleActionParam.isValid()) {
|
||||||
|
qCWarning(dcJsonRpc) << "got an actionParam with value AND eventTypeId!";
|
||||||
|
return QPair<QList<RuleAction>, RuleEngine::RuleError>(actions, RuleEngine::RuleErrorInvalidRuleActionParameter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
qCDebug(dcJsonRpc) << "params in exitAction" << action.ruleActionParams();
|
||||||
|
action.setRuleActionParams(actionParamList);
|
||||||
|
actions.append(action);
|
||||||
|
}
|
||||||
|
|
||||||
|
// check possible eventTypeIds in params
|
||||||
|
foreach (const RuleAction &ruleAction, actions) {
|
||||||
|
if (ruleAction.isEventBased()) {
|
||||||
|
foreach (const RuleActionParam &ruleActionParam, ruleAction.ruleActionParams()) {
|
||||||
|
if (ruleActionParam.eventTypeId() != EventTypeId()) {
|
||||||
|
// We have an eventTypeId
|
||||||
|
if (eventDescriptorList.isEmpty()) {
|
||||||
|
qCWarning(dcJsonRpc) << "RuleAction" << ruleAction.actionTypeId() << "contains an eventTypeId, but there are no eventDescriptors.";
|
||||||
|
return QPair<QList<RuleAction>, RuleEngine::RuleError>(actions, RuleEngine::RuleErrorInvalidRuleActionParameter);
|
||||||
|
}
|
||||||
|
// now check if this eventType is in the eventDescriptorList of this rule
|
||||||
|
if (!checkEventDescriptors(eventDescriptorList, ruleActionParam.eventTypeId())) {
|
||||||
|
qCWarning(dcJsonRpc) << "eventTypeId from RuleAction" << ruleAction.actionTypeId() << "missing in eventDescriptors.";
|
||||||
|
return QPair<QList<RuleAction>, RuleEngine::RuleError>(actions, RuleEngine::RuleErrorInvalidRuleActionParameter);
|
||||||
|
}
|
||||||
|
|
||||||
|
// check if the param type of the event and the action match
|
||||||
|
QVariant::Type eventParamType = getEventParamType(ruleActionParam.eventTypeId(), ruleActionParam.eventParamName());
|
||||||
|
QVariant::Type actionParamType = getActionParamType(ruleAction.actionTypeId(), ruleActionParam.name());
|
||||||
|
if (eventParamType != actionParamType) {
|
||||||
|
qCWarning(dcJsonRpc) << "RuleActionParam" << ruleActionParam.name() << " and given event param " << ruleActionParam.eventParamName() << "have not the same type:";
|
||||||
|
qCWarning(dcJsonRpc) << " -> actionParamType:" << actionParamType;
|
||||||
|
qCWarning(dcJsonRpc) << " -> eventParamType:" << eventParamType;
|
||||||
|
return QPair<QList<RuleAction>, RuleEngine::RuleError>(actions, RuleEngine::RuleErrorTypesNotMatching);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return QPair<QList<RuleAction>, RuleEngine::RuleError>(actions, RuleEngine::RuleErrorNoError);
|
||||||
|
}
|
||||||
|
|
||||||
|
QPair<QList<RuleAction>, RuleEngine::RuleError> JsonTypes::verifyExitActions(const QVariantMap ¶ms)
|
||||||
|
{
|
||||||
|
QList<RuleAction> exitActions;
|
||||||
|
if (params.contains("exitActions")) {
|
||||||
|
QVariantList exitActionList = params.value("exitActions").toList();
|
||||||
|
qCDebug(dcJsonRpc) << "unpacking exitActions:" << exitActionList;
|
||||||
|
foreach (const QVariant &actionVariant, exitActionList) {
|
||||||
|
QVariantMap actionMap = actionVariant.toMap();
|
||||||
|
RuleAction action(ActionTypeId(actionMap.value("actionTypeId").toString()), DeviceId(actionMap.value("deviceId").toString()));
|
||||||
|
if (action.isEventBased()) {
|
||||||
|
qCWarning(dcJsonRpc) << "got exitAction with a param value containing an eventTypeId!";
|
||||||
|
return QPair<QList<RuleAction>, RuleEngine::RuleError>(exitActions, RuleEngine::RuleErrorInvalidRuleActionParameter);
|
||||||
|
}
|
||||||
|
qCDebug(dcJsonRpc) << "params in exitAction" << action.ruleActionParams();
|
||||||
|
action.setRuleActionParams(JsonTypes::unpackRuleActionParams(actionMap.value("ruleActionParams").toList()));
|
||||||
|
exitActions.append(action);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return QPair<QList<RuleAction>, RuleEngine::RuleError>(exitActions, RuleEngine::RuleErrorNoError);
|
||||||
|
}
|
||||||
|
|
||||||
QPair<bool, QString> JsonTypes::validateEnum(const QVariantList &enumDescription, const QVariant &value)
|
QPair<bool, QString> JsonTypes::validateEnum(const QVariantList &enumDescription, const QVariant &value)
|
||||||
{
|
{
|
||||||
QStringList enumStrings;
|
QStringList enumStrings;
|
||||||
|
|||||||
@ -197,6 +197,15 @@ public:
|
|||||||
static QPair<bool, QString> validateEnum(const QVariantList &enumList, const QVariant &value);
|
static QPair<bool, QString> validateEnum(const QVariantList &enumList, const QVariant &value);
|
||||||
static QPair<bool, QString> validateBasicType(const QVariant &variant);
|
static QPair<bool, QString> validateBasicType(const QVariant &variant);
|
||||||
|
|
||||||
|
// rule validation helper methods
|
||||||
|
static bool checkEventDescriptors(const QList<EventDescriptor> eventDescriptors, const EventTypeId &eventTypeId);
|
||||||
|
static QVariant::Type getActionParamType(const ActionTypeId &actionTypeId, const QString ¶mName);
|
||||||
|
static QVariant::Type getEventParamType(const EventTypeId &eventTypeId, const QString ¶mName);
|
||||||
|
static RuleEngine::RuleError verifyRuleConsistency(const QVariantMap ¶ms);
|
||||||
|
static QPair<QList<EventDescriptor>, RuleEngine::RuleError> verifyEventDescriptors(const QVariantMap ¶ms);
|
||||||
|
static QPair<QList<RuleAction>, RuleEngine::RuleError> verifyActions(const QVariantMap ¶ms, const QList<EventDescriptor> &eventDescriptorList);
|
||||||
|
static QPair<QList<RuleAction>, RuleEngine::RuleError> verifyExitActions(const QVariantMap ¶ms);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static bool s_initialized;
|
static bool s_initialized;
|
||||||
static void init();
|
static void init();
|
||||||
|
|||||||
@ -175,7 +175,7 @@ JsonReply *RulesHandler::GetRuleDetails(const QVariantMap ¶ms)
|
|||||||
JsonReply* RulesHandler::AddRule(const QVariantMap ¶ms)
|
JsonReply* RulesHandler::AddRule(const QVariantMap ¶ms)
|
||||||
{
|
{
|
||||||
// check rule consistency
|
// check rule consistency
|
||||||
RuleEngine::RuleError ruleConsistencyError = verifyRuleConsistency(params);
|
RuleEngine::RuleError ruleConsistencyError = JsonTypes::verifyRuleConsistency(params);
|
||||||
if (ruleConsistencyError != RuleEngine::RuleErrorNoError) {
|
if (ruleConsistencyError != RuleEngine::RuleErrorNoError) {
|
||||||
QVariantMap returns;
|
QVariantMap returns;
|
||||||
returns.insert("ruleError", JsonTypes::ruleErrorToString(ruleConsistencyError));
|
returns.insert("ruleError", JsonTypes::ruleErrorToString(ruleConsistencyError));
|
||||||
@ -183,7 +183,7 @@ JsonReply* RulesHandler::AddRule(const QVariantMap ¶ms)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Check and upack eventDescriptorList
|
// Check and upack eventDescriptorList
|
||||||
QPair<QList<EventDescriptor>, RuleEngine::RuleError> eventDescriptorVerification = verifyEventDescriptors(params);
|
QPair<QList<EventDescriptor>, RuleEngine::RuleError> eventDescriptorVerification = JsonTypes::verifyEventDescriptors(params);
|
||||||
QList<EventDescriptor> eventDescriptorList = eventDescriptorVerification.first;
|
QList<EventDescriptor> eventDescriptorList = eventDescriptorVerification.first;
|
||||||
if (eventDescriptorVerification.second != RuleEngine::RuleErrorNoError) {
|
if (eventDescriptorVerification.second != RuleEngine::RuleErrorNoError) {
|
||||||
QVariantMap returns;
|
QVariantMap returns;
|
||||||
@ -191,13 +191,12 @@ JsonReply* RulesHandler::AddRule(const QVariantMap ¶ms)
|
|||||||
return createReply(returns);
|
return createReply(returns);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Check and unpack stateEvaluator
|
// Check and unpack stateEvaluator
|
||||||
qCDebug(dcJsonRpc) << "unpacking stateEvaluator:" << params.value("stateEvaluator").toMap();
|
qCDebug(dcJsonRpc) << "unpacking stateEvaluator:" << params.value("stateEvaluator").toMap();
|
||||||
StateEvaluator stateEvaluator = JsonTypes::unpackStateEvaluator(params.value("stateEvaluator").toMap());
|
StateEvaluator stateEvaluator = JsonTypes::unpackStateEvaluator(params.value("stateEvaluator").toMap());
|
||||||
|
|
||||||
// Check and unpack actions
|
// Check and unpack actions
|
||||||
QPair<QList<RuleAction>, RuleEngine::RuleError> actionsVerification = verifyActions(params, eventDescriptorList);
|
QPair<QList<RuleAction>, RuleEngine::RuleError> actionsVerification = JsonTypes::verifyActions(params, eventDescriptorList);
|
||||||
QList<RuleAction> actions = actionsVerification.first;
|
QList<RuleAction> actions = actionsVerification.first;
|
||||||
if (actionsVerification.second != RuleEngine::RuleErrorNoError) {
|
if (actionsVerification.second != RuleEngine::RuleErrorNoError) {
|
||||||
QVariantMap returns;
|
QVariantMap returns;
|
||||||
@ -206,7 +205,7 @@ JsonReply* RulesHandler::AddRule(const QVariantMap ¶ms)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Check and unpack exitActions
|
// Check and unpack exitActions
|
||||||
QPair<QList<RuleAction>, RuleEngine::RuleError> exitActionsVerification = verifyExitActions(params);
|
QPair<QList<RuleAction>, RuleEngine::RuleError> exitActionsVerification = JsonTypes::verifyExitActions(params);
|
||||||
QList<RuleAction> exitActions = exitActionsVerification.first;
|
QList<RuleAction> exitActions = exitActionsVerification.first;
|
||||||
if (exitActionsVerification.second != RuleEngine::RuleErrorNoError) {
|
if (exitActionsVerification.second != RuleEngine::RuleErrorNoError) {
|
||||||
QVariantMap returns;
|
QVariantMap returns;
|
||||||
@ -230,7 +229,7 @@ JsonReply* RulesHandler::AddRule(const QVariantMap ¶ms)
|
|||||||
JsonReply *RulesHandler::EditRule(const QVariantMap ¶ms)
|
JsonReply *RulesHandler::EditRule(const QVariantMap ¶ms)
|
||||||
{
|
{
|
||||||
// check rule consistency
|
// check rule consistency
|
||||||
RuleEngine::RuleError ruleConsistencyError = verifyRuleConsistency(params);
|
RuleEngine::RuleError ruleConsistencyError = JsonTypes::verifyRuleConsistency(params);
|
||||||
if (ruleConsistencyError != RuleEngine::RuleErrorNoError) {
|
if (ruleConsistencyError != RuleEngine::RuleErrorNoError) {
|
||||||
QVariantMap returns;
|
QVariantMap returns;
|
||||||
returns.insert("ruleError", JsonTypes::ruleErrorToString(ruleConsistencyError));
|
returns.insert("ruleError", JsonTypes::ruleErrorToString(ruleConsistencyError));
|
||||||
@ -238,7 +237,7 @@ JsonReply *RulesHandler::EditRule(const QVariantMap ¶ms)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Check and upack eventDescriptorList
|
// Check and upack eventDescriptorList
|
||||||
QPair<QList<EventDescriptor>, RuleEngine::RuleError> eventDescriptorVerification = verifyEventDescriptors(params);
|
QPair<QList<EventDescriptor>, RuleEngine::RuleError> eventDescriptorVerification = JsonTypes::verifyEventDescriptors(params);
|
||||||
QList<EventDescriptor> eventDescriptorList = eventDescriptorVerification.first;
|
QList<EventDescriptor> eventDescriptorList = eventDescriptorVerification.first;
|
||||||
if (eventDescriptorVerification.second != RuleEngine::RuleErrorNoError) {
|
if (eventDescriptorVerification.second != RuleEngine::RuleErrorNoError) {
|
||||||
QVariantMap returns;
|
QVariantMap returns;
|
||||||
@ -251,7 +250,7 @@ JsonReply *RulesHandler::EditRule(const QVariantMap ¶ms)
|
|||||||
StateEvaluator stateEvaluator = JsonTypes::unpackStateEvaluator(params.value("stateEvaluator").toMap());
|
StateEvaluator stateEvaluator = JsonTypes::unpackStateEvaluator(params.value("stateEvaluator").toMap());
|
||||||
|
|
||||||
// Check and unpack actions
|
// Check and unpack actions
|
||||||
QPair<QList<RuleAction>, RuleEngine::RuleError> actionsVerification = verifyActions(params, eventDescriptorList);
|
QPair<QList<RuleAction>, RuleEngine::RuleError> actionsVerification = JsonTypes::verifyActions(params, eventDescriptorList);
|
||||||
QList<RuleAction> actions = actionsVerification.first;
|
QList<RuleAction> actions = actionsVerification.first;
|
||||||
if (actionsVerification.second != RuleEngine::RuleErrorNoError) {
|
if (actionsVerification.second != RuleEngine::RuleErrorNoError) {
|
||||||
QVariantMap returns;
|
QVariantMap returns;
|
||||||
@ -260,7 +259,7 @@ JsonReply *RulesHandler::EditRule(const QVariantMap ¶ms)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Check and unpack exitActions
|
// Check and unpack exitActions
|
||||||
QPair<QList<RuleAction>, RuleEngine::RuleError> exitActionsVerification = verifyExitActions(params);
|
QPair<QList<RuleAction>, RuleEngine::RuleError> exitActionsVerification = JsonTypes::verifyExitActions(params);
|
||||||
QList<RuleAction> exitActions = exitActionsVerification.first;
|
QList<RuleAction> exitActions = exitActionsVerification.first;
|
||||||
if (exitActionsVerification.second != RuleEngine::RuleErrorNoError) {
|
if (exitActionsVerification.second != RuleEngine::RuleErrorNoError) {
|
||||||
QVariantMap returns;
|
QVariantMap returns;
|
||||||
@ -315,168 +314,6 @@ JsonReply *RulesHandler::DisableRule(const QVariantMap ¶ms)
|
|||||||
return createReply(statusToReply(GuhCore::instance()->disableRule(RuleId(params.value("ruleId").toString()))));
|
return createReply(statusToReply(GuhCore::instance()->disableRule(RuleId(params.value("ruleId").toString()))));
|
||||||
}
|
}
|
||||||
|
|
||||||
QVariant::Type RulesHandler::getActionParamType(const ActionTypeId &actionTypeId, const QString ¶mName)
|
|
||||||
{
|
|
||||||
foreach (const DeviceClass &deviceClass, GuhCore::instance()->supportedDevices()) {
|
|
||||||
foreach (const ActionType &actionType, deviceClass.actionTypes()) {
|
|
||||||
if (actionType.id() == actionTypeId) {
|
|
||||||
foreach (const ParamType ¶mType, actionType.paramTypes()) {
|
|
||||||
if (paramType.name() == paramName) {
|
|
||||||
return paramType.type();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return QVariant::Invalid;
|
|
||||||
}
|
|
||||||
|
|
||||||
QVariant::Type RulesHandler::getEventParamType(const EventTypeId &eventTypeId, const QString ¶mName)
|
|
||||||
{
|
|
||||||
foreach (const DeviceClass &deviceClass, GuhCore::instance()->supportedDevices()) {
|
|
||||||
foreach (const EventType &eventType, deviceClass.eventTypes()) {
|
|
||||||
if (eventType.id() == eventTypeId) {
|
|
||||||
foreach (const ParamType ¶mType, eventType.paramTypes()) {
|
|
||||||
// get ParamType of Event
|
|
||||||
if (paramType.name() == paramName) {
|
|
||||||
return paramType.type();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return QVariant::Invalid;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool RulesHandler::checkEventDescriptors(const QList<EventDescriptor> eventDescriptors, const EventTypeId &eventTypeId)
|
|
||||||
{
|
|
||||||
foreach (const EventDescriptor eventDescriptor, eventDescriptors) {
|
|
||||||
if (eventDescriptor.eventTypeId() == eventTypeId) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
RuleEngine::RuleError RulesHandler::verifyRuleConsistency(const QVariantMap ¶ms)
|
|
||||||
{
|
|
||||||
// check if there are an eventDescriptor and an eventDescriptorList
|
|
||||||
if (params.contains("eventDescriptor") && params.contains("eventDescriptorList")) {
|
|
||||||
qCWarning(dcJsonRpc) << "Only one of eventDesciptor or eventDescriptorList may be used.";
|
|
||||||
return RuleEngine::RuleErrorInvalidParameter;
|
|
||||||
}
|
|
||||||
|
|
||||||
// check if this rules is based on any event and contains exit actions
|
|
||||||
if (params.contains("eventDescriptor") || params.contains("eventDescriptorList")) {
|
|
||||||
if (params.contains("exitActions")) {
|
|
||||||
qCWarning(dcJsonRpc) << "The exitActions will never be executed if the rule contains an eventDescriptor.";
|
|
||||||
return RuleEngine::RuleErrorInvalidRuleFormat;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// check if there are any actions
|
|
||||||
if (params.value("actions").toList().isEmpty()) {
|
|
||||||
qCWarning(dcJsonRpc) << "Rule actions missing. A rule without actions has no effect.";
|
|
||||||
return RuleEngine::RuleErrorMissingParameter;
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: check if events and stateEvaluators are missing
|
|
||||||
|
|
||||||
return RuleEngine::RuleErrorNoError;
|
|
||||||
}
|
|
||||||
|
|
||||||
QPair<QList<EventDescriptor>, RuleEngine::RuleError> RulesHandler::verifyEventDescriptors(const QVariantMap ¶ms)
|
|
||||||
{
|
|
||||||
// Check and unpack eventDescriptors
|
|
||||||
QList<EventDescriptor> eventDescriptorList = QList<EventDescriptor>();
|
|
||||||
if (params.contains("eventDescriptor")) {
|
|
||||||
QVariantMap eventMap = params.value("eventDescriptor").toMap();
|
|
||||||
qCDebug(dcJsonRpc) << "unpacking eventDescriptor" << eventMap;
|
|
||||||
eventDescriptorList.append(JsonTypes::unpackEventDescriptor(eventMap));
|
|
||||||
} else if (params.contains("eventDescriptorList")) {
|
|
||||||
QVariantList eventDescriptors = params.value("eventDescriptorList").toList();
|
|
||||||
qCDebug(dcJsonRpc) << "unpacking eventDescriptorList:" << eventDescriptors;
|
|
||||||
foreach (const QVariant &eventVariant, eventDescriptors) {
|
|
||||||
QVariantMap eventMap = eventVariant.toMap();
|
|
||||||
eventDescriptorList.append(JsonTypes::unpackEventDescriptor(eventMap));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return QPair<QList<EventDescriptor>, RuleEngine::RuleError>(eventDescriptorList, RuleEngine::RuleErrorNoError);
|
|
||||||
}
|
|
||||||
|
|
||||||
QPair<QList<RuleAction>, RuleEngine::RuleError> RulesHandler::verifyActions(const QVariantMap ¶ms, const QList<EventDescriptor> &eventDescriptorList)
|
|
||||||
{
|
|
||||||
QList<RuleAction> actions;
|
|
||||||
QVariantList actionList = params.value("actions").toList();
|
|
||||||
qCDebug(dcJsonRpc) << "unpacking actions:" << actionList;
|
|
||||||
foreach (const QVariant &actionVariant, actionList) {
|
|
||||||
QVariantMap actionMap = actionVariant.toMap();
|
|
||||||
RuleAction action(ActionTypeId(actionMap.value("actionTypeId").toString()), DeviceId(actionMap.value("deviceId").toString()));
|
|
||||||
RuleActionParamList actionParamList = JsonTypes::unpackRuleActionParams(actionMap.value("ruleActionParams").toList());
|
|
||||||
foreach (const RuleActionParam &ruleActionParam, actionParamList) {
|
|
||||||
if (!ruleActionParam.isValid()) {
|
|
||||||
qCWarning(dcJsonRpc) << "got an actionParam with value AND eventTypeId!";
|
|
||||||
return QPair<QList<RuleAction>, RuleEngine::RuleError>(actions, RuleEngine::RuleErrorInvalidRuleActionParameter);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
qCDebug(dcJsonRpc) << "params in exitAction" << action.ruleActionParams();
|
|
||||||
action.setRuleActionParams(actionParamList);
|
|
||||||
actions.append(action);
|
|
||||||
}
|
|
||||||
|
|
||||||
// check possible eventTypeIds in params
|
|
||||||
foreach (const RuleAction &ruleAction, actions) {
|
|
||||||
if (ruleAction.isEventBased()) {
|
|
||||||
foreach (const RuleActionParam &ruleActionParam, ruleAction.ruleActionParams()) {
|
|
||||||
if (ruleActionParam.eventTypeId() != EventTypeId()) {
|
|
||||||
// We have an eventTypeId
|
|
||||||
if (eventDescriptorList.isEmpty()) {
|
|
||||||
qCWarning(dcJsonRpc) << "RuleAction" << ruleAction.actionTypeId() << "contains an eventTypeId, but there are no eventDescriptors.";
|
|
||||||
return QPair<QList<RuleAction>, RuleEngine::RuleError>(actions, RuleEngine::RuleErrorInvalidRuleActionParameter);
|
|
||||||
}
|
|
||||||
// now check if this eventType is in the eventDescriptorList of this rule
|
|
||||||
if (!checkEventDescriptors(eventDescriptorList, ruleActionParam.eventTypeId())) {
|
|
||||||
qCWarning(dcJsonRpc) << "eventTypeId from RuleAction" << ruleAction.actionTypeId() << "missing in eventDescriptors.";
|
|
||||||
return QPair<QList<RuleAction>, RuleEngine::RuleError>(actions, RuleEngine::RuleErrorInvalidRuleActionParameter);
|
|
||||||
}
|
|
||||||
|
|
||||||
// check if the param type of the event and the action match
|
|
||||||
QVariant::Type eventParamType = getEventParamType(ruleActionParam.eventTypeId(), ruleActionParam.eventParamName());
|
|
||||||
QVariant::Type actionParamType = getActionParamType(ruleAction.actionTypeId(), ruleActionParam.name());
|
|
||||||
if (eventParamType != actionParamType) {
|
|
||||||
qCWarning(dcJsonRpc) << "RuleActionParam" << ruleActionParam.name() << " and given event param " << ruleActionParam.eventParamName() << "have not the same type:";
|
|
||||||
qCWarning(dcJsonRpc) << " -> actionParamType:" << actionParamType;
|
|
||||||
qCWarning(dcJsonRpc) << " -> eventParamType:" << eventParamType;
|
|
||||||
return QPair<QList<RuleAction>, RuleEngine::RuleError>(actions, RuleEngine::RuleErrorTypesNotMatching);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return QPair<QList<RuleAction>, RuleEngine::RuleError>(actions, RuleEngine::RuleErrorNoError);
|
|
||||||
}
|
|
||||||
|
|
||||||
QPair<QList<RuleAction>, RuleEngine::RuleError> RulesHandler::verifyExitActions(const QVariantMap ¶ms)
|
|
||||||
{
|
|
||||||
QList<RuleAction> exitActions;
|
|
||||||
if (params.contains("exitActions")) {
|
|
||||||
QVariantList exitActionList = params.value("exitActions").toList();
|
|
||||||
qCDebug(dcJsonRpc) << "unpacking exitActions:" << exitActionList;
|
|
||||||
foreach (const QVariant &actionVariant, exitActionList) {
|
|
||||||
QVariantMap actionMap = actionVariant.toMap();
|
|
||||||
RuleAction action(ActionTypeId(actionMap.value("actionTypeId").toString()), DeviceId(actionMap.value("deviceId").toString()));
|
|
||||||
if (action.isEventBased()) {
|
|
||||||
qCWarning(dcJsonRpc) << "got exitAction with a param value containing an eventTypeId!";
|
|
||||||
return QPair<QList<RuleAction>, RuleEngine::RuleError>(exitActions, RuleEngine::RuleErrorInvalidRuleActionParameter);
|
|
||||||
}
|
|
||||||
qCDebug(dcJsonRpc) << "params in exitAction" << action.ruleActionParams();
|
|
||||||
action.setRuleActionParams(JsonTypes::unpackRuleActionParams(actionMap.value("ruleActionParams").toList()));
|
|
||||||
exitActions.append(action);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return QPair<QList<RuleAction>, RuleEngine::RuleError>(exitActions, RuleEngine::RuleErrorNoError);
|
|
||||||
}
|
|
||||||
|
|
||||||
void RulesHandler::ruleRemovedNotification(const RuleId &ruleId)
|
void RulesHandler::ruleRemovedNotification(const RuleId &ruleId)
|
||||||
{
|
{
|
||||||
QVariantMap params;
|
QVariantMap params;
|
||||||
|
|||||||
@ -51,17 +51,6 @@ signals:
|
|||||||
void RuleActiveChanged(const QVariantMap ¶ms);
|
void RuleActiveChanged(const QVariantMap ¶ms);
|
||||||
void RuleConfigurationChanged(const QVariantMap ¶ms);
|
void RuleConfigurationChanged(const QVariantMap ¶ms);
|
||||||
|
|
||||||
private:
|
|
||||||
QVariant::Type getActionParamType(const ActionTypeId &actionTypeId, const QString ¶mName);
|
|
||||||
QVariant::Type getEventParamType(const EventTypeId &eventTypeId, const QString ¶mName);
|
|
||||||
|
|
||||||
bool checkEventDescriptors(const QList<EventDescriptor> eventDescriptors, const EventTypeId &eventTypeId);
|
|
||||||
|
|
||||||
RuleEngine::RuleError verifyRuleConsistency(const QVariantMap ¶ms);
|
|
||||||
QPair<QList<EventDescriptor>, RuleEngine::RuleError> verifyEventDescriptors(const QVariantMap ¶ms);
|
|
||||||
QPair<QList<RuleAction>, RuleEngine::RuleError> verifyActions(const QVariantMap ¶ms, const QList<EventDescriptor> &eventDescriptorList);
|
|
||||||
QPair<QList<RuleAction>, RuleEngine::RuleError> verifyExitActions(const QVariantMap ¶ms);
|
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void ruleRemovedNotification(const RuleId &ruleId);
|
void ruleRemovedNotification(const RuleId &ruleId);
|
||||||
void ruleAddedNotification(const Rule &rule);
|
void ruleAddedNotification(const Rule &rule);
|
||||||
|
|||||||
@ -45,7 +45,6 @@ HttpReply *DevicesResource::proccessRequest(const HttpRequest &request, const QS
|
|||||||
{
|
{
|
||||||
m_device = 0;
|
m_device = 0;
|
||||||
|
|
||||||
|
|
||||||
// get the main resource
|
// get the main resource
|
||||||
if (urlTokens.count() >= 4) {
|
if (urlTokens.count() >= 4) {
|
||||||
DeviceId deviceId = DeviceId(urlTokens.at(3));
|
DeviceId deviceId = DeviceId(urlTokens.at(3));
|
||||||
|
|||||||
@ -62,6 +62,9 @@ HttpReply *RulesResource::proccessRequest(const HttpRequest &request, const QStr
|
|||||||
case HttpRequest::Put:
|
case HttpRequest::Put:
|
||||||
reply = proccessPutRequest(request, urlTokens);
|
reply = proccessPutRequest(request, urlTokens);
|
||||||
break;
|
break;
|
||||||
|
case HttpRequest::Post:
|
||||||
|
reply = proccessPostRequest(request, urlTokens);
|
||||||
|
break;
|
||||||
case HttpRequest::Delete:
|
case HttpRequest::Delete:
|
||||||
reply = proccessDeleteRequest(request, urlTokens);
|
reply = proccessDeleteRequest(request, urlTokens);
|
||||||
break;
|
break;
|
||||||
@ -129,6 +132,14 @@ HttpReply *RulesResource::proccessPostRequest(const HttpRequest &request, const
|
|||||||
if (urlTokens.count() == 3)
|
if (urlTokens.count() == 3)
|
||||||
return addRule(request.payload());
|
return addRule(request.payload());
|
||||||
|
|
||||||
|
// POST /api/v1/rules/{ruleId}/enable
|
||||||
|
if (urlTokens.count() == 5 && urlTokens.at(4) == "enable")
|
||||||
|
return enableRule(m_ruleId);
|
||||||
|
|
||||||
|
// POST /api/v1/rules/{ruleId}/disable
|
||||||
|
if (urlTokens.count() == 5 && urlTokens.at(4) == "disable")
|
||||||
|
return disableRule(m_ruleId);
|
||||||
|
|
||||||
return createErrorReply(HttpReply::NotImplemented);
|
return createErrorReply(HttpReply::NotImplemented);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -179,19 +190,130 @@ HttpReply *RulesResource::removeRule(const RuleId &ruleId) const
|
|||||||
|
|
||||||
HttpReply *RulesResource::addRule(const QByteArray &payload) const
|
HttpReply *RulesResource::addRule(const QByteArray &payload) const
|
||||||
{
|
{
|
||||||
Q_UNUSED(payload)
|
|
||||||
qCDebug(dcRest) << "Add new rule";
|
qCDebug(dcRest) << "Add new rule";
|
||||||
|
|
||||||
|
QPair<bool, QVariant> verification = RestResource::verifyPayload(payload);
|
||||||
|
if (!verification.first)
|
||||||
|
return createErrorReply(HttpReply::BadRequest);
|
||||||
|
|
||||||
return createErrorReply(HttpReply::NotImplemented);
|
QVariantMap params = verification.second.toMap();
|
||||||
|
|
||||||
|
// check rule consistency
|
||||||
|
RuleEngine::RuleError ruleConsistencyError = JsonTypes::verifyRuleConsistency(params);
|
||||||
|
if (ruleConsistencyError != RuleEngine::RuleErrorNoError)
|
||||||
|
return createErrorReply(HttpReply::BadRequest);
|
||||||
|
|
||||||
|
// Check and upack eventDescriptorList
|
||||||
|
QPair<QList<EventDescriptor>, RuleEngine::RuleError> eventDescriptorVerification = JsonTypes::verifyEventDescriptors(params);
|
||||||
|
QList<EventDescriptor> eventDescriptorList = eventDescriptorVerification.first;
|
||||||
|
if (eventDescriptorVerification.second != RuleEngine::RuleErrorNoError)
|
||||||
|
return createErrorReply(HttpReply::BadRequest);
|
||||||
|
|
||||||
|
// Check and unpack stateEvaluator
|
||||||
|
qCDebug(dcRest) << "unpacking stateEvaluator:" << params.value("stateEvaluator").toMap();
|
||||||
|
StateEvaluator stateEvaluator = JsonTypes::unpackStateEvaluator(params.value("stateEvaluator").toMap());
|
||||||
|
|
||||||
|
// Check and unpack actions
|
||||||
|
QPair<QList<RuleAction>, RuleEngine::RuleError> actionsVerification = JsonTypes::verifyActions(params, eventDescriptorList);
|
||||||
|
QList<RuleAction> actions = actionsVerification.first;
|
||||||
|
if (actionsVerification.second != RuleEngine::RuleErrorNoError)
|
||||||
|
return createErrorReply(HttpReply::BadRequest);
|
||||||
|
|
||||||
|
|
||||||
|
// Check and unpack exitActions
|
||||||
|
QPair<QList<RuleAction>, RuleEngine::RuleError> exitActionsVerification = JsonTypes::verifyExitActions(params);
|
||||||
|
QList<RuleAction> exitActions = exitActionsVerification.first;
|
||||||
|
if (exitActionsVerification.second != RuleEngine::RuleErrorNoError)
|
||||||
|
return createErrorReply(HttpReply::BadRequest);
|
||||||
|
|
||||||
|
QString name = params.value("name", QString()).toString();
|
||||||
|
bool enabled = params.value("enabled", true).toBool();
|
||||||
|
|
||||||
|
RuleId newRuleId = RuleId::createRuleId();
|
||||||
|
RuleEngine::RuleError status = GuhCore::instance()->addRule(newRuleId, name, eventDescriptorList, stateEvaluator, actions, exitActions, enabled);
|
||||||
|
|
||||||
|
if (status == RuleEngine::RuleErrorNoError) {
|
||||||
|
QVariantMap returns;
|
||||||
|
returns.insert("ruleId", newRuleId.toString());
|
||||||
|
HttpReply *reply = createSuccessReply();
|
||||||
|
reply->setPayload(QJsonDocument::fromVariant(returns).toJson());
|
||||||
|
return reply;
|
||||||
|
}
|
||||||
|
|
||||||
|
return createErrorReply(HttpReply::BadRequest);
|
||||||
|
}
|
||||||
|
|
||||||
|
HttpReply *RulesResource::enableRule(const RuleId &ruleId) const
|
||||||
|
{
|
||||||
|
qCDebug(dcRest) << "Enable rule with id" << ruleId.toString();
|
||||||
|
|
||||||
|
RuleEngine::RuleError status = GuhCore::instance()->enableRule(ruleId);
|
||||||
|
if (status == RuleEngine::RuleErrorNoError)
|
||||||
|
return createSuccessReply();
|
||||||
|
|
||||||
|
return createErrorReply(HttpReply::BadRequest);
|
||||||
|
}
|
||||||
|
|
||||||
|
HttpReply *RulesResource::disableRule(const RuleId &ruleId) const
|
||||||
|
{
|
||||||
|
qCDebug(dcRest) << "Disable rule with id" << ruleId.toString();
|
||||||
|
|
||||||
|
RuleEngine::RuleError status = GuhCore::instance()->disableRule(ruleId);
|
||||||
|
if (status == RuleEngine::RuleErrorNoError)
|
||||||
|
return createSuccessReply();
|
||||||
|
|
||||||
|
return createErrorReply(HttpReply::BadRequest);
|
||||||
}
|
}
|
||||||
|
|
||||||
HttpReply *RulesResource::editRule(const RuleId &ruleId, const QByteArray &payload) const
|
HttpReply *RulesResource::editRule(const RuleId &ruleId, const QByteArray &payload) const
|
||||||
{
|
{
|
||||||
Q_UNUSED(payload)
|
qCDebug(dcRest) << "Edit rule with id" << ruleId.toString();
|
||||||
qCDebug(dcRest) << "Edit rule with id" << ruleId;
|
|
||||||
|
|
||||||
return createErrorReply(HttpReply::NotImplemented);
|
QPair<bool, QVariant> verification = RestResource::verifyPayload(payload);
|
||||||
|
if (!verification.first)
|
||||||
|
return createErrorReply(HttpReply::BadRequest);
|
||||||
|
|
||||||
|
QVariantMap params = verification.second.toMap();
|
||||||
|
|
||||||
|
// check rule consistency
|
||||||
|
RuleEngine::RuleError ruleConsistencyError = JsonTypes::verifyRuleConsistency(params);
|
||||||
|
if (ruleConsistencyError != RuleEngine::RuleErrorNoError)
|
||||||
|
return createErrorReply(HttpReply::BadRequest);
|
||||||
|
|
||||||
|
// Check and upack eventDescriptorList
|
||||||
|
QPair<QList<EventDescriptor>, RuleEngine::RuleError> eventDescriptorVerification = JsonTypes::verifyEventDescriptors(params);
|
||||||
|
QList<EventDescriptor> eventDescriptorList = eventDescriptorVerification.first;
|
||||||
|
if (eventDescriptorVerification.second != RuleEngine::RuleErrorNoError)
|
||||||
|
return createErrorReply(HttpReply::BadRequest);
|
||||||
|
|
||||||
|
// Check and unpack stateEvaluator
|
||||||
|
qCDebug(dcRest) << "unpacking stateEvaluator:" << params.value("stateEvaluator").toMap();
|
||||||
|
StateEvaluator stateEvaluator = JsonTypes::unpackStateEvaluator(params.value("stateEvaluator").toMap());
|
||||||
|
|
||||||
|
// Check and unpack actions
|
||||||
|
QPair<QList<RuleAction>, RuleEngine::RuleError> actionsVerification = JsonTypes::verifyActions(params, eventDescriptorList);
|
||||||
|
QList<RuleAction> actions = actionsVerification.first;
|
||||||
|
if (actionsVerification.second != RuleEngine::RuleErrorNoError)
|
||||||
|
return createErrorReply(HttpReply::BadRequest);
|
||||||
|
|
||||||
|
// Check and unpack exitActions
|
||||||
|
QPair<QList<RuleAction>, RuleEngine::RuleError> exitActionsVerification = JsonTypes::verifyExitActions(params);
|
||||||
|
QList<RuleAction> exitActions = exitActionsVerification.first;
|
||||||
|
if (exitActionsVerification.second != RuleEngine::RuleErrorNoError)
|
||||||
|
return createErrorReply(HttpReply::BadRequest);
|
||||||
|
|
||||||
|
QString name = params.value("name", QString()).toString();
|
||||||
|
bool enabled = params.value("enabled", true).toBool();
|
||||||
|
|
||||||
|
RuleEngine::RuleError status = GuhCore::instance()->editRule(ruleId, name, eventDescriptorList, stateEvaluator, actions, exitActions, enabled);
|
||||||
|
|
||||||
|
if (status == RuleEngine::RuleErrorNoError) {
|
||||||
|
qCDebug(dcRest) << "Edit rule successfully finished";
|
||||||
|
return createSuccessReply();
|
||||||
|
}
|
||||||
|
|
||||||
|
qCWarning(dcRest) << "Edit rule finished with error" << status;
|
||||||
|
return createErrorReply(HttpReply::BadRequest);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -60,6 +60,8 @@ private:
|
|||||||
|
|
||||||
// Post methods
|
// Post methods
|
||||||
HttpReply *addRule(const QByteArray &payload) const;
|
HttpReply *addRule(const QByteArray &payload) const;
|
||||||
|
HttpReply *enableRule(const RuleId &ruleId) const;
|
||||||
|
HttpReply *disableRule(const RuleId &ruleId) const;
|
||||||
|
|
||||||
// Put methods
|
// Put methods
|
||||||
HttpReply *editRule(const RuleId &ruleId, const QByteArray &payload) const;
|
HttpReply *editRule(const RuleId &ruleId, const QByteArray &payload) const;
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
|
|
||||||
contains(DEFINES, WEBSERVER){
|
contains(DEFINES, WEBSOCKET){
|
||||||
QT += websockets
|
QT += websockets
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
TEMPLATE=subdirs
|
TEMPLATE = subdirs
|
||||||
|
|
||||||
SUBDIRS=versioning \
|
SUBDIRS = versioning \
|
||||||
devices \
|
devices \
|
||||||
jsonrpc \
|
jsonrpc \
|
||||||
events \
|
events \
|
||||||
@ -13,3 +13,4 @@ SUBDIRS=versioning \
|
|||||||
restdeviceclasses \
|
restdeviceclasses \
|
||||||
restplugins \
|
restplugins \
|
||||||
restvendors \
|
restvendors \
|
||||||
|
restrules \
|
||||||
|
|||||||
@ -248,6 +248,7 @@ void TestRestDeviceClasses::discoverDevices()
|
|||||||
QNetworkAccessManager *nam = new QNetworkAccessManager();
|
QNetworkAccessManager *nam = new QNetworkAccessManager();
|
||||||
QSignalSpy clientSpy(nam, SIGNAL(finished(QNetworkReply*)));
|
QSignalSpy clientSpy(nam, SIGNAL(finished(QNetworkReply*)));
|
||||||
|
|
||||||
|
// DISCOVER
|
||||||
QUrl url(QString("http://localhost:3000/api/v1/deviceclasses/%1/discover").arg(deviceClassId.toString()));
|
QUrl url(QString("http://localhost:3000/api/v1/deviceclasses/%1/discover").arg(deviceClassId.toString()));
|
||||||
|
|
||||||
if (!discoveryParams.isEmpty()) {
|
if (!discoveryParams.isEmpty()) {
|
||||||
@ -275,7 +276,7 @@ void TestRestDeviceClasses::discoverDevices()
|
|||||||
QVariantList foundDevices = jsonDoc.toVariant().toList();
|
QVariantList foundDevices = jsonDoc.toVariant().toList();
|
||||||
QCOMPARE(foundDevices.count(), resultCount);
|
QCOMPARE(foundDevices.count(), resultCount);
|
||||||
|
|
||||||
// add the discovered device
|
// ADD the discovered device
|
||||||
request.setUrl(QUrl("http://localhost:3000/api/v1/devices"));
|
request.setUrl(QUrl("http://localhost:3000/api/v1/devices"));
|
||||||
DeviceDescriptorId descriptorId = DeviceDescriptorId(foundDevices.first().toMap().value("id").toString());
|
DeviceDescriptorId descriptorId = DeviceDescriptorId(foundDevices.first().toMap().value("id").toString());
|
||||||
qDebug() << descriptorId;
|
qDebug() << descriptorId;
|
||||||
@ -294,7 +295,7 @@ void TestRestDeviceClasses::discoverDevices()
|
|||||||
reply->deleteLater();
|
reply->deleteLater();
|
||||||
QCOMPARE(statusCode, expectedStatusCode);
|
QCOMPARE(statusCode, expectedStatusCode);
|
||||||
|
|
||||||
// remove added device
|
// REMOVE added device
|
||||||
jsonDoc = QJsonDocument::fromJson(data, &error);
|
jsonDoc = QJsonDocument::fromJson(data, &error);
|
||||||
QCOMPARE(error.error, QJsonParseError::NoError);
|
QCOMPARE(error.error, QJsonParseError::NoError);
|
||||||
QVariantMap response = jsonDoc.toVariant().toMap();
|
QVariantMap response = jsonDoc.toVariant().toMap();
|
||||||
|
|||||||
5
tests/auto/restrules/restrules.pro
Normal file
5
tests/auto/restrules/restrules.pro
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
include(../../../guh.pri)
|
||||||
|
include(../autotests.pri)
|
||||||
|
|
||||||
|
TARGET = restrules
|
||||||
|
SOURCES += testrestrules.cpp
|
||||||
911
tests/auto/restrules/testrestrules.cpp
Normal file
911
tests/auto/restrules/testrestrules.cpp
Normal file
@ -0,0 +1,911 @@
|
|||||||
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
|
* *
|
||||||
|
* Copyright (C) 2015 Simon Stuerz <simon.stuerz@guh.guru> *
|
||||||
|
* *
|
||||||
|
* 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 "webserver.h"
|
||||||
|
|
||||||
|
#include <QtTest/QtTest>
|
||||||
|
#include <QCoreApplication>
|
||||||
|
#include <QTcpSocket>
|
||||||
|
#include <QNetworkAccessManager>
|
||||||
|
#include <QNetworkRequest>
|
||||||
|
#include <QNetworkReply>
|
||||||
|
#include <QCoreApplication>
|
||||||
|
#include <QJsonDocument>
|
||||||
|
#include <QHttpPart>
|
||||||
|
#include <QMetaType>
|
||||||
|
|
||||||
|
using namespace guhserver;
|
||||||
|
|
||||||
|
class TestRestRules: public GuhTestBase
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
private:
|
||||||
|
void cleanupMockHistory();
|
||||||
|
void cleanupRules();
|
||||||
|
|
||||||
|
void verifyRuleExecuted(const ActionTypeId &actionTypeId);
|
||||||
|
void verifyRuleNotExecuted();
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void addRemoveRules_data();
|
||||||
|
void addRemoveRules();
|
||||||
|
|
||||||
|
void editRules_data();
|
||||||
|
void editRules();
|
||||||
|
|
||||||
|
void enableDisableRule();
|
||||||
|
|
||||||
|
void getRules();
|
||||||
|
};
|
||||||
|
|
||||||
|
void TestRestRules::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 TestRestRules::cleanupRules()
|
||||||
|
{
|
||||||
|
QNetworkAccessManager *nam = new QNetworkAccessManager(this);
|
||||||
|
QSignalSpy clientSpy(nam, SIGNAL(finished(QNetworkReply*)));
|
||||||
|
|
||||||
|
// Get all rules
|
||||||
|
QNetworkRequest request = QNetworkRequest(QUrl("http://localhost:3000/api/v1/rules"));
|
||||||
|
QNetworkReply *reply = nam->get(request);
|
||||||
|
clientSpy.wait();
|
||||||
|
QVERIFY2(clientSpy.count() == 1, "expected exactly 1 response from webserver");
|
||||||
|
int statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
|
||||||
|
QCOMPARE(statusCode, 200);
|
||||||
|
QByteArray data = reply->readAll();
|
||||||
|
reply->deleteLater();
|
||||||
|
|
||||||
|
QJsonParseError error;
|
||||||
|
QJsonDocument jsonDoc = QJsonDocument::fromJson(data, &error);
|
||||||
|
QCOMPARE(error.error, QJsonParseError::NoError);
|
||||||
|
QVariantList rulesList = jsonDoc.toVariant().toList();
|
||||||
|
|
||||||
|
// delete each rule
|
||||||
|
foreach (const QVariant &rule, rulesList) {
|
||||||
|
clientSpy.clear();
|
||||||
|
QVariantMap ruleMap = rule.toMap();
|
||||||
|
QNetworkRequest request(QUrl(QString("http://localhost:3000/api/v1/rules/%1").arg(ruleMap.value("id").toString())));
|
||||||
|
request.setHeader(QNetworkRequest::ContentTypeHeader, "text/json");
|
||||||
|
reply = nam->deleteResource(request);
|
||||||
|
clientSpy.wait();
|
||||||
|
QVERIFY2(clientSpy.count() == 1, "expected exactly 1 response from webserver");
|
||||||
|
int statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
|
||||||
|
QCOMPARE(statusCode, 200);
|
||||||
|
reply->deleteLater();
|
||||||
|
}
|
||||||
|
nam->deleteLater();
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestRestRules::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 TestRestRules::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();
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestRestRules::addRemoveRules_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>("action1");
|
||||||
|
QTest::addColumn<QVariantMap>("exitAction1");
|
||||||
|
QTest::addColumn<QVariantMap>("eventDescriptor");
|
||||||
|
QTest::addColumn<QVariantList>("eventDescriptorList");
|
||||||
|
QTest::addColumn<QVariantMap>("stateEvaluator");
|
||||||
|
QTest::addColumn<int>("expectedStatusCode");
|
||||||
|
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() << 200 << true << "ActionEventRule1";
|
||||||
|
QTest::newRow("invalid rule. enabled, 1 Action (eventBased), 1 EventDescriptor, name") << true << invalidActionEventBased2 << QVariantMap() << validEventDescriptor3 << QVariantList() << QVariantMap() << 400 << false << "TestRule";
|
||||||
|
|
||||||
|
QTest::newRow("invalid rule. enabled, 1 Action (eventBased), types not matching, name") << true << invalidActionEventBased3 << QVariantMap() << validEventDescriptor1 << QVariantList() << QVariantMap() << 400 << false << "TestRule";
|
||||||
|
|
||||||
|
QTest::newRow("invalid rule. enabled, 1 Action (eventBased), 1 EventDescriptor, name") << true << invalidActionEventBased << QVariantMap() << validEventDescriptor2 << QVariantList() << QVariantMap() << 400 << false << "TestRule";
|
||||||
|
QTest::newRow("invalid rule. enabled, 1 Action (eventBased), 1 StateEvaluator, name") << true << validActionEventBased << QVariantMap() << QVariantMap() << QVariantList() << validStateEvaluator << 400 << false << "TestRule";
|
||||||
|
QTest::newRow("invalid rule. enabled, 1 Action (eventBased), 1 EventDescriptor, name") << true << validActionEventBased << validActionEventBased << validEventDescriptor2 << QVariantList() << QVariantMap() << 400 << false << "TestRule";
|
||||||
|
QTest::newRow("invalid rule. enabled, 1 Action, 1 ExitAction (EventBased), name") << true << validActionNoParams << validActionEventBased << validEventDescriptor2 << QVariantList() << QVariantMap() << 400 << 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 << 200 << true << "TestRule";
|
||||||
|
QTest::newRow("valid rule. disabled, 1 Action, 1 Exit Action, 1 StateEvaluator, name") << false << validActionNoParams << validExitActionNoParams << QVariantMap() << QVariantList() << validStateEvaluator << 200 << true << "TestRule";
|
||||||
|
QTest::newRow("invalid rule. disabled, 1 Action, 1 invalid Exit Action, 1 StateEvaluator, name") << false << validActionNoParams << invalidExitAction << QVariantMap() << QVariantList() << validStateEvaluator << 400 << false << "TestRule";
|
||||||
|
QTest::newRow("invalid rule. 1 Action, 1 Exit Action, 1 EventDescriptor, 1 StateEvaluator, name") << true << validActionNoParams << validExitActionNoParams << validEventDescriptor1 << QVariantList() << validStateEvaluator << 400 << false << "TestRule";
|
||||||
|
QTest::newRow("invalid rule. 1 Action, 1 Exit Action, eventDescriptorList, 1 StateEvaluator, name") << true << validActionNoParams << validExitActionNoParams << QVariantMap() << eventDescriptorList << validStateEvaluator << 400 << false << "TestRule";
|
||||||
|
|
||||||
|
// Rules without exit actions
|
||||||
|
QTest::newRow("valid rule. enabled, 1 EventDescriptor, StateEvaluator, 1 Action, name") << true << validActionNoParams << QVariantMap() << validEventDescriptor1 << QVariantList() << validStateEvaluator << 200 << true << "TestRule";
|
||||||
|
QTest::newRow("valid rule. diabled, 1 EventDescriptor, StateEvaluator, 1 Action, name") << false << validActionNoParams << QVariantMap() << validEventDescriptor1 << QVariantList() << validStateEvaluator << 200 << true << "TestRule";
|
||||||
|
QTest::newRow("valid rule. 2 EventDescriptors, 1 Action, name") << true << validActionNoParams << QVariantMap() << QVariantMap() << eventDescriptorList << validStateEvaluator << 200 << true << "TestRule";
|
||||||
|
QTest::newRow("invalid rule: eventDescriptor and eventDescriptorList used") << true << validActionNoParams << QVariantMap() << validEventDescriptor1 << eventDescriptorList << validStateEvaluator << 400 << false << "TestRule";
|
||||||
|
QTest::newRow("invalid action") << true << invalidAction << QVariantMap() << validEventDescriptor1 << QVariantList() << validStateEvaluator << 400 << false << "TestRule";
|
||||||
|
QTest::newRow("invalid event descriptor") << true << validActionNoParams << QVariantMap() << invalidEventDescriptor << QVariantList() << validStateEvaluator << 400 << false << "TestRule";
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestRestRules::addRemoveRules()
|
||||||
|
{
|
||||||
|
QFETCH(bool, enabled);
|
||||||
|
QFETCH(QVariantMap, action1);
|
||||||
|
QFETCH(QVariantMap, exitAction1);
|
||||||
|
QFETCH(QVariantMap, eventDescriptor);
|
||||||
|
QFETCH(QVariantList, eventDescriptorList);
|
||||||
|
QFETCH(QVariantMap, stateEvaluator);
|
||||||
|
QFETCH(int, expectedStatusCode);
|
||||||
|
QFETCH(bool, jsonError);
|
||||||
|
QFETCH(QString, name);
|
||||||
|
|
||||||
|
Q_UNUSED(jsonError)
|
||||||
|
|
||||||
|
// create add params for rule
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
QNetworkAccessManager *nam = new QNetworkAccessManager(this);
|
||||||
|
QSignalSpy clientSpy(nam, SIGNAL(finished(QNetworkReply*)));
|
||||||
|
|
||||||
|
// Get rules and verify there is no rule added
|
||||||
|
QNetworkRequest request;
|
||||||
|
request.setUrl(QUrl("http://localhost:3000/api/v1/rules"));
|
||||||
|
QNetworkReply *reply = nam->get(request);
|
||||||
|
clientSpy.wait();
|
||||||
|
QVERIFY2(clientSpy.count() == 1, "expected exactly 1 response from webserver");
|
||||||
|
int statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
|
||||||
|
QCOMPARE(statusCode, 200);
|
||||||
|
QByteArray data = reply->readAll();
|
||||||
|
reply->deleteLater();
|
||||||
|
|
||||||
|
QJsonParseError error;
|
||||||
|
QJsonDocument jsonDoc = QJsonDocument::fromJson(data, &error);
|
||||||
|
QCOMPARE(error.error, QJsonParseError::NoError);
|
||||||
|
QVariantList rulesList = jsonDoc.toVariant().toList();
|
||||||
|
QVERIFY2(rulesList.count() == 0, "there should be no rules.");
|
||||||
|
|
||||||
|
// ADD rule
|
||||||
|
clientSpy.clear();
|
||||||
|
request = QNetworkRequest(QUrl(QString("http://localhost:3000/api/v1/rules")));
|
||||||
|
request.setHeader(QNetworkRequest::ContentTypeHeader, "text/json");
|
||||||
|
reply = nam->post(request, QJsonDocument::fromVariant(params).toJson(QJsonDocument::Compact));
|
||||||
|
clientSpy.wait();
|
||||||
|
QVERIFY2(clientSpy.count() == 1, "expected exactly 1 response from webserver");
|
||||||
|
statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
|
||||||
|
QCOMPARE(statusCode, expectedStatusCode);
|
||||||
|
|
||||||
|
if (expectedStatusCode != 200)
|
||||||
|
return;
|
||||||
|
|
||||||
|
jsonDoc = QJsonDocument::fromJson(reply->readAll(), &error);
|
||||||
|
QCOMPARE(error.error, QJsonParseError::NoError);
|
||||||
|
reply->deleteLater();
|
||||||
|
|
||||||
|
RuleId ruleId = RuleId(jsonDoc.toVariant().toMap().value("ruleId").toString());
|
||||||
|
QVERIFY(!ruleId.isNull());
|
||||||
|
|
||||||
|
// GET rule details
|
||||||
|
clientSpy.clear();
|
||||||
|
request = QNetworkRequest(QUrl(QString("http://localhost:3000/api/v1/rules/%1").arg(ruleId.toString())));
|
||||||
|
request.setHeader(QNetworkRequest::ContentTypeHeader, "text/json");
|
||||||
|
reply = nam->get(request);
|
||||||
|
clientSpy.wait();
|
||||||
|
QVERIFY2(clientSpy.count() == 1, "expected exactly 1 response from webserver");
|
||||||
|
statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
|
||||||
|
QCOMPARE(statusCode, 200);
|
||||||
|
data = reply->readAll();
|
||||||
|
reply->deleteLater();
|
||||||
|
jsonDoc = QJsonDocument::fromJson(data, &error);
|
||||||
|
QCOMPARE(error.error, QJsonParseError::NoError);
|
||||||
|
|
||||||
|
// REMOVE rule
|
||||||
|
clientSpy.clear();
|
||||||
|
request = QNetworkRequest(QUrl(QString("http://localhost:3000/api/v1/rules/%1").arg(ruleId.toString())));
|
||||||
|
request.setHeader(QNetworkRequest::ContentTypeHeader, "text/json");
|
||||||
|
reply = nam->deleteResource(request);
|
||||||
|
clientSpy.wait();
|
||||||
|
QVERIFY2(clientSpy.count() == 1, "expected exactly 1 response from webserver");
|
||||||
|
statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
|
||||||
|
QCOMPARE(statusCode, 200);
|
||||||
|
reply->deleteLater();
|
||||||
|
|
||||||
|
nam->deleteLater();
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestRestRules::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<int>("expectedStatusCode");
|
||||||
|
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() << 200 << "ActionEventRule1";
|
||||||
|
QTest::newRow("invalid rule. enabled, 1 Action (eventBased), 1 EventDescriptor, name") << true << invalidActionEventBased2 << QVariantMap() << validEventDescriptor3 << QVariantList() << QVariantMap() << 400 << "TestRule";
|
||||||
|
|
||||||
|
QTest::newRow("invalid rule. enabled, 1 Action (eventBased), types not matching, name") << true << invalidActionEventBased3 << QVariantMap() << validEventDescriptor1 << QVariantList() << QVariantMap() << 400 << "TestRule";
|
||||||
|
|
||||||
|
QTest::newRow("invalid rule. enabled, 1 Action (eventBased), 1 EventDescriptor, name") << true << invalidActionEventBased << QVariantMap() << validEventDescriptor2 << QVariantList() << QVariantMap() << 400 << "TestRule";
|
||||||
|
QTest::newRow("invalid rule. enabled, 1 Action (eventBased), 1 StateEvaluator, name") << true << validActionEventBased << QVariantMap() << QVariantMap() << QVariantList() << validStateEvaluator << 400 << "TestRule";
|
||||||
|
QTest::newRow("invalid rule. enabled, 1 Action (eventBased), 1 EventDescriptor, name") << true << validActionEventBased << validActionEventBased << validEventDescriptor2 << QVariantList() << QVariantMap() << 400 << "TestRule";
|
||||||
|
QTest::newRow("invalid rule. enabled, 1 Action, 1 ExitAction (EventBased), name") << true << validActionNoParams << validActionEventBased << validEventDescriptor2 << QVariantList() << QVariantMap() << 400 << "TestRule";
|
||||||
|
|
||||||
|
// Rules with exit actions
|
||||||
|
QTest::newRow("valid rule. enabled, 1 Action, 1 Exit Action, 1 StateEvaluator, name") << true << validActionNoParams << validExitActionNoParams << QVariantMap() << QVariantList() << validStateEvaluator << 200 << "TestRule";
|
||||||
|
QTest::newRow("valid rule. disabled, 1 Action, 1 Exit Action, 1 StateEvaluator, name") << false << validActionNoParams << validExitActionNoParams << QVariantMap() << QVariantList() << validStateEvaluator << 200 << "TestRule";
|
||||||
|
QTest::newRow("invalid rule. 1 Action, 1 Exit Action, 1 EventDescriptor, 1 StateEvaluator, name") << true << validActionNoParams << validExitActionNoParams << validEventDescriptor1 << QVariantList() << validStateEvaluator << 400 << "TestRule";
|
||||||
|
QTest::newRow("invalid rule. 1 Action, 1 Exit Action, eventDescriptorList, 1 StateEvaluator, name") << true << validActionNoParams << validExitActionNoParams << QVariantMap() << eventDescriptorList << validStateEvaluator << 400 << "TestRule";
|
||||||
|
|
||||||
|
// Rules without exit actions
|
||||||
|
QTest::newRow("valid rule. enabled, 1 EventDescriptor, StateEvaluator, 1 Action, name") << true << validActionNoParams << QVariantMap() << validEventDescriptor1 << QVariantList() << validStateEvaluator << 200 << "TestRule";
|
||||||
|
QTest::newRow("valid rule. diabled, 1 EventDescriptor, StateEvaluator, 1 Action, name") << false << validActionNoParams << QVariantMap() << validEventDescriptor1 << QVariantList() << validStateEvaluator << 200 << "TestRule";
|
||||||
|
QTest::newRow("valid rule. 2 EventDescriptors, 1 Action, name") << true << validActionNoParams << QVariantMap() << QVariantMap() << eventDescriptorList << validStateEvaluator << 200 << "TestRule";
|
||||||
|
QTest::newRow("invalid rule: eventDescriptor and eventDescriptorList used") << true << validActionNoParams << QVariantMap() << validEventDescriptor1 << eventDescriptorList << validStateEvaluator << 400 << "TestRule";
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestRestRules::editRules()
|
||||||
|
{
|
||||||
|
QFETCH(bool, enabled);
|
||||||
|
QFETCH(QVariantMap, action);
|
||||||
|
QFETCH(QVariantMap, exitAction);
|
||||||
|
QFETCH(QVariantMap, eventDescriptor);
|
||||||
|
QFETCH(QVariantList, eventDescriptorList);
|
||||||
|
QFETCH(QVariantMap, stateEvaluator);
|
||||||
|
QFETCH(int, expectedStatusCode);
|
||||||
|
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");
|
||||||
|
|
||||||
|
|
||||||
|
QNetworkAccessManager *nam = new QNetworkAccessManager(this);
|
||||||
|
QSignalSpy clientSpy(nam, SIGNAL(finished(QNetworkReply*)));
|
||||||
|
|
||||||
|
// Get rules and verify there is no rule added
|
||||||
|
QNetworkRequest request;
|
||||||
|
request.setUrl(QUrl("http://localhost:3000/api/v1/rules"));
|
||||||
|
QNetworkReply *reply = nam->get(request);
|
||||||
|
clientSpy.wait();
|
||||||
|
QVERIFY2(clientSpy.count() == 1, "expected exactly 1 response from webserver");
|
||||||
|
int statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
|
||||||
|
QCOMPARE(statusCode, 200);
|
||||||
|
QByteArray data = reply->readAll();
|
||||||
|
reply->deleteLater();
|
||||||
|
|
||||||
|
QJsonParseError error;
|
||||||
|
QJsonDocument jsonDoc = QJsonDocument::fromJson(data, &error);
|
||||||
|
QCOMPARE(error.error, QJsonParseError::NoError);
|
||||||
|
QVariantList rulesList = jsonDoc.toVariant().toList();
|
||||||
|
QVERIFY2(rulesList.count() == 0, "there should be no rules.");
|
||||||
|
|
||||||
|
// ADD rule
|
||||||
|
clientSpy.clear();
|
||||||
|
request = QNetworkRequest(QUrl(QString("http://localhost:3000/api/v1/rules")));
|
||||||
|
request.setHeader(QNetworkRequest::ContentTypeHeader, "text/json");
|
||||||
|
reply = nam->post(request, QJsonDocument::fromVariant(params).toJson(QJsonDocument::Compact));
|
||||||
|
clientSpy.wait();
|
||||||
|
QVERIFY2(clientSpy.count() == 1, "expected exactly 1 response from webserver");
|
||||||
|
statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
|
||||||
|
QCOMPARE(statusCode, 200);
|
||||||
|
|
||||||
|
jsonDoc = QJsonDocument::fromJson(reply->readAll(), &error);
|
||||||
|
QCOMPARE(error.error, QJsonParseError::NoError);
|
||||||
|
reply->deleteLater();
|
||||||
|
|
||||||
|
RuleId ruleId = RuleId(jsonDoc.toVariant().toMap().value("ruleId").toString());
|
||||||
|
QVERIFY(!ruleId.isNull());
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
// EDIT rule
|
||||||
|
clientSpy.clear();
|
||||||
|
request = QNetworkRequest(QUrl(QString("http://localhost:3000/api/v1/rules/%1").arg(ruleId.toString())));
|
||||||
|
request.setHeader(QNetworkRequest::ContentTypeHeader, "text/json");
|
||||||
|
reply = nam->put(request, QJsonDocument::fromVariant(params).toJson(QJsonDocument::Compact));
|
||||||
|
clientSpy.wait();
|
||||||
|
QVERIFY2(clientSpy.count() == 1, "expected exactly 1 response from webserver");
|
||||||
|
statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
|
||||||
|
QCOMPARE(statusCode, expectedStatusCode);
|
||||||
|
|
||||||
|
if (expectedStatusCode == 200) {
|
||||||
|
// get edit rule and verify params
|
||||||
|
clientSpy.clear();
|
||||||
|
request = QNetworkRequest(QUrl(QString("http://localhost:3000/api/v1/rules")));
|
||||||
|
request.setHeader(QNetworkRequest::ContentTypeHeader, "text/json");
|
||||||
|
reply = nam->get(request);
|
||||||
|
clientSpy.wait();
|
||||||
|
QVERIFY2(clientSpy.count() == 1, "expected exactly 1 response from webserver");
|
||||||
|
statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
|
||||||
|
QCOMPARE(statusCode, 200);
|
||||||
|
jsonDoc = QJsonDocument::fromJson(reply->readAll(), &error);
|
||||||
|
QCOMPARE(error.error, QJsonParseError::NoError);
|
||||||
|
reply->deleteLater();
|
||||||
|
}
|
||||||
|
|
||||||
|
// REMOVE rule
|
||||||
|
clientSpy.clear();
|
||||||
|
request = QNetworkRequest(QUrl(QString("http://localhost:3000/api/v1/rules/%1").arg(ruleId.toString())));
|
||||||
|
request.setHeader(QNetworkRequest::ContentTypeHeader, "text/json");
|
||||||
|
reply = nam->deleteResource(request);
|
||||||
|
clientSpy.wait();
|
||||||
|
QVERIFY2(clientSpy.count() == 1, "expected exactly 1 response from webserver");
|
||||||
|
statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
|
||||||
|
QCOMPARE(statusCode, 200);
|
||||||
|
reply->deleteLater();
|
||||||
|
|
||||||
|
|
||||||
|
// check if removed
|
||||||
|
clientSpy.clear();
|
||||||
|
request = QNetworkRequest(QUrl(QString("http://localhost:3000/api/v1/rules/%1").arg(ruleId.toString())));
|
||||||
|
request.setHeader(QNetworkRequest::ContentTypeHeader, "text/json");
|
||||||
|
reply = nam->get(request);
|
||||||
|
clientSpy.wait();
|
||||||
|
QVERIFY2(clientSpy.count() == 1, "expected exactly 1 response from webserver");
|
||||||
|
statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
|
||||||
|
QCOMPARE(statusCode, 404);
|
||||||
|
reply->deleteLater();
|
||||||
|
|
||||||
|
nam->deleteLater();
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestRestRules::enableDisableRule()
|
||||||
|
{
|
||||||
|
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);
|
||||||
|
|
||||||
|
QNetworkAccessManager *nam = new QNetworkAccessManager(this);
|
||||||
|
QSignalSpy clientSpy(nam, SIGNAL(finished(QNetworkReply*)));
|
||||||
|
|
||||||
|
// ADD rule
|
||||||
|
QNetworkRequest request = QNetworkRequest(QUrl(QString("http://localhost:3000/api/v1/rules")));
|
||||||
|
request.setHeader(QNetworkRequest::ContentTypeHeader, "text/json");
|
||||||
|
QNetworkReply *reply = nam->post(request, QJsonDocument::fromVariant(addRuleParams).toJson(QJsonDocument::Compact));
|
||||||
|
clientSpy.wait();
|
||||||
|
QVERIFY2(clientSpy.count() == 1, "expected exactly 1 response from webserver");
|
||||||
|
int statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
|
||||||
|
QCOMPARE(statusCode, 200);
|
||||||
|
QByteArray data = reply->readAll();
|
||||||
|
reply->deleteLater();
|
||||||
|
|
||||||
|
QJsonParseError error;
|
||||||
|
QJsonDocument jsonDoc = QJsonDocument::fromJson(data, &error);
|
||||||
|
QCOMPARE(error.error, QJsonParseError::NoError);
|
||||||
|
|
||||||
|
RuleId ruleId = RuleId(jsonDoc.toVariant().toMap().value("ruleId").toString());
|
||||||
|
QVERIFY(!ruleId.isNull());
|
||||||
|
|
||||||
|
// ENABLE rule
|
||||||
|
clientSpy.clear();
|
||||||
|
request = QNetworkRequest(QUrl(QString("http://localhost:3000/api/v1/rules/%1/enable").arg(ruleId.toString())));
|
||||||
|
reply = nam->post(request, QByteArray());
|
||||||
|
clientSpy.wait();
|
||||||
|
QVERIFY2(clientSpy.count() == 1, "expected exactly 1 response from webserver");
|
||||||
|
statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
|
||||||
|
QCOMPARE(statusCode, 200);
|
||||||
|
reply->deleteLater();
|
||||||
|
|
||||||
|
// Trigger an event
|
||||||
|
|
||||||
|
// trigger event in mock device
|
||||||
|
clientSpy.clear();
|
||||||
|
request = QNetworkRequest(QUrl(QString("http://localhost:%1/generateevent?eventtypeid=%2").arg(m_mockDevice1Port).arg(mockEvent1Id.toString())));
|
||||||
|
reply = nam->get(request);
|
||||||
|
clientSpy.wait();
|
||||||
|
QCOMPARE(clientSpy.count(), 1);
|
||||||
|
reply->deleteLater();
|
||||||
|
|
||||||
|
verifyRuleExecuted(mockActionIdNoParams);
|
||||||
|
|
||||||
|
cleanupMockHistory();
|
||||||
|
|
||||||
|
// DISABLE the rule
|
||||||
|
clientSpy.clear();
|
||||||
|
request = QNetworkRequest(QUrl(QString("http://localhost:3000/api/v1/rules/%1/disable").arg(ruleId.toString())));
|
||||||
|
reply = nam->post(request, QByteArray());
|
||||||
|
clientSpy.wait();
|
||||||
|
QVERIFY2(clientSpy.count() == 1, "expected exactly 1 response from webserver");
|
||||||
|
statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
|
||||||
|
QCOMPARE(statusCode, 200);
|
||||||
|
reply->deleteLater();
|
||||||
|
|
||||||
|
|
||||||
|
// trigger event in mock device
|
||||||
|
clientSpy.clear();
|
||||||
|
request = QNetworkRequest(QUrl(QString("http://localhost:%1/generateevent?eventtypeid=%2").arg(m_mockDevice1Port).arg(mockEvent1Id.toString())));
|
||||||
|
reply = nam->get(request);
|
||||||
|
clientSpy.wait();
|
||||||
|
QCOMPARE(clientSpy.count(), 1);
|
||||||
|
reply->deleteLater();
|
||||||
|
|
||||||
|
verifyRuleNotExecuted();
|
||||||
|
|
||||||
|
cleanupMockHistory();
|
||||||
|
|
||||||
|
// ENABLE again
|
||||||
|
clientSpy.clear();
|
||||||
|
request = QNetworkRequest(QUrl(QString("http://localhost:3000/api/v1/rules/%1/enable").arg(ruleId.toString())));
|
||||||
|
reply = nam->post(request, QByteArray());
|
||||||
|
clientSpy.wait();
|
||||||
|
QVERIFY2(clientSpy.count() == 1, "expected exactly 1 response from webserver");
|
||||||
|
statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
|
||||||
|
QCOMPARE(statusCode, 200);
|
||||||
|
reply->deleteLater();
|
||||||
|
|
||||||
|
// trigger event in mock device
|
||||||
|
clientSpy.clear();
|
||||||
|
request = QNetworkRequest(QUrl(QString("http://localhost:%1/generateevent?eventtypeid=%2").arg(m_mockDevice1Port).arg(mockEvent1Id.toString())));
|
||||||
|
reply = nam->get(request);
|
||||||
|
clientSpy.wait();
|
||||||
|
QCOMPARE(clientSpy.count(), 1);
|
||||||
|
reply->deleteLater();
|
||||||
|
|
||||||
|
verifyRuleExecuted(mockActionIdNoParams);
|
||||||
|
|
||||||
|
cleanupRules();
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestRestRules::getRules()
|
||||||
|
{
|
||||||
|
QNetworkAccessManager *nam = new QNetworkAccessManager(this);
|
||||||
|
QSignalSpy clientSpy(nam, SIGNAL(finished(QNetworkReply*)));
|
||||||
|
|
||||||
|
// Get all rules
|
||||||
|
QNetworkRequest request;
|
||||||
|
request.setUrl(QUrl("http://localhost:3000/api/v1/rules"));
|
||||||
|
QNetworkReply *reply = nam->get(request);
|
||||||
|
clientSpy.wait();
|
||||||
|
QVERIFY2(clientSpy.count() == 1, "expected exactly 1 response from webserver");
|
||||||
|
int statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
|
||||||
|
QCOMPARE(statusCode, 200);
|
||||||
|
QByteArray data = reply->readAll();
|
||||||
|
reply->deleteLater();
|
||||||
|
|
||||||
|
QJsonParseError error;
|
||||||
|
QJsonDocument jsonDoc = QJsonDocument::fromJson(data, &error);
|
||||||
|
QCOMPARE(error.error, QJsonParseError::NoError);
|
||||||
|
QVariantList rulesList = jsonDoc.toVariant().toList();
|
||||||
|
QVERIFY2(rulesList.count() == 0, "there should be at least one vendor.");
|
||||||
|
|
||||||
|
// Get each of thouse rules individualy
|
||||||
|
foreach (const QVariant &rule, rulesList) {
|
||||||
|
QVariantMap ruleMap = rule.toMap();
|
||||||
|
QNetworkRequest request(QUrl(QString("http://localhost:3000/api/v1/rules/%1").arg(ruleMap.value("id").toString())));
|
||||||
|
request.setHeader(QNetworkRequest::ContentTypeHeader, "text/json");
|
||||||
|
clientSpy.clear();
|
||||||
|
QNetworkReply *reply = nam->get(request);
|
||||||
|
clientSpy.wait();
|
||||||
|
QVERIFY2(clientSpy.count() == 1, "expected exactly 1 response from webserver");
|
||||||
|
int statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
|
||||||
|
QCOMPARE(statusCode, 200);
|
||||||
|
jsonDoc = QJsonDocument::fromJson(reply->readAll(), &error);
|
||||||
|
QCOMPARE(error.error, QJsonParseError::NoError);
|
||||||
|
reply->deleteLater();
|
||||||
|
|
||||||
|
}
|
||||||
|
nam->deleteLater();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#include "testrestrules.moc"
|
||||||
|
QTEST_MAIN(TestRestRules)
|
||||||
Reference in New Issue
Block a user