2 * Copyright © 2020 Red Hat, Inc.
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 * DEALINGS IN THE SOFTWARE.
33 #include <sys/types.h>
35 #include "xkbcommon/xkbregistry.h"
40 #define NO_VARIANT NULL
50 const char *name; /* required */
52 const char *description;
56 const char *name; /* required */
59 const char *description;
60 const char *iso639[3]; /* language list (iso639 three letter codes), 3 is enough for our test */
61 const char *iso3166[3]; /* country list (iso3166 two letter codes), 3 is enough for our tests */
66 const char *description;
69 struct test_option_group {
71 const char *description;
72 bool allow_multiple_selection;
74 struct test_option options[10];
78 fprint_config_item(FILE *fp,
82 const char *description,
83 const char * const iso639[3],
84 const char * const iso3166[3])
86 fprintf(fp, " <configItem>\n"
87 " <name>%s</name>\n", name);
89 fprintf(fp, " <shortDescription>%s</shortDescription>\n", brief);
91 fprintf(fp, " <description>%s</description>\n", description);
93 fprintf(fp, " <vendor>%s</vendor>\n", vendor);
94 if (iso3166 && iso3166[0]) {
95 fprintf(fp, " <countryList>\n");
96 for (int i = 0; i < 3; i++) {
97 const char *iso = iso3166[i];
100 fprintf(fp, " <iso3166Id>%s</iso3166Id>\n", iso);
102 fprintf(fp, " </countryList>\n");
104 if (iso639 && iso639[0]) {
105 fprintf(fp, " <languageList>\n");
106 for (int i = 0; i < 3; i++) {
107 const char *iso = iso639[i];
110 fprintf(fp, " <iso639Id>%s</iso639Id>\n", iso);
112 fprintf(fp, " </languageList>\n");
115 fprintf(fp, " </configItem>\n");
119 * Create a directory populated with a rules/<ruleset>.xml that contains the
122 * @return the XKB base directory
125 test_create_rules(const char *ruleset,
126 const struct test_model *test_models,
127 const struct test_layout *test_layouts,
128 const struct test_option_group *test_groups)
130 static int iteration;
136 char *template = asprintf_safe("%s.%d.XXXXXX", ruleset, iteration++);
137 assert(template != NULL);
138 tmpdir = test_maketempdir(template);
141 free(test_makedir(tmpdir, "rules"));
143 rc = snprintf_safe(buf, sizeof(buf), "%s/rules/%s.xml", tmpdir, ruleset);
146 fp = fopen(buf, "w");
150 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
151 "<!DOCTYPE xkbConfigRegistry SYSTEM \"xkb.dtd\">\n"
152 "<xkbConfigRegistry version=\"1.1\">\n");
155 fprintf(fp, "<modelList>\n");
157 for (const struct test_model *m = test_models; m->name; m++) {
158 fprintf(fp, "<model>\n");
159 fprint_config_item(fp, m->name, m->vendor, NULL, m->description, NULL, NULL);
160 fprintf(fp, "</model>\n");
162 fprintf(fp, "</modelList>\n");
166 const struct test_layout *l, *next;
168 fprintf(fp, "<layoutList>\n");
173 assert(l->variant == NULL);
176 fprintf(fp, "<layout>\n");
177 fprint_config_item(fp, l->name, NULL, l->brief, l->description, l->iso639, l->iso3166);
179 if (next->name && streq(next->name, l->name)) {
180 fprintf(fp, "<variantList>\n");
182 fprintf(fp, "<variant>\n");
183 fprint_config_item(fp, next->variant, NULL, next->brief, next->description, next->iso639, next->iso3166);
184 fprintf(fp, "</variant>\n");
187 } while (next->name && streq(next->name, l->name));
188 fprintf(fp, "</variantList>\n");
190 fprintf(fp, "</layout>\n");
193 fprintf(fp, "</layoutList>\n");
197 fprintf(fp, "<optionList>\n");
199 for (const struct test_option_group *g = test_groups; g->name; g++) {
200 fprintf(fp, "<group allowMultipleSelection=\"%s\">\n",
201 g->allow_multiple_selection ? "true" : "false");
202 fprint_config_item(fp, g->name, NULL, NULL, g->description, NULL, NULL);
203 for (const struct test_option *o = g->options; o->name; o++) {
204 fprintf(fp, " <option>\n");
205 fprint_config_item(fp, o->name, NULL, NULL, o->description, NULL, NULL);
206 fprintf(fp, "</option>\n");
208 fprintf(fp, "</group>\n");
210 fprintf(fp, "</optionList>\n");
213 fprintf(fp, "</xkbConfigRegistry>\n");
220 test_remove_rules(char *basedir, const char *ruleset)
225 rc = snprintf_safe(path, sizeof(path), "%s/rules/%s.xml", basedir,
229 rc = snprintf_safe(path, sizeof(path), "%s/xkb/rules", basedir);
236 static struct rxkb_context *
237 test_setup_context_for(const char *ruleset,
238 struct test_model *system_models,
239 struct test_model *user_models,
240 struct test_layout *system_layouts,
241 struct test_layout *user_layouts,
242 struct test_option_group *system_groups,
243 struct test_option_group *user_groups)
245 char *sysdir = NULL, *userdir = NULL;
246 struct rxkb_context *ctx;
248 sysdir = test_create_rules(ruleset, system_models, system_layouts,
250 if (user_models || user_layouts || user_groups)
251 userdir = test_create_rules(ruleset, user_models, user_layouts,
254 ctx = rxkb_context_new(RXKB_CONTEXT_NO_DEFAULT_INCLUDES);
257 assert(rxkb_context_include_path_append(ctx, userdir));
258 assert(rxkb_context_include_path_append(ctx, sysdir));
259 assert(rxkb_context_parse(ctx, ruleset));
261 test_remove_rules(sysdir, ruleset);
263 test_remove_rules(userdir, ruleset);
268 static struct rxkb_context *
269 test_setup_context(struct test_model *system_models,
270 struct test_model *user_models,
271 struct test_layout *system_layouts,
272 struct test_layout *user_layouts,
273 struct test_option_group *system_groups,
274 struct test_option_group *user_groups)
276 const char *ruleset = "xkbtests";
277 return test_setup_context_for(ruleset, system_models,
278 user_models, system_layouts,
279 user_layouts, system_groups,
283 static struct rxkb_model *
284 fetch_model(struct rxkb_context *ctx, const char *model)
286 struct rxkb_model *m = rxkb_model_first(ctx);
288 if (streq(rxkb_model_get_name(m), model))
289 return rxkb_model_ref(m);
290 m = rxkb_model_next(m);
296 find_model(struct rxkb_context *ctx, const char *model)
298 struct rxkb_model *m = fetch_model(ctx, model);
304 find_models(struct rxkb_context *ctx, ...)
312 name = va_arg(args, const char *);
314 assert(++idx < 20); /* safety guard */
315 if (!find_model(ctx, name))
317 name = va_arg(args, const char *);
326 static struct rxkb_layout *
327 fetch_layout(struct rxkb_context *ctx, const char *layout, const char *variant)
329 struct rxkb_layout *l = rxkb_layout_first(ctx);
331 const char *v = rxkb_layout_get_variant(l);
333 if (streq(rxkb_layout_get_name(l), layout) &&
334 ((v == NULL && variant == NULL) ||
335 (v != NULL && variant != NULL && streq(v, variant))))
336 return rxkb_layout_ref(l);
337 l = rxkb_layout_next(l);
343 find_layout(struct rxkb_context *ctx, const char *layout, const char *variant)
345 struct rxkb_layout *l = fetch_layout(ctx, layout, variant);
346 rxkb_layout_unref(l);
351 find_layouts(struct rxkb_context *ctx, ...)
354 const char *name, *variant;
359 name = va_arg(args, const char *);
360 variant = va_arg(args, const char *);
362 assert(++idx < 20); /* safety guard */
363 if (!find_layout(ctx, name, variant))
365 name = va_arg(args, const char *);
367 variant = va_arg(args, const char *);
376 static struct rxkb_option_group *
377 fetch_option_group(struct rxkb_context *ctx, const char *grp)
379 struct rxkb_option_group *g = rxkb_option_group_first(ctx);
381 if (streq(grp, rxkb_option_group_get_name(g)))
382 return rxkb_option_group_ref(g);
383 g = rxkb_option_group_next(g);
389 find_option_group(struct rxkb_context *ctx, const char *grp)
391 struct rxkb_option_group *g = fetch_option_group(ctx, grp);
392 rxkb_option_group_unref(g);
396 static struct rxkb_option *
397 fetch_option(struct rxkb_context *ctx, const char *grp, const char *opt)
399 struct rxkb_option_group *g = rxkb_option_group_first(ctx);
401 if (streq(grp, rxkb_option_group_get_name(g))) {
402 struct rxkb_option *o = rxkb_option_first(g);
405 if (streq(opt, rxkb_option_get_name(o)))
406 return rxkb_option_ref(o);
407 o = rxkb_option_next(o);
410 g = rxkb_option_group_next(g);
416 find_option(struct rxkb_context *ctx, const char *grp, const char *opt)
418 struct rxkb_option *o = fetch_option(ctx, grp, opt);
419 rxkb_option_unref(o);
424 find_options(struct rxkb_context *ctx, ...)
427 const char *grp, *opt;
432 grp = va_arg(args, const char *);
433 opt = va_arg(args, const char *);
435 assert(++idx < 20); /* safety guard */
436 if (!find_option(ctx, grp, opt))
438 grp = va_arg(args, const char *);
440 opt = va_arg(args, const char *);
450 cmp_models(struct test_model *tm, struct rxkb_model *m)
455 if (!streq(tm->name, rxkb_model_get_name(m)))
458 if (!streq_null(tm->vendor, rxkb_model_get_vendor(m)))
461 if (!streq_null(tm->description, rxkb_model_get_description(m)))
468 cmp_layouts(struct test_layout *tl, struct rxkb_layout *l)
470 struct rxkb_iso3166_code *iso3166 = NULL;
471 struct rxkb_iso639_code *iso639 = NULL;
476 if (!streq(tl->name, rxkb_layout_get_name(l)))
479 if (!streq_null(tl->variant, rxkb_layout_get_variant(l)))
482 if (!streq_null(tl->brief, rxkb_layout_get_brief(l)))
485 if (!streq_null(tl->description, rxkb_layout_get_description(l)))
488 iso3166 = rxkb_layout_get_iso3166_first(l);
489 for (size_t i = 0; i < sizeof(tl->iso3166); i++) {
490 const char *iso = tl->iso3166[i];
491 if (iso == NULL && iso3166 == NULL)
494 if (!streq_null(iso, rxkb_iso3166_code_get_code(iso3166)))
497 iso3166 = rxkb_iso3166_code_next(iso3166);
503 iso639 = rxkb_layout_get_iso639_first(l);
504 for (size_t i = 0; i < sizeof(tl->iso639); i++) {
505 const char *iso = tl->iso639[i];
506 if (iso == NULL && iso639 == NULL)
509 if (!streq_null(iso, rxkb_iso639_code_get_code(iso639)))
512 iso639 = rxkb_iso639_code_next(iso639);
522 cmp_options(struct test_option *to, struct rxkb_option *o)
527 if (!streq(to->name, rxkb_option_get_name(o)))
530 if (!streq_null(to->description, rxkb_option_get_description(o)))
542 cmp_option_groups(struct test_option_group *tg, struct rxkb_option_group *g,
545 struct rxkb_option *o;
546 struct test_option *to;
551 if (!streq(tg->name, rxkb_option_group_get_name(g)))
554 if (!streq_null(tg->description, rxkb_option_group_get_description(g)))
557 if (tg->allow_multiple_selection != rxkb_option_group_allows_multiple(g))
561 o = rxkb_option_first(g);
563 while (o && to->name) {
564 if (!cmp_options(to, o))
567 o = rxkb_option_next(o);
570 if (cmp == CMP_EXACT && (o || to->name))
577 test_load_basic(void)
579 struct test_model system_models[] = {
584 struct test_layout system_layouts[] = {
589 struct test_option_group system_groups[] = {
591 { {"grp1:1"}, {"grp1:2"} } },
592 {"grp2", NULL, false,
593 { {"grp2:1"}, {"grp2:2"} } },
596 struct rxkb_context *ctx;
598 ctx = test_setup_context(system_models, NULL,
599 system_layouts, NULL,
600 system_groups, NULL);
602 assert(find_models(ctx, "m1", "m2", NULL));
603 assert(find_layouts(ctx, "l1", NO_VARIANT,
605 assert(find_options(ctx, "grp1", "grp1:1",
608 "grp2", "grp2:2", NULL));
609 rxkb_context_unref(ctx);
615 struct test_model system_models[] = {
616 {"m1", "vendor1", "desc1"},
617 {"m2", "vendor2", "desc2"},
620 struct test_layout system_layouts[] = {
621 {"l1", NO_VARIANT, "lbrief1", "ldesc1"},
622 {"l1", "v1", "vbrief1", "vdesc1"},
623 {"l1", "v2", NULL, "vdesc2"},
626 struct test_option_group system_groups[] = {
627 {"grp1", "gdesc1", true,
628 { {"grp1:1", "odesc11"}, {"grp1:2", "odesc12"} } },
629 {"grp2", "gdesc2", false,
630 { {"grp2:1", "odesc21"}, {"grp2:2", "odesc22"} } },
633 struct rxkb_context *ctx;
634 struct rxkb_model *m;
635 struct rxkb_layout *l;
636 struct rxkb_option_group *g;
638 ctx = test_setup_context(system_models, NULL,
639 system_layouts, NULL,
640 system_groups, NULL);
642 m = fetch_model(ctx, "m1");
643 assert(cmp_models(&system_models[0], m));
646 m = fetch_model(ctx, "m2");
647 assert(cmp_models(&system_models[1], m));
650 l = fetch_layout(ctx, "l1", NO_VARIANT);
651 assert(cmp_layouts(&system_layouts[0], l));
652 rxkb_layout_unref(l);
654 l = fetch_layout(ctx, "l1", "v1");
655 assert(cmp_layouts(&system_layouts[1], l));
656 rxkb_layout_unref(l);
658 l = fetch_layout(ctx, "l1", "v2");
659 struct test_layout expected = {"l1", "v2", "lbrief1", "vdesc2"};
660 assert(cmp_layouts(&expected, l));
661 rxkb_layout_unref(l);
663 g = fetch_option_group(ctx, "grp1");
664 assert(cmp_option_groups(&system_groups[0], g, CMP_EXACT));
665 rxkb_option_group_unref(g);
667 g = fetch_option_group(ctx, "grp2");
668 assert(cmp_option_groups(&system_groups[1], g, CMP_EXACT));
669 rxkb_option_group_unref(g);
671 rxkb_context_unref(ctx);
675 test_load_languages(void)
677 struct test_model system_models[] = {
678 {"m1", "vendor1", "desc1"},
681 struct test_layout system_layouts[] = {
682 {"l1", NO_VARIANT, "lbrief1", "ldesc1",
683 .iso639 = { "abc", "def" },
684 .iso3166 = { "uv", "wx" }},
685 {"l1", "v1", "vbrief1", "vdesc1",
688 {"l2", NO_VARIANT, "lbrief1", "ldesc1",
689 .iso639 = { "hij", "klm" },
690 .iso3166 = { "op", "qr" }},
691 {"l2", "v2", "lbrief1", "ldesc1",
692 .iso639 = { NULL }, /* inherit from parent */
693 .iso3166 = { NULL }}, /* inherit from parent */
696 struct test_option_group system_groups[] = {
697 {"grp1", "gdesc1", true,
698 { {"grp1:1", "odesc11"}, {"grp1:2", "odesc12"} } },
701 struct rxkb_context *ctx;
702 struct rxkb_layout *l;
703 struct rxkb_iso3166_code *iso3166;
704 struct rxkb_iso639_code *iso639;
706 ctx = test_setup_context(system_models, NULL,
707 system_layouts, NULL,
708 system_groups, NULL);
710 l = fetch_layout(ctx, "l1", NO_VARIANT);
711 assert(cmp_layouts(&system_layouts[0], l));
712 rxkb_layout_unref(l);
714 l = fetch_layout(ctx, "l1", "v1");
715 assert(cmp_layouts(&system_layouts[1], l));
716 rxkb_layout_unref(l);
718 l = fetch_layout(ctx, "l2", "v2");
719 iso3166 = rxkb_layout_get_iso3166_first(l);
720 assert(streq(rxkb_iso3166_code_get_code(iso3166), "op"));
721 iso3166 = rxkb_iso3166_code_next(iso3166);
722 assert(streq(rxkb_iso3166_code_get_code(iso3166), "qr"));
724 iso639 = rxkb_layout_get_iso639_first(l);
725 assert(streq(rxkb_iso639_code_get_code(iso639), "hij"));
726 iso639 = rxkb_iso639_code_next(iso639);
727 assert(streq(rxkb_iso639_code_get_code(iso639), "klm"));
729 rxkb_layout_unref(l);
730 rxkb_context_unref(ctx);
734 test_load_invalid_languages(void)
736 struct test_model system_models[] = {
737 {"m1", "vendor1", "desc1"},
740 struct test_layout system_layouts[] = {
741 {"l1", NO_VARIANT, "lbrief1", "ldesc1",
742 .iso639 = { "ab", "def" },
743 .iso3166 = { "uvw", "xz" }},
746 struct test_option_group system_groups[] = {
747 {"grp1", "gdesc1", true,
748 { {"grp1:1", "odesc11"}, {"grp1:2", "odesc12"} } },
751 struct rxkb_context *ctx;
752 struct rxkb_layout *l;
753 struct rxkb_iso3166_code *iso3166;
754 struct rxkb_iso639_code *iso639;
756 ctx = test_setup_context(system_models, NULL,
757 system_layouts, NULL,
758 system_groups, NULL);
760 l = fetch_layout(ctx, "l1", NO_VARIANT);
761 /* uvw is invalid, we expect 2 letters, verify it was ignored */
762 iso3166 = rxkb_layout_get_iso3166_first(l);
763 assert(streq(rxkb_iso3166_code_get_code(iso3166), "xz"));
764 assert(rxkb_iso3166_code_next(iso3166) == NULL);
766 /* ab is invalid, we expect 3 letters, verify it was ignored */
767 iso639 = rxkb_layout_get_iso639_first(l);
768 assert(streq(rxkb_iso639_code_get_code(iso639), "def"));
769 assert(rxkb_iso639_code_next(iso639) == NULL);
770 rxkb_layout_unref(l);
772 rxkb_context_unref(ctx);
776 test_popularity(void)
778 struct test_layout system_layouts[] = {
783 struct rxkb_context *ctx;
784 struct rxkb_layout *l;
785 const char *ruleset = "xkbtests.extras";
788 dir = test_create_rules(ruleset, NULL, system_layouts, NULL);
789 ctx = rxkb_context_new(RXKB_CONTEXT_NO_DEFAULT_INCLUDES |
790 RXKB_CONTEXT_LOAD_EXOTIC_RULES);
792 assert(rxkb_context_include_path_append(ctx, dir));
793 /* Hack: rulest above generates xkbtests.extras.xml, loading "xkbtests"
794 * means the extras file counts as exotic */
795 assert(rxkb_context_parse(ctx, "xkbtests"));
797 l = fetch_layout(ctx, "l1", NO_VARIANT);
798 assert(rxkb_layout_get_popularity(l) == RXKB_POPULARITY_EXOTIC);
799 rxkb_layout_unref(l);
801 l = fetch_layout(ctx, "l1", "v1");
802 assert(rxkb_layout_get_popularity(l) == RXKB_POPULARITY_EXOTIC);
803 rxkb_layout_unref(l);
805 test_remove_rules(dir, ruleset);
806 rxkb_context_unref(ctx);
811 test_load_merge(void)
813 struct test_model system_models[] = {
814 {"m1", "vendor1", "desc1"},
815 {"m2", "vendor2", "desc2"},
818 struct test_model user_models[] = {
819 {"m3", "vendor3", "desc3"},
820 {"m4", "vendor4", "desc4"},
823 struct test_layout system_layouts[] = {
824 {"l1", NO_VARIANT, "lbrief1", "ldesc1"},
825 {"l1", "v1", "vbrief1", "vdesc1"},
828 struct test_layout user_layouts[] = {
829 {"l2", NO_VARIANT, "lbrief2", "ldesc2"},
830 {"l2", "v2", "vbrief2", "vdesc2"},
833 struct test_option_group system_groups[] = {
835 { {"grp1:1"}, {"grp1:2"} } },
836 {"grp2", NULL, false,
837 { {"grp2:1"}, {"grp2:2"} } },
840 struct test_option_group user_groups[] = {
842 { {"grp3:1"}, {"grp3:2"} } },
843 {"grp4", NULL, false,
844 { {"grp4:1"}, {"grp4:2"} } },
847 struct rxkb_context *ctx;
848 struct rxkb_model *m;
849 struct rxkb_layout *l;
850 struct rxkb_option_group *g;
852 ctx = test_setup_context(system_models, user_models,
853 system_layouts, user_layouts,
854 system_groups, user_groups);
856 assert(find_models(ctx, "m1", "m2", "m3", "m4", NULL));
857 assert(find_layouts(ctx, "l1", NO_VARIANT,
862 m = fetch_model(ctx, "m1");
863 assert(cmp_models(&system_models[0], m));
866 m = fetch_model(ctx, "m2");
867 assert(cmp_models(&system_models[1], m));
870 m = fetch_model(ctx, "m3");
871 assert(cmp_models(&user_models[0], m));
874 m = fetch_model(ctx, "m4");
875 assert(cmp_models(&user_models[1], m));
878 l = fetch_layout(ctx, "l1", NO_VARIANT);
879 assert(cmp_layouts(&system_layouts[0], l));
880 rxkb_layout_unref(l);
882 l = fetch_layout(ctx, "l1", "v1");
883 assert(cmp_layouts(&system_layouts[1], l));
884 rxkb_layout_unref(l);
886 l = fetch_layout(ctx, "l2", NO_VARIANT);
887 assert(cmp_layouts(&user_layouts[0], l));
888 rxkb_layout_unref(l);
890 l = fetch_layout(ctx, "l2", "v2");
891 assert(cmp_layouts(&user_layouts[1], l));
892 rxkb_layout_unref(l);
894 g = fetch_option_group(ctx, "grp1");
895 assert(cmp_option_groups(&system_groups[0], g, CMP_EXACT));
896 rxkb_option_group_unref(g);
898 g = fetch_option_group(ctx, "grp2");
899 assert(cmp_option_groups(&system_groups[1], g, CMP_EXACT));
900 rxkb_option_group_unref(g);
902 g = fetch_option_group(ctx, "grp3");
903 assert(cmp_option_groups(&user_groups[0], g, CMP_EXACT));
904 rxkb_option_group_unref(g);
906 g = fetch_option_group(ctx, "grp4");
907 assert(cmp_option_groups(&user_groups[1], g, CMP_EXACT));
908 rxkb_option_group_unref(g);
910 rxkb_context_unref(ctx);
914 test_load_merge_no_overwrite(void)
916 struct test_model system_models[] = {
917 {"m1", "vendor1", "desc1"},
918 {"m2", "vendor2", "desc2"},
921 struct test_model user_models[] = {
922 {"m1", "vendor3", "desc3"}, /* must not overwrite */
923 {"m4", "vendor4", "desc4"},
926 struct test_layout system_layouts[] = {
927 {"l1", NO_VARIANT, "lbrief1", "ldesc1"},
928 {"l1", "v1", "vbrief1", "vdesc1"},
931 struct test_layout user_layouts[] = {
932 {"l2", NO_VARIANT, "lbrief2", "ldesc2"},
933 {"l2", "v2", "vbrief2", "vdesc2"},
934 {"l1", NO_VARIANT, "lbrief3", "ldesc3"}, /* must not overwrite */
935 {"l1", "v2", "vbrief3", "vdesc3"}, /* must not overwrite */
938 struct test_option_group system_groups[] = {
939 {"grp1", "gdesc1", true,
940 { {"grp1:1", "odesc11"}, {"grp1:2", "odesc12"} } },
941 {"grp2", "gdesc2", false,
942 { {"grp2:1", "odesc21"}, {"grp2:2", "odesc22"} } },
945 struct test_option_group user_groups[] = {
946 {"grp1", "XXXXX", false, /* must not overwrite */
947 { {"grp1:1", "YYYYYYY"}, /* must not overwrite */
948 {"grp1:3", "ZZZZZZ"} } }, /* append */
949 {"grp4", "gdesc4", false,
950 { {"grp4:1", "odesc41"}, {"grp4:2", "odesc42"} } },
953 struct rxkb_context *ctx;
954 struct rxkb_model *m;
955 struct rxkb_layout *l;
956 struct rxkb_option_group *g;
958 ctx = test_setup_context(system_models, user_models,
959 system_layouts, user_layouts,
960 system_groups, user_groups);
962 m = fetch_model(ctx, "m1");
963 assert(cmp_models(&system_models[0], m));
966 l = fetch_layout(ctx, "l1", NO_VARIANT);
967 assert(cmp_layouts(&system_layouts[0], l));
968 rxkb_layout_unref(l);
970 l = fetch_layout(ctx, "l1", "v1");
971 assert(cmp_layouts(&system_layouts[1], l));
972 rxkb_layout_unref(l);
974 assert(find_option(ctx, "grp1", "grp1:3"));
975 g = fetch_option_group(ctx, "grp1");
976 assert(cmp_option_groups(&system_groups[0], g, CMP_MATCHING_ONLY));
977 rxkb_option_group_unref(g);
979 rxkb_context_unref(ctx);
983 test_no_include_paths(void)
985 struct rxkb_context *ctx;
987 ctx = rxkb_context_new(RXKB_CONTEXT_NO_DEFAULT_INCLUDES);
989 assert(!rxkb_context_parse_default_ruleset(ctx));
991 rxkb_context_unref(ctx);
995 test_invalid_include(void)
997 struct rxkb_context *ctx;
999 ctx = rxkb_context_new(RXKB_CONTEXT_NO_DEFAULT_INCLUDES);
1001 assert(!rxkb_context_include_path_append(ctx, "/foo/bar/baz/bat"));
1002 assert(!rxkb_context_parse_default_ruleset(ctx));
1004 rxkb_context_unref(ctx);
1010 test_no_include_paths();
1011 test_invalid_include();
1015 test_load_merge_no_overwrite();
1016 test_load_languages();
1017 test_load_invalid_languages();