overlapping weekly calendar item

This commit is contained in:
Simon Stürz 2016-04-07 12:20:39 +02:00 committed by Michael Zanetti
parent 5237ba09c1
commit 6782ea1a77
5 changed files with 191 additions and 100 deletions

View File

@ -63,7 +63,6 @@ void HttpDaemon::incomingConnection(qintptr socket)
void HttpDaemon::actionExecuted(const ActionTypeId &actionTypeId) void HttpDaemon::actionExecuted(const ActionTypeId &actionTypeId)
{ {
qCDebug(dcMockDevice) << "Log actions executed" << actionTypeId.toString();
m_actionList.append(qMakePair<ActionTypeId, QDateTime>(actionTypeId, QDateTime::currentDateTime())); m_actionList.append(qMakePair<ActionTypeId, QDateTime>(actionTypeId, QDateTime::currentDateTime()));
} }
@ -119,8 +118,6 @@ void HttpDaemon::discardClient()
{ {
QTcpSocket* socket = (QTcpSocket*)sender(); QTcpSocket* socket = (QTcpSocket*)sender();
socket->deleteLater(); socket->deleteLater();
qCDebug(dcMockDevice) << "Connection closed";
} }
QString HttpDaemon::generateHeader() QString HttpDaemon::generateHeader()

View File

@ -19,10 +19,10 @@
* * * *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#include <QCoreApplication>
#include <QCommandLineParser>
#include <QLoggingCategory>
#include <QCommandLineOption> #include <QCommandLineOption>
#include <QCommandLineParser>
#include <QCoreApplication>
#include <QLoggingCategory>
#include <QMessageLogger> #include <QMessageLogger>
#include <QStringList> #include <QStringList>
#include <QTextStream> #include <QTextStream>
@ -112,10 +112,10 @@ int main(int argc, char *argv[])
s_loggingFilters.insert("Connection", true); s_loggingFilters.insert("Connection", true);
s_loggingFilters.insert("LogEngine", false); s_loggingFilters.insert("LogEngine", false);
s_loggingFilters.insert("TcpServer", false); s_loggingFilters.insert("TcpServer", false);
s_loggingFilters.insert("WebServer", true); s_loggingFilters.insert("WebServer", false);
s_loggingFilters.insert("WebSocketServer", true); s_loggingFilters.insert("WebSocketServer", false);
s_loggingFilters.insert("JsonRpc", true); s_loggingFilters.insert("JsonRpc", false);
s_loggingFilters.insert("Rest", true); s_loggingFilters.insert("Rest", false);
s_loggingFilters.insert("OAuth2", false); s_loggingFilters.insert("OAuth2", false);
s_loggingFilters.insert("TimeManager", false); s_loggingFilters.insert("TimeManager", false);

View File

@ -185,18 +185,21 @@ bool CalendarItem::evaluateWeekly(const QDateTime &dateTime) const
QDateTime startDateTime = weekStartDateTime.addDays(weekDay); QDateTime startDateTime = weekStartDateTime.addDays(weekDay);
QDateTime endDateTime = startDateTime.addSecs(duration() * 60); QDateTime endDateTime = startDateTime.addSecs(duration() * 60);
bool overlapping = false;
// Check if this calendar item overlaps a week // Check if this calendar item overlaps a week
if (startDateTime.date().weekNumber() != endDateTime.date().weekNumber()) bool overlapping = startDateTime.date().weekNumber() != endDateTime.date().weekNumber();
overlapping = true;
if (overlapping) { if (overlapping) {
// Jump one week into the past // Check if already matches for this week
QDateTime startPreviouseDateTime = startDateTime.addDays(-7); if (dateTime >= startDateTime && dateTime < endDateTime)
QDateTime endPreviouseDateTime = startPreviouseDateTime.addSecs(duration() * 60); // Return true if the current time is between start
// and end of this calendar item
return true;
if (dateTime >= startPreviouseDateTime && dateTime < endPreviouseDateTime) // Jump one week into the past
QDateTime startDateTimePreviouseWeek = startDateTime.addDays(-7);
QDateTime endDateTimePreviouseWeek = startDateTimePreviouseWeek.addSecs(duration() * 60);
if (dateTime >= startDateTimePreviouseWeek && dateTime < endDateTimePreviouseWeek)
// Return true if the current time is between start // Return true if the current time is between start
// and end of this calendar item from the previouse week // and end of this calendar item from the previouse week
return true; return true;

View File

@ -154,9 +154,9 @@ bool RepeatingOption::isValid() const
return !m_weekDays.isEmpty() && m_monthDays.isEmpty(); return !m_weekDays.isEmpty() && m_monthDays.isEmpty();
case RepeatingModeMonthly: case RepeatingModeMonthly:
return m_weekDays.isEmpty() && !m_monthDays.isEmpty(); return m_weekDays.isEmpty() && !m_monthDays.isEmpty();
default:
return false;
} }
return false;
} }
/*! Returns true if the week day of the given \a dateTime matches this \l{RepeatingOption}. */ /*! Returns true if the week day of the given \a dateTime matches this \l{RepeatingOption}. */

