add missing docs

first working calendarItem
This commit is contained in:
Simon Stürz 2016-04-01 23:31:46 +02:00 committed by Michael Zanetti
parent 76cc3577e1
commit e5d9823c2b
11 changed files with 283 additions and 51 deletions

View File

@ -397,8 +397,7 @@ GuhCore::GuhCore(QObject *parent) :
connect(m_ruleEngine, &RuleEngine::ruleRemoved, this, &GuhCore::ruleRemoved);
connect(m_ruleEngine, &RuleEngine::ruleConfigurationChanged, this, &GuhCore::ruleConfigurationChanged);
connect(m_timeManager, &TimeManager::timeChanged, this, &GuhCore::onTimeChanged);
connect(m_timeManager, &TimeManager::dateChanged, this, &GuhCore::onDateChanged);
connect(m_timeManager, &TimeManager::dateTimeChanged, this, &GuhCore::onDateTimeChanged);
connect(m_timeManager, &TimeManager::tick, m_deviceManager, &DeviceManager::timeTick);
m_logger->logSystemEvent(true);
@ -462,14 +461,30 @@ void GuhCore::gotEvent(const Event &event)
executeRuleActions(actions);
}
void GuhCore::onTimeChanged(const QTime &currentTime)
void GuhCore::onDateTimeChanged(const QDateTime &dateTime)
{
qCDebug(dcTimeManager) << currentTime.toString("hh:mm");
}
qCDebug(dcTimeManager) << dateTime.toString("dd.MM.yyyy hh:mm");
void GuhCore::onDateChanged(const QDate &currentDate)
{
qCDebug(dcTimeManager) << currentDate.toString("dd.MM.yyyy");
QList<RuleAction> actions;
foreach (const Rule &rule, m_ruleEngine->evaluateTime(dateTime)) {
// TimeEvent based
if (!rule.timeDescriptor().timeEventItems().isEmpty()) {
m_logger->logRuleTriggered(rule);
foreach (const RuleAction &action, rule.actions()) {
actions.append(action);
}
} else {
// Calendar based rule
m_logger->logRuleActiveChanged(rule);
emit ruleActiveChanged(rule);
if (rule.active()) {
actions.append(rule.actions());
} else {
actions.append(rule.exitActions());
}
}
}
executeRuleActions(actions);
}
/*! Return the instance of the log engine */

View File

@ -103,8 +103,7 @@ private:
private slots:
void gotEvent(const Event &event);
void onTimeChanged(const QTime &currentTime);
void onDateChanged(const QDate &currentDate);
void onDateTimeChanged(const QDateTime &dateTime);
void actionExecutionFinished(const ActionId &id, DeviceManager::DeviceError status);
};

View File

