mirror of https://github.com/nymea/nymea.git
add rule tests and rest resource
parent
1330ed31a3
commit
1f6cfd4527
|
|
@ -1,11 +1,13 @@
|
|||
[JSONRPC]
|
||||
port=12345
|
||||
port=1234
|
||||
interfaces="lo","all"
|
||||
ip="IPv4", "IPv6"
|
||||
|
||||
[Webserver]
|
||||
port=3001
|
||||
port=3000
|
||||
publicFolder=/usr/share/guh-webinterface/
|
||||
https=false
|
||||
|
||||
|
||||
[GPIO]
|
||||
rf433rx=27
|
||||
|
|
|
|||
3
guh.pri
3
guh.pri
|
|
@ -28,9 +28,8 @@ enable433gpio {
|
|||
|
||||
# check webserver support
|
||||
equals(QT_MAJOR_VERSION, 5):greaterThan(QT_MINOR_VERSION, 3) {
|
||||
DEFINES += WEBSERVER
|
||||
DEFINES += WEBSOCKET
|
||||
}
|
||||
|
||||
|
||||
top_srcdir=$$PWD
|
||||
top_builddir=$$shadowed($$PWD)
|
||||
|
|
|
|||
6
guh.pro
6
guh.pro
|
|
@ -34,10 +34,10 @@ coverage {
|
|||
message("Building coverage.")
|
||||
}
|
||||
|
||||
contains(DEFINES, WEBSERVER){
|
||||
message("Building guh with webserver.")
|
||||
contains(DEFINES, WEBSOCKET){
|
||||
message("Building guh with websocket.")
|
||||
} else {
|
||||
message("Building guh without webserver.")
|
||||
message("Building guh without websocket.")
|
||||
}
|
||||
|
||||
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()));
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
QStringList enumStrings;
|
||||
|
|
|
|||
|
|
@ -197,6 +197,15 @@ public:
|
|||
static QPair<bool, QString> validateEnum(const QVariantList &enumList, const QVariant &value);
|
||||
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:
|
||||
static bool s_initialized;
|
||||
static void init();
|
||||
|
|
|
|||
|
|
@ -175,7 +175,7 @@ JsonReply *RulesHandler::GetRuleDetails(const QVariantMap ¶ms)
|
|||
JsonReply* RulesHandler::AddRule(const QVariantMap ¶ms)
|
||||
{
|
||||
// check rule consistency
|
||||
RuleEngine::RuleError ruleConsistencyError = verifyRuleConsistency(params);
|
||||
RuleEngine::RuleError ruleConsistencyError = JsonTypes::verifyRuleConsistency(params);
|
||||
if (ruleConsistencyError != RuleEngine::RuleErrorNoError) {
|
||||
QVariantMap returns;
|
||||
returns.insert("ruleError", JsonTypes::ruleErrorToString(ruleConsistencyError));
|
||||
|
|
@ -183,7 +183,7 @@ JsonReply* RulesHandler::AddRule(const QVariantMap ¶ms)
|
|||
}
|
||||
|
||||
// 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;
|
||||
if (eventDescriptorVerification.second != RuleEngine::RuleErrorNoError) {
|
||||
QVariantMap returns;
|
||||
|
|
@ -191,13 +191,12 @@ JsonReply* RulesHandler::AddRule(const QVariantMap ¶ms)
|
|||
return createReply(returns);
|
||||
}
|
||||
|
||||
|
||||
// Check and unpack stateEvaluator
|
||||
qCDebug(dcJsonRpc) << "unpacking stateEvaluator:" << params.value("stateEvaluator").toMap();
|
||||
StateEvaluator stateEvaluator = JsonTypes::unpackStateEvaluator(params.value("stateEvaluator").toMap());
|
||||
|
||||
// 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;
|
||||
if (actionsVerification.second != RuleEngine::RuleErrorNoError) {
|
||||
QVariantMap returns;
|
||||
|
|
@ -206,7 +205,7 @@ JsonReply* RulesHandler::AddRule(const QVariantMap ¶ms)
|
|||
}
|
||||
|
||||
// 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;
|
||||
if (exitActionsVerification.second != RuleEngine::RuleErrorNoError) {
|
||||
QVariantMap returns;
|
||||
|
|
@ -230,7 +229,7 @@ JsonReply* RulesHandler::AddRule(const QVariantMap ¶ms)
|
|||
JsonReply *RulesHandler::EditRule(const QVariantMap ¶ms)
|
||||
{
|
||||
// check rule consistency
|
||||
RuleEngine::RuleError ruleConsistencyError = verifyRuleConsistency(params);
|
||||
RuleEngine::RuleError ruleConsistencyError = JsonTypes::verifyRuleConsistency(params);
|
||||
if (ruleConsistencyError != RuleEngine::RuleErrorNoError) {
|
||||
QVariantMap returns;
|
||||
returns.insert("ruleError", JsonTypes::ruleErrorToString(ruleConsistencyError));
|
||||
|
|
@ -238,7 +237,7 @@ JsonReply *RulesHandler::EditRule(const QVariantMap ¶ms)
|
|||
}
|
||||
|
||||
// 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;
|
||||
if (eventDescriptorVerification.second != RuleEngine::RuleErrorNoError) {
|
||||
QVariantMap returns;
|
||||
|
|
@ -251,7 +250,7 @@ JsonReply *RulesHandler::EditRule(const QVariantMap ¶ms)
|
|||
StateEvaluator stateEvaluator = JsonTypes::unpackStateEvaluator(params.value("stateEvaluator").toMap());
|
||||
|
||||
// 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;
|
||||
if (actionsVerification.second != RuleEngine::RuleErrorNoError) {
|
||||
QVariantMap returns;
|
||||
|
|
@ -260,7 +259,7 @@ JsonReply *RulesHandler::EditRule(const QVariantMap ¶ms)
|
|||
}
|
||||
|
||||
// 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;
|
||||
if (exitActionsVerification.second != RuleEngine::RuleErrorNoError) {
|
||||
QVariantMap returns;
|
||||
|
|
@ -315,168 +314,6 @@ JsonReply *RulesHandler::DisableRule(const QVariantMap ¶ms)
|
|||
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)
|
||||
{
|
||||
QVariantMap params;
|
||||
|
|
|
|||
|
|
@ -51,17 +51,6 @@ signals:
|
|||
void RuleActiveChanged(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:
|
||||
void ruleRemovedNotification(const RuleId &ruleId);
|
||||
void ruleAddedNotification(const Rule &rule);
|
||||
|
|
|
|||
|
|
@ -45,7 +45,6 @@ HttpReply *DevicesResource::proccessRequest(const HttpRequest &request, const QS
|
|||
{
|
||||
m_device = 0;
|
||||
|
||||
|
||||
// get the main resource
|
||||
if (urlTokens.count() >= 4) {
|
||||
DeviceId deviceId = DeviceId(urlTokens.at(3));
|
||||
|
|
|
|||
|
|
@ -62,6 +62,9 @@ HttpReply *RulesResource::proccessRequest(const HttpRequest &request, const QStr
|
|||
case HttpRequest::Put:
|
||||
reply = proccessPutRequest(request, urlTokens);
|
||||
break;
|
||||
case HttpRequest::Post:
|
||||
reply = proccessPostRequest(request, urlTokens);
|
||||
break;
|
||||
case HttpRequest::Delete:
|
||||
reply = proccessDeleteRequest(request, urlTokens);
|
||||
break;
|
||||
|
|
@ -129,6 +132,14 @@ HttpReply *RulesResource::proccessPostRequest(const HttpRequest &request, const
|
|||
if (urlTokens.count() == 3)
|
||||
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);
|
||||
}
|
||||
|
||||
|
|
@ -179,19 +190,130 @@ HttpReply *RulesResource::removeRule(const RuleId &ruleId) const
|
|||
|
||||
HttpReply *RulesResource::addRule(const QByteArray &payload) const
|
||||
{
|
||||
Q_UNUSED(payload)
|
||||
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
|
||||
{
|
||||
Q_UNUSED(payload)
|
||||
qCDebug(dcRest) << "Edit rule with id" << ruleId;
|
||||
qCDebug(dcRest) << "Edit rule with id" << ruleId.toString();
|
||||
|
||||
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
|
||||
HttpReply *addRule(const QByteArray &payload) const;
|
||||
HttpReply *enableRule(const RuleId &ruleId) const;
|
||||
HttpReply *disableRule(const RuleId &ruleId) const;
|
||||
|
||||
// Put methods
|
||||
HttpReply *editRule(const RuleId &ruleId, const QByteArray &payload) const;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
|
||||
contains(DEFINES, WEBSERVER){
|
||||
contains(DEFINES, WEBSOCKET){
|
||||
QT += websockets
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
TEMPLATE=subdirs
|
||||
TEMPLATE = subdirs
|
||||
|
||||
SUBDIRS=versioning \
|
||||
SUBDIRS = versioning \
|
||||
devices \
|
||||
jsonrpc \
|
||||
events \
|
||||
|
|
@ -13,3 +13,4 @@ SUBDIRS=versioning \
|
|||
restdeviceclasses \
|
||||
restplugins \
|
||||
restvendors \
|
||||
restrules \
|
||||
|
|
|
|||
|
|
@ -248,6 +248,7 @@ void TestRestDeviceClasses::discoverDevices()
|
|||
QNetworkAccessManager *nam = new QNetworkAccessManager();
|
||||
QSignalSpy clientSpy(nam, SIGNAL(finished(QNetworkReply*)));
|
||||
|
||||
// DISCOVER
|
||||
QUrl url(QString("http://localhost:3000/api/v1/deviceclasses/%1/discover").arg(deviceClassId.toString()));
|
||||
|
||||
if (!discoveryParams.isEmpty()) {
|
||||
|
|
@ -275,7 +276,7 @@ void TestRestDeviceClasses::discoverDevices()
|
|||
QVariantList foundDevices = jsonDoc.toVariant().toList();
|
||||
QCOMPARE(foundDevices.count(), resultCount);
|
||||
|
||||
// add the discovered device
|
||||
// ADD the discovered device
|
||||
request.setUrl(QUrl("http://localhost:3000/api/v1/devices"));
|
||||
DeviceDescriptorId descriptorId = DeviceDescriptorId(foundDevices.first().toMap().value("id").toString());
|
||||
qDebug() << descriptorId;
|
||||
|
|
@ -294,7 +295,7 @@ void TestRestDeviceClasses::discoverDevices()
|
|||
reply->deleteLater();
|
||||
QCOMPARE(statusCode, expectedStatusCode);
|
||||
|
||||
// remove added device
|
||||
// REMOVE added device
|
||||
jsonDoc = QJsonDocument::fromJson(data, &error);
|
||||
QCOMPARE(error.error, QJsonParseError::NoError);
|
||||
QVariantMap response = jsonDoc.toVariant().toMap();
|
||||
|
|
|
|||
|
|
@ -0,0 +1,5 @@
|
|||
include(../../../guh.pri)
|
||||
include(../autotests.pri)
|
||||
|
||||
TARGET = restrules
|
||||
SOURCES += testrestrules.cpp
|
||||
|
|
@ -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)
|
||||
Loading…
Reference in New Issue