diff options
-rw-r--r-- | debian/control | 3 | ||||
-rw-r--r-- | src/CMakeLists.txt | 2 | ||||
-rw-r--r-- | src/utils.c | 47 | ||||
-rw-r--r-- | tests/CMakeLists.txt | 22 | ||||
-rw-r--r-- | tests/glib-fixture.h | 120 | ||||
-rw-r--r-- | tests/test-formatter.cc | 98 |
6 files changed, 271 insertions, 21 deletions
diff --git a/debian/control b/debian/control index 357b099..d9d4f56 100644 --- a/debian/control +++ b/debian/control @@ -2,12 +2,14 @@ Source: indicator-datetime Section: misc Priority: optional Maintainer: Ubuntu Desktop Team <ubuntu-desktop@lists.ubuntu.com> +# language-pack-en-base is for the unit tests s.t. we can test in 12h and 24h locales Build-Depends: cmake, dbus, debhelper (>= 9), dh-translations, intltool (>= 0.35.0), gnome-common, + language-pack-en-base, libxorg-gtest-dev, libgtest-dev, libglib2.0-dev (>= 2.35.4), @@ -25,6 +27,7 @@ Build-Depends: cmake, libgnome-control-center-dev, libtimezonemap1-dev, liburl-dispatcher1-dev, + locales, Standards-Version: 3.9.3 Homepage: https://launchpad.net/indicator-datetime # If you aren't a member of ~indicator-applet-developers but need to upload diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 2d51385..15f29ea 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,4 +1,4 @@ -set (SERVICE_LIB "libindicatordatetimeservice") +set (SERVICE_LIB "indicatordatetimeservice") set (SERVICE_EXEC "indicator-datetime-service") add_definitions (-DTIMEZONE_FILE="/etc/timezone" diff --git a/src/utils.c b/src/utils.c index 5539c5c..c90f2e7 100644 --- a/src/utils.c +++ b/src/utils.c @@ -188,6 +188,31 @@ join_date_and_time_format_strings (const char * date_string, **** ***/ +static const gchar * +get_default_header_time_format (gboolean twelvehour, gboolean show_seconds) +{ + const gchar * fmt; + + if (twelvehour && show_seconds) + /* TRANSLATORS: a strftime(3) format for 12hr time w/seconds */ + fmt = T_("%l:%M:%S %p"); + else if (twelvehour) + /* TRANSLATORS: a strftime(3) format for 12hr time */ + fmt = T_("%l:%M %p"); + else if (show_seconds) + /* TRANSLATORS: a strftime(3) format for 24hr time w/seconds */ + fmt = T_("%H:%M:%S"); + else + /* TRANSLATORS: a strftime(3) format for 24hr time */ + fmt = T_("%H:%M"); + + return fmt; +} + +/*** +**** +***/ + typedef enum { DATE_PROXIMITY_TODAY, @@ -293,8 +318,10 @@ get_terse_date_format_string (date_proximity_t proximity) const gchar* get_terse_header_time_format_string (void) { - /* a strftime(3) fmt string for a H:MM 12 hour time, eg "6:59 PM" */ - return T_("%l:%M %p"); + const gboolean twelvehour = is_locale_12h (); + const gboolean show_seconds = FALSE; + + return get_default_header_time_format (twelvehour, show_seconds); } const gchar * @@ -374,7 +401,6 @@ get_full_time_format_string (GSettings * settings) { gboolean twelvehour; gboolean show_seconds; - const gchar * fmt; g_return_val_if_fail (settings != NULL, NULL); @@ -395,20 +421,7 @@ get_full_time_format_string (GSettings * settings) break; } - if (twelvehour && show_seconds) - /* TRANSLATORS: a strftime(3) format for 12hr time w/seconds */ - fmt = T_("%l:%M:%S %p"); - else if (twelvehour) - /* TRANSLATORS: a strftime(3) format for 12hr time */ - fmt = T_("%l:%M %p"); - else if (show_seconds) - /* TRANSLATORS: a strftime(3) format for 24hr time w/seconds */ - fmt = T_("%H:%M:%S"); - else - /* TRANSLATORS: a strftime(3) format for 24hr time */ - fmt = T_("%H:%M"); - - return fmt; + return get_default_header_time_format (twelvehour, show_seconds); } gchar * diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 682896b..6564a25 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,19 @@ 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 (${SERVICE_DEPS_INCLUDE_DIRS}) +# 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}) diff --git a/tests/glib-fixture.h b/tests/glib-fixture.h new file mode 100644 index 0000000..c6ecc68 --- /dev/null +++ b/tests/glib-fixture.h @@ -0,0 +1,120 @@ +/* + * Copyright 2013 Canonical Ltd. + * + * Authors: + * Charles Kerr <charles.kerr@canonical.com> + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 3, as published + * by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranties of + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <map> + +#include <glib.h> +#include <glib/gstdio.h> +#include <gio/gio.h> + +#include <gtest/gtest.h> + +class GlibFixture : public ::testing::Test +{ + private: + + GLogFunc realLogHandler; + + protected: + + std::map<GLogLevelFlags,int> logCounts; + + void testLogCount (GLogLevelFlags log_level, int expected G_GNUC_UNUSED) + { + ASSERT_EQ (expected, logCounts[log_level]); + + 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", log_domain, (int)log_level, message); + static_cast<GlibFixture*>(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() + { + // confirm there aren't any unexpected log messages + ASSERT_EQ (0, logCounts[G_LOG_LEVEL_ERROR]); + ASSERT_EQ (0, logCounts[G_LOG_LEVEL_CRITICAL]); + ASSERT_EQ (0, logCounts[G_LOG_LEVEL_WARNING]); + ASSERT_EQ (0, logCounts[G_LOG_LEVEL_MESSAGE]); + ASSERT_EQ (0, logCounts[G_LOG_LEVEL_INFO]); + + // 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; + } + + 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 + guint handler_id = g_signal_connect_swapped (o, signal, + G_CALLBACK(g_main_loop_quit), + loop); + gulong 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) + { + guint id = g_timeout_add (msec, (GSourceFunc)g_main_loop_quit, loop); + g_main_loop_run (loop); + g_source_remove (id); + } + + GMainLoop * loop; +}; diff --git a/tests/test-formatter.cc b/tests/test-formatter.cc new file mode 100644 index 0000000..6a408ab --- /dev/null +++ b/tests/test-formatter.cc @@ -0,0 +1,98 @@ + +/* + * Copyright 2013 Canonical Ltd. + * + * Authors: + * Charles Kerr <charles.kerr@canonical.com> + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 3, as published + * by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranties of + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <langinfo.h> +#include <locale.h> + +#include <glib/gi18n.h> + +#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); + } +} |