@ -1067,6 +1067,7 @@ ParamList JsonTypes::unpackParams(const QVariantList &paramList)
return params;
}
/*! Returns a \l{Rule} created from the given \a ruleMap. */
Rule JsonTypes::unpackRule(const QVariantMap &ruleMap)
{
// The rule id will only be valid if unpacking for edit
@ -1121,6 +1122,7 @@ Rule JsonTypes::unpackRule(const QVariantMap &ruleMap)
return rule;
}
/*! Returns a \l{RuleAction} created from the given \a ruleActionMap. */
RuleAction JsonTypes::unpackRuleAction(const QVariantMap &ruleActionMap)
{
RuleAction action(ActionTypeId(ruleActionMap.value("actionTypeId").toString()), DeviceId(ruleActionMap.value("deviceId").toString()));

View File

@ -39,7 +39,7 @@
namespace guhserver {
/*! Constructs an empty, invalid rule. */
/*! Constructs an empty, invalid \l{Rule}. */
Rule::Rule():
m_id(RuleId()),
m_name(QString()),
@ -55,12 +55,13 @@ Rule::Rule():
}
/*! Returns the id of this Rule. */
/*! Returns the id of this \l{Rule}. */
RuleId Rule::id() const
{
return m_id;
}
/*! Sets the \a ruleId of this \l{Rule}. */
void Rule::setId(const RuleId &ruleId)
{
m_id = ruleId;
@ -72,6 +73,7 @@ QString Rule::name() const
return m_name;
}
/*! Sets the \a name of this \l{Rule}. */
void Rule::setName(const QString &name)
{
m_name = name;
@ -89,6 +91,7 @@ TimeDescriptor Rule::timeDescriptor() const
return m_timeDescriptor;
}
/*! Sets the \a timeDescriptor of this \l{Rule}. */
void Rule::setTimeDescriptor(const TimeDescriptor &timeDescriptor)
{
m_timeDescriptor = timeDescriptor;
@ -100,6 +103,7 @@ StateEvaluator Rule::stateEvaluator() const
return m_stateEvaluator;
}
/*! Sets the \a stateEvaluator of this \l{Rule}. */
void Rule::setStateEvaluator(const StateEvaluator &stateEvaluator)
{
m_stateEvaluator = stateEvaluator;
@ -111,6 +115,7 @@ QList<EventDescriptor> Rule::eventDescriptors() const
return m_eventDescriptors;
}
/*! Sets the \a eventDescriptors of this \l{Rule}. */
void Rule::setEventDescriptors(const QList<EventDescriptor> &eventDescriptors)
{
m_eventDescriptors = eventDescriptors;
@ -122,6 +127,7 @@ QList<RuleAction> Rule::actions() const
return m_actions;
}
/*! Sets the \a actions of this \l{Rule}. */
void Rule::setActions(const QList<RuleAction> actions)
{
m_actions = actions;
@ -133,6 +139,7 @@ QList<RuleAction> Rule::exitActions() const
return m_exitActions;
}
/*! Sets the \a exitActions of this \l{Rule}. */
void Rule::setExitActions(const QList<RuleAction> exitActions)
{
m_exitActions = exitActions;
@ -162,11 +169,13 @@ void Rule::setExecutable(const bool &executable)
m_executable = executable;
}
/*! Returns true if this \l{Rule} is valid. A \l{Rule} with a valid \l{id()} is valid. */
bool Rule::isValid() const
{
return !m_id.isNull();
}
/*! Returns true if this \l{Rule} is consistent. */
bool Rule::isConsistent() const
{
// check if this rules is based on any event and contains exit actions
@ -184,7 +193,6 @@ bool Rule::isConsistent() const
return true;
}
void Rule::setActive(const bool &active)
{
m_active = active;

View File

@ -74,6 +74,14 @@
The types of the \l{RuleActionParam} and the corresponding \l{Event} \l{Param} do not match.
\value RuleErrorNotExecutable
This rule is not executable.
\value RuleErrorInvalidRepeatingOption
One of the given \l{RepeatingOption}{RepeatingOption} is not valid.
\value RuleErrorInvalidCalendarItem
One of the given \l{CalendarItem}{CalendarItems} is not valid.
\value RuleErrorInvalidTimeDescriptor
One of the given \l{TimeDescriptor}{TimeDescriptors} is not valid.
\value RuleErrorInvalidTimeEventItem
One of the given \l{TimeEventItem}{TimeEventItems} is not valid.
\value RuleErrorContainsEventBasesAction
This rule contains an \l{Action} which depends on an \l{Event} value. This \l{Rule} cannot execute
the \l{Action}{Actions} without the \l{Event} value.
@ -238,7 +246,7 @@ QList<Rule> RuleEngine::evaluateEvent(const Event &event)
qCDebug(dcRuleEngine) << "got event:" << event << device->name() << event.eventTypeId();
QList<Rule> rules;
foreach (const RuleId &id, m_ruleIds) {
foreach (const RuleId &id, ruleIds()) {
Rule rule = m_rules.value(id);
if (!rule.enabled())
continue;
@ -278,14 +286,65 @@ QList<Rule> RuleEngine::evaluateEvent(const Event &event)
return rules;
}
/*! Ask the Engine to evaluate all the rules for the given \a dateTime.
This will search all the \l{Rule}{Rules} triggered by the given \a dateTime
and evaluate their \l{CalendarItem}{CalendarItems} and \l{TimeEventItem}{TimeEventItems}.
It will return a list of all \l{Rule}{Rules} that are triggered or change its active state.
*/
QList<Rule> RuleEngine::evaluateTime(const QDateTime &dateTime)
{
Q_UNUSED(dateTime)
QList<Rule> rules;
foreach (const Rule &r, m_rules.values()) {
Rule rule = m_rules.value(r.id());
if (!rule.enabled())
continue;
// check if this rule is time based
if (!rule.timeDescriptor().isEmpty()) {
// check if this rule is based on calendarItems
if (!rule.timeDescriptor().calendarItems().isEmpty()) {
qCDebug(dcRuleEngine()) << "Evaluate CalendarItem against" << dateTime.toString("dd:MM:yyyy hh:mm") << "for rule" << rule.id().toString();
bool active = rule.timeDescriptor().evaluate(dateTime);
if (active) {
if (m_activeRules.contains(rule.id())) {
qCDebug(dcRuleEngine) << "Rule" << rule.id().toString() << "still active.";
} else {
qCDebug(dcRuleEngine) << "Rule" << rule.id().toString() << "active.";
rule.setActive(true);
m_rules[rule.id()] = rule;
m_activeRules.append(rule.id());
rules.append(rule);
}
} else {
if (m_activeRules.contains(rule.id())) {
qCDebug(dcRuleEngine) << "Rule" << rule.id().toString() << "inactive.";
rule.setActive(false);
m_rules[rule.id()] = rule;
m_activeRules.removeAll(rule.id());
rules.append(rule);
}
}
}
// check if this rule is based on timeEventItems
if (!rule.timeDescriptor().timeEventItems().isEmpty()) {
bool valid = rule.timeDescriptor().evaluate(dateTime);
qCDebug(dcRuleEngine()) << "Result:" << (valid ? "valid" : "invalid");
if (valid) {
rules.append(rule);
}
}
}
}
return rules;
}
/*! Add the given \a rule to the system. If the rule will be added
from an edit request, the parameter \a fromEdit will be true.
*/
RuleEngine::RuleError RuleEngine::addRule(const Rule &rule, bool fromEdit)
{
if (rule.id().isNull())
@ -333,7 +392,7 @@ RuleEngine::RuleError RuleEngine::addRule(const Rule &rule, bool fromEdit)
// Check time descriptor
if (!rule.timeDescriptor().isEmpty()) {
if (rule.timeDescriptor().isValid()) {
if (!rule.timeDescriptor().isValid()) {
qCDebug(dcRuleEngine()) << "Cannot create rule. Got invalid timeDescriptor.";
return RuleErrorInvalidTimeDescriptor;
}
@ -484,6 +543,9 @@ RuleEngine::RuleError RuleEngine::addRule(const Rule &rule, bool fromEdit)
return RuleErrorNoError;
}
/*! Edit the given \a rule in the system. The rule with the \l{RuleId} from the given \a rule
will be removed from the system and readded with the new parameters in the given \a rule.
*/
RuleEngine::RuleError RuleEngine::editRule(const Rule &rule)
{
if (rule.id().isNull())

View File

@ -29,6 +29,7 @@
*/
#include "calendaritem.h"
#include "loggingcategories.h"
namespace guhserver {
@ -102,19 +103,16 @@ bool CalendarItem::isValid() const
/*! Returns true, if the given \a dateTime matches this \l{CalendarItem}. */
bool CalendarItem::evaluate(const QDateTime &dateTime) const
{
qCDebug(dcRuleEngine()) << "Evaluate CalendarItem";
if (!isValid())
return false;
if (!repeatingOption().isValid())
return false;
if (m_dateTime.isValid() && !repeatingOption().isEmtpy())
return false;
// Only check repeating option mode if this is not a timedate calendarItem,
// which can only be valid once and is not repeatable.
if (!m_dateTime.isValid()) {
switch (repeatingOption().mode()) {
if (m_startTime.isValid()) {
switch (m_repeatingOption.mode()) {
case RepeatingOption::RepeatingModeNone:
// If there is no repeating option, we assume it is meant daily.
return evaluateDaily(dateTime);
@ -137,9 +135,20 @@ bool CalendarItem::evaluate(const QDateTime &dateTime) const
bool CalendarItem::evaluateHourly(const QDateTime &dateTime) const
{
qCDebug(dcRuleEngine()) << "Evaluate CalendarItem Hourly";
// If the duration is longer than a hour, this calendar item is always true
// 1 hour has 60 minutes
if (duration() >= 60)
return true;
QDateTime startDateTime = QDateTime(dateTime.date(), QTime(dateTime.time().hour(), startTime().minute()));
QDateTime endDateTime = startDateTime.addSecs(duration() * 60);
qCDebug(dcRuleEngine()) << "current time" << dateTime.toString("hh:mm");
qCDebug(dcRuleEngine()) << "startTime" << startDateTime.toString("hh:mm");
qCDebug(dcRuleEngine()) << "endTime" << endDateTime.toString("hh:mm");
bool timeValid = dateTime >= startDateTime && dateTime < endDateTime;
bool weekdayValid = repeatingOption().evaluateWeekDay(dateTime);
bool monthdayValid = repeatingOption().evaluateMonthDay(dateTime);
@ -149,6 +158,8 @@ bool CalendarItem::evaluateHourly(const QDateTime &dateTime) const
bool CalendarItem::evaluateDaily(const QDateTime &dateTime) const
{
qCDebug(dcRuleEngine()) << "Evaluate CalendarItem Hourly";
// If the duration is longer than a day, this calendar item is always true
// 1 day has 1440 minutes
if (duration() >= 1440)

View File

@ -69,7 +69,7 @@ void TimeDescriptor::setCalendarItems(const QList<CalendarItem> &calendarItems)
/*! Returns true if either the calendarItems list is not empty or the timeEventItems list.*/
bool TimeDescriptor::isValid() const
{
return !m_timeEventItems.isEmpty() && !m_calendarItems.isEmpty();
return !m_timeEventItems.isEmpty() != !m_calendarItems.isEmpty();
}
/*! Returns true if the calendarItems list and the timeEventItems list is empty.*/
@ -84,7 +84,23 @@ bool TimeDescriptor::isEmpty() const
*/
bool TimeDescriptor::evaluate(const QDateTime &dateTime) const
{
Q_UNUSED(dateTime)
// If there are calendarItems (always OR connected)
if (!m_calendarItems.isEmpty()) {
foreach (const CalendarItem &calendarItem, m_calendarItems) {
if (calendarItem.evaluate(dateTime)) {
return true;
}
}
}
// If there are timeEventItems (always OR connected)
if (!m_timeEventItems.isEmpty()) {
foreach (const TimeEventItem &timeEventItem, m_timeEventItems) {
if (timeEventItem.evaluate(dateTime)) {
return true;
}
}
}
return false;
}

View File

@ -30,12 +30,8 @@
Represents the central time tick. Will be emitted every second.
*/
/*! \fn void guhserver::TimeManager::dateChanged(const QDate &currentDate);
Will be emitted when the \a currentDate has changed.
*/
/*! \fn void guhserver::TimeManager::timeChanged(const QTime &currentTime);
Will be emitted when the \a currentTime has changed.
/*! \fn void guhserver::TimeManager::dateTimeChanged(const QDateTime &dateTime);
Will be emitted when the \a dateTime has changed.
*/
#include "timemanager.h"
@ -106,6 +102,13 @@ void TimeManager::stopTimer()
// Stop clock (used for testing)
m_guhTimer->stop();
}
void TimeManager::setTime(const QDateTime &dateTime)
{
// This method will only be called for testing
emit tick();
emit dateTimeChanged(dateTime.toTimeZone(m_timeZone));
}
#endif
void TimeManager::guhTimeout()
@ -113,17 +116,11 @@ void TimeManager::guhTimeout()
// tick for deviceManager
emit tick();
QDateTime currentDateTime = QDateTime::currentDateTimeUtc();
// Minute based guh time
QDateTime currentDateTime = QDateTime::currentDateTimeUtc();
if (m_dateTime.time().minute() != currentDateTime.toTimeZone(m_timeZone).time().minute()) {
m_dateTime = currentDateTime;
emit timeChanged(m_dateTime.toTimeZone(m_timeZone).time());
}
// check if day changed
if (m_dateTime.date() != currentDateTime.toTimeZone(m_timeZone).date()) {
emit dateChanged(m_dateTime.toTimeZone(m_timeZone).date());
emit dateTimeChanged(m_dateTime.toTimeZone(m_timeZone));
}
}

View File

@ -43,6 +43,7 @@ public:
#ifdef TESTING_ENABLED
void stopTimer();
void setTime(const QDateTime &dateTime);
#endif
private:
@ -52,8 +53,7 @@ private:
signals:
void tick();
void dateChanged(const QDate &currentDate);
void timeChanged(const QTime &currentTime);
void dateTimeChanged(const QDateTime &dateTime);
private slots:
void guhTimeout();

View File

@ -141,7 +141,6 @@ void TestRules::verifyRuleExecuted(const ActionTypeId &actionTypeId)
qDebug() << "have action history" << actionHistory;
QVERIFY2(actionTypeId == ActionTypeId(actionHistory), "Action not triggered");
reply->deleteLater();
}
void TestRules::verifyRuleNotExecuted()
@ -157,7 +156,6 @@ void TestRules::verifyRuleNotExecuted()
qDebug() << "have action history" << actionHistory;
QVERIFY2(actionHistory.isEmpty(), "Action is triggered while it should not have been.");
reply->deleteLater();
}

View File

@ -25,10 +25,13 @@
#include "devicemanager.h"
#include "mocktcpserver.h"
#include <QTimeZone>
#include <QDateTime>
#include <QtTest/QtTest>
#include <QCoreApplication>
#include <QNetworkAccessManager>
#include <QNetworkRequest>
#include <QNetworkReply>
#include <QTimeZone>
#include <QDateTime>
using namespace guhserver;
@ -43,7 +46,14 @@ private slots:
void addTimeDescriptor_data();
void addTimeDescriptor();
void testCalendarItemHourly();
private:
void verifyRuleExecuted(const ActionTypeId &actionTypeId);
void verifyRuleNotExecuted();
void cleanupMockHistory();
QVariantMap createTimeEventItem(const QString &time = QString(), const QVariantMap &repeatingOption = QVariantMap()) const;
QVariantMap createTimeEventItem(const int &dateTime, const QVariantMap &repeatingOption = QVariantMap()) const;
QVariantMap createTimeDescriptorTimeEvent(const QVariantMap &timeEventItem) const;
@ -53,7 +63,6 @@ private:
QVariantMap createCalendarItem(const int &dateTime, const uint &duration = 0, const QVariantMap &repeatingOption = QVariantMap()) const;
QVariantMap createTimeDescriptorCalendar(const QVariantMap &calendarItem) const;
QVariantMap createTimeDescriptorCalendar(const QVariantList &calendarItems) const;
};
void TestTimeManager::changeTimeZone_data()
@ -114,6 +123,10 @@ void TestTimeManager::addTimeDescriptor_data()
repeatingOptionMonthlyMultiple.insert("monthDays", QVariantList() << 20 << 14 << 5);
// invalid RepeatingOptions
QVariantMap repeatingOptionInvalidNone;
repeatingOptionInvalidNone.insert("mode", "RepeatingModeNone");
repeatingOptionInvalidNone.insert("monthDays", QVariantList() << 13 << 12 << 27);
QVariantMap repeatingOptionInvalidWeekly;
repeatingOptionInvalidWeekly.insert("mode", "RepeatingModeWeekly");
repeatingOptionInvalidWeekly.insert("monthDays", QVariantList() << 12 << 2 << 7);
@ -168,6 +181,7 @@ void TestTimeManager::addTimeDescriptor_data()
QTest::newRow("valid: timeEventItem - monthly - multiple days") << createTimeDescriptorTimeEvent(createTimeEventItem("23:00", repeatingOptionMonthlyMultiple)) << RuleEngine::RuleErrorNoError;
QTest::newRow("invalid: calendarItem empty") << createTimeDescriptorCalendar(createCalendarItem()) << RuleEngine::RuleErrorInvalidCalendarItem;
QTest::newRow("invalid: calendarItem none") << createTimeDescriptorCalendar(createCalendarItem("00:12", 12, repeatingOptionInvalidNone)) << RuleEngine::RuleErrorInvalidRepeatingOption;
QTest::newRow("invalid: calendarItem - dateTime + repeatingOption") << createTimeDescriptorCalendar(createCalendarItem(QDateTime::currentDateTime().toTime_t(), 5, repeatingOptionDaily)) << RuleEngine::RuleErrorInvalidCalendarItem;
QTest::newRow("invalid: calendarItem invalid time") << createTimeDescriptorCalendar(createCalendarItem("35:80", 5)) << RuleEngine::RuleErrorInvalidCalendarItem;
QTest::newRow("invalid: calendarItem invalid duration") << createTimeDescriptorCalendar(createCalendarItem("12:00", 0)) << RuleEngine::RuleErrorInvalidCalendarItem;
@ -179,6 +193,7 @@ void TestTimeManager::addTimeDescriptor_data()
QTest::newRow("invalid: calendarItem - invalid monthdays (to big)") << createTimeDescriptorCalendar(createCalendarItem("13:13", 5, repeatingOptionInvalidMonthDays2)) << RuleEngine::RuleErrorInvalidRepeatingOption;
QTest::newRow("invalid: timeEventItem empty") << createTimeDescriptorTimeEvent(createTimeEventItem()) << RuleEngine::RuleErrorInvalidTimeEventItem;
QTest::newRow("invalid: timeEventItem none") << createTimeDescriptorTimeEvent(createTimeEventItem("00:12", repeatingOptionInvalidNone)) << RuleEngine::RuleErrorInvalidRepeatingOption;
QTest::newRow("invalid: timeEventItem - dateTime + repeatingOption") << createTimeDescriptorTimeEvent(createTimeEventItem(QDateTime::currentDateTime().toTime_t(), repeatingOptionDaily)) << RuleEngine::RuleErrorInvalidTimeEventItem;
QTest::newRow("invalid: timeEventItem invalid time") << createTimeDescriptorTimeEvent(createTimeEventItem("35:80")) << RuleEngine::RuleErrorInvalidTimeEventItem;
QTest::newRow("invalid: timeEventItem - monthly - weekDays") << createTimeDescriptorTimeEvent(createTimeEventItem("13:13", repeatingOptionInvalidMonthly)) << RuleEngine::RuleErrorInvalidRepeatingOption;
@ -211,11 +226,120 @@ void TestTimeManager::addTimeDescriptor()
// Print rule
RuleId newRuleId = RuleId(response.toMap().value("params").toMap().value("ruleId").toString());
QVariantMap params;
params.insert("ruleId", newRuleId);
response = injectAndWait("Rules.GetRuleDetails", params);
QVariantMap rule = response.toMap().value("params").toMap().value("rule").toMap();
qDebug() << QJsonDocument::fromVariant(rule).toJson();
// REMOVE rule
QVariantMap removeParams;
removeParams.insert("ruleId", newRuleId);
response = injectAndWait("Rules.RemoveRule", removeParams);
verifyRuleError(response);
}
void TestTimeManager::testCalendarItemHourly()
{
GuhCore::instance()->timeManager()->stopTimer();
qDebug() << GuhCore::instance()->timeManager()->currentDate().toString();
qDebug() << GuhCore::instance()->timeManager()->currentTime().toString();
qDebug() << GuhCore::instance()->timeManager()->currentDateTime().toString();
QVariantMap ruleMap; QVariantMap action; QVariantMap exitAction; QVariantMap repeatingOptionHourly;
repeatingOptionHourly.insert("mode", "RepeatingModeHourly");
action.insert("actionTypeId", mockActionIdNoParams);
action.insert("deviceId", m_mockDeviceId);
action.insert("ruleActionParams", QVariantList());
exitAction.insert("actionTypeId", mockActionIdWithParams);
QVariantList actionParams;
QVariantMap param1;
param1.insert("name", "mockActionParam1");
param1.insert("value", 5);
actionParams.append(param1);
QVariantMap param2;
param2.insert("name", "mockActionParam2");
param2.insert("value", true);
actionParams.append(param2);
exitAction.insert("deviceId", m_mockDeviceId);
exitAction.insert("ruleActionParams", actionParams);
ruleMap.insert("name", "Time based hourly calendar rule");
ruleMap.insert("timeDescriptor", createTimeDescriptorCalendar(createCalendarItem("08:05", 5)));
ruleMap.insert("actions", QVariantList() << action);
ruleMap.insert("exitActions", QVariantList() << exitAction);
QVariant response = injectAndWait("Rules.AddRule", ruleMap);
verifyRuleError(response);
RuleId ruleId = RuleId(response.toMap().value("params").toMap().value("ruleId").toString());
QDateTime currentDateTime = GuhCore::instance()->timeManager()->currentDateTime();
// check the next 24 hours
QDateTime future = QDateTime(currentDateTime.date(), QTime(8, 4));
for (int i = 0; i < 24; i++) {
// inactive
GuhCore::instance()->timeManager()->setTime(future);
verifyRuleNotExecuted();
// active
GuhCore::instance()->timeManager()->setTime(QDateTime(currentDateTime.date(), QTime(future.time().hour(), 5)));
verifyRuleExecuted(mockActionIdNoParams);
cleanupMockHistory();
// active unchanged
GuhCore::instance()->timeManager()->setTime(QDateTime(currentDateTime.date(), QTime(future.time().hour(), 7)));
verifyRuleNotExecuted();
// inactive
GuhCore::instance()->timeManager()->setTime(QDateTime(currentDateTime.date(), QTime(future.time().hour(), 10)));
verifyRuleExecuted(mockActionIdWithParams);
cleanupMockHistory();
// inactive unchanged
GuhCore::instance()->timeManager()->setTime(QDateTime(currentDateTime.date(), QTime(future.time().hour(), 11)));
verifyRuleNotExecuted();
// One hour "Back to the future"
future = future.addSecs(60*60);
}
// REMOVE rule
QVariantMap removeParams;
removeParams.insert("ruleId", ruleId);
response = injectAndWait("Rules.RemoveRule", removeParams);
verifyRuleError(response);
}
void TestTimeManager::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(QString::number(m_mockDevice1Port))));
QNetworkReply *reply = nam.get(request);
spy.wait();
QCOMPARE(spy.count(), 1);
QByteArray actionHistory = reply->readAll();
qDebug() << "have action history" << actionHistory;
QVERIFY2(actionTypeId == ActionTypeId(actionHistory), "Action not triggered");
reply->deleteLater();
}
void TestTimeManager::verifyRuleNotExecuted()
{
QNetworkAccessManager nam;
QSignalSpy spy(&nam, SIGNAL(finished(QNetworkReply*)));
QNetworkRequest request(QUrl(QString("http://localhost:%1/actionhistory").arg(QString::number(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 TestTimeManager::cleanupMockHistory() {
QNetworkAccessManager nam;
QSignalSpy spy(&nam, SIGNAL(finished(QNetworkReply*)));
QNetworkRequest request(QUrl(QString("http://localhost:%1/clearactionhistory").arg(QString::number(m_mockDevice1Port))));
QNetworkReply *reply = nam.get(request);
spy.wait();
QCOMPARE(spy.count(), 1);
reply->deleteLater();
}
QVariantMap TestTimeManager::createTimeEventItem(const QString &time, const QVariantMap &repeatingOption) const