/* * 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); }