From 4897d1dc0f00f1571b0cc78ec4a20cd78c6c3ade Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Thu, 26 May 2016 13:35:20 -0400 Subject: localed: split out keymap parsing to a separate file This way the dbus and management logic is seperated from the business logic and we can write test cases for the mapping functionality. --- Makefile.am | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'Makefile.am') diff --git a/Makefile.am b/Makefile.am index c31c30c051..4ff39987ac 100644 --- a/Makefile.am +++ b/Makefile.am @@ -213,6 +213,7 @@ AM_CPPFLAGS = \ -I $(top_srcdir)/src/shared \ -I $(top_builddir)/src/shared \ -I $(top_srcdir)/src/network \ + -I $(top_srcdir)/src/locale \ -I $(top_srcdir)/src/login \ -I $(top_srcdir)/src/journal \ -I $(top_builddir)/src/journal \ @@ -4741,7 +4742,9 @@ BUSNAMES_TARGET_WANTS += \ # ------------------------------------------------------------------------------ if ENABLE_LOCALED systemd_localed_SOURCES = \ - src/locale/localed.c + src/locale/localed.c \ + src/locale/keymap-util.c \ + src/locale/keymap-util.h systemd_localed_LDADD = \ libshared.la \ -- cgit v1.2.3-54-g00ecf From aa63b56f5f56c9aa9b0ed00b4213c258c629c614 Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Sat, 28 May 2016 17:53:00 -0400 Subject: keymap-util: add tests and fix one small bug When converting an empty x11 variant, we would not delete vconsole mapping properly. find_legacy_keymap() is made non-static. I think it's important to be able to test it. In principle we could also test it through the higher-level interface of x11_convert_to_vconsole, but x11_convert_to_vconsole also uses find_converted_keymap, and it's better to test at this lower level. Note that find_legacy_keymap might be a bit of a misnomer, because we'd probably want to keep kbd-model-map even if the "legacy" layouts went away. So we might want to change this name, but I'm leaving that for another commit. --- .gitignore | 1 + Makefile.am | 12 +++ src/locale/keymap-util.c | 5 +- src/locale/keymap-util.h | 1 + src/locale/test-keymap-util.c | 216 ++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 233 insertions(+), 2 deletions(-) create mode 100644 src/locale/test-keymap-util.c (limited to 'Makefile.am') diff --git a/.gitignore b/.gitignore index 091b400182..f7db68b4a6 100644 --- a/.gitignore +++ b/.gitignore @@ -217,6 +217,7 @@ /test-journal-stream /test-journal-syslog /test-journal-verify +/test-keymap-util /test-libsystemd-sym* /test-libudev /test-libudev-sym* diff --git a/Makefile.am b/Makefile.am index 4ff39987ac..fc6f3bf6d5 100644 --- a/Makefile.am +++ b/Makefile.am @@ -4782,6 +4782,18 @@ dist_pkgdata_DATA = \ src/locale/kbd-model-map \ src/locale/language-fallback-map +test_keymap_util_SOURCES = \ + src/locale/test-keymap-util.c \ + src/locale/keymap-util.c \ + src/locale/keymap-util.h + +test_keymap_util_LDADD = \ + libshared.la \ + -ldl + +tests += \ + test-keymap-util + localectl_SOURCES = \ src/locale/localectl.c diff --git a/src/locale/keymap-util.c b/src/locale/keymap-util.c index 1827014b89..68b80a4801 100644 --- a/src/locale/keymap-util.c +++ b/src/locale/keymap-util.c @@ -522,7 +522,7 @@ int find_converted_keymap(const char *x11_layout, const char *x11_variant, char return 0; } -static int find_legacy_keymap(Context *c, char **new_keymap) { +int find_legacy_keymap(Context *c, char **new_keymap) { _cleanup_fclose_ FILE *f; unsigned n = 0; unsigned best_matching = 0; @@ -617,6 +617,7 @@ int find_language_fallback(const char *lang, char **language) { _cleanup_fclose_ FILE *f = NULL; unsigned n = 0; + assert(lang); assert(language); f = fopen(SYSTEMD_LANGUAGE_FALLBACK_MAP, "re"); @@ -651,7 +652,7 @@ int x11_convert_to_vconsole(Context *c) { !isempty(c->vc_keymap) || !isempty(c->vc_keymap_toggle); - context_free_x11(c); + context_free_vconsole(c); } else { char *new_keymap = NULL; int r; diff --git a/src/locale/keymap-util.h b/src/locale/keymap-util.h index 244dd62563..20ef2a4a34 100644 --- a/src/locale/keymap-util.h +++ b/src/locale/keymap-util.h @@ -33,6 +33,7 @@ typedef struct Context { } Context; int find_converted_keymap(const char *x11_layout, const char *x11_variant, char **new_keymap); +int find_legacy_keymap(Context *c, char **new_keymap); int find_language_fallback(const char *lang, char **language); int context_read_data(Context *c); diff --git a/src/locale/test-keymap-util.c b/src/locale/test-keymap-util.c new file mode 100644 index 0000000000..680aae6228 --- /dev/null +++ b/src/locale/test-keymap-util.c @@ -0,0 +1,216 @@ +/*** + This file is part of systemd. + + Copyright 2016 Zbigniew Jędrzejewski-Szmek + + systemd is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. + + systemd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with systemd; If not, see . +***/ + +#include "alloc-util.h" +#include "keymap-util.h" +#include "log.h" +#include "string-util.h" + +static void test_find_language_fallback(void) { + _cleanup_free_ char *ans = NULL, *ans2 = NULL; + int r; + + log_info("/* %s */", __func__); + + r = find_language_fallback("foobar", &ans); + if (r == -ENOENT) { + log_info_errno(r, "Skipping language fallback tests: %m"); + return; + } + assert_se(r == 0); + assert_se(ans == NULL); + + assert_se(find_language_fallback("csb", &ans) == 0); + assert_se(ans == NULL); + + assert_se(find_language_fallback("csb_PL", &ans) == 1); + assert_se(streq(ans, "csb:pl")); + + assert_se(find_language_fallback("szl_PL", &ans2) == 1); + assert_se(streq(ans2, "szl:pl")); +} + +static void test_find_converted_keymap(void) { + _cleanup_free_ char *ans = NULL, *ans2 = NULL; + int r; + + log_info("/* %s */", __func__); + + assert_se(find_converted_keymap("pl", "foobar", &ans) == 0); + assert_se(ans == NULL); + + r = find_converted_keymap("pl", NULL, &ans); + if (r == 0) { + log_info_errno(r, "Skipping find_converted_keymap tests: %m"); + return; + } + assert_se(r == 1); + assert_se(streq(ans, "pl")); + + assert_se(find_converted_keymap("pl", "dvorak", &ans) == 1); + assert_se(streq(ans, "pl-dvorak")); +} + +static void test_find_legacy_keymap(void) { + Context c = {}; + _cleanup_free_ char *ans = NULL, *ans2 = NULL; + int r; + + log_info("/* %s */", __func__); + + c.x11_layout = (char*) "foobar"; + r = find_legacy_keymap(&c, &ans); + if (r == -ENOENT) { + log_info_errno(r, "Skipping test_legacy_keymap tests: %m"); + return; + } + assert_se(r == 0); + assert_se(ans == NULL); + + c.x11_layout = (char*) "pl"; + assert_se(find_legacy_keymap(&c, &ans) == 0); /* should this be 1? */ + assert_se(streq(ans, "pl2")); + + c.x11_layout = (char*) "pl,ru"; + assert_se(find_legacy_keymap(&c, &ans2) == 0); /* should this be 1? */ + assert_se(streq(ans, "pl2")); +} + +static void test_vconsole_convert_to_x11(void) { + _cleanup_(context_free) Context c = {}; + + log_info("/* %s */", __func__); + + log_info("/* test emptying first (:) */"); + assert_se(free_and_strdup(&c.x11_layout, "foo") >= 0); + assert_se(free_and_strdup(&c.x11_variant, "bar") >= 0); + assert_se(vconsole_convert_to_x11(&c) == 1); + assert_se(c.x11_layout == NULL); + assert_se(c.x11_variant == NULL); + + log_info("/* test emptying second (:) */"); + + assert_se(vconsole_convert_to_x11(&c) == 0); + assert_se(c.x11_layout == NULL); + assert_se(c.x11_variant == NULL); + + log_info("/* test without variant, new mapping (es:) */"); + assert_se(free_and_strdup(&c.vc_keymap, "es") >= 0); + + assert_se(vconsole_convert_to_x11(&c) == 1); + assert_se(streq(c.x11_layout, "es")); + assert_se(c.x11_variant == NULL); + + log_info("/* test with known variant, new mapping (es:dvorak) */"); + assert_se(free_and_strdup(&c.vc_keymap, "es-dvorak") >= 0); + + assert_se(vconsole_convert_to_x11(&c) == 0); // FIXME + assert_se(streq(c.x11_layout, "es")); + assert_se(c.x11_variant == NULL); // FIXME: "dvorak" + + log_info("/* test with old mapping (fr:latin9) */"); + assert_se(free_and_strdup(&c.vc_keymap, "fr-latin9") >= 0); + + assert_se(vconsole_convert_to_x11(&c) == 1); + assert_se(streq(c.x11_layout, "fr")); + assert_se(streq(c.x11_variant, "latin9")); + + log_info("/* test with a compound mapping (ru,us) */"); + assert_se(free_and_strdup(&c.vc_keymap, "ru") >= 0); + + assert_se(vconsole_convert_to_x11(&c) == 1); + assert_se(streq(c.x11_layout, "ru,us")); + assert_se(c.x11_variant == NULL); + + log_info("/* test with a simple mapping (us) */"); + assert_se(free_and_strdup(&c.vc_keymap, "us") >= 0); + + assert_se(vconsole_convert_to_x11(&c) == 1); + assert_se(streq(c.x11_layout, "us")); + assert_se(c.x11_variant == NULL); +} + +static void test_x11_convert_to_vconsole(void) { + _cleanup_(context_free) Context c = {}; + + log_info("/* %s */", __func__); + + log_info("/* test emptying first (:) */"); + assert_se(free_and_strdup(&c.vc_keymap, "foobar") >= 0); + assert_se(x11_convert_to_vconsole(&c) == 1); + assert_se(c.vc_keymap == NULL); + + log_info("/* test emptying second (:) */"); + + assert_se(x11_convert_to_vconsole(&c) == 0); + assert_se(c.vc_keymap == NULL); + + log_info("/* test without variant, new mapping (es:) */"); + assert_se(free_and_strdup(&c.x11_layout, "es") >= 0); + + assert_se(x11_convert_to_vconsole(&c) == 1); + assert_se(streq(c.vc_keymap, "es")); + + log_info("/* test with unknown variant, new mapping (es:foobar) */"); + assert_se(free_and_strdup(&c.x11_variant, "foobar") >= 0); + + assert_se(x11_convert_to_vconsole(&c) == 0); + assert_se(streq(c.vc_keymap, "es")); + + log_info("/* test with known variant, new mapping (es:dvorak) */"); + assert_se(free_and_strdup(&c.x11_variant, "dvorak") >= 0); + + assert_se(x11_convert_to_vconsole(&c) == 1); + assert_se(streq(c.vc_keymap, "es-dvorak")); + + log_info("/* test with old mapping (fr:latin9) */"); + assert_se(free_and_strdup(&c.x11_layout, "fr") >= 0); + assert_se(free_and_strdup(&c.x11_variant, "latin9") >= 0); + + assert_se(x11_convert_to_vconsole(&c) == 1); + assert_se(streq(c.vc_keymap, "fr-latin9")); + + log_info("/* test with a compound mapping (us,ru:) */"); + assert_se(free_and_strdup(&c.x11_layout, "us,ru") >= 0); + assert_se(free_and_strdup(&c.x11_variant, NULL) >= 0); + + assert_se(x11_convert_to_vconsole(&c) == 1); + assert_se(streq(c.vc_keymap, "us")); + + log_info("/* test with a compound mapping (ru,us:) */"); + assert_se(free_and_strdup(&c.x11_layout, "ru,us") >= 0); + assert_se(free_and_strdup(&c.x11_variant, NULL) >= 0); + + assert_se(x11_convert_to_vconsole(&c) == 1); + assert_se(streq(c.vc_keymap, "ru")); +} + +int main(int argc, char **argv) { + log_set_max_level(LOG_DEBUG); + log_parse_environment(); + + test_find_language_fallback(); + test_find_converted_keymap(); + test_find_legacy_keymap(); + + test_vconsole_convert_to_x11(); + test_x11_convert_to_vconsole(); + + return 0; +} -- cgit v1.2.3-54-g00ecf From cabffaf86c17cdf74f92b8ef168fb9668f699c14 Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Sat, 4 Jun 2016 18:15:42 -0400 Subject: test-keymap-util: use kbd-model-map/language-fallback-map from $(srcdir) This adds (undocumented) environment variables SYSTEMD_KBD_MODEL_MAP and SYSTEMD_LANGUAGE_FALLBACK_MAP, which, if set, override compiled-in locations of those two files. Instead of skipping tests when the maps are not installed, just use the one from the source dir. We still cannot do the mappings the other way if /usr/lib/kbd/keymaps is not present, so truncate the tests in that case. Also tweak the debug messages a bit to make it easier to see which function is failing. --- Makefile.am | 4 ++++ src/locale/keymap-util.c | 43 ++++++++++++++++++++++++++++++++++++------- src/locale/test-keymap-util.c | 38 +++++++++++++++++--------------------- 3 files changed, 57 insertions(+), 28 deletions(-) (limited to 'Makefile.am') diff --git a/Makefile.am b/Makefile.am index fc6f3bf6d5..de3013567e 100644 --- a/Makefile.am +++ b/Makefile.am @@ -141,6 +141,10 @@ else noinst_PROGRAMS = TESTS = endif +AM_TESTS_ENVIRONMENT = \ + export SYSTEMD_KBD_MODEL_MAP=$(abs_top_srcdir)/src/locale/kbd-model-map; \ + export SYSTEMD_LANGUAGE_FALLBACK_MAP=$(abs_top_srcdir)/src/locale/language-fallback-map; + if ENABLE_BASH_COMPLETION dist_bashcompletion_DATA = $(dist_bashcompletion_data) nodist_bashcompletion_DATA = $(nodist_bashcompletion_data) diff --git a/src/locale/keymap-util.c b/src/locale/keymap-util.c index 17bef9e481..a6bcd1ad54 100644 --- a/src/locale/keymap-util.c +++ b/src/locale/keymap-util.c @@ -46,6 +46,26 @@ static const char* strnulldash(const char *s) { return isempty(s) || streq(s, "-") ? NULL : s; } +static const char* systemd_kbd_model_map(void) { + const char* s; + + s = getenv("SYSTEMD_KBD_MODEL_MAP"); + if (s) + return s; + + return SYSTEMD_KBD_MODEL_MAP; +} + +static const char* systemd_language_fallback_map(void) { + const char* s; + + s = getenv("SYSTEMD_LANGUAGE_FALLBACK_MAP"); + if (s) + return s; + + return SYSTEMD_LANGUAGE_FALLBACK_MAP; +} + static void context_free_x11(Context *c) { c->x11_layout = mfree(c->x11_layout); c->x11_options = mfree(c->x11_options); @@ -427,8 +447,11 @@ static int read_next_mapping(const char* filename, } int vconsole_convert_to_x11(Context *c) { + const char *map; int modified = -1; + map = systemd_kbd_model_map(); + if (isempty(c->vc_keymap)) { modified = !isempty(c->x11_layout) || @@ -441,7 +464,7 @@ int vconsole_convert_to_x11(Context *c) { _cleanup_fclose_ FILE *f = NULL; unsigned n = 0; - f = fopen(SYSTEMD_KBD_MODEL_MAP, "re"); + f = fopen(map, "re"); if (!f) return -errno; @@ -449,7 +472,7 @@ int vconsole_convert_to_x11(Context *c) { _cleanup_strv_free_ char **a = NULL; int r; - r = read_next_mapping(SYSTEMD_KBD_MODEL_MAP, 5, UINT_MAX, f, &n, &a); + r = read_next_mapping(map, 5, UINT_MAX, f, &n, &a); if (r < 0) return r; if (r == 0) @@ -526,14 +549,17 @@ int find_converted_keymap(const char *x11_layout, const char *x11_variant, char } int find_legacy_keymap(Context *c, char **new_keymap) { - _cleanup_fclose_ FILE *f; + const char *map; + _cleanup_fclose_ FILE *f = NULL; unsigned n = 0; unsigned best_matching = 0; int r; assert(!isempty(c->x11_layout)); - f = fopen(SYSTEMD_KBD_MODEL_MAP, "re"); + map = systemd_kbd_model_map(); + + f = fopen(map, "re"); if (!f) return -errno; @@ -541,7 +567,7 @@ int find_legacy_keymap(Context *c, char **new_keymap) { _cleanup_strv_free_ char **a = NULL; unsigned matching = 0; - r = read_next_mapping(SYSTEMD_KBD_MODEL_MAP, 5, UINT_MAX, f, &n, &a); + r = read_next_mapping(map, 5, UINT_MAX, f, &n, &a); if (r < 0) return r; if (r == 0) @@ -619,13 +645,16 @@ int find_legacy_keymap(Context *c, char **new_keymap) { } int find_language_fallback(const char *lang, char **language) { + const char *map; _cleanup_fclose_ FILE *f = NULL; unsigned n = 0; assert(lang); assert(language); - f = fopen(SYSTEMD_LANGUAGE_FALLBACK_MAP, "re"); + map = systemd_language_fallback_map(); + + f = fopen(map, "re"); if (!f) return -errno; @@ -633,7 +662,7 @@ int find_language_fallback(const char *lang, char **language) { _cleanup_strv_free_ char **a = NULL; int r; - r = read_next_mapping(SYSTEMD_LANGUAGE_FALLBACK_MAP, 2, 2, f, &n, &a); + r = read_next_mapping(map, 2, 2, f, &n, &a); if (r <= 0) return r; diff --git a/src/locale/test-keymap-util.c b/src/locale/test-keymap-util.c index 1e30fa4cb0..7e2c9e505a 100644 --- a/src/locale/test-keymap-util.c +++ b/src/locale/test-keymap-util.c @@ -24,16 +24,10 @@ static void test_find_language_fallback(void) { _cleanup_free_ char *ans = NULL, *ans2 = NULL; - int r; - log_info("/* %s */", __func__); + log_info("/*** %s ***/", __func__); - r = find_language_fallback("foobar", &ans); - if (r == -ENOENT) { - log_info_errno(r, "Skipping language fallback tests: %m"); - return; - } - assert_se(r == 0); + assert_se(find_language_fallback("foobar", &ans) == 0); assert_se(ans == NULL); assert_se(find_language_fallback("csb", &ans) == 0); @@ -50,16 +44,17 @@ static void test_find_converted_keymap(void) { _cleanup_free_ char *ans = NULL, *ans2 = NULL; int r; - log_info("/* %s */", __func__); + log_info("/*** %s ***/", __func__); assert_se(find_converted_keymap("pl", "foobar", &ans) == 0); assert_se(ans == NULL); r = find_converted_keymap("pl", NULL, &ans); if (r == 0) { - log_info_errno(r, "Skipping find_converted_keymap tests: %m"); + log_info("Skipping rest of %s: keymaps are not installed", __func__); return; } + assert_se(r == 1); assert_se(streq(ans, "pl")); @@ -70,17 +65,11 @@ static void test_find_converted_keymap(void) { static void test_find_legacy_keymap(void) { Context c = {}; _cleanup_free_ char *ans = NULL, *ans2 = NULL; - int r; - log_info("/* %s */", __func__); + log_info("/*** %s ***/", __func__); c.x11_layout = (char*) "foobar"; - r = find_legacy_keymap(&c, &ans); - if (r == -ENOENT) { - log_info_errno(r, "Skipping test_legacy_keymap tests: %m"); - return; - } - assert_se(r == 0); + assert_se(find_legacy_keymap(&c, &ans) == 0); assert_se(ans == NULL); c.x11_layout = (char*) "pl"; @@ -95,7 +84,7 @@ static void test_find_legacy_keymap(void) { static void test_vconsole_convert_to_x11(void) { _cleanup_(context_free) Context c = {}; - log_info("/* %s */", __func__); + log_info("/*** %s ***/", __func__); log_info("/* test emptying first (:) */"); assert_se(free_and_strdup(&c.x11_layout, "foo") >= 0); @@ -148,8 +137,9 @@ static void test_vconsole_convert_to_x11(void) { static void test_x11_convert_to_vconsole(void) { _cleanup_(context_free) Context c = {}; + int r; - log_info("/* %s */", __func__); + log_info("/*** %s ***/", __func__); log_info("/* test emptying first (:) */"); assert_se(free_and_strdup(&c.vc_keymap, "foobar") >= 0); @@ -176,7 +166,13 @@ static void test_x11_convert_to_vconsole(void) { log_info("/* test with known variant, new mapping (es:dvorak) */"); assert_se(free_and_strdup(&c.x11_variant, "dvorak") >= 0); - assert_se(x11_convert_to_vconsole(&c) == 1); + r = x11_convert_to_vconsole(&c); + if (r == 0) { + log_info("Skipping rest of %s: keymaps are not installed", __func__); + return; + } + + assert_se(r == 1); assert_se(streq(c.vc_keymap, "es-dvorak")); log_info("/* test with old mapping (fr:latin9) */"); -- cgit v1.2.3-54-g00ecf