From 060bc69d8bdfe9860a71109ecf92810beb99f4da Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Tue, 17 Dec 2013 21:59:43 -0600 Subject: add clock + tests --- tests/test-clock.cc | 244 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 244 insertions(+) create mode 100644 tests/test-clock.cc (limited to 'tests') diff --git a/tests/test-clock.cc b/tests/test-clock.cc new file mode 100644 index 0000000..a0b4360 --- /dev/null +++ b/tests/test-clock.cc @@ -0,0 +1,244 @@ +/* + * 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 . + * + * Authors: + * Charles Kerr + */ + +#include +#include + +#include "glib-fixture.h" + +/*** +**** +***/ + +using unity::indicator::datetime::Clock; +using unity::indicator::datetime::LiveClock; +using unity::indicator::datetime::Timezones; + +class ClockFixture: public GlibFixture +{ + private: + + typedef GlibFixture super; + + static void + on_bus_opened (GObject * o G_GNUC_UNUSED, GAsyncResult * res, gpointer gself) + { + auto self = static_cast(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(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; + + 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); + } + + 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 (); + } + + 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); + } +}; + +/*** +**** +***/ + +#define TIMEZONE_FILE (SANDBOX"/timezone") + +TEST_F (ClockFixture, HelloFixture) +{ + std::shared_ptr zones (new Timezones); + zones->timezone.set("America/New_York"); + 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); + 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); + + /// change the timezones! + clock.skewDetected.connect([this](){ + g_main_loop_quit(loop); + }); + file_timezone = "America/Los_Angeles"; + g_idle_add ([](gpointer str){ + set_file(static_cast(str)); + return G_SOURCE_REMOVE; + }, const_cast(file_timezone.c_str())); + 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); + 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); +#endif +} + + +TEST_F (ClockFixture, TimezoneChangeTriggersSkew) +{ + std::shared_ptr zones (new Timezones); + zones->timezone.set("America/New_York"); + LiveClock clock (zones); + //std::string file_timezone = "America/New_York"; + //set_file (file_timezone); + //std::shared_ptr 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); + + /// change the timezones! + clock.skewDetected.connect([this](){ + g_main_loop_quit(loop); + }); + g_idle_add ([](gpointer gs){ + static_cast(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); + 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); +} + +/** + * Confirm that a "PrepareForSleep" event wil trigger a skew event + */ +TEST_F (ClockFixture, SleepTriggersSkew) +{ + std::shared_ptr zones (new Timezones); + zones->timezone.set("America/New_York"); + LiveClock clock (zones); + wait_msec (500); // wait for the bus to set up + + bool skewed = false; + clock.skewDetected.connect([&skewed, this](){ + skewed = true; + g_main_loop_quit(loop); + return G_SOURCE_REMOVE; + }); + + g_idle_add ([](gpointer gself){ + static_cast(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 (ClockFixture, IdleDoesNotTriggerSkew) +{ + std::shared_ptr zones (new Timezones); + zones->timezone.set("America/New_York"); + LiveClock clock (zones); + wait_msec (500); // wait for the bus to set up + + bool skewed = false; + clock.skewDetected.connect([&skewed](){ + skewed = true; + g_warn_if_reached(); + return G_SOURCE_REMOVE; + }); + + const unsigned int intervalSec = 4; + clock.skewTestIntervalSec.set(intervalSec); + wait_msec (intervalSec * 2.5 * 1000); + EXPECT_FALSE (skewed); +} -- cgit v1.2.3 From 36d8e8ee2d9f2b7967cef6c74c6f779263727eb9 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Tue, 17 Dec 2013 22:00:32 -0600 Subject: add timezone-file + tests --- tests/test-timezone-file.cc | 133 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 133 insertions(+) create mode 100644 tests/test-timezone-file.cc (limited to 'tests') diff --git a/tests/test-timezone-file.cc b/tests/test-timezone-file.cc new file mode 100644 index 0000000..510d12c --- /dev/null +++ b/tests/test-timezone-file.cc @@ -0,0 +1,133 @@ + +/* + * Copyright 2013 Canonical Ltd. + * + * Authors: + * Charles Kerr + * + * 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 . + */ + +#include "glib-fixture.h" + +#include + +//#include +//#include +//#include +//#include +//#include +//#include +//#include +//#include + +#include // fopen() +//#include // chmod() +#include // sync() + +using unity::indicator::datetime::FileTimezone; + + +/*** +**** +***/ + +#define TIMEZONE_FILE (SANDBOX"/timezone") + +class TimezoneFixture: public GlibFixture +{ + private: + + typedef GlibFixture super; + + protected: + + virtual void SetUp () + { + super::SetUp (); + } + + virtual void TearDown () + { + super::TearDown (); + } + + public: + + /* convenience func to set the timezone file */ + void set_file (const std::string& text) + { + FILE * fp = fopen (TIMEZONE_FILE, "w+"); + fprintf (fp, "%s\n", text.c_str()); + fclose (fp); + sync (); + } +}; + + +/** + * Test that timezone-file warns, but doesn't crash, if the timezone file doesn't exist + */ +TEST_F (TimezoneFixture, NoFile) +{ + remove (TIMEZONE_FILE); + ASSERT_FALSE (g_file_test (TIMEZONE_FILE, G_FILE_TEST_EXISTS)); + + FileTimezone tz (TIMEZONE_FILE); + testLogCount (G_LOG_LEVEL_WARNING, 1); +} + + +/** + * Test that timezone-file picks up the initial value + */ +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()); +} + + +/** + * Test that clearing the timezone results in an empty string + */ +TEST_F (TimezoneFixture, ChangedValue) +{ + const std::string initial_timezone = "America/Chicago"; + const std::string changed_timezone = "America/New_York"; + set_file (initial_timezone); + + 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()); + changed = true; + g_main_loop_quit (loop); + }); + + g_idle_add ([](gpointer gself){ + static_cast(gself)->set_file ("America/New_York"); + // static_cast(gtz)->timezone.set ("America/New_York"); + return G_SOURCE_REMOVE; + }, this);//&tz); + + g_main_loop_run (loop); + + ASSERT_TRUE (changed); + ASSERT_EQ (changed_timezone, tz.timezone.get()); +} -- cgit v1.2.3 From a1cb4d7802e6e024c842f2a4fa41b91b67162698 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Tue, 17 Dec 2013 22:00:51 -0600 Subject: add timezone-geoclue + tests --- tests/test-timezone-geoclue.cc | 97 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 97 insertions(+) create mode 100644 tests/test-timezone-geoclue.cc (limited to 'tests') diff --git a/tests/test-timezone-geoclue.cc b/tests/test-timezone-geoclue.cc new file mode 100644 index 0000000..a577fbd --- /dev/null +++ b/tests/test-timezone-geoclue.cc @@ -0,0 +1,97 @@ +/* + * Copyright 2013 Canonical Ltd. + * + * Authors: + * Charles Kerr + * + * 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 . + */ + +#include "geoclue-fixture.h" + +#include + +//#include + +using unity::indicator::datetime::GeoclueTimezone; + +/*** +**** +***/ + +class TimezoneGeoclueFixture : public GeoclueFixture +{ +}; + +#if 0 +namespace +{ + struct EmitAddressChangedData + { + DbusTestDbusMock * mock = nullptr; + DbusTestDbusMockObject * obj_client = nullptr; + std::string timezone; + EmitAddressChangedData(DbusTestDbusMock * mock_, + DbusTestDbusMockObject * obj_client_, + const std::string& timezone_): mock(mock_), obj_client(obj_client_), timezone(timezone_) {} + }; + + gboolean emit_address_changed_idle (gpointer gdata) + { + auto data = static_cast(gdata); + + GError * error = nullptr; + 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))"), + &error); + if (error) + { + g_warning ("%s: %s", G_STRFUNC, error->message); + g_error_free (error); + } + + delete data; + return G_SOURCE_REMOVE; + } +} +#endif + +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()); + + // 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()); + changed = true; + 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()); +} + + -- cgit v1.2.3 From 172246c997d7b20d7e98fc25a7b23f4a79a0f6a6 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Tue, 17 Dec 2013 22:02:06 -0600 Subject: add formatter + tests --- tests/test-formatter.cc | 270 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 270 insertions(+) create mode 100644 tests/test-formatter.cc (limited to 'tests') diff --git a/tests/test-formatter.cc b/tests/test-formatter.cc new file mode 100644 index 0000000..641338b --- /dev/null +++ b/tests/test-formatter.cc @@ -0,0 +1,270 @@ + +/* + * Copyright 2013 Canonical Ltd. + * + * Authors: + * Charles Kerr + * + * 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 . + */ + +#include "clock-mock.h" +#include "glib-fixture.h" + +#include +#include + +#include + +#include +#include + +using unity::indicator::datetime::Clock; +using unity::indicator::datetime::MockClock; +using unity::indicator::datetime::PhoneFormatter; +using unity::indicator::datetime::DesktopFormatter; + +/*** +**** +***/ + +class FormatterFixture: public GlibFixture +{ + private: + + typedef GlibFixture super; + gchar * original_locale = nullptr; + + protected: + + GSettings * settings = nullptr; + + virtual void SetUp () + { + super::SetUp (); + + settings = g_settings_new (SETTINGS_INTERFACE); + + original_locale = g_strdup (setlocale (LC_TIME, NULL)); + } + + virtual void TearDown () + { + g_clear_object (&settings); + + setlocale (LC_TIME, original_locale); + g_clear_pointer (&original_locale, g_free); + + super::TearDown (); + } + + bool SetLocale (const char * expected_locale, const char * name) + { + setlocale (LC_TIME, expected_locale); + const char * actual_locale = setlocale (LC_TIME, NULL); + if (!g_strcmp0 (expected_locale, actual_locale)) + { + return true; + } + else + { + g_warning ("Unable to set locale to %s; skipping %s locale tests.", expected_locale, name); + return false; + } + } + + inline bool Set24hLocale () { return SetLocale ("C", "24h"); } + inline bool Set12hLocale () { return SetLocale ("en_US.utf8", "12h"); } +}; + + +/** + * Test the phone header format + */ +TEST_F (FormatterFixture, TestPhoneHeader) +{ + GDateTime * now = g_date_time_new_local (2020, 10, 31, 18, 30, 59); + std::shared_ptr mock (new MockClock(now)); + std::shared_ptr clock = std::dynamic_pointer_cast(mock); + + // test the default value in a 24h locale + if (Set24hLocale ()) + { + PhoneFormatter formatter (clock); + EXPECT_EQ (std::string("%H:%M"), formatter.headerFormat.get()); + EXPECT_EQ (std::string("18:30"), formatter.header.get()); + } + + // test the default value in a 12h locale + if (Set12hLocale ()) + { + PhoneFormatter formatter (clock); + EXPECT_EQ (std::string("%l:%M %p"), formatter.headerFormat.get()); + EXPECT_EQ (std::string(" 6:30 PM"), formatter.header.get()); + } +} + +#define EM_SPACE "\u2003" + +/** + * Test the default values of the desktop header format + */ +TEST_F (FormatterFixture, TestDesktopHeader) +{ + struct { + bool is_12h; + bool show_day; + bool show_date; + bool show_year; + const char * expected_format_string; + } test_cases[] = { + { false, false, false, false, "%H:%M" }, + { false, false, false, true, "%H:%M" }, // show_year is ignored iff show_date is false + { false, false, true, false, "%b %e" EM_SPACE "%H:%M" }, + { false, false, true, true, "%b %e %Y" EM_SPACE "%H:%M" }, + { false, true, false, false, "%a" EM_SPACE "%H:%M" }, + { false, true, false, true, "%a" EM_SPACE "%H:%M" }, // show_year is ignored iff show_date is false + { false, true, true, false, "%a %b %e" EM_SPACE "%H:%M" }, + { false, true, true, true, "%a %b %e %Y" EM_SPACE "%H:%M" }, + { true, false, false, false, "%l:%M %p" }, + { true, false, false, true, "%l:%M %p" }, // show_year is ignored iff show_date is false + { true, false, true, false, "%b %e" EM_SPACE "%l:%M %p" }, + { true, false, true, true, "%b %e %Y" EM_SPACE "%l:%M %p" }, + { true, true, false, false, "%a" EM_SPACE "%l:%M %p" }, + { true, true, false, true, "%a" EM_SPACE "%l:%M %p" }, // show_year is ignored iff show_date is false + { true, true, true, false, "%a %b %e" EM_SPACE "%l:%M %p" }, + { 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 mock (new MockClock(now)); + std::shared_ptr clock = std::dynamic_pointer_cast(mock); + + for (int i=0, n=G_N_ELEMENTS(test_cases); i mock (new MockClock(test_cases[i].now)); + std::shared_ptr clock = std::dynamic_pointer_cast(mock); + DesktopFormatter f (clock); + + std::string fmt = f.getRelativeFormat (test_cases[i].then, test_cases[i].then_end); + 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); + } + } + + g_date_time_unref (a); +} + + +/** + * Test the default values of the desktop header format + */ +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); + + struct { + bool is_12h; + GDateTime * now; + GDateTime * then; + GDateTime * then_end; + const char * expected_format_string; + } test_cases[] = { + { false, g_date_time_ref(day), g_date_time_ref(day_begin), g_date_time_ref(day_end), _("Today") }, + { true, g_date_time_ref(day), g_date_time_ref(day_begin), g_date_time_ref(day_end), _("Today") }, + { false, g_date_time_ref(day), g_date_time_ref(tomorrow_begin), g_date_time_ref(tomorrow_end), _("Tomorrow") }, + { true, g_date_time_ref(day), g_date_time_ref(tomorrow_begin), g_date_time_ref(tomorrow_end), _("Tomorrow") } + }; + + for (int i=0, n=G_N_ELEMENTS(test_cases); i mock (new MockClock(test_cases[i].now)); + std::shared_ptr clock = std::dynamic_pointer_cast(mock); + DesktopFormatter f (clock); + + std::string fmt = f.getRelativeFormat (test_cases[i].then, test_cases[i].then_end); + 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); + } + } + + g_date_time_unref (tomorrow_end); + g_date_time_unref (tomorrow_begin); + g_date_time_unref (day_end); + g_date_time_unref (day_begin); + g_date_time_unref (day); +} + + -- cgit v1.2.3 From 38b878589ffb08d2272169d2529703e887933be9 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Tue, 17 Dec 2013 22:03:12 -0600 Subject: add planner + tests --- tests/test-planner-eds.cc | 70 +++++++++++++++++++++++++++++++++++++++++++++++ tests/test-planner.cc | 68 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 138 insertions(+) create mode 100644 tests/test-planner-eds.cc create mode 100644 tests/test-planner.cc (limited to 'tests') diff --git a/tests/test-planner-eds.cc b/tests/test-planner-eds.cc new file mode 100644 index 0000000..986a45e --- /dev/null +++ b/tests/test-planner-eds.cc @@ -0,0 +1,70 @@ +/* + * Copyright 2013 Canonical Ltd. + * + * Authors: + * Charles Kerr + * + * 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 . + */ + +#include "clock-mock.h" +#include "glib-fixture.h" + +#include + +#include + +#include +#include + +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 new file mode 100644 index 0000000..8c74366 --- /dev/null +++ b/tests/test-planner.cc @@ -0,0 +1,68 @@ +/* + * Copyright 2013 Canonical Ltd. + * + * Authors: + * Charles Kerr + * + * 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 . + */ + +#include "clock-mock.h" +#include "glib-fixture.h" + +#include +#include + +#include + +#include +#include + +using unity::indicator::datetime::Appointment; + +/*** +**** +***/ + +typedef GlibFixture PlannerFixture; + + +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); + + Appointment a; + a.summary = "Test"; + a.begin = halloween; + 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())); + + Appointment c; + c.begin = christmas; + 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())); + a = d; + EXPECT_EQ (0, g_date_time_compare (d.begin(), a.begin())); + EXPECT_EQ (0, g_date_time_compare (d.end(), a.end())); +} + -- cgit v1.2.3 From db7b874bbf1a98f85ffe511be230164c40fe080d Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Tue, 17 Dec 2013 22:03:43 -0600 Subject: add locations + tests --- tests/test-locations.cc | 172 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 172 insertions(+) create mode 100644 tests/test-locations.cc (limited to 'tests') diff --git a/tests/test-locations.cc b/tests/test-locations.cc new file mode 100644 index 0000000..c833bed --- /dev/null +++ b/tests/test-locations.cc @@ -0,0 +1,172 @@ + + +/* + * Copyright 2013 Canonical Ltd. + * + * Authors: + * Charles Kerr + * + * 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 . + */ + +#include "clock-mock.h" +#include "glib-fixture.h" + +#include +#include +#include + +#include + +#include +#include + +using unity::indicator::datetime::Location; +using unity::indicator::datetime::Locations; +using unity::indicator::datetime::SettingsLocations; +using unity::indicator::datetime::Timezones; + +/*** +**** +***/ + +class LocationsFixture: public GlibFixture +{ + private: + + typedef GlibFixture super; + + protected: + + GSettings * settings = nullptr; + std::shared_ptr timezones; + const std::string nyc = "America/New_York"; + const std::string chicago = "America/Chicago"; + + virtual void SetUp () + { + super::SetUp (); + + 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); + + timezones.reset (new Timezones); + timezones->timezone.set (chicago); + timezones->timezones.set (std::set({ nyc, chicago })); + } + + virtual void TearDown () + { + //timezones.reset (nullptr); + g_clear_object (&settings); + + super::TearDown (); + } +}; + +TEST_F (LocationsFixture, Timezones) +{ + g_settings_set_boolean (settings, SETTINGS_SHOW_LOCATIONS_S, false); + + SettingsLocations locations (SETTINGS_INTERFACE, timezones); + std::vector 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); +} + +TEST_F (LocationsFixture, SettingsLocations) +{ + SettingsLocations locations (SETTINGS_INTERFACE, timezones); + + std::vector 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); +} + +TEST_F (LocationsFixture, ChangeLocationStrings) +{ + SettingsLocations locations (SETTINGS_INTERFACE, timezones); + + bool locations_changed = false; + locations.locations.changed().connect([&locations_changed, this](const std::vector&){ + locations_changed = true; + g_main_loop_quit (loop); + }); + + 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), SETTINGS_LOCATIONS_S, strv); + return G_SOURCE_REMOVE; + }, settings); + + g_main_loop_run (loop); + + EXPECT_TRUE (locations_changed); + std::vector 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); + locations_changed = false; +} + +TEST_F (LocationsFixture, ChangeLocationVisibility) +{ + SettingsLocations locations (SETTINGS_INTERFACE, timezones); + + bool locations_changed = false; + locations.locations.changed().connect([&locations_changed, this](const std::vector&){ + locations_changed = true; + g_main_loop_quit (loop); + }); + + g_idle_add ([](gpointer gsettings){ + g_settings_set_boolean (static_cast(gsettings), SETTINGS_SHOW_LOCATIONS_S, false); + return G_SOURCE_REMOVE; + }, settings); + + g_main_loop_run (loop); + + EXPECT_TRUE (locations_changed); + std::vector 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); +} -- cgit v1.2.3 From 3b8833efe6ab21387b6f73b4a4ef757445801623 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Tue, 17 Dec 2013 22:10:18 -0600 Subject: add geoclue, glib test fixtures --- tests/CMakeLists.txt | 76 +++++++++++++++++- tests/geoclue-fixture.h | 142 ++++++++++++++++++++++++++++++++ tests/glib-fixture.h | 131 ++++++++++++++++++++++++++++++ tests/test-core.cc | 148 ++++++++++++++++++++++++++++++++++ tests/test-skew.cc | 209 ++++++++++++++++++++++++++++++++++++++++++++++++ tests/test-timezones.cc | 122 ++++++++++++++++++++++++++++ 6 files changed, 825 insertions(+), 3 deletions(-) create mode 100644 tests/geoclue-fixture.h create mode 100644 tests/glib-fixture.h create mode 100644 tests/test-core.cc create mode 100644 tests/test-skew.cc create mode 100644 tests/test-timezones.cc (limited to 'tests') diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 682896b..a424858 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -1,3 +1,12 @@ +# build libgtest +add_library (gtest STATIC + ${GTEST_SOURCE_DIR}/gtest-all.cc + ${GTEST_SOURCE_DIR}/gtest_main.cc) +set_target_properties (gtest PROPERTIES INCLUDE_DIRECTORIES ${INCLUDE_DIRECTORIES} ${GTEST_INCLUDE_DIR}) +set_target_properties (gtest PROPERTIES COMPILE_FLAGS ${COMPILE_FLAGS} -w) + +SET (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x -g ${CC_WARNING_ARGS}") + # build the necessary schemas set_directory_properties (PROPERTIES ADDITIONAL_MAKE_CLEAN_FILES gschemas.compiled) @@ -12,12 +21,73 @@ execute_process (COMMAND ${PKG_CONFIG_EXECUTABLE} gio-2.0 --variable glib_compil OUTPUT_VARIABLE COMPILE_SCHEMA_EXECUTABLE OUTPUT_STRIP_TRAILING_WHITESPACE) add_custom_command (OUTPUT gschemas.compiled - DEPENDS ${CMAKE_SOURCE_DIR}/data/com.canonical.indicator.session.gschema.xml + DEPENDS ${CMAKE_SOURCE_DIR}/data/com.canonical.indicator.datetime.gschema.xml COMMAND cp -f ${CMAKE_SOURCE_DIR}/data/*gschema.xml ${SCHEMA_DIR} COMMAND ${COMPILE_SCHEMA_EXECUTABLE} ${SCHEMA_DIR}) -# look for hearder in our src dir, and also in the directories where we autogenerate files... +# look for headers in our src dir, and also in the directories where we autogenerate files... include_directories (${CMAKE_SOURCE_DIR}/src) -include_directories (${CMAKE_CURRENT_BINARY_DIR} ${SERVICE_INCLUDE_DIRS}) +include_directories (${CMAKE_CURRENT_BINARY_DIR}) +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) +add_test (${TEST_NAME} ${TEST_NAME}) +target_link_libraries (${TEST_NAME} indicatordatetimeservice gtest ${SERVICE_DEPS_LIBRARIES} ${GTEST_LIBS}) + +# test-timezone-geoclue +set (TEST_NAME test-timezone-geoclue) +add_executable (${TEST_NAME} ${TEST_NAME}.cc) +add_test (${TEST_NAME} ${TEST_NAME}) +target_link_libraries (${TEST_NAME} indicatordatetimeservice gtest ${SERVICE_DEPS_LIBRARIES} ${DBUSTEST_LIBRARIES} ${GTEST_LIBS}) + +# test-timezones +set (TEST_NAME test-timezones) +add_executable (${TEST_NAME} ${TEST_NAME}.cc) +add_test (${TEST_NAME} ${TEST_NAME}) +target_link_libraries (${TEST_NAME} indicatordatetimeservice gtest ${SERVICE_DEPS_LIBRARIES} ${DBUSTEST_LIBRARIES} ${GTEST_LIBS}) + +# test-clock +set (TEST_NAME test-clock) +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-formatter +set (TEST_NAME test-formatter) +add_executable (${TEST_NAME} test-formatter.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-planner +set (TEST_NAME test-planner) +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-planner-eds +set (TEST_NAME test-planner-eds) +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) +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/geoclue-fixture.h b/tests/geoclue-fixture.h new file mode 100644 index 0000000..890204a --- /dev/null +++ b/tests/geoclue-fixture.h @@ -0,0 +1,142 @@ +/* + * Copyright 2013 Canonical Ltd. + * + * Authors: + * Charles Kerr + * + * 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 . + */ + +#include "glib-fixture.h" + +#include + +class GeoclueFixture : public GlibFixture +{ + private: + + typedef GlibFixture super; + + GDBusConnection * bus = nullptr; + + protected: + + DbusTestService * service = nullptr; + DbusTestDbusMock * mock = nullptr; + DbusTestDbusMockObject * obj_master = nullptr; + DbusTestDbusMockObject * obj_client = nullptr; + const std::string timezone_1 = "America/Denver"; + + void SetUp () + { + super::SetUp(); + + GError * error = nullptr; + const gchar * const client_path = "/org/freedesktop/Geoclue/Master/client0"; + GString * gstr = g_string_new (nullptr); + + service = dbus_test_service_new (nullptr); + mock = dbus_test_dbus_mock_new ("org.freedesktop.Geoclue.Master"); + + obj_master = dbus_test_dbus_mock_get_object (mock, + "/org/freedesktop/Geoclue/Master", + "org.freedesktop.Geoclue.Master", + nullptr); + g_string_printf (gstr, "ret = '%s'", client_path); + dbus_test_dbus_mock_object_add_method (mock, obj_master, nullptr, "Create", nullptr, G_VARIANT_TYPE_OBJECT_PATH, gstr->str, &error); + + obj_client = dbus_test_dbus_mock_get_object (mock, client_path, "org.freedesktop.Geoclue.MasterClient", nullptr); + dbus_test_dbus_mock_object_add_method (mock, obj_client, nullptr, "SetRequirements", G_VARIANT_TYPE("(iibi)"), nullptr, "", &error); + dbus_test_dbus_mock_object_add_method (mock, obj_client, nullptr, "AddressStart", nullptr, nullptr, "", &error); + dbus_test_dbus_mock_object_add_method (mock, obj_client, "org.freedesktop.Geoclue", "AddReference", nullptr, nullptr, "", &error); + g_string_printf (gstr, "ret = (1385238033, {'timezone': '%s'}, (3, 0.0, 0.0))", timezone_1.c_str()); + dbus_test_dbus_mock_object_add_method (mock, obj_client, "org.freedesktop.Geoclue.Address", "GetAddress", nullptr, G_VARIANT_TYPE("(ia{ss}(idd))"), gstr->str, &error); + + dbus_test_service_add_task(service, DBUS_TEST_TASK(mock)); + dbus_test_service_start_tasks(service); + + bus = g_bus_get_sync (G_BUS_TYPE_SESSION, nullptr, nullptr); + g_dbus_connection_set_exit_on_close (bus, FALSE); + g_object_add_weak_pointer (G_OBJECT(bus), (gpointer*)&bus); + + g_string_free (gstr, TRUE); + } + + virtual void TearDown () + { + g_clear_object (&mock); + g_clear_object (&service); + g_object_unref (bus); + + unsigned int cleartry = 0; + while (bus != nullptr && cleartry < 10) + { + wait_msec (100); + cleartry++; + } + + // I've looked and can't find where this extra ref is coming from. + // is there an unbalanced ref to the bus in the test harness?! + while (bus != NULL) + { + g_object_unref (bus); + wait_msec (1000); + } + + super::TearDown (); + } + +private: + + struct EmitAddressChangedData + { + DbusTestDbusMock * mock = nullptr; + DbusTestDbusMockObject * obj_client = nullptr; + std::string timezone; + EmitAddressChangedData(DbusTestDbusMock * mock_, + DbusTestDbusMockObject * obj_client_, + const std::string& timezone_): mock(mock_), obj_client(obj_client_), timezone(timezone_) {} + }; + + static gboolean emit_address_changed_idle (gpointer gdata) + { + auto data = static_cast(gdata); + auto fmt = g_strdup_printf ("(1385238033, {'timezone': '%s'}, (3, 0.0, 0.0))", data->timezone.c_str()); + + GError * error = nullptr; + 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 (fmt), + &error); + if (error) + { + g_warning("%s: %s", G_STRFUNC, error->message); + g_error_free (error); + } + + g_free (fmt); + delete data; + return G_SOURCE_REMOVE; + } + +public: + + void setGeoclueTimezoneOnIdle (const std::string& newZone) + { + g_timeout_add (50, emit_address_changed_idle, new EmitAddressChangedData(mock, obj_client, newZone.c_str())); + } + +}; + diff --git a/tests/glib-fixture.h b/tests/glib-fixture.h new file mode 100644 index 0000000..043b7e3 --- /dev/null +++ b/tests/glib-fixture.h @@ -0,0 +1,131 @@ +/* + * Copyright 2013 Canonical Ltd. + * + * Authors: + * Charles Kerr + * + * 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 . + */ + +#include + +#include +#include +#include + +#include + +class GlibFixture : public ::testing::Test +{ + private: + + //GLogFunc realLogHandler; + + protected: + + std::map logCounts; + + void testLogCount (GLogLevelFlags log_level, int expected G_GNUC_UNUSED) + { +#if 0 + EXPECT_EQ (expected, logCounts[log_level]); +#endif + + logCounts.erase (log_level); + } + + private: + + 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); + static_cast(self)->logCounts[log_level]++; + } + + protected: + + virtual void SetUp () + { + loop = g_main_loop_new (NULL, FALSE); + + //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); + } + + 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]); +#endif + + // revert to glib's log handler + //g_log_set_default_handler (realLogHandler, this); + + g_clear_pointer (&loop, g_main_loop_unref); + } + + private: + + static gboolean + wait_for_signal__timeout (gpointer 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) + { + g_main_loop_quit (static_cast(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) + { + // 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); + } + + /* convenience func to loop for N msec */ + 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); + } + + GMainLoop * loop; +}; diff --git a/tests/test-core.cc b/tests/test-core.cc new file mode 100644 index 0000000..7ed38a9 --- /dev/null +++ b/tests/test-core.cc @@ -0,0 +1,148 @@ + +/* + * Copyright 2013 Canonical Ltd. + * + * Authors: + * Charles Kerr + * + * 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 . + */ + +#include +#include +#include +#include + +#include +#include + +#include + +#include +#include +#include + +#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 Handler; + + void stop() + { + stop_requested = true; + } + + void run() + { + while (!stop_requested) + { + std::unique_lock 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 lg(guard); + handlers.push(h); + } + + bool stop_requested = false; + std::queue 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 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-skew.cc b/tests/test-skew.cc new file mode 100644 index 0000000..90c0164 --- /dev/null +++ b/tests/test-skew.cc @@ -0,0 +1,209 @@ +/* + * Copyright 2013 Canonical Ltd. + * + * Authors: + * Charles Kerr + * + * 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 . + */ + +#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(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(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 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(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(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(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(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(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(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-timezones.cc b/tests/test-timezones.cc new file mode 100644 index 0000000..cda53a6 --- /dev/null +++ b/tests/test-timezones.cc @@ -0,0 +1,122 @@ +/* + * 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 . + * + * Authors: + * Charles Kerr + */ + +#include "geoclue-fixture.h" + +#include + +#include // fopen() +#include // sync() + +using unity::indicator::datetime::LiveTimezones; + +typedef GeoclueFixture TimezonesFixture; + +#define TIMEZONE_FILE (SANDBOX "/timezone") + +namespace +{ + /* convenience func to set the timezone file */ + void set_file (const std::string& text) + { + FILE * fp = fopen (TIMEZONE_FILE, "w+"); + fprintf (fp, "%s\n", text.c_str()); + fclose (fp); + sync (); + } +} + + +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 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); + }); + + // start listening for a timezone change, then change the timezone + bool zones_changed = false; + auto zones_connection = z.timezones.changed().connect([&zones_changed, &zones, this](const std::set& timezones) { + zones_changed = true; + zones = timezones; + g_main_loop_quit (loop); + }); + + g_idle_add ([](gpointer gz) { + auto az = static_cast(gz); + 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)); + zones_changed = false; + + // now tweak the geoclue value... the geoclue-detected timezone should change, + // causing the 'timezones' property to change + 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)); + + // 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(str)); return G_SOURCE_REMOVE;}, const_cast(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)); + + + +} + + -- cgit v1.2.3 From ee64bb2698adfe27e55615a8856b0e2c78ad8469 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Tue, 14 Jan 2014 23:07:10 -0600 Subject: Function: add fully-tested ActionGroups, per-profile Menus, state object. Form: Add code annotations/comments. Remove dead code. Use Mir style guide. Todo: GSettings toggles, sync with new dbus-test-runner API, get GNOME Panel building again --- tests/CMakeLists.txt | 27 ++- tests/Makefile.am.strings | 38 ---- tests/actions-mock.h | 88 +++++++++ tests/glib-fixture.h | 85 +++++---- tests/planner-mock.c | 34 ++-- tests/state-fixture.h | 75 ++++++++ tests/test-actions.cc | 173 ++++++++++++++++++ tests/test-clock.cc | 176 +++++++++--------- tests/test-core.cc | 148 --------------- tests/test-dbus-fixture.h | 100 ++++++++++ tests/test-formatter.cc | 61 ++++--- tests/test-indicator.cc | 92 ---------- tests/test-locations.cc | 136 +++++++------- tests/test-menus.cc | 406 +++++++++++++++++++++++++++++++++++++++++ tests/test-planner-eds.cc | 70 ------- tests/test-planner.cc | 49 +++-- tests/test-skew.cc | 209 --------------------- tests/test-timezone-file.cc | 60 +++--- tests/test-timezone-geoclue.cc | 28 +-- tests/test-timezones.cc | 83 ++++----- tests/test-utils.cc | 153 ++++++++-------- 21 files changed, 1301 insertions(+), 990 deletions(-) delete mode 100644 tests/Makefile.am.strings create mode 100644 tests/actions-mock.h create mode 100644 tests/state-fixture.h create mode 100644 tests/test-actions.cc delete mode 100644 tests/test-core.cc create mode 100644 tests/test-dbus-fixture.h delete mode 100644 tests/test-indicator.cc create mode 100644 tests/test-menus.cc delete mode 100644 tests/test-planner-eds.cc delete mode 100644 tests/test-skew.cc (limited to 'tests') 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 . + * + * Authors: + * Charles Kerr + */ + +#ifndef INDICATOR_DATETIME_ACTIONS_MOCK_H +#define INDICATOR_DATETIME_ACTIONS_MOCK_H + +#include + +#include + +namespace unity { +namespace indicator { +namespace datetime { + +class MockActions: public Actions +{ +public: + MockActions(std::shared_ptr& state_in): Actions(state_in) {} + ~MockActions() =default; + + enum Action { OpenDesktopSettings, OpenPhoneSettings, OpenPhoneClockApp, + OpenPlanner, OpenPlannerAt, OpenAppointment, + SetLocation, SetCalendarDate }; + const std::vector& 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 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 +#include // setlocale() + class GlibFixture : public ::testing::Test { private: @@ -35,96 +37,101 @@ class GlibFixture : public ::testing::Test std::map 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(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(loop)); + g_main_loop_quit(static_cast(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 . + * + * Authors: + * Charles Kerr + */ + +#include "glib-fixture.h" +#include "actions-mock.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace unity::indicator::datetime; + +class StateFixture: public GlibFixture +{ +private: + typedef GlibFixture super; + +protected: + std::shared_ptr m_clock; + std::shared_ptr m_state; + std::shared_ptr m_mock_actions; + std::shared_ptr 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(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(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 . + * + * Authors: + * Charles Kerr + */ + +#include + +#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({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({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(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(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 zones (new Timezones); + std::shared_ptr 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(str)); return G_SOURCE_REMOVE; }, const_cast(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 zones (new Timezones); + std::shared_ptr 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 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 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(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(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 zones (new Timezones); + std::shared_ptr 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(gself)->emitPrepareForSleep(); - return G_SOURCE_REMOVE; + g_idle_add([](gpointer gself){ + static_cast(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 zones (new Timezones); + std::shared_ptr 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 - * - * 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 . - */ - -#include -#include -#include -#include - -#include -#include - -#include - -#include -#include -#include - -#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 Handler; - - void stop() - { - stop_requested = true; - } - - void run() - { - while (!stop_requested) - { - std::unique_lock 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 lg(guard); - handlers.push(h); - } - - bool stop_requested = false; - std::queue 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 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 . + * + * Authors: + * Charles Kerr + */ + +#include "glib-fixture.h" + +/*** +**** +***/ + +class TestDBusFixture: public GlibFixture +{ + public: + + TestDBusFixture() {} + + TestDBusFixture(const std::vector& 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(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(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 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 . */ -#include "clock-mock.h" #include "glib-fixture.h" +#include #include #include @@ -30,9 +30,10 @@ #include 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 mock (new MockClock(now)); + std::shared_ptr mock (new MockClock(DateTime(now))); + g_date_time_unref(now); std::shared_ptr clock = std::dynamic_pointer_cast(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 mock (new MockClock(now)); + GDateTime * now = g_date_time_new_local(2020, 10, 31, 18, 30, 59); + std::shared_ptr mock(new MockClock(DateTime(now))); + g_date_time_unref(now); std::shared_ptr clock = std::dynamic_pointer_cast(mock); for (int i=0, n=G_N_ELEMENTS(test_cases); i mock (new MockClock(test_cases[i].now)); + DateTime tmp(test_cases[i].now); + tmp.get(); + std::shared_ptr mock (new MockClock(tmp));//DateTime(test_cases[i].now))); std::shared_ptr clock = std::dynamic_pointer_cast(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 mock (new MockClock(test_cases[i].now)); + std::shared_ptr mock (new MockClock(DateTime(test_cases[i].now))); std::shared_ptr clock = std::dynamic_pointer_cast(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 - -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 . -*/ - -#include - -#include - -/*** -**** -***/ - -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(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 . */ -#include "clock-mock.h" #include "glib-fixture.h" +#include #include #include #include @@ -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({ nyc, chicago })); + timezones.reset(new Timezones); + timezones->timezone.set(chicago); + timezones->timezones.set(std::set({ 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 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 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&){ 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), SETTINGS_LOCATIONS_S, strv); + g_settings_set_strv(static_cast(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 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&){ 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), SETTINGS_SHOW_LOCATIONS_S, false); + g_idle_add([](gpointer gsettings){ + g_settings_set_boolean(static_cast(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 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 . + * + * Authors: + * Charles Kerr + */ + + +#include "actions-mock.h" +#include "state-fixture.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +using namespace unity::indicator::datetime; + +class MenuFixture: public StateFixture +{ +private: + typedef StateFixture super; + +protected: + std::shared_ptr m_menu_factory; + std::vector> 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; ibuildMenu(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 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& 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 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 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; imenu_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 - * - * 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 . - */ - -#include "clock-mock.h" -#include "glib-fixture.h" - -#include - -#include - -#include -#include - -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 . */ -#include "clock-mock.h" #include "glib-fixture.h" #include +#include +#include #include - -#include +#include #include #include 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 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 - * - * 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 . - */ - -#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(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(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 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(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(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(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(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(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(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(gself)->set_file ("America/New_York"); - // static_cast(gtz)->timezone.set ("America/New_York"); + g_idle_add([](gpointer gself){ + static_cast(gself)->set_file("America/New_York"); + // static_cast(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(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 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 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& 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(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(str)); return G_SOURCE_REMOVE;}, const_cast(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(str)); return G_SOURCE_REMOVE;}, const_cast(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 - -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 . -*/ + * 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 . + * + * Authors: + * Charles Kerr + */ #include @@ -27,36 +27,33 @@ with this program. If not, see . **** ***/ -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 Date: Thu, 16 Jan 2014 15:10:39 -0600 Subject: Implement Settings, a properties-cpp wrapper around GSettings --- tests/CMakeLists.txt | 14 ++++ tests/test-settings.cc | 197 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 211 insertions(+) create mode 100644 tests/test-settings.cc (limited to 'tests') diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index fb55f5a..a908801 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -91,6 +91,20 @@ add_test (${TEST_NAME} ${TEST_NAME}) add_dependencies (${TEST_NAME} libindicatordatetimeservice) target_link_libraries (${TEST_NAME} indicatordatetimeservice gtest ${SERVICE_DEPS_LIBRARIES} ${GTEST_LIBS}) +# test-utils +set (TEST_NAME test-utils) +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-utils +set (TEST_NAME test-settings) +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) diff --git a/tests/test-settings.cc b/tests/test-settings.cc new file mode 100644 index 0000000..9e52197 --- /dev/null +++ b/tests/test-settings.cc @@ -0,0 +1,197 @@ +/* + * Copyright 2013 Canonical Ltd. + * + * Authors: + * Charles Kerr + * + * 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 . + */ + +#include "glib-fixture.h" + +#include +#include + +using namespace unity::indicator::datetime; + +/*** +**** +***/ + +class SettingsFixture: public GlibFixture +{ +private: + typedef GlibFixture super; + +protected: + + std::shared_ptr m_live; + std::shared_ptr m_settings; + GSettings * m_gsettings; + + virtual void SetUp() + { + super::SetUp(); + + m_gsettings = g_settings_new(SETTINGS_INTERFACE); + m_live.reset(new LiveSettings); + m_settings = std::dynamic_pointer_cast(m_live); + } + + virtual void TearDown() + { + g_clear_object(&m_gsettings); + m_settings.reset(); + m_live.reset(); + + super::TearDown(); + } + + void TestBoolProperty(core::Property& property, const gchar* key) + { + EXPECT_EQ(g_settings_get_boolean(m_gsettings, key), property.get()); + g_settings_set_boolean(m_gsettings, key, false); + EXPECT_EQ(false, property.get()); + g_settings_set_boolean(m_gsettings, key, true); + EXPECT_EQ(true, property.get()); + + property.set(false); + EXPECT_EQ(false, g_settings_get_boolean(m_gsettings, key)); + property.set(true); + EXPECT_EQ(true, g_settings_get_boolean(m_gsettings, key)); + } + + void TestStringProperty(core::Property& property, const gchar* key) + { + gchar* tmp; + std::string str; + + tmp = g_settings_get_string(m_gsettings, key); + EXPECT_EQ(tmp, property.get()); + g_clear_pointer(&tmp, g_free); + + str = "a"; + g_settings_set_string(m_gsettings, key, str.c_str()); + EXPECT_EQ(str, property.get()); + + str = "b"; + g_settings_set_string(m_gsettings, key, str.c_str()); + EXPECT_EQ(str, property.get()); + + str = "a"; + property.set(str); + tmp = g_settings_get_string(m_gsettings, key); + EXPECT_EQ(str, tmp); + g_clear_pointer(&tmp, g_free); + + str = "b"; + property.set(str); + tmp = g_settings_get_string(m_gsettings, key); + EXPECT_EQ(str, tmp); + g_clear_pointer(&tmp, g_free); + } +}; + +/*** +**** +***/ + +TEST_F(SettingsFixture, HelloWorld) +{ + EXPECT_TRUE(true); +} + +TEST_F(SettingsFixture, BoolProperties) +{ + TestBoolProperty(m_settings->show_seconds, SETTINGS_SHOW_SECONDS_S); + TestBoolProperty(m_settings->show_calendar, SETTINGS_SHOW_CALENDAR_S); + TestBoolProperty(m_settings->show_clock, SETTINGS_SHOW_CLOCK_S); + TestBoolProperty(m_settings->show_date, SETTINGS_SHOW_DATE_S); + TestBoolProperty(m_settings->show_day, SETTINGS_SHOW_DAY_S); + TestBoolProperty(m_settings->show_detected_location, SETTINGS_SHOW_DETECTED_S); + TestBoolProperty(m_settings->show_events, SETTINGS_SHOW_EVENTS_S); + TestBoolProperty(m_settings->show_locations, SETTINGS_SHOW_LOCATIONS_S); + TestBoolProperty(m_settings->show_week_numbers, SETTINGS_SHOW_WEEK_NUMBERS_S); + TestBoolProperty(m_settings->show_year, SETTINGS_SHOW_YEAR_S); +} + +TEST_F(SettingsFixture, StringProperties) +{ + TestStringProperty(m_settings->custom_time_format, SETTINGS_CUSTOM_TIME_FORMAT_S); + TestStringProperty(m_settings->timezone_name, SETTINGS_TIMEZONE_NAME_S); +} + +TEST_F(SettingsFixture, TimeFormatMode) +{ + const auto key = SETTINGS_TIME_FORMAT_S; + const TimeFormatMode modes[] = { TIME_FORMAT_MODE_LOCALE_DEFAULT, + TIME_FORMAT_MODE_12_HOUR, + TIME_FORMAT_MODE_24_HOUR, + TIME_FORMAT_MODE_CUSTOM }; + + for(const auto& mode : modes) + { + g_settings_set_enum(m_gsettings, key, mode); + EXPECT_EQ(mode, m_settings->time_format_mode.get()); + } + + for(const auto& mode : modes) + { + m_settings->time_format_mode.set(mode); + EXPECT_EQ(mode, g_settings_get_enum(m_gsettings, key)); + } +} + +namespace +{ + std::vector strv_to_vector(const gchar** strv) + { + std::vector v; + for(int i=0; strv && strv[i]; i++) + v.push_back(strv[i]); + return v; + } +}; + +TEST_F(SettingsFixture, Locations) +{ + const auto key = SETTINGS_LOCATIONS_S; + + const gchar* astrv[] = {"America/Los_Angeles Oakland", "America/Chicago Oklahoma City", "Europe/London London", NULL}; + const gchar* bstrv[] = {"America/Denver", "Europe/London London", "Europe/Berlin Berlin", NULL}; + const std::vector av = strv_to_vector(astrv); + const std::vector bv = strv_to_vector(bstrv); + + g_settings_set_strv(m_gsettings, key, astrv); + EXPECT_EQ(av, m_settings->locations.get()); + g_settings_set_strv(m_gsettings, key, bstrv); + EXPECT_EQ(bv, m_settings->locations.get()); + + m_settings->locations.set(av); + auto tmp = g_settings_get_strv(m_gsettings, key); + auto vtmp = strv_to_vector((const gchar**)tmp); + g_strfreev(tmp); + EXPECT_EQ(av, vtmp); + + m_settings->locations.set(bv); + tmp = g_settings_get_strv(m_gsettings, key); + vtmp = strv_to_vector((const gchar**)tmp); + g_strfreev(tmp); + EXPECT_EQ(bv, vtmp); +} + +#if 0 + core::Property> locations; + core::Property time_format_mode; + +#endif -- cgit v1.2.3 From 78d0a231c12c159d1130ec080efab472f59851af Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Thu, 16 Jan 2014 16:42:36 -0600 Subject: update DesktopFormatter class to use the "Settings" class instead of using GSettings directly. --- tests/test-formatter.cc | 177 ++++++++++++++++++++++-------------------------- 1 file changed, 80 insertions(+), 97 deletions(-) (limited to 'tests') diff --git a/tests/test-formatter.cc b/tests/test-formatter.cc index 42c828c..9950453 100644 --- a/tests/test-formatter.cc +++ b/tests/test-formatter.cc @@ -22,18 +22,14 @@ #include #include -#include +#include #include #include #include -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 namespace unity::indicator::datetime; /*** **** @@ -44,75 +40,73 @@ class FormatterFixture: public GlibFixture private: typedef GlibFixture super; - gchar * original_locale = nullptr; + gchar* m_original_locale = nullptr; protected: - GSettings * settings = nullptr; + std::shared_ptr m_settings; - virtual void SetUp () + virtual void SetUp() { - super::SetUp (); + super::SetUp(); - settings = g_settings_new (SETTINGS_INTERFACE); - - original_locale = g_strdup (setlocale (LC_TIME, NULL)); + m_settings.reset(new Settings); + m_original_locale = g_strdup(setlocale(LC_TIME, nullptr)); } - virtual void TearDown () + virtual void TearDown() { - g_clear_object (&settings); + m_settings.reset(); - setlocale (LC_TIME, original_locale); - g_clear_pointer (&original_locale, g_free); + setlocale(LC_TIME, m_original_locale); + g_clear_pointer(&m_original_locale, g_free); - super::TearDown (); + super::TearDown(); } - bool SetLocale (const char * expected_locale, const char * name) + bool SetLocale(const char* expected_locale, const char* name) { - setlocale (LC_TIME, expected_locale); - const char * actual_locale = setlocale (LC_TIME, NULL); - if (!g_strcmp0 (expected_locale, actual_locale)) + setlocale(LC_TIME, expected_locale); + const auto actual_locale = setlocale(LC_TIME, nullptr); + if (!g_strcmp0(expected_locale, actual_locale)) { return true; } else { - g_warning ("Unable to set locale to %s; skipping %s locale tests.", expected_locale, name); + g_warning("Unable to set locale to %s; skipping %s locale tests.", expected_locale, name); return false; } } - inline bool Set24hLocale () { return SetLocale ("C", "24h"); } - inline bool Set12hLocale () { return SetLocale ("en_US.utf8", "12h"); } + inline bool Set24hLocale() { return SetLocale("C", "24h"); } + inline bool Set12hLocale() { return SetLocale("en_US.utf8", "12h"); } }; /** * Test the phone header format */ -TEST_F (FormatterFixture, TestPhoneHeader) +TEST_F(FormatterFixture, TestPhoneHeader) { - GDateTime * now = g_date_time_new_local (2020, 10, 31, 18, 30, 59); - std::shared_ptr mock (new MockClock(DateTime(now))); + auto now = g_date_time_new_local(2020, 10, 31, 18, 30, 59); + std::shared_ptr clock(new MockClock(DateTime(now))); g_date_time_unref(now); - std::shared_ptr clock = std::dynamic_pointer_cast(mock); // test the default value in a 24h locale - if (Set24hLocale ()) + if(Set24hLocale()) { - PhoneFormatter formatter (clock); - EXPECT_EQ (std::string("%H:%M"), formatter.headerFormat.get()); - EXPECT_EQ (std::string("18:30"), formatter.header.get()); + PhoneFormatter formatter(clock); + EXPECT_EQ(std::string("%H:%M"), formatter.headerFormat.get()); + EXPECT_EQ(std::string("18:30"), formatter.header.get()); } // test the default value in a 12h locale - if (Set12hLocale ()) + if(Set12hLocale()) { - PhoneFormatter formatter (clock); - EXPECT_EQ (std::string("%l:%M %p"), formatter.headerFormat.get()); - EXPECT_EQ (std::string(" 6:30 PM"), formatter.header.get()); + PhoneFormatter formatter(clock); + EXPECT_EQ(std::string("%l:%M %p"), formatter.headerFormat.get()); + EXPECT_EQ(std::string(" 6:30 PM"), formatter.header.get()); } } @@ -121,14 +115,14 @@ TEST_F (FormatterFixture, TestPhoneHeader) /** * Test the default values of the desktop header format */ -TEST_F (FormatterFixture, TestDesktopHeader) +TEST_F(FormatterFixture, TestDesktopHeader) { struct { bool is_12h; bool show_day; bool show_date; bool show_year; - const char * expected_format_string; + const char* expected_format_string; } test_cases[] = { { false, false, false, false, "%H:%M" }, { false, false, false, true, "%H:%M" }, // show_year is ignored iff show_date is false @@ -148,26 +142,21 @@ 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 mock(new MockClock(DateTime(now))); + auto now = g_date_time_new_local(2020, 10, 31, 18, 30, 59); + std::shared_ptr clock(new MockClock(DateTime(now))); g_date_time_unref(now); - std::shared_ptr clock = std::dynamic_pointer_cast(mock); - for (int i=0, n=G_N_ELEMENTS(test_cases); ishow_day.set(test_case.show_day); + m_settings->show_date.set(test_case.show_date); + m_settings->show_year.set(test_case.show_year); - ASSERT_STREQ (test_cases[i].expected_format_string, f.headerFormat.get().c_str()); - - g_settings_reset (settings, SETTINGS_SHOW_DAY_S); - g_settings_reset (settings, SETTINGS_SHOW_DATE_S); - g_settings_reset (settings, SETTINGS_SHOW_YEAR_S); + ASSERT_STREQ(test_case.expected_format_string, f.headerFormat.get().c_str()); } } } @@ -175,15 +164,15 @@ TEST_F (FormatterFixture, TestDesktopHeader) /** * Test the default values of the desktop header format */ -TEST_F (FormatterFixture, TestUpcomingTimes) +TEST_F(FormatterFixture, TestUpcomingTimes) { - auto 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; - const char * expected_format_string; + GDateTime* now; + GDateTime* then; + const char* expected_format_string; } test_cases[] = { { 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 @@ -200,45 +189,42 @@ TEST_F (FormatterFixture, TestUpcomingTimes) { 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 mock (new MockClock(tmp));//DateTime(test_cases[i].now))); - std::shared_ptr clock = std::dynamic_pointer_cast(mock); - DesktopFormatter f (clock); + std::shared_ptr clock (new MockClock(DateTime(test_case.now))); + DesktopFormatter f(clock, m_settings); - std::string fmt = f.getRelativeFormat (test_cases[i].then); - ASSERT_STREQ (test_cases[i].expected_format_string, fmt.c_str()); + const auto fmt = f.getRelativeFormat(test_case.then); + ASSERT_EQ(test_case.expected_format_string, fmt); - 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_case.now, g_date_time_unref); + g_clear_pointer(&test_case.then, g_date_time_unref); } } - g_date_time_unref (a); + g_date_time_unref(a); } /** * Test the default values of the desktop header format */ -TEST_F (FormatterFixture, TestEventTimes) +TEST_F(FormatterFixture, TestEventTimes) { - 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); + 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; - GDateTime * now; - GDateTime * then; - GDateTime * then_end; - const char * expected_format_string; + GDateTime* now; + GDateTime* then; + GDateTime* then_end; + const char* expected_format_string; } test_cases[] = { { false, g_date_time_ref(day), g_date_time_ref(day_begin), g_date_time_ref(day_end), _("Today") }, { true, g_date_time_ref(day), g_date_time_ref(day_begin), g_date_time_ref(day_end), _("Today") }, @@ -246,28 +232,25 @@ TEST_F (FormatterFixture, TestEventTimes) { true, g_date_time_ref(day), g_date_time_ref(tomorrow_begin), g_date_time_ref(tomorrow_end), _("Tomorrow") } }; - for (int i=0, n=G_N_ELEMENTS(test_cases); i mock (new MockClock(DateTime(test_cases[i].now))); - std::shared_ptr clock = std::dynamic_pointer_cast(mock); - DesktopFormatter f (clock); + std::shared_ptr clock(new MockClock(DateTime(test_case.now))); + DesktopFormatter f(clock, m_settings); - std::string fmt = f.getRelativeFormat (test_cases[i].then, test_cases[i].then_end); - ASSERT_STREQ (test_cases[i].expected_format_string, fmt.c_str()); + const auto fmt = f.getRelativeFormat(test_case.then, test_case.then_end); + ASSERT_STREQ(test_case.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); + g_clear_pointer(&test_case.now, g_date_time_unref); + g_clear_pointer(&test_case.then, g_date_time_unref); + g_clear_pointer(&test_case.then_end, g_date_time_unref); } } - g_date_time_unref (tomorrow_end); - g_date_time_unref (tomorrow_begin); - g_date_time_unref (day_end); - g_date_time_unref (day_begin); - g_date_time_unref (day); + g_date_time_unref(tomorrow_end); + g_date_time_unref(tomorrow_begin); + g_date_time_unref(day_end); + g_date_time_unref(day_begin); + g_date_time_unref(day); } - - -- cgit v1.2.3 From 9c81a4d60d06b1f33001602cd0cde9844c9233a6 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Thu, 16 Jan 2014 16:44:06 -0600 Subject: update SettingsLocations class to use the "Settings" class instead of using GSettings directly. --- tests/test-locations.cc | 133 +++++++++++++++++++++++------------------------- 1 file changed, 65 insertions(+), 68 deletions(-) (limited to 'tests') diff --git a/tests/test-locations.cc b/tests/test-locations.cc index edaac69..65adbc7 100644 --- a/tests/test-locations.cc +++ b/tests/test-locations.cc @@ -21,18 +21,11 @@ #include "glib-fixture.h" -#include -#include #include -#include - -#include - -#include -#include using unity::indicator::datetime::Location; using unity::indicator::datetime::Locations; +using unity::indicator::datetime::Settings; using unity::indicator::datetime::SettingsLocations; using unity::indicator::datetime::Timezones; @@ -48,8 +41,9 @@ class LocationsFixture: public GlibFixture protected: - GSettings * settings = nullptr; - std::shared_ptr timezones; + //GSettings * settings = nullptr; + std::shared_ptr m_settings; + std::shared_ptr m_timezones; const std::string nyc = "America/New_York"; const std::string chicago = "America/Chicago"; @@ -57,20 +51,24 @@ class LocationsFixture: public GlibFixture { super::SetUp(); - 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); - - timezones.reset(new Timezones); - timezones->timezone.set(chicago); - timezones->timezones.set(std::set({ nyc, chicago })); + m_settings.reset(new Settings); + m_settings->show_locations.set(true); + m_settings->locations.set({"America/Los_Angeles Oakland", + "America/Chicago Chicago", + "America/Chicago Oklahoma City", + "America/Toronto Toronto", + "Europe/London London", + "Europe/Berlin Berlin"}); + + m_timezones.reset(new Timezones); + m_timezones->timezone.set(chicago); + m_timezones->timezones.set(std::set({ nyc, chicago })); } virtual void TearDown() { - //timezones.reset(nullptr); - g_clear_object(&settings); + m_timezones.reset(); + m_settings.reset(); super::TearDown(); } @@ -78,42 +76,42 @@ class LocationsFixture: public GlibFixture TEST_F(LocationsFixture, Timezones) { - g_settings_set_boolean(settings, SETTINGS_SHOW_LOCATIONS_S, false); + m_settings->show_locations.set(false); - SettingsLocations locations(SETTINGS_INTERFACE, timezones); - std::vector l = locations.locations.get(); + SettingsLocations locations(m_settings, m_timezones); + const auto 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_STREQ("Chicago", l[0].name().c_str()); + EXPECT_EQ(chicago, l[0].zone()); + EXPECT_EQ("New York", l[1].name()); + EXPECT_EQ(nyc, l[1].zone()); } TEST_F(LocationsFixture, SettingsLocations) { - SettingsLocations locations(SETTINGS_INTERFACE, timezones); + SettingsLocations locations(m_settings, m_timezones); - std::vector l = locations.locations.get(); + const auto 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("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) { - SettingsLocations locations(SETTINGS_INTERFACE, timezones); + SettingsLocations locations(m_settings, m_timezones); bool locations_changed = false; locations.locations.changed().connect([&locations_changed, this](const std::vector&){ @@ -121,33 +119,32 @@ TEST_F(LocationsFixture, ChangeLocationStrings) g_main_loop_quit(loop); }); - 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), SETTINGS_LOCATIONS_S, strv); + g_idle_add([](gpointer settings){ + static_cast(settings)->locations.set({"America/Los_Angeles Oakland", "Europe/London London", "Europe/Berlin Berlin"}); return G_SOURCE_REMOVE; - }, settings); + }, m_settings.get()); g_main_loop_run(loop); EXPECT_TRUE(locations_changed); - std::vector l = locations.locations.get(); + const auto 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("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) { - SettingsLocations locations(SETTINGS_INTERFACE, timezones); + SettingsLocations locations(m_settings, m_timezones); bool locations_changed = false; locations.locations.changed().connect([&locations_changed, this](const std::vector&){ @@ -155,18 +152,18 @@ TEST_F(LocationsFixture, ChangeLocationVisibility) g_main_loop_quit(loop); }); - g_idle_add([](gpointer gsettings){ - g_settings_set_boolean(static_cast(gsettings), SETTINGS_SHOW_LOCATIONS_S, false); + g_idle_add([](gpointer settings){ + static_cast(settings)->show_locations.set(false); return G_SOURCE_REMOVE; - }, settings); + }, m_settings.get()); g_main_loop_run(loop); EXPECT_TRUE(locations_changed); - std::vector l = locations.locations.get(); + const auto 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("Chicago", l[0].name()); + EXPECT_EQ(chicago, l[0].zone()); + EXPECT_EQ("New York", l[1].name()); + EXPECT_EQ(nyc, l[1].zone()); } -- cgit v1.2.3 From a2b5c79157fa8db36d94786de1b86b756308912d Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Thu, 16 Jan 2014 16:45:40 -0600 Subject: Plug the Settings object into the State container s.t. menus and actions can update themselves when the user's settings change. --- tests/test-menus.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'tests') diff --git a/tests/test-menus.cc b/tests/test-menus.cc index 88e4706..0f86b0d 100644 --- a/tests/test-menus.cc +++ b/tests/test-menus.cc @@ -170,7 +170,7 @@ protected: 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); + m_state->settings->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)); @@ -179,7 +179,7 @@ protected: // when "show_events" is true, // there should be an "add event" button even if there aren't any appointments std::vector appointments; - m_state->show_events.set(true); + m_state->settings->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); -- cgit v1.2.3 From 4cc19729c540ffba163d5c9a53b9352fe61fe8af Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Thu, 16 Jan 2014 17:28:37 -0600 Subject: in utils.c, make a version of get_timezone_name() that doesn't require a GSettings argument. Update utils tests. --- tests/state-fixture.h | 1 + tests/test-utils.cc | 79 ++++++++++++++++----------------------------------- 2 files changed, 25 insertions(+), 55 deletions(-) (limited to 'tests') diff --git a/tests/state-fixture.h b/tests/state-fixture.h index 0286ea9..3c6ecd5 100644 --- a/tests/state-fixture.h +++ b/tests/state-fixture.h @@ -50,6 +50,7 @@ protected: const DateTime now = DateTime::NowLocal(); m_clock.reset(new MockClock(now)); m_state.reset(new State); + m_state->settings.reset(new Settings); m_state->timezones.reset(new Timezones); m_state->clock = std::dynamic_pointer_cast(m_clock); m_state->planner.reset(new MockPlanner); diff --git a/tests/test-utils.cc b/tests/test-utils.cc index 8246396..2fe6a2e 100644 --- a/tests/test-utils.cc +++ b/tests/test-utils.cc @@ -17,22 +17,16 @@ * Charles Kerr */ -#include - -#include - -#include "utils.h" +#include -/*** -**** -***/ +#include TEST(UtilsTest, SplitSettingsLocation) { struct { - const char * location; - const char * expected_zone; - const char * expected_name; + 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" }, @@ -43,63 +37,38 @@ TEST(UtilsTest, SplitSettingsLocation) { "UTC UTC", "UTC", "UTC" } }; - for(guint i=0, n=G_N_ELEMENTS(test_cases); i Date: Thu, 16 Jan 2014 21:23:57 -0600 Subject: get timezone, clock tests running again with Settings & State --- tests/geoclue-fixture.h | 48 +++++++------ tests/test-clock.cc | 168 ++++++++++------------------------------------ tests/test-dbus-fixture.h | 14 ++-- tests/test-timezones.cc | 21 +++--- 4 files changed, 82 insertions(+), 169 deletions(-) (limited to 'tests') diff --git a/tests/geoclue-fixture.h b/tests/geoclue-fixture.h index 890204a..7e29018 100644 --- a/tests/geoclue-fixture.h +++ b/tests/geoclue-fixture.h @@ -33,8 +33,10 @@ class GeoclueFixture : public GlibFixture DbusTestService * service = nullptr; DbusTestDbusMock * mock = nullptr; - DbusTestDbusMockObject * obj_master = nullptr; - DbusTestDbusMockObject * obj_client = nullptr; + DbusTestDbusMockObject * obj_geo = nullptr; + DbusTestDbusMockObject * obj_geo_m = nullptr; + DbusTestDbusMockObject * obj_geo_mc = nullptr; + DbusTestDbusMockObject * obj_geo_addr = nullptr; const std::string timezone_1 = "America/Denver"; void SetUp () @@ -42,25 +44,31 @@ class GeoclueFixture : public GlibFixture super::SetUp(); GError * error = nullptr; - const gchar * const client_path = "/org/freedesktop/Geoclue/Master/client0"; + const auto master_path = "/org/freedesktop/Geoclue/Master"; + const auto client_path = "/org/freedesktop/Geoclue/Master/client0"; GString * gstr = g_string_new (nullptr); service = dbus_test_service_new (nullptr); mock = dbus_test_dbus_mock_new ("org.freedesktop.Geoclue.Master"); - obj_master = dbus_test_dbus_mock_get_object (mock, - "/org/freedesktop/Geoclue/Master", - "org.freedesktop.Geoclue.Master", - nullptr); + auto interface = "org.freedesktop.Geoclue.Master"; + obj_geo_m = dbus_test_dbus_mock_get_object (mock, master_path, interface, nullptr); g_string_printf (gstr, "ret = '%s'", client_path); - dbus_test_dbus_mock_object_add_method (mock, obj_master, nullptr, "Create", nullptr, G_VARIANT_TYPE_OBJECT_PATH, gstr->str, &error); + dbus_test_dbus_mock_object_add_method (mock, obj_geo_m, "Create", nullptr, G_VARIANT_TYPE_OBJECT_PATH, gstr->str, &error); - obj_client = dbus_test_dbus_mock_get_object (mock, client_path, "org.freedesktop.Geoclue.MasterClient", nullptr); - dbus_test_dbus_mock_object_add_method (mock, obj_client, nullptr, "SetRequirements", G_VARIANT_TYPE("(iibi)"), nullptr, "", &error); - dbus_test_dbus_mock_object_add_method (mock, obj_client, nullptr, "AddressStart", nullptr, nullptr, "", &error); - dbus_test_dbus_mock_object_add_method (mock, obj_client, "org.freedesktop.Geoclue", "AddReference", nullptr, nullptr, "", &error); + interface = "org.freedesktop.Geoclue.MasterClient"; + obj_geo_mc = dbus_test_dbus_mock_get_object (mock, client_path, interface, nullptr); + dbus_test_dbus_mock_object_add_method (mock, obj_geo_mc, "SetRequirements", G_VARIANT_TYPE("(iibi)"), nullptr, "", &error); + dbus_test_dbus_mock_object_add_method (mock, obj_geo_mc, "AddressStart", nullptr, nullptr, "", &error); + + interface = "org.freedesktop.Geoclue"; + obj_geo = dbus_test_dbus_mock_get_object (mock, client_path, interface, nullptr); + dbus_test_dbus_mock_object_add_method (mock, obj_geo, "AddReference", nullptr, nullptr, "", &error); g_string_printf (gstr, "ret = (1385238033, {'timezone': '%s'}, (3, 0.0, 0.0))", timezone_1.c_str()); - dbus_test_dbus_mock_object_add_method (mock, obj_client, "org.freedesktop.Geoclue.Address", "GetAddress", nullptr, G_VARIANT_TYPE("(ia{ss}(idd))"), gstr->str, &error); + + interface = "org.freedesktop.Geoclue.Address"; + obj_geo_addr = dbus_test_dbus_mock_get_object (mock, client_path, interface, nullptr); + dbus_test_dbus_mock_object_add_method (mock, obj_geo_addr, "GetAddress", nullptr, G_VARIANT_TYPE("(ia{ss}(idd))"), gstr->str, &error); dbus_test_service_add_task(service, DBUS_TEST_TASK(mock)); dbus_test_service_start_tasks(service); @@ -101,11 +109,11 @@ private: struct EmitAddressChangedData { DbusTestDbusMock * mock = nullptr; - DbusTestDbusMockObject * obj_client = nullptr; + DbusTestDbusMockObject * obj_geo_addr = nullptr; std::string timezone; - EmitAddressChangedData(DbusTestDbusMock * mock_, - DbusTestDbusMockObject * obj_client_, - const std::string& timezone_): mock(mock_), obj_client(obj_client_), timezone(timezone_) {} + EmitAddressChangedData(DbusTestDbusMock* mock_, + DbusTestDbusMockObject* obj_geo_addr_, + const std::string& timezone_): mock(mock_), obj_geo_addr(obj_geo_addr_), timezone(timezone_) {} }; static gboolean emit_address_changed_idle (gpointer gdata) @@ -114,8 +122,8 @@ private: auto fmt = g_strdup_printf ("(1385238033, {'timezone': '%s'}, (3, 0.0, 0.0))", data->timezone.c_str()); GError * error = nullptr; - dbus_test_dbus_mock_object_emit_signal(data->mock, data->obj_client, - "org.freedesktop.Geoclue.Address", + dbus_test_dbus_mock_object_emit_signal(data->mock, data->obj_geo_addr, + //"org.freedesktop.Geoclue.Address", "AddressChanged", G_VARIANT_TYPE("(ia{ss}(idd))"), g_variant_new_parsed (fmt), @@ -135,7 +143,7 @@ public: void setGeoclueTimezoneOnIdle (const std::string& newZone) { - g_timeout_add (50, emit_address_changed_idle, new EmitAddressChangedData(mock, obj_client, newZone.c_str())); + g_timeout_add (50, emit_address_changed_idle, new EmitAddressChangedData(mock, obj_geo_addr, newZone.c_str())); } }; diff --git a/tests/test-clock.cc b/tests/test-clock.cc index 7d3a35e..142ccad 100644 --- a/tests/test-clock.cc +++ b/tests/test-clock.cc @@ -20,95 +20,56 @@ #include #include -#include "glib-fixture.h" +#include "test-dbus-fixture.h" /*** **** ***/ -using unity::indicator::datetime::Clock; -using unity::indicator::datetime::LiveClock; -using unity::indicator::datetime::Timezones; +using namespace unity::indicator::datetime; -class ClockFixture: public GlibFixture +class ClockFixture: public TestDBusFixture { private: - - typedef GlibFixture super; - - static void - on_bus_opened(GObject* /*object*/, GAsyncResult* res, gpointer gself) - { - auto self = static_cast(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(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; - - 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); - } - - 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(); - } + typedef TestDBusFixture super; 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); + NULL, + "/org/freedesktop/login1", // object path + "org.freedesktop.login1.Manager", // interface + "PrepareForSleep", // signal name + g_variant_new("(b)", FALSE), + NULL); } }; +/** + * 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) +{ + std::shared_ptr zones(new Timezones); + zones->timezone.set("America/New_York"); + LiveClock clock(zones); + wait_msec(500); // wait for the bus to set up + + bool skewed = false; + clock.skewDetected.connect([&skewed](){ + skewed = true; + g_warn_if_reached(); + return G_SOURCE_REMOVE; + }); + + const unsigned int intervalSec = 3; + clock.skewTestIntervalSec.set(intervalSec); + wait_msec(intervalSec * 2.5 * 1000); + EXPECT_FALSE(skewed); +} + /*** **** ***/ @@ -120,37 +81,6 @@ TEST_F(ClockFixture, HelloFixture) std::shared_ptr zones(new Timezones); zones->timezone.set("America/New_York"); 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); - 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); - - /// change the timezones! - clock.skewDetected.connect([this](){ - g_main_loop_quit(loop); - }); - file_timezone = "America/Los_Angeles"; - g_idle_add([](gpointer str){ - set_file(static_cast(str)); - return G_SOURCE_REMOVE; - }, const_cast(file_timezone.c_str())); - 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); - 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); -#endif } @@ -159,10 +89,6 @@ TEST_F(ClockFixture, TimezoneChangeTriggersSkew) std::shared_ptr zones(new Timezones); zones->timezone.set("America/New_York"); LiveClock clock(zones); - //std::string file_timezone = "America/New_York"; - //set_file(file_timezone); - //std::shared_ptr 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); @@ -213,30 +139,6 @@ TEST_F(ClockFixture, SleepTriggersSkew) return G_SOURCE_REMOVE; }, this); - wait_msec(1000); + g_main_loop_run(loop); 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(ClockFixture, IdleDoesNotTriggerSkew) -{ - std::shared_ptr zones(new Timezones); - zones->timezone.set("America/New_York"); - LiveClock clock(zones); - wait_msec(500); // wait for the bus to set up - - bool skewed = false; - clock.skewDetected.connect([&skewed](){ - skewed = true; - g_warn_if_reached(); - return G_SOURCE_REMOVE; - }); - - const unsigned int intervalSec = 4; - clock.skewTestIntervalSec.set(intervalSec); - wait_msec(intervalSec * 2.5 * 1000); - EXPECT_FALSE(skewed); -} diff --git a/tests/test-dbus-fixture.h b/tests/test-dbus-fixture.h index fc7ab5a..db06be2 100644 --- a/tests/test-dbus-fixture.h +++ b/tests/test-dbus-fixture.h @@ -86,15 +86,17 @@ class TestDBusFixture: public GlibFixture virtual void TearDown () { + wait_msec(); + // 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(); } }; diff --git a/tests/test-timezones.cc b/tests/test-timezones.cc index d3c8e3a..3f02761 100644 --- a/tests/test-timezones.cc +++ b/tests/test-timezones.cc @@ -19,12 +19,15 @@ #include "geoclue-fixture.h" +#include #include +#include // std::shared_ptr + #include // fopen() #include // sync() -using unity::indicator::datetime::LiveTimezones; +using namespace unity::indicator::datetime; typedef GeoclueFixture TimezonesFixture; @@ -49,7 +52,8 @@ TEST_F(TimezonesFixture, ManagerTest) std::string timezone_geo = "America/Denver"; set_file(timezone_file); - LiveTimezones z(TIMEZONE_FILE); + std::shared_ptr settings(new Settings); + LiveTimezones z(settings, 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(); @@ -71,13 +75,13 @@ TEST_F(TimezonesFixture, ManagerTest) g_main_loop_quit(loop); }); - g_idle_add([](gpointer gz) { - auto az = static_cast(gz); - g_message("geolocation was %d", (int)az->geolocationEnabled.get()); + g_idle_add([](gpointer s_in) { + auto s = static_cast(s_in); + g_message("geolocation was %d", (int)s->show_detected_location.get()); g_message("turning geolocation on"); - az->geolocationEnabled.set(true); + s->show_detected_location.set(true); return G_SOURCE_REMOVE; - }, &z); + }, settings.get()); // turn on geoclue during the idle... this should add timezone_1 to the 'timezones' property g_main_loop_run(loop); @@ -115,9 +119,6 @@ TEST_F(TimezonesFixture, ManagerTest) EXPECT_EQ(2, zones.size()); EXPECT_EQ(1, zones.count(timezone_file)); EXPECT_EQ(1, zones.count(timezone_geo)); - - - } -- cgit v1.2.3 From 8910c3c25d9c3c77aaa987fdc366cd77f63d376c Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Tue, 21 Jan 2014 23:27:45 -0600 Subject: Extract the MockState logic from state-fixture.h so that it can be reused for testing LiveActions --- tests/state-fixture.h | 30 +++++++----------------------- tests/state-mock.h | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 56 insertions(+), 23 deletions(-) create mode 100644 tests/state-mock.h (limited to 'tests') diff --git a/tests/state-fixture.h b/tests/state-fixture.h index 3c6ecd5..7d8358e 100644 --- a/tests/state-fixture.h +++ b/tests/state-fixture.h @@ -18,16 +18,9 @@ */ #include "glib-fixture.h" -#include "actions-mock.h" -#include -#include -#include -#include -#include -#include -#include -#include +#include "actions-mock.h" +#include "state-mock.h" using namespace unity::indicator::datetime; @@ -37,7 +30,7 @@ private: typedef GlibFixture super; protected: - std::shared_ptr m_clock; + std::shared_ptr m_mock_state; std::shared_ptr m_state; std::shared_ptr m_mock_actions; std::shared_ptr m_actions; @@ -46,19 +39,9 @@ protected: { 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->settings.reset(new Settings); - m_state->timezones.reset(new Timezones); - m_state->clock = std::dynamic_pointer_cast(m_clock); - m_state->planner.reset(new MockPlanner); - m_state->planner->time = now; - m_state->locations.reset(new Locations); - m_state->calendar_day = now; + m_mock_state.reset(new MockState); + m_state = std::dynamic_pointer_cast(m_mock_state); - // build the actions on top of the state m_mock_actions.reset(new MockActions(m_state)); m_actions = std::dynamic_pointer_cast(m_mock_actions); } @@ -67,8 +50,9 @@ protected: { m_actions.reset(); m_mock_actions.reset(); + m_state.reset(); - m_clock.reset(); + m_mock_state.reset(); super::TearDown(); } diff --git a/tests/state-mock.h b/tests/state-mock.h new file mode 100644 index 0000000..ae1217b --- /dev/null +++ b/tests/state-mock.h @@ -0,0 +1,49 @@ +/* + * 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 . + * + * Authors: + * Charles Kerr + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace unity::indicator::datetime; + +class MockState: public State +{ +public: + std::shared_ptr mock_clock; + + MockState() + { + const DateTime now = DateTime::NowLocal(); + mock_clock.reset(new MockClock(now)); + settings.reset(new Settings); + timezones.reset(new Timezones); + clock = std::dynamic_pointer_cast(mock_clock); + planner.reset(new MockPlanner); + planner->time = now; + locations.reset(new Locations); + calendar_day = now; + } +}; + -- cgit v1.2.3 From 74f8897902c99180e721d616614a9962c819d90b Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Tue, 21 Jan 2014 23:29:19 -0600 Subject: add LiveActions implementation and unit tests --- tests/CMakeLists.txt | 9 ++++++++- tests/test-menus.cc | 2 +- 2 files changed, 9 insertions(+), 2 deletions(-) (limited to 'tests') diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index a908801..9bc1d75 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -84,6 +84,13 @@ add_test (${TEST_NAME} ${TEST_NAME}) add_dependencies (${TEST_NAME} libindicatordatetimeservice) target_link_libraries (${TEST_NAME} indicatordatetimeservice gtest ${SERVICE_DEPS_LIBRARIES} ${GTEST_LIBS}) +# test-live-actions +set (TEST_NAME test-live-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) @@ -98,7 +105,7 @@ add_test (${TEST_NAME} ${TEST_NAME}) add_dependencies (${TEST_NAME} libindicatordatetimeservice) target_link_libraries (${TEST_NAME} indicatordatetimeservice gtest ${SERVICE_DEPS_LIBRARIES} ${GTEST_LIBS}) -# test-utils +# test-settings set (TEST_NAME test-settings) add_executable (${TEST_NAME} ${TEST_NAME}.cc) add_test (${TEST_NAME} ${TEST_NAME}) diff --git a/tests/test-menus.cc b/tests/test-menus.cc index 0f86b0d..95ac5c2 100644 --- a/tests/test-menus.cc +++ b/tests/test-menus.cc @@ -148,7 +148,7 @@ protected: 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); + m_mock_state->mock_clock->set_localtime(tomorrow); wait_msec(); section = g_menu_model_get_item_link(submenu, Menu::Calendar, G_MENU_LINK_SECTION); -- cgit v1.2.3 From 931e448b916453139e2c043161088851a1b47b42 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Wed, 22 Jan 2014 00:33:22 -0600 Subject: remove unnecessary #includes --- tests/state-mock.h | 3 --- tests/test-menus.cc | 4 ---- 2 files changed, 7 deletions(-) (limited to 'tests') diff --git a/tests/state-mock.h b/tests/state-mock.h index ae1217b..2104aa0 100644 --- a/tests/state-mock.h +++ b/tests/state-mock.h @@ -18,11 +18,8 @@ */ #include -#include #include -#include #include -#include #include #include diff --git a/tests/test-menus.cc b/tests/test-menus.cc index 95ac5c2..fe1e86e 100644 --- a/tests/test-menus.cc +++ b/tests/test-menus.cc @@ -22,13 +22,9 @@ #include "state-fixture.h" #include -#include #include #include -#include -#include #include -#include #include -- cgit v1.2.3 From 6d515551ef24c92fa9a56e9533c4175e2b4f7bbd Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Wed, 22 Jan 2014 01:23:38 -0600 Subject: add unit tests for the menu/action exporter --- tests/CMakeLists.txt | 7 +++ tests/test-exporter.cc | 128 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 135 insertions(+) create mode 100644 tests/test-exporter.cc (limited to 'tests') diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 9bc1d75..ff4a8a5 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -112,6 +112,13 @@ add_test (${TEST_NAME} ${TEST_NAME}) add_dependencies (${TEST_NAME} libindicatordatetimeservice) target_link_libraries (${TEST_NAME} indicatordatetimeservice gtest ${SERVICE_DEPS_LIBRARIES} ${GTEST_LIBS}) +# test-exporter +set (TEST_NAME test-exporter) +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) diff --git a/tests/test-exporter.cc b/tests/test-exporter.cc new file mode 100644 index 0000000..ea62cd3 --- /dev/null +++ b/tests/test-exporter.cc @@ -0,0 +1,128 @@ +/* + * 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 . + * + * Authors: + * Charles Kerr + */ + +#include "actions-mock.h" +#include "state-mock.h" +#include "glib-fixture.h" + +#include +#include +#include + +#include +#include + +using namespace unity::indicator::datetime; + +class ExporterFixture: public GlibFixture +{ +private: + + typedef GlibFixture super; + + static void on_bus_closed(GObject * object, + GAsyncResult * res, + gpointer gself) + { + auto self = static_cast(gself); + GError* err = nullptr; + g_dbus_connection_close_finish(G_DBUS_CONNECTION(object), res, &err); + g_assert_no_error(err); + g_main_loop_quit(self->loop); + } + +protected: + + GTestDBus* bus = nullptr; + + void SetUp() + { + super::SetUp(); + + // bring up the test bus + bus = g_test_dbus_new(G_TEST_DBUS_NONE); + g_test_dbus_up(bus); + const auto address = g_test_dbus_get_bus_address(bus); + g_setenv("DBUS_SYSTEM_BUS_ADDRESS", address, true); + g_setenv("DBUS_SESSION_BUS_ADDRESS", address, true); + } + + void TearDown() + { + GDBusConnection* connection = g_bus_get_sync (G_BUS_TYPE_SESSION, nullptr, nullptr); + g_dbus_connection_close(connection, nullptr, on_bus_closed, this); + g_main_loop_run(loop); + g_clear_object(&connection); + g_test_dbus_down(bus); + g_clear_object(&bus); + + super::TearDown(); + } +}; + +TEST_F(ExporterFixture, HelloWorld) +{ + // confirms that the Test DBus SetUp() and TearDown() works +} + +TEST_F(ExporterFixture, Publish) +{ + std::shared_ptr state(new MockState); + std::shared_ptr actions(new MockActions(state)); + std::vector> menus; + + Exporter exporter; + exporter.publish(actions, menus); + wait_msec(); + + auto connection = g_bus_get_sync (G_BUS_TYPE_SESSION, nullptr, nullptr); + auto exported = g_dbus_action_group_get (connection, BUS_NAME, BUS_PATH); + auto names_strv = g_action_group_list_actions(G_ACTION_GROUP(exported)); + + // wait for the exported ActionGroup to be populated + if (g_strv_length(names_strv) == 0) + { + g_strfreev(names_strv); + wait_for_signal(exported, "action-added"); + names_strv = g_action_group_list_actions(G_ACTION_GROUP(exported)); + } + + // convert it to a std::set for easy prodding + std::set names; + for(int i=0; names_strv && names_strv[i]; i++) + names.insert(names_strv[i]); + + // confirm the actions that we expect + EXPECT_EQ(1, names.count("activate-appointment")); + EXPECT_EQ(1, names.count("activate-desktop-settings")); + EXPECT_EQ(1, names.count("activate-phone-clock-app")); + EXPECT_EQ(1, names.count("activate-phone-settings")); + EXPECT_EQ(1, names.count("activate-planner")); + EXPECT_EQ(1, names.count("calendar")); + EXPECT_EQ(1, names.count("desktop-greeter-header")); + EXPECT_EQ(1, names.count("desktop-header")); + EXPECT_EQ(1, names.count("phone-greeter-header")); + EXPECT_EQ(1, names.count("phone-header")); + EXPECT_EQ(1, names.count("set-location")); + + // cleanup + g_strfreev(names_strv); + g_clear_object(&exported); + g_clear_object(&connection); +} -- cgit v1.2.3 From f1027f7cd2f846211a46b072965331fb0eb69fec Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Wed, 22 Jan 2014 01:34:04 -0600 Subject: fold repetitious unit test rules into CMake functions --- tests/CMakeLists.txt | 122 ++++++++++++--------------------------------------- 1 file changed, 29 insertions(+), 93 deletions(-) (limited to 'tests') diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index ff4a8a5..c8dd6aa 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -32,97 +32,33 @@ include_directories (${DBUSTEST_INCLUDE_DIRS}) add_definitions (-DSANDBOX="${CMAKE_CURRENT_BINARY_DIR}") -# test-timezone-file -set (TEST_NAME test-timezone-file) -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-geoclue -set (TEST_NAME test-timezone-geoclue) -add_executable (${TEST_NAME} ${TEST_NAME}.cc) -add_test (${TEST_NAME} ${TEST_NAME}) -target_link_libraries (${TEST_NAME} indicatordatetimeservice gtest ${SERVICE_DEPS_LIBRARIES} ${DBUSTEST_LIBRARIES} ${GTEST_LIBS}) - -# test-timezones -set (TEST_NAME test-timezones) -add_executable (${TEST_NAME} ${TEST_NAME}.cc) -add_test (${TEST_NAME} ${TEST_NAME}) -target_link_libraries (${TEST_NAME} indicatordatetimeservice gtest ${SERVICE_DEPS_LIBRARIES} ${DBUSTEST_LIBRARIES} ${GTEST_LIBS}) - -# test-clock -set (TEST_NAME test-clock) -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-formatter -set (TEST_NAME test-formatter) -add_executable (${TEST_NAME} test-formatter.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-planner -set (TEST_NAME test-planner) -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) -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-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-live-actions -set (TEST_NAME test-live-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-utils -set (TEST_NAME test-utils) -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-settings -set (TEST_NAME test-settings) -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-exporter -set (TEST_NAME test-exporter) -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}) +function(add_test_by_name name) + set (TEST_NAME ${name}) + 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}) +endfunction() +add_test_by_name(test-actions) +add_test_by_name(test-clock) +add_test_by_name(test-exporter) +add_test_by_name(test-formatter) +add_test_by_name(test-live-actions) +add_test_by_name(test-locations) +add_test_by_name(test-menus) +add_test_by_name(test-planner) +add_test_by_name(test-settings) +add_test_by_name(test-timezone-file) +add_test_by_name(test-utils) + + +function(add_dbusmock_test_by_name name) + set (TEST_NAME ${name}) + 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} ${DBUSTEST_LIBRARIES} ${GTEST_LIBS}) +endfunction() +add_dbusmock_test_by_name(test-timezone-geoclue) +add_dbusmock_test_by_name(test-timezones) -- cgit v1.2.3 From dd41db685c518acab1c8e3676f4292f66e4d0476 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Wed, 22 Jan 2014 09:06:01 -0600 Subject: copyediting: rename the test/ directory's .cc files to .cpp for consistency with src/ --- tests/CMakeLists.txt | 4 +- tests/test-actions.cc | 173 ----------------- tests/test-actions.cpp | 173 +++++++++++++++++ tests/test-clock.cc | 144 -------------- tests/test-clock.cpp | 144 ++++++++++++++ tests/test-exporter.cc | 128 ------------- tests/test-exporter.cpp | 128 +++++++++++++ tests/test-formatter.cc | 256 ------------------------- tests/test-formatter.cpp | 256 +++++++++++++++++++++++++ tests/test-live-actions.cpp | 289 +++++++++++++++++++++++++++++ tests/test-locations.cc | 169 ----------------- tests/test-locations.cpp | 169 +++++++++++++++++ tests/test-menus.cc | 402 ---------------------------------------- tests/test-menus.cpp | 402 ++++++++++++++++++++++++++++++++++++++++ tests/test-planner.cc | 85 --------- tests/test-planner.cpp | 85 +++++++++ tests/test-settings.cc | 197 -------------------- tests/test-settings.cpp | 197 ++++++++++++++++++++ tests/test-timezone-file.cc | 133 ------------- tests/test-timezone-file.cpp | 133 +++++++++++++ tests/test-timezone-geoclue.cc | 97 ---------- tests/test-timezone-geoclue.cpp | 97 ++++++++++ tests/test-timezones.cc | 124 ------------- tests/test-timezones.cpp | 124 +++++++++++++ tests/test-utils.cc | 74 -------- tests/test-utils.cpp | 74 ++++++++ 26 files changed, 2273 insertions(+), 1984 deletions(-) delete mode 100644 tests/test-actions.cc create mode 100644 tests/test-actions.cpp delete mode 100644 tests/test-clock.cc create mode 100644 tests/test-clock.cpp delete mode 100644 tests/test-exporter.cc create mode 100644 tests/test-exporter.cpp delete mode 100644 tests/test-formatter.cc create mode 100644 tests/test-formatter.cpp create mode 100644 tests/test-live-actions.cpp delete mode 100644 tests/test-locations.cc create mode 100644 tests/test-locations.cpp delete mode 100644 tests/test-menus.cc create mode 100644 tests/test-menus.cpp delete mode 100644 tests/test-planner.cc create mode 100644 tests/test-planner.cpp delete mode 100644 tests/test-settings.cc create mode 100644 tests/test-settings.cpp delete mode 100644 tests/test-timezone-file.cc create mode 100644 tests/test-timezone-file.cpp delete mode 100644 tests/test-timezone-geoclue.cc create mode 100644 tests/test-timezone-geoclue.cpp delete mode 100644 tests/test-timezones.cc create mode 100644 tests/test-timezones.cpp delete mode 100644 tests/test-utils.cc create mode 100644 tests/test-utils.cpp (limited to 'tests') diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index c8dd6aa..c909e0e 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -35,7 +35,7 @@ add_definitions (-DSANDBOX="${CMAKE_CURRENT_BINARY_DIR}") function(add_test_by_name name) set (TEST_NAME ${name}) - add_executable (${TEST_NAME} ${TEST_NAME}.cc) + add_executable (${TEST_NAME} ${TEST_NAME}.cpp) add_test (${TEST_NAME} ${TEST_NAME}) add_dependencies (${TEST_NAME} libindicatordatetimeservice) target_link_libraries (${TEST_NAME} indicatordatetimeservice gtest ${SERVICE_DEPS_LIBRARIES} ${GTEST_LIBS}) @@ -55,7 +55,7 @@ add_test_by_name(test-utils) function(add_dbusmock_test_by_name name) set (TEST_NAME ${name}) - add_executable (${TEST_NAME} ${TEST_NAME}.cc) + add_executable (${TEST_NAME} ${TEST_NAME}.cpp) add_test (${TEST_NAME} ${TEST_NAME}) add_dependencies (${TEST_NAME} libindicatordatetimeservice) target_link_libraries (${TEST_NAME} indicatordatetimeservice gtest ${SERVICE_DEPS_LIBRARIES} ${DBUSTEST_LIBRARIES} ${GTEST_LIBS}) diff --git a/tests/test-actions.cc b/tests/test-actions.cc deleted file mode 100644 index 4329608..0000000 --- a/tests/test-actions.cc +++ /dev/null @@ -1,173 +0,0 @@ -/* - * 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 . - * - * Authors: - * Charles Kerr - */ - -#include - -#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({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({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-actions.cpp b/tests/test-actions.cpp new file mode 100644 index 0000000..4329608 --- /dev/null +++ b/tests/test-actions.cpp @@ -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 . + * + * Authors: + * Charles Kerr + */ + +#include + +#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({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({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 deleted file mode 100644 index 142ccad..0000000 --- a/tests/test-clock.cc +++ /dev/null @@ -1,144 +0,0 @@ -/* - * 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 . - * - * Authors: - * Charles Kerr - */ - -#include -#include - -#include "test-dbus-fixture.h" - -/*** -**** -***/ - -using namespace unity::indicator::datetime; - -class ClockFixture: public TestDBusFixture -{ - private: - typedef TestDBusFixture super; - - 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); - } -}; - -/** - * 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) -{ - std::shared_ptr zones(new Timezones); - zones->timezone.set("America/New_York"); - LiveClock clock(zones); - wait_msec(500); // wait for the bus to set up - - bool skewed = false; - clock.skewDetected.connect([&skewed](){ - skewed = true; - g_warn_if_reached(); - return G_SOURCE_REMOVE; - }); - - const unsigned int intervalSec = 3; - clock.skewTestIntervalSec.set(intervalSec); - wait_msec(intervalSec * 2.5 * 1000); - EXPECT_FALSE(skewed); -} - -/*** -**** -***/ - -#define TIMEZONE_FILE (SANDBOX"/timezone") - -TEST_F(ClockFixture, HelloFixture) -{ - std::shared_ptr zones(new Timezones); - zones->timezone.set("America/New_York"); - LiveClock clock(zones); -} - - -TEST_F(ClockFixture, TimezoneChangeTriggersSkew) -{ - std::shared_ptr zones(new Timezones); - zones->timezone.set("America/New_York"); - LiveClock clock(zones); - - 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(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.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) -{ - std::shared_ptr zones(new Timezones); - zones->timezone.set("America/New_York"); - LiveClock clock(zones); - wait_msec(500); // wait for the bus to set up - - bool skewed = false; - clock.skewDetected.connect([&skewed, this](){ - skewed = true; - g_main_loop_quit(loop); - return G_SOURCE_REMOVE; - }); - - g_idle_add([](gpointer gself){ - static_cast(gself)->emitPrepareForSleep(); - return G_SOURCE_REMOVE; - }, this); - - g_main_loop_run(loop); - EXPECT_TRUE(skewed); -} diff --git a/tests/test-clock.cpp b/tests/test-clock.cpp new file mode 100644 index 0000000..142ccad --- /dev/null +++ b/tests/test-clock.cpp @@ -0,0 +1,144 @@ +/* + * 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 . + * + * Authors: + * Charles Kerr + */ + +#include +#include + +#include "test-dbus-fixture.h" + +/*** +**** +***/ + +using namespace unity::indicator::datetime; + +class ClockFixture: public TestDBusFixture +{ + private: + typedef TestDBusFixture super; + + 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); + } +}; + +/** + * 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) +{ + std::shared_ptr zones(new Timezones); + zones->timezone.set("America/New_York"); + LiveClock clock(zones); + wait_msec(500); // wait for the bus to set up + + bool skewed = false; + clock.skewDetected.connect([&skewed](){ + skewed = true; + g_warn_if_reached(); + return G_SOURCE_REMOVE; + }); + + const unsigned int intervalSec = 3; + clock.skewTestIntervalSec.set(intervalSec); + wait_msec(intervalSec * 2.5 * 1000); + EXPECT_FALSE(skewed); +} + +/*** +**** +***/ + +#define TIMEZONE_FILE (SANDBOX"/timezone") + +TEST_F(ClockFixture, HelloFixture) +{ + std::shared_ptr zones(new Timezones); + zones->timezone.set("America/New_York"); + LiveClock clock(zones); +} + + +TEST_F(ClockFixture, TimezoneChangeTriggersSkew) +{ + std::shared_ptr zones(new Timezones); + zones->timezone.set("America/New_York"); + LiveClock clock(zones); + + 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(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.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) +{ + std::shared_ptr zones(new Timezones); + zones->timezone.set("America/New_York"); + LiveClock clock(zones); + wait_msec(500); // wait for the bus to set up + + bool skewed = false; + clock.skewDetected.connect([&skewed, this](){ + skewed = true; + g_main_loop_quit(loop); + return G_SOURCE_REMOVE; + }); + + g_idle_add([](gpointer gself){ + static_cast(gself)->emitPrepareForSleep(); + return G_SOURCE_REMOVE; + }, this); + + g_main_loop_run(loop); + EXPECT_TRUE(skewed); +} diff --git a/tests/test-exporter.cc b/tests/test-exporter.cc deleted file mode 100644 index ea62cd3..0000000 --- a/tests/test-exporter.cc +++ /dev/null @@ -1,128 +0,0 @@ -/* - * 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 . - * - * Authors: - * Charles Kerr - */ - -#include "actions-mock.h" -#include "state-mock.h" -#include "glib-fixture.h" - -#include -#include -#include - -#include -#include - -using namespace unity::indicator::datetime; - -class ExporterFixture: public GlibFixture -{ -private: - - typedef GlibFixture super; - - static void on_bus_closed(GObject * object, - GAsyncResult * res, - gpointer gself) - { - auto self = static_cast(gself); - GError* err = nullptr; - g_dbus_connection_close_finish(G_DBUS_CONNECTION(object), res, &err); - g_assert_no_error(err); - g_main_loop_quit(self->loop); - } - -protected: - - GTestDBus* bus = nullptr; - - void SetUp() - { - super::SetUp(); - - // bring up the test bus - bus = g_test_dbus_new(G_TEST_DBUS_NONE); - g_test_dbus_up(bus); - const auto address = g_test_dbus_get_bus_address(bus); - g_setenv("DBUS_SYSTEM_BUS_ADDRESS", address, true); - g_setenv("DBUS_SESSION_BUS_ADDRESS", address, true); - } - - void TearDown() - { - GDBusConnection* connection = g_bus_get_sync (G_BUS_TYPE_SESSION, nullptr, nullptr); - g_dbus_connection_close(connection, nullptr, on_bus_closed, this); - g_main_loop_run(loop); - g_clear_object(&connection); - g_test_dbus_down(bus); - g_clear_object(&bus); - - super::TearDown(); - } -}; - -TEST_F(ExporterFixture, HelloWorld) -{ - // confirms that the Test DBus SetUp() and TearDown() works -} - -TEST_F(ExporterFixture, Publish) -{ - std::shared_ptr state(new MockState); - std::shared_ptr actions(new MockActions(state)); - std::vector> menus; - - Exporter exporter; - exporter.publish(actions, menus); - wait_msec(); - - auto connection = g_bus_get_sync (G_BUS_TYPE_SESSION, nullptr, nullptr); - auto exported = g_dbus_action_group_get (connection, BUS_NAME, BUS_PATH); - auto names_strv = g_action_group_list_actions(G_ACTION_GROUP(exported)); - - // wait for the exported ActionGroup to be populated - if (g_strv_length(names_strv) == 0) - { - g_strfreev(names_strv); - wait_for_signal(exported, "action-added"); - names_strv = g_action_group_list_actions(G_ACTION_GROUP(exported)); - } - - // convert it to a std::set for easy prodding - std::set names; - for(int i=0; names_strv && names_strv[i]; i++) - names.insert(names_strv[i]); - - // confirm the actions that we expect - EXPECT_EQ(1, names.count("activate-appointment")); - EXPECT_EQ(1, names.count("activate-desktop-settings")); - EXPECT_EQ(1, names.count("activate-phone-clock-app")); - EXPECT_EQ(1, names.count("activate-phone-settings")); - EXPECT_EQ(1, names.count("activate-planner")); - EXPECT_EQ(1, names.count("calendar")); - EXPECT_EQ(1, names.count("desktop-greeter-header")); - EXPECT_EQ(1, names.count("desktop-header")); - EXPECT_EQ(1, names.count("phone-greeter-header")); - EXPECT_EQ(1, names.count("phone-header")); - EXPECT_EQ(1, names.count("set-location")); - - // cleanup - g_strfreev(names_strv); - g_clear_object(&exported); - g_clear_object(&connection); -} diff --git a/tests/test-exporter.cpp b/tests/test-exporter.cpp new file mode 100644 index 0000000..ea62cd3 --- /dev/null +++ b/tests/test-exporter.cpp @@ -0,0 +1,128 @@ +/* + * 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 . + * + * Authors: + * Charles Kerr + */ + +#include "actions-mock.h" +#include "state-mock.h" +#include "glib-fixture.h" + +#include +#include +#include + +#include +#include + +using namespace unity::indicator::datetime; + +class ExporterFixture: public GlibFixture +{ +private: + + typedef GlibFixture super; + + static void on_bus_closed(GObject * object, + GAsyncResult * res, + gpointer gself) + { + auto self = static_cast(gself); + GError* err = nullptr; + g_dbus_connection_close_finish(G_DBUS_CONNECTION(object), res, &err); + g_assert_no_error(err); + g_main_loop_quit(self->loop); + } + +protected: + + GTestDBus* bus = nullptr; + + void SetUp() + { + super::SetUp(); + + // bring up the test bus + bus = g_test_dbus_new(G_TEST_DBUS_NONE); + g_test_dbus_up(bus); + const auto address = g_test_dbus_get_bus_address(bus); + g_setenv("DBUS_SYSTEM_BUS_ADDRESS", address, true); + g_setenv("DBUS_SESSION_BUS_ADDRESS", address, true); + } + + void TearDown() + { + GDBusConnection* connection = g_bus_get_sync (G_BUS_TYPE_SESSION, nullptr, nullptr); + g_dbus_connection_close(connection, nullptr, on_bus_closed, this); + g_main_loop_run(loop); + g_clear_object(&connection); + g_test_dbus_down(bus); + g_clear_object(&bus); + + super::TearDown(); + } +}; + +TEST_F(ExporterFixture, HelloWorld) +{ + // confirms that the Test DBus SetUp() and TearDown() works +} + +TEST_F(ExporterFixture, Publish) +{ + std::shared_ptr state(new MockState); + std::shared_ptr actions(new MockActions(state)); + std::vector> menus; + + Exporter exporter; + exporter.publish(actions, menus); + wait_msec(); + + auto connection = g_bus_get_sync (G_BUS_TYPE_SESSION, nullptr, nullptr); + auto exported = g_dbus_action_group_get (connection, BUS_NAME, BUS_PATH); + auto names_strv = g_action_group_list_actions(G_ACTION_GROUP(exported)); + + // wait for the exported ActionGroup to be populated + if (g_strv_length(names_strv) == 0) + { + g_strfreev(names_strv); + wait_for_signal(exported, "action-added"); + names_strv = g_action_group_list_actions(G_ACTION_GROUP(exported)); + } + + // convert it to a std::set for easy prodding + std::set names; + for(int i=0; names_strv && names_strv[i]; i++) + names.insert(names_strv[i]); + + // confirm the actions that we expect + EXPECT_EQ(1, names.count("activate-appointment")); + EXPECT_EQ(1, names.count("activate-desktop-settings")); + EXPECT_EQ(1, names.count("activate-phone-clock-app")); + EXPECT_EQ(1, names.count("activate-phone-settings")); + EXPECT_EQ(1, names.count("activate-planner")); + EXPECT_EQ(1, names.count("calendar")); + EXPECT_EQ(1, names.count("desktop-greeter-header")); + EXPECT_EQ(1, names.count("desktop-header")); + EXPECT_EQ(1, names.count("phone-greeter-header")); + EXPECT_EQ(1, names.count("phone-header")); + EXPECT_EQ(1, names.count("set-location")); + + // cleanup + g_strfreev(names_strv); + g_clear_object(&exported); + g_clear_object(&connection); +} diff --git a/tests/test-formatter.cc b/tests/test-formatter.cc deleted file mode 100644 index 9950453..0000000 --- a/tests/test-formatter.cc +++ /dev/null @@ -1,256 +0,0 @@ - -/* - * Copyright 2013 Canonical Ltd. - * - * Authors: - * Charles Kerr - * - * 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 . - */ - -#include "glib-fixture.h" - -#include -#include -#include - -#include - -#include -#include - -using namespace unity::indicator::datetime; - -/*** -**** -***/ - -class FormatterFixture: public GlibFixture -{ - private: - - typedef GlibFixture super; - gchar* m_original_locale = nullptr; - - protected: - - std::shared_ptr m_settings; - - virtual void SetUp() - { - super::SetUp(); - - m_settings.reset(new Settings); - m_original_locale = g_strdup(setlocale(LC_TIME, nullptr)); - } - - virtual void TearDown() - { - m_settings.reset(); - - setlocale(LC_TIME, m_original_locale); - g_clear_pointer(&m_original_locale, g_free); - - super::TearDown(); - } - - bool SetLocale(const char* expected_locale, const char* name) - { - setlocale(LC_TIME, expected_locale); - const auto actual_locale = setlocale(LC_TIME, nullptr); - if (!g_strcmp0(expected_locale, actual_locale)) - { - return true; - } - else - { - g_warning("Unable to set locale to %s; skipping %s locale tests.", expected_locale, name); - return false; - } - } - - inline bool Set24hLocale() { return SetLocale("C", "24h"); } - inline bool Set12hLocale() { return SetLocale("en_US.utf8", "12h"); } -}; - - -/** - * Test the phone header format - */ -TEST_F(FormatterFixture, TestPhoneHeader) -{ - auto now = g_date_time_new_local(2020, 10, 31, 18, 30, 59); - std::shared_ptr clock(new MockClock(DateTime(now))); - g_date_time_unref(now); - - // test the default value in a 24h locale - if(Set24hLocale()) - { - PhoneFormatter formatter(clock); - EXPECT_EQ(std::string("%H:%M"), formatter.headerFormat.get()); - EXPECT_EQ(std::string("18:30"), formatter.header.get()); - } - - // test the default value in a 12h locale - if(Set12hLocale()) - { - PhoneFormatter formatter(clock); - EXPECT_EQ(std::string("%l:%M %p"), formatter.headerFormat.get()); - EXPECT_EQ(std::string(" 6:30 PM"), formatter.header.get()); - } -} - -#define EM_SPACE "\u2003" - -/** - * Test the default values of the desktop header format - */ -TEST_F(FormatterFixture, TestDesktopHeader) -{ - struct { - bool is_12h; - bool show_day; - bool show_date; - bool show_year; - const char* expected_format_string; - } test_cases[] = { - { false, false, false, false, "%H:%M" }, - { false, false, false, true, "%H:%M" }, // show_year is ignored iff show_date is false - { false, false, true, false, "%b %e" EM_SPACE "%H:%M" }, - { false, false, true, true, "%b %e %Y" EM_SPACE "%H:%M" }, - { false, true, false, false, "%a" EM_SPACE "%H:%M" }, - { false, true, false, true, "%a" EM_SPACE "%H:%M" }, // show_year is ignored iff show_date is false - { false, true, true, false, "%a %b %e" EM_SPACE "%H:%M" }, - { false, true, true, true, "%a %b %e %Y" EM_SPACE "%H:%M" }, - { true, false, false, false, "%l:%M %p" }, - { true, false, false, true, "%l:%M %p" }, // show_year is ignored iff show_date is false - { true, false, true, false, "%b %e" EM_SPACE "%l:%M %p" }, - { true, false, true, true, "%b %e %Y" EM_SPACE "%l:%M %p" }, - { true, true, false, false, "%a" EM_SPACE "%l:%M %p" }, - { true, true, false, true, "%a" EM_SPACE "%l:%M %p" }, // show_year is ignored iff show_date is false - { true, true, true, false, "%a %b %e" EM_SPACE "%l:%M %p" }, - { true, true, true, true, "%a %b %e %Y" EM_SPACE "%l:%M %p" } - }; - - auto now = g_date_time_new_local(2020, 10, 31, 18, 30, 59); - std::shared_ptr clock(new MockClock(DateTime(now))); - g_date_time_unref(now); - - for(const auto& test_case : test_cases) - { - if (test_case.is_12h ? Set12hLocale() : Set24hLocale()) - { - DesktopFormatter f(clock, m_settings); - - m_settings->show_day.set(test_case.show_day); - m_settings->show_date.set(test_case.show_date); - m_settings->show_year.set(test_case.show_year); - - ASSERT_STREQ(test_case.expected_format_string, f.headerFormat.get().c_str()); - } - } -} - -/** - * Test the default values of the desktop header format - */ -TEST_F(FormatterFixture, TestUpcomingTimes) -{ - auto a = g_date_time_new_local(2020, 10, 31, 18, 30, 59); - - struct { - gboolean is_12h; - GDateTime* now; - GDateTime* then; - const char* expected_format_string; - } test_cases[] = { - { 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(const auto& test_case : test_cases) - { - if (test_case.is_12h ? Set12hLocale() : Set24hLocale()) - { - std::shared_ptr clock (new MockClock(DateTime(test_case.now))); - DesktopFormatter f(clock, m_settings); - - const auto fmt = f.getRelativeFormat(test_case.then); - ASSERT_EQ(test_case.expected_format_string, fmt); - - g_clear_pointer(&test_case.now, g_date_time_unref); - g_clear_pointer(&test_case.then, g_date_time_unref); - } - } - - g_date_time_unref(a); -} - - -/** - * Test the default values of the desktop header format - */ -TEST_F(FormatterFixture, TestEventTimes) -{ - 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; - GDateTime* now; - GDateTime* then; - GDateTime* then_end; - const char* expected_format_string; - } test_cases[] = { - { false, g_date_time_ref(day), g_date_time_ref(day_begin), g_date_time_ref(day_end), _("Today") }, - { true, g_date_time_ref(day), g_date_time_ref(day_begin), g_date_time_ref(day_end), _("Today") }, - { false, g_date_time_ref(day), g_date_time_ref(tomorrow_begin), g_date_time_ref(tomorrow_end), _("Tomorrow") }, - { true, g_date_time_ref(day), g_date_time_ref(tomorrow_begin), g_date_time_ref(tomorrow_end), _("Tomorrow") } - }; - - for(const auto& test_case : test_cases) - { - if (test_case.is_12h ? Set12hLocale() : Set24hLocale()) - { - std::shared_ptr clock(new MockClock(DateTime(test_case.now))); - DesktopFormatter f(clock, m_settings); - - const auto fmt = f.getRelativeFormat(test_case.then, test_case.then_end); - ASSERT_STREQ(test_case.expected_format_string, fmt.c_str()); - - g_clear_pointer(&test_case.now, g_date_time_unref); - g_clear_pointer(&test_case.then, g_date_time_unref); - g_clear_pointer(&test_case.then_end, g_date_time_unref); - } - } - - g_date_time_unref(tomorrow_end); - g_date_time_unref(tomorrow_begin); - g_date_time_unref(day_end); - g_date_time_unref(day_begin); - g_date_time_unref(day); -} diff --git a/tests/test-formatter.cpp b/tests/test-formatter.cpp new file mode 100644 index 0000000..9950453 --- /dev/null +++ b/tests/test-formatter.cpp @@ -0,0 +1,256 @@ + +/* + * Copyright 2013 Canonical Ltd. + * + * Authors: + * Charles Kerr + * + * 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 . + */ + +#include "glib-fixture.h" + +#include +#include +#include + +#include + +#include +#include + +using namespace unity::indicator::datetime; + +/*** +**** +***/ + +class FormatterFixture: public GlibFixture +{ + private: + + typedef GlibFixture super; + gchar* m_original_locale = nullptr; + + protected: + + std::shared_ptr m_settings; + + virtual void SetUp() + { + super::SetUp(); + + m_settings.reset(new Settings); + m_original_locale = g_strdup(setlocale(LC_TIME, nullptr)); + } + + virtual void TearDown() + { + m_settings.reset(); + + setlocale(LC_TIME, m_original_locale); + g_clear_pointer(&m_original_locale, g_free); + + super::TearDown(); + } + + bool SetLocale(const char* expected_locale, const char* name) + { + setlocale(LC_TIME, expected_locale); + const auto actual_locale = setlocale(LC_TIME, nullptr); + if (!g_strcmp0(expected_locale, actual_locale)) + { + return true; + } + else + { + g_warning("Unable to set locale to %s; skipping %s locale tests.", expected_locale, name); + return false; + } + } + + inline bool Set24hLocale() { return SetLocale("C", "24h"); } + inline bool Set12hLocale() { return SetLocale("en_US.utf8", "12h"); } +}; + + +/** + * Test the phone header format + */ +TEST_F(FormatterFixture, TestPhoneHeader) +{ + auto now = g_date_time_new_local(2020, 10, 31, 18, 30, 59); + std::shared_ptr clock(new MockClock(DateTime(now))); + g_date_time_unref(now); + + // test the default value in a 24h locale + if(Set24hLocale()) + { + PhoneFormatter formatter(clock); + EXPECT_EQ(std::string("%H:%M"), formatter.headerFormat.get()); + EXPECT_EQ(std::string("18:30"), formatter.header.get()); + } + + // test the default value in a 12h locale + if(Set12hLocale()) + { + PhoneFormatter formatter(clock); + EXPECT_EQ(std::string("%l:%M %p"), formatter.headerFormat.get()); + EXPECT_EQ(std::string(" 6:30 PM"), formatter.header.get()); + } +} + +#define EM_SPACE "\u2003" + +/** + * Test the default values of the desktop header format + */ +TEST_F(FormatterFixture, TestDesktopHeader) +{ + struct { + bool is_12h; + bool show_day; + bool show_date; + bool show_year; + const char* expected_format_string; + } test_cases[] = { + { false, false, false, false, "%H:%M" }, + { false, false, false, true, "%H:%M" }, // show_year is ignored iff show_date is false + { false, false, true, false, "%b %e" EM_SPACE "%H:%M" }, + { false, false, true, true, "%b %e %Y" EM_SPACE "%H:%M" }, + { false, true, false, false, "%a" EM_SPACE "%H:%M" }, + { false, true, false, true, "%a" EM_SPACE "%H:%M" }, // show_year is ignored iff show_date is false + { false, true, true, false, "%a %b %e" EM_SPACE "%H:%M" }, + { false, true, true, true, "%a %b %e %Y" EM_SPACE "%H:%M" }, + { true, false, false, false, "%l:%M %p" }, + { true, false, false, true, "%l:%M %p" }, // show_year is ignored iff show_date is false + { true, false, true, false, "%b %e" EM_SPACE "%l:%M %p" }, + { true, false, true, true, "%b %e %Y" EM_SPACE "%l:%M %p" }, + { true, true, false, false, "%a" EM_SPACE "%l:%M %p" }, + { true, true, false, true, "%a" EM_SPACE "%l:%M %p" }, // show_year is ignored iff show_date is false + { true, true, true, false, "%a %b %e" EM_SPACE "%l:%M %p" }, + { true, true, true, true, "%a %b %e %Y" EM_SPACE "%l:%M %p" } + }; + + auto now = g_date_time_new_local(2020, 10, 31, 18, 30, 59); + std::shared_ptr clock(new MockClock(DateTime(now))); + g_date_time_unref(now); + + for(const auto& test_case : test_cases) + { + if (test_case.is_12h ? Set12hLocale() : Set24hLocale()) + { + DesktopFormatter f(clock, m_settings); + + m_settings->show_day.set(test_case.show_day); + m_settings->show_date.set(test_case.show_date); + m_settings->show_year.set(test_case.show_year); + + ASSERT_STREQ(test_case.expected_format_string, f.headerFormat.get().c_str()); + } + } +} + +/** + * Test the default values of the desktop header format + */ +TEST_F(FormatterFixture, TestUpcomingTimes) +{ + auto a = g_date_time_new_local(2020, 10, 31, 18, 30, 59); + + struct { + gboolean is_12h; + GDateTime* now; + GDateTime* then; + const char* expected_format_string; + } test_cases[] = { + { 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(const auto& test_case : test_cases) + { + if (test_case.is_12h ? Set12hLocale() : Set24hLocale()) + { + std::shared_ptr clock (new MockClock(DateTime(test_case.now))); + DesktopFormatter f(clock, m_settings); + + const auto fmt = f.getRelativeFormat(test_case.then); + ASSERT_EQ(test_case.expected_format_string, fmt); + + g_clear_pointer(&test_case.now, g_date_time_unref); + g_clear_pointer(&test_case.then, g_date_time_unref); + } + } + + g_date_time_unref(a); +} + + +/** + * Test the default values of the desktop header format + */ +TEST_F(FormatterFixture, TestEventTimes) +{ + 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; + GDateTime* now; + GDateTime* then; + GDateTime* then_end; + const char* expected_format_string; + } test_cases[] = { + { false, g_date_time_ref(day), g_date_time_ref(day_begin), g_date_time_ref(day_end), _("Today") }, + { true, g_date_time_ref(day), g_date_time_ref(day_begin), g_date_time_ref(day_end), _("Today") }, + { false, g_date_time_ref(day), g_date_time_ref(tomorrow_begin), g_date_time_ref(tomorrow_end), _("Tomorrow") }, + { true, g_date_time_ref(day), g_date_time_ref(tomorrow_begin), g_date_time_ref(tomorrow_end), _("Tomorrow") } + }; + + for(const auto& test_case : test_cases) + { + if (test_case.is_12h ? Set12hLocale() : Set24hLocale()) + { + std::shared_ptr clock(new MockClock(DateTime(test_case.now))); + DesktopFormatter f(clock, m_settings); + + const auto fmt = f.getRelativeFormat(test_case.then, test_case.then_end); + ASSERT_STREQ(test_case.expected_format_string, fmt.c_str()); + + g_clear_pointer(&test_case.now, g_date_time_unref); + g_clear_pointer(&test_case.then, g_date_time_unref); + g_clear_pointer(&test_case.then_end, g_date_time_unref); + } + } + + g_date_time_unref(tomorrow_end); + g_date_time_unref(tomorrow_begin); + g_date_time_unref(day_end); + g_date_time_unref(day_begin); + g_date_time_unref(day); +} diff --git a/tests/test-live-actions.cpp b/tests/test-live-actions.cpp new file mode 100644 index 0000000..d3d7720 --- /dev/null +++ b/tests/test-live-actions.cpp @@ -0,0 +1,289 @@ +/* + * 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 . + * + * Authors: + * Charles Kerr + */ + +#include + +#include "state-mock.h" +#include "glib-fixture.h" + +/*** +**** +***/ + +class MockLiveActions: public LiveActions +{ +public: + std::string last_cmd; + std::string last_url; + MockLiveActions(const std::shared_ptr& state_in): LiveActions(state_in) {} + virtual ~MockLiveActions() {} + +protected: + void dispatch_url(const std::string& url) { last_url = url; } + void execute_command(const std::string& cmd) { last_cmd = cmd; } +}; + +/*** +**** +***/ + +using namespace unity::indicator::datetime; + +class LiveActionsFixture: public GlibFixture +{ +private: + + typedef GlibFixture super; + + static void on_bus_acquired(GDBusConnection* conn, + const gchar* name, + gpointer gself) + { + auto self = static_cast(gself); + g_debug("bus acquired: %s, connection is %p", name, conn); + + // Set up a mock GSD. + // All it really does is wait for calls to GetDevice and + // returns the get_devices_retval variant + static const GDBusInterfaceVTable vtable = { + timedate1_handle_method_call, + nullptr, /* GetProperty */ + nullptr, /* SetProperty */ + }; + + self->connection = G_DBUS_CONNECTION(g_object_ref(G_OBJECT(conn))); + + GError* error = nullptr; + self->object_register_id = g_dbus_connection_register_object( + conn, + "/org/freedesktop/timedate1", + self->node_info->interfaces[0], + &vtable, + self, + nullptr, + &error); + g_assert_no_error(error); + } + + static void on_name_acquired(GDBusConnection* /*conn*/, + const gchar* /*name*/, + gpointer gself) + { + auto self = static_cast(gself); + self->name_acquired = true; + g_main_loop_quit(self->loop); + } + + static void on_name_lost(GDBusConnection* /*conn*/, + const gchar* /*name*/, + gpointer gself) + { + auto self = static_cast(gself); + self->name_acquired = false; + } + + static void on_bus_closed(GObject* /*object*/, + GAsyncResult* res, + gpointer gself) + { + auto self = static_cast(gself); + GError* err = nullptr; + g_dbus_connection_close_finish(self->connection, res, &err); + g_assert_no_error(err); + g_main_loop_quit(self->loop); + } + + static void + timedate1_handle_method_call(GDBusConnection * /*connection*/, + const gchar * /*sender*/, + const gchar * /*object_path*/, + const gchar * /*interface_name*/, + const gchar * method_name, + GVariant * parameters, + GDBusMethodInvocation * invocation, + gpointer gself) + { + g_assert(!g_strcmp0(method_name, "SetTimezone")); + g_assert(g_variant_is_of_type(parameters, G_VARIANT_TYPE_TUPLE)); + g_assert(2 == g_variant_n_children(parameters)); + + auto child = g_variant_get_child_value(parameters, 0); + g_assert(g_variant_is_of_type(child, G_VARIANT_TYPE_STRING)); + auto self = static_cast(gself); + self->attempted_tzid = g_variant_get_string(child, nullptr); + g_variant_unref(child); + + g_dbus_method_invocation_return_value(invocation, nullptr); + g_main_loop_quit(self->loop); + } + +protected: + + std::shared_ptr m_mock_state; + std::shared_ptr m_state; + std::shared_ptr m_live_actions; + std::shared_ptr m_actions; + + bool name_acquired; + std::string attempted_tzid; + + GTestDBus* bus; + guint own_name; + GDBusConnection* connection; + GDBusNodeInfo* node_info; + int object_register_id; + + void SetUp() + { + super::SetUp(); + + name_acquired = false; + attempted_tzid.clear(); + connection = nullptr; + node_info = nullptr; + object_register_id = 0; + own_name = 0; + + // bring up the test bus + bus = g_test_dbus_new(G_TEST_DBUS_NONE); + g_test_dbus_up(bus); + const auto address = g_test_dbus_get_bus_address(bus); + 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); + + // parse the org.freedesktop.timedate1 interface + const gchar introspection_xml[] = + "" + " " + " " + " " + " " + " " + " " + ""; + node_info = g_dbus_node_info_new_for_xml(introspection_xml, nullptr); + ASSERT_TRUE(node_info != nullptr); + ASSERT_TRUE(node_info->interfaces != nullptr); + ASSERT_TRUE(node_info->interfaces[0] != nullptr); + ASSERT_TRUE(node_info->interfaces[1] == nullptr); + ASSERT_STREQ("org.freedesktop.timedate1", node_info->interfaces[0]->name); + + // own the bus + own_name = g_bus_own_name(G_BUS_TYPE_SYSTEM, + "org.freedesktop.timedate1", + G_BUS_NAME_OWNER_FLAGS_NONE, + on_bus_acquired, on_name_acquired, on_name_lost, + this, nullptr); + ASSERT_TRUE(object_register_id == 0); + ASSERT_FALSE(name_acquired); + ASSERT_TRUE(connection == nullptr); + g_main_loop_run(loop); + ASSERT_TRUE(object_register_id != 0); + ASSERT_TRUE(name_acquired); + ASSERT_TRUE(G_IS_DBUS_CONNECTION(connection)); + + // create the State and Actions + m_mock_state.reset(new MockState); + m_mock_state->settings.reset(new Settings); + m_state = std::dynamic_pointer_cast(m_mock_state); + m_live_actions.reset(new MockLiveActions(m_state)); + m_actions = std::dynamic_pointer_cast(m_live_actions); + } + + void TearDown() + { + m_actions.reset(); + m_live_actions.reset(); + m_state.reset(); + m_mock_state.reset(); + + g_dbus_connection_unregister_object(connection, object_register_id); + g_dbus_node_info_unref(node_info); + g_bus_unown_name(own_name); + g_dbus_connection_close(connection, nullptr, on_bus_closed, this); + g_main_loop_run(loop); + g_clear_object(&connection); + g_test_dbus_down(bus); + g_clear_object(&bus); + + super::TearDown(); + } +}; + +/*** +**** +***/ + +TEST_F(LiveActionsFixture, HelloWorld) +{ + EXPECT_TRUE(true); +} + +TEST_F(LiveActionsFixture, SetLocation) +{ + const std::string tzid = "America/Chicago"; + const std::string name = "Oklahoma City"; + const std::string expected = tzid + " " + name; + + EXPECT_NE(expected, m_state->settings->timezone_name.get()); + + m_actions->set_location(tzid, name); + g_main_loop_run(loop); + EXPECT_EQ(attempted_tzid, tzid); + wait_msec(); + + EXPECT_EQ(expected, m_state->settings->timezone_name.get()); +} + +TEST_F(LiveActionsFixture, OpenDesktopSettings) +{ + m_actions->open_desktop_settings(); + const std::string expected_substr = "control-center"; + EXPECT_NE(m_live_actions->last_cmd.find(expected_substr), std::string::npos); +} + +TEST_F(LiveActionsFixture, OpenPlanner) +{ + m_actions->open_planner(); + const std::string expected = "evolution -c calendar"; + EXPECT_EQ(expected, m_live_actions->last_cmd); +} + +TEST_F(LiveActionsFixture, OpenPhoneSettings) +{ + m_actions->open_phone_settings(); + const std::string expected = "settings:///system/time-date"; + EXPECT_EQ(expected, m_live_actions->last_url); +} + +TEST_F(LiveActionsFixture, OpenPhoneClockApp) +{ + m_actions->open_phone_clock_app(); + const std::string expected = "appid://com.ubuntu.clock/clock/current-user-version"; + EXPECT_EQ(expected, m_live_actions->last_url); +} + +TEST_F(LiveActionsFixture, OpenPlannerAt) +{ + const auto now = DateTime::NowLocal(); + m_actions->open_planner_at(now); + const std::string expected = now.format("evolution \"calendar:///?startdate=%Y%m%d\""); + EXPECT_EQ(expected, m_live_actions->last_cmd); +} diff --git a/tests/test-locations.cc b/tests/test-locations.cc deleted file mode 100644 index 65adbc7..0000000 --- a/tests/test-locations.cc +++ /dev/null @@ -1,169 +0,0 @@ - - -/* - * Copyright 2013 Canonical Ltd. - * - * Authors: - * Charles Kerr - * - * 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 . - */ - -#include "glib-fixture.h" - -#include - -using unity::indicator::datetime::Location; -using unity::indicator::datetime::Locations; -using unity::indicator::datetime::Settings; -using unity::indicator::datetime::SettingsLocations; -using unity::indicator::datetime::Timezones; - -/*** -**** -***/ - -class LocationsFixture: public GlibFixture -{ - private: - - typedef GlibFixture super; - - protected: - - //GSettings * settings = nullptr; - std::shared_ptr m_settings; - std::shared_ptr m_timezones; - const std::string nyc = "America/New_York"; - const std::string chicago = "America/Chicago"; - - virtual void SetUp() - { - super::SetUp(); - - m_settings.reset(new Settings); - m_settings->show_locations.set(true); - m_settings->locations.set({"America/Los_Angeles Oakland", - "America/Chicago Chicago", - "America/Chicago Oklahoma City", - "America/Toronto Toronto", - "Europe/London London", - "Europe/Berlin Berlin"}); - - m_timezones.reset(new Timezones); - m_timezones->timezone.set(chicago); - m_timezones->timezones.set(std::set({ nyc, chicago })); - } - - virtual void TearDown() - { - m_timezones.reset(); - m_settings.reset(); - - super::TearDown(); - } -}; - -TEST_F(LocationsFixture, Timezones) -{ - m_settings->show_locations.set(false); - - SettingsLocations locations(m_settings, m_timezones); - const auto l = locations.locations.get(); - EXPECT_EQ(2, l.size()); - EXPECT_STREQ("Chicago", l[0].name().c_str()); - EXPECT_EQ(chicago, l[0].zone()); - EXPECT_EQ("New York", l[1].name()); - EXPECT_EQ(nyc, l[1].zone()); -} - -TEST_F(LocationsFixture, SettingsLocations) -{ - SettingsLocations locations(m_settings, m_timezones); - - const auto 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()); -} - -TEST_F(LocationsFixture, ChangeLocationStrings) -{ - SettingsLocations locations(m_settings, m_timezones); - - bool locations_changed = false; - locations.locations.changed().connect([&locations_changed, this](const std::vector&){ - locations_changed = true; - g_main_loop_quit(loop); - }); - - g_idle_add([](gpointer settings){ - static_cast(settings)->locations.set({"America/Los_Angeles Oakland", "Europe/London London", "Europe/Berlin Berlin"}); - return G_SOURCE_REMOVE; - }, m_settings.get()); - - g_main_loop_run(loop); - - EXPECT_TRUE(locations_changed); - const auto 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()); - locations_changed = false; -} - -TEST_F(LocationsFixture, ChangeLocationVisibility) -{ - SettingsLocations locations(m_settings, m_timezones); - - bool locations_changed = false; - locations.locations.changed().connect([&locations_changed, this](const std::vector&){ - locations_changed = true; - g_main_loop_quit(loop); - }); - - g_idle_add([](gpointer settings){ - static_cast(settings)->show_locations.set(false); - return G_SOURCE_REMOVE; - }, m_settings.get()); - - g_main_loop_run(loop); - - EXPECT_TRUE(locations_changed); - const auto 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()); -} diff --git a/tests/test-locations.cpp b/tests/test-locations.cpp new file mode 100644 index 0000000..65adbc7 --- /dev/null +++ b/tests/test-locations.cpp @@ -0,0 +1,169 @@ + + +/* + * Copyright 2013 Canonical Ltd. + * + * Authors: + * Charles Kerr + * + * 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 . + */ + +#include "glib-fixture.h" + +#include + +using unity::indicator::datetime::Location; +using unity::indicator::datetime::Locations; +using unity::indicator::datetime::Settings; +using unity::indicator::datetime::SettingsLocations; +using unity::indicator::datetime::Timezones; + +/*** +**** +***/ + +class LocationsFixture: public GlibFixture +{ + private: + + typedef GlibFixture super; + + protected: + + //GSettings * settings = nullptr; + std::shared_ptr m_settings; + std::shared_ptr m_timezones; + const std::string nyc = "America/New_York"; + const std::string chicago = "America/Chicago"; + + virtual void SetUp() + { + super::SetUp(); + + m_settings.reset(new Settings); + m_settings->show_locations.set(true); + m_settings->locations.set({"America/Los_Angeles Oakland", + "America/Chicago Chicago", + "America/Chicago Oklahoma City", + "America/Toronto Toronto", + "Europe/London London", + "Europe/Berlin Berlin"}); + + m_timezones.reset(new Timezones); + m_timezones->timezone.set(chicago); + m_timezones->timezones.set(std::set({ nyc, chicago })); + } + + virtual void TearDown() + { + m_timezones.reset(); + m_settings.reset(); + + super::TearDown(); + } +}; + +TEST_F(LocationsFixture, Timezones) +{ + m_settings->show_locations.set(false); + + SettingsLocations locations(m_settings, m_timezones); + const auto l = locations.locations.get(); + EXPECT_EQ(2, l.size()); + EXPECT_STREQ("Chicago", l[0].name().c_str()); + EXPECT_EQ(chicago, l[0].zone()); + EXPECT_EQ("New York", l[1].name()); + EXPECT_EQ(nyc, l[1].zone()); +} + +TEST_F(LocationsFixture, SettingsLocations) +{ + SettingsLocations locations(m_settings, m_timezones); + + const auto 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()); +} + +TEST_F(LocationsFixture, ChangeLocationStrings) +{ + SettingsLocations locations(m_settings, m_timezones); + + bool locations_changed = false; + locations.locations.changed().connect([&locations_changed, this](const std::vector&){ + locations_changed = true; + g_main_loop_quit(loop); + }); + + g_idle_add([](gpointer settings){ + static_cast(settings)->locations.set({"America/Los_Angeles Oakland", "Europe/London London", "Europe/Berlin Berlin"}); + return G_SOURCE_REMOVE; + }, m_settings.get()); + + g_main_loop_run(loop); + + EXPECT_TRUE(locations_changed); + const auto 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()); + locations_changed = false; +} + +TEST_F(LocationsFixture, ChangeLocationVisibility) +{ + SettingsLocations locations(m_settings, m_timezones); + + bool locations_changed = false; + locations.locations.changed().connect([&locations_changed, this](const std::vector&){ + locations_changed = true; + g_main_loop_quit(loop); + }); + + g_idle_add([](gpointer settings){ + static_cast(settings)->show_locations.set(false); + return G_SOURCE_REMOVE; + }, m_settings.get()); + + g_main_loop_run(loop); + + EXPECT_TRUE(locations_changed); + const auto 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()); +} diff --git a/tests/test-menus.cc b/tests/test-menus.cc deleted file mode 100644 index fe1e86e..0000000 --- a/tests/test-menus.cc +++ /dev/null @@ -1,402 +0,0 @@ -/* - * 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 . - * - * Authors: - * Charles Kerr - */ - - -#include "actions-mock.h" -#include "state-fixture.h" - -#include -#include -#include -#include - -#include - -using namespace unity::indicator::datetime; - -class MenuFixture: public StateFixture -{ -private: - typedef StateFixture super; - -protected: - std::shared_ptr m_menu_factory; - std::vector> 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; ibuildMenu(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_mock_state->mock_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->settings->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 appointments; - m_state->settings->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& 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 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 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; imenu_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-menus.cpp b/tests/test-menus.cpp new file mode 100644 index 0000000..fe1e86e --- /dev/null +++ b/tests/test-menus.cpp @@ -0,0 +1,402 @@ +/* + * 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 . + * + * Authors: + * Charles Kerr + */ + + +#include "actions-mock.h" +#include "state-fixture.h" + +#include +#include +#include +#include + +#include + +using namespace unity::indicator::datetime; + +class MenuFixture: public StateFixture +{ +private: + typedef StateFixture super; + +protected: + std::shared_ptr m_menu_factory; + std::vector> 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; ibuildMenu(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_mock_state->mock_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->settings->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 appointments; + m_state->settings->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& 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 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 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; imenu_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.cc b/tests/test-planner.cc deleted file mode 100644 index 3072aea..0000000 --- a/tests/test-planner.cc +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright 2013 Canonical Ltd. - * - * Authors: - * Charles Kerr - * - * 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 . - */ - -#include "glib-fixture.h" - -#include -#include -#include -#include -#include - -#include -#include - -using unity::indicator::datetime::Appointment; -using unity::indicator::datetime::DateTime; -using unity::indicator::datetime::PlannerEds; - -/*** -**** -***/ - -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 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) -{ - 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); - 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())); - - Appointment c; - c.begin = christmas; - 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())); - a = d; - 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-planner.cpp b/tests/test-planner.cpp new file mode 100644 index 0000000..3072aea --- /dev/null +++ b/tests/test-planner.cpp @@ -0,0 +1,85 @@ +/* + * Copyright 2013 Canonical Ltd. + * + * Authors: + * Charles Kerr + * + * 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 . + */ + +#include "glib-fixture.h" + +#include +#include +#include +#include +#include + +#include +#include + +using unity::indicator::datetime::Appointment; +using unity::indicator::datetime::DateTime; +using unity::indicator::datetime::PlannerEds; + +/*** +**** +***/ + +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 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) +{ + 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); + 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())); + + Appointment c; + c.begin = christmas; + 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())); + a = d; + 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-settings.cc b/tests/test-settings.cc deleted file mode 100644 index 9e52197..0000000 --- a/tests/test-settings.cc +++ /dev/null @@ -1,197 +0,0 @@ -/* - * Copyright 2013 Canonical Ltd. - * - * Authors: - * Charles Kerr - * - * 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 . - */ - -#include "glib-fixture.h" - -#include -#include - -using namespace unity::indicator::datetime; - -/*** -**** -***/ - -class SettingsFixture: public GlibFixture -{ -private: - typedef GlibFixture super; - -protected: - - std::shared_ptr m_live; - std::shared_ptr m_settings; - GSettings * m_gsettings; - - virtual void SetUp() - { - super::SetUp(); - - m_gsettings = g_settings_new(SETTINGS_INTERFACE); - m_live.reset(new LiveSettings); - m_settings = std::dynamic_pointer_cast(m_live); - } - - virtual void TearDown() - { - g_clear_object(&m_gsettings); - m_settings.reset(); - m_live.reset(); - - super::TearDown(); - } - - void TestBoolProperty(core::Property& property, const gchar* key) - { - EXPECT_EQ(g_settings_get_boolean(m_gsettings, key), property.get()); - g_settings_set_boolean(m_gsettings, key, false); - EXPECT_EQ(false, property.get()); - g_settings_set_boolean(m_gsettings, key, true); - EXPECT_EQ(true, property.get()); - - property.set(false); - EXPECT_EQ(false, g_settings_get_boolean(m_gsettings, key)); - property.set(true); - EXPECT_EQ(true, g_settings_get_boolean(m_gsettings, key)); - } - - void TestStringProperty(core::Property& property, const gchar* key) - { - gchar* tmp; - std::string str; - - tmp = g_settings_get_string(m_gsettings, key); - EXPECT_EQ(tmp, property.get()); - g_clear_pointer(&tmp, g_free); - - str = "a"; - g_settings_set_string(m_gsettings, key, str.c_str()); - EXPECT_EQ(str, property.get()); - - str = "b"; - g_settings_set_string(m_gsettings, key, str.c_str()); - EXPECT_EQ(str, property.get()); - - str = "a"; - property.set(str); - tmp = g_settings_get_string(m_gsettings, key); - EXPECT_EQ(str, tmp); - g_clear_pointer(&tmp, g_free); - - str = "b"; - property.set(str); - tmp = g_settings_get_string(m_gsettings, key); - EXPECT_EQ(str, tmp); - g_clear_pointer(&tmp, g_free); - } -}; - -/*** -**** -***/ - -TEST_F(SettingsFixture, HelloWorld) -{ - EXPECT_TRUE(true); -} - -TEST_F(SettingsFixture, BoolProperties) -{ - TestBoolProperty(m_settings->show_seconds, SETTINGS_SHOW_SECONDS_S); - TestBoolProperty(m_settings->show_calendar, SETTINGS_SHOW_CALENDAR_S); - TestBoolProperty(m_settings->show_clock, SETTINGS_SHOW_CLOCK_S); - TestBoolProperty(m_settings->show_date, SETTINGS_SHOW_DATE_S); - TestBoolProperty(m_settings->show_day, SETTINGS_SHOW_DAY_S); - TestBoolProperty(m_settings->show_detected_location, SETTINGS_SHOW_DETECTED_S); - TestBoolProperty(m_settings->show_events, SETTINGS_SHOW_EVENTS_S); - TestBoolProperty(m_settings->show_locations, SETTINGS_SHOW_LOCATIONS_S); - TestBoolProperty(m_settings->show_week_numbers, SETTINGS_SHOW_WEEK_NUMBERS_S); - TestBoolProperty(m_settings->show_year, SETTINGS_SHOW_YEAR_S); -} - -TEST_F(SettingsFixture, StringProperties) -{ - TestStringProperty(m_settings->custom_time_format, SETTINGS_CUSTOM_TIME_FORMAT_S); - TestStringProperty(m_settings->timezone_name, SETTINGS_TIMEZONE_NAME_S); -} - -TEST_F(SettingsFixture, TimeFormatMode) -{ - const auto key = SETTINGS_TIME_FORMAT_S; - const TimeFormatMode modes[] = { TIME_FORMAT_MODE_LOCALE_DEFAULT, - TIME_FORMAT_MODE_12_HOUR, - TIME_FORMAT_MODE_24_HOUR, - TIME_FORMAT_MODE_CUSTOM }; - - for(const auto& mode : modes) - { - g_settings_set_enum(m_gsettings, key, mode); - EXPECT_EQ(mode, m_settings->time_format_mode.get()); - } - - for(const auto& mode : modes) - { - m_settings->time_format_mode.set(mode); - EXPECT_EQ(mode, g_settings_get_enum(m_gsettings, key)); - } -} - -namespace -{ - std::vector strv_to_vector(const gchar** strv) - { - std::vector v; - for(int i=0; strv && strv[i]; i++) - v.push_back(strv[i]); - return v; - } -}; - -TEST_F(SettingsFixture, Locations) -{ - const auto key = SETTINGS_LOCATIONS_S; - - const gchar* astrv[] = {"America/Los_Angeles Oakland", "America/Chicago Oklahoma City", "Europe/London London", NULL}; - const gchar* bstrv[] = {"America/Denver", "Europe/London London", "Europe/Berlin Berlin", NULL}; - const std::vector av = strv_to_vector(astrv); - const std::vector bv = strv_to_vector(bstrv); - - g_settings_set_strv(m_gsettings, key, astrv); - EXPECT_EQ(av, m_settings->locations.get()); - g_settings_set_strv(m_gsettings, key, bstrv); - EXPECT_EQ(bv, m_settings->locations.get()); - - m_settings->locations.set(av); - auto tmp = g_settings_get_strv(m_gsettings, key); - auto vtmp = strv_to_vector((const gchar**)tmp); - g_strfreev(tmp); - EXPECT_EQ(av, vtmp); - - m_settings->locations.set(bv); - tmp = g_settings_get_strv(m_gsettings, key); - vtmp = strv_to_vector((const gchar**)tmp); - g_strfreev(tmp); - EXPECT_EQ(bv, vtmp); -} - -#if 0 - core::Property> locations; - core::Property time_format_mode; - -#endif diff --git a/tests/test-settings.cpp b/tests/test-settings.cpp new file mode 100644 index 0000000..9e52197 --- /dev/null +++ b/tests/test-settings.cpp @@ -0,0 +1,197 @@ +/* + * Copyright 2013 Canonical Ltd. + * + * Authors: + * Charles Kerr + * + * 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 . + */ + +#include "glib-fixture.h" + +#include +#include + +using namespace unity::indicator::datetime; + +/*** +**** +***/ + +class SettingsFixture: public GlibFixture +{ +private: + typedef GlibFixture super; + +protected: + + std::shared_ptr m_live; + std::shared_ptr m_settings; + GSettings * m_gsettings; + + virtual void SetUp() + { + super::SetUp(); + + m_gsettings = g_settings_new(SETTINGS_INTERFACE); + m_live.reset(new LiveSettings); + m_settings = std::dynamic_pointer_cast(m_live); + } + + virtual void TearDown() + { + g_clear_object(&m_gsettings); + m_settings.reset(); + m_live.reset(); + + super::TearDown(); + } + + void TestBoolProperty(core::Property& property, const gchar* key) + { + EXPECT_EQ(g_settings_get_boolean(m_gsettings, key), property.get()); + g_settings_set_boolean(m_gsettings, key, false); + EXPECT_EQ(false, property.get()); + g_settings_set_boolean(m_gsettings, key, true); + EXPECT_EQ(true, property.get()); + + property.set(false); + EXPECT_EQ(false, g_settings_get_boolean(m_gsettings, key)); + property.set(true); + EXPECT_EQ(true, g_settings_get_boolean(m_gsettings, key)); + } + + void TestStringProperty(core::Property& property, const gchar* key) + { + gchar* tmp; + std::string str; + + tmp = g_settings_get_string(m_gsettings, key); + EXPECT_EQ(tmp, property.get()); + g_clear_pointer(&tmp, g_free); + + str = "a"; + g_settings_set_string(m_gsettings, key, str.c_str()); + EXPECT_EQ(str, property.get()); + + str = "b"; + g_settings_set_string(m_gsettings, key, str.c_str()); + EXPECT_EQ(str, property.get()); + + str = "a"; + property.set(str); + tmp = g_settings_get_string(m_gsettings, key); + EXPECT_EQ(str, tmp); + g_clear_pointer(&tmp, g_free); + + str = "b"; + property.set(str); + tmp = g_settings_get_string(m_gsettings, key); + EXPECT_EQ(str, tmp); + g_clear_pointer(&tmp, g_free); + } +}; + +/*** +**** +***/ + +TEST_F(SettingsFixture, HelloWorld) +{ + EXPECT_TRUE(true); +} + +TEST_F(SettingsFixture, BoolProperties) +{ + TestBoolProperty(m_settings->show_seconds, SETTINGS_SHOW_SECONDS_S); + TestBoolProperty(m_settings->show_calendar, SETTINGS_SHOW_CALENDAR_S); + TestBoolProperty(m_settings->show_clock, SETTINGS_SHOW_CLOCK_S); + TestBoolProperty(m_settings->show_date, SETTINGS_SHOW_DATE_S); + TestBoolProperty(m_settings->show_day, SETTINGS_SHOW_DAY_S); + TestBoolProperty(m_settings->show_detected_location, SETTINGS_SHOW_DETECTED_S); + TestBoolProperty(m_settings->show_events, SETTINGS_SHOW_EVENTS_S); + TestBoolProperty(m_settings->show_locations, SETTINGS_SHOW_LOCATIONS_S); + TestBoolProperty(m_settings->show_week_numbers, SETTINGS_SHOW_WEEK_NUMBERS_S); + TestBoolProperty(m_settings->show_year, SETTINGS_SHOW_YEAR_S); +} + +TEST_F(SettingsFixture, StringProperties) +{ + TestStringProperty(m_settings->custom_time_format, SETTINGS_CUSTOM_TIME_FORMAT_S); + TestStringProperty(m_settings->timezone_name, SETTINGS_TIMEZONE_NAME_S); +} + +TEST_F(SettingsFixture, TimeFormatMode) +{ + const auto key = SETTINGS_TIME_FORMAT_S; + const TimeFormatMode modes[] = { TIME_FORMAT_MODE_LOCALE_DEFAULT, + TIME_FORMAT_MODE_12_HOUR, + TIME_FORMAT_MODE_24_HOUR, + TIME_FORMAT_MODE_CUSTOM }; + + for(const auto& mode : modes) + { + g_settings_set_enum(m_gsettings, key, mode); + EXPECT_EQ(mode, m_settings->time_format_mode.get()); + } + + for(const auto& mode : modes) + { + m_settings->time_format_mode.set(mode); + EXPECT_EQ(mode, g_settings_get_enum(m_gsettings, key)); + } +} + +namespace +{ + std::vector strv_to_vector(const gchar** strv) + { + std::vector v; + for(int i=0; strv && strv[i]; i++) + v.push_back(strv[i]); + return v; + } +}; + +TEST_F(SettingsFixture, Locations) +{ + const auto key = SETTINGS_LOCATIONS_S; + + const gchar* astrv[] = {"America/Los_Angeles Oakland", "America/Chicago Oklahoma City", "Europe/London London", NULL}; + const gchar* bstrv[] = {"America/Denver", "Europe/London London", "Europe/Berlin Berlin", NULL}; + const std::vector av = strv_to_vector(astrv); + const std::vector bv = strv_to_vector(bstrv); + + g_settings_set_strv(m_gsettings, key, astrv); + EXPECT_EQ(av, m_settings->locations.get()); + g_settings_set_strv(m_gsettings, key, bstrv); + EXPECT_EQ(bv, m_settings->locations.get()); + + m_settings->locations.set(av); + auto tmp = g_settings_get_strv(m_gsettings, key); + auto vtmp = strv_to_vector((const gchar**)tmp); + g_strfreev(tmp); + EXPECT_EQ(av, vtmp); + + m_settings->locations.set(bv); + tmp = g_settings_get_strv(m_gsettings, key); + vtmp = strv_to_vector((const gchar**)tmp); + g_strfreev(tmp); + EXPECT_EQ(bv, vtmp); +} + +#if 0 + core::Property> locations; + core::Property time_format_mode; + +#endif diff --git a/tests/test-timezone-file.cc b/tests/test-timezone-file.cc deleted file mode 100644 index 453b353..0000000 --- a/tests/test-timezone-file.cc +++ /dev/null @@ -1,133 +0,0 @@ - -/* - * Copyright 2013 Canonical Ltd. - * - * Authors: - * Charles Kerr - * - * 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 . - */ - -#include "glib-fixture.h" - -#include - -//#include -//#include -//#include -//#include -//#include -//#include -//#include -//#include - -#include // fopen() -//#include // chmod() -#include // sync() - -using unity::indicator::datetime::FileTimezone; - - -/*** -**** -***/ - -#define TIMEZONE_FILE (SANDBOX"/timezone") - -class TimezoneFixture: public GlibFixture -{ - private: - - typedef GlibFixture super; - - protected: - - virtual void SetUp() - { - super::SetUp(); - } - - virtual void TearDown() - { - super::TearDown(); - } - - public: - - /* convenience func to set the timezone file */ - void set_file(const std::string& text) - { - auto fp = fopen(TIMEZONE_FILE, "w+"); - fprintf(fp, "%s\n", text.c_str()); - fclose(fp); - sync(); - } -}; - - -/** - * Test that timezone-file warns, but doesn't crash, if the timezone file doesn't exist - */ -TEST_F(TimezoneFixture, NoFile) -{ - remove(TIMEZONE_FILE); - ASSERT_FALSE(g_file_test(TIMEZONE_FILE, G_FILE_TEST_EXISTS)); - - FileTimezone tz(TIMEZONE_FILE); - testLogCount(G_LOG_LEVEL_WARNING, 1); -} - - -/** - * Test that timezone-file picks up the initial value - */ -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()); -} - - -/** - * Test that clearing the timezone results in an empty string - */ -TEST_F(TimezoneFixture, ChangedValue) -{ - const std::string initial_timezone = "America/Chicago"; - const std::string changed_timezone = "America/New_York"; - set_file(initial_timezone); - - 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()); - changed = true; - g_main_loop_quit(loop); - }); - - g_idle_add([](gpointer gself){ - static_cast(gself)->set_file("America/New_York"); - // static_cast(gtz)->timezone.set("America/New_York"); - return G_SOURCE_REMOVE; - }, this);//&tz); - - g_main_loop_run(loop); - - ASSERT_TRUE(changed); - ASSERT_EQ(changed_timezone, tz.timezone.get()); -} diff --git a/tests/test-timezone-file.cpp b/tests/test-timezone-file.cpp new file mode 100644 index 0000000..453b353 --- /dev/null +++ b/tests/test-timezone-file.cpp @@ -0,0 +1,133 @@ + +/* + * Copyright 2013 Canonical Ltd. + * + * Authors: + * Charles Kerr + * + * 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 . + */ + +#include "glib-fixture.h" + +#include + +//#include +//#include +//#include +//#include +//#include +//#include +//#include +//#include + +#include // fopen() +//#include // chmod() +#include // sync() + +using unity::indicator::datetime::FileTimezone; + + +/*** +**** +***/ + +#define TIMEZONE_FILE (SANDBOX"/timezone") + +class TimezoneFixture: public GlibFixture +{ + private: + + typedef GlibFixture super; + + protected: + + virtual void SetUp() + { + super::SetUp(); + } + + virtual void TearDown() + { + super::TearDown(); + } + + public: + + /* convenience func to set the timezone file */ + void set_file(const std::string& text) + { + auto fp = fopen(TIMEZONE_FILE, "w+"); + fprintf(fp, "%s\n", text.c_str()); + fclose(fp); + sync(); + } +}; + + +/** + * Test that timezone-file warns, but doesn't crash, if the timezone file doesn't exist + */ +TEST_F(TimezoneFixture, NoFile) +{ + remove(TIMEZONE_FILE); + ASSERT_FALSE(g_file_test(TIMEZONE_FILE, G_FILE_TEST_EXISTS)); + + FileTimezone tz(TIMEZONE_FILE); + testLogCount(G_LOG_LEVEL_WARNING, 1); +} + + +/** + * Test that timezone-file picks up the initial value + */ +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()); +} + + +/** + * Test that clearing the timezone results in an empty string + */ +TEST_F(TimezoneFixture, ChangedValue) +{ + const std::string initial_timezone = "America/Chicago"; + const std::string changed_timezone = "America/New_York"; + set_file(initial_timezone); + + 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()); + changed = true; + g_main_loop_quit(loop); + }); + + g_idle_add([](gpointer gself){ + static_cast(gself)->set_file("America/New_York"); + // static_cast(gtz)->timezone.set("America/New_York"); + return G_SOURCE_REMOVE; + }, this);//&tz); + + g_main_loop_run(loop); + + ASSERT_TRUE(changed); + ASSERT_EQ(changed_timezone, tz.timezone.get()); +} diff --git a/tests/test-timezone-geoclue.cc b/tests/test-timezone-geoclue.cc deleted file mode 100644 index 4bf08a7..0000000 --- a/tests/test-timezone-geoclue.cc +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Copyright 2013 Canonical Ltd. - * - * Authors: - * Charles Kerr - * - * 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 . - */ - -#include "geoclue-fixture.h" - -#include - -//#include - -using unity::indicator::datetime::GeoclueTimezone; - -/*** -**** -***/ - -class TimezoneGeoclueFixture : public GeoclueFixture -{ -}; - -#if 0 -namespace -{ - struct EmitAddressChangedData - { - DbusTestDbusMock * mock = nullptr; - DbusTestDbusMockObject * obj_client = nullptr; - std::string timezone; - EmitAddressChangedData(DbusTestDbusMock * mock_, - DbusTestDbusMockObject * obj_client_, - const std::string& timezone_): mock(mock_), obj_client(obj_client_), timezone(timezone_) {} - }; - - gboolean emit_address_changed_idle(gpointer gdata) - { - auto data = static_cast(gdata); - - GError * error = nullptr; - 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))"), - &error); - if (error) - { - g_warning("%s: %s", G_STRFUNC, error->message); - g_error_free(error); - } - - delete data; - return G_SOURCE_REMOVE; - } -} -#endif - -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()); - - // 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()); - changed = true; - 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()); -} - - diff --git a/tests/test-timezone-geoclue.cpp b/tests/test-timezone-geoclue.cpp new file mode 100644 index 0000000..4bf08a7 --- /dev/null +++ b/tests/test-timezone-geoclue.cpp @@ -0,0 +1,97 @@ +/* + * Copyright 2013 Canonical Ltd. + * + * Authors: + * Charles Kerr + * + * 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 . + */ + +#include "geoclue-fixture.h" + +#include + +//#include + +using unity::indicator::datetime::GeoclueTimezone; + +/*** +**** +***/ + +class TimezoneGeoclueFixture : public GeoclueFixture +{ +}; + +#if 0 +namespace +{ + struct EmitAddressChangedData + { + DbusTestDbusMock * mock = nullptr; + DbusTestDbusMockObject * obj_client = nullptr; + std::string timezone; + EmitAddressChangedData(DbusTestDbusMock * mock_, + DbusTestDbusMockObject * obj_client_, + const std::string& timezone_): mock(mock_), obj_client(obj_client_), timezone(timezone_) {} + }; + + gboolean emit_address_changed_idle(gpointer gdata) + { + auto data = static_cast(gdata); + + GError * error = nullptr; + 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))"), + &error); + if (error) + { + g_warning("%s: %s", G_STRFUNC, error->message); + g_error_free(error); + } + + delete data; + return G_SOURCE_REMOVE; + } +} +#endif + +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()); + + // 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()); + changed = true; + 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()); +} + + diff --git a/tests/test-timezones.cc b/tests/test-timezones.cc deleted file mode 100644 index 3f02761..0000000 --- a/tests/test-timezones.cc +++ /dev/null @@ -1,124 +0,0 @@ -/* - * 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 . - * - * Authors: - * Charles Kerr - */ - -#include "geoclue-fixture.h" - -#include -#include - -#include // std::shared_ptr - -#include // fopen() -#include // sync() - -using namespace unity::indicator::datetime; - -typedef GeoclueFixture TimezonesFixture; - -#define TIMEZONE_FILE (SANDBOX "/timezone") - -namespace -{ - /* convenience func to set the timezone file */ - void set_file(const std::string& text) - { - auto fp = fopen(TIMEZONE_FILE, "w+"); - fprintf(fp, "%s\n", text.c_str()); - fclose(fp); - sync(); - } -} - - -TEST_F(TimezonesFixture, ManagerTest) -{ - std::string timezone_file = "America/New_York"; - std::string timezone_geo = "America/Denver"; - - set_file(timezone_file); - std::shared_ptr settings(new Settings); - LiveTimezones z(settings, 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 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); - }); - - // start listening for a timezone change, then change the timezone - bool zones_changed = false; - auto zones_connection = z.timezones.changed().connect([&zones_changed, &zones, this](const std::set& timezones) { - zones_changed = true; - zones = timezones; - g_main_loop_quit(loop); - }); - - g_idle_add([](gpointer s_in) { - auto s = static_cast(s_in); - g_message("geolocation was %d", (int)s->show_detected_location.get()); - g_message("turning geolocation on"); - s->show_detected_location.set(true); - return G_SOURCE_REMOVE; - }, settings.get()); - - // 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)); - zones_changed = false; - - // now tweak the geoclue value... the geoclue-detected timezone should change, - // causing the 'timezones' property to change - 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)); - - // 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(str)); return G_SOURCE_REMOVE;}, const_cast(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-timezones.cpp b/tests/test-timezones.cpp new file mode 100644 index 0000000..3f02761 --- /dev/null +++ b/tests/test-timezones.cpp @@ -0,0 +1,124 @@ +/* + * 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 . + * + * Authors: + * Charles Kerr + */ + +#include "geoclue-fixture.h" + +#include +#include + +#include // std::shared_ptr + +#include // fopen() +#include // sync() + +using namespace unity::indicator::datetime; + +typedef GeoclueFixture TimezonesFixture; + +#define TIMEZONE_FILE (SANDBOX "/timezone") + +namespace +{ + /* convenience func to set the timezone file */ + void set_file(const std::string& text) + { + auto fp = fopen(TIMEZONE_FILE, "w+"); + fprintf(fp, "%s\n", text.c_str()); + fclose(fp); + sync(); + } +} + + +TEST_F(TimezonesFixture, ManagerTest) +{ + std::string timezone_file = "America/New_York"; + std::string timezone_geo = "America/Denver"; + + set_file(timezone_file); + std::shared_ptr settings(new Settings); + LiveTimezones z(settings, 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 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); + }); + + // start listening for a timezone change, then change the timezone + bool zones_changed = false; + auto zones_connection = z.timezones.changed().connect([&zones_changed, &zones, this](const std::set& timezones) { + zones_changed = true; + zones = timezones; + g_main_loop_quit(loop); + }); + + g_idle_add([](gpointer s_in) { + auto s = static_cast(s_in); + g_message("geolocation was %d", (int)s->show_detected_location.get()); + g_message("turning geolocation on"); + s->show_detected_location.set(true); + return G_SOURCE_REMOVE; + }, settings.get()); + + // 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)); + zones_changed = false; + + // now tweak the geoclue value... the geoclue-detected timezone should change, + // causing the 'timezones' property to change + 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)); + + // 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(str)); return G_SOURCE_REMOVE;}, const_cast(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 deleted file mode 100644 index 2fe6a2e..0000000 --- a/tests/test-utils.cc +++ /dev/null @@ -1,74 +0,0 @@ -/* - * 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 . - * - * Authors: - * Charles Kerr - */ - -#include - -#include - -TEST(UtilsTest, SplitSettingsLocation) -{ - 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(const auto& test_case : test_cases) - { - char * zone = nullptr; - char * name = nullptr; - - split_settings_location(test_case.location, &zone, &name); - ASSERT_STREQ(test_case.expected_zone, zone); - ASSERT_STREQ(test_case.expected_name, name); - - g_free(zone); - g_free(name); - } -} - -TEST(UtilsTest, BeautifulTimezoneName) -{ - struct { - const char* timezone; - const char* location; - const char* expected_name; - } test_cases[] = { - { "America/Chicago", NULL, "Chicago" }, - { "America/Chicago", "America/Chicago", "Chicago" }, - { "America/Chicago", "America/Chigago Chicago", "Chicago" }, - { "America/Chicago", "America/Chicago Oklahoma City", "Oklahoma City" }, - { "America/Chicago", "Europe/London London", "Chicago" } - }; - - for(const auto& test_case : test_cases) - { - auto name = get_beautified_timezone_name(test_case.timezone, test_case.location); - EXPECT_STREQ(test_case.expected_name, name); - g_free(name); - } -} diff --git a/tests/test-utils.cpp b/tests/test-utils.cpp new file mode 100644 index 0000000..2fe6a2e --- /dev/null +++ b/tests/test-utils.cpp @@ -0,0 +1,74 @@ +/* + * 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 . + * + * Authors: + * Charles Kerr + */ + +#include + +#include + +TEST(UtilsTest, SplitSettingsLocation) +{ + 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(const auto& test_case : test_cases) + { + char * zone = nullptr; + char * name = nullptr; + + split_settings_location(test_case.location, &zone, &name); + ASSERT_STREQ(test_case.expected_zone, zone); + ASSERT_STREQ(test_case.expected_name, name); + + g_free(zone); + g_free(name); + } +} + +TEST(UtilsTest, BeautifulTimezoneName) +{ + struct { + const char* timezone; + const char* location; + const char* expected_name; + } test_cases[] = { + { "America/Chicago", NULL, "Chicago" }, + { "America/Chicago", "America/Chicago", "Chicago" }, + { "America/Chicago", "America/Chigago Chicago", "Chicago" }, + { "America/Chicago", "America/Chicago Oklahoma City", "Oklahoma City" }, + { "America/Chicago", "Europe/London London", "Chicago" } + }; + + for(const auto& test_case : test_cases) + { + auto name = get_beautified_timezone_name(test_case.timezone, test_case.location); + EXPECT_STREQ(test_case.expected_name, name); + g_free(name); + } +} -- cgit v1.2.3 From 572377478193fab7189e817f08487a17543ee32b Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Wed, 22 Jan 2014 09:16:32 -0600 Subject: silence a minor compiler warning in test-settings --- tests/test-settings.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'tests') diff --git a/tests/test-settings.cpp b/tests/test-settings.cpp index 9e52197..df01cd7 100644 --- a/tests/test-settings.cpp +++ b/tests/test-settings.cpp @@ -61,14 +61,14 @@ protected: { EXPECT_EQ(g_settings_get_boolean(m_gsettings, key), property.get()); g_settings_set_boolean(m_gsettings, key, false); - EXPECT_EQ(false, property.get()); + EXPECT_FALSE(property.get()); g_settings_set_boolean(m_gsettings, key, true); - EXPECT_EQ(true, property.get()); + EXPECT_TRUE(property.get()); property.set(false); - EXPECT_EQ(false, g_settings_get_boolean(m_gsettings, key)); + EXPECT_FALSE(g_settings_get_boolean(m_gsettings, key)); property.set(true); - EXPECT_EQ(true, g_settings_get_boolean(m_gsettings, key)); + EXPECT_TRUE(g_settings_get_boolean(m_gsettings, key)); } void TestStringProperty(core::Property& property, const gchar* key) -- cgit v1.2.3 From 2db8f6e7c4b7148377800400c72bb2e59b793d3a Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Wed, 22 Jan 2014 10:01:20 -0600 Subject: remove the State.timezones property. Timezones is a helper class for LiveClock and doesn't need to be public in State. --- tests/state-mock.h | 3 --- 1 file changed, 3 deletions(-) (limited to 'tests') diff --git a/tests/state-mock.h b/tests/state-mock.h index 2104aa0..f2e58e6 100644 --- a/tests/state-mock.h +++ b/tests/state-mock.h @@ -18,10 +18,8 @@ */ #include -#include #include #include -#include using namespace unity::indicator::datetime; @@ -35,7 +33,6 @@ public: const DateTime now = DateTime::NowLocal(); mock_clock.reset(new MockClock(now)); settings.reset(new Settings); - timezones.reset(new Timezones); clock = std::dynamic_pointer_cast(mock_clock); planner.reset(new MockPlanner); planner->time = now; -- cgit v1.2.3 From 063ff0ef0a7761e713b7b36e220e0e2bfa442326 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Wed, 22 Jan 2014 10:14:56 -0600 Subject: sync test-exporter with the greeter profile's header names that changed in r325 --- tests/test-exporter.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'tests') diff --git a/tests/test-exporter.cpp b/tests/test-exporter.cpp index ea62cd3..aa9e89d 100644 --- a/tests/test-exporter.cpp +++ b/tests/test-exporter.cpp @@ -115,9 +115,9 @@ TEST_F(ExporterFixture, Publish) EXPECT_EQ(1, names.count("activate-phone-settings")); EXPECT_EQ(1, names.count("activate-planner")); EXPECT_EQ(1, names.count("calendar")); - EXPECT_EQ(1, names.count("desktop-greeter-header")); + EXPECT_EQ(1, names.count("desktop_greeter-header")); EXPECT_EQ(1, names.count("desktop-header")); - EXPECT_EQ(1, names.count("phone-greeter-header")); + EXPECT_EQ(1, names.count("phone_greeter-header")); EXPECT_EQ(1, names.count("phone-header")); EXPECT_EQ(1, names.count("set-location")); -- cgit v1.2.3 From 08b1cfd6bc97cae18b916d97a03781986e7421fe Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Wed, 22 Jan 2014 10:15:56 -0600 Subject: move planner-mock.h from include/datetime/ to tests/ because it's only needed by the tests. --- tests/planner-mock.h | 52 +++++++++++++++++++--------------------------------- tests/state-mock.h | 3 ++- 2 files changed, 21 insertions(+), 34 deletions(-) (limited to 'tests') diff --git a/tests/planner-mock.h b/tests/planner-mock.h index 8d7d7c2..44d30c7 100644 --- a/tests/planner-mock.h +++ b/tests/planner-mock.h @@ -1,9 +1,6 @@ /* * Copyright 2013 Canonical Ltd. * - * Authors: - * Charles Kerr - * * 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. @@ -15,44 +12,33 @@ * * You should have received a copy of the GNU General Public License along * with this program. If not, see . + * + * Authors: + * Charles Kerr */ -#ifndef __INDICATOR_DATETIME_PLANNER_MOCK__H__ -#define __INDICATOR_DATETIME_PLANNER_MOCK__H__ - -#include "planner.h" /* parent class */ +#ifndef INDICATOR_DATETIME_PLANNER_MOCK_H +#define INDICATOR_DATETIME_PLANNER_MOCK_H -G_BEGIN_DECLS +#include -#define INDICATOR_TYPE_DATETIME_PLANNER_MOCK (indicator_datetime_planner_mock_get_type()) -#define INDICATOR_DATETIME_PLANNER_MOCK(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), INDICATOR_TYPE_DATETIME_PLANNER_MOCK, IndicatorDatetimePlannerMock)) -#define INDICATOR_DATETIME_PLANNER_MOCK_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), INDICATOR_TYPE_DATETIME_PLANNER_MOCK, IndicatorDatetimePlannerMockClass)) -#define INDICATOR_IS_DATETIME_PLANNER_MOCK(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), INDICATOR_TYPE_DATETIME_PLANNER_MOCK)) - -typedef struct _IndicatorDatetimePlannerMock IndicatorDatetimePlannerMock; -typedef struct _IndicatorDatetimePlannerMockPriv IndicatorDatetimePlannerMockPriv; -typedef struct _IndicatorDatetimePlannerMockClass IndicatorDatetimePlannerMockClass; - -GType indicator_datetime_planner_mock_get_type (void); +namespace unity { +namespace indicator { +namespace datetime { /** - * An IndicatorDatetimePlanner which uses Evolution Data Server - * to get its list of appointments. + * \brief Planner which does nothing on its own. + * It requires its client must set its appointments property. */ -struct _IndicatorDatetimePlannerMock -{ - /*< private >*/ - IndicatorDatetimePlanner parent; - IndicatorDatetimePlannerMockPriv * priv; -}; - -struct _IndicatorDatetimePlannerMockClass +class MockPlanner: public Planner { - IndicatorDatetimePlannerClass parent_class; +public: + MockPlanner() =default; + virtual ~MockPlanner() =default; }; -IndicatorDatetimePlanner * indicator_datetime_planner_mock_new (void); - -G_END_DECLS +} // namespace datetime +} // namespace indicator +} // namespace unity -#endif /* __INDICATOR_DATETIME_PLANNER_MOCK__H__ */ +#endif // INDICATOR_DATETIME_PLANNER_MOCK_H diff --git a/tests/state-mock.h b/tests/state-mock.h index f2e58e6..64ab08b 100644 --- a/tests/state-mock.h +++ b/tests/state-mock.h @@ -17,8 +17,9 @@ * Charles Kerr */ +#include "planner-mock.h" + #include -#include #include using namespace unity::indicator::datetime; -- cgit v1.2.3 From aad7e86a109aeec75b3772cda20478363f966745 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Wed, 22 Jan 2014 14:28:20 -0600 Subject: Alarms is going to need to know when the clock's minute changes. We already have a timer for that in Formatter, so move it from there to Clock and add a corresponding public signal Clock.minuteChanged that both Formatter and Alarms can use. Sync unit tests. --- tests/test-clock.cpp | 32 ++++++++++++++------------------ 1 file changed, 14 insertions(+), 18 deletions(-) (limited to 'tests') diff --git a/tests/test-clock.cpp b/tests/test-clock.cpp index 142ccad..4271374 100644 --- a/tests/test-clock.cpp +++ b/tests/test-clock.cpp @@ -46,28 +46,24 @@ class ClockFixture: public TestDBusFixture } }; -/** - * 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, MinuteChangedSignalShouldTriggerOncePerMinute) { + // start up a live clock std::shared_ptr zones(new Timezones); zones->timezone.set("America/New_York"); LiveClock clock(zones); wait_msec(500); // wait for the bus to set up - bool skewed = false; - clock.skewDetected.connect([&skewed](){ - skewed = true; - g_warn_if_reached(); - return G_SOURCE_REMOVE; - }); - - const unsigned int intervalSec = 3; - clock.skewTestIntervalSec.set(intervalSec); - wait_msec(intervalSec * 2.5 * 1000); - EXPECT_FALSE(skewed); + // count how many times clock.minuteChanged() is emitted over the next minute + const DateTime now = clock.localtime(); + const auto gnow = now.get(); + auto gthen = g_date_time_add_minutes(gnow, 1); + int count = 0; + clock.minuteChanged.connect([&count](){count++;}); + const auto msec = g_date_time_difference(gthen,gnow) / 1000; + wait_msec(msec); + EXPECT_EQ(1, count); + g_date_time_unref(gthen); } /*** @@ -99,7 +95,7 @@ TEST_F(ClockFixture, TimezoneChangeTriggersSkew) g_time_zone_unref(tz_nyc); /// change the timezones! - clock.skewDetected.connect([this](){ + clock.minuteChanged.connect([this](){ g_main_loop_quit(loop); }); g_idle_add([](gpointer gs){ @@ -128,7 +124,7 @@ TEST_F(ClockFixture, SleepTriggersSkew) wait_msec(500); // wait for the bus to set up bool skewed = false; - clock.skewDetected.connect([&skewed, this](){ + clock.minuteChanged.connect([&skewed, this](){ skewed = true; g_main_loop_quit(loop); return G_SOURCE_REMOVE; -- cgit v1.2.3 From 7b09a0ff5652bdca7c8d8e046d2af6a696f94147 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Sat, 25 Jan 2014 16:54:41 -0600 Subject: sync the exported calendar state with the #State backend --- tests/actions-mock.h | 8 +--- tests/state-mock.h | 1 - tests/test-actions.cpp | 19 +++++--- tests/test-live-actions.cpp | 114 ++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 127 insertions(+), 15 deletions(-) (limited to 'tests') diff --git a/tests/actions-mock.h b/tests/actions-mock.h index 112900b..da93cb9 100644 --- a/tests/actions-mock.h +++ b/tests/actions-mock.h @@ -35,8 +35,7 @@ public: ~MockActions() =default; enum Action { OpenDesktopSettings, OpenPhoneSettings, OpenPhoneClockApp, - OpenPlanner, OpenPlannerAt, OpenAppointment, - SetLocation, SetCalendarDate }; + OpenPlanner, OpenPlannerAt, OpenAppointment, SetLocation }; const std::vector& history() const { return m_history; } const DateTime& date_time() const { return m_date_time; } const std::string& zone() const { return m_zone; } @@ -68,11 +67,6 @@ public: 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; diff --git a/tests/state-mock.h b/tests/state-mock.h index 64ab08b..721b82f 100644 --- a/tests/state-mock.h +++ b/tests/state-mock.h @@ -38,7 +38,6 @@ public: planner.reset(new MockPlanner); planner->time = now; locations.reset(new Locations); - calendar_day = now; } }; diff --git a/tests/test-actions.cpp b/tests/test-actions.cpp index 4329608..c30d1fb 100644 --- a/tests/test-actions.cpp +++ b/tests/test-actions.cpp @@ -137,18 +137,23 @@ TEST_F(ActionsFixture, SetLocation) TEST_F(ActionsFixture, SetCalendarDate) { + // confirm that such an action exists 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()); + // pick an arbitrary DateTime... + auto tmp = g_date_time_new_local(2010, 1, 2, 3, 4, 5); + const auto now = DateTime(tmp); + g_date_time_unref(tmp); + + // confirm that Planner.time gets changed to that date when we + // activate the 'calendar' action with that date's time_t as the arg + EXPECT_NE (now, m_state->planner->time.get()); + auto v = g_variant_new_int64(now.to_unix()); + g_action_group_activate_action (action_group, action_name, v); + EXPECT_EQ (now, m_state->planner->time.get()); } TEST_F(ActionsFixture, OpenAppointment) diff --git a/tests/test-live-actions.cpp b/tests/test-live-actions.cpp index d3d7720..562b358 100644 --- a/tests/test-live-actions.cpp +++ b/tests/test-live-actions.cpp @@ -287,3 +287,117 @@ TEST_F(LiveActionsFixture, OpenPlannerAt) const std::string expected = now.format("evolution \"calendar:///?startdate=%Y%m%d\""); EXPECT_EQ(expected, m_live_actions->last_cmd); } + +TEST_F(LiveActionsFixture, CalendarState) +{ + // init the clock + auto tmp = g_date_time_new_local (2014, 1, 1, 0, 0, 0); + const DateTime now (tmp); + g_date_time_unref (tmp); + m_mock_state->mock_clock->set_localtime (now); + m_state->planner->time.set(now); + + /// + /// Test the default calendar state. + /// + + auto action_group = m_actions->action_group(); + auto calendar_state = g_action_group_get_action_state (action_group, "calendar"); + EXPECT_TRUE (calendar_state != nullptr); + EXPECT_TRUE (g_variant_is_of_type (calendar_state, G_VARIANT_TYPE_DICTIONARY)); + + // there's nothing in the planner yet, so appointment-days should be an empty array + auto v = g_variant_lookup_value (calendar_state, "appointment-days", G_VARIANT_TYPE_ARRAY); + EXPECT_TRUE (v != nullptr); + EXPECT_EQ (0, g_variant_n_children (v)); + g_clear_pointer (&v, g_variant_unref); + + // calendar-day should be in sync with m_state->calendar_day + v = g_variant_lookup_value (calendar_state, "calendar-day", G_VARIANT_TYPE_INT64); + EXPECT_TRUE (v != nullptr); + EXPECT_EQ (m_state->planner->time.get().to_unix(), g_variant_get_int64(v)); + g_clear_pointer (&v, g_variant_unref); + + // show-week-numbers should be false because MockSettings defaults everything to 0 + v = g_variant_lookup_value (calendar_state, "show-week-numbers", G_VARIANT_TYPE_BOOLEAN); + EXPECT_TRUE (v != nullptr); + EXPECT_FALSE (g_variant_get_boolean (v)); + g_clear_pointer (&v, g_variant_unref); + + // cleanup this step + g_clear_pointer (&calendar_state, g_variant_unref); + + + /// + /// Now add appointments to the planner and confirm that the state keeps in sync + /// + + auto tomorrow = g_date_time_add_days (now.get(), 1); + auto tomorrow_begin = g_date_time_add_full (tomorrow, 0, 0, 0, + -g_date_time_get_hour(tomorrow), + -g_date_time_get_minute(tomorrow), + -g_date_time_get_seconds(tomorrow)); + auto tomorrow_end = g_date_time_add_full (tomorrow_begin, 0, 0, 1, 0, 0, -1); + Appointment a1; + a1.color = "green"; + a1.summary = "write unit tests"; + a1.url = "http://www.ubuntu.com/"; + a1.uid = "D4B57D50247291478ED31DED17FF0A9838DED402"; + a1.begin = tomorrow_begin; + a1.end = tomorrow_end; + + auto next_begin = g_date_time_add_days (tomorrow_begin, 1); + auto next_end = g_date_time_add_full (next_begin, 0, 0, 1, 0, 0, -1); + Appointment a2; + a2.color = "orange"; + a2.summary = "code review"; + a2.url = "http://www.ubuntu.com/"; + a2.uid = "2756ff7de3745bbffd65d2e4779c37c7ca60d843"; + a2.begin = next_begin; + a2.end = next_end; + + m_state->planner->thisMonth.set(std::vector({a1, a2})); + + /// + /// Now test the calendar state again. + /// The thisMonth field should now contain the appointments we just added. + /// + + calendar_state = g_action_group_get_action_state (action_group, "calendar"); + v = g_variant_lookup_value (calendar_state, "appointment-days", G_VARIANT_TYPE_ARRAY); + EXPECT_TRUE (v != nullptr); + int i; + g_variant_get_child (v, 0, "i", &i); + EXPECT_EQ (g_date_time_get_day_of_month(a1.begin.get()), i); + g_variant_get_child (v, 1, "i", &i); + EXPECT_EQ (g_date_time_get_day_of_month(a2.begin.get()), i); + g_clear_pointer(&v, g_variant_unref); + g_clear_pointer(&calendar_state, g_variant_unref); + + // cleanup this step + g_date_time_unref (next_end); + g_date_time_unref (next_begin); + g_date_time_unref (tomorrow_end); + g_date_time_unref (tomorrow_begin); + g_date_time_unref (tomorrow); + + /// + /// Confirm that the action state's dictionary + /// keeps in sync with settings.show_week_numbers + /// + + auto b = m_state->settings->show_week_numbers.get(); + for (i=0; i<2; i++) + { + b = !b; + m_state->settings->show_week_numbers.set(b); + + calendar_state = g_action_group_get_action_state (action_group, "calendar"); + v = g_variant_lookup_value (calendar_state, "show-week-numbers", G_VARIANT_TYPE_BOOLEAN); + EXPECT_TRUE(v != nullptr); + EXPECT_EQ(b, g_variant_get_boolean(v)); + + g_clear_pointer(&v, g_variant_unref); + g_clear_pointer(&calendar_state, g_variant_unref); + } +} -- cgit v1.2.3 From 1c547710eb14d7805e47205f7c62fb7b0d0f3756 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Mon, 27 Jan 2014 01:26:02 -0600 Subject: add unit tests for utils.cpp's get_timezone_name() --- tests/test-utils.cpp | 32 ++++++++++++++++++++++++++++---- 1 file changed, 28 insertions(+), 4 deletions(-) (limited to 'tests') diff --git a/tests/test-utils.cpp b/tests/test-utils.cpp index 2fe6a2e..036c13f 100644 --- a/tests/test-utils.cpp +++ b/tests/test-utils.cpp @@ -17,6 +17,7 @@ * Charles Kerr */ +#include #include #include @@ -51,24 +52,47 @@ TEST(UtilsTest, SplitSettingsLocation) } } -TEST(UtilsTest, BeautifulTimezoneName) +namespace { struct { const char* timezone; const char* location; const char* expected_name; - } test_cases[] = { + } beautify_timezone_test_cases[] = { { "America/Chicago", NULL, "Chicago" }, { "America/Chicago", "America/Chicago", "Chicago" }, { "America/Chicago", "America/Chigago Chicago", "Chicago" }, { "America/Chicago", "America/Chicago Oklahoma City", "Oklahoma City" }, { "America/Chicago", "Europe/London London", "Chicago" } }; - - for(const auto& test_case : test_cases) +} + +TEST(UtilsTest, BeautifulTimezoneName) +{ + for(const auto& test_case : beautify_timezone_test_cases) { auto name = get_beautified_timezone_name(test_case.timezone, test_case.location); EXPECT_STREQ(test_case.expected_name, name); g_free(name); } } + + +TEST(UtilsTest, GetTimezonename) +{ + // set up a local GSettings + 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); + auto settings = g_settings_new(SETTINGS_INTERFACE); + + for(const auto& test_case : beautify_timezone_test_cases) + { + g_settings_set_string(settings, SETTINGS_TIMEZONE_NAME_S, test_case.location); + auto name = get_timezone_name (test_case.timezone, settings); + EXPECT_STREQ(test_case.expected_name, name); + g_free(name); + } + + g_clear_object(&settings); +} -- cgit v1.2.3 From f320760f20b282e9b2695477ab602d4041a3ada8 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Mon, 27 Jan 2014 01:26:52 -0600 Subject: add test coverage for Exporter's name_lost signal --- tests/test-exporter.cpp | 34 ++++++++++++++++++++-------------- 1 file changed, 20 insertions(+), 14 deletions(-) (limited to 'tests') diff --git a/tests/test-exporter.cpp b/tests/test-exporter.cpp index aa9e89d..104fb4b 100644 --- a/tests/test-exporter.cpp +++ b/tests/test-exporter.cpp @@ -36,17 +36,6 @@ private: typedef GlibFixture super; - static void on_bus_closed(GObject * object, - GAsyncResult * res, - gpointer gself) - { - auto self = static_cast(gself); - GError* err = nullptr; - g_dbus_connection_close_finish(G_DBUS_CONNECTION(object), res, &err); - g_assert_no_error(err); - g_main_loop_quit(self->loop); - } - protected: GTestDBus* bus = nullptr; @@ -65,9 +54,11 @@ protected: void TearDown() { - GDBusConnection* connection = g_bus_get_sync (G_BUS_TYPE_SESSION, nullptr, nullptr); - g_dbus_connection_close(connection, nullptr, on_bus_closed, this); - g_main_loop_run(loop); + GError * error = nullptr; + GDBusConnection* connection = g_bus_get_sync(G_BUS_TYPE_SESSION, nullptr, &error); + if(!g_dbus_connection_is_closed(connection)) + g_dbus_connection_close_sync(connection, nullptr, &error); + g_assert_no_error(error); g_clear_object(&connection); g_test_dbus_down(bus); g_clear_object(&bus); @@ -87,6 +78,10 @@ TEST_F(ExporterFixture, Publish) std::shared_ptr actions(new MockActions(state)); std::vector> menus; + MenuFactory menu_factory (actions, state); + for(int i=0; i Date: Tue, 28 Jan 2014 17:02:34 -0600 Subject: fix bootstrap error in unit tests by ensuring we always use the local gschema instead of the one preinstalled on the system --- tests/CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'tests') diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index c909e0e..c86b4bb 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -35,7 +35,7 @@ add_definitions (-DSANDBOX="${CMAKE_CURRENT_BINARY_DIR}") function(add_test_by_name name) set (TEST_NAME ${name}) - add_executable (${TEST_NAME} ${TEST_NAME}.cpp) + add_executable (${TEST_NAME} ${TEST_NAME}.cpp gschemas.compiled) add_test (${TEST_NAME} ${TEST_NAME}) add_dependencies (${TEST_NAME} libindicatordatetimeservice) target_link_libraries (${TEST_NAME} indicatordatetimeservice gtest ${SERVICE_DEPS_LIBRARIES} ${GTEST_LIBS}) @@ -55,7 +55,7 @@ add_test_by_name(test-utils) function(add_dbusmock_test_by_name name) set (TEST_NAME ${name}) - add_executable (${TEST_NAME} ${TEST_NAME}.cpp) + add_executable (${TEST_NAME} ${TEST_NAME}.cpp gschemas.compiled) add_test (${TEST_NAME} ${TEST_NAME}) add_dependencies (${TEST_NAME} libindicatordatetimeservice) target_link_libraries (${TEST_NAME} indicatordatetimeservice gtest ${SERVICE_DEPS_LIBRARIES} ${DBUSTEST_LIBRARIES} ${GTEST_LIBS}) -- cgit v1.2.3 From c3ee494eefcabd48eb0d2cb8ea8cf8cb1600331a Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Tue, 28 Jan 2014 21:15:39 -0600 Subject: ensure the unit tests' default locale supports utf-8 --- tests/glib-fixture.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'tests') diff --git a/tests/glib-fixture.h b/tests/glib-fixture.h index 3f517d4..1914b8c 100644 --- a/tests/glib-fixture.h +++ b/tests/glib-fixture.h @@ -61,7 +61,7 @@ class GlibFixture : public ::testing::Test virtual void SetUp() { - setlocale(LC_ALL, ""); + setlocale(LC_ALL, "C.UTF-8"); loop = g_main_loop_new(nullptr, false); -- cgit v1.2.3 From 9045a274a93bb96be458e563bebbceca1426da96 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Tue, 28 Jan 2014 21:42:05 -0600 Subject: comment out unit tests that require a version of dbus-test-runner that hasn't landed yet. --- tests/CMakeLists.txt | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) (limited to 'tests') diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index c86b4bb..3dcd151 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -53,12 +53,15 @@ add_test_by_name(test-timezone-file) add_test_by_name(test-utils) -function(add_dbusmock_test_by_name name) - set (TEST_NAME ${name}) - add_executable (${TEST_NAME} ${TEST_NAME}.cpp gschemas.compiled) - add_test (${TEST_NAME} ${TEST_NAME}) - add_dependencies (${TEST_NAME} libindicatordatetimeservice) - target_link_libraries (${TEST_NAME} indicatordatetimeservice gtest ${SERVICE_DEPS_LIBRARIES} ${DBUSTEST_LIBRARIES} ${GTEST_LIBS}) -endfunction() -add_dbusmock_test_by_name(test-timezone-geoclue) -add_dbusmock_test_by_name(test-timezones) +# disabling the timezone unit tests because they require +# https://code.launchpad.net/~ted/dbus-test-runner/multi-interface-test/+merge/199724 +# which hasn't landed yet. These can be re-enabled as soon as that lands. +#function(add_dbusmock_test_by_name name) +# set (TEST_NAME ${name}) +# add_executable (${TEST_NAME} ${TEST_NAME}.cpp gschemas.compiled) +# add_test (${TEST_NAME} ${TEST_NAME}) +# add_dependencies (${TEST_NAME} libindicatordatetimeservice) +# target_link_libraries (${TEST_NAME} indicatordatetimeservice gtest ${SERVICE_DEPS_LIBRARIES} ${DBUSTEST_LIBRARIES} ${GTEST_LIBS}) +#endfunction() +#add_dbusmock_test_by_name(test-timezone-geoclue) +#add_dbusmock_test_by_name(test-timezones) -- cgit v1.2.3 From f07f97ef53522abdce52cf3c7b583c0d6d47aa40 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Wed, 29 Jan 2014 12:50:59 -0600 Subject: sync with lp:~larsu/indicator-datetime/reset-date and add corresponding unit tests. --- tests/test-actions.cpp | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) (limited to 'tests') diff --git a/tests/test-actions.cpp b/tests/test-actions.cpp index c30d1fb..1865cfd 100644 --- a/tests/test-actions.cpp +++ b/tests/test-actions.cpp @@ -156,6 +156,60 @@ TEST_F(ActionsFixture, SetCalendarDate) EXPECT_EQ (now, m_state->planner->time.get()); } +TEST_F(ActionsFixture, ActivatingTheCalendarResetsItsDate) +{ + // Confirm that the GActions exist + auto action_group = m_actions->action_group(); + EXPECT_TRUE(g_action_group_has_action(action_group, "calendar")); + EXPECT_TRUE(g_action_group_has_action(action_group, "calendar-active")); + + /// + /// Prerequisite for the test: move calendar-date away from today + /// + + // move calendar-date a week into the future... + const auto now = m_state->clock->localtime(); + auto next_week = g_date_time_add_weeks(now.get(), 1); + const auto next_week_unix = g_date_time_to_unix(next_week); + g_action_group_activate_action (action_group, "calendar", g_variant_new_int64(next_week_unix)); + + // confirm the planner and calendar action state moved a week into the future + // but that m_state->clock is unchanged + EXPECT_EQ(next_week_unix, m_state->planner->time.get().to_unix()); + EXPECT_EQ(now, m_state->clock->localtime()); + auto calendar_state = g_action_group_get_action_state(action_group, "calendar"); + EXPECT_TRUE(calendar_state != nullptr); + EXPECT_TRUE(g_variant_is_of_type(calendar_state, G_VARIANT_TYPE_DICTIONARY)); + auto v = g_variant_lookup_value(calendar_state, "calendar-day", G_VARIANT_TYPE_INT64); + EXPECT_TRUE(v != nullptr); + EXPECT_EQ(next_week_unix, g_variant_get_int64(v)); + g_clear_pointer(&v, g_variant_unref); + g_clear_pointer(&calendar_state, g_variant_unref); + + /// + /// Now the actual test. + /// We set the state of 'calendar-active' to true, which should reset the calendar date. + /// This is so the calendar always starts on today's date when the indicator's menu is pulled down. + /// + + // change the state... + g_action_group_change_action_state(action_group, "calendar-active", g_variant_new_boolean(true)); + + // confirm the planner and calendar action state were reset back to m_state->clock's time + EXPECT_EQ(now.to_unix(), m_state->planner->time.get().to_unix()); + EXPECT_EQ(now, m_state->clock->localtime()); + calendar_state = g_action_group_get_action_state(action_group, "calendar"); + EXPECT_TRUE(calendar_state != nullptr); + EXPECT_TRUE(g_variant_is_of_type(calendar_state, G_VARIANT_TYPE_DICTIONARY)); + v = g_variant_lookup_value(calendar_state, "calendar-day", G_VARIANT_TYPE_INT64); + EXPECT_TRUE(v != nullptr); + EXPECT_EQ(now.to_unix(), g_variant_get_int64(v)); + g_clear_pointer(&v, g_variant_unref); + g_clear_pointer(&calendar_state, g_variant_unref); + +} + + TEST_F(ActionsFixture, OpenAppointment) { Appointment appt; -- cgit v1.2.3 From 6b2c01ed6063bd7fd12e192668b738a075dc3a24 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Wed, 29 Jan 2014 16:10:50 -0600 Subject: fix instant calendar toggle issue reported in testing by seb128; add a test for this regression --- tests/test-menus.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'tests') diff --git a/tests/test-menus.cpp b/tests/test-menus.cpp index fe1e86e..27248ad 100644 --- a/tests/test-menus.cpp +++ b/tests/test-menus.cpp @@ -93,7 +93,8 @@ protected: { gchar* str = nullptr; const auto actions_expected = (profile == Menu::Desktop) || (profile == Menu::Phone); - const auto calendar_expected = (profile == Menu::Desktop) || (profile == Menu::DesktopGreeter); + const auto calendar_expected = ((profile == Menu::Desktop) || (profile == Menu::DesktopGreeter)) + && (m_state->settings->show_calendar.get()); // get the calendar section auto submenu = g_menu_model_get_item_link(menu_model, 0, G_MENU_LINK_SUBMENU); @@ -377,6 +378,11 @@ TEST_F(MenuFixture, Sections) TEST_F(MenuFixture, Calendar) { + m_state->settings->show_calendar.set(true); + for(auto& menu : m_menus) + InspectCalendar(menu->menu_model(), menu->profile()); + + m_state->settings->show_calendar.set(false); for(auto& menu : m_menus) InspectCalendar(menu->menu_model(), menu->profile()); } -- cgit v1.2.3 From 131f7512975e3e0e1363cb787834abee5b79b4e5 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Wed, 29 Jan 2014 16:26:25 -0600 Subject: =?UTF-8?q?fix=20disabled=20'Add=20Event=E2=80=A6'=20menuitem=20is?= =?UTF-8?q?sue=20reported=20in=20testing=20by=20seb128;=20add=20a=20test?= =?UTF-8?q?=20for=20this=20regression?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tests/test-menus.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'tests') diff --git a/tests/test-menus.cpp b/tests/test-menus.cpp index 27248ad..e9dd7df 100644 --- a/tests/test-menus.cpp +++ b/tests/test-menus.cpp @@ -182,6 +182,14 @@ protected: 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)); + if (appointments_expected) + { + gchar* action = nullptr; + EXPECT_TRUE(g_menu_model_get_item_attribute(section, 0, G_MENU_ATTRIBUTE_ACTION, "s", &action)); + EXPECT_STREQ("indicator.activate-planner", action); + EXPECT_TRUE(g_action_group_has_action(m_actions->action_group(), "activate-planner")); + g_free(action); + } g_clear_object(§ion); // try adding a few appointments and see if the menu updates itself -- cgit v1.2.3 From 9752ca1cd3e75e1245ebb8dcb4719503e332a352 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Thu, 30 Jan 2014 10:57:19 -0600 Subject: fix 'clock app' menuitem on phone profile reported by seb128 and update the corresponding unit tests --- tests/test-menus.cpp | 242 +++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 175 insertions(+), 67 deletions(-) (limited to 'tests') diff --git a/tests/test-menus.cpp b/tests/test-menus.cpp index e9dd7df..73d6036 100644 --- a/tests/test-menus.cpp +++ b/tests/test-menus.cpp @@ -158,42 +158,20 @@ protected: g_object_unref(submenu); } - void InspectAppointments(GMenuModel* menu_model, Menu::Profile profile) - { - const bool appointments_expected = (profile == Menu::Desktop) - || (profile == Menu::Phone); +private: + void InspectEmptySection(GMenuModel* menu_model, Menu::Section section) + { // get the Appointments section auto submenu = g_menu_model_get_item_link(menu_model, 0, G_MENU_LINK_SUBMENU); + auto menu_section = g_menu_model_get_item_link(submenu, section, G_MENU_LINK_SECTION); + EXPECT_EQ(0, g_menu_model_get_n_items(menu_section)); + g_clear_object(&menu_section); + g_clear_object(&submenu); + } - // there shouldn't be any menuitems when "show events" is false - m_state->settings->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 appointments; - m_state->settings->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)); - if (appointments_expected) - { - gchar* action = nullptr; - EXPECT_TRUE(g_menu_model_get_item_attribute(section, 0, G_MENU_ATTRIBUTE_ACTION, "s", &action)); - EXPECT_STREQ("indicator.activate-planner", action); - EXPECT_TRUE(g_action_group_has_action(m_actions->action_group(), "activate-planner")); - g_free(action); - } - g_clear_object(§ion); - - // try adding a few appointments and see if the menu updates itself - + std::vector build_some_appointments() + { const auto now = m_state->clock->localtime(); auto gdt_tomorrow = g_date_time_add_days(now.get(), 1); const auto tomorrow = DateTime(gdt_tomorrow); @@ -206,7 +184,6 @@ protected: 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"; @@ -215,52 +192,183 @@ protected: 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 + return std::vector({a1, a2}); + } - 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) + void InspectAppointmentMenuItem(GMenuModel* section, + int index, + const Appointment& appt) + { + // confirm it has the right x-canonical-type + gchar * str = nullptr; + g_menu_model_get_item_attribute(section, index, "x-canonical-type", "s", &str); + if (appt.has_alarms) + EXPECT_STREQ("com.canonical.indicator.alarm", str); + else + 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, index, "x-canonical-time-format", "s", &str); + EXPECT_TRUE(str && *str); + g_clear_pointer(&str, g_free); + + // confirm the color hint, if it exists, + // is in the x-canonical-color attribute + if (appt.color.empty()) { - gchar * str = nullptr; + EXPECT_FALSE(g_menu_model_get_item_attribute(section, + index, + "x-canonical-color", + "s", + &str)); + } + else + { + EXPECT_TRUE(g_menu_model_get_item_attribute(section, + index, + "x-canonical-color", + "s", + &str)); + EXPECT_EQ(appt.color, str); + } + g_clear_pointer(&str, g_free); - // 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); + // confirm that alarms have an icon + if (appt.has_alarms) + { + auto v = g_menu_model_get_item_attribute_value(section, + index, + 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); } + } + + void InspectAppointmentMenuItems(GMenuModel* section, + int first_appt_index, + const std::vector& appointments) + { + // try adding a few appointments and see if the menu updates itself + m_state->planner->upcoming.set(appointments); + wait_msec(); // wait a moment for the menu to update + + //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::Appointments, G_MENU_LINK_SECTION); + EXPECT_EQ(appointments.size()+1, g_menu_model_get_n_items(section)); + + for (int i=0, n=appointments.size(); isettings->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); - g_object_unref(submenu); + // when "show_events" is true, + // there should be an "add event" button even if there aren't any appointments + std::vector appointments; + m_state->settings->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); + EXPECT_EQ(1, g_menu_model_get_n_items(section)); + gchar* action = nullptr; + EXPECT_TRUE(g_menu_model_get_item_attribute(section, 0, G_MENU_ATTRIBUTE_ACTION, "s", &action)); + const char* expected_action = "activate-planner"; + EXPECT_EQ(std::string("indicator.")+expected_action, action); + EXPECT_TRUE(g_action_group_has_action(m_actions->action_group(), expected_action)); + g_free(action); + g_clear_object(§ion); + + // try adding a few appointments and see if the menu updates itself + appointments = build_some_appointments(); + 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); + EXPECT_EQ(3, g_menu_model_get_n_items(section)); + InspectAppointmentMenuItems(section, 0, appointments); + g_clear_object(§ion); + + // cleanup + g_clear_object(&submenu); + } + + void InspectPhoneAppointments(GMenuModel* menu_model) + { + auto submenu = g_menu_model_get_item_link(menu_model, 0, G_MENU_LINK_SUBMENU); + + // clear all the appointments + std::vector appointments; + m_state->planner->upcoming.set(appointments); + wait_msec(); // wait a moment for the menu to update + + // check that there's a "clock app" menuitem even when there are no appointments + auto section = g_menu_model_get_item_link(submenu, Menu::Appointments, G_MENU_LINK_SECTION); + const char* expected_action = "activate-phone-clock-app"; + EXPECT_EQ(1, g_menu_model_get_n_items(section)); + gchar* action = nullptr; + EXPECT_TRUE(g_menu_model_get_item_attribute(section, 0, G_MENU_ATTRIBUTE_ACTION, "s", &action)); + EXPECT_EQ(std::string("indicator.")+expected_action, action); + EXPECT_TRUE(g_action_group_has_action(m_actions->action_group(), expected_action)); + g_free(action); + g_clear_object(§ion); + + // add some appointments and test them + appointments = build_some_appointments(); + 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); + EXPECT_EQ(3, g_menu_model_get_n_items(section)); + InspectAppointmentMenuItems(section, 1, appointments); + g_clear_object(§ion); + + // cleanup + g_clear_object(&submenu); + } + +protected: + + void InspectAppointments(GMenuModel* menu_model, Menu::Profile profile) + { + switch (profile) + { + case Menu::Desktop: + InspectDesktopAppointments(menu_model); + break; + + case Menu::DesktopGreeter: + InspectEmptySection(menu_model, Menu::Appointments); + break; + + case Menu::Phone: + InspectPhoneAppointments(menu_model); + break; + + case Menu::PhoneGreeter: + InspectEmptySection(menu_model, Menu::Appointments); + break; + + default: + g_warn_if_reached(); + break; + } } void CompareLocationsTo(GMenuModel* menu_model, const std::vector& locations) -- cgit v1.2.3 From 8564861a5026561d94310cd60ed77e3986f64246 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Thu, 30 Jan 2014 14:24:17 -0600 Subject: remove dead files --- tests/planner-mock.c | 178 ------------------------------------------------ tests/test-formatter.cc | 98 -------------------------- 2 files changed, 276 deletions(-) delete mode 100644 tests/planner-mock.c delete mode 100644 tests/test-formatter.cc (limited to 'tests') diff --git a/tests/planner-mock.c b/tests/planner-mock.c deleted file mode 100644 index df5413e..0000000 --- a/tests/planner-mock.c +++ /dev/null @@ -1,178 +0,0 @@ -/* - * Copyright 2013 Canonical Ltd. - * - * Authors: - * Charles Kerr - * - * 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 . - */ - -#include "config.h" - -#include "planner-mock.h" - -struct _IndicatorDatetimePlannerMockPriv -{ - gboolean is_configured; -}; - -typedef IndicatorDatetimePlannerMockPriv priv_t; - -G_DEFINE_TYPE (IndicatorDatetimePlannerMock, - indicator_datetime_planner_mock, - INDICATOR_TYPE_DATETIME_PLANNER) - -/*** -**** IndicatorDatetimePlanner virtual funcs -***/ - -static void -my_get_appointments (IndicatorDatetimePlanner * planner, - GDateTime * begin_datetime, - GDateTime * /*end_datetime*/, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GTask * task; - GSList * appointments; - struct IndicatorDatetimeAppt * appt; - struct IndicatorDatetimeAppt * prev; - - task = g_task_new (planner, NULL, callback, user_data); - - /** - *** Build the appointments list - **/ - - appointments = NULL; - - /* add a daily appointment that occurs at the beginning of the next minute */ - appt = g_slice_new0 (struct IndicatorDatetimeAppt); - appt->is_daily = TRUE; - appt->begin = g_date_time_add_seconds (begin_datetime, 60-g_date_time_get_seconds(begin_datetime)); - appt->end = g_date_time_add_minutes (appt->begin, 1); - appt->color = g_strdup ("#00FF00"); - appt->is_event = TRUE; - appt->summary = g_strdup ("Daily alarm"); - appt->uid = g_strdup ("this uid isn't very random."); - appt->has_alarms = TRUE; - appt->url = g_strdup ("alarm:///some-alarm-info-goes-here"); - appointments = g_slist_prepend (appointments, appt); - prev = appt; - - /* and add one for a minute later that has an alarm uri */ - appt = g_slice_new0 (struct IndicatorDatetimeAppt); - appt->is_daily = TRUE; - appt->begin = g_date_time_add_minutes (prev->end, 1); - appt->end = g_date_time_add_minutes (appt->begin, 1); - appt->color = g_strdup ("#0000FF"); - appt->is_event = TRUE; - appt->summary = g_strdup ("Second Daily alarm"); - appt->uid = g_strdup ("this uid isn't very random either."); - appt->has_alarms = FALSE; - appointments = g_slist_prepend (appointments, appt); - - /* done */ - g_task_return_pointer (task, appointments, NULL); - g_object_unref (task); -} - -static GSList * -my_get_appointments_finish (IndicatorDatetimePlanner* /*self*/, - GAsyncResult* res, - GError** error) -{ - return g_task_propagate_pointer(G_TASK(res), error); -} - -static gboolean -my_is_configured(IndicatorDatetimePlanner* planner) -{ - IndicatorDatetimePlannerMock * self; - self = INDICATOR_DATETIME_PLANNER_MOCK(planner); - return self->priv->is_configured; -} - -static void -my_activate(IndicatorDatetimePlanner* /*self*/) -{ - g_message("%s %s", G_STRLOC, G_STRFUNC); -} - -static void -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); -} - -/*** -**** GObject virtual funcs -***/ - -static void -my_dispose(GObject * o) -{ - G_OBJECT_CLASS(indicator_datetime_planner_mock_parent_class)->dispose(o); -} - -/*** -**** Instantiation -***/ - -static void -indicator_datetime_planner_mock_class_init(IndicatorDatetimePlannerMockClass* klass) -{ - GObjectClass * object_class; - IndicatorDatetimePlannerClass * planner_class; - - object_class = G_OBJECT_CLASS (klass); - object_class->dispose = my_dispose; - - planner_class = INDICATOR_DATETIME_PLANNER_CLASS (klass); - planner_class->is_configured = my_is_configured; - planner_class->activate = my_activate; - planner_class->activate_time = my_activate_time; - planner_class->get_appointments = my_get_appointments; - planner_class->get_appointments_finish = my_get_appointments_finish; - - g_type_class_add_private (klass, sizeof (IndicatorDatetimePlannerMockPriv)); -} - -static void -indicator_datetime_planner_mock_init (IndicatorDatetimePlannerMock * self) -{ - priv_t * p; - - p = G_TYPE_INSTANCE_GET_PRIVATE (self, - INDICATOR_TYPE_DATETIME_PLANNER_MOCK, - IndicatorDatetimePlannerMockPriv); - - p->is_configured = TRUE; - - self->priv = p; -} - -/*** -**** Public -***/ - -IndicatorDatetimePlanner * -indicator_datetime_planner_mock_new (void) -{ - gpointer o = g_object_new (INDICATOR_TYPE_DATETIME_PLANNER_MOCK, NULL); - - return INDICATOR_DATETIME_PLANNER (o); -} diff --git a/tests/test-formatter.cc b/tests/test-formatter.cc deleted file mode 100644 index 6a408ab..0000000 --- a/tests/test-formatter.cc +++ /dev/null @@ -1,98 +0,0 @@ - -/* - * Copyright 2013 Canonical Ltd. - * - * Authors: - * Charles Kerr - * - * 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 . - */ - -#include -#include - -#include - -#include "utils.h" - -#include "glib-fixture.h" - -/*** -**** -***/ - -class FormatterFixture: public GlibFixture -{ - private: - - typedef GlibFixture super; - gchar * original_locale = nullptr; - - protected: - - virtual void SetUp () - { - super::SetUp (); - - original_locale = g_strdup (setlocale (LC_TIME, NULL)); - } - - virtual void TearDown () - { - setlocale (LC_TIME, original_locale); - g_clear_pointer (&original_locale, g_free); - - super::TearDown (); - } - - bool SetLocale (const char * expected_locale, const char * name) - { - setlocale (LC_TIME, expected_locale); - const char * actual_locale = setlocale (LC_TIME, NULL); - if (!g_strcmp0 (expected_locale, actual_locale)) - { - return true; - } - else - { - g_warning ("Unable to set locale to %s; skipping %s locale tests.", expected_locale, name); - return false; - } - } - - inline bool Set24hLocale () { return SetLocale ("C", "24h"); } - inline bool Set12hLocale () { return SetLocale ("en_US.utf8", "12h"); } -}; - - -/** - * Test the phone header format - */ -TEST_F (FormatterFixture, TestPhoneHeader) -{ - // test the default value in a 24h locale - if (Set24hLocale ()) - { - const gchar * format = get_terse_header_time_format_string (); - ASSERT_NE (nullptr, format); - ASSERT_STREQ ("%H:%M", format); - } - - // test the default value in a 12h locale - if (Set12hLocale ()) - { - const gchar * format = get_terse_header_time_format_string (); - ASSERT_NE (nullptr, format); - ASSERT_STREQ ("%l:%M %p", format); - } -} -- cgit v1.2.3 From a7a09a5ca5012fb1c48f259d2587542316e7349b Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Thu, 30 Jan 2014 18:33:14 -0600 Subject: copyediting: as per review, use name_of_thing() instead of get_name_of_thing() or getNameOfThing() --- tests/test-clock.cpp | 8 ++++---- tests/test-formatter.cpp | 10 +++++----- tests/test-live-actions.cpp | 4 ++-- tests/test-planner.cpp | 6 +++--- 4 files changed, 14 insertions(+), 14 deletions(-) (limited to 'tests') diff --git a/tests/test-clock.cpp b/tests/test-clock.cpp index 4271374..4287e1c 100644 --- a/tests/test-clock.cpp +++ b/tests/test-clock.cpp @@ -54,12 +54,12 @@ TEST_F(ClockFixture, MinuteChangedSignalShouldTriggerOncePerMinute) LiveClock clock(zones); wait_msec(500); // wait for the bus to set up - // count how many times clock.minuteChanged() is emitted over the next minute + // count how many times clock.minute_changed() is emitted over the next minute const DateTime now = clock.localtime(); const auto gnow = now.get(); auto gthen = g_date_time_add_minutes(gnow, 1); int count = 0; - clock.minuteChanged.connect([&count](){count++;}); + clock.minute_changed.connect([&count](){count++;}); const auto msec = g_date_time_difference(gthen,gnow) / 1000; wait_msec(msec); EXPECT_EQ(1, count); @@ -95,7 +95,7 @@ TEST_F(ClockFixture, TimezoneChangeTriggersSkew) g_time_zone_unref(tz_nyc); /// change the timezones! - clock.minuteChanged.connect([this](){ + clock.minute_changed.connect([this](){ g_main_loop_quit(loop); }); g_idle_add([](gpointer gs){ @@ -124,7 +124,7 @@ TEST_F(ClockFixture, SleepTriggersSkew) wait_msec(500); // wait for the bus to set up bool skewed = false; - clock.minuteChanged.connect([&skewed, this](){ + clock.minute_changed.connect([&skewed, this](){ skewed = true; g_main_loop_quit(loop); return G_SOURCE_REMOVE; diff --git a/tests/test-formatter.cpp b/tests/test-formatter.cpp index 9950453..01df4f2 100644 --- a/tests/test-formatter.cpp +++ b/tests/test-formatter.cpp @@ -97,7 +97,7 @@ TEST_F(FormatterFixture, TestPhoneHeader) if(Set24hLocale()) { PhoneFormatter formatter(clock); - EXPECT_EQ(std::string("%H:%M"), formatter.headerFormat.get()); + EXPECT_EQ(std::string("%H:%M"), formatter.header_format.get()); EXPECT_EQ(std::string("18:30"), formatter.header.get()); } @@ -105,7 +105,7 @@ TEST_F(FormatterFixture, TestPhoneHeader) if(Set12hLocale()) { PhoneFormatter formatter(clock); - EXPECT_EQ(std::string("%l:%M %p"), formatter.headerFormat.get()); + EXPECT_EQ(std::string("%l:%M %p"), formatter.header_format.get()); EXPECT_EQ(std::string(" 6:30 PM"), formatter.header.get()); } } @@ -156,7 +156,7 @@ TEST_F(FormatterFixture, TestDesktopHeader) m_settings->show_date.set(test_case.show_date); m_settings->show_year.set(test_case.show_year); - ASSERT_STREQ(test_case.expected_format_string, f.headerFormat.get().c_str()); + ASSERT_STREQ(test_case.expected_format_string, f.header_format.get().c_str()); } } } @@ -196,7 +196,7 @@ TEST_F(FormatterFixture, TestUpcomingTimes) std::shared_ptr clock (new MockClock(DateTime(test_case.now))); DesktopFormatter f(clock, m_settings); - const auto fmt = f.getRelativeFormat(test_case.then); + const auto fmt = f.relative_format(test_case.then); ASSERT_EQ(test_case.expected_format_string, fmt); g_clear_pointer(&test_case.now, g_date_time_unref); @@ -239,7 +239,7 @@ TEST_F(FormatterFixture, TestEventTimes) std::shared_ptr clock(new MockClock(DateTime(test_case.now))); DesktopFormatter f(clock, m_settings); - const auto fmt = f.getRelativeFormat(test_case.then, test_case.then_end); + const auto fmt = f.relative_format(test_case.then, test_case.then_end); ASSERT_STREQ(test_case.expected_format_string, fmt.c_str()); g_clear_pointer(&test_case.now, g_date_time_unref); diff --git a/tests/test-live-actions.cpp b/tests/test-live-actions.cpp index 562b358..eab8596 100644 --- a/tests/test-live-actions.cpp +++ b/tests/test-live-actions.cpp @@ -356,11 +356,11 @@ TEST_F(LiveActionsFixture, CalendarState) a2.begin = next_begin; a2.end = next_end; - m_state->planner->thisMonth.set(std::vector({a1, a2})); + m_state->planner->this_month.set(std::vector({a1, a2})); /// /// Now test the calendar state again. - /// The thisMonth field should now contain the appointments we just added. + /// The this_month field should now contain the appointments we just added. /// calendar_state = g_action_group_get_action_state (action_group, "calendar"); diff --git a/tests/test-planner.cpp b/tests/test-planner.cpp index 3072aea..b476ee8 100644 --- a/tests/test-planner.cpp +++ b/tests/test-planner.cpp @@ -47,9 +47,9 @@ TEST_F(PlannerFixture, EDS) planner.time.set(DateTime(now)); wait_msec(2500); - std::vector thisMonth = planner.thisMonth.get(); - std::cerr << thisMonth.size() << " appointments this month" << std::endl; - for(const auto& a : thisMonth) + std::vector this_month = planner.this_month.get(); + std::cerr << this_month.size() << " appointments this month" << std::endl; + for(const auto& a : this_month) std::cerr << a.summary << std::endl; } -- cgit v1.2.3 From 271b0fbf8b14a4f7a8f47de0e3a8751bd50676c3 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Thu, 30 Jan 2014 18:40:13 -0600 Subject: copyediting: remove dead '#if 0''ed code --- tests/test-settings.cpp | 6 ----- tests/test-timezone-geoclue.cpp | 59 ++++------------------------------------- 2 files changed, 5 insertions(+), 60 deletions(-) (limited to 'tests') diff --git a/tests/test-settings.cpp b/tests/test-settings.cpp index df01cd7..980e7fa 100644 --- a/tests/test-settings.cpp +++ b/tests/test-settings.cpp @@ -189,9 +189,3 @@ TEST_F(SettingsFixture, Locations) g_strfreev(tmp); EXPECT_EQ(bv, vtmp); } - -#if 0 - core::Property> locations; - core::Property time_format_mode; - -#endif diff --git a/tests/test-timezone-geoclue.cpp b/tests/test-timezone-geoclue.cpp index 4bf08a7..3cc1393 100644 --- a/tests/test-timezone-geoclue.cpp +++ b/tests/test-timezone-geoclue.cpp @@ -21,64 +21,17 @@ #include -//#include - using unity::indicator::datetime::GeoclueTimezone; -/*** -**** -***/ - -class TimezoneGeoclueFixture : public GeoclueFixture -{ -}; - -#if 0 -namespace +// This test looks small because the interesting +// work is all happening in GeoclueFixture... +TEST_F(GeoclueFixture, ChangeDetected) { - struct EmitAddressChangedData - { - DbusTestDbusMock * mock = nullptr; - DbusTestDbusMockObject * obj_client = nullptr; - std::string timezone; - EmitAddressChangedData(DbusTestDbusMock * mock_, - DbusTestDbusMockObject * obj_client_, - const std::string& timezone_): mock(mock_), obj_client(obj_client_), timezone(timezone_) {} - }; - - gboolean emit_address_changed_idle(gpointer gdata) - { - auto data = static_cast(gdata); - - GError * error = nullptr; - 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))"), - &error); - if (error) - { - g_warning("%s: %s", G_STRFUNC, error->message); - g_error_free(error); - } - - delete data; - return G_SOURCE_REMOVE; - } -} -#endif - -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()); - // start listening for a timezone change, then change the timezone + // Start listening for a timezone change, then change the timezone. bool changed = false; auto connection = tz.timezone.changed().connect( @@ -88,10 +41,8 @@ TEST_F(TimezoneGeoclueFixture, ChangeDetected) g_main_loop_quit(loop); }); + const std::string timezone_2 = "America/Chicago"; 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()); } - - -- cgit v1.2.3