View File

@ -46,6 +46,7 @@ private slots:
void addTimeDescriptor_data(); void addTimeDescriptor_data();
void addTimeDescriptor(); void addTimeDescriptor();
void testCalendarItemHourly_data();
void testCalendarItemHourly(); void testCalendarItemHourly();
void testCalendarItemDaily_data(); void testCalendarItemDaily_data();
@ -242,8 +243,19 @@ void TestTimeManager::addTimeDescriptor()
verifyRuleError(response); verifyRuleError(response);
} }
void TestTimeManager::testCalendarItemHourly_data()
{
QTest::addColumn<int>("duration");
QTest::newRow("hourly - for 5 minutes") << 5;
QTest::newRow("hourly - for 60 minutes") << 60;
}
void TestTimeManager::testCalendarItemHourly() void TestTimeManager::testCalendarItemHourly()
{ {
QFETCH(int, duration);
initTimeManager(); initTimeManager();
QVariantMap ruleMap; QVariantMap action; QVariantMap exitAction; QVariantMap repeatingOptionHourly; QVariantMap ruleMap; QVariantMap action; QVariantMap exitAction; QVariantMap repeatingOptionHourly;
@ -264,7 +276,7 @@ void TestTimeManager::testCalendarItemHourly()
exitAction.insert("deviceId", m_mockDeviceId); exitAction.insert("deviceId", m_mockDeviceId);
exitAction.insert("ruleActionParams", actionParams); exitAction.insert("ruleActionParams", actionParams);
ruleMap.insert("name", "Time based hourly calendar rule"); ruleMap.insert("name", "Time based hourly calendar rule");
ruleMap.insert("timeDescriptor", createTimeDescriptorCalendar(createCalendarItem("08:05", 5, repeatingOptionHourly))); ruleMap.insert("timeDescriptor", createTimeDescriptorCalendar(createCalendarItem("08:05", duration, repeatingOptionHourly)));
ruleMap.insert("actions", QVariantList() << action); ruleMap.insert("actions", QVariantList() << action);
ruleMap.insert("exitActions", QVariantList() << exitAction); ruleMap.insert("exitActions", QVariantList() << exitAction);
@ -278,31 +290,43 @@ void TestTimeManager::testCalendarItemHourly()
QDateTime currentDateTime = GuhCore::instance()->timeManager()->currentDateTime(); QDateTime currentDateTime = GuhCore::instance()->timeManager()->currentDateTime();
// check the next 24 hours
QDateTime future = QDateTime(currentDateTime.date(), QTime(8, 4)); QDateTime future = QDateTime(currentDateTime.date(), QTime(8, 4));
for (int i = 0; i < 24; i+=3) {
// 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" // Check if should be enabled always
future = future.addSecs(3*60*60); if (duration == 60) {
qDebug() << "Enabled always";
GuhCore::instance()->timeManager()->setTime(future);
// Should be active since adding
verifyRuleExecuted(mockActionIdNoParams);
} else {
// check the next 24 hours in 4h steps
for (int i = 0; i < 24; i+=4) {
// 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(3*60*60);
}
} }
cleanupMockHistory();
// REMOVE rule // REMOVE rule
QVariantMap removeParams; QVariantMap removeParams;
removeParams.insert("ruleId", ruleId); removeParams.insert("ruleId", ruleId);
@ -320,7 +344,8 @@ void TestTimeManager::testCalendarItemDaily_data()
QTest::addColumn<int>("duration"); QTest::addColumn<int>("duration");
QTest::newRow("daily") << createTimeDescriptorCalendar(createCalendarItem("06:55", 10, repeatingOptionDaily)) << "06:55" << 10; QTest::newRow("daily") << createTimeDescriptorCalendar(createCalendarItem("06:55", 10, repeatingOptionDaily)) << "06:55" << 10;
QTest::newRow("daily jump date") << createTimeDescriptorCalendar(createCalendarItem("23:55", 10, repeatingOptionDaily)) << "23:55" << 10; QTest::newRow("daily - jump date") << createTimeDescriptorCalendar(createCalendarItem("23:55", 10, repeatingOptionDaily)) << "23:55" << 10;
QTest::newRow("daily - always") << createTimeDescriptorCalendar(createCalendarItem("08:00", 1440)) << "08:00" << 1440;
} }
void TestTimeManager::testCalendarItemDaily() void TestTimeManager::testCalendarItemDaily()
@ -366,28 +391,38 @@ void TestTimeManager::testCalendarItemDaily()
// start with one minute before starttime today // start with one minute before starttime today
QDateTime future = QDateTime(currentDateTime.date(), QTime::fromString(time, "hh:mm").addSecs(-60)); QDateTime future = QDateTime(currentDateTime.date(), QTime::fromString(time, "hh:mm").addSecs(-60));
// check the next 7 days // if always true
for (int i = 0; i < 7; i++) { if (time == "08:00") {
// inactive qDebug() << "Enabled always";
GuhCore::instance()->timeManager()->setTime(future); GuhCore::instance()->timeManager()->setTime(future);
verifyRuleNotExecuted(); // Should be active since adding
// active
GuhCore::instance()->timeManager()->setTime(future.addSecs(60));
verifyRuleExecuted(mockActionIdNoParams); verifyRuleExecuted(mockActionIdNoParams);
cleanupMockHistory(); } else {
// active unchanged // check the next 7 days
GuhCore::instance()->timeManager()->setTime(future.addSecs(6* 60)); for (int i = 0; i < 7; i++) {
verifyRuleNotExecuted(); // inactive
// inactive GuhCore::instance()->timeManager()->setTime(future);
GuhCore::instance()->timeManager()->setTime(future.addSecs(11 * 60)); verifyRuleNotExecuted();
verifyRuleExecuted(mockActionIdWithParams); // active
cleanupMockHistory(); GuhCore::instance()->timeManager()->setTime(future.addSecs(60));
// inactive unchanged verifyRuleExecuted(mockActionIdNoParams);
GuhCore::instance()->timeManager()->setTime(future.addSecs(12 * 60)); cleanupMockHistory();
verifyRuleNotExecuted(); // active unchanged
// One day "Back to the future" GuhCore::instance()->timeManager()->setTime(future.addSecs(6* 60));
future = future.addDays(1); verifyRuleNotExecuted();
// inactive
GuhCore::instance()->timeManager()->setTime(future.addSecs(11 * 60));
verifyRuleExecuted(mockActionIdWithParams);
cleanupMockHistory();
// inactive unchanged
GuhCore::instance()->timeManager()->setTime(future.addSecs(12 * 60));
verifyRuleNotExecuted();
// One day "Back to the future"
future = future.addDays(1);
}
} }
cleanupMockHistory();
// REMOVE rule // REMOVE rule
QVariantMap removeParams; QVariantMap removeParams;
removeParams.insert("ruleId", ruleId); removeParams.insert("ruleId", ruleId);
@ -403,14 +438,16 @@ void TestTimeManager::testCalendarItemWeekly_data()
QVariantMap repeatingOptionWeeklyOverlapping; QVariantMap repeatingOptionWeeklyOverlapping;
repeatingOptionWeeklyOverlapping.insert("mode", "RepeatingModeWeekly"); repeatingOptionWeeklyOverlapping.insert("mode", "RepeatingModeWeekly");
repeatingOptionWeeklyOverlapping.insert("weekDays", QVariantList() << 2 << 4 << 7); repeatingOptionWeeklyOverlapping.insert("weekDays", QVariantList() << 6);
QTest::addColumn<QVariantMap>("timeDescriptor"); QTest::addColumn<QVariantMap>("timeDescriptor");
QTest::addColumn<QVariantMap>("repeatingOption"); QTest::addColumn<QVariantMap>("repeatingOption");
QTest::addColumn<QString>("time"); QTest::addColumn<QString>("time");
QTest::addColumn<bool>("overlapping");
QTest::newRow("weekly") << createTimeDescriptorCalendar(createCalendarItem("06:55", 10, repeatingOptionWeekly)) << repeatingOptionWeekly << "06:55"; QTest::newRow("weekly") << createTimeDescriptorCalendar(createCalendarItem("06:55", 10, repeatingOptionWeekly)) << repeatingOptionWeekly << "06:55" << false;
//QTest::newRow("weekly overlapping") << createTimeDescriptorCalendar(createCalendarItem("23:55", 10, repeatingOptionWeeklyOverlapping)) << repeatingOptionWeeklyOverlapping << "23:55"; QTest::newRow("weekly - always") << createTimeDescriptorCalendar(createCalendarItem("06:55", 10080)) << QVariantMap() << "06:55" << false;
QTest::newRow("weekly - overlapping") << createTimeDescriptorCalendar(createCalendarItem("08:00", 2880, repeatingOptionWeeklyOverlapping)) << repeatingOptionWeeklyOverlapping << "08:00" << true;
} }
void TestTimeManager::testCalendarItemWeekly() void TestTimeManager::testCalendarItemWeekly()
@ -418,14 +455,17 @@ void TestTimeManager::testCalendarItemWeekly()
QFETCH(QVariantMap, timeDescriptor); QFETCH(QVariantMap, timeDescriptor);
QFETCH(QVariantMap, repeatingOption); QFETCH(QVariantMap, repeatingOption);
QFETCH(QString, time); QFETCH(QString, time);
QFETCH(bool, overlapping);
initTimeManager(); initTimeManager();
// Action (without params)
QVariantMap ruleMap; QVariantMap action; QVariantMap exitAction; QVariantMap ruleMap; QVariantMap action; QVariantMap exitAction;
action.insert("actionTypeId", mockActionIdNoParams); action.insert("actionTypeId", mockActionIdNoParams);
action.insert("deviceId", m_mockDeviceId); action.insert("deviceId", m_mockDeviceId);
action.insert("ruleActionParams", QVariantList()); action.insert("ruleActionParams", QVariantList());
exitAction.insert("actionTypeId", mockActionIdWithParams);
// Exit action (with params)
QVariantList actionParams; QVariantList actionParams;
QVariantMap param1; QVariantMap param1;
param1.insert("name", "mockActionParam1"); param1.insert("name", "mockActionParam1");
@ -435,13 +475,17 @@ void TestTimeManager::testCalendarItemWeekly()
param2.insert("name", "mockActionParam2"); param2.insert("name", "mockActionParam2");
param2.insert("value", true); param2.insert("value", true);
actionParams.append(param2); actionParams.append(param2);
exitAction.insert("actionTypeId", mockActionIdWithParams);
exitAction.insert("deviceId", m_mockDeviceId); exitAction.insert("deviceId", m_mockDeviceId);
exitAction.insert("ruleActionParams", actionParams); exitAction.insert("ruleActionParams", actionParams);
// Create the rule map
ruleMap.insert("name", "Time based hourly calendar rule"); ruleMap.insert("name", "Time based hourly calendar rule");
ruleMap.insert("timeDescriptor", timeDescriptor); ruleMap.insert("timeDescriptor", timeDescriptor);
ruleMap.insert("actions", QVariantList() << action); ruleMap.insert("actions", QVariantList() << action);
ruleMap.insert("exitActions", QVariantList() << exitAction); ruleMap.insert("exitActions", QVariantList() << exitAction);
// Add the rule
QVariant response = injectAndWait("Rules.AddRule", ruleMap); QVariant response = injectAndWait("Rules.AddRule", ruleMap);
verifyRuleError(response); verifyRuleError(response);
RuleId ruleId = RuleId(response.toMap().value("params").toMap().value("ruleId").toString()); RuleId ruleId = RuleId(response.toMap().value("params").toMap().value("ruleId").toString());
@ -463,53 +507,100 @@ void TestTimeManager::testCalendarItemWeekly()
weekDays.append(variant.toInt()); weekDays.append(variant.toInt());
} }
// check the next 7 days // the whole week active (always)
for (int i = 0; i < 7; i++) { if (repeatingOption.isEmpty()) {
// inactive qDebug() << "Enabled always";
GuhCore::instance()->timeManager()->setTime(future); GuhCore::instance()->timeManager()->setTime(future);
verifyRuleNotExecuted(); // Should be active since adding
verifyRuleExecuted(mockActionIdNoParams);
} else {
if (!overlapping) {
// check the next 7 days (because not overlapping the week)
for (int i = 0; i < 7; i++) {
// inactive
GuhCore::instance()->timeManager()->setTime(future);
verifyRuleNotExecuted();
// Check if today is a weekday
qDebug() << "Day of week:" << future.date().dayOfWeek();
if (weekDays.contains(future.date().dayOfWeek())) {
// should trigger today
// active
GuhCore::instance()->timeManager()->setTime(future.addSecs(60));
verifyRuleExecuted(mockActionIdNoParams);
cleanupMockHistory();
// active unchanged
GuhCore::instance()->timeManager()->setTime(future.addSecs(6* 60));
verifyRuleNotExecuted();
// inactive
GuhCore::instance()->timeManager()->setTime(future.addSecs(11 * 60));
verifyRuleExecuted(mockActionIdWithParams);
cleanupMockHistory();
// inactive unchanged
GuhCore::instance()->timeManager()->setTime(future.addSecs(12 * 60));
verifyRuleNotExecuted();
// One day "Back to the future"
future = future.addDays(1);
} else {
// should not trigger today
// inactive
GuhCore::instance()->timeManager()->setTime(future);
verifyRuleNotExecuted();
// inactive
GuhCore::instance()->timeManager()->setTime(future.addSecs(6* 60));
verifyRuleNotExecuted();
// inactive
GuhCore::instance()->timeManager()->setTime(future.addSecs(11 * 60));
verifyRuleNotExecuted();
// inactive
GuhCore::instance()->timeManager()->setTime(future.addSecs(12 * 60));
verifyRuleNotExecuted();
// One day "Back to the future"
future = future.addDays(1);
}
}
} else {
// Overlapping the week
int weekDay = weekDays.first();
qDebug() << "weekday to start" << weekDay;
// go to the next start day (saturday)
QDateTime startDate = future;
while (startDate.date().dayOfWeek() < 6) {
startDate = startDate.addDays(1);
qDebug() << startDate.toString();
}
// inactive
GuhCore::instance()->timeManager()->setTime(startDate);
verifyRuleNotExecuted();
// Check if today is a weekday
qDebug() << "Day of week:" << future.date().dayOfWeek();
if (weekDays.contains(future.date().dayOfWeek())) {
// should trigger today
// active // active
GuhCore::instance()->timeManager()->setTime(future.addSecs(60)); GuhCore::instance()->timeManager()->setTime(startDate.addSecs(60));
verifyRuleExecuted(mockActionIdNoParams); verifyRuleExecuted(mockActionIdNoParams);
cleanupMockHistory(); cleanupMockHistory();
// active unchanged
GuhCore::instance()->timeManager()->setTime(future.addSecs(6* 60)); // still active
GuhCore::instance()->timeManager()->setTime(startDate.addDays(1));
verifyRuleNotExecuted(); verifyRuleNotExecuted();
// still active
GuhCore::instance()->timeManager()->setTime(startDate.addDays(2));
verifyRuleNotExecuted();
// inactive // inactive
GuhCore::instance()->timeManager()->setTime(future.addSecs(11 * 60)); GuhCore::instance()->timeManager()->setTime(startDate.addDays(2).addSecs(60));
verifyRuleExecuted(mockActionIdWithParams); verifyRuleExecuted(mockActionIdWithParams);
cleanupMockHistory();
// inactive unchanged
GuhCore::instance()->timeManager()->setTime(future.addSecs(12 * 60));
verifyRuleNotExecuted();
// One day "Back to the future"
future = future.addDays(1);
} else {
// should not trigger today
// inactive
GuhCore::instance()->timeManager()->setTime(future);
verifyRuleNotExecuted();
// inactive
GuhCore::instance()->timeManager()->setTime(future.addSecs(6* 60));
verifyRuleNotExecuted();
// inactive
GuhCore::instance()->timeManager()->setTime(future.addSecs(11 * 60));
verifyRuleNotExecuted();
// inactive
GuhCore::instance()->timeManager()->setTime(future.addSecs(12 * 60));
verifyRuleNotExecuted();
// One day "Back to the future"
future = future.addDays(1);
} }
} }
cleanupMockHistory();
// REMOVE rule // REMOVE rule
QVariantMap removeParams; QVariantMap removeParams;
removeParams.insert("ruleId", ruleId); removeParams.insert("ruleId", ruleId);