diff --git a/server/time/calendaritem.cpp b/server/time/calendaritem.cpp index 7d1f98e1..4c506939 100644 --- a/server/time/calendaritem.cpp +++ b/server/time/calendaritem.cpp @@ -106,6 +106,7 @@ bool CalendarItem::isValid() const bool CalendarItem::evaluate(const QDateTime &dateTime) const { if (m_startTime.isValid()) { + switch (m_repeatingOption.mode()) { case RepeatingOption::RepeatingModeNone: // If there is no repeating option, we assume it is meant daily. @@ -120,14 +121,13 @@ bool CalendarItem::evaluate(const QDateTime &dateTime) const return evaluateMonthly(dateTime); case RepeatingOption::RepeatingModeYearly: return evaluateYearly(dateTime); - default: - return false; } - } else if (m_repeatingOption.mode() == RepeatingOption::RepeatingModeYearly) { - return evaluateYearly(dateTime); - } else { - return dateTime >= m_dateTime && dateTime < m_dateTime.addSecs(duration() * 60); + } + if (m_repeatingOption.mode() == RepeatingOption::RepeatingModeYearly) + return evaluateYearly(dateTime); + + return dateTime >= m_dateTime && dateTime < m_dateTime.addSecs(duration() * 60); } bool CalendarItem::evaluateHourly(const QDateTime &dateTime) const @@ -230,17 +230,6 @@ bool CalendarItem::evaluateMonthly(const QDateTime &dateTime) const // and end of this calendar item return true; -// // Check if this calendar item overlaps a month... -// if (startDateTime.date().month() != endDateTime.date().month()) { -// // ...jump one month back in to the past -// QDateTime startDateTimePreviousMonth = startDateTime.addMonths(-1); -// QDateTime endDateTimePreviousMonth = startDateTimePreviousMonth.addSecs(duration() * 60); - -// if (dateTime >= startDateTimePreviousMonth && dateTime < endDateTimePreviousMonth) -// // Return true if the current time is between start -// // and end of this calendar item from the previouse month -// return true; -// } } return false; diff --git a/server/time/timeeventitem.cpp b/server/time/timeeventitem.cpp index d001b9d1..33de772e 100644 --- a/server/time/timeeventitem.cpp +++ b/server/time/timeeventitem.cpp @@ -80,9 +80,11 @@ void TimeEventItem::setRepeatingOption(const RepeatingOption &repeatingOption) */ bool TimeEventItem::isValid() const { - // A dateTime AND a repeating option would not make sense + // If dateTime AND a repeating option definend... if (m_dateTime.isValid() && !repeatingOption().isEmtpy()) - return false; + // ...only repeating mode yearly is allowed for dateTime + if (repeatingOption().mode() != RepeatingOption::RepeatingModeYearly) + return false; return (!m_dateTime.isNull() != !m_time.isNull()); } @@ -90,11 +92,33 @@ bool TimeEventItem::isValid() const /*! Returns true, if the given \a dateTime matches this \l{TimeEventItem}. */ bool TimeEventItem::evaluate(const QDateTime &dateTime) const { - Q_UNUSED(dateTime) + // Check time matches + if (m_time.isValid()) { + switch (m_repeatingOption.mode()) { + case RepeatingOption::RepeatingModeNone: + // If there is no repeating option, we assume it is meant daily. + return m_time == dateTime.time();; + case RepeatingOption::RepeatingModeHourly: + return m_time.minute() == dateTime.time().minute(); + case RepeatingOption::RepeatingModeDaily: + return m_time == dateTime.time();; + case RepeatingOption::RepeatingModeWeekly: + return m_repeatingOption.evaluateWeekDay(dateTime) && m_time == dateTime.time(); + case RepeatingOption::RepeatingModeMonthly: + return m_repeatingOption.evaluateMonthDay(dateTime) && m_time == dateTime.time(); + case RepeatingOption::RepeatingModeYearly: + return false; + } + } - // TODO: evaluate the calendar item, return true if the current time matches the calendar item, otherwise false + // Check dateTime and yearly repeating + if (m_repeatingOption.mode() == RepeatingOption::RepeatingModeYearly) + return m_dateTime.date().month() == dateTime.date().month() && + m_dateTime.date().day() == dateTime.date().day() && + m_dateTime.time() == dateTime.time(); - return false; + // Check dateTime matches + return dateTime == m_dateTime; } } diff --git a/server/time/timeeventitem.h b/server/time/timeeventitem.h index 2ca74e49..a04f0a9c 100644 --- a/server/time/timeeventitem.h +++ b/server/time/timeeventitem.h @@ -52,7 +52,6 @@ private: QTime m_time; RepeatingOption m_repeatingOption; - }; } diff --git a/tests/auto/guhtestbase.cpp b/tests/auto/guhtestbase.cpp index 7e28739a..18646c68 100644 --- a/tests/auto/guhtestbase.cpp +++ b/tests/auto/guhtestbase.cpp @@ -24,6 +24,7 @@ #include "guhcore.h" #include "guhsettings.h" #include "devicemanager.h" +#include "loggingcategories.h" #include "logging/logengine.h" #include "jsontypes.h" @@ -60,6 +61,20 @@ ActionTypeId mockActionIdAsync = ActionTypeId("fbae06d3-7666-483e-a39e-ec50fe890 ActionTypeId mockActionIdFailing = ActionTypeId("df3cf33d-26d5-4577-9132-9823bd33fad0"); ActionTypeId mockActionIdAsyncFailing = ActionTypeId("bfe89a1d-3497-4121-8318-e77c37537219"); +static QHash s_loggingFilters; + +static void loggingCategoryFilter(QLoggingCategory *category) +{ + if (s_loggingFilters.contains(category->categoryName())) { + bool debugEnabled = s_loggingFilters.value(category->categoryName()); + category->setEnabled(QtDebugMsg, debugEnabled); + category->setEnabled(QtWarningMsg, debugEnabled || s_loggingFilters.value("Warnings")); + } else { + category->setEnabled(QtDebugMsg, true); + category->setEnabled(QtWarningMsg, true); + } +} + GuhTestBase::GuhTestBase(QObject *parent) : QObject(parent), m_commandId(0) @@ -81,6 +96,39 @@ void GuhTestBase::initTestCase() GuhSettings pluginSettings(GuhSettings::SettingsRolePlugins); pluginSettings.clear(); + // debug categories + // logging filers for core and libguh + s_loggingFilters.insert("Application", true); + s_loggingFilters.insert("Warnings", true); + s_loggingFilters.insert("DeviceManager", true); + s_loggingFilters.insert("RuleEngine", true); + s_loggingFilters.insert("Hardware", false); + s_loggingFilters.insert("Connection", false); + s_loggingFilters.insert("LogEngine", false); + s_loggingFilters.insert("TcpServer", false); + s_loggingFilters.insert("WebServer", false); + s_loggingFilters.insert("WebSocketServer", false); + s_loggingFilters.insert("JsonRpc", false); + s_loggingFilters.insert("Rest", false); + s_loggingFilters.insert("OAuth2", false); + s_loggingFilters.insert("TimeManager", true); + + QHash loggingFiltersPlugins; + foreach (const QJsonObject &pluginMetadata, DeviceManager::pluginsMetadata()) { + loggingFiltersPlugins.insert(pluginMetadata.value("idName").toString(), false); + } + + // add plugin metadata to the static hash + foreach (const QString &category, loggingFiltersPlugins.keys()) { + if (category == "MockDevice") { + s_loggingFilters.insert(category, true); + } else { + s_loggingFilters.insert(category, false); + } + } + + QLoggingCategory::installFilter(loggingCategoryFilter); + GuhCore::instance(); // Wait for the DeviceManager to signal that it has loaded plugins and everything diff --git a/tests/auto/timemanager/testtimemanager.cpp b/tests/auto/timemanager/testtimemanager.cpp index 07ef16f6..2e552692 100644 --- a/tests/auto/timemanager/testtimemanager.cpp +++ b/tests/auto/timemanager/testtimemanager.cpp @@ -49,9 +49,6 @@ private slots: void testCalendarDateTime_data(); void testCalendarDateTime(); - void testCalendarYearlyDateTime_data(); - void testCalendarYearlyDateTime(); - void testCalendarItemHourly_data(); void testCalendarItemHourly(); @@ -64,6 +61,14 @@ private slots: void testCalendarItemMonthly_data(); void testCalendarItemMonthly(); + void testCalendarYearlyDateTime_data(); + void testCalendarYearlyDateTime(); + + void testEventItemDateTime_data(); + void testEventItemDateTime(); + + + private: void initTimeManager(); @@ -196,6 +201,7 @@ void TestTimeManager::addTimeDescriptor_data() QTest::newRow("valid: timeEventItem") << createTimeDescriptorTimeEvent(createTimeEventItem("08:00")) << RuleEngine::RuleErrorNoError; QTest::newRow("valid: timeEventItem dateTime") << createTimeDescriptorTimeEvent(createTimeEventItem(QDateTime::currentDateTime().toTime_t())) << RuleEngine::RuleErrorNoError; + QTest::newRow("valid: timeEventItem dateTime - yearly") << createTimeDescriptorTimeEvent(createTimeEventItem(QDateTime::currentDateTime().toTime_t(), repeatingOptionYearly)) << RuleEngine::RuleErrorNoError; QTest::newRow("valid: timeEventItem - daily") << createTimeDescriptorTimeEvent(createTimeEventItem("08:00", repeatingOptionDaily)) << RuleEngine::RuleErrorNoError; QTest::newRow("valid: timeEventItem - none") << createTimeDescriptorTimeEvent(createTimeEventItem("09:00", repeatingOptionNone)) << RuleEngine::RuleErrorNoError; QTest::newRow("valid: timeEventItem - hourly") << createTimeDescriptorTimeEvent(createTimeEventItem("09:00", repeatingOptionHourly)) << RuleEngine::RuleErrorNoError; @@ -204,7 +210,7 @@ void TestTimeManager::addTimeDescriptor_data() 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 + daily") << createTimeDescriptorCalendar(createCalendarItem(QDateTime::currentDateTime().toTime_t(), 5, repeatingOptionDaily)) << RuleEngine::RuleErrorInvalidCalendarItem; + QTest::newRow("invalid: calendarItem dateTime - daily") << 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; QTest::newRow("invalid: calendarItem - monthly - weekDays") << createTimeDescriptorCalendar(createCalendarItem("13:13", 5, repeatingOptionInvalidMonthly)) << RuleEngine::RuleErrorInvalidRepeatingOption; @@ -337,114 +343,6 @@ void TestTimeManager::testCalendarDateTime() verifyRuleError(response); } -void TestTimeManager::testCalendarYearlyDateTime_data() -{ - QTest::addColumn("dateTime"); - QTest::addColumn("duration"); - - QTest::newRow("dateTime - yearly - christmas") << QDateTime::fromString(QString("24.12.%1 20:00").arg(QDateTime::currentDateTime().date().year() + 1), "dd.MM.yyyy hh:mm") << 60; - QTest::newRow("dateTime - yearly - new year") << QDateTime::fromString(QString("31.12.%1 23:00").arg(QDateTime::currentDateTime().date().year() + 1), "dd.MM.yyyy hh:mm") << 120; - QTest::newRow("dateTime - yearly - valentines day") << QDateTime::fromString("14.02.2017 08:00", "dd.MM.yyyy hh:mm") << 120; -} - -void TestTimeManager::testCalendarYearlyDateTime() -{ - QFETCH(QDateTime, dateTime); - QFETCH(int, duration); - - initTimeManager(); - - // Action (without params) - QVariantMap ruleMap; QVariantMap action; QVariantMap exitAction; - action.insert("actionTypeId", mockActionIdNoParams); - action.insert("deviceId", m_mockDeviceId); - action.insert("ruleActionParams", QVariantList()); - - // Exit action (with params) - QVariantList actionParams; - QVariantMap param1; - param1.insert("name", "mockActionParam1"); - param1.insert("value", 12); - actionParams.append(param1); - QVariantMap param2; - param2.insert("name", "mockActionParam2"); - param2.insert("value", true); - actionParams.append(param2); - exitAction.insert("actionTypeId", mockActionIdWithParams); - exitAction.insert("deviceId", m_mockDeviceId); - exitAction.insert("ruleActionParams", actionParams); - - // RepeatingOption - QVariantMap repeatingOption; - repeatingOption.insert("mode", "RepeatingModeYearly"); - - // CalendarItem - QVariantMap calendarItem; - calendarItem.insert("datetime", QVariant(dateTime.toTime_t())); - calendarItem.insert("duration", QVariant(duration)); - calendarItem.insert("repeating", repeatingOption); - - // Create the rule map - ruleMap.insert("name", "Time based yearly calendar rule"); - ruleMap.insert("timeDescriptor", createTimeDescriptorCalendar(calendarItem)); - ruleMap.insert("actions", QVariantList() << action); - ruleMap.insert("exitActions", QVariantList() << exitAction); - - // Add the rule - QVariant response = injectAndWait("Rules.AddRule", ruleMap); - verifyRuleError(response); - RuleId ruleId = RuleId(response.toMap().value("params").toMap().value("ruleId").toString()); - - QDateTime oneMinuteBeforeEvent = dateTime.addSecs(-60); - - GuhCore::instance()->timeManager()->setTime(oneMinuteBeforeEvent); - verifyRuleNotExecuted(); - // active - GuhCore::instance()->timeManager()->setTime(dateTime); - verifyRuleExecuted(mockActionIdNoParams); - cleanupMockHistory(); - // active unchanged - GuhCore::instance()->timeManager()->setTime(dateTime.addSecs(duration * 30)); - verifyRuleNotExecuted(); - // inactive - GuhCore::instance()->timeManager()->setTime(dateTime.addSecs(duration * 60)); - verifyRuleExecuted(mockActionIdWithParams); - cleanupMockHistory(); - // inactive unchanged - GuhCore::instance()->timeManager()->setTime(dateTime.addSecs((duration + 1) * 60)); - verifyRuleNotExecuted(); - - - // One year "Back to the future" - oneMinuteBeforeEvent = oneMinuteBeforeEvent.addYears(1); - dateTime = dateTime.addYears(1); - - GuhCore::instance()->timeManager()->setTime(oneMinuteBeforeEvent); - verifyRuleNotExecuted(); - // active - GuhCore::instance()->timeManager()->setTime(dateTime); - verifyRuleExecuted(mockActionIdNoParams); - cleanupMockHistory(); - // active unchanged - GuhCore::instance()->timeManager()->setTime(dateTime.addSecs(duration * 30)); - verifyRuleNotExecuted(); - // inactive - GuhCore::instance()->timeManager()->setTime(dateTime.addSecs(duration * 60)); - verifyRuleExecuted(mockActionIdWithParams); - cleanupMockHistory(); - // inactive unchanged - GuhCore::instance()->timeManager()->setTime(dateTime.addSecs((duration + 1) * 60)); - verifyRuleNotExecuted(); - - cleanupMockHistory(); - - // REMOVE rule - QVariantMap removeParams; - removeParams.insert("ruleId", ruleId); - response = injectAndWait("Rules.RemoveRule", removeParams); - verifyRuleError(response); -} - void TestTimeManager::testCalendarItemHourly_data() { QTest::addColumn("duration"); @@ -730,18 +628,8 @@ void TestTimeManager::testCalendarItemWeekly() 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); @@ -928,6 +816,167 @@ void TestTimeManager::testCalendarItemMonthly() verifyRuleError(response); } +void TestTimeManager::testCalendarYearlyDateTime_data() +{ + QTest::addColumn("dateTime"); + QTest::addColumn("duration"); + + QTest::newRow("dateTime - yearly - christmas") << QDateTime::fromString(QString("24.12.%1 20:00").arg(QDateTime::currentDateTime().date().year() + 1), "dd.MM.yyyy hh:mm") << 60; + QTest::newRow("dateTime - yearly - new year") << QDateTime::fromString(QString("31.12.%1 23:00").arg(QDateTime::currentDateTime().date().year() + 1), "dd.MM.yyyy hh:mm") << 120; + QTest::newRow("dateTime - yearly - valentines day") << QDateTime::fromString("14.02.2017 08:00", "dd.MM.yyyy hh:mm") << 120; +} + +void TestTimeManager::testCalendarYearlyDateTime() +{ + QFETCH(QDateTime, dateTime); + QFETCH(int, duration); + + initTimeManager(); + + // Action (without params) + QVariantMap ruleMap; QVariantMap action; QVariantMap exitAction; + action.insert("actionTypeId", mockActionIdNoParams); + action.insert("deviceId", m_mockDeviceId); + action.insert("ruleActionParams", QVariantList()); + + // Exit action (with params) + QVariantList actionParams; + QVariantMap param1; + param1.insert("name", "mockActionParam1"); + param1.insert("value", 12); + actionParams.append(param1); + QVariantMap param2; + param2.insert("name", "mockActionParam2"); + param2.insert("value", true); + actionParams.append(param2); + exitAction.insert("actionTypeId", mockActionIdWithParams); + exitAction.insert("deviceId", m_mockDeviceId); + exitAction.insert("ruleActionParams", actionParams); + + // RepeatingOption + QVariantMap repeatingOption; + repeatingOption.insert("mode", "RepeatingModeYearly"); + + // CalendarItem + QVariantMap calendarItem; + calendarItem.insert("datetime", QVariant(dateTime.toTime_t())); + calendarItem.insert("duration", QVariant(duration)); + calendarItem.insert("repeating", repeatingOption); + + // Create the rule map + ruleMap.insert("name", "Time based yearly calendar rule"); + ruleMap.insert("timeDescriptor", createTimeDescriptorCalendar(calendarItem)); + ruleMap.insert("actions", QVariantList() << action); + ruleMap.insert("exitActions", QVariantList() << exitAction); + + // Add the rule + QVariant response = injectAndWait("Rules.AddRule", ruleMap); + verifyRuleError(response); + RuleId ruleId = RuleId(response.toMap().value("params").toMap().value("ruleId").toString()); + + QDateTime oneMinuteBeforeEvent = dateTime.addSecs(-60); + + GuhCore::instance()->timeManager()->setTime(oneMinuteBeforeEvent); + verifyRuleNotExecuted(); + // active + GuhCore::instance()->timeManager()->setTime(dateTime); + verifyRuleExecuted(mockActionIdNoParams); + cleanupMockHistory(); + // active unchanged + GuhCore::instance()->timeManager()->setTime(dateTime.addSecs(duration * 30)); + verifyRuleNotExecuted(); + // inactive + GuhCore::instance()->timeManager()->setTime(dateTime.addSecs(duration * 60)); + verifyRuleExecuted(mockActionIdWithParams); + cleanupMockHistory(); + // inactive unchanged + GuhCore::instance()->timeManager()->setTime(dateTime.addSecs((duration + 1) * 60)); + verifyRuleNotExecuted(); + + + // One year "Back to the future" + oneMinuteBeforeEvent = oneMinuteBeforeEvent.addYears(1); + dateTime = dateTime.addYears(1); + + GuhCore::instance()->timeManager()->setTime(oneMinuteBeforeEvent); + verifyRuleNotExecuted(); + // active + GuhCore::instance()->timeManager()->setTime(dateTime); + verifyRuleExecuted(mockActionIdNoParams); + cleanupMockHistory(); + // active unchanged + GuhCore::instance()->timeManager()->setTime(dateTime.addSecs(duration * 30)); + verifyRuleNotExecuted(); + // inactive + GuhCore::instance()->timeManager()->setTime(dateTime.addSecs(duration * 60)); + verifyRuleExecuted(mockActionIdWithParams); + cleanupMockHistory(); + // inactive unchanged + GuhCore::instance()->timeManager()->setTime(dateTime.addSecs((duration + 1) * 60)); + verifyRuleNotExecuted(); + + cleanupMockHistory(); + + // REMOVE rule + QVariantMap removeParams; + removeParams.insert("ruleId", ruleId); + response = injectAndWait("Rules.RemoveRule", removeParams); + verifyRuleError(response); +} + +void TestTimeManager::testEventItemDateTime_data() +{ + QTest::addColumn("dateTime"); + + QTest::newRow("dateTime - christmas") << QDateTime::fromString("24.12.2016 20:00", "dd.MM.yyyy hh:mm"); + QTest::newRow("dateTime - new year") << QDateTime::fromString("31.12.2016 00:00", "dd.MM.yyyy hh:mm"); + QTest::newRow("dateTime - valentines day") << QDateTime::fromString("14.02.2016 08:00", "dd.MM.yyyy hh:mm"); +} + +void TestTimeManager::testEventItemDateTime() +{ + QFETCH(QDateTime, dateTime); + + initTimeManager(); + + // Action (without params) + QVariantMap ruleMap; QVariantMap action; + action.insert("actionTypeId", mockActionIdNoParams); + action.insert("deviceId", m_mockDeviceId); + action.insert("ruleActionParams", QVariantList()); + + // Create the rule map + ruleMap.insert("name", "Time based hourly calendar rule"); + ruleMap.insert("timeDescriptor", createTimeDescriptorTimeEvent(createTimeEventItem(dateTime.toTime_t()))); + ruleMap.insert("actions", QVariantList() << action); + + // Add the rule + QVariant response = injectAndWait("Rules.AddRule", ruleMap); + verifyRuleError(response); + RuleId ruleId = RuleId(response.toMap().value("params").toMap().value("ruleId").toString()); + + QDateTime oneMinuteBeforeEvent = dateTime.addSecs(-60); + + // not triggering + GuhCore::instance()->timeManager()->setTime(oneMinuteBeforeEvent); + verifyRuleNotExecuted(); + // trigger + GuhCore::instance()->timeManager()->setTime(dateTime); + verifyRuleExecuted(mockActionIdNoParams); + cleanupMockHistory(); + // not triggering + GuhCore::instance()->timeManager()->setTime(dateTime.addSecs(60)); + verifyRuleNotExecuted(); + + cleanupMockHistory(); + + // REMOVE rule + QVariantMap removeParams; + removeParams.insert("ruleId", ruleId); + response = injectAndWait("Rules.RemoveRule", removeParams); + verifyRuleError(response); +} + void TestTimeManager::initTimeManager() { GuhCore::instance()->timeManager()->stopTimer();