From cff541acfef717aae4c9b696627b4817e7eac851 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Thu, 24 Apr 2014 11:04:55 -0500 Subject: rename 'clock-watcher' as 'alarm-queue' because the former name isn't very informative. --- include/datetime/alarm-queue.h | 75 +++++++++++++++++ include/datetime/clock-watcher.h | 75 ----------------- src/CMakeLists.txt | 2 +- src/alarm-queue.cpp | 81 ++++++++++++++++++ src/clock-watcher.cpp | 81 ------------------ src/main.cpp | 6 +- tests/CMakeLists.txt | 2 +- tests/test-alarm-queue.cpp | 172 +++++++++++++++++++++++++++++++++++++++ tests/test-clock-watcher.cpp | 172 --------------------------------------- 9 files changed, 333 insertions(+), 333 deletions(-) create mode 100644 include/datetime/alarm-queue.h delete mode 100644 include/datetime/clock-watcher.h create mode 100644 src/alarm-queue.cpp delete mode 100644 src/clock-watcher.cpp create mode 100644 tests/test-alarm-queue.cpp delete mode 100644 tests/test-clock-watcher.cpp diff --git a/include/datetime/alarm-queue.h b/include/datetime/alarm-queue.h new file mode 100644 index 0000000..5db4ad8 --- /dev/null +++ b/include/datetime/alarm-queue.h @@ -0,0 +1,75 @@ +/* + * Copyright 2014 Canonical Ltd. + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 3, as published + * by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranties of + * MERCHANTABILITY, SATISFACTORY QUALITY, 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 this program. If not, see . + * + * Authors: + * Charles Kerr + */ + +#ifndef INDICATOR_DATETIME_ALARM_QUEUE_H +#define INDICATOR_DATETIME_ALARM_QUEUE_H + +#include +#include +#include + +#include + +#include +#include +#include + +namespace unity { +namespace indicator { +namespace datetime { + + +/** + * \brief Watches the clock and appointments to notify when an + * appointment's time is reached. + */ +class AlarmQueue +{ +public: + AlarmQueue() =default; + virtual ~AlarmQueue() =default; + virtual core::Signal& alarm_reached() = 0; +}; + + +/** + * \brief A #AlarmQueue implementation + */ +class AlarmQueueImpl: public AlarmQueue +{ +public: + AlarmQueueImpl(const std::shared_ptr& clock, + const std::shared_ptr& upcoming_planner); + ~AlarmQueueImpl() =default; + core::Signal& alarm_reached(); + +private: + void pulse(); + std::set m_triggered; + const std::shared_ptr m_clock; + const std::shared_ptr m_upcoming_planner; + core::Signal m_alarm_reached; +}; + + +} // namespace datetime +} // namespace indicator +} // namespace unity + +#endif // INDICATOR_DATETIME_ALARM_QUEUE_H diff --git a/include/datetime/clock-watcher.h b/include/datetime/clock-watcher.h deleted file mode 100644 index 90bbb63..0000000 --- a/include/datetime/clock-watcher.h +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright 2014 Canonical Ltd. - * - * This program is free software: you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 3, as published - * by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranties of - * MERCHANTABILITY, SATISFACTORY QUALITY, 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 this program. If not, see . - * - * Authors: - * Charles Kerr - */ - -#ifndef INDICATOR_DATETIME_CLOCK_WATCHER_H -#define INDICATOR_DATETIME_CLOCK_WATCHER_H - -#include -#include -#include - -#include - -#include -#include -#include - -namespace unity { -namespace indicator { -namespace datetime { - - -/** - * \brief Watches the clock and appointments to notify when an - * appointment's time is reached. - */ -class ClockWatcher -{ -public: - ClockWatcher() =default; - virtual ~ClockWatcher() =default; - virtual core::Signal& alarm_reached() = 0; -}; - - -/** - * \brief A #ClockWatcher implementation - */ -class ClockWatcherImpl: public ClockWatcher -{ -public: - ClockWatcherImpl(const std::shared_ptr& clock, - const std::shared_ptr& upcoming_planner); - ~ClockWatcherImpl() =default; - core::Signal& alarm_reached(); - -private: - void pulse(); - std::set m_triggered; - const std::shared_ptr m_clock; - const std::shared_ptr m_upcoming_planner; - core::Signal m_alarm_reached; -}; - - -} // namespace datetime -} // namespace indicator -} // namespace unity - -#endif // INDICATOR_DATETIME_CLOCK_WATCHER_H diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 9bc22f2..6b65ebc 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -10,10 +10,10 @@ add_definitions (-DTIMEZONE_FILE="/etc/timezone" add_library (${SERVICE_LIB} STATIC actions.cpp actions-live.cpp + alarm-queue.cpp appointment.cpp clock.cpp clock-live.cpp - clock-watcher.cpp date-time.cpp engine-eds.cpp exporter.cpp diff --git a/src/alarm-queue.cpp b/src/alarm-queue.cpp new file mode 100644 index 0000000..9e9da7f --- /dev/null +++ b/src/alarm-queue.cpp @@ -0,0 +1,81 @@ +/* + * Copyright 2014 Canonical Ltd. + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 3, as published + * by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranties of + * MERCHANTABILITY, SATISFACTORY QUALITY, 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 this program. If not, see . + * + * Authors: + * Charles Kerr + */ + +#include + +namespace unity { +namespace indicator { +namespace datetime { + +/*** +**** +***/ + +AlarmQueueImpl::AlarmQueueImpl(const std::shared_ptr& clock, + const std::shared_ptr& upcoming_planner): + m_clock(clock), + m_upcoming_planner(upcoming_planner) +{ + m_clock->date_changed.connect([this](){ + const auto now = m_clock->localtime(); + g_debug("AlarmQueue %p refretching appointments due to date change: %s", this, now.format("%F %T").c_str()); + m_upcoming_planner->date().set(now); + }); + + m_clock->minute_changed.connect([this](){ + g_debug("AlarmQueue %p calling pulse() due to clock minute_changed", this); + pulse(); + }); + + m_upcoming_planner->appointments().changed().connect([this](const std::vector&){ + g_debug("AlarmQueue %p calling pulse() due to appointments changed", this); + pulse(); + }); + + pulse(); +} + +core::Signal& AlarmQueueImpl::alarm_reached() +{ + return m_alarm_reached; +} + +void AlarmQueueImpl::pulse() +{ + const auto now = m_clock->localtime(); + + for(const auto& appointment : m_upcoming_planner->appointments().get()) + { + if (m_triggered.count(appointment.uid)) + continue; + if (!DateTime::is_same_minute(now, appointment.begin)) + continue; + + m_triggered.insert(appointment.uid); + m_alarm_reached(appointment); + } +} + +/*** +**** +***/ + +} // namespace datetime +} // namespace indicator +} // namespace unity diff --git a/src/clock-watcher.cpp b/src/clock-watcher.cpp deleted file mode 100644 index 5da66c8..0000000 --- a/src/clock-watcher.cpp +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright 2014 Canonical Ltd. - * - * This program is free software: you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 3, as published - * by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranties of - * MERCHANTABILITY, SATISFACTORY QUALITY, 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 this program. If not, see . - * - * Authors: - * Charles Kerr - */ - -#include - -namespace unity { -namespace indicator { -namespace datetime { - -/*** -**** -***/ - -ClockWatcherImpl::ClockWatcherImpl(const std::shared_ptr& clock, - const std::shared_ptr& upcoming_planner): - m_clock(clock), - m_upcoming_planner(upcoming_planner) -{ - m_clock->date_changed.connect([this](){ - const auto now = m_clock->localtime(); - g_debug("ClockWatcher %p refretching appointments due to date change: %s", this, now.format("%F %T").c_str()); - m_upcoming_planner->date().set(now); - }); - - m_clock->minute_changed.connect([this](){ - g_debug("ClockWatcher %p calling pulse() due to clock minute_changed", this); - pulse(); - }); - - m_upcoming_planner->appointments().changed().connect([this](const std::vector&){ - g_debug("ClockWatcher %p calling pulse() due to appointments changed", this); - pulse(); - }); - - pulse(); -} - -core::Signal& ClockWatcherImpl::alarm_reached() -{ - return m_alarm_reached; -} - -void ClockWatcherImpl::pulse() -{ - const auto now = m_clock->localtime(); - - for(const auto& appointment : m_upcoming_planner->appointments().get()) - { - if (m_triggered.count(appointment.uid)) - continue; - if (!DateTime::is_same_minute(now, appointment.begin)) - continue; - - m_triggered.insert(appointment.uid); - m_alarm_reached(appointment); - } -} - -/*** -**** -***/ - -} // namespace datetime -} // namespace indicator -} // namespace unity diff --git a/src/main.cpp b/src/main.cpp index c7b35e5..238bd02 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -18,8 +18,8 @@ */ #include +#include #include -#include #include #include #include @@ -80,9 +80,9 @@ main(int /*argc*/, char** /*argv*/) // snap decisions std::shared_ptr upcoming_planner(new UpcomingPlanner(std::shared_ptr(new SimpleRangePlanner(engine, file_timezone)), now)); - ClockWatcherImpl clock_watcher(live_clock, upcoming_planner); + AlarmQueueImpl alarm_queue(live_clock, upcoming_planner); Snap snap; - clock_watcher.alarm_reached().connect([&snap](const Appointment& appt){ + alarm_queue.alarm_reached().connect([&snap](const Appointment& appt){ auto snap_show = [](const Appointment& a){ const char* url; if(!a.url.empty()) diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 7d590c9..fe6d7eb 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -41,8 +41,8 @@ function(add_test_by_name name) target_link_libraries (${TEST_NAME} indicatordatetimeservice gtest ${SERVICE_DEPS_LIBRARIES} ${GTEST_LIBS}) endfunction() add_test_by_name(test-actions) +add_test_by_name(test-alarm-queue) add_test_by_name(test-clock) -add_test_by_name(test-clock-watcher) add_test_by_name(test-exporter) add_test_by_name(test-formatter) add_test_by_name(test-live-actions) diff --git a/tests/test-alarm-queue.cpp b/tests/test-alarm-queue.cpp new file mode 100644 index 0000000..881a4ad --- /dev/null +++ b/tests/test-alarm-queue.cpp @@ -0,0 +1,172 @@ +/* + * Copyright 2014 Canonical Ltd. + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 3, as published + * by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranties of + * MERCHANTABILITY, SATISFACTORY QUALITY, 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 this program. If not, see . + * + * Authors: + * Charles Kerr + */ + +#include + +#include + +#include "state-fixture.h" + +using namespace unity::indicator::datetime; + +class AlarmQueueFixture: public StateFixture +{ +private: + + typedef StateFixture super; + +protected: + + std::vector m_triggered; + std::unique_ptr m_watcher; + std::shared_ptr m_range_planner; + std::shared_ptr m_upcoming; + + void SetUp() + { + super::SetUp(); + + m_range_planner.reset(new MockRangePlanner); + m_upcoming.reset(new UpcomingPlanner(m_range_planner, m_state->clock->localtime())); + m_watcher.reset(new AlarmQueueImpl(m_state->clock, m_upcoming)); + m_watcher->alarm_reached().connect([this](const Appointment& appt){ + m_triggered.push_back(appt.uid); + }); + + EXPECT_TRUE(m_triggered.empty()); + } + + void TearDown() + { + m_triggered.clear(); + m_watcher.reset(); + m_upcoming.reset(); + m_range_planner.reset(); + + super::TearDown(); + } + + std::vector build_some_appointments() + { + const auto now = m_state->clock->localtime(); + auto tomorrow = g_date_time_add_days (now.get(), 1); + auto tomorrow_begin = g_date_time_add_full (tomorrow, 0, 0, 0, + -g_date_time_get_hour(tomorrow), + -g_date_time_get_minute(tomorrow), + -g_date_time_get_seconds(tomorrow)); + auto tomorrow_end = g_date_time_add_full (tomorrow_begin, 0, 0, 1, 0, 0, -1); + + Appointment a1; // an alarm clock appointment + a1.color = "red"; + a1.summary = "Alarm"; + a1.summary = "http://www.example.com/"; + a1.uid = "example"; + a1.has_alarms = true; + a1.begin = tomorrow_begin; + a1.end = tomorrow_end; + + auto ubermorgen_begin = g_date_time_add_days (tomorrow, 1); + auto ubermorgen_end = g_date_time_add_full (tomorrow_begin, 0, 0, 1, 0, 0, -1); + + Appointment a2; // a non-alarm appointment + a2.color = "green"; + a2.summary = "Other Text"; + a2.summary = "http://www.monkey.com/"; + a2.uid = "monkey"; + a2.has_alarms = false; + a2.begin = ubermorgen_begin; + a2.end = ubermorgen_end; + + // cleanup + g_date_time_unref(ubermorgen_end); + g_date_time_unref(ubermorgen_begin); + g_date_time_unref(tomorrow_end); + g_date_time_unref(tomorrow_begin); + g_date_time_unref(tomorrow); + + return std::vector({a1, a2}); + } +}; + +/*** +**** +***/ + +TEST_F(AlarmQueueFixture, AppointmentsChanged) +{ + // Add some appointments to the planner. + // One of these matches our state's localtime, so that should get triggered. + std::vector a = build_some_appointments(); + a[0].begin = m_state->clock->localtime(); + m_range_planner->appointments().set(a); + + // Confirm that it got fired + EXPECT_EQ(1, m_triggered.size()); + EXPECT_EQ(a[0].uid, m_triggered[0]); +} + + +TEST_F(AlarmQueueFixture, TimeChanged) +{ + // Add some appointments to the planner. + // Neither of these match the state's localtime, so nothing should be triggered. + std::vector a = build_some_appointments(); + m_range_planner->appointments().set(a); + EXPECT_TRUE(m_triggered.empty()); + + // Set the state's clock to a time that matches one of the appointments(). + // That appointment should get triggered. + m_mock_state->mock_clock->set_localtime(a[1].begin); + EXPECT_EQ(1, m_triggered.size()); + EXPECT_EQ(a[1].uid, m_triggered[0]); +} + + +TEST_F(AlarmQueueFixture, MoreThanOne) +{ + const auto now = m_state->clock->localtime(); + std::vector a = build_some_appointments(); + a[0].begin = a[1].begin = now; + m_range_planner->appointments().set(a); + + EXPECT_EQ(2, m_triggered.size()); + EXPECT_EQ(a[0].uid, m_triggered[0]); + EXPECT_EQ(a[1].uid, m_triggered[1]); +} + + +TEST_F(AlarmQueueFixture, NoDuplicates) +{ + // Setup: add an appointment that gets triggered. + const auto now = m_state->clock->localtime(); + const std::vector appointments = build_some_appointments(); + std::vector a; + a.push_back(appointments[0]); + a[0].begin = now; + m_range_planner->appointments().set(a); + EXPECT_EQ(1, m_triggered.size()); + EXPECT_EQ(a[0].uid, m_triggered[0]); + + // Now change the appointment vector by adding one to it. + // Confirm that the AlarmQueue doesn't re-trigger a[0] + a.push_back(appointments[1]); + m_range_planner->appointments().set(a); + EXPECT_EQ(1, m_triggered.size()); + EXPECT_EQ(a[0].uid, m_triggered[0]); +} diff --git a/tests/test-clock-watcher.cpp b/tests/test-clock-watcher.cpp deleted file mode 100644 index 2425fe8..0000000 --- a/tests/test-clock-watcher.cpp +++ /dev/null @@ -1,172 +0,0 @@ -/* - * Copyright 2014 Canonical Ltd. - * - * This program is free software: you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 3, as published - * by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranties of - * MERCHANTABILITY, SATISFACTORY QUALITY, 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 this program. If not, see . - * - * Authors: - * Charles Kerr - */ - -#include - -#include - -#include "state-fixture.h" - -using namespace unity::indicator::datetime; - -class ClockWatcherFixture: public StateFixture -{ -private: - - typedef StateFixture super; - -protected: - - std::vector m_triggered; - std::unique_ptr m_watcher; - std::shared_ptr m_range_planner; - std::shared_ptr m_upcoming; - - void SetUp() - { - super::SetUp(); - - m_range_planner.reset(new MockRangePlanner); - m_upcoming.reset(new UpcomingPlanner(m_range_planner, m_state->clock->localtime())); - m_watcher.reset(new ClockWatcherImpl(m_state->clock, m_upcoming)); - m_watcher->alarm_reached().connect([this](const Appointment& appt){ - m_triggered.push_back(appt.uid); - }); - - EXPECT_TRUE(m_triggered.empty()); - } - - void TearDown() - { - m_triggered.clear(); - m_watcher.reset(); - m_upcoming.reset(); - m_range_planner.reset(); - - super::TearDown(); - } - - std::vector build_some_appointments() - { - const auto now = m_state->clock->localtime(); - auto tomorrow = g_date_time_add_days (now.get(), 1); - auto tomorrow_begin = g_date_time_add_full (tomorrow, 0, 0, 0, - -g_date_time_get_hour(tomorrow), - -g_date_time_get_minute(tomorrow), - -g_date_time_get_seconds(tomorrow)); - auto tomorrow_end = g_date_time_add_full (tomorrow_begin, 0, 0, 1, 0, 0, -1); - - Appointment a1; // an alarm clock appointment - a1.color = "red"; - a1.summary = "Alarm"; - a1.summary = "http://www.example.com/"; - a1.uid = "example"; - a1.has_alarms = true; - a1.begin = tomorrow_begin; - a1.end = tomorrow_end; - - auto ubermorgen_begin = g_date_time_add_days (tomorrow, 1); - auto ubermorgen_end = g_date_time_add_full (tomorrow_begin, 0, 0, 1, 0, 0, -1); - - Appointment a2; // a non-alarm appointment - a2.color = "green"; - a2.summary = "Other Text"; - a2.summary = "http://www.monkey.com/"; - a2.uid = "monkey"; - a2.has_alarms = false; - a2.begin = ubermorgen_begin; - a2.end = ubermorgen_end; - - // cleanup - g_date_time_unref(ubermorgen_end); - g_date_time_unref(ubermorgen_begin); - g_date_time_unref(tomorrow_end); - g_date_time_unref(tomorrow_begin); - g_date_time_unref(tomorrow); - - return std::vector({a1, a2}); - } -}; - -/*** -**** -***/ - -TEST_F(ClockWatcherFixture, AppointmentsChanged) -{ - // Add some appointments to the planner. - // One of these matches our state's localtime, so that should get triggered. - std::vector a = build_some_appointments(); - a[0].begin = m_state->clock->localtime(); - m_range_planner->appointments().set(a); - - // Confirm that it got fired - EXPECT_EQ(1, m_triggered.size()); - EXPECT_EQ(a[0].uid, m_triggered[0]); -} - - -TEST_F(ClockWatcherFixture, TimeChanged) -{ - // Add some appointments to the planner. - // Neither of these match the state's localtime, so nothing should be triggered. - std::vector a = build_some_appointments(); - m_range_planner->appointments().set(a); - EXPECT_TRUE(m_triggered.empty()); - - // Set the state's clock to a time that matches one of the appointments(). - // That appointment should get triggered. - m_mock_state->mock_clock->set_localtime(a[1].begin); - EXPECT_EQ(1, m_triggered.size()); - EXPECT_EQ(a[1].uid, m_triggered[0]); -} - - -TEST_F(ClockWatcherFixture, MoreThanOne) -{ - const auto now = m_state->clock->localtime(); - std::vector a = build_some_appointments(); - a[0].begin = a[1].begin = now; - m_range_planner->appointments().set(a); - - EXPECT_EQ(2, m_triggered.size()); - EXPECT_EQ(a[0].uid, m_triggered[0]); - EXPECT_EQ(a[1].uid, m_triggered[1]); -} - - -TEST_F(ClockWatcherFixture, NoDuplicates) -{ - // Setup: add an appointment that gets triggered. - const auto now = m_state->clock->localtime(); - const std::vector appointments = build_some_appointments(); - std::vector a; - a.push_back(appointments[0]); - a[0].begin = now; - m_range_planner->appointments().set(a); - EXPECT_EQ(1, m_triggered.size()); - EXPECT_EQ(a[0].uid, m_triggered[0]); - - // Now change the appointment vector by adding one to it. - // Confirm that the ClockWatcher doesn't re-trigger a[0] - a.push_back(appointments[1]); - m_range_planner->appointments().set(a); - EXPECT_EQ(1, m_triggered.size()); - EXPECT_EQ(a[0].uid, m_triggered[0]); -} -- cgit v1.2.3