diff options
Diffstat (limited to 'tests')
-rw-r--r-- | tests/CMakeLists.txt | 27 | ||||
-rw-r--r-- | tests/Makefile.am.strings | 38 | ||||
-rw-r--r-- | tests/actions-mock.h | 88 | ||||
-rw-r--r-- | tests/glib-fixture.h | 85 | ||||
-rw-r--r-- | tests/planner-mock.c | 34 | ||||
-rw-r--r-- | tests/state-fixture.h | 75 | ||||
-rw-r--r-- | tests/test-actions.cc | 173 | ||||
-rw-r--r-- | tests/test-clock.cc | 176 | ||||
-rw-r--r-- | tests/test-core.cc | 148 | ||||
-rw-r--r-- | tests/test-dbus-fixture.h | 100 | ||||
-rw-r--r-- | tests/test-formatter.cc | 61 | ||||
-rw-r--r-- | tests/test-indicator.cc | 92 | ||||
-rw-r--r-- | tests/test-locations.cc | 136 | ||||
-rw-r--r-- | tests/test-menus.cc | 406 | ||||
-rw-r--r-- | tests/test-planner-eds.cc | 70 | ||||
-rw-r--r-- | tests/test-planner.cc | 49 | ||||
-rw-r--r-- | tests/test-skew.cc | 209 | ||||
-rw-r--r-- | tests/test-timezone-file.cc | 60 | ||||
-rw-r--r-- | tests/test-timezone-geoclue.cc | 28 | ||||
-rw-r--r-- | tests/test-timezones.cc | 83 | ||||
-rw-r--r-- | tests/test-utils.cc | 153 |
21 files changed, 1301 insertions, 990 deletions
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index a424858..fb55f5a 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -32,12 +32,6 @@ include_directories (${DBUSTEST_INCLUDE_DIRS}) add_definitions (-DSANDBOX="${CMAKE_CURRENT_BINARY_DIR}") -# test-core -set (TEST_NAME test-core) -add_executable (${TEST_NAME} ${TEST_NAME}.cc) -add_test (${TEST_NAME} ${TEST_NAME}) -target_link_libraries (${TEST_NAME} indicatordatetimeservice gtest ${SERVICE_DEPS_LIBRARIES} ${GTEST_LIBS}) - # test-timezone-file set (TEST_NAME test-timezone-file) add_executable (${TEST_NAME} ${TEST_NAME}.cc) @@ -76,18 +70,31 @@ add_test (${TEST_NAME} ${TEST_NAME}) add_dependencies (${TEST_NAME} libindicatordatetimeservice) target_link_libraries (${TEST_NAME} indicatordatetimeservice gtest ${SERVICE_DEPS_LIBRARIES} ${GTEST_LIBS}) -# test-planner-eds -set (TEST_NAME test-planner-eds) +# test-locations +set (TEST_NAME test-locations) add_executable (${TEST_NAME} ${TEST_NAME}.cc) add_test (${TEST_NAME} ${TEST_NAME}) add_dependencies (${TEST_NAME} libindicatordatetimeservice) target_link_libraries (${TEST_NAME} indicatordatetimeservice gtest ${SERVICE_DEPS_LIBRARIES} ${GTEST_LIBS}) -# test-locations -set (TEST_NAME test-locations) +# test-actions +set (TEST_NAME test-actions) +add_executable (${TEST_NAME} ${TEST_NAME}.cc) +add_test (${TEST_NAME} ${TEST_NAME}) +add_dependencies (${TEST_NAME} libindicatordatetimeservice) +target_link_libraries (${TEST_NAME} indicatordatetimeservice gtest ${SERVICE_DEPS_LIBRARIES} ${GTEST_LIBS}) + +# test-menus +set (TEST_NAME test-menus) add_executable (${TEST_NAME} ${TEST_NAME}.cc) add_test (${TEST_NAME} ${TEST_NAME}) add_dependencies (${TEST_NAME} libindicatordatetimeservice) target_link_libraries (${TEST_NAME} indicatordatetimeservice gtest ${SERVICE_DEPS_LIBRARIES} ${GTEST_LIBS}) +# test-desktop +#set (TEST_NAME test-desktop) +#add_executable (${TEST_NAME} ${TEST_NAME}.cc) +#add_test (${TEST_NAME} ${TEST_NAME}) +#add_dependencies (${TEST_NAME} libindicatordatetimeservice) +#target_link_libraries (${TEST_NAME} indicatordatetimeservice gtest ${SERVICE_DEPS_LIBRARIES} ${GTEST_LIBS}) diff --git a/tests/Makefile.am.strings b/tests/Makefile.am.strings deleted file mode 100644 index 4a89e8f..0000000 --- a/tests/Makefile.am.strings +++ /dev/null @@ -1,38 +0,0 @@ -TESTS += \ - test-ellipsis \ - test-space-ellipsis \ - test-ascii-quotes - -##### -# Tests for there being proper ellipsis instead of three periods in a row -##### -test-ellipsis: $(top_srcdir)/po - @echo "#!/bin/bash" > $@ - @echo "(cd $(top_srcdir)/po && make $(GETTEXT_PACKAGE).pot)" >> $@ - @echo "grep -c -e \"^msgid.*\.\.\.\\\"\" $(top_srcdir)/po/$(GETTEXT_PACKAGE).pot > /dev/null && echo \"Ellipsis found in user visible strings\" >&2 && exit 1" >> $@ - @echo "exit 0" >> $@ - @chmod +x $@ - -##### -# Tests for there being a space before an ellipsis -##### -test-space-ellipsis: $(top_srcdir)/po - @echo "#!/bin/bash" > $@ - @echo "(cd $(top_srcdir)/po && make $(GETTEXT_PACKAGE).pot)" >> $@ - @echo "grep -c -e \"^msgid.* …\\\"\" $(top_srcdir)/po/$(GETTEXT_PACKAGE).pot > /dev/null && echo \"Space before ellipsis found in user visible strings\" >&2 && exit 1" >> $@ - @echo "exit 0" >> $@ - @chmod +x $@ - -##### -# Tests for ASCII quote types -##### -test-ascii-quotes: $(top_srcdir)/po - @echo "#!/bin/bash" > $@ - @echo "(cd $(top_srcdir)/po && make $(GETTEXT_PACKAGE).pot)" >> $@ - @echo "grep -c -e \"^msgid \\\".*'.*\\\"\" $(top_srcdir)/po/$(GETTEXT_PACKAGE).pot > /dev/null && echo \"ASCII apostrophe found in user visible strings\" >&2 && exit 1" >> $@ - @echo "grep -c -e \"^msgid \\\".*\\\".*\\\"\" $(top_srcdir)/po/$(GETTEXT_PACKAGE).pot > /dev/null && echo \"ASCII quote found in user visible strings\" >&2 && exit 1" >> $@ - @echo "grep -c -e \"^msgid \\\".*\\\`.*\\\"\" $(top_srcdir)/po/$(GETTEXT_PACKAGE).pot > /dev/null && echo \"ASCII backtick found in user visible strings\" >&2 && exit 1" >> $@ - @echo "exit 0" >> $@ - @chmod +x $@ - -CLEANFILES += $(TESTS) diff --git a/tests/actions-mock.h b/tests/actions-mock.h new file mode 100644 index 0000000..112900b --- /dev/null +++ b/tests/actions-mock.h @@ -0,0 +1,88 @@ +/* + * Copyright 2013 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 <http://www.gnu.org/licenses/>. + * + * Authors: + * Charles Kerr <charles.kerr@canonical.com> + */ + +#ifndef INDICATOR_DATETIME_ACTIONS_MOCK_H +#define INDICATOR_DATETIME_ACTIONS_MOCK_H + +#include <datetime/actions.h> + +#include <set> + +namespace unity { +namespace indicator { +namespace datetime { + +class MockActions: public Actions +{ +public: + MockActions(std::shared_ptr<State>& state_in): Actions(state_in) {} + ~MockActions() =default; + + enum Action { OpenDesktopSettings, OpenPhoneSettings, OpenPhoneClockApp, + OpenPlanner, OpenPlannerAt, OpenAppointment, + SetLocation, SetCalendarDate }; + const std::vector<Action>& history() const { return m_history; } + const DateTime& date_time() const { return m_date_time; } + const std::string& zone() const { return m_zone; } + const std::string& name() const { return m_name; } + const std::string& url() const { return m_url; } + void clear() { m_history.clear(); m_zone.clear(); m_name.clear(); } + + void open_desktop_settings() { m_history.push_back(OpenDesktopSettings); } + + void open_phone_settings() { m_history.push_back(OpenPhoneSettings); } + + void open_phone_clock_app() { m_history.push_back(OpenPhoneClockApp); } + + void open_planner() { m_history.push_back(OpenPlanner); } + + void open_planner_at(const DateTime& date_time_) { + m_history.push_back(OpenPlannerAt); + m_date_time = date_time_; + } + + void set_location(const std::string& zone_, const std::string& name_) { + m_history.push_back(SetLocation); + m_zone = zone_; + m_name = name_; + } + + void open_appointment(const std::string& url_) { + m_history.push_back(OpenAppointment); + m_url = url_; + } + + void set_calendar_date(const DateTime& date_time_) { + m_history.push_back(SetCalendarDate); + m_date_time = date_time_; + } + +private: + std::string m_url; + std::string m_zone; + std::string m_name; + DateTime m_date_time; + std::vector<Action> m_history; +}; + +} // namespace datetime +} // namespace indicator +} // namespace unity + +#endif // INDICATOR_DATETIME_ACTIONS_MOCK_H diff --git a/tests/glib-fixture.h b/tests/glib-fixture.h index 043b7e3..3f517d4 100644 --- a/tests/glib-fixture.h +++ b/tests/glib-fixture.h @@ -25,6 +25,8 @@ #include <gtest/gtest.h> +#include <locale.h> // setlocale() + class GlibFixture : public ::testing::Test { private: @@ -35,96 +37,101 @@ class GlibFixture : public ::testing::Test std::map<GLogLevelFlags,int> logCounts; - void testLogCount (GLogLevelFlags log_level, int expected G_GNUC_UNUSED) + void testLogCount(GLogLevelFlags log_level, int /*expected*/) { #if 0 - EXPECT_EQ (expected, logCounts[log_level]); + EXPECT_EQ(expected, logCounts[log_level]); #endif - logCounts.erase (log_level); + logCounts.erase(log_level); } private: - static void default_log_handler (const gchar * log_domain, - GLogLevelFlags log_level, - const gchar * message, - gpointer self) + static void default_log_handler(const gchar * log_domain, + GLogLevelFlags log_level, + const gchar * message, + gpointer self) { - g_print ("%s - %d - %s\n", log_domain, (int)log_level, message); + g_print("%s - %d - %s\n", log_domain, (int)log_level, message); static_cast<GlibFixture*>(self)->logCounts[log_level]++; } protected: - virtual void SetUp () + virtual void SetUp() { - loop = g_main_loop_new (NULL, FALSE); + setlocale(LC_ALL, ""); + + loop = g_main_loop_new(nullptr, false); - //g_log_set_default_handler (default_log_handler, this); + //g_log_set_default_handler(default_log_handler, this); // only use local, temporary settings - g_setenv ("GSETTINGS_SCHEMA_DIR", SCHEMA_DIR, TRUE); - g_setenv ("GSETTINGS_BACKEND", "memory", TRUE); - g_debug ("SCHEMA_DIR is %s", SCHEMA_DIR); + g_assert(g_setenv("GSETTINGS_SCHEMA_DIR", SCHEMA_DIR, true)); + g_assert(g_setenv("GSETTINGS_BACKEND", "memory", true)); + g_debug("SCHEMA_DIR is %s", SCHEMA_DIR); + + g_unsetenv("DISPLAY"); + } virtual void TearDown() { #if 0 // confirm there aren't any unexpected log messages - EXPECT_EQ (0, logCounts[G_LOG_LEVEL_ERROR]); - EXPECT_EQ (0, logCounts[G_LOG_LEVEL_CRITICAL]); - EXPECT_EQ (0, logCounts[G_LOG_LEVEL_WARNING]); - EXPECT_EQ (0, logCounts[G_LOG_LEVEL_MESSAGE]); - EXPECT_EQ (0, logCounts[G_LOG_LEVEL_INFO]); + EXPECT_EQ(0, logCounts[G_LOG_LEVEL_ERROR]); + EXPECT_EQ(0, logCounts[G_LOG_LEVEL_CRITICAL]); + EXPECT_EQ(0, logCounts[G_LOG_LEVEL_WARNING]); + EXPECT_EQ(0, logCounts[G_LOG_LEVEL_MESSAGE]); + EXPECT_EQ(0, logCounts[G_LOG_LEVEL_INFO]); #endif // revert to glib's log handler - //g_log_set_default_handler (realLogHandler, this); + //g_log_set_default_handler(realLogHandler, this); - g_clear_pointer (&loop, g_main_loop_unref); + g_clear_pointer(&loop, g_main_loop_unref); } private: static gboolean - wait_for_signal__timeout (gpointer name) + wait_for_signal__timeout(gpointer name) { - g_error ("%s: timed out waiting for signal '%s'", G_STRLOC, (char*)name); + g_error("%s: timed out waiting for signal '%s'", G_STRLOC, (char*)name); return G_SOURCE_REMOVE; } static gboolean - wait_msec__timeout (gpointer loop) + wait_msec__timeout(gpointer loop) { - g_main_loop_quit (static_cast<GMainLoop*>(loop)); + g_main_loop_quit(static_cast<GMainLoop*>(loop)); return G_SOURCE_CONTINUE; } protected: /* convenience func to loop while waiting for a GObject's signal */ - void wait_for_signal (gpointer o, const gchar * signal, const int timeout_seconds=5) + void wait_for_signal(gpointer o, const gchar * signal, const int timeout_seconds=5) { // wait for the signal or for timeout, whichever comes first - const auto handler_id = g_signal_connect_swapped (o, signal, - G_CALLBACK(g_main_loop_quit), - loop); - const auto timeout_id = g_timeout_add_seconds (timeout_seconds, - wait_for_signal__timeout, - loop); - g_main_loop_run (loop); - g_source_remove (timeout_id); - g_signal_handler_disconnect (o, handler_id); + const auto handler_id = g_signal_connect_swapped(o, signal, + G_CALLBACK(g_main_loop_quit), + loop); + const auto timeout_id = g_timeout_add_seconds(timeout_seconds, + wait_for_signal__timeout, + loop); + g_main_loop_run(loop); + g_source_remove(timeout_id); + g_signal_handler_disconnect(o, handler_id); } /* convenience func to loop for N msec */ - void wait_msec (int msec=50) + void wait_msec(int msec=50) { - const auto id = g_timeout_add (msec, wait_msec__timeout, loop); - g_main_loop_run (loop); - g_source_remove (id); + const auto id = g_timeout_add(msec, wait_msec__timeout, loop); + g_main_loop_run(loop); + g_source_remove(id); } GMainLoop * loop; diff --git a/tests/planner-mock.c b/tests/planner-mock.c index e67ad7e..df5413e 100644 --- a/tests/planner-mock.c +++ b/tests/planner-mock.c @@ -39,7 +39,7 @@ G_DEFINE_TYPE (IndicatorDatetimePlannerMock, static void my_get_appointments (IndicatorDatetimePlanner * planner, GDateTime * begin_datetime, - GDateTime * end_datetime G_GNUC_UNUSED, + GDateTime * /*end_datetime*/, GAsyncReadyCallback callback, gpointer user_data) { @@ -88,34 +88,34 @@ my_get_appointments (IndicatorDatetimePlanner * planner, } static GSList * -my_get_appointments_finish (IndicatorDatetimePlanner * self G_GNUC_UNUSED, - GAsyncResult * res, - GError ** error) +my_get_appointments_finish (IndicatorDatetimePlanner* /*self*/, + GAsyncResult* res, + GError** error) { - return g_task_propagate_pointer (G_TASK(res), error); + return g_task_propagate_pointer(G_TASK(res), error); } static gboolean -my_is_configured (IndicatorDatetimePlanner * planner) +my_is_configured(IndicatorDatetimePlanner* planner) { IndicatorDatetimePlannerMock * self; - self = INDICATOR_DATETIME_PLANNER_MOCK (planner); + self = INDICATOR_DATETIME_PLANNER_MOCK(planner); return self->priv->is_configured; } static void -my_activate (IndicatorDatetimePlanner * self G_GNUC_UNUSED) +my_activate(IndicatorDatetimePlanner* /*self*/) { - g_message ("%s %s", G_STRLOC, G_STRFUNC); + g_message("%s %s", G_STRLOC, G_STRFUNC); } static void -my_activate_time (IndicatorDatetimePlanner * self G_GNUC_UNUSED, - GDateTime * activate_time) +my_activate_time(IndicatorDatetimePlanner* /*self*/, + GDateTime* activate_time) { - gchar * str = g_date_time_format (activate_time, "%F %T"); - g_message ("%s %s: %s", G_STRLOC, G_STRFUNC, str); - g_free (str); + gchar * str = g_date_time_format(activate_time, "%F %T"); + g_message("%s %s: %s", G_STRLOC, G_STRFUNC, str); + g_free(str); } /*** @@ -123,9 +123,9 @@ my_activate_time (IndicatorDatetimePlanner * self G_GNUC_UNUSED, ***/ static void -my_dispose (GObject * o) +my_dispose(GObject * o) { - G_OBJECT_CLASS (indicator_datetime_planner_mock_parent_class)->dispose (o); + G_OBJECT_CLASS(indicator_datetime_planner_mock_parent_class)->dispose(o); } /*** @@ -133,7 +133,7 @@ my_dispose (GObject * o) ***/ static void -indicator_datetime_planner_mock_class_init (IndicatorDatetimePlannerMockClass * klass) +indicator_datetime_planner_mock_class_init(IndicatorDatetimePlannerMockClass* klass) { GObjectClass * object_class; IndicatorDatetimePlannerClass * planner_class; diff --git a/tests/state-fixture.h b/tests/state-fixture.h new file mode 100644 index 0000000..0286ea9 --- /dev/null +++ b/tests/state-fixture.h @@ -0,0 +1,75 @@ +/* + * Copyright 2013 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 <http://www.gnu.org/licenses/>. + * + * Authors: + * Charles Kerr <charles.kerr@canonical.com> + */ + +#include "glib-fixture.h" +#include "actions-mock.h" + +#include <datetime/clock-mock.h> +#include <datetime/formatter.h> +#include <datetime/locations.h> +#include <datetime/menu.h> +#include <datetime/planner-mock.h> +#include <datetime/service.h> +#include <datetime/state.h> +#include <datetime/timezones.h> + +using namespace unity::indicator::datetime; + +class StateFixture: public GlibFixture +{ +private: + typedef GlibFixture super; + +protected: + std::shared_ptr<MockClock> m_clock; + std::shared_ptr<State> m_state; + std::shared_ptr<MockActions> m_mock_actions; + std::shared_ptr<Actions> m_actions; + + virtual void SetUp() + { + super::SetUp(); + + // first, build a mock backend state + const DateTime now = DateTime::NowLocal(); + m_clock.reset(new MockClock(now)); + m_state.reset(new State); + m_state->timezones.reset(new Timezones); + m_state->clock = std::dynamic_pointer_cast<Clock>(m_clock); + m_state->planner.reset(new MockPlanner); + m_state->planner->time = now; + m_state->locations.reset(new Locations); + m_state->calendar_day = now; + + // build the actions on top of the state + m_mock_actions.reset(new MockActions(m_state)); + m_actions = std::dynamic_pointer_cast<Actions>(m_mock_actions); + } + + virtual void TearDown() + { + m_actions.reset(); + m_mock_actions.reset(); + m_state.reset(); + m_clock.reset(); + + super::TearDown(); + } +}; + diff --git a/tests/test-actions.cc b/tests/test-actions.cc new file mode 100644 index 0000000..4329608 --- /dev/null +++ b/tests/test-actions.cc @@ -0,0 +1,173 @@ +/* + * Copyright 2013 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 <http://www.gnu.org/licenses/>. + * + * Authors: + * Charles Kerr <charles.kerr@canonical.com> + */ + +#include <datetime/actions.h> + +#include "state-fixture.h" + +using namespace unity::indicator::datetime; + +typedef StateFixture ActionsFixture; + +TEST_F(ActionsFixture, ActionsExist) +{ + EXPECT_TRUE(m_actions != nullptr); + + const char* names[] = { "desktop-header", + "calendar", + "set-location", + "activate-planner", + "activate-appointment", + "activate-phone-settings", + "activate-phone-clock-app", + "activate-desktop-settings" }; + for(const auto& name: names) + { + EXPECT_TRUE(g_action_group_has_action(m_actions->action_group(), name)); + } +} + +TEST_F(ActionsFixture, ActivateDesktopSettings) +{ + const auto action_name = "activate-desktop-settings"; + const auto expected_action = MockActions::OpenDesktopSettings; + + auto action_group = m_actions->action_group(); + auto history = m_mock_actions->history(); + EXPECT_EQ(0, history.size()); + EXPECT_TRUE(g_action_group_has_action(action_group, action_name)); + + g_action_group_activate_action(action_group, action_name, nullptr); + history = m_mock_actions->history(); + EXPECT_EQ(1, history.size()); + EXPECT_EQ(expected_action, history[0]); +} + +TEST_F(ActionsFixture, ActivatePhoneSettings) +{ + const auto action_name = "activate-phone-settings"; + const auto expected_action = MockActions::OpenPhoneSettings; + + auto action_group = m_actions->action_group(); + EXPECT_TRUE(m_mock_actions->history().empty()); + EXPECT_TRUE(g_action_group_has_action(action_group, action_name)); + + g_action_group_activate_action(action_group, action_name, nullptr); + auto history = m_mock_actions->history(); + EXPECT_EQ(1, history.size()); + EXPECT_EQ(expected_action, history[0]); +} + +TEST_F(ActionsFixture, ActivatePhoneClockApp) +{ + const auto action_name = "activate-phone-clock-app"; + const auto expected_action = MockActions::OpenPhoneClockApp; + + auto action_group = m_actions->action_group(); + EXPECT_TRUE(m_mock_actions->history().empty()); + EXPECT_TRUE(g_action_group_has_action(action_group, action_name)); + + g_action_group_activate_action(action_group, action_name, nullptr); + auto history = m_mock_actions->history(); + EXPECT_EQ(1, history.size()); + EXPECT_EQ(expected_action, history[0]); +} + +TEST_F(ActionsFixture, ActivatePlanner) +{ + const auto action_name = "activate-planner"; + auto action_group = m_actions->action_group(); + EXPECT_TRUE(m_mock_actions->history().empty()); + EXPECT_TRUE(g_action_group_has_action(action_group, action_name)); + + const auto expected_action = MockActions::OpenPlanner; + auto v = g_variant_new_int64(0); + g_action_group_activate_action(action_group, action_name, v); + auto history = m_mock_actions->history(); + EXPECT_EQ(1, history.size()); + EXPECT_EQ(expected_action, history[0]); +} + +TEST_F(ActionsFixture, ActivatePlannerAt) +{ + const auto action_name = "activate-planner"; + auto action_group = m_actions->action_group(); + EXPECT_TRUE(m_mock_actions->history().empty()); + EXPECT_TRUE(g_action_group_has_action(action_group, action_name)); + + const auto now = DateTime::NowLocal(); + auto v = g_variant_new_int64(now.to_unix()); + g_action_group_activate_action(action_group, action_name, v); + const auto a = MockActions::OpenPlannerAt; + EXPECT_EQ(std::vector<MockActions::Action>({a}), m_mock_actions->history()); + EXPECT_EQ(now.to_unix(), m_mock_actions->date_time().to_unix()); +} + +TEST_F(ActionsFixture, SetLocation) +{ + const auto action_name = "set-location"; + auto action_group = m_actions->action_group(); + EXPECT_TRUE(m_mock_actions->history().empty()); + EXPECT_TRUE(g_action_group_has_action(action_group, action_name)); + + auto v = g_variant_new_string("America/Chicago Oklahoma City"); + g_action_group_activate_action(action_group, action_name, v); + const auto expected_action = MockActions::SetLocation; + ASSERT_EQ(1, m_mock_actions->history().size()); + EXPECT_EQ(expected_action, m_mock_actions->history()[0]); + EXPECT_EQ("America/Chicago", m_mock_actions->zone()); + EXPECT_EQ("Oklahoma City", m_mock_actions->name()); +} + +TEST_F(ActionsFixture, SetCalendarDate) +{ + const auto action_name = "calendar"; + auto action_group = m_actions->action_group(); + EXPECT_TRUE(m_mock_actions->history().empty()); + EXPECT_TRUE(g_action_group_has_action(action_group, action_name)); + + auto unix = m_state->clock->localtime().to_unix(); + auto v = g_variant_new_int64(unix); + g_action_group_activate_action(action_group, action_name, v); + const auto expected_action = MockActions::SetCalendarDate; + ASSERT_EQ(1, m_mock_actions->history().size()); + EXPECT_EQ(expected_action, m_mock_actions->history()[0]); + EXPECT_EQ(unix, m_mock_actions->date_time().to_unix()); +} + +TEST_F(ActionsFixture, OpenAppointment) +{ + Appointment appt; + appt.uid = "some arbitrary uid"; + appt.url = "http://www.canonical.com/"; + m_state->planner->upcoming.set(std::vector<Appointment>({appt})); + + const auto action_name = "activate-appointment"; + auto action_group = m_actions->action_group(); + EXPECT_TRUE(m_mock_actions->history().empty()); + EXPECT_TRUE(g_action_group_has_action(action_group, action_name)); + + auto v = g_variant_new_string(appt.uid.c_str()); + g_action_group_activate_action(action_group, action_name, v); + const auto a = MockActions::OpenAppointment; + ASSERT_EQ(1, m_mock_actions->history().size()); + ASSERT_EQ(a, m_mock_actions->history()[0]); + EXPECT_EQ(appt.url, m_mock_actions->url()); +} + diff --git a/tests/test-clock.cc b/tests/test-clock.cc index a0b4360..7d3a35e 100644 --- a/tests/test-clock.cc +++ b/tests/test-clock.cc @@ -37,27 +37,27 @@ class ClockFixture: public GlibFixture typedef GlibFixture super; static void - on_bus_opened (GObject * o G_GNUC_UNUSED, GAsyncResult * res, gpointer gself) + on_bus_opened(GObject* /*object*/, GAsyncResult* res, gpointer gself) { auto self = static_cast<ClockFixture*>(gself); GError * err = 0; - self->system_bus = g_bus_get_finish (res, &err); - g_assert_no_error (err); + self->system_bus = g_bus_get_finish(res, &err); + g_assert_no_error(err); - g_main_loop_quit (self->loop); + g_main_loop_quit(self->loop); } static void - on_bus_closed (GObject * o G_GNUC_UNUSED, GAsyncResult * res, gpointer gself) + on_bus_closed(GObject* /*object*/, GAsyncResult* res, gpointer gself) { auto self = static_cast<ClockFixture*>(gself); GError * err = 0; - g_dbus_connection_close_finish (self->system_bus, res, &err); - g_assert_no_error (err); + g_dbus_connection_close_finish(self->system_bus, res, &err); + g_assert_no_error(err); - g_main_loop_quit (self->loop); + g_main_loop_quit(self->loop); } protected: @@ -65,41 +65,41 @@ class ClockFixture: public GlibFixture GTestDBus * test_dbus; GDBusConnection * system_bus; - virtual void SetUp () + virtual void SetUp() { - super::SetUp (); + super::SetUp(); // pull up a test dbus - test_dbus = g_test_dbus_new (G_TEST_DBUS_NONE); - g_test_dbus_up (test_dbus); - const char * address = g_test_dbus_get_bus_address (test_dbus); - g_setenv ("DBUS_SYSTEM_BUS_ADDRESS", address, TRUE); - g_debug ("test_dbus's address is %s", address); + test_dbus = g_test_dbus_new(G_TEST_DBUS_NONE); + g_test_dbus_up(test_dbus); + const char * address = g_test_dbus_get_bus_address(test_dbus); + g_setenv("DBUS_SYSTEM_BUS_ADDRESS", address, TRUE); + g_debug("test_dbus's address is %s", address); // wait for the GDBusConnection before returning - g_bus_get (G_BUS_TYPE_SYSTEM, nullptr, on_bus_opened, this); - g_main_loop_run (loop); + g_bus_get(G_BUS_TYPE_SYSTEM, nullptr, on_bus_opened, this); + g_main_loop_run(loop); } - virtual void TearDown () + virtual void TearDown() { // close the system bus - g_dbus_connection_close (system_bus, nullptr, on_bus_closed, this); - g_main_loop_run (loop); - g_clear_object (&system_bus); + g_dbus_connection_close(system_bus, nullptr, on_bus_closed, this); + g_main_loop_run(loop); + g_clear_object(&system_bus); // tear down the test dbus - g_test_dbus_down (test_dbus); - g_clear_object (&test_dbus); + g_test_dbus_down(test_dbus); + g_clear_object(&test_dbus); - super::TearDown (); + super::TearDown(); } public: - void emitPrepareForSleep () + void emitPrepareForSleep() { - g_dbus_connection_emit_signal (g_bus_get_sync (G_BUS_TYPE_SYSTEM, nullptr, nullptr), + g_dbus_connection_emit_signal(g_bus_get_sync(G_BUS_TYPE_SYSTEM, nullptr, nullptr), NULL, "/org/freedesktop/login1", // object path "org.freedesktop.login1.Manager", // interface @@ -115,93 +115,91 @@ class ClockFixture: public GlibFixture #define TIMEZONE_FILE (SANDBOX"/timezone") -TEST_F (ClockFixture, HelloFixture) +TEST_F(ClockFixture, HelloFixture) { - std::shared_ptr<Timezones> zones (new Timezones); + std::shared_ptr<Timezones> zones(new Timezones); zones->timezone.set("America/New_York"); - LiveClock clock (zones); + LiveClock clock(zones); #if 0 - GTimeZone * tz_nyc = g_time_zone_new (file_timezone.c_str()); - GDateTime * now_nyc = g_date_time_new_now (tz_nyc); + GTimeZone * tz_nyc = g_time_zone_new(file_timezone.c_str()); + GDateTime * now_nyc = g_date_time_new_now(tz_nyc); GDateTime * now = clock.localtime(); - EXPECT_EQ (g_date_time_get_utc_offset(now_nyc), g_date_time_get_utc_offset(now)); - EXPECT_LE (abs(g_date_time_difference(now_nyc,now)), G_USEC_PER_SEC); - g_date_time_unref (now); - g_date_time_unref (now_nyc); - g_time_zone_unref (tz_nyc); + EXPECT_EQ(g_date_time_get_utc_offset(now_nyc), g_date_time_get_utc_offset(now)); + EXPECT_LE(abs(g_date_time_difference(now_nyc,now)), G_USEC_PER_SEC); + g_date_time_unref(now); + g_date_time_unref(now_nyc); + g_time_zone_unref(tz_nyc); /// change the timezones! clock.skewDetected.connect([this](){ g_main_loop_quit(loop); }); file_timezone = "America/Los_Angeles"; - g_idle_add ([](gpointer str){ + g_idle_add([](gpointer str){ set_file(static_cast<const char*>(str)); return G_SOURCE_REMOVE; }, const_cast<char*>(file_timezone.c_str())); - g_main_loop_run (loop); + g_main_loop_run(loop); - GTimeZone * tz_la = g_time_zone_new (file_timezone.c_str()); - GDateTime * now_la = g_date_time_new_now (tz_la); + GTimeZone * tz_la = g_time_zone_new(file_timezone.c_str()); + GDateTime * now_la = g_date_time_new_now(tz_la); now = clock.localtime(); - EXPECT_EQ (g_date_time_get_utc_offset(now_la), g_date_time_get_utc_offset(now)); - EXPECT_LE (abs(g_date_time_difference(now_la,now)), G_USEC_PER_SEC); - g_date_time_unref (now); - g_date_time_unref (now_la); - g_time_zone_unref (tz_la); + EXPECT_EQ(g_date_time_get_utc_offset(now_la), g_date_time_get_utc_offset(now)); + EXPECT_LE(abs(g_date_time_difference(now_la,now)), G_USEC_PER_SEC); + g_date_time_unref(now); + g_date_time_unref(now_la); + g_time_zone_unref(tz_la); #endif } -TEST_F (ClockFixture, TimezoneChangeTriggersSkew) +TEST_F(ClockFixture, TimezoneChangeTriggersSkew) { - std::shared_ptr<Timezones> zones (new Timezones); + std::shared_ptr<Timezones> zones(new Timezones); zones->timezone.set("America/New_York"); - LiveClock clock (zones); + LiveClock clock(zones); //std::string file_timezone = "America/New_York"; - //set_file (file_timezone); - //std::shared_ptr<TimezoneDetector> detector (new TimezoneDetector(TIMEZONE_FILE)); - //LiveClock clock (detector); - - GTimeZone * tz_nyc = g_time_zone_new ("America/New_York"); - GDateTime * now_nyc = g_date_time_new_now (tz_nyc); - GDateTime * now = clock.localtime(); - EXPECT_EQ (g_date_time_get_utc_offset(now_nyc), g_date_time_get_utc_offset(now)); - EXPECT_LE (abs(g_date_time_difference(now_nyc,now)), G_USEC_PER_SEC); - g_date_time_unref (now); - g_date_time_unref (now_nyc); - g_time_zone_unref (tz_nyc); + //set_file(file_timezone); + //std::shared_ptr<TimezoneDetector> detector(new TimezoneDetector(TIMEZONE_FILE)); + //LiveClock clock(detector); + + auto tz_nyc = g_time_zone_new("America/New_York"); + auto now_nyc = g_date_time_new_now(tz_nyc); + auto now = clock.localtime(); + EXPECT_EQ(g_date_time_get_utc_offset(now_nyc), g_date_time_get_utc_offset(now.get())); + EXPECT_LE(abs(g_date_time_difference(now_nyc,now.get())), G_USEC_PER_SEC); + g_date_time_unref(now_nyc); + g_time_zone_unref(tz_nyc); /// change the timezones! clock.skewDetected.connect([this](){ - g_main_loop_quit(loop); - }); - g_idle_add ([](gpointer gs){ - static_cast<Timezones*>(gs)->timezone.set("America/Los_Angeles"); - return G_SOURCE_REMOVE; - }, zones.get()); - g_main_loop_run (loop); - - GTimeZone * tz_la = g_time_zone_new ("America/Los_Angeles"); - GDateTime * now_la = g_date_time_new_now (tz_la); + g_main_loop_quit(loop); + }); + g_idle_add([](gpointer gs){ + static_cast<Timezones*>(gs)->timezone.set("America/Los_Angeles"); + return G_SOURCE_REMOVE; + }, zones.get()); + g_main_loop_run(loop); + + auto tz_la = g_time_zone_new("America/Los_Angeles"); + auto now_la = g_date_time_new_now(tz_la); now = clock.localtime(); - EXPECT_EQ (g_date_time_get_utc_offset(now_la), g_date_time_get_utc_offset(now)); - EXPECT_LE (abs(g_date_time_difference(now_la,now)), G_USEC_PER_SEC); - g_date_time_unref (now); - g_date_time_unref (now_la); - g_time_zone_unref (tz_la); + EXPECT_EQ(g_date_time_get_utc_offset(now_la), g_date_time_get_utc_offset(now.get())); + EXPECT_LE(abs(g_date_time_difference(now_la,now.get())), G_USEC_PER_SEC); + g_date_time_unref(now_la); + g_time_zone_unref(tz_la); } /** * Confirm that a "PrepareForSleep" event wil trigger a skew event */ -TEST_F (ClockFixture, SleepTriggersSkew) +TEST_F(ClockFixture, SleepTriggersSkew) { - std::shared_ptr<Timezones> zones (new Timezones); + std::shared_ptr<Timezones> zones(new Timezones); zones->timezone.set("America/New_York"); - LiveClock clock (zones); - wait_msec (500); // wait for the bus to set up + LiveClock clock(zones); + wait_msec(500); // wait for the bus to set up bool skewed = false; clock.skewDetected.connect([&skewed, this](){ @@ -210,12 +208,12 @@ TEST_F (ClockFixture, SleepTriggersSkew) return G_SOURCE_REMOVE; }); - g_idle_add ([](gpointer gself){ - static_cast<ClockFixture*>(gself)->emitPrepareForSleep(); - return G_SOURCE_REMOVE; + g_idle_add([](gpointer gself){ + static_cast<ClockFixture*>(gself)->emitPrepareForSleep(); + return G_SOURCE_REMOVE; }, this); - wait_msec (1000); + wait_msec(1000); EXPECT_TRUE(skewed); } @@ -223,12 +221,12 @@ TEST_F (ClockFixture, SleepTriggersSkew) * Confirm that normal time passing doesn't trigger a skew event. * that idling changing the clock's time triggers a skew event */ -TEST_F (ClockFixture, IdleDoesNotTriggerSkew) +TEST_F(ClockFixture, IdleDoesNotTriggerSkew) { - std::shared_ptr<Timezones> zones (new Timezones); + std::shared_ptr<Timezones> zones(new Timezones); zones->timezone.set("America/New_York"); - LiveClock clock (zones); - wait_msec (500); // wait for the bus to set up + LiveClock clock(zones); + wait_msec(500); // wait for the bus to set up bool skewed = false; clock.skewDetected.connect([&skewed](){ @@ -239,6 +237,6 @@ TEST_F (ClockFixture, IdleDoesNotTriggerSkew) const unsigned int intervalSec = 4; clock.skewTestIntervalSec.set(intervalSec); - wait_msec (intervalSec * 2.5 * 1000); - EXPECT_FALSE (skewed); + wait_msec(intervalSec * 2.5 * 1000); + EXPECT_FALSE(skewed); } diff --git a/tests/test-core.cc b/tests/test-core.cc deleted file mode 100644 index 7ed38a9..0000000 --- a/tests/test-core.cc +++ /dev/null @@ -1,148 +0,0 @@ - -/* - * Copyright 2013 Canonical Ltd. - * - * Authors: - * Charles Kerr <charles.kerr@canonical.com> - * - * 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 <http://www.gnu.org/licenses/>. - */ - -#include <condition_variable> -#include <mutex> -#include <queue> -#include <thread> - -#include <langinfo.h> -#include <locale.h> - -#include <glib/gi18n.h> - -#include <core/connection.h> -#include <core/signal.h> -#include <core/property.h> - -#include "glib-fixture.h" - -/*** -**** -***/ - -class CoreFixture: public GlibFixture -{ - private: - - typedef GlibFixture super; - - protected: - - virtual void SetUp () - { - super::SetUp (); - } - - virtual void TearDown () - { - super::TearDown (); - } -}; - -namespace -{ -struct EventLoop -{ - typedef std::function<void()> Handler; - - void stop() - { - stop_requested = true; - } - - void run() - { - while (!stop_requested) - { - std::unique_lock<std::mutex> ul(guard); - wait_condition.wait_for( - ul, - std::chrono::milliseconds{500}, - [this]() { return handlers.size() > 0; }); - - std::cerr << "handlers.size() is " << handlers.size() << std::endl; - while (handlers.size() > 0) - { - std::cerr << "gaba begin" << std::endl; - handlers.front()(); - std::cerr << "gaba end" << std::endl; - handlers.pop(); - } - } - } - - void dispatch(const Handler& h) - { -std::cerr << "in dispatch" << std::endl; - std::lock_guard<std::mutex> lg(guard); - handlers.push(h); - } - - bool stop_requested = false; - std::queue<Handler> handlers; - std::mutex guard; - std::condition_variable wait_condition; -}; -} - - -TEST_F (CoreFixture, HelloWorld) -{ - // We instantiate an event loop and run it on a different thread than the main one. - EventLoop dispatcher; - std::thread dispatcher_thread{[&dispatcher]() { dispatcher.run(); }}; - std::thread::id dispatcher_thread_id = dispatcher_thread.get_id(); - - // The signal that we want to dispatch via the event loop. - core::Signal<int, double> s; - - static const int expected_invocation_count = 10000; - - // Setup the connection. For each invocation we check that the id of the - // thread the handler is being called upon equals the thread that the - // event loop is running upon. - auto connection = s.connect( - [&dispatcher, dispatcher_thread_id](int value, double d) - { - std::cerr << "this is the lambda" << std::endl; - EXPECT_EQ(dispatcher_thread_id, - std::this_thread::get_id()); - - std::cout << d << std::endl; - - if (value == expected_invocation_count) - dispatcher.stop(); - }); - - // Route the connection via the dispatcher - connection.dispatch_via( - std::bind( - &EventLoop::dispatch, - std::ref(dispatcher), - std::placeholders::_1)); - - // Invoke the signal from the main thread. - for (unsigned int i = 1; i <= expected_invocation_count; i++) - s(i, 42.); - - if (dispatcher_thread.joinable()) - dispatcher_thread.join(); -} diff --git a/tests/test-dbus-fixture.h b/tests/test-dbus-fixture.h new file mode 100644 index 0000000..fc7ab5a --- /dev/null +++ b/tests/test-dbus-fixture.h @@ -0,0 +1,100 @@ +/* + * Copyright 2013 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 <http://www.gnu.org/licenses/>. + * + * Authors: + * Charles Kerr <charles.kerr@canonical.com> + */ + +#include "glib-fixture.h" + +/*** +**** +***/ + +class TestDBusFixture: public GlibFixture +{ + public: + + TestDBusFixture() {} + + TestDBusFixture(const std::vector<std::string>& service_dirs_in): service_dirs(service_dirs_in) {} + + private: + + typedef GlibFixture super; + + static void + on_bus_opened (GObject* /*object*/, GAsyncResult * res, gpointer gself) + { + auto self = static_cast<TestDBusFixture*>(gself); + + GError * err = 0; + self->system_bus = g_bus_get_finish (res, &err); + g_assert_no_error (err); + + g_main_loop_quit (self->loop); + } + + static void + on_bus_closed (GObject* /*object*/, GAsyncResult * res, gpointer gself) + { + auto self = static_cast<TestDBusFixture*>(gself); + + GError * err = 0; + g_dbus_connection_close_finish (self->system_bus, res, &err); + g_assert_no_error (err); + + g_main_loop_quit (self->loop); + } + + protected: + + GTestDBus * test_dbus; + GDBusConnection * system_bus; + const std::vector<std::string> service_dirs; + + virtual void SetUp () + { + super::SetUp (); + + // pull up a test dbus + test_dbus = g_test_dbus_new (G_TEST_DBUS_NONE); + for (const auto& dir : service_dirs) + g_test_dbus_add_service_dir (test_dbus, dir.c_str()); + g_test_dbus_up (test_dbus); + const char * address = g_test_dbus_get_bus_address (test_dbus); + g_setenv ("DBUS_SYSTEM_BUS_ADDRESS", address, true); + g_setenv ("DBUS_SESSION_BUS_ADDRESS", address, true); + g_debug ("test_dbus's address is %s", address); + + // wait for the GDBusConnection before returning + g_bus_get (G_BUS_TYPE_SYSTEM, nullptr, on_bus_opened, this); + g_main_loop_run (loop); + } + + virtual void TearDown () + { + // close the system bus + g_dbus_connection_close (system_bus, nullptr, on_bus_closed, this); + g_main_loop_run (loop); + g_clear_object (&system_bus); + + // tear down the test dbus + g_test_dbus_down (test_dbus); + g_clear_object (&test_dbus); + + super::TearDown (); + } +}; diff --git a/tests/test-formatter.cc b/tests/test-formatter.cc index 641338b..42c828c 100644 --- a/tests/test-formatter.cc +++ b/tests/test-formatter.cc @@ -18,9 +18,9 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "clock-mock.h" #include "glib-fixture.h" +#include <datetime/clock-mock.h> #include <datetime/formatter.h> #include <datetime/settings-shared.h> @@ -30,9 +30,10 @@ #include <locale.h> using unity::indicator::datetime::Clock; +using unity::indicator::datetime::DateTime; +using unity::indicator::datetime::DesktopFormatter; using unity::indicator::datetime::MockClock; using unity::indicator::datetime::PhoneFormatter; -using unity::indicator::datetime::DesktopFormatter; /*** **** @@ -94,7 +95,8 @@ class FormatterFixture: public GlibFixture TEST_F (FormatterFixture, TestPhoneHeader) { GDateTime * now = g_date_time_new_local (2020, 10, 31, 18, 30, 59); - std::shared_ptr<MockClock> mock (new MockClock(now)); + std::shared_ptr<MockClock> mock (new MockClock(DateTime(now))); + g_date_time_unref(now); std::shared_ptr<Clock> clock = std::dynamic_pointer_cast<Clock>(mock); // test the default value in a 24h locale @@ -146,8 +148,9 @@ TEST_F (FormatterFixture, TestDesktopHeader) { true, true, true, true, "%a %b %e %Y" EM_SPACE "%l:%M %p" } }; - GDateTime * now = g_date_time_new_local (2020, 10, 31, 18, 30, 59); - std::shared_ptr<MockClock> mock (new MockClock(now)); + GDateTime * now = g_date_time_new_local(2020, 10, 31, 18, 30, 59); + std::shared_ptr<MockClock> mock(new MockClock(DateTime(now))); + g_date_time_unref(now); std::shared_ptr<Clock> clock = std::dynamic_pointer_cast<Clock>(mock); for (int i=0, n=G_N_ELEMENTS(test_cases); i<n; i++) @@ -174,44 +177,44 @@ TEST_F (FormatterFixture, TestDesktopHeader) */ TEST_F (FormatterFixture, TestUpcomingTimes) { - GDateTime * a = g_date_time_new_local (2020, 10, 31, 18, 30, 59); + auto a = g_date_time_new_local (2020, 10, 31, 18, 30, 59); struct { gboolean is_12h; GDateTime * now; GDateTime * then; - GDateTime * then_end; const char * expected_format_string; } test_cases[] = { - { true, g_date_time_ref(a), g_date_time_ref(a), NULL, "%l:%M %p" }, // identical time - { true, g_date_time_ref(a), g_date_time_add_hours(a,1), NULL, "%l:%M %p" }, // later today - { true, g_date_time_ref(a), g_date_time_add_days(a,1), NULL, "Tomorrow" EM_SPACE "%l:%M %p" }, // tomorrow - { true, g_date_time_ref(a), g_date_time_add_days(a,2), NULL, "%a" EM_SPACE "%l:%M %p" }, - { true, g_date_time_ref(a), g_date_time_add_days(a,6), NULL, "%a" EM_SPACE "%l:%M %p" }, - { true, g_date_time_ref(a), g_date_time_add_days(a,7), NULL, "%a %d %b" EM_SPACE "%l:%M %p" }, // over one week away - - { false, g_date_time_ref(a), g_date_time_ref(a), NULL, "%H:%M" }, // identical time - { false, g_date_time_ref(a), g_date_time_add_hours(a,1), NULL, "%H:%M" }, // later today - { false, g_date_time_ref(a), g_date_time_add_days(a,1), NULL, "Tomorrow" EM_SPACE "%H:%M" }, // tomorrow - { false, g_date_time_ref(a), g_date_time_add_days(a,2), NULL, "%a" EM_SPACE "%H:%M" }, - { false, g_date_time_ref(a), g_date_time_add_days(a,6), NULL, "%a" EM_SPACE "%H:%M" }, - { false, g_date_time_ref(a), g_date_time_add_days(a,7), NULL, "%a %d %b" EM_SPACE "%H:%M" } // over one week away + { true, g_date_time_ref(a), g_date_time_ref(a), "%l:%M %p" }, // identical time + { true, g_date_time_ref(a), g_date_time_add_hours(a,1), "%l:%M %p" }, // later today + { true, g_date_time_ref(a), g_date_time_add_days(a,1), "Tomorrow" EM_SPACE "%l:%M %p" }, // tomorrow + { true, g_date_time_ref(a), g_date_time_add_days(a,2), "%a" EM_SPACE "%l:%M %p" }, + { true, g_date_time_ref(a), g_date_time_add_days(a,6), "%a" EM_SPACE "%l:%M %p" }, + { true, g_date_time_ref(a), g_date_time_add_days(a,7), "%a %d %b" EM_SPACE "%l:%M %p" }, // over one week away + + { false, g_date_time_ref(a), g_date_time_ref(a), "%H:%M" }, // identical time + { false, g_date_time_ref(a), g_date_time_add_hours(a,1), "%H:%M" }, // later today + { false, g_date_time_ref(a), g_date_time_add_days(a,1), "Tomorrow" EM_SPACE "%H:%M" }, // tomorrow + { false, g_date_time_ref(a), g_date_time_add_days(a,2), "%a" EM_SPACE "%H:%M" }, + { false, g_date_time_ref(a), g_date_time_add_days(a,6), "%a" EM_SPACE "%H:%M" }, + { false, g_date_time_ref(a), g_date_time_add_days(a,7), "%a %d %b" EM_SPACE "%H:%M" } // over one week away }; for (int i=0, n=G_N_ELEMENTS(test_cases); i<n; i++) { if (test_cases[i].is_12h ? Set12hLocale() : Set24hLocale()) { - std::shared_ptr<MockClock> mock (new MockClock(test_cases[i].now)); + DateTime tmp(test_cases[i].now); + tmp.get(); + std::shared_ptr<MockClock> mock (new MockClock(tmp));//DateTime(test_cases[i].now))); std::shared_ptr<Clock> clock = std::dynamic_pointer_cast<Clock>(mock); DesktopFormatter f (clock); - std::string fmt = f.getRelativeFormat (test_cases[i].then, test_cases[i].then_end); + std::string fmt = f.getRelativeFormat (test_cases[i].then); ASSERT_STREQ (test_cases[i].expected_format_string, fmt.c_str()); g_clear_pointer (&test_cases[i].now, g_date_time_unref); g_clear_pointer (&test_cases[i].then, g_date_time_unref); - g_clear_pointer (&test_cases[i].then_end, g_date_time_unref); } } @@ -224,11 +227,11 @@ TEST_F (FormatterFixture, TestUpcomingTimes) */ TEST_F (FormatterFixture, TestEventTimes) { - GDateTime * day = g_date_time_new_local (2013, 1, 1, 13, 0, 0); - GDateTime * day_begin = g_date_time_new_local (2013, 1, 1, 13, 0, 0); - GDateTime * day_end = g_date_time_add_days (day_begin, 1); - GDateTime * tomorrow_begin = g_date_time_add_days (day_begin, 1); - GDateTime * tomorrow_end = g_date_time_add_days (tomorrow_begin, 1); + auto day = g_date_time_new_local (2013, 1, 1, 13, 0, 0); + auto day_begin = g_date_time_new_local (2013, 1, 1, 13, 0, 0); + auto day_end = g_date_time_add_days (day_begin, 1); + auto tomorrow_begin = g_date_time_add_days (day_begin, 1); + auto tomorrow_end = g_date_time_add_days (tomorrow_begin, 1); struct { bool is_12h; @@ -247,7 +250,7 @@ TEST_F (FormatterFixture, TestEventTimes) { if (test_cases[i].is_12h ? Set12hLocale() : Set24hLocale()) { - std::shared_ptr<MockClock> mock (new MockClock(test_cases[i].now)); + std::shared_ptr<MockClock> mock (new MockClock(DateTime(test_cases[i].now))); std::shared_ptr<Clock> clock = std::dynamic_pointer_cast<Clock>(mock); DesktopFormatter f (clock); diff --git a/tests/test-indicator.cc b/tests/test-indicator.cc deleted file mode 100644 index 2480c94..0000000 --- a/tests/test-indicator.cc +++ /dev/null @@ -1,92 +0,0 @@ -/* -Copyright 2012 Canonical Ltd. - -Authors: - Charles Kerr <charles.kerr@canonical.com> - -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 <http://www.gnu.org/licenses/>. -*/ - -#include <gtest/gtest.h> - -#include <glib-object.h> - -/*** -**** -***/ - -namespace -{ - void ensure_glib_initialized () - { - static bool initialized = false; - - if (G_UNLIKELY(!initialized)) - { - initialized = true; - g_setenv ("GSETTINGS_SCHEMA_DIR", SCHEMA_DIR, TRUE); - } - } -} - -/*** -**** -***/ - -class IndicatorTest : public ::testing::Test -{ - private: - - guint log_handler_id; - - int log_count_ipower_actual; - - static void log_count_func (const gchar *log_domain, - GLogLevelFlags log_level, - const gchar *message, - gpointer user_data) - { - reinterpret_cast<IndicatorTest*>(user_data)->log_count_ipower_actual++; - } - - protected: - - int log_count_ipower_expected; - - protected: - - virtual void SetUp() - { - const GLogLevelFlags flags = GLogLevelFlags(G_LOG_LEVEL_CRITICAL|G_LOG_LEVEL_WARNING); - log_handler_id = g_log_set_handler ("Indicator-Power", flags, log_count_func, this); - log_count_ipower_expected = 0; - log_count_ipower_actual = 0; - - ensure_glib_initialized (); - } - - virtual void TearDown() - { - ASSERT_EQ (log_count_ipower_expected, log_count_ipower_actual); - g_log_remove_handler ("Indicator-Power", log_handler_id); - } -}; - -/*** -**** -***/ - -TEST_F(IndicatorTest, HelloWorld) -{ - ASSERT_TRUE (TRUE); -} diff --git a/tests/test-locations.cc b/tests/test-locations.cc index c833bed..edaac69 100644 --- a/tests/test-locations.cc +++ b/tests/test-locations.cc @@ -19,9 +19,9 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "clock-mock.h" #include "glib-fixture.h" +#include <datetime/clock-mock.h> #include <datetime/locations.h> #include <datetime/locations-settings.h> #include <datetime/settings-shared.h> @@ -53,120 +53,120 @@ class LocationsFixture: public GlibFixture const std::string nyc = "America/New_York"; const std::string chicago = "America/Chicago"; - virtual void SetUp () + virtual void SetUp() { - super::SetUp (); + super::SetUp(); - settings = g_settings_new (SETTINGS_INTERFACE); + settings = g_settings_new(SETTINGS_INTERFACE); const gchar * location_strv[] = { "America/Los_Angeles Oakland", "America/Chicago Chicago", "America/Chicago Oklahoma City", "America/Toronto Toronto", "Europe/London London", "Europe/Berlin Berlin", NULL }; - g_settings_set_strv (settings, SETTINGS_LOCATIONS_S, location_strv); - g_settings_set_boolean (settings, SETTINGS_SHOW_LOCATIONS_S, true); + g_settings_set_strv(settings, SETTINGS_LOCATIONS_S, location_strv); + g_settings_set_boolean(settings, SETTINGS_SHOW_LOCATIONS_S, true); - timezones.reset (new Timezones); - timezones->timezone.set (chicago); - timezones->timezones.set (std::set<std::string>({ nyc, chicago })); + timezones.reset(new Timezones); + timezones->timezone.set(chicago); + timezones->timezones.set(std::set<std::string>({ nyc, chicago })); } - virtual void TearDown () + virtual void TearDown() { - //timezones.reset (nullptr); - g_clear_object (&settings); + //timezones.reset(nullptr); + g_clear_object(&settings); - super::TearDown (); + super::TearDown(); } }; -TEST_F (LocationsFixture, Timezones) +TEST_F(LocationsFixture, Timezones) { - g_settings_set_boolean (settings, SETTINGS_SHOW_LOCATIONS_S, false); + g_settings_set_boolean(settings, SETTINGS_SHOW_LOCATIONS_S, false); - SettingsLocations locations (SETTINGS_INTERFACE, timezones); + SettingsLocations locations(SETTINGS_INTERFACE, timezones); std::vector<Location> l = locations.locations.get(); - EXPECT_EQ (2, l.size()); - EXPECT_EQ ("Chicago", l[0].name); - EXPECT_EQ (chicago, l[0].zone); - EXPECT_EQ ("New York", l[1].name); - EXPECT_EQ (nyc, l[1].zone); + EXPECT_EQ(2, l.size()); + EXPECT_EQ("Chicago", l[0].name); + EXPECT_EQ(chicago, l[0].zone); + EXPECT_EQ("New York", l[1].name); + EXPECT_EQ(nyc, l[1].zone); } -TEST_F (LocationsFixture, SettingsLocations) +TEST_F(LocationsFixture, SettingsLocations) { - SettingsLocations locations (SETTINGS_INTERFACE, timezones); + SettingsLocations locations(SETTINGS_INTERFACE, timezones); std::vector<Location> l = locations.locations.get(); - EXPECT_EQ (7, l.size()); - EXPECT_EQ ("Chicago", l[0].name); - EXPECT_EQ (chicago, l[0].zone); - EXPECT_EQ ("New York", l[1].name); - EXPECT_EQ (nyc, l[1].zone); - EXPECT_EQ ("Oakland", l[2].name); - EXPECT_EQ ("America/Los_Angeles", l[2].zone); - EXPECT_EQ ("Oklahoma City", l[3].name); - EXPECT_EQ ("America/Chicago", l[3].zone); - EXPECT_EQ ("Toronto", l[4].name); - EXPECT_EQ ("America/Toronto", l[4].zone); - EXPECT_EQ ("London", l[5].name); - EXPECT_EQ ("Europe/London", l[5].zone); - EXPECT_EQ ("Berlin", l[6].name); - EXPECT_EQ ("Europe/Berlin", l[6].zone); + EXPECT_EQ(7, l.size()); + EXPECT_EQ("Chicago", l[0].name); + EXPECT_EQ(chicago, l[0].zone); + EXPECT_EQ("New York", l[1].name); + EXPECT_EQ(nyc, l[1].zone); + EXPECT_EQ("Oakland", l[2].name); + EXPECT_EQ("America/Los_Angeles", l[2].zone); + EXPECT_EQ("Oklahoma City", l[3].name); + EXPECT_EQ("America/Chicago", l[3].zone); + EXPECT_EQ("Toronto", l[4].name); + EXPECT_EQ("America/Toronto", l[4].zone); + EXPECT_EQ("London", l[5].name); + EXPECT_EQ("Europe/London", l[5].zone); + EXPECT_EQ("Berlin", l[6].name); + EXPECT_EQ("Europe/Berlin", l[6].zone); } -TEST_F (LocationsFixture, ChangeLocationStrings) +TEST_F(LocationsFixture, ChangeLocationStrings) { - SettingsLocations locations (SETTINGS_INTERFACE, timezones); + SettingsLocations locations(SETTINGS_INTERFACE, timezones); bool locations_changed = false; locations.locations.changed().connect([&locations_changed, this](const std::vector<Location>&){ locations_changed = true; - g_main_loop_quit (loop); + g_main_loop_quit(loop); }); - g_idle_add ([](gpointer gsettings){ + g_idle_add([](gpointer gsettings){ const gchar * strv[] = { "America/Los_Angeles Oakland", "Europe/London London", "Europe/Berlin Berlin", NULL }; - g_settings_set_strv (static_cast<GSettings*>(gsettings), SETTINGS_LOCATIONS_S, strv); + g_settings_set_strv(static_cast<GSettings*>(gsettings), SETTINGS_LOCATIONS_S, strv); return G_SOURCE_REMOVE; }, settings); - g_main_loop_run (loop); + g_main_loop_run(loop); - EXPECT_TRUE (locations_changed); + EXPECT_TRUE(locations_changed); std::vector<Location> l = locations.locations.get(); - EXPECT_EQ (5, l.size()); - EXPECT_EQ ("Chicago", l[0].name); - EXPECT_EQ (chicago, l[0].zone); - EXPECT_EQ ("New York", l[1].name); - EXPECT_EQ (nyc, l[1].zone); - EXPECT_EQ ("Oakland", l[2].name); - EXPECT_EQ ("America/Los_Angeles", l[2].zone); - EXPECT_EQ ("London", l[3].name); - EXPECT_EQ ("Europe/London", l[3].zone); - EXPECT_EQ ("Berlin", l[4].name); - EXPECT_EQ ("Europe/Berlin", l[4].zone); + EXPECT_EQ(5, l.size()); + EXPECT_EQ("Chicago", l[0].name); + EXPECT_EQ(chicago, l[0].zone); + EXPECT_EQ("New York", l[1].name); + EXPECT_EQ(nyc, l[1].zone); + EXPECT_EQ("Oakland", l[2].name); + EXPECT_EQ("America/Los_Angeles", l[2].zone); + EXPECT_EQ("London", l[3].name); + EXPECT_EQ("Europe/London", l[3].zone); + EXPECT_EQ("Berlin", l[4].name); + EXPECT_EQ("Europe/Berlin", l[4].zone); locations_changed = false; } -TEST_F (LocationsFixture, ChangeLocationVisibility) +TEST_F(LocationsFixture, ChangeLocationVisibility) { - SettingsLocations locations (SETTINGS_INTERFACE, timezones); + SettingsLocations locations(SETTINGS_INTERFACE, timezones); bool locations_changed = false; locations.locations.changed().connect([&locations_changed, this](const std::vector<Location>&){ locations_changed = true; - g_main_loop_quit (loop); + g_main_loop_quit(loop); }); - g_idle_add ([](gpointer gsettings){ - g_settings_set_boolean (static_cast<GSettings*>(gsettings), SETTINGS_SHOW_LOCATIONS_S, false); + g_idle_add([](gpointer gsettings){ + g_settings_set_boolean(static_cast<GSettings*>(gsettings), SETTINGS_SHOW_LOCATIONS_S, false); return G_SOURCE_REMOVE; }, settings); - g_main_loop_run (loop); + g_main_loop_run(loop); - EXPECT_TRUE (locations_changed); + EXPECT_TRUE(locations_changed); std::vector<Location> l = locations.locations.get(); - EXPECT_EQ (2, l.size()); - EXPECT_EQ ("Chicago", l[0].name); - EXPECT_EQ (chicago, l[0].zone); - EXPECT_EQ ("New York", l[1].name); - EXPECT_EQ (nyc, l[1].zone); + EXPECT_EQ(2, l.size()); + EXPECT_EQ("Chicago", l[0].name); + EXPECT_EQ(chicago, l[0].zone); + EXPECT_EQ("New York", l[1].name); + EXPECT_EQ(nyc, l[1].zone); } diff --git a/tests/test-menus.cc b/tests/test-menus.cc new file mode 100644 index 0000000..88e4706 --- /dev/null +++ b/tests/test-menus.cc @@ -0,0 +1,406 @@ +/* + * Copyright 2013 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 <http://www.gnu.org/licenses/>. + * + * Authors: + * Charles Kerr <charles.kerr@canonical.com> + */ + + +#include "actions-mock.h" +#include "state-fixture.h" + +#include <datetime/clock-mock.h> +#include <datetime/formatter.h> +#include <datetime/locations.h> +#include <datetime/menu.h> +#include <datetime/planner-mock.h> +#include <datetime/service.h> +#include <datetime/state.h> +#include <datetime/timezones.h> + +#include <gio/gio.h> + +using namespace unity::indicator::datetime; + +class MenuFixture: public StateFixture +{ +private: + typedef StateFixture super; + +protected: + std::shared_ptr<MenuFactory> m_menu_factory; + std::vector<std::shared_ptr<Menu>> m_menus; + + virtual void SetUp() + { + super::SetUp(); + + // build the menus on top of the actions and state + m_menu_factory.reset(new MenuFactory(m_actions, m_state)); + for(int i=0; i<Menu::NUM_PROFILES; i++) + m_menus.push_back(m_menu_factory->buildMenu(Menu::Profile(i))); + } + + virtual void TearDown() + { + m_menus.clear(); + m_menu_factory.reset(); + + super::TearDown(); + } + + void InspectHeader(GMenuModel* menu_model, const std::string& name) + { + // check that there's a header menuitem + EXPECT_EQ(1,g_menu_model_get_n_items(menu_model)); + gchar* str = nullptr; + g_menu_model_get_item_attribute(menu_model, 0, "x-canonical-type", "s", &str); + EXPECT_STREQ("com.canonical.indicator.root", str); + g_clear_pointer(&str, g_free); + g_menu_model_get_item_attribute(menu_model, 0, G_MENU_ATTRIBUTE_ACTION, "s", &str); + const auto action_name = name + "-header"; + EXPECT_EQ(std::string("indicator.")+action_name, str); + g_clear_pointer(&str, g_free); + + // check the header + auto dict = g_action_group_get_action_state(m_actions->action_group(), action_name.c_str()); + EXPECT_TRUE(dict != nullptr); + EXPECT_TRUE(g_variant_is_of_type(dict, G_VARIANT_TYPE_VARDICT)); + auto v = g_variant_lookup_value(dict, "accessible-desc", G_VARIANT_TYPE_STRING); + EXPECT_TRUE(v != nullptr); + g_variant_unref(v); + v = g_variant_lookup_value(dict, "label", G_VARIANT_TYPE_STRING); + EXPECT_TRUE(v != nullptr); + g_variant_unref(v); + v = g_variant_lookup_value(dict, "title", G_VARIANT_TYPE_STRING); + EXPECT_TRUE(v != nullptr); + g_variant_unref(v); + v = g_variant_lookup_value(dict, "visible", G_VARIANT_TYPE_BOOLEAN); + EXPECT_TRUE(v != nullptr); + g_variant_unref(v); + g_variant_unref(dict); + } + + void InspectCalendar(GMenuModel* menu_model, Menu::Profile profile) + { + gchar* str = nullptr; + const auto actions_expected = (profile == Menu::Desktop) || (profile == Menu::Phone); + const auto calendar_expected = (profile == Menu::Desktop) || (profile == Menu::DesktopGreeter); + + // get the calendar section + auto submenu = g_menu_model_get_item_link(menu_model, 0, G_MENU_LINK_SUBMENU); + auto section = g_menu_model_get_item_link(submenu, Menu::Calendar, G_MENU_LINK_SECTION); + + // should be one or two items: a date label and maybe a calendar + ASSERT_TRUE(section != nullptr); + auto n_expected = calendar_expected ? 2 : 1; + EXPECT_EQ(n_expected, g_menu_model_get_n_items(section)); + + // look at the date menuitem + g_menu_model_get_item_attribute(section, 0, G_MENU_ATTRIBUTE_LABEL, "s", &str); + const auto now = m_state->clock->localtime(); + EXPECT_EQ(now.format("%A, %e %B %Y"), str); + + g_clear_pointer(&str, g_free); + + g_menu_model_get_item_attribute(section, 0, G_MENU_ATTRIBUTE_ACTION, "s", &str); + if (actions_expected) + EXPECT_STREQ("indicator.activate-planner", str); + else + EXPECT_TRUE(str == nullptr); + g_clear_pointer(&str, g_free); + + // look at the calendar menuitem + if (calendar_expected) + { + g_menu_model_get_item_attribute(section, 1, "x-canonical-type", "s", &str); + EXPECT_STREQ("com.canonical.indicator.calendar", str); + g_clear_pointer(&str, g_free); + + g_menu_model_get_item_attribute(section, 1, G_MENU_ATTRIBUTE_ACTION, "s", &str); + EXPECT_STREQ("indicator.calendar", str); + g_clear_pointer(&str, g_free); + + g_menu_model_get_item_attribute(section, 1, "activation-action", "s", &str); + if (actions_expected) + EXPECT_STREQ("indicator.activate-planner", str); + else + EXPECT_TRUE(str == nullptr); + g_clear_pointer(&str, g_free); + } + + g_clear_object(§ion); + + // now change the clock and see if the date label changes appropriately + + auto gdt_tomorrow = g_date_time_add_days(now.get(), 1); + auto tomorrow = DateTime(gdt_tomorrow); + g_date_time_unref(gdt_tomorrow); + m_clock->set_localtime(tomorrow); + wait_msec(); + + section = g_menu_model_get_item_link(submenu, Menu::Calendar, G_MENU_LINK_SECTION); + g_menu_model_get_item_attribute(section, 0, G_MENU_ATTRIBUTE_LABEL, "s", &str); + EXPECT_EQ(tomorrow.format("%A, %e %B %Y"), str); + g_clear_pointer(&str, g_free); + g_clear_object(§ion); + + // cleanup + g_object_unref(submenu); + } + + void InspectAppointments(GMenuModel* menu_model, Menu::Profile profile) + { + const bool appointments_expected = (profile == Menu::Desktop) + || (profile == Menu::Phone); + + // get the Appointments section + auto submenu = g_menu_model_get_item_link(menu_model, 0, G_MENU_LINK_SUBMENU); + + // there shouldn't be any menuitems when "show events" is false + m_state->show_events.set(false); + wait_msec(); + auto section = g_menu_model_get_item_link(submenu, Menu::Appointments, G_MENU_LINK_SECTION); + EXPECT_EQ(0, g_menu_model_get_n_items(section)); + g_clear_object(§ion); + + // when "show_events" is true, + // there should be an "add event" button even if there aren't any appointments + std::vector<Appointment> appointments; + m_state->show_events.set(true); + m_state->planner->upcoming.set(appointments); + wait_msec(); + section = g_menu_model_get_item_link(submenu, Menu::Appointments, G_MENU_LINK_SECTION); + int expected_n = appointments_expected ? 1 : 0; + EXPECT_EQ(expected_n, g_menu_model_get_n_items(section)); + g_clear_object(§ion); + + // try adding a few appointments and see if the menu updates itself + + const auto now = m_state->clock->localtime(); + auto gdt_tomorrow = g_date_time_add_days(now.get(), 1); + const auto tomorrow = DateTime(gdt_tomorrow); + g_date_time_unref(gdt_tomorrow); + + 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 = a1.end = tomorrow; + appointments.push_back(a1); + + 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 = a2.end = tomorrow; + appointments.push_back(a2); + + m_state->planner->upcoming.set(appointments); + wait_msec(); // wait a moment for the menu to update + + section = g_menu_model_get_item_link(submenu, Menu::Appointments, G_MENU_LINK_SECTION); + expected_n = appointments_expected ? 3 : 0; + EXPECT_EQ(expected_n, g_menu_model_get_n_items(section)); + if (appointments_expected) + { + gchar * str = nullptr; + + // test the alarm + // - confirm it has an x-canonical-type of "alarm" + g_menu_model_get_item_attribute(section, 0, "x-canonical-type", "s", &str); + EXPECT_STREQ("com.canonical.indicator.alarm", str); + g_clear_pointer(&str, g_free); + // - confirm it has a nonempty x-canonical-time-format + g_menu_model_get_item_attribute(section, 0, "x-canonical-time-format", "s", &str); + EXPECT_TRUE(str && *str); + g_clear_pointer(&str, g_free); + // - confirm it has a serialized icon attribute + auto v = g_menu_model_get_item_attribute_value(section, 0, G_MENU_ATTRIBUTE_ICON, nullptr); + EXPECT_TRUE(v != nullptr); + auto icon = g_icon_deserialize(v); + EXPECT_TRUE(icon != nullptr); + g_clear_object(&icon); + g_clear_pointer(&v, g_variant_unref); + + // test the appointment + // - confirm it has an x-canonical-type of "appointment" + g_menu_model_get_item_attribute(section, 1, "x-canonical-type", "s", &str); + EXPECT_STREQ("com.canonical.indicator.appointment", str); + g_clear_pointer(&str, g_free); + // - confirm it has a nonempty x-canonical-time-format + g_menu_model_get_item_attribute(section, 0, "x-canonical-time-format", "s", &str); + EXPECT_TRUE(str && *str); + g_clear_pointer(&str, g_free); + // - confirm its color matches the one we fed the appointments vector + g_menu_model_get_item_attribute(section, 1, "x-canonical-color", "s", &str); + EXPECT_EQ(a2.color, str); + g_clear_pointer(&str, g_free); + } + g_clear_object(§ion); + + g_object_unref(submenu); + } + + void CompareLocationsTo(GMenuModel* menu_model, const std::vector<Location>& locations) + { + // get the Locations section + auto submenu = g_menu_model_get_item_link(menu_model, 0, G_MENU_LINK_SUBMENU); + auto section = g_menu_model_get_item_link(submenu, Menu::Locations, G_MENU_LINK_SECTION); + + // confirm that section's menuitems mirror the "locations" vector + const auto n = locations.size(); + ASSERT_EQ(n, g_menu_model_get_n_items(section)); + for (guint i=0; i<n; i++) + { + gchar* str = nullptr; + + // confirm that the x-canonical-type is right + g_menu_model_get_item_attribute(section, i, "x-canonical-type", "s", &str); + EXPECT_STREQ("com.canonical.indicator.location", str); + g_clear_pointer(&str, g_free); + + // confirm that the timezones match the ones in the vector + g_menu_model_get_item_attribute(section, i, "x-canonical-timezone", "s", &str); + EXPECT_EQ(locations[i].zone(), str); + g_clear_pointer(&str, g_free); + + // confirm that x-canonical-time-format has some kind of time format string + g_menu_model_get_item_attribute(section, i, "x-canonical-time-format", "s", &str); + EXPECT_TRUE(str && *str && (strchr(str,'%')!=nullptr)); + g_clear_pointer(&str, g_free); + } + + g_clear_object(§ion); + g_clear_object(&submenu); + } + + void InspectLocations(GMenuModel* menu_model, Menu::Profile profile) + { + const bool locations_expected = profile == Menu::Desktop; + + // when there aren't any locations, confirm the menu is empty + const std::vector<Location> empty; + m_state->locations->locations.set(empty); + wait_msec(); + CompareLocationsTo(menu_model, empty); + + // add some locations and confirm the menu picked up our changes + Location l1 ("America/Chicago", "Dallas"); + Location l2 ("America/Arizona", "Phoenix"); + std::vector<Location> locations({l1, l2}); + m_state->locations->locations.set(locations); + wait_msec(); + CompareLocationsTo(menu_model, locations_expected ? locations : empty); + + // now remove one of the locations... + locations.pop_back(); + m_state->locations->locations.set(locations); + wait_msec(); + CompareLocationsTo(menu_model, locations_expected ? locations : empty); + } + + void InspectSettings(GMenuModel* menu_model, Menu::Profile profile) + { + std::string expected_action; + + if (profile == Menu::Desktop) + expected_action = "indicator.activate-desktop-settings"; + else if (profile == Menu::Phone) + expected_action = "indicator.activate-phone-settings"; + + // get the Settings section + auto submenu = g_menu_model_get_item_link(menu_model, 0, G_MENU_LINK_SUBMENU); + auto section = g_menu_model_get_item_link(submenu, Menu::Settings, G_MENU_LINK_SECTION); + + if (expected_action.empty()) + { + EXPECT_EQ(0, g_menu_model_get_n_items(section)); + } + else + { + EXPECT_EQ(1, g_menu_model_get_n_items(section)); + gchar* str = nullptr; + g_menu_model_get_item_attribute(section, 0, G_MENU_ATTRIBUTE_ACTION, "s", &str); + EXPECT_EQ(expected_action, str); + g_clear_pointer(&str, g_free); + } + + g_clear_object(§ion); + g_object_unref(submenu); + } +}; + + +TEST_F(MenuFixture, HelloWorld) +{ + EXPECT_EQ(Menu::NUM_PROFILES, m_menus.size()); + for (int i=0; i<Menu::NUM_PROFILES; i++) + { + EXPECT_TRUE(m_menus[i] != false); + EXPECT_TRUE(m_menus[i]->menu_model() != nullptr); + EXPECT_EQ(i, m_menus[i]->profile()); + } + EXPECT_EQ(m_menus[Menu::Desktop]->name(), "desktop"); +} + +TEST_F(MenuFixture, Header) +{ + for(auto& menu : m_menus) + InspectHeader(menu->menu_model(), menu->name()); +} + +TEST_F(MenuFixture, Sections) +{ + for(auto& menu : m_menus) + { + // check that the header has a submenu + auto menu_model = menu->menu_model(); + auto submenu = g_menu_model_get_item_link(menu_model, 0, G_MENU_LINK_SUBMENU); + EXPECT_TRUE(submenu != nullptr); + EXPECT_EQ(Menu::NUM_SECTIONS, g_menu_model_get_n_items(submenu)); + g_object_unref(submenu); + } +} + +TEST_F(MenuFixture, Calendar) +{ + for(auto& menu : m_menus) + InspectCalendar(menu->menu_model(), menu->profile()); +} + +TEST_F(MenuFixture, Appointments) +{ + for(auto& menu : m_menus) + InspectAppointments(menu->menu_model(), menu->profile()); +} + +TEST_F(MenuFixture, Locations) +{ + for(auto& menu : m_menus) + InspectLocations(menu->menu_model(), menu->profile()); +} + +TEST_F(MenuFixture, Settings) +{ + for(auto& menu : m_menus) + InspectSettings(menu->menu_model(), menu->profile()); +} + + diff --git a/tests/test-planner-eds.cc b/tests/test-planner-eds.cc deleted file mode 100644 index 986a45e..0000000 --- a/tests/test-planner-eds.cc +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright 2013 Canonical Ltd. - * - * Authors: - * Charles Kerr <charles.kerr@canonical.com> - * - * 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 <http://www.gnu.org/licenses/>. - */ - -#include "clock-mock.h" -#include "glib-fixture.h" - -#include <datetime/planner-eds.h> - -#include <glib/gi18n.h> - -#include <langinfo.h> -#include <locale.h> - -using unity::indicator::datetime::Appointment; -using unity::indicator::datetime::DateTime; -using unity::indicator::datetime::PlannerEds; - -/*** -**** -***/ - -class PlannerEdsFixture: public GlibFixture -{ - private: - - typedef GlibFixture super; - - protected: - - virtual void SetUp () - { - super::SetUp (); - } - - virtual void TearDown () - { - super::TearDown (); - } -}; - -/*** -**** -***/ - -TEST_F (PlannerEdsFixture, HelloWorld) -{ - DateTime dt; - dt = g_date_time_new_now_local(); - - PlannerEds planner; - planner.time.set (dt); - g_main_loop_run (loop); -} - diff --git a/tests/test-planner.cc b/tests/test-planner.cc index 8c74366..3072aea 100644 --- a/tests/test-planner.cc +++ b/tests/test-planner.cc @@ -17,18 +17,20 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "clock-mock.h" #include "glib-fixture.h" #include <datetime/appointment.h> +#include <datetime/clock-mock.h> +#include <datetime/date-time.h> #include <datetime/planner.h> - -#include <glib/gi18n.h> +#include <datetime/planner-eds.h> #include <langinfo.h> #include <locale.h> using unity::indicator::datetime::Appointment; +using unity::indicator::datetime::DateTime; +using unity::indicator::datetime::PlannerEds; /*** **** @@ -36,33 +38,48 @@ using unity::indicator::datetime::Appointment; typedef GlibFixture PlannerFixture; +TEST_F(PlannerFixture, EDS) +{ + PlannerEds planner; + wait_msec(100); + + auto now = g_date_time_new_now_local(); + planner.time.set(DateTime(now)); + wait_msec(2500); + + std::vector<Appointment> thisMonth = planner.thisMonth.get(); + std::cerr << thisMonth.size() << " appointments this month" << std::endl; + for(const auto& a : thisMonth) + std::cerr << a.summary << std::endl; +} + -TEST_F (PlannerFixture, HelloWorld) +TEST_F(PlannerFixture, HelloWorld) { - GDateTime * halloween = g_date_time_new_local (2020, 10, 31, 18, 30, 59); - GDateTime * christmas = g_date_time_new_local (2020, 12, 25, 0, 0, 0); + auto halloween = g_date_time_new_local(2020, 10, 31, 18, 30, 59); + auto christmas = g_date_time_new_local(2020, 12, 25, 0, 0, 0); Appointment a; a.summary = "Test"; a.begin = halloween; - a.end = g_date_time_add_hours (halloween, 1); + a.end = g_date_time_add_hours(halloween, 1); const Appointment b = a; a.summary = "Foo"; - EXPECT_EQ (a.summary, "Foo"); - EXPECT_EQ (b.summary, "Test"); - EXPECT_EQ (0, g_date_time_compare (a.begin(), b.begin())); - EXPECT_EQ (0, g_date_time_compare (a.end(), b.end())); + EXPECT_EQ(a.summary, "Foo"); + EXPECT_EQ(b.summary, "Test"); + EXPECT_EQ(0, g_date_time_compare(a.begin(), b.begin())); + EXPECT_EQ(0, g_date_time_compare(a.end(), b.end())); Appointment c; c.begin = christmas; - c.end = g_date_time_add_hours (christmas, 1); + c.end = g_date_time_add_hours(christmas, 1); Appointment d; d = c; - EXPECT_EQ (0, g_date_time_compare (c.begin(), d.begin())); - EXPECT_EQ (0, g_date_time_compare (c.end(), d.end())); + EXPECT_EQ(0, g_date_time_compare(c.begin(), d.begin())); + EXPECT_EQ(0, g_date_time_compare(c.end(), d.end())); a = d; - EXPECT_EQ (0, g_date_time_compare (d.begin(), a.begin())); - EXPECT_EQ (0, g_date_time_compare (d.end(), a.end())); + EXPECT_EQ(0, g_date_time_compare(d.begin(), a.begin())); + EXPECT_EQ(0, g_date_time_compare(d.end(), a.end())); } diff --git a/tests/test-skew.cc b/tests/test-skew.cc deleted file mode 100644 index 90c0164..0000000 --- a/tests/test-skew.cc +++ /dev/null @@ -1,209 +0,0 @@ -/* - * Copyright 2013 Canonical Ltd. - * - * Authors: - * Charles Kerr <charles.kerr@canonical.com> - * - * 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 <http://www.gnu.org/licenses/>. - */ - -#include "glib-fixture.h" - -#include "Clock.h" -#include "MockClock.h" - -/*** -**** -***/ - -using unity::indicator::datetime::Clock; -using unity::indicator::datetime::MockClock; -using unity::indicator::datetime::SkewDetector; - -class SkewFixture: public GlibFixture -{ - private: - - typedef GlibFixture super; - - static void - on_bus_opened (GObject * o G_GNUC_UNUSED, GAsyncResult * res, gpointer gself) - { - auto self = static_cast<SkewFixture*>(gself); - - GError * err = 0; - self->system_bus = g_bus_get_finish (res, &err); - g_assert_no_error (err); - - g_main_loop_quit (self->loop); - } - - static void - on_bus_closed (GObject * o G_GNUC_UNUSED, GAsyncResult * res, gpointer gself) - { - auto self = static_cast<SkewFixture*>(gself); - - GError * err = 0; - g_dbus_connection_close_finish (self->system_bus, res, &err); - g_assert_no_error (err); - - g_main_loop_quit (self->loop); - } - - protected: - - std::shared_ptr<Clock> mockClock; - GTestDBus * test_dbus; - GDBusConnection * system_bus; - - virtual void SetUp () - { - super::SetUp (); - - // pull up a test dbus - test_dbus = g_test_dbus_new (G_TEST_DBUS_NONE); - g_test_dbus_up (test_dbus); - const char * address = g_test_dbus_get_bus_address (test_dbus); - g_setenv ("DBUS_SYSTEM_BUS_ADDRESS", address, TRUE); - g_debug ("test_dbus's address is %s", address); - - // wait for the GDBusConnection before returning - g_bus_get (G_BUS_TYPE_SYSTEM, nullptr, on_bus_opened, this); - g_main_loop_run (loop); - - // create a clock - GDateTime * now = g_date_time_new_now_local (); - mockClock.reset (new MockClock (now)); - g_date_time_unref (now); - } - - virtual void TearDown () - { - mockClock.reset(); - - // close the system bus - g_dbus_connection_close (system_bus, nullptr, on_bus_closed, this); - g_main_loop_run (loop); - g_clear_object (&system_bus); - - // tear down the test dbus - g_test_dbus_down (test_dbus); - g_clear_object (&test_dbus); - - super::TearDown (); - } - - public: - - void emitPrepareForSleep () - { - g_dbus_connection_emit_signal (g_bus_get_sync (G_BUS_TYPE_SYSTEM, nullptr, nullptr), - NULL, - "/org/freedesktop/login1", // object path - "org.freedesktop.login1.Manager", // interface - "PrepareForSleep", // signal name - g_variant_new("(b)", FALSE), - NULL); - } -}; - - -/** - * A simple "hello world" style test. - */ -TEST_F (SkewFixture, CanInstantiate) -{ - SkewDetector skew (std::dynamic_pointer_cast<Clock>(mockClock)); - wait_msec (500); // wait for the bus to set up -} - - -/** - * Confirm that changing the clock's timezone triggers a skew event - */ -TEST_F (SkewFixture, ChangingTimezonesTriggersEvent) -{ - SkewDetector skew (std::dynamic_pointer_cast<Clock>(mockClock)); - wait_msec (500); // wait for the bus to set up - - bool skewed = false; - skew.skewDetected.connect([&skewed, this](){ - skewed = true; - g_main_loop_quit(loop); - return G_SOURCE_REMOVE; - }); - - g_idle_add([](gpointer gclock){ - GDateTime * arbitrary = g_date_time_new_local (2020, 10, 31, 18, 30, 59); - static_cast<MockClock*>(gclock)->setLocaltime (arbitrary); - g_date_time_unref (arbitrary); - return G_SOURCE_REMOVE; - }, mockClock.get()); - - wait_msec (1000); - - EXPECT_TRUE (skewed); - GDateTime * expected = g_date_time_new_local (2020, 10, 31, 18, 30, 59); - GDateTime * actual = mockClock->localtime(); - EXPECT_EQ (0, g_date_time_compare (expected, actual)); - g_date_time_unref (actual); - g_date_time_unref (expected); -} - -/** - * Confirm that a "PrepareForSleep" event wil trigger a skew event - */ -TEST_F (SkewFixture, PrepareForSleep) -{ - SkewDetector skew (std::dynamic_pointer_cast<Clock>(mockClock)); - wait_msec (500); // wait for the bus to set up - - bool skewed = false; - skew.skewDetected.connect([&skewed, this](){ - skewed = true; - g_main_loop_quit(loop); - return G_SOURCE_REMOVE; - }); - - g_idle_add ([](gpointer gself){ - static_cast<SkewFixture*>(gself)->emitPrepareForSleep(); - return G_SOURCE_REMOVE; - }, this); - - wait_msec (1000); - EXPECT_TRUE(skewed); -} - - -/** - * Confirm that normal time passing doesn't trigger a skew event. - * that idling changing the clock's time triggers a skew event - */ -TEST_F (SkewFixture, IdleDoesNotTriggerEvent) -{ - SkewDetector skew (std::dynamic_pointer_cast<Clock>(mockClock)); - wait_msec (500); // wait for the bus to set up - - bool skewed = false; - skew.skewDetected.connect([&skewed](){ - skewed = true; - g_warn_if_reached(); - //abort(); - return G_SOURCE_REMOVE; - }); - - const unsigned int intervalSec = 4; - skew.intervalSec.set(intervalSec); - wait_msec (intervalSec * 2.5 * 1000); - EXPECT_FALSE (skewed); -} diff --git a/tests/test-timezone-file.cc b/tests/test-timezone-file.cc index 510d12c..453b353 100644 --- a/tests/test-timezone-file.cc +++ b/tests/test-timezone-file.cc @@ -52,25 +52,25 @@ class TimezoneFixture: public GlibFixture protected: - virtual void SetUp () + virtual void SetUp() { - super::SetUp (); + super::SetUp(); } - virtual void TearDown () + virtual void TearDown() { - super::TearDown (); + super::TearDown(); } public: /* convenience func to set the timezone file */ - void set_file (const std::string& text) + void set_file(const std::string& text) { - FILE * fp = fopen (TIMEZONE_FILE, "w+"); - fprintf (fp, "%s\n", text.c_str()); - fclose (fp); - sync (); + auto fp = fopen(TIMEZONE_FILE, "w+"); + fprintf(fp, "%s\n", text.c_str()); + fclose(fp); + sync(); } }; @@ -78,56 +78,56 @@ class TimezoneFixture: public GlibFixture /** * Test that timezone-file warns, but doesn't crash, if the timezone file doesn't exist */ -TEST_F (TimezoneFixture, NoFile) +TEST_F(TimezoneFixture, NoFile) { - remove (TIMEZONE_FILE); - ASSERT_FALSE (g_file_test (TIMEZONE_FILE, G_FILE_TEST_EXISTS)); + remove(TIMEZONE_FILE); + ASSERT_FALSE(g_file_test(TIMEZONE_FILE, G_FILE_TEST_EXISTS)); - FileTimezone tz (TIMEZONE_FILE); - testLogCount (G_LOG_LEVEL_WARNING, 1); + FileTimezone tz(TIMEZONE_FILE); + testLogCount(G_LOG_LEVEL_WARNING, 1); } /** * Test that timezone-file picks up the initial value */ -TEST_F (TimezoneFixture, InitialValue) +TEST_F(TimezoneFixture, InitialValue) { const std::string expected_timezone = "America/Chicago"; - set_file (expected_timezone); - FileTimezone tz (TIMEZONE_FILE); - ASSERT_EQ (expected_timezone, tz.timezone.get()); + set_file(expected_timezone); + FileTimezone tz(TIMEZONE_FILE); + ASSERT_EQ(expected_timezone, tz.timezone.get()); } /** * Test that clearing the timezone results in an empty string */ -TEST_F (TimezoneFixture, ChangedValue) +TEST_F(TimezoneFixture, ChangedValue) { const std::string initial_timezone = "America/Chicago"; const std::string changed_timezone = "America/New_York"; - set_file (initial_timezone); + set_file(initial_timezone); - FileTimezone tz (TIMEZONE_FILE); - ASSERT_EQ (initial_timezone, tz.timezone.get()); + FileTimezone tz(TIMEZONE_FILE); + ASSERT_EQ(initial_timezone, tz.timezone.get()); bool changed = false; auto connection = tz.timezone.changed().connect( [&changed, this](const std::string& s){ - g_message ("timezone changed to %s", s.c_str()); + g_message("timezone changed to %s", s.c_str()); changed = true; - g_main_loop_quit (loop); + g_main_loop_quit(loop); }); - g_idle_add ([](gpointer gself){ - static_cast<TimezoneFixture*>(gself)->set_file ("America/New_York"); - // static_cast<FileTimezone*>(gtz)->timezone.set ("America/New_York"); + g_idle_add([](gpointer gself){ + static_cast<TimezoneFixture*>(gself)->set_file("America/New_York"); + // static_cast<FileTimezone*>(gtz)->timezone.set("America/New_York"); return G_SOURCE_REMOVE; }, this);//&tz); - g_main_loop_run (loop); + g_main_loop_run(loop); - ASSERT_TRUE (changed); - ASSERT_EQ (changed_timezone, tz.timezone.get()); + ASSERT_TRUE(changed); + ASSERT_EQ(changed_timezone, tz.timezone.get()); } diff --git a/tests/test-timezone-geoclue.cc b/tests/test-timezone-geoclue.cc index a577fbd..4bf08a7 100644 --- a/tests/test-timezone-geoclue.cc +++ b/tests/test-timezone-geoclue.cc @@ -46,21 +46,21 @@ namespace const std::string& timezone_): mock(mock_), obj_client(obj_client_), timezone(timezone_) {} }; - gboolean emit_address_changed_idle (gpointer gdata) + gboolean emit_address_changed_idle(gpointer gdata) { auto data = static_cast<EmitAddressChangedData*>(gdata); GError * error = nullptr; - dbus_test_dbus_mock_object_emit_signal (data->mock, data->obj_client, + dbus_test_dbus_mock_object_emit_signal(data->mock, data->obj_client, "org.freedesktop.Geoclue.Address", "AddressChanged", G_VARIANT_TYPE("(ia{ss}(idd))"), - g_variant_new_parsed ("(1385238033, {'timezone': 'America/Chicago'}, (3, 0.0, 0.0))"), + g_variant_new_parsed("(1385238033, {'timezone': 'America/Chicago'}, (3, 0.0, 0.0))"), &error); if (error) { - g_warning ("%s: %s", G_STRFUNC, error->message); - g_error_free (error); + g_warning("%s: %s", G_STRFUNC, error->message); + g_error_free(error); } delete data; @@ -69,29 +69,29 @@ namespace } #endif -TEST_F (TimezoneGeoclueFixture, ChangeDetected) +TEST_F(TimezoneGeoclueFixture, ChangeDetected) { // const std::string timezone_1 = "America/Denver"; const std::string timezone_2 = "America/Chicago"; GeoclueTimezone tz; - wait_msec (500); // wait for the bus to get set up - EXPECT_EQ (timezone_1, tz.timezone.get()); + wait_msec(500); // wait for the bus to get set up + EXPECT_EQ(timezone_1, tz.timezone.get()); // start listening for a timezone change, then change the timezone bool changed = false; auto connection = tz.timezone.changed().connect( [&changed, this](const std::string& s){ - g_debug ("timezone changed to %s", s.c_str()); + g_debug("timezone changed to %s", s.c_str()); changed = true; - g_main_loop_quit (loop); + g_main_loop_quit(loop); }); - setGeoclueTimezoneOnIdle (timezone_2); - //g_timeout_add (50, emit_address_changed_idle, new EmitAddressChangedData(mock, obj_client, timezone_2.c_str())); - g_main_loop_run (loop); - EXPECT_EQ (timezone_2, tz.timezone.get()); + setGeoclueTimezoneOnIdle(timezone_2); + //g_timeout_add(50, emit_address_changed_idle, new EmitAddressChangedData(mock, obj_client, timezone_2.c_str())); + g_main_loop_run(loop); + EXPECT_EQ(timezone_2, tz.timezone.get()); } diff --git a/tests/test-timezones.cc b/tests/test-timezones.cc index cda53a6..d3c8e3a 100644 --- a/tests/test-timezones.cc +++ b/tests/test-timezones.cc @@ -33,33 +33,34 @@ typedef GeoclueFixture TimezonesFixture; namespace { /* convenience func to set the timezone file */ - void set_file (const std::string& text) + void set_file(const std::string& text) { - FILE * fp = fopen (TIMEZONE_FILE, "w+"); - fprintf (fp, "%s\n", text.c_str()); - fclose (fp); - sync (); + auto fp = fopen(TIMEZONE_FILE, "w+"); + fprintf(fp, "%s\n", text.c_str()); + fclose(fp); + sync(); } } -TEST_F (TimezonesFixture, ManagerTest) +TEST_F(TimezonesFixture, ManagerTest) { std::string timezone_file = "America/New_York"; std::string timezone_geo = "America/Denver"; - set_file (timezone_file); - LiveTimezones z (TIMEZONE_FILE); - wait_msec (500); // wait for the bus to get set up - EXPECT_EQ (timezone_file, z.timezone.get()); - std::set<std::string> zones = z.timezones.get(); - EXPECT_EQ (1, zones.size()); - EXPECT_EQ (1, zones.count(timezone_file)); + set_file(timezone_file); + LiveTimezones z(TIMEZONE_FILE); + wait_msec(500); // wait for the bus to get set up + EXPECT_EQ(timezone_file, z.timezone.get()); + auto zones = z.timezones.get(); + //std::set<std::string> zones = z.timezones.get(); + EXPECT_EQ(1, zones.size()); + EXPECT_EQ(1, zones.count(timezone_file)); bool zone_changed = false; auto zone_connection = z.timezone.changed().connect([&zone_changed, this](const std::string&) { zone_changed = true; - g_main_loop_quit (loop); + g_main_loop_quit(loop); }); // start listening for a timezone change, then change the timezone @@ -67,24 +68,24 @@ TEST_F (TimezonesFixture, ManagerTest) auto zones_connection = z.timezones.changed().connect([&zones_changed, &zones, this](const std::set<std::string>& timezones) { zones_changed = true; zones = timezones; - g_main_loop_quit (loop); + g_main_loop_quit(loop); }); - g_idle_add ([](gpointer gz) { + g_idle_add([](gpointer gz) { auto az = static_cast<LiveTimezones*>(gz); - g_message ("geolocation was %d", (int)az->geolocationEnabled.get()); - g_message ("turning geolocation on"); + g_message("geolocation was %d", (int)az->geolocationEnabled.get()); + g_message("turning geolocation on"); az->geolocationEnabled.set(true); return G_SOURCE_REMOVE; }, &z); // turn on geoclue during the idle... this should add timezone_1 to the 'timezones' property - g_main_loop_run (loop); - EXPECT_TRUE (zones_changed); - EXPECT_EQ (timezone_file, z.timezone.get()); - EXPECT_EQ (2, zones.size()); - EXPECT_EQ (1, zones.count(timezone_file)); - EXPECT_EQ (1, zones.count(timezone_geo)); + g_main_loop_run(loop); + EXPECT_TRUE(zones_changed); + EXPECT_EQ(timezone_file, z.timezone.get()); + EXPECT_EQ(2, zones.size()); + EXPECT_EQ(1, zones.count(timezone_file)); + EXPECT_EQ(1, zones.count(timezone_geo)); zones_changed = false; // now tweak the geoclue value... the geoclue-detected timezone should change, @@ -92,28 +93,28 @@ TEST_F (TimezonesFixture, ManagerTest) zone_changed = false; zones_changed = false; timezone_geo = "America/Chicago"; - setGeoclueTimezoneOnIdle (timezone_geo); - g_main_loop_run (loop); - EXPECT_FALSE (zone_changed); - EXPECT_TRUE (zones_changed); - EXPECT_EQ (timezone_file, z.timezone.get()); - EXPECT_EQ (2, zones.size()); - EXPECT_EQ (1, zones.count(timezone_file)); - EXPECT_EQ (1, zones.count(timezone_geo)); + setGeoclueTimezoneOnIdle(timezone_geo); + g_main_loop_run(loop); + EXPECT_FALSE(zone_changed); + EXPECT_TRUE(zones_changed); + EXPECT_EQ(timezone_file, z.timezone.get()); + EXPECT_EQ(2, zones.size()); + EXPECT_EQ(1, zones.count(timezone_file)); + EXPECT_EQ(1, zones.count(timezone_geo)); // now set the file value... this should change both the primary property and set property zone_changed = false; zones_changed = false; timezone_file = "America/Los_Angeles"; - EXPECT_EQ (0, zones.count(timezone_file)); - g_idle_add ([](gpointer str) {set_file(static_cast<const char*>(str)); return G_SOURCE_REMOVE;}, const_cast<char*>(timezone_file.c_str())); - g_main_loop_run (loop); - EXPECT_TRUE (zone_changed); - EXPECT_TRUE (zones_changed); - EXPECT_EQ (timezone_file, z.timezone.get()); - EXPECT_EQ (2, zones.size()); - EXPECT_EQ (1, zones.count(timezone_file)); - EXPECT_EQ (1, zones.count(timezone_geo)); + EXPECT_EQ(0, zones.count(timezone_file)); + g_idle_add([](gpointer str) {set_file(static_cast<const char*>(str)); return G_SOURCE_REMOVE;}, const_cast<char*>(timezone_file.c_str())); + g_main_loop_run(loop); + EXPECT_TRUE(zone_changed); + EXPECT_TRUE(zones_changed); + EXPECT_EQ(timezone_file, z.timezone.get()); + EXPECT_EQ(2, zones.size()); + EXPECT_EQ(1, zones.count(timezone_file)); + EXPECT_EQ(1, zones.count(timezone_geo)); diff --git a/tests/test-utils.cc b/tests/test-utils.cc index d0f277b..8246396 100644 --- a/tests/test-utils.cc +++ b/tests/test-utils.cc @@ -1,21 +1,21 @@ /* -Copyright 2012 Canonical Ltd. - -Authors: - Charles Kerr <charles.kerr@canonical.com> - -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 <http://www.gnu.org/licenses/>. -*/ + * Copyright 2013 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 <http://www.gnu.org/licenses/>. + * + * Authors: + * Charles Kerr <charles.kerr@canonical.com> + */ #include <gtest/gtest.h> @@ -27,36 +27,33 @@ with this program. If not, see <http://www.gnu.org/licenses/>. **** ***/ -TEST (UtilsTest, SplitSettingsLocation) +TEST(UtilsTest, SplitSettingsLocation) { - guint i; - guint n; - - struct { - const char * location; - const char * expected_zone; - const char * expected_name; - } test_cases[] = { - { "America/Chicago Chicago", "America/Chicago", "Chicago" }, - { "America/Chicago Oklahoma City", "America/Chicago", "Oklahoma City" }, - { "America/Los_Angeles", "America/Los_Angeles", "Los Angeles" }, - { "America/Los_Angeles ", "America/Los_Angeles", "Los Angeles" }, - { " America/Los_Angeles", "America/Los_Angeles", "Los Angeles" }, - { " America/Los_Angeles ", "America/Los_Angeles", "Los Angeles" }, - { "UTC UTC", "UTC", "UTC" } - }; - - for (i=0, n=G_N_ELEMENTS(test_cases); i<n; i++) + struct { + const char * location; + const char * expected_zone; + const char * expected_name; + } test_cases[] = { + { "America/Chicago Chicago", "America/Chicago", "Chicago" }, + { "America/Chicago Oklahoma City", "America/Chicago", "Oklahoma City" }, + { "America/Los_Angeles", "America/Los_Angeles", "Los Angeles" }, + { "America/Los_Angeles ", "America/Los_Angeles", "Los Angeles" }, + { " America/Los_Angeles", "America/Los_Angeles", "Los Angeles" }, + { " America/Los_Angeles ", "America/Los_Angeles", "Los Angeles" }, + { "UTC UTC", "UTC", "UTC" } + }; + + for(guint i=0, n=G_N_ELEMENTS(test_cases); i<n; i++) { - char * zone = NULL; - char * name = NULL; + char * zone = NULL; + char * name = NULL; - split_settings_location (test_cases[i].location, &zone, &name); - ASSERT_STREQ (test_cases[i].expected_zone, zone); - ASSERT_STREQ (test_cases[i].expected_name, name); + split_settings_location(test_cases[i].location, &zone, &name); + ASSERT_STREQ(test_cases[i].expected_zone, zone); + ASSERT_STREQ(test_cases[i].expected_name, name); - g_free (zone); - g_free (name); + g_free(zone); + g_free(name); } } @@ -66,47 +63,43 @@ TEST (UtilsTest, SplitSettingsLocation) #define EM_SPACE "\xE2\x80\x82" -TEST (UtilsTest, GenerateTerseFormatString) +TEST(UtilsTest, GenerateTerseFormatString) { - guint i; - guint n; - GDateTime * arbitrary_day = g_date_time_new_local (2013, 6, 25, 12, 34, 56); - GDateTime * on_the_hour = g_date_time_new_local (2013, 6, 25, 12, 0, 0); - - struct { - GDateTime * now; - GDateTime * time; - const char * expected_format_string; - } test_cases[] = { - { g_date_time_ref(arbitrary_day), g_date_time_ref(arbitrary_day), "%l:%M %p" }, /* identical time */ - { g_date_time_ref(arbitrary_day), g_date_time_add_hours(arbitrary_day,1), "%l:%M %p" }, /* later today */ - { g_date_time_ref(arbitrary_day), g_date_time_add_days(arbitrary_day,1), "Tomorrow" EM_SPACE "%l:%M %p" }, /* tomorrow */ - { g_date_time_ref(arbitrary_day), g_date_time_add_days(arbitrary_day,2), "%a" EM_SPACE "%l:%M %p" }, - { g_date_time_ref(arbitrary_day), g_date_time_add_days(arbitrary_day,6), "%a" EM_SPACE "%l:%M %p" }, - { g_date_time_ref(arbitrary_day), g_date_time_add_days(arbitrary_day,7), "%d %b" EM_SPACE "%l:%M %p" }, /* over one week away */ - - { g_date_time_ref(on_the_hour), g_date_time_ref(on_the_hour), "%l %p" }, /* identical time */ - { g_date_time_ref(on_the_hour), g_date_time_add_hours(on_the_hour,1), "%l %p" }, /* later today */ - { g_date_time_ref(on_the_hour), g_date_time_add_days(on_the_hour,1), "Tomorrow" EM_SPACE "%l %p" }, /* tomorrow */ - { g_date_time_ref(on_the_hour), g_date_time_add_days(on_the_hour,2), "%a" EM_SPACE "%l %p" }, - { g_date_time_ref(on_the_hour), g_date_time_add_days(on_the_hour,6), "%a" EM_SPACE "%l %p" }, - { g_date_time_ref(on_the_hour), g_date_time_add_days(on_the_hour,7), "%d %b" EM_SPACE "%l %p" }, /* over one week away */ - }; - - for (i=0, n=G_N_ELEMENTS(test_cases); i<n; i++) + auto arbitrary_day = g_date_time_new_local(2013, 6, 25, 12, 34, 56); + auto on_the_hour = g_date_time_new_local(2013, 6, 25, 12, 0, 0); + + struct { + GDateTime * now; + GDateTime * time; + const char * expected_format_string; + } test_cases[] = { + { g_date_time_ref(arbitrary_day), g_date_time_ref(arbitrary_day), "%l:%M %p" }, /* identical time */ + { g_date_time_ref(arbitrary_day), g_date_time_add_hours(arbitrary_day,1), "%l:%M %p" }, /* later today */ + { g_date_time_ref(arbitrary_day), g_date_time_add_days(arbitrary_day,1), "Tomorrow" EM_SPACE "%l:%M %p" }, /* tomorrow */ + { g_date_time_ref(arbitrary_day), g_date_time_add_days(arbitrary_day,2), "%a" EM_SPACE "%l:%M %p" }, + { g_date_time_ref(arbitrary_day), g_date_time_add_days(arbitrary_day,6), "%a" EM_SPACE "%l:%M %p" }, + { g_date_time_ref(arbitrary_day), g_date_time_add_days(arbitrary_day,7), "%d %b" EM_SPACE "%l:%M %p" }, /* over one week away */ + + { g_date_time_ref(on_the_hour), g_date_time_ref(on_the_hour), "%l %p" }, /* identical time */ + { g_date_time_ref(on_the_hour), g_date_time_add_hours(on_the_hour,1), "%l %p" }, /* later today */ + { g_date_time_ref(on_the_hour), g_date_time_add_days(on_the_hour,1), "Tomorrow" EM_SPACE "%l %p" }, /* tomorrow */ + { g_date_time_ref(on_the_hour), g_date_time_add_days(on_the_hour,2), "%a" EM_SPACE "%l %p" }, + { g_date_time_ref(on_the_hour), g_date_time_add_days(on_the_hour,6), "%a" EM_SPACE "%l %p" }, + { g_date_time_ref(on_the_hour), g_date_time_add_days(on_the_hour,7), "%d %b" EM_SPACE "%l %p" }, /* over one week away */ + }; + + for(guint i=0, n=G_N_ELEMENTS(test_cases); i<n; i++) { - char * format_string; - - format_string = generate_terse_format_string_at_time (test_cases[i].now, - test_cases[i].time); + auto format_string = generate_terse_format_string_at_time(test_cases[i].now, + test_cases[i].time); - ASSERT_STREQ (test_cases[i].expected_format_string, format_string); + ASSERT_STREQ(test_cases[i].expected_format_string, format_string); - g_free (format_string); - g_date_time_unref (test_cases[i].now); - g_date_time_unref (test_cases[i].time); + g_free(format_string); + g_date_time_unref(test_cases[i].now); + g_date_time_unref(test_cases[i].time); } - g_date_time_unref (arbitrary_day); - g_date_time_unref (on_the_hour); + g_date_time_unref(arbitrary_day); + g_date_time_unref(on_the_hour); } |