xref: /aosp_15_r20/external/libxkbcommon/test/registry.c (revision 2b949d0487e80d67f1fda82db69e101e761f8064)
1*2b949d04SAndroid Build Coastguard Worker /*
2*2b949d04SAndroid Build Coastguard Worker  * Copyright © 2020 Red Hat, Inc.
3*2b949d04SAndroid Build Coastguard Worker  *
4*2b949d04SAndroid Build Coastguard Worker  * Permission is hereby granted, free of charge, to any person obtaining a
5*2b949d04SAndroid Build Coastguard Worker  * copy of this software and associated documentation files (the "Software"),
6*2b949d04SAndroid Build Coastguard Worker  * to deal in the Software without restriction, including without limitation
7*2b949d04SAndroid Build Coastguard Worker  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8*2b949d04SAndroid Build Coastguard Worker  * and/or sell copies of the Software, and to permit persons to whom the
9*2b949d04SAndroid Build Coastguard Worker  * Software is furnished to do so, subject to the following conditions:
10*2b949d04SAndroid Build Coastguard Worker  *
11*2b949d04SAndroid Build Coastguard Worker  * The above copyright notice and this permission notice (including the next
12*2b949d04SAndroid Build Coastguard Worker  * paragraph) shall be included in all copies or substantial portions of the
13*2b949d04SAndroid Build Coastguard Worker  * Software.
14*2b949d04SAndroid Build Coastguard Worker  *
15*2b949d04SAndroid Build Coastguard Worker  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16*2b949d04SAndroid Build Coastguard Worker  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17*2b949d04SAndroid Build Coastguard Worker  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18*2b949d04SAndroid Build Coastguard Worker  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19*2b949d04SAndroid Build Coastguard Worker  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20*2b949d04SAndroid Build Coastguard Worker  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21*2b949d04SAndroid Build Coastguard Worker  * DEALINGS IN THE SOFTWARE.
22*2b949d04SAndroid Build Coastguard Worker  */
23*2b949d04SAndroid Build Coastguard Worker 
24*2b949d04SAndroid Build Coastguard Worker #include "config.h"
25*2b949d04SAndroid Build Coastguard Worker 
26*2b949d04SAndroid Build Coastguard Worker #include <assert.h>
27*2b949d04SAndroid Build Coastguard Worker #if HAVE_UNISTD_H
28*2b949d04SAndroid Build Coastguard Worker #include <unistd.h>
29*2b949d04SAndroid Build Coastguard Worker #endif
30*2b949d04SAndroid Build Coastguard Worker #include <stdarg.h>
31*2b949d04SAndroid Build Coastguard Worker #include <stdio.h>
32*2b949d04SAndroid Build Coastguard Worker #include <sys/stat.h>
33*2b949d04SAndroid Build Coastguard Worker #include <sys/types.h>
34*2b949d04SAndroid Build Coastguard Worker 
35*2b949d04SAndroid Build Coastguard Worker #include "xkbcommon/xkbregistry.h"
36*2b949d04SAndroid Build Coastguard Worker 
37*2b949d04SAndroid Build Coastguard Worker #include "utils.h"
38*2b949d04SAndroid Build Coastguard Worker 
39*2b949d04SAndroid Build Coastguard Worker #define NO_VARIANT NULL
40*2b949d04SAndroid Build Coastguard Worker 
41*2b949d04SAndroid Build Coastguard Worker enum {
42*2b949d04SAndroid Build Coastguard Worker     MODEL = 78,
43*2b949d04SAndroid Build Coastguard Worker     LAYOUT,
44*2b949d04SAndroid Build Coastguard Worker     VARIANT,
45*2b949d04SAndroid Build Coastguard Worker     OPTION,
46*2b949d04SAndroid Build Coastguard Worker };
47*2b949d04SAndroid Build Coastguard Worker 
48*2b949d04SAndroid Build Coastguard Worker struct test_model {
49*2b949d04SAndroid Build Coastguard Worker     const char *name; /* required */
50*2b949d04SAndroid Build Coastguard Worker     const char *vendor;
51*2b949d04SAndroid Build Coastguard Worker     const char *description;
52*2b949d04SAndroid Build Coastguard Worker };
53*2b949d04SAndroid Build Coastguard Worker 
54*2b949d04SAndroid Build Coastguard Worker struct test_layout {
55*2b949d04SAndroid Build Coastguard Worker     const char *name; /* required */
56*2b949d04SAndroid Build Coastguard Worker     const char *variant;
57*2b949d04SAndroid Build Coastguard Worker     const char *brief;
58*2b949d04SAndroid Build Coastguard Worker     const char *description;
59*2b949d04SAndroid Build Coastguard Worker     const char *iso639[3];  /* language list (iso639 three letter codes), 3 is enough for our test  */
60*2b949d04SAndroid Build Coastguard Worker     const char *iso3166[3]; /* country list (iso3166 two letter codes), 3 is enough for our tests */
61*2b949d04SAndroid Build Coastguard Worker };
62*2b949d04SAndroid Build Coastguard Worker 
63*2b949d04SAndroid Build Coastguard Worker struct test_option {
64*2b949d04SAndroid Build Coastguard Worker     const char *name;
65*2b949d04SAndroid Build Coastguard Worker     const char *description;
66*2b949d04SAndroid Build Coastguard Worker };
67*2b949d04SAndroid Build Coastguard Worker 
68*2b949d04SAndroid Build Coastguard Worker struct test_option_group {
69*2b949d04SAndroid Build Coastguard Worker     const char *name;
70*2b949d04SAndroid Build Coastguard Worker     const char *description;
71*2b949d04SAndroid Build Coastguard Worker     bool allow_multiple_selection;
72*2b949d04SAndroid Build Coastguard Worker 
73*2b949d04SAndroid Build Coastguard Worker     struct test_option options[10];
74*2b949d04SAndroid Build Coastguard Worker };
75*2b949d04SAndroid Build Coastguard Worker 
76*2b949d04SAndroid Build Coastguard Worker static void
fprint_config_item(FILE * fp,const char * name,const char * vendor,const char * brief,const char * description,const char * const iso639[3],const char * const iso3166[3])77*2b949d04SAndroid Build Coastguard Worker fprint_config_item(FILE *fp,
78*2b949d04SAndroid Build Coastguard Worker                    const char *name,
79*2b949d04SAndroid Build Coastguard Worker                    const char *vendor,
80*2b949d04SAndroid Build Coastguard Worker                    const char *brief,
81*2b949d04SAndroid Build Coastguard Worker                    const char *description,
82*2b949d04SAndroid Build Coastguard Worker                    const char * const iso639[3],
83*2b949d04SAndroid Build Coastguard Worker                    const char * const iso3166[3])
84*2b949d04SAndroid Build Coastguard Worker {
85*2b949d04SAndroid Build Coastguard Worker     fprintf(fp, "  <configItem>\n"
86*2b949d04SAndroid Build Coastguard Worker                 "    <name>%s</name>\n", name);
87*2b949d04SAndroid Build Coastguard Worker     if (brief)
88*2b949d04SAndroid Build Coastguard Worker         fprintf(fp, "    <shortDescription>%s</shortDescription>\n", brief);
89*2b949d04SAndroid Build Coastguard Worker     if (description)
90*2b949d04SAndroid Build Coastguard Worker         fprintf(fp, "    <description>%s</description>\n", description);
91*2b949d04SAndroid Build Coastguard Worker     if (vendor)
92*2b949d04SAndroid Build Coastguard Worker         fprintf(fp, "    <vendor>%s</vendor>\n", vendor);
93*2b949d04SAndroid Build Coastguard Worker     if (iso3166 && iso3166[0]) {
94*2b949d04SAndroid Build Coastguard Worker         fprintf(fp, "    <countryList>\n");
95*2b949d04SAndroid Build Coastguard Worker         for (int i = 0; i < 3; i++) {
96*2b949d04SAndroid Build Coastguard Worker             const char *iso = iso3166[i];
97*2b949d04SAndroid Build Coastguard Worker             if (!iso)
98*2b949d04SAndroid Build Coastguard Worker                 break;
99*2b949d04SAndroid Build Coastguard Worker             fprintf(fp, "        <iso3166Id>%s</iso3166Id>\n", iso);
100*2b949d04SAndroid Build Coastguard Worker         }
101*2b949d04SAndroid Build Coastguard Worker         fprintf(fp, "    </countryList>\n");
102*2b949d04SAndroid Build Coastguard Worker     }
103*2b949d04SAndroid Build Coastguard Worker     if (iso639 && iso639[0]) {
104*2b949d04SAndroid Build Coastguard Worker         fprintf(fp, "    <languageList>\n");
105*2b949d04SAndroid Build Coastguard Worker         for (int i = 0; i < 3; i++) {
106*2b949d04SAndroid Build Coastguard Worker             const char *iso = iso639[i];
107*2b949d04SAndroid Build Coastguard Worker             if (!iso)
108*2b949d04SAndroid Build Coastguard Worker                 break;
109*2b949d04SAndroid Build Coastguard Worker             fprintf(fp, "        <iso639Id>%s</iso639Id>\n", iso);
110*2b949d04SAndroid Build Coastguard Worker         }
111*2b949d04SAndroid Build Coastguard Worker         fprintf(fp, "    </languageList>\n");
112*2b949d04SAndroid Build Coastguard Worker     }
113*2b949d04SAndroid Build Coastguard Worker 
114*2b949d04SAndroid Build Coastguard Worker     fprintf(fp, "  </configItem>\n");
115*2b949d04SAndroid Build Coastguard Worker }
116*2b949d04SAndroid Build Coastguard Worker 
117*2b949d04SAndroid Build Coastguard Worker /**
118*2b949d04SAndroid Build Coastguard Worker  * Create a directory populated with a rules/<ruleset>.xml that contains the
119*2b949d04SAndroid Build Coastguard Worker  * given items.
120*2b949d04SAndroid Build Coastguard Worker  *
121*2b949d04SAndroid Build Coastguard Worker  * @return the XKB base directory
122*2b949d04SAndroid Build Coastguard Worker  */
123*2b949d04SAndroid Build Coastguard Worker static char *
test_create_rules(const char * ruleset,const struct test_model * test_models,const struct test_layout * test_layouts,const struct test_option_group * test_groups)124*2b949d04SAndroid Build Coastguard Worker test_create_rules(const char *ruleset,
125*2b949d04SAndroid Build Coastguard Worker                   const struct test_model *test_models,
126*2b949d04SAndroid Build Coastguard Worker                   const struct test_layout *test_layouts,
127*2b949d04SAndroid Build Coastguard Worker                   const struct test_option_group *test_groups)
128*2b949d04SAndroid Build Coastguard Worker {
129*2b949d04SAndroid Build Coastguard Worker     static int iteration;
130*2b949d04SAndroid Build Coastguard Worker     char *tmpdir;
131*2b949d04SAndroid Build Coastguard Worker     char buf[PATH_MAX];
132*2b949d04SAndroid Build Coastguard Worker     int rc;
133*2b949d04SAndroid Build Coastguard Worker     FILE *fp;
134*2b949d04SAndroid Build Coastguard Worker 
135*2b949d04SAndroid Build Coastguard Worker     tmpdir = asprintf_safe("/tmp/%s.%d.XXXXXX", ruleset, iteration++);
136*2b949d04SAndroid Build Coastguard Worker     assert(tmpdir);
137*2b949d04SAndroid Build Coastguard Worker     assert(mkdtemp(tmpdir) == tmpdir);
138*2b949d04SAndroid Build Coastguard Worker 
139*2b949d04SAndroid Build Coastguard Worker     rc = snprintf_safe(buf, sizeof(buf), "%s/rules", tmpdir);
140*2b949d04SAndroid Build Coastguard Worker     assert(rc);
141*2b949d04SAndroid Build Coastguard Worker     rc = mkdir(buf, 0777);
142*2b949d04SAndroid Build Coastguard Worker     assert(rc == 0);
143*2b949d04SAndroid Build Coastguard Worker     rc = snprintf_safe(buf, sizeof(buf), "%s/rules/%s.xml", tmpdir, ruleset);
144*2b949d04SAndroid Build Coastguard Worker     assert(rc);
145*2b949d04SAndroid Build Coastguard Worker 
146*2b949d04SAndroid Build Coastguard Worker     fp = fopen(buf, "w");
147*2b949d04SAndroid Build Coastguard Worker     assert(fp);
148*2b949d04SAndroid Build Coastguard Worker 
149*2b949d04SAndroid Build Coastguard Worker     fprintf(fp,
150*2b949d04SAndroid Build Coastguard Worker             "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
151*2b949d04SAndroid Build Coastguard Worker             "<!DOCTYPE xkbConfigRegistry SYSTEM \"xkb.dtd\">\n"
152*2b949d04SAndroid Build Coastguard Worker             "<xkbConfigRegistry version=\"1.1\">\n");
153*2b949d04SAndroid Build Coastguard Worker 
154*2b949d04SAndroid Build Coastguard Worker     if (test_models) {
155*2b949d04SAndroid Build Coastguard Worker         fprintf(fp, "<modelList>\n");
156*2b949d04SAndroid Build Coastguard Worker 
157*2b949d04SAndroid Build Coastguard Worker         for (const struct test_model *m = test_models; m->name; m++) {
158*2b949d04SAndroid Build Coastguard Worker             fprintf(fp, "<model>\n");
159*2b949d04SAndroid Build Coastguard Worker             fprint_config_item(fp, m->name, m->vendor, NULL, m->description, NULL, NULL);
160*2b949d04SAndroid Build Coastguard Worker             fprintf(fp, "</model>\n");
161*2b949d04SAndroid Build Coastguard Worker         }
162*2b949d04SAndroid Build Coastguard Worker         fprintf(fp, "</modelList>\n");
163*2b949d04SAndroid Build Coastguard Worker     }
164*2b949d04SAndroid Build Coastguard Worker 
165*2b949d04SAndroid Build Coastguard Worker     if (test_layouts) {
166*2b949d04SAndroid Build Coastguard Worker         const struct test_layout *l, *next;
167*2b949d04SAndroid Build Coastguard Worker 
168*2b949d04SAndroid Build Coastguard Worker         fprintf(fp, "<layoutList>\n");
169*2b949d04SAndroid Build Coastguard Worker 
170*2b949d04SAndroid Build Coastguard Worker         l = test_layouts;
171*2b949d04SAndroid Build Coastguard Worker         next = l + 1;
172*2b949d04SAndroid Build Coastguard Worker 
173*2b949d04SAndroid Build Coastguard Worker         assert(l->variant == NULL);
174*2b949d04SAndroid Build Coastguard Worker 
175*2b949d04SAndroid Build Coastguard Worker         while (l->name) {
176*2b949d04SAndroid Build Coastguard Worker             fprintf(fp, "<layout>\n");
177*2b949d04SAndroid Build Coastguard Worker             fprint_config_item(fp, l->name, NULL, l->brief, l->description, l->iso639, l->iso3166);
178*2b949d04SAndroid Build Coastguard Worker 
179*2b949d04SAndroid Build Coastguard Worker             if (next->name && streq(next->name, l->name)) {
180*2b949d04SAndroid Build Coastguard Worker                 fprintf(fp, "<variantList>\n");
181*2b949d04SAndroid Build Coastguard Worker                 do {
182*2b949d04SAndroid Build Coastguard Worker                     fprintf(fp, "<variant>\n");
183*2b949d04SAndroid Build Coastguard Worker                     fprint_config_item(fp, next->variant, NULL, next->brief, next->description, next->iso639, next->iso3166);
184*2b949d04SAndroid Build Coastguard Worker                     fprintf(fp, "</variant>\n");
185*2b949d04SAndroid Build Coastguard Worker                     l = next;
186*2b949d04SAndroid Build Coastguard Worker                     next++;
187*2b949d04SAndroid Build Coastguard Worker                 } while (next->name && streq(next->name, l->name));
188*2b949d04SAndroid Build Coastguard Worker                 fprintf(fp, "</variantList>\n");
189*2b949d04SAndroid Build Coastguard Worker             }
190*2b949d04SAndroid Build Coastguard Worker             fprintf(fp, "</layout>\n");
191*2b949d04SAndroid Build Coastguard Worker             l++;
192*2b949d04SAndroid Build Coastguard Worker         }
193*2b949d04SAndroid Build Coastguard Worker         fprintf(fp, "</layoutList>\n");
194*2b949d04SAndroid Build Coastguard Worker     }
195*2b949d04SAndroid Build Coastguard Worker 
196*2b949d04SAndroid Build Coastguard Worker     if (test_groups) {
197*2b949d04SAndroid Build Coastguard Worker         fprintf(fp, "<optionList>\n");
198*2b949d04SAndroid Build Coastguard Worker 
199*2b949d04SAndroid Build Coastguard Worker         for (const struct test_option_group *g = test_groups; g->name; g++) {
200*2b949d04SAndroid Build Coastguard Worker             fprintf(fp, "<group allowMultipleSelection=\"%s\">\n",
201*2b949d04SAndroid Build Coastguard Worker                     g->allow_multiple_selection ? "true" : "false");
202*2b949d04SAndroid Build Coastguard Worker             fprint_config_item(fp, g->name, NULL, NULL, g->description, NULL, NULL);
203*2b949d04SAndroid Build Coastguard Worker             for (const struct test_option *o = g->options; o->name; o++) {
204*2b949d04SAndroid Build Coastguard Worker                 fprintf(fp, "  <option>\n");
205*2b949d04SAndroid Build Coastguard Worker                 fprint_config_item(fp, o->name, NULL, NULL, o->description, NULL, NULL);
206*2b949d04SAndroid Build Coastguard Worker                 fprintf(fp, "</option>\n");
207*2b949d04SAndroid Build Coastguard Worker             }
208*2b949d04SAndroid Build Coastguard Worker             fprintf(fp, "</group>\n");
209*2b949d04SAndroid Build Coastguard Worker         }
210*2b949d04SAndroid Build Coastguard Worker         fprintf(fp, "</optionList>\n");
211*2b949d04SAndroid Build Coastguard Worker     }
212*2b949d04SAndroid Build Coastguard Worker 
213*2b949d04SAndroid Build Coastguard Worker     fprintf(fp, "</xkbConfigRegistry>\n");
214*2b949d04SAndroid Build Coastguard Worker     fclose(fp);
215*2b949d04SAndroid Build Coastguard Worker 
216*2b949d04SAndroid Build Coastguard Worker     return tmpdir;
217*2b949d04SAndroid Build Coastguard Worker }
218*2b949d04SAndroid Build Coastguard Worker 
219*2b949d04SAndroid Build Coastguard Worker static void
test_remove_rules(char * basedir,const char * ruleset)220*2b949d04SAndroid Build Coastguard Worker test_remove_rules(char *basedir, const char *ruleset)
221*2b949d04SAndroid Build Coastguard Worker {
222*2b949d04SAndroid Build Coastguard Worker     char path[PATH_MAX];
223*2b949d04SAndroid Build Coastguard Worker     int rc;
224*2b949d04SAndroid Build Coastguard Worker 
225*2b949d04SAndroid Build Coastguard Worker     rc = snprintf_safe(path, sizeof(path), "%s/rules/%s.xml", basedir,
226*2b949d04SAndroid Build Coastguard Worker                        ruleset);
227*2b949d04SAndroid Build Coastguard Worker     assert(rc);
228*2b949d04SAndroid Build Coastguard Worker     unlink(path);
229*2b949d04SAndroid Build Coastguard Worker     rc = snprintf_safe(path, sizeof(path), "%s/xkb/rules", basedir);
230*2b949d04SAndroid Build Coastguard Worker     assert(rc);
231*2b949d04SAndroid Build Coastguard Worker     rmdir(path);
232*2b949d04SAndroid Build Coastguard Worker     rmdir(basedir);
233*2b949d04SAndroid Build Coastguard Worker     free(basedir);
234*2b949d04SAndroid Build Coastguard Worker }
235*2b949d04SAndroid Build Coastguard Worker 
236*2b949d04SAndroid Build Coastguard Worker static struct rxkb_context *
test_setup_context_for(const char * ruleset,struct test_model * system_models,struct test_model * user_models,struct test_layout * system_layouts,struct test_layout * user_layouts,struct test_option_group * system_groups,struct test_option_group * user_groups)237*2b949d04SAndroid Build Coastguard Worker test_setup_context_for(const char *ruleset,
238*2b949d04SAndroid Build Coastguard Worker                        struct test_model *system_models,
239*2b949d04SAndroid Build Coastguard Worker                        struct test_model *user_models,
240*2b949d04SAndroid Build Coastguard Worker                        struct test_layout *system_layouts,
241*2b949d04SAndroid Build Coastguard Worker                        struct test_layout *user_layouts,
242*2b949d04SAndroid Build Coastguard Worker                        struct test_option_group *system_groups,
243*2b949d04SAndroid Build Coastguard Worker                        struct test_option_group *user_groups)
244*2b949d04SAndroid Build Coastguard Worker {
245*2b949d04SAndroid Build Coastguard Worker     char *sysdir = NULL, *userdir = NULL;
246*2b949d04SAndroid Build Coastguard Worker     struct rxkb_context *ctx;
247*2b949d04SAndroid Build Coastguard Worker 
248*2b949d04SAndroid Build Coastguard Worker     sysdir = test_create_rules(ruleset, system_models, system_layouts,
249*2b949d04SAndroid Build Coastguard Worker                                system_groups);
250*2b949d04SAndroid Build Coastguard Worker     if (user_models || user_layouts || user_groups)
251*2b949d04SAndroid Build Coastguard Worker         userdir = test_create_rules(ruleset, user_models, user_layouts,
252*2b949d04SAndroid Build Coastguard Worker                                     user_groups);
253*2b949d04SAndroid Build Coastguard Worker 
254*2b949d04SAndroid Build Coastguard Worker     ctx = rxkb_context_new(RXKB_CONTEXT_NO_DEFAULT_INCLUDES);
255*2b949d04SAndroid Build Coastguard Worker     assert(ctx);
256*2b949d04SAndroid Build Coastguard Worker     if (userdir)
257*2b949d04SAndroid Build Coastguard Worker         assert(rxkb_context_include_path_append(ctx, userdir));
258*2b949d04SAndroid Build Coastguard Worker     assert(rxkb_context_include_path_append(ctx, sysdir));
259*2b949d04SAndroid Build Coastguard Worker     assert(rxkb_context_parse(ctx, ruleset));
260*2b949d04SAndroid Build Coastguard Worker 
261*2b949d04SAndroid Build Coastguard Worker     test_remove_rules(sysdir, ruleset);
262*2b949d04SAndroid Build Coastguard Worker     if (userdir)
263*2b949d04SAndroid Build Coastguard Worker         test_remove_rules(userdir, ruleset);
264*2b949d04SAndroid Build Coastguard Worker 
265*2b949d04SAndroid Build Coastguard Worker     return ctx;
266*2b949d04SAndroid Build Coastguard Worker }
267*2b949d04SAndroid Build Coastguard Worker 
268*2b949d04SAndroid Build Coastguard Worker static struct rxkb_context *
test_setup_context(struct test_model * system_models,struct test_model * user_models,struct test_layout * system_layouts,struct test_layout * user_layouts,struct test_option_group * system_groups,struct test_option_group * user_groups)269*2b949d04SAndroid Build Coastguard Worker test_setup_context(struct test_model *system_models,
270*2b949d04SAndroid Build Coastguard Worker                    struct test_model *user_models,
271*2b949d04SAndroid Build Coastguard Worker                    struct test_layout *system_layouts,
272*2b949d04SAndroid Build Coastguard Worker                    struct test_layout *user_layouts,
273*2b949d04SAndroid Build Coastguard Worker                    struct test_option_group *system_groups,
274*2b949d04SAndroid Build Coastguard Worker                    struct test_option_group *user_groups)
275*2b949d04SAndroid Build Coastguard Worker {
276*2b949d04SAndroid Build Coastguard Worker     const char *ruleset = "xkbtests";
277*2b949d04SAndroid Build Coastguard Worker     return test_setup_context_for(ruleset, system_models,
278*2b949d04SAndroid Build Coastguard Worker                                   user_models, system_layouts,
279*2b949d04SAndroid Build Coastguard Worker                                   user_layouts, system_groups,
280*2b949d04SAndroid Build Coastguard Worker                                   user_groups);
281*2b949d04SAndroid Build Coastguard Worker }
282*2b949d04SAndroid Build Coastguard Worker 
283*2b949d04SAndroid Build Coastguard Worker static struct rxkb_model *
fetch_model(struct rxkb_context * ctx,const char * model)284*2b949d04SAndroid Build Coastguard Worker fetch_model(struct rxkb_context *ctx, const char *model)
285*2b949d04SAndroid Build Coastguard Worker {
286*2b949d04SAndroid Build Coastguard Worker     struct rxkb_model *m = rxkb_model_first(ctx);
287*2b949d04SAndroid Build Coastguard Worker     while (m) {
288*2b949d04SAndroid Build Coastguard Worker         if (streq(rxkb_model_get_name(m), model))
289*2b949d04SAndroid Build Coastguard Worker             return rxkb_model_ref(m);
290*2b949d04SAndroid Build Coastguard Worker         m = rxkb_model_next(m);
291*2b949d04SAndroid Build Coastguard Worker     }
292*2b949d04SAndroid Build Coastguard Worker     return NULL;
293*2b949d04SAndroid Build Coastguard Worker }
294*2b949d04SAndroid Build Coastguard Worker 
295*2b949d04SAndroid Build Coastguard Worker static bool
find_model(struct rxkb_context * ctx,const char * model)296*2b949d04SAndroid Build Coastguard Worker find_model(struct rxkb_context *ctx, const char *model)
297*2b949d04SAndroid Build Coastguard Worker {
298*2b949d04SAndroid Build Coastguard Worker     struct rxkb_model *m = fetch_model(ctx, model);
299*2b949d04SAndroid Build Coastguard Worker     rxkb_model_unref(m);
300*2b949d04SAndroid Build Coastguard Worker     return m != NULL;
301*2b949d04SAndroid Build Coastguard Worker }
302*2b949d04SAndroid Build Coastguard Worker 
303*2b949d04SAndroid Build Coastguard Worker static bool
find_models(struct rxkb_context * ctx,...)304*2b949d04SAndroid Build Coastguard Worker find_models(struct rxkb_context *ctx, ...)
305*2b949d04SAndroid Build Coastguard Worker {
306*2b949d04SAndroid Build Coastguard Worker     va_list args;
307*2b949d04SAndroid Build Coastguard Worker     const char *name;
308*2b949d04SAndroid Build Coastguard Worker     int idx = 0;
309*2b949d04SAndroid Build Coastguard Worker     bool rc = false;
310*2b949d04SAndroid Build Coastguard Worker 
311*2b949d04SAndroid Build Coastguard Worker     va_start(args, ctx);
312*2b949d04SAndroid Build Coastguard Worker     name = va_arg(args, const char *);
313*2b949d04SAndroid Build Coastguard Worker     while(name) {
314*2b949d04SAndroid Build Coastguard Worker         assert(++idx < 20); /* safety guard */
315*2b949d04SAndroid Build Coastguard Worker         if (!find_model(ctx, name))
316*2b949d04SAndroid Build Coastguard Worker             goto out;
317*2b949d04SAndroid Build Coastguard Worker         name = va_arg(args, const char *);
318*2b949d04SAndroid Build Coastguard Worker     };
319*2b949d04SAndroid Build Coastguard Worker 
320*2b949d04SAndroid Build Coastguard Worker     rc = true;
321*2b949d04SAndroid Build Coastguard Worker out:
322*2b949d04SAndroid Build Coastguard Worker     va_end(args);
323*2b949d04SAndroid Build Coastguard Worker     return rc;
324*2b949d04SAndroid Build Coastguard Worker }
325*2b949d04SAndroid Build Coastguard Worker 
326*2b949d04SAndroid Build Coastguard Worker static struct rxkb_layout *
fetch_layout(struct rxkb_context * ctx,const char * layout,const char * variant)327*2b949d04SAndroid Build Coastguard Worker fetch_layout(struct rxkb_context *ctx, const char *layout, const char *variant)
328*2b949d04SAndroid Build Coastguard Worker {
329*2b949d04SAndroid Build Coastguard Worker     struct rxkb_layout *l = rxkb_layout_first(ctx);
330*2b949d04SAndroid Build Coastguard Worker     while (l) {
331*2b949d04SAndroid Build Coastguard Worker         const char *v = rxkb_layout_get_variant(l);
332*2b949d04SAndroid Build Coastguard Worker 
333*2b949d04SAndroid Build Coastguard Worker         if (streq(rxkb_layout_get_name(l), layout) &&
334*2b949d04SAndroid Build Coastguard Worker             ((v == NULL && variant == NULL) ||
335*2b949d04SAndroid Build Coastguard Worker              (v != NULL && variant != NULL && streq(v, variant))))
336*2b949d04SAndroid Build Coastguard Worker             return rxkb_layout_ref(l);
337*2b949d04SAndroid Build Coastguard Worker         l = rxkb_layout_next(l);
338*2b949d04SAndroid Build Coastguard Worker     }
339*2b949d04SAndroid Build Coastguard Worker     return NULL;
340*2b949d04SAndroid Build Coastguard Worker }
341*2b949d04SAndroid Build Coastguard Worker 
342*2b949d04SAndroid Build Coastguard Worker static bool
find_layout(struct rxkb_context * ctx,const char * layout,const char * variant)343*2b949d04SAndroid Build Coastguard Worker find_layout(struct rxkb_context *ctx, const char *layout, const char *variant)
344*2b949d04SAndroid Build Coastguard Worker {
345*2b949d04SAndroid Build Coastguard Worker     struct rxkb_layout *l = fetch_layout(ctx, layout, variant);
346*2b949d04SAndroid Build Coastguard Worker     rxkb_layout_unref(l);
347*2b949d04SAndroid Build Coastguard Worker     return l != NULL;
348*2b949d04SAndroid Build Coastguard Worker }
349*2b949d04SAndroid Build Coastguard Worker 
350*2b949d04SAndroid Build Coastguard Worker static bool
find_layouts(struct rxkb_context * ctx,...)351*2b949d04SAndroid Build Coastguard Worker find_layouts(struct rxkb_context *ctx, ...)
352*2b949d04SAndroid Build Coastguard Worker {
353*2b949d04SAndroid Build Coastguard Worker     va_list args;
354*2b949d04SAndroid Build Coastguard Worker     const char *name, *variant;
355*2b949d04SAndroid Build Coastguard Worker     int idx = 0;
356*2b949d04SAndroid Build Coastguard Worker     bool rc = false;
357*2b949d04SAndroid Build Coastguard Worker 
358*2b949d04SAndroid Build Coastguard Worker     va_start(args, ctx);
359*2b949d04SAndroid Build Coastguard Worker     name = va_arg(args, const char *);
360*2b949d04SAndroid Build Coastguard Worker     variant = va_arg(args, const char *);
361*2b949d04SAndroid Build Coastguard Worker     while(name) {
362*2b949d04SAndroid Build Coastguard Worker         assert(++idx < 20); /* safety guard */
363*2b949d04SAndroid Build Coastguard Worker         if (!find_layout(ctx, name, variant))
364*2b949d04SAndroid Build Coastguard Worker             goto out;
365*2b949d04SAndroid Build Coastguard Worker         name = va_arg(args, const char *);
366*2b949d04SAndroid Build Coastguard Worker         if (name)
367*2b949d04SAndroid Build Coastguard Worker             variant = va_arg(args, const char *);
368*2b949d04SAndroid Build Coastguard Worker     };
369*2b949d04SAndroid Build Coastguard Worker 
370*2b949d04SAndroid Build Coastguard Worker     rc = true;
371*2b949d04SAndroid Build Coastguard Worker out:
372*2b949d04SAndroid Build Coastguard Worker     va_end(args);
373*2b949d04SAndroid Build Coastguard Worker     return rc;
374*2b949d04SAndroid Build Coastguard Worker }
375*2b949d04SAndroid Build Coastguard Worker 
376*2b949d04SAndroid Build Coastguard Worker static struct rxkb_option_group *
fetch_option_group(struct rxkb_context * ctx,const char * grp)377*2b949d04SAndroid Build Coastguard Worker fetch_option_group(struct rxkb_context *ctx, const char *grp)
378*2b949d04SAndroid Build Coastguard Worker {
379*2b949d04SAndroid Build Coastguard Worker     struct rxkb_option_group *g = rxkb_option_group_first(ctx);
380*2b949d04SAndroid Build Coastguard Worker     while (g) {
381*2b949d04SAndroid Build Coastguard Worker         if (streq(grp, rxkb_option_group_get_name(g)))
382*2b949d04SAndroid Build Coastguard Worker             return rxkb_option_group_ref(g);
383*2b949d04SAndroid Build Coastguard Worker         g = rxkb_option_group_next(g);
384*2b949d04SAndroid Build Coastguard Worker     }
385*2b949d04SAndroid Build Coastguard Worker     return NULL;
386*2b949d04SAndroid Build Coastguard Worker }
387*2b949d04SAndroid Build Coastguard Worker 
388*2b949d04SAndroid Build Coastguard Worker static inline bool
find_option_group(struct rxkb_context * ctx,const char * grp)389*2b949d04SAndroid Build Coastguard Worker find_option_group(struct rxkb_context *ctx, const char *grp)
390*2b949d04SAndroid Build Coastguard Worker {
391*2b949d04SAndroid Build Coastguard Worker     struct rxkb_option_group *g = fetch_option_group(ctx, grp);
392*2b949d04SAndroid Build Coastguard Worker     rxkb_option_group_unref(g);
393*2b949d04SAndroid Build Coastguard Worker     return g != NULL;
394*2b949d04SAndroid Build Coastguard Worker }
395*2b949d04SAndroid Build Coastguard Worker 
396*2b949d04SAndroid Build Coastguard Worker static struct rxkb_option *
fetch_option(struct rxkb_context * ctx,const char * grp,const char * opt)397*2b949d04SAndroid Build Coastguard Worker fetch_option(struct rxkb_context *ctx, const char *grp, const char *opt)
398*2b949d04SAndroid Build Coastguard Worker {
399*2b949d04SAndroid Build Coastguard Worker     struct rxkb_option_group *g = rxkb_option_group_first(ctx);
400*2b949d04SAndroid Build Coastguard Worker     while (g) {
401*2b949d04SAndroid Build Coastguard Worker         if (streq(grp, rxkb_option_group_get_name(g))) {
402*2b949d04SAndroid Build Coastguard Worker             struct rxkb_option *o = rxkb_option_first(g);
403*2b949d04SAndroid Build Coastguard Worker 
404*2b949d04SAndroid Build Coastguard Worker             while (o) {
405*2b949d04SAndroid Build Coastguard Worker                 if (streq(opt, rxkb_option_get_name(o)))
406*2b949d04SAndroid Build Coastguard Worker                     return rxkb_option_ref(o);
407*2b949d04SAndroid Build Coastguard Worker                 o = rxkb_option_next(o);
408*2b949d04SAndroid Build Coastguard Worker             }
409*2b949d04SAndroid Build Coastguard Worker         }
410*2b949d04SAndroid Build Coastguard Worker         g = rxkb_option_group_next(g);
411*2b949d04SAndroid Build Coastguard Worker     }
412*2b949d04SAndroid Build Coastguard Worker     return NULL;
413*2b949d04SAndroid Build Coastguard Worker }
414*2b949d04SAndroid Build Coastguard Worker 
415*2b949d04SAndroid Build Coastguard Worker static bool
find_option(struct rxkb_context * ctx,const char * grp,const char * opt)416*2b949d04SAndroid Build Coastguard Worker find_option(struct rxkb_context *ctx, const char *grp, const char *opt)
417*2b949d04SAndroid Build Coastguard Worker {
418*2b949d04SAndroid Build Coastguard Worker     struct rxkb_option *o = fetch_option(ctx, grp, opt);
419*2b949d04SAndroid Build Coastguard Worker     rxkb_option_unref(o);
420*2b949d04SAndroid Build Coastguard Worker     return o != NULL;
421*2b949d04SAndroid Build Coastguard Worker }
422*2b949d04SAndroid Build Coastguard Worker 
423*2b949d04SAndroid Build Coastguard Worker static bool
find_options(struct rxkb_context * ctx,...)424*2b949d04SAndroid Build Coastguard Worker find_options(struct rxkb_context *ctx, ...)
425*2b949d04SAndroid Build Coastguard Worker {
426*2b949d04SAndroid Build Coastguard Worker     va_list args;
427*2b949d04SAndroid Build Coastguard Worker     const char *grp, *opt;
428*2b949d04SAndroid Build Coastguard Worker     int idx = 0;
429*2b949d04SAndroid Build Coastguard Worker     bool rc = false;
430*2b949d04SAndroid Build Coastguard Worker 
431*2b949d04SAndroid Build Coastguard Worker     va_start(args, ctx);
432*2b949d04SAndroid Build Coastguard Worker     grp = va_arg(args, const char *);
433*2b949d04SAndroid Build Coastguard Worker     opt = va_arg(args, const char *);
434*2b949d04SAndroid Build Coastguard Worker     while(grp) {
435*2b949d04SAndroid Build Coastguard Worker         assert(++idx < 20); /* safety guard */
436*2b949d04SAndroid Build Coastguard Worker         if (!find_option(ctx, grp, opt))
437*2b949d04SAndroid Build Coastguard Worker             goto out;
438*2b949d04SAndroid Build Coastguard Worker         grp = va_arg(args, const char *);
439*2b949d04SAndroid Build Coastguard Worker         if (grp)
440*2b949d04SAndroid Build Coastguard Worker             opt = va_arg(args, const char *);
441*2b949d04SAndroid Build Coastguard Worker     };
442*2b949d04SAndroid Build Coastguard Worker 
443*2b949d04SAndroid Build Coastguard Worker     rc = true;
444*2b949d04SAndroid Build Coastguard Worker out:
445*2b949d04SAndroid Build Coastguard Worker     va_end(args);
446*2b949d04SAndroid Build Coastguard Worker     return rc;
447*2b949d04SAndroid Build Coastguard Worker }
448*2b949d04SAndroid Build Coastguard Worker 
449*2b949d04SAndroid Build Coastguard Worker static bool
cmp_models(struct test_model * tm,struct rxkb_model * m)450*2b949d04SAndroid Build Coastguard Worker cmp_models(struct test_model *tm, struct rxkb_model *m)
451*2b949d04SAndroid Build Coastguard Worker {
452*2b949d04SAndroid Build Coastguard Worker     if (!tm || !m)
453*2b949d04SAndroid Build Coastguard Worker         return false;
454*2b949d04SAndroid Build Coastguard Worker 
455*2b949d04SAndroid Build Coastguard Worker     if (!streq(tm->name, rxkb_model_get_name(m)))
456*2b949d04SAndroid Build Coastguard Worker         return false;
457*2b949d04SAndroid Build Coastguard Worker 
458*2b949d04SAndroid Build Coastguard Worker     if (!streq_null(tm->vendor, rxkb_model_get_vendor(m)))
459*2b949d04SAndroid Build Coastguard Worker         return false;
460*2b949d04SAndroid Build Coastguard Worker 
461*2b949d04SAndroid Build Coastguard Worker     if (!streq_null(tm->description, rxkb_model_get_description(m)))
462*2b949d04SAndroid Build Coastguard Worker         return false;
463*2b949d04SAndroid Build Coastguard Worker 
464*2b949d04SAndroid Build Coastguard Worker     return true;
465*2b949d04SAndroid Build Coastguard Worker }
466*2b949d04SAndroid Build Coastguard Worker 
467*2b949d04SAndroid Build Coastguard Worker static bool
cmp_layouts(struct test_layout * tl,struct rxkb_layout * l)468*2b949d04SAndroid Build Coastguard Worker cmp_layouts(struct test_layout *tl, struct rxkb_layout *l)
469*2b949d04SAndroid Build Coastguard Worker {
470*2b949d04SAndroid Build Coastguard Worker     struct rxkb_iso3166_code *iso3166 = NULL;
471*2b949d04SAndroid Build Coastguard Worker     struct rxkb_iso639_code *iso639 = NULL;
472*2b949d04SAndroid Build Coastguard Worker 
473*2b949d04SAndroid Build Coastguard Worker     if (!tl || !l)
474*2b949d04SAndroid Build Coastguard Worker         return false;
475*2b949d04SAndroid Build Coastguard Worker 
476*2b949d04SAndroid Build Coastguard Worker     if (!streq(tl->name, rxkb_layout_get_name(l)))
477*2b949d04SAndroid Build Coastguard Worker         return false;
478*2b949d04SAndroid Build Coastguard Worker 
479*2b949d04SAndroid Build Coastguard Worker     if (!streq_null(tl->variant, rxkb_layout_get_variant(l)))
480*2b949d04SAndroid Build Coastguard Worker         return false;
481*2b949d04SAndroid Build Coastguard Worker 
482*2b949d04SAndroid Build Coastguard Worker     if (!streq_null(tl->brief, rxkb_layout_get_brief(l)))
483*2b949d04SAndroid Build Coastguard Worker         return false;
484*2b949d04SAndroid Build Coastguard Worker 
485*2b949d04SAndroid Build Coastguard Worker     if (!streq_null(tl->description, rxkb_layout_get_description(l)))
486*2b949d04SAndroid Build Coastguard Worker         return false;
487*2b949d04SAndroid Build Coastguard Worker 
488*2b949d04SAndroid Build Coastguard Worker     iso3166 = rxkb_layout_get_iso3166_first(l);
489*2b949d04SAndroid Build Coastguard Worker     for (size_t i = 0; i < sizeof(tl->iso3166); i++) {
490*2b949d04SAndroid Build Coastguard Worker         const char *iso = tl->iso3166[i];
491*2b949d04SAndroid Build Coastguard Worker         if (iso == NULL && iso3166 == NULL)
492*2b949d04SAndroid Build Coastguard Worker             break;
493*2b949d04SAndroid Build Coastguard Worker 
494*2b949d04SAndroid Build Coastguard Worker         if (!streq_null(iso, rxkb_iso3166_code_get_code(iso3166)))
495*2b949d04SAndroid Build Coastguard Worker             return false;
496*2b949d04SAndroid Build Coastguard Worker 
497*2b949d04SAndroid Build Coastguard Worker         iso3166 = rxkb_iso3166_code_next(iso3166);
498*2b949d04SAndroid Build Coastguard Worker     }
499*2b949d04SAndroid Build Coastguard Worker 
500*2b949d04SAndroid Build Coastguard Worker     if (iso3166 != NULL)
501*2b949d04SAndroid Build Coastguard Worker         return false;
502*2b949d04SAndroid Build Coastguard Worker 
503*2b949d04SAndroid Build Coastguard Worker     iso639 = rxkb_layout_get_iso639_first(l);
504*2b949d04SAndroid Build Coastguard Worker     for (size_t i = 0; i < sizeof(tl->iso639); i++) {
505*2b949d04SAndroid Build Coastguard Worker         const char *iso = tl->iso639[i];
506*2b949d04SAndroid Build Coastguard Worker         if (iso == NULL && iso639 == NULL)
507*2b949d04SAndroid Build Coastguard Worker             break;
508*2b949d04SAndroid Build Coastguard Worker 
509*2b949d04SAndroid Build Coastguard Worker         if (!streq_null(iso, rxkb_iso639_code_get_code(iso639)))
510*2b949d04SAndroid Build Coastguard Worker             return false;
511*2b949d04SAndroid Build Coastguard Worker 
512*2b949d04SAndroid Build Coastguard Worker         iso639 = rxkb_iso639_code_next(iso639);
513*2b949d04SAndroid Build Coastguard Worker     }
514*2b949d04SAndroid Build Coastguard Worker 
515*2b949d04SAndroid Build Coastguard Worker     if (iso639 != NULL)
516*2b949d04SAndroid Build Coastguard Worker         return false;
517*2b949d04SAndroid Build Coastguard Worker 
518*2b949d04SAndroid Build Coastguard Worker     return true;
519*2b949d04SAndroid Build Coastguard Worker }
520*2b949d04SAndroid Build Coastguard Worker 
521*2b949d04SAndroid Build Coastguard Worker static bool
cmp_options(struct test_option * to,struct rxkb_option * o)522*2b949d04SAndroid Build Coastguard Worker cmp_options(struct test_option *to, struct rxkb_option *o)
523*2b949d04SAndroid Build Coastguard Worker {
524*2b949d04SAndroid Build Coastguard Worker     if (!to || !o)
525*2b949d04SAndroid Build Coastguard Worker         return false;
526*2b949d04SAndroid Build Coastguard Worker 
527*2b949d04SAndroid Build Coastguard Worker     if (!streq(to->name, rxkb_option_get_name(o)))
528*2b949d04SAndroid Build Coastguard Worker         return false;
529*2b949d04SAndroid Build Coastguard Worker 
530*2b949d04SAndroid Build Coastguard Worker     if (!streq_null(to->description, rxkb_option_get_description(o)))
531*2b949d04SAndroid Build Coastguard Worker         return false;
532*2b949d04SAndroid Build Coastguard Worker 
533*2b949d04SAndroid Build Coastguard Worker     return true;
534*2b949d04SAndroid Build Coastguard Worker }
535*2b949d04SAndroid Build Coastguard Worker 
536*2b949d04SAndroid Build Coastguard Worker enum cmp_type {
537*2b949d04SAndroid Build Coastguard Worker     CMP_EXACT,
538*2b949d04SAndroid Build Coastguard Worker     CMP_MATCHING_ONLY,
539*2b949d04SAndroid Build Coastguard Worker };
540*2b949d04SAndroid Build Coastguard Worker 
541*2b949d04SAndroid Build Coastguard Worker static bool
cmp_option_groups(struct test_option_group * tg,struct rxkb_option_group * g,enum cmp_type cmp)542*2b949d04SAndroid Build Coastguard Worker cmp_option_groups(struct test_option_group *tg, struct rxkb_option_group *g,
543*2b949d04SAndroid Build Coastguard Worker                   enum cmp_type cmp)
544*2b949d04SAndroid Build Coastguard Worker {
545*2b949d04SAndroid Build Coastguard Worker     struct rxkb_option *o;
546*2b949d04SAndroid Build Coastguard Worker     struct test_option *to;
547*2b949d04SAndroid Build Coastguard Worker 
548*2b949d04SAndroid Build Coastguard Worker     if (!tg || !g)
549*2b949d04SAndroid Build Coastguard Worker         return false;
550*2b949d04SAndroid Build Coastguard Worker 
551*2b949d04SAndroid Build Coastguard Worker     if (!streq(tg->name, rxkb_option_group_get_name(g)))
552*2b949d04SAndroid Build Coastguard Worker         return false;
553*2b949d04SAndroid Build Coastguard Worker 
554*2b949d04SAndroid Build Coastguard Worker     if (!streq_null(tg->description, rxkb_option_group_get_description(g)))
555*2b949d04SAndroid Build Coastguard Worker         return false;
556*2b949d04SAndroid Build Coastguard Worker 
557*2b949d04SAndroid Build Coastguard Worker     if (tg->allow_multiple_selection != rxkb_option_group_allows_multiple(g))
558*2b949d04SAndroid Build Coastguard Worker         return false;
559*2b949d04SAndroid Build Coastguard Worker 
560*2b949d04SAndroid Build Coastguard Worker     to = tg->options;
561*2b949d04SAndroid Build Coastguard Worker     o = rxkb_option_first(g);
562*2b949d04SAndroid Build Coastguard Worker 
563*2b949d04SAndroid Build Coastguard Worker     while (o && to->name) {
564*2b949d04SAndroid Build Coastguard Worker         if (!cmp_options(to, o))
565*2b949d04SAndroid Build Coastguard Worker             return false;
566*2b949d04SAndroid Build Coastguard Worker         to++;
567*2b949d04SAndroid Build Coastguard Worker         o = rxkb_option_next(o);
568*2b949d04SAndroid Build Coastguard Worker     }
569*2b949d04SAndroid Build Coastguard Worker 
570*2b949d04SAndroid Build Coastguard Worker     if (cmp == CMP_EXACT && (o || to->name))
571*2b949d04SAndroid Build Coastguard Worker         return false;
572*2b949d04SAndroid Build Coastguard Worker 
573*2b949d04SAndroid Build Coastguard Worker     return true;
574*2b949d04SAndroid Build Coastguard Worker }
575*2b949d04SAndroid Build Coastguard Worker 
576*2b949d04SAndroid Build Coastguard Worker static void
test_load_basic(void)577*2b949d04SAndroid Build Coastguard Worker test_load_basic(void)
578*2b949d04SAndroid Build Coastguard Worker {
579*2b949d04SAndroid Build Coastguard Worker     struct test_model system_models[] =  {
580*2b949d04SAndroid Build Coastguard Worker         {"m1"},
581*2b949d04SAndroid Build Coastguard Worker         {"m2"},
582*2b949d04SAndroid Build Coastguard Worker         {NULL},
583*2b949d04SAndroid Build Coastguard Worker     };
584*2b949d04SAndroid Build Coastguard Worker     struct test_layout system_layouts[] =  {
585*2b949d04SAndroid Build Coastguard Worker         {"l1"},
586*2b949d04SAndroid Build Coastguard Worker         {"l1", "v1"},
587*2b949d04SAndroid Build Coastguard Worker         {NULL},
588*2b949d04SAndroid Build Coastguard Worker     };
589*2b949d04SAndroid Build Coastguard Worker     struct test_option_group system_groups[] = {
590*2b949d04SAndroid Build Coastguard Worker         {"grp1", NULL, true,
591*2b949d04SAndroid Build Coastguard Worker           { {"grp1:1"}, {"grp1:2"} } },
592*2b949d04SAndroid Build Coastguard Worker         {"grp2", NULL, false,
593*2b949d04SAndroid Build Coastguard Worker           { {"grp2:1"}, {"grp2:2"} } },
594*2b949d04SAndroid Build Coastguard Worker         { NULL },
595*2b949d04SAndroid Build Coastguard Worker     };
596*2b949d04SAndroid Build Coastguard Worker     struct rxkb_context *ctx;
597*2b949d04SAndroid Build Coastguard Worker 
598*2b949d04SAndroid Build Coastguard Worker     ctx = test_setup_context(system_models, NULL,
599*2b949d04SAndroid Build Coastguard Worker                              system_layouts, NULL,
600*2b949d04SAndroid Build Coastguard Worker                              system_groups, NULL);
601*2b949d04SAndroid Build Coastguard Worker 
602*2b949d04SAndroid Build Coastguard Worker     assert(find_models(ctx, "m1", "m2", NULL));
603*2b949d04SAndroid Build Coastguard Worker     assert(find_layouts(ctx, "l1", NO_VARIANT,
604*2b949d04SAndroid Build Coastguard Worker                              "l1", "v1", NULL));
605*2b949d04SAndroid Build Coastguard Worker     assert(find_options(ctx, "grp1", "grp1:1",
606*2b949d04SAndroid Build Coastguard Worker                              "grp1", "grp1:2",
607*2b949d04SAndroid Build Coastguard Worker                              "grp2", "grp2:1",
608*2b949d04SAndroid Build Coastguard Worker                              "grp2", "grp2:2", NULL));
609*2b949d04SAndroid Build Coastguard Worker     rxkb_context_unref(ctx);
610*2b949d04SAndroid Build Coastguard Worker }
611*2b949d04SAndroid Build Coastguard Worker 
612*2b949d04SAndroid Build Coastguard Worker static void
test_load_full(void)613*2b949d04SAndroid Build Coastguard Worker test_load_full(void)
614*2b949d04SAndroid Build Coastguard Worker {
615*2b949d04SAndroid Build Coastguard Worker     struct test_model system_models[] =  {
616*2b949d04SAndroid Build Coastguard Worker         {"m1", "vendor1", "desc1"},
617*2b949d04SAndroid Build Coastguard Worker         {"m2", "vendor2", "desc2"},
618*2b949d04SAndroid Build Coastguard Worker         {NULL},
619*2b949d04SAndroid Build Coastguard Worker     };
620*2b949d04SAndroid Build Coastguard Worker     struct test_layout system_layouts[] =  {
621*2b949d04SAndroid Build Coastguard Worker         {"l1", NO_VARIANT, "lbrief1", "ldesc1"},
622*2b949d04SAndroid Build Coastguard Worker         {"l1", "v1", "vbrief1", "vdesc1"},
623*2b949d04SAndroid Build Coastguard Worker         {"l1", "v2", NULL, "vdesc2"},
624*2b949d04SAndroid Build Coastguard Worker         {NULL},
625*2b949d04SAndroid Build Coastguard Worker     };
626*2b949d04SAndroid Build Coastguard Worker     struct test_option_group system_groups[] = {
627*2b949d04SAndroid Build Coastguard Worker         {"grp1", "gdesc1", true,
628*2b949d04SAndroid Build Coastguard Worker           { {"grp1:1", "odesc11"}, {"grp1:2", "odesc12"} } },
629*2b949d04SAndroid Build Coastguard Worker         {"grp2", "gdesc2", false,
630*2b949d04SAndroid Build Coastguard Worker           { {"grp2:1", "odesc21"}, {"grp2:2", "odesc22"} } },
631*2b949d04SAndroid Build Coastguard Worker         { NULL },
632*2b949d04SAndroid Build Coastguard Worker     };
633*2b949d04SAndroid Build Coastguard Worker     struct rxkb_context *ctx;
634*2b949d04SAndroid Build Coastguard Worker     struct rxkb_model *m;
635*2b949d04SAndroid Build Coastguard Worker     struct rxkb_layout *l;
636*2b949d04SAndroid Build Coastguard Worker     struct rxkb_option_group *g;
637*2b949d04SAndroid Build Coastguard Worker 
638*2b949d04SAndroid Build Coastguard Worker     ctx = test_setup_context(system_models, NULL,
639*2b949d04SAndroid Build Coastguard Worker                              system_layouts, NULL,
640*2b949d04SAndroid Build Coastguard Worker                              system_groups, NULL);
641*2b949d04SAndroid Build Coastguard Worker 
642*2b949d04SAndroid Build Coastguard Worker     m = fetch_model(ctx, "m1");
643*2b949d04SAndroid Build Coastguard Worker     assert(cmp_models(&system_models[0], m));
644*2b949d04SAndroid Build Coastguard Worker     rxkb_model_unref(m);
645*2b949d04SAndroid Build Coastguard Worker 
646*2b949d04SAndroid Build Coastguard Worker     m = fetch_model(ctx, "m2");
647*2b949d04SAndroid Build Coastguard Worker     assert(cmp_models(&system_models[1], m));
648*2b949d04SAndroid Build Coastguard Worker     rxkb_model_unref(m);
649*2b949d04SAndroid Build Coastguard Worker 
650*2b949d04SAndroid Build Coastguard Worker     l = fetch_layout(ctx, "l1", NO_VARIANT);
651*2b949d04SAndroid Build Coastguard Worker     assert(cmp_layouts(&system_layouts[0], l));
652*2b949d04SAndroid Build Coastguard Worker     rxkb_layout_unref(l);
653*2b949d04SAndroid Build Coastguard Worker 
654*2b949d04SAndroid Build Coastguard Worker     l = fetch_layout(ctx, "l1", "v1");
655*2b949d04SAndroid Build Coastguard Worker     assert(cmp_layouts(&system_layouts[1], l));
656*2b949d04SAndroid Build Coastguard Worker     rxkb_layout_unref(l);
657*2b949d04SAndroid Build Coastguard Worker 
658*2b949d04SAndroid Build Coastguard Worker     l = fetch_layout(ctx, "l1", "v2");
659*2b949d04SAndroid Build Coastguard Worker     struct test_layout expected = {"l1", "v2", "lbrief1", "vdesc2"};
660*2b949d04SAndroid Build Coastguard Worker     assert(cmp_layouts(&expected, l));
661*2b949d04SAndroid Build Coastguard Worker     rxkb_layout_unref(l);
662*2b949d04SAndroid Build Coastguard Worker 
663*2b949d04SAndroid Build Coastguard Worker     g = fetch_option_group(ctx, "grp1");
664*2b949d04SAndroid Build Coastguard Worker     assert(cmp_option_groups(&system_groups[0], g, CMP_EXACT));
665*2b949d04SAndroid Build Coastguard Worker     rxkb_option_group_unref(g);
666*2b949d04SAndroid Build Coastguard Worker 
667*2b949d04SAndroid Build Coastguard Worker     g = fetch_option_group(ctx, "grp2");
668*2b949d04SAndroid Build Coastguard Worker     assert(cmp_option_groups(&system_groups[1], g, CMP_EXACT));
669*2b949d04SAndroid Build Coastguard Worker     rxkb_option_group_unref(g);
670*2b949d04SAndroid Build Coastguard Worker 
671*2b949d04SAndroid Build Coastguard Worker     rxkb_context_unref(ctx);
672*2b949d04SAndroid Build Coastguard Worker }
673*2b949d04SAndroid Build Coastguard Worker 
674*2b949d04SAndroid Build Coastguard Worker static void
test_load_languages(void)675*2b949d04SAndroid Build Coastguard Worker test_load_languages(void)
676*2b949d04SAndroid Build Coastguard Worker {
677*2b949d04SAndroid Build Coastguard Worker     struct test_model system_models[] =  {
678*2b949d04SAndroid Build Coastguard Worker         {"m1", "vendor1", "desc1"},
679*2b949d04SAndroid Build Coastguard Worker         {NULL},
680*2b949d04SAndroid Build Coastguard Worker     };
681*2b949d04SAndroid Build Coastguard Worker     struct test_layout system_layouts[] =  {
682*2b949d04SAndroid Build Coastguard Worker         {"l1", NO_VARIANT, "lbrief1", "ldesc1",
683*2b949d04SAndroid Build Coastguard Worker             .iso639 = { "abc", "def" },
684*2b949d04SAndroid Build Coastguard Worker             .iso3166 = { "uv", "wx" }},
685*2b949d04SAndroid Build Coastguard Worker         {"l1", "v1", "vbrief1", "vdesc1",
686*2b949d04SAndroid Build Coastguard Worker             .iso639 = {"efg"},
687*2b949d04SAndroid Build Coastguard Worker             .iso3166 = {"yz"}},
688*2b949d04SAndroid Build Coastguard Worker         {"l2", NO_VARIANT, "lbrief1", "ldesc1",
689*2b949d04SAndroid Build Coastguard Worker             .iso639 = { "hij", "klm" },
690*2b949d04SAndroid Build Coastguard Worker             .iso3166 = { "op", "qr" }},
691*2b949d04SAndroid Build Coastguard Worker         {"l2", "v2", "lbrief1", "ldesc1",
692*2b949d04SAndroid Build Coastguard Worker             .iso639 = { NULL }, /* inherit from parent */
693*2b949d04SAndroid Build Coastguard Worker             .iso3166 = { NULL }},  /* inherit from parent */
694*2b949d04SAndroid Build Coastguard Worker         {NULL},
695*2b949d04SAndroid Build Coastguard Worker     };
696*2b949d04SAndroid Build Coastguard Worker     struct test_option_group system_groups[] = {
697*2b949d04SAndroid Build Coastguard Worker         {"grp1", "gdesc1", true,
698*2b949d04SAndroid Build Coastguard Worker           { {"grp1:1", "odesc11"}, {"grp1:2", "odesc12"} } },
699*2b949d04SAndroid Build Coastguard Worker         { NULL },
700*2b949d04SAndroid Build Coastguard Worker     };
701*2b949d04SAndroid Build Coastguard Worker     struct rxkb_context *ctx;
702*2b949d04SAndroid Build Coastguard Worker     struct rxkb_layout *l;
703*2b949d04SAndroid Build Coastguard Worker     struct rxkb_iso3166_code *iso3166;
704*2b949d04SAndroid Build Coastguard Worker     struct rxkb_iso639_code *iso639;
705*2b949d04SAndroid Build Coastguard Worker 
706*2b949d04SAndroid Build Coastguard Worker     ctx = test_setup_context(system_models, NULL,
707*2b949d04SAndroid Build Coastguard Worker                              system_layouts, NULL,
708*2b949d04SAndroid Build Coastguard Worker                              system_groups, NULL);
709*2b949d04SAndroid Build Coastguard Worker 
710*2b949d04SAndroid Build Coastguard Worker     l = fetch_layout(ctx, "l1", NO_VARIANT);
711*2b949d04SAndroid Build Coastguard Worker     assert(cmp_layouts(&system_layouts[0], l));
712*2b949d04SAndroid Build Coastguard Worker     rxkb_layout_unref(l);
713*2b949d04SAndroid Build Coastguard Worker 
714*2b949d04SAndroid Build Coastguard Worker     l = fetch_layout(ctx, "l1", "v1");
715*2b949d04SAndroid Build Coastguard Worker     assert(cmp_layouts(&system_layouts[1], l));
716*2b949d04SAndroid Build Coastguard Worker     rxkb_layout_unref(l);
717*2b949d04SAndroid Build Coastguard Worker 
718*2b949d04SAndroid Build Coastguard Worker     l = fetch_layout(ctx, "l2", "v2");
719*2b949d04SAndroid Build Coastguard Worker     iso3166 = rxkb_layout_get_iso3166_first(l);
720*2b949d04SAndroid Build Coastguard Worker     assert(streq(rxkb_iso3166_code_get_code(iso3166), "op"));
721*2b949d04SAndroid Build Coastguard Worker     iso3166 = rxkb_iso3166_code_next(iso3166);
722*2b949d04SAndroid Build Coastguard Worker     assert(streq(rxkb_iso3166_code_get_code(iso3166), "qr"));
723*2b949d04SAndroid Build Coastguard Worker 
724*2b949d04SAndroid Build Coastguard Worker     iso639 = rxkb_layout_get_iso639_first(l);
725*2b949d04SAndroid Build Coastguard Worker     assert(streq(rxkb_iso639_code_get_code(iso639), "hij"));
726*2b949d04SAndroid Build Coastguard Worker     iso639 = rxkb_iso639_code_next(iso639);
727*2b949d04SAndroid Build Coastguard Worker     assert(streq(rxkb_iso639_code_get_code(iso639), "klm"));
728*2b949d04SAndroid Build Coastguard Worker 
729*2b949d04SAndroid Build Coastguard Worker     rxkb_layout_unref(l);
730*2b949d04SAndroid Build Coastguard Worker     rxkb_context_unref(ctx);
731*2b949d04SAndroid Build Coastguard Worker }
732*2b949d04SAndroid Build Coastguard Worker 
733*2b949d04SAndroid Build Coastguard Worker static void
test_load_invalid_languages(void)734*2b949d04SAndroid Build Coastguard Worker test_load_invalid_languages(void)
735*2b949d04SAndroid Build Coastguard Worker {
736*2b949d04SAndroid Build Coastguard Worker     struct test_model system_models[] =  {
737*2b949d04SAndroid Build Coastguard Worker         {"m1", "vendor1", "desc1"},
738*2b949d04SAndroid Build Coastguard Worker         {NULL},
739*2b949d04SAndroid Build Coastguard Worker     };
740*2b949d04SAndroid Build Coastguard Worker     struct test_layout system_layouts[] =  {
741*2b949d04SAndroid Build Coastguard Worker         {"l1", NO_VARIANT, "lbrief1", "ldesc1",
742*2b949d04SAndroid Build Coastguard Worker             .iso639 = { "ab", "def" },
743*2b949d04SAndroid Build Coastguard Worker             .iso3166 = { "uvw", "xz" }},
744*2b949d04SAndroid Build Coastguard Worker         {NULL},
745*2b949d04SAndroid Build Coastguard Worker     };
746*2b949d04SAndroid Build Coastguard Worker     struct test_option_group system_groups[] = {
747*2b949d04SAndroid Build Coastguard Worker         {"grp1", "gdesc1", true,
748*2b949d04SAndroid Build Coastguard Worker           { {"grp1:1", "odesc11"}, {"grp1:2", "odesc12"} } },
749*2b949d04SAndroid Build Coastguard Worker         { NULL },
750*2b949d04SAndroid Build Coastguard Worker     };
751*2b949d04SAndroid Build Coastguard Worker     struct rxkb_context *ctx;
752*2b949d04SAndroid Build Coastguard Worker     struct rxkb_layout *l;
753*2b949d04SAndroid Build Coastguard Worker     struct rxkb_iso3166_code *iso3166;
754*2b949d04SAndroid Build Coastguard Worker     struct rxkb_iso639_code *iso639;
755*2b949d04SAndroid Build Coastguard Worker 
756*2b949d04SAndroid Build Coastguard Worker     ctx = test_setup_context(system_models, NULL,
757*2b949d04SAndroid Build Coastguard Worker                              system_layouts, NULL,
758*2b949d04SAndroid Build Coastguard Worker                              system_groups, NULL);
759*2b949d04SAndroid Build Coastguard Worker 
760*2b949d04SAndroid Build Coastguard Worker     l = fetch_layout(ctx, "l1", NO_VARIANT);
761*2b949d04SAndroid Build Coastguard Worker     /* uvw is invalid, we expect 2 letters, verify it was ignored */
762*2b949d04SAndroid Build Coastguard Worker     iso3166 = rxkb_layout_get_iso3166_first(l);
763*2b949d04SAndroid Build Coastguard Worker     assert(streq(rxkb_iso3166_code_get_code(iso3166), "xz"));
764*2b949d04SAndroid Build Coastguard Worker     assert(rxkb_iso3166_code_next(iso3166) == NULL);
765*2b949d04SAndroid Build Coastguard Worker 
766*2b949d04SAndroid Build Coastguard Worker     /* ab is invalid, we expect 3 letters, verify it was ignored */
767*2b949d04SAndroid Build Coastguard Worker     iso639 = rxkb_layout_get_iso639_first(l);
768*2b949d04SAndroid Build Coastguard Worker     assert(streq(rxkb_iso639_code_get_code(iso639), "def"));
769*2b949d04SAndroid Build Coastguard Worker     assert(rxkb_iso639_code_next(iso639) == NULL);
770*2b949d04SAndroid Build Coastguard Worker     rxkb_layout_unref(l);
771*2b949d04SAndroid Build Coastguard Worker 
772*2b949d04SAndroid Build Coastguard Worker     rxkb_context_unref(ctx);
773*2b949d04SAndroid Build Coastguard Worker }
774*2b949d04SAndroid Build Coastguard Worker 
775*2b949d04SAndroid Build Coastguard Worker static void
test_popularity(void)776*2b949d04SAndroid Build Coastguard Worker test_popularity(void)
777*2b949d04SAndroid Build Coastguard Worker {
778*2b949d04SAndroid Build Coastguard Worker     struct test_layout system_layouts[] =  {
779*2b949d04SAndroid Build Coastguard Worker         {"l1", NO_VARIANT },
780*2b949d04SAndroid Build Coastguard Worker         {"l1", "v1" },
781*2b949d04SAndroid Build Coastguard Worker         {NULL},
782*2b949d04SAndroid Build Coastguard Worker     };
783*2b949d04SAndroid Build Coastguard Worker     struct rxkb_context *ctx;
784*2b949d04SAndroid Build Coastguard Worker     struct rxkb_layout *l;
785*2b949d04SAndroid Build Coastguard Worker     const char *ruleset = "xkbtests.extras";
786*2b949d04SAndroid Build Coastguard Worker     char *dir = NULL;
787*2b949d04SAndroid Build Coastguard Worker 
788*2b949d04SAndroid Build Coastguard Worker     dir = test_create_rules(ruleset, NULL, system_layouts, NULL);
789*2b949d04SAndroid Build Coastguard Worker     ctx = rxkb_context_new(RXKB_CONTEXT_NO_DEFAULT_INCLUDES |
790*2b949d04SAndroid Build Coastguard Worker                            RXKB_CONTEXT_LOAD_EXOTIC_RULES);
791*2b949d04SAndroid Build Coastguard Worker     assert(ctx);
792*2b949d04SAndroid Build Coastguard Worker     assert(rxkb_context_include_path_append(ctx, dir));
793*2b949d04SAndroid Build Coastguard Worker     /* Hack: rulest above generates xkbtests.extras.xml, loading "xkbtests"
794*2b949d04SAndroid Build Coastguard Worker      * means the extras file counts as exotic */
795*2b949d04SAndroid Build Coastguard Worker     assert(rxkb_context_parse(ctx, "xkbtests"));
796*2b949d04SAndroid Build Coastguard Worker 
797*2b949d04SAndroid Build Coastguard Worker     l = fetch_layout(ctx, "l1", NO_VARIANT);
798*2b949d04SAndroid Build Coastguard Worker     assert(rxkb_layout_get_popularity(l) == RXKB_POPULARITY_EXOTIC);
799*2b949d04SAndroid Build Coastguard Worker     rxkb_layout_unref(l);
800*2b949d04SAndroid Build Coastguard Worker 
801*2b949d04SAndroid Build Coastguard Worker     l = fetch_layout(ctx, "l1", "v1");
802*2b949d04SAndroid Build Coastguard Worker     assert(rxkb_layout_get_popularity(l) == RXKB_POPULARITY_EXOTIC);
803*2b949d04SAndroid Build Coastguard Worker     rxkb_layout_unref(l);
804*2b949d04SAndroid Build Coastguard Worker 
805*2b949d04SAndroid Build Coastguard Worker     test_remove_rules(dir, ruleset);
806*2b949d04SAndroid Build Coastguard Worker     rxkb_context_unref(ctx);
807*2b949d04SAndroid Build Coastguard Worker }
808*2b949d04SAndroid Build Coastguard Worker 
809*2b949d04SAndroid Build Coastguard Worker 
810*2b949d04SAndroid Build Coastguard Worker static void
test_load_merge(void)811*2b949d04SAndroid Build Coastguard Worker test_load_merge(void)
812*2b949d04SAndroid Build Coastguard Worker {
813*2b949d04SAndroid Build Coastguard Worker     struct test_model system_models[] =  {
814*2b949d04SAndroid Build Coastguard Worker         {"m1", "vendor1", "desc1"},
815*2b949d04SAndroid Build Coastguard Worker         {"m2", "vendor2", "desc2"},
816*2b949d04SAndroid Build Coastguard Worker         {NULL},
817*2b949d04SAndroid Build Coastguard Worker     };
818*2b949d04SAndroid Build Coastguard Worker     struct test_model user_models[] =  {
819*2b949d04SAndroid Build Coastguard Worker         {"m3", "vendor3", "desc3"},
820*2b949d04SAndroid Build Coastguard Worker         {"m4", "vendor4", "desc4"},
821*2b949d04SAndroid Build Coastguard Worker         {NULL},
822*2b949d04SAndroid Build Coastguard Worker     };
823*2b949d04SAndroid Build Coastguard Worker     struct test_layout system_layouts[] =  {
824*2b949d04SAndroid Build Coastguard Worker         {"l1", NO_VARIANT, "lbrief1", "ldesc1"},
825*2b949d04SAndroid Build Coastguard Worker         {"l1", "v1", "vbrief1", "vdesc1"},
826*2b949d04SAndroid Build Coastguard Worker         {NULL},
827*2b949d04SAndroid Build Coastguard Worker     };
828*2b949d04SAndroid Build Coastguard Worker     struct test_layout user_layouts[] =  {
829*2b949d04SAndroid Build Coastguard Worker         {"l2", NO_VARIANT, "lbrief2", "ldesc2"},
830*2b949d04SAndroid Build Coastguard Worker         {"l2", "v2", "vbrief2", "vdesc2"},
831*2b949d04SAndroid Build Coastguard Worker         {NULL},
832*2b949d04SAndroid Build Coastguard Worker     };
833*2b949d04SAndroid Build Coastguard Worker     struct test_option_group system_groups[] = {
834*2b949d04SAndroid Build Coastguard Worker         {"grp1", NULL, true,
835*2b949d04SAndroid Build Coastguard Worker           { {"grp1:1"}, {"grp1:2"} } },
836*2b949d04SAndroid Build Coastguard Worker         {"grp2", NULL, false,
837*2b949d04SAndroid Build Coastguard Worker           { {"grp2:1"}, {"grp2:2"} } },
838*2b949d04SAndroid Build Coastguard Worker         { NULL },
839*2b949d04SAndroid Build Coastguard Worker     };
840*2b949d04SAndroid Build Coastguard Worker     struct test_option_group user_groups[] = {
841*2b949d04SAndroid Build Coastguard Worker         {"grp3", NULL, true,
842*2b949d04SAndroid Build Coastguard Worker           { {"grp3:1"}, {"grp3:2"} } },
843*2b949d04SAndroid Build Coastguard Worker         {"grp4", NULL, false,
844*2b949d04SAndroid Build Coastguard Worker           { {"grp4:1"}, {"grp4:2"} } },
845*2b949d04SAndroid Build Coastguard Worker         { NULL },
846*2b949d04SAndroid Build Coastguard Worker     };
847*2b949d04SAndroid Build Coastguard Worker     struct rxkb_context *ctx;
848*2b949d04SAndroid Build Coastguard Worker     struct rxkb_model *m;
849*2b949d04SAndroid Build Coastguard Worker     struct rxkb_layout *l;
850*2b949d04SAndroid Build Coastguard Worker     struct rxkb_option_group *g;
851*2b949d04SAndroid Build Coastguard Worker 
852*2b949d04SAndroid Build Coastguard Worker     ctx = test_setup_context(system_models, user_models,
853*2b949d04SAndroid Build Coastguard Worker                              system_layouts, user_layouts,
854*2b949d04SAndroid Build Coastguard Worker                              system_groups, user_groups);
855*2b949d04SAndroid Build Coastguard Worker 
856*2b949d04SAndroid Build Coastguard Worker     assert(find_models(ctx, "m1", "m2", "m3", "m4", NULL));
857*2b949d04SAndroid Build Coastguard Worker     assert(find_layouts(ctx, "l1", NO_VARIANT,
858*2b949d04SAndroid Build Coastguard Worker                              "l1", "v1",
859*2b949d04SAndroid Build Coastguard Worker                              "l2", NO_VARIANT,
860*2b949d04SAndroid Build Coastguard Worker                              "l2", "v2", NULL));
861*2b949d04SAndroid Build Coastguard Worker 
862*2b949d04SAndroid Build Coastguard Worker     m = fetch_model(ctx, "m1");
863*2b949d04SAndroid Build Coastguard Worker     assert(cmp_models(&system_models[0], m));
864*2b949d04SAndroid Build Coastguard Worker     rxkb_model_unref(m);
865*2b949d04SAndroid Build Coastguard Worker 
866*2b949d04SAndroid Build Coastguard Worker     m = fetch_model(ctx, "m2");
867*2b949d04SAndroid Build Coastguard Worker     assert(cmp_models(&system_models[1], m));
868*2b949d04SAndroid Build Coastguard Worker     rxkb_model_unref(m);
869*2b949d04SAndroid Build Coastguard Worker 
870*2b949d04SAndroid Build Coastguard Worker     m = fetch_model(ctx, "m3");
871*2b949d04SAndroid Build Coastguard Worker     assert(cmp_models(&user_models[0], m));
872*2b949d04SAndroid Build Coastguard Worker     rxkb_model_unref(m);
873*2b949d04SAndroid Build Coastguard Worker 
874*2b949d04SAndroid Build Coastguard Worker     m = fetch_model(ctx, "m4");
875*2b949d04SAndroid Build Coastguard Worker     assert(cmp_models(&user_models[1], m));
876*2b949d04SAndroid Build Coastguard Worker     rxkb_model_unref(m);
877*2b949d04SAndroid Build Coastguard Worker 
878*2b949d04SAndroid Build Coastguard Worker     l = fetch_layout(ctx, "l1", NO_VARIANT);
879*2b949d04SAndroid Build Coastguard Worker     assert(cmp_layouts(&system_layouts[0], l));
880*2b949d04SAndroid Build Coastguard Worker     rxkb_layout_unref(l);
881*2b949d04SAndroid Build Coastguard Worker 
882*2b949d04SAndroid Build Coastguard Worker     l = fetch_layout(ctx, "l1", "v1");
883*2b949d04SAndroid Build Coastguard Worker     assert(cmp_layouts(&system_layouts[1], l));
884*2b949d04SAndroid Build Coastguard Worker     rxkb_layout_unref(l);
885*2b949d04SAndroid Build Coastguard Worker 
886*2b949d04SAndroid Build Coastguard Worker     l = fetch_layout(ctx, "l2", NO_VARIANT);
887*2b949d04SAndroid Build Coastguard Worker     assert(cmp_layouts(&user_layouts[0], l));
888*2b949d04SAndroid Build Coastguard Worker     rxkb_layout_unref(l);
889*2b949d04SAndroid Build Coastguard Worker 
890*2b949d04SAndroid Build Coastguard Worker     l = fetch_layout(ctx, "l2", "v2");
891*2b949d04SAndroid Build Coastguard Worker     assert(cmp_layouts(&user_layouts[1], l));
892*2b949d04SAndroid Build Coastguard Worker     rxkb_layout_unref(l);
893*2b949d04SAndroid Build Coastguard Worker 
894*2b949d04SAndroid Build Coastguard Worker     g = fetch_option_group(ctx, "grp1");
895*2b949d04SAndroid Build Coastguard Worker     assert(cmp_option_groups(&system_groups[0], g, CMP_EXACT));
896*2b949d04SAndroid Build Coastguard Worker     rxkb_option_group_unref(g);
897*2b949d04SAndroid Build Coastguard Worker 
898*2b949d04SAndroid Build Coastguard Worker     g = fetch_option_group(ctx, "grp2");
899*2b949d04SAndroid Build Coastguard Worker     assert(cmp_option_groups(&system_groups[1], g, CMP_EXACT));
900*2b949d04SAndroid Build Coastguard Worker     rxkb_option_group_unref(g);
901*2b949d04SAndroid Build Coastguard Worker 
902*2b949d04SAndroid Build Coastguard Worker     g = fetch_option_group(ctx, "grp3");
903*2b949d04SAndroid Build Coastguard Worker     assert(cmp_option_groups(&user_groups[0], g, CMP_EXACT));
904*2b949d04SAndroid Build Coastguard Worker     rxkb_option_group_unref(g);
905*2b949d04SAndroid Build Coastguard Worker 
906*2b949d04SAndroid Build Coastguard Worker     g = fetch_option_group(ctx, "grp4");
907*2b949d04SAndroid Build Coastguard Worker     assert(cmp_option_groups(&user_groups[1], g, CMP_EXACT));
908*2b949d04SAndroid Build Coastguard Worker     rxkb_option_group_unref(g);
909*2b949d04SAndroid Build Coastguard Worker 
910*2b949d04SAndroid Build Coastguard Worker     rxkb_context_unref(ctx);
911*2b949d04SAndroid Build Coastguard Worker }
912*2b949d04SAndroid Build Coastguard Worker 
913*2b949d04SAndroid Build Coastguard Worker static void
test_load_merge_no_overwrite(void)914*2b949d04SAndroid Build Coastguard Worker test_load_merge_no_overwrite(void)
915*2b949d04SAndroid Build Coastguard Worker {
916*2b949d04SAndroid Build Coastguard Worker     struct test_model system_models[] =  {
917*2b949d04SAndroid Build Coastguard Worker         {"m1", "vendor1", "desc1"},
918*2b949d04SAndroid Build Coastguard Worker         {"m2", "vendor2", "desc2"},
919*2b949d04SAndroid Build Coastguard Worker         {NULL},
920*2b949d04SAndroid Build Coastguard Worker     };
921*2b949d04SAndroid Build Coastguard Worker     struct test_model user_models[] =  {
922*2b949d04SAndroid Build Coastguard Worker         {"m1", "vendor3", "desc3"}, /* must not overwrite */
923*2b949d04SAndroid Build Coastguard Worker         {"m4", "vendor4", "desc4"},
924*2b949d04SAndroid Build Coastguard Worker         {NULL},
925*2b949d04SAndroid Build Coastguard Worker     };
926*2b949d04SAndroid Build Coastguard Worker     struct test_layout system_layouts[] =  {
927*2b949d04SAndroid Build Coastguard Worker         {"l1", NO_VARIANT, "lbrief1", "ldesc1"},
928*2b949d04SAndroid Build Coastguard Worker         {"l1", "v1", "vbrief1", "vdesc1"},
929*2b949d04SAndroid Build Coastguard Worker         {NULL},
930*2b949d04SAndroid Build Coastguard Worker     };
931*2b949d04SAndroid Build Coastguard Worker     struct test_layout user_layouts[] =  {
932*2b949d04SAndroid Build Coastguard Worker         {"l2", NO_VARIANT, "lbrief2", "ldesc2"},
933*2b949d04SAndroid Build Coastguard Worker         {"l2", "v2", "vbrief2", "vdesc2"},
934*2b949d04SAndroid Build Coastguard Worker         {"l1", NO_VARIANT, "lbrief3", "ldesc3"}, /* must not overwrite */
935*2b949d04SAndroid Build Coastguard Worker         {"l1", "v2", "vbrief3", "vdesc3"}, /* must not overwrite */
936*2b949d04SAndroid Build Coastguard Worker         {NULL},
937*2b949d04SAndroid Build Coastguard Worker     };
938*2b949d04SAndroid Build Coastguard Worker     struct test_option_group system_groups[] = {
939*2b949d04SAndroid Build Coastguard Worker         {"grp1", "gdesc1", true,
940*2b949d04SAndroid Build Coastguard Worker           { {"grp1:1", "odesc11"}, {"grp1:2", "odesc12"} } },
941*2b949d04SAndroid Build Coastguard Worker         {"grp2", "gdesc2", false,
942*2b949d04SAndroid Build Coastguard Worker           { {"grp2:1", "odesc21"}, {"grp2:2", "odesc22"} } },
943*2b949d04SAndroid Build Coastguard Worker         { NULL },
944*2b949d04SAndroid Build Coastguard Worker     };
945*2b949d04SAndroid Build Coastguard Worker     struct test_option_group user_groups[] = {
946*2b949d04SAndroid Build Coastguard Worker         {"grp1", "XXXXX", false, /* must not overwrite */
947*2b949d04SAndroid Build Coastguard Worker           { {"grp1:1", "YYYYYYY"}, /* must not overwrite */
948*2b949d04SAndroid Build Coastguard Worker             {"grp1:3", "ZZZZZZ"} } }, /* append */
949*2b949d04SAndroid Build Coastguard Worker         {"grp4", "gdesc4", false,
950*2b949d04SAndroid Build Coastguard Worker           { {"grp4:1", "odesc41"}, {"grp4:2", "odesc42"} } },
951*2b949d04SAndroid Build Coastguard Worker         { NULL },
952*2b949d04SAndroid Build Coastguard Worker     };
953*2b949d04SAndroid Build Coastguard Worker     struct rxkb_context *ctx;
954*2b949d04SAndroid Build Coastguard Worker     struct rxkb_model *m;
955*2b949d04SAndroid Build Coastguard Worker     struct rxkb_layout *l;
956*2b949d04SAndroid Build Coastguard Worker     struct rxkb_option_group *g;
957*2b949d04SAndroid Build Coastguard Worker 
958*2b949d04SAndroid Build Coastguard Worker     ctx = test_setup_context(system_models, user_models,
959*2b949d04SAndroid Build Coastguard Worker                              system_layouts, user_layouts,
960*2b949d04SAndroid Build Coastguard Worker                              system_groups, user_groups);
961*2b949d04SAndroid Build Coastguard Worker 
962*2b949d04SAndroid Build Coastguard Worker     m = fetch_model(ctx, "m1");
963*2b949d04SAndroid Build Coastguard Worker     assert(cmp_models(&system_models[0], m));
964*2b949d04SAndroid Build Coastguard Worker     rxkb_model_unref(m);
965*2b949d04SAndroid Build Coastguard Worker 
966*2b949d04SAndroid Build Coastguard Worker     l = fetch_layout(ctx, "l1", NO_VARIANT);
967*2b949d04SAndroid Build Coastguard Worker     assert(cmp_layouts(&system_layouts[0], l));
968*2b949d04SAndroid Build Coastguard Worker     rxkb_layout_unref(l);
969*2b949d04SAndroid Build Coastguard Worker 
970*2b949d04SAndroid Build Coastguard Worker     l = fetch_layout(ctx, "l1", "v1");
971*2b949d04SAndroid Build Coastguard Worker     assert(cmp_layouts(&system_layouts[1], l));
972*2b949d04SAndroid Build Coastguard Worker     rxkb_layout_unref(l);
973*2b949d04SAndroid Build Coastguard Worker 
974*2b949d04SAndroid Build Coastguard Worker     assert(find_option(ctx, "grp1", "grp1:3"));
975*2b949d04SAndroid Build Coastguard Worker     g = fetch_option_group(ctx, "grp1");
976*2b949d04SAndroid Build Coastguard Worker     assert(cmp_option_groups(&system_groups[0], g, CMP_MATCHING_ONLY));
977*2b949d04SAndroid Build Coastguard Worker     rxkb_option_group_unref(g);
978*2b949d04SAndroid Build Coastguard Worker 
979*2b949d04SAndroid Build Coastguard Worker     rxkb_context_unref(ctx);
980*2b949d04SAndroid Build Coastguard Worker }
981*2b949d04SAndroid Build Coastguard Worker 
982*2b949d04SAndroid Build Coastguard Worker static void
test_no_include_paths(void)983*2b949d04SAndroid Build Coastguard Worker test_no_include_paths(void)
984*2b949d04SAndroid Build Coastguard Worker {
985*2b949d04SAndroid Build Coastguard Worker     struct rxkb_context *ctx;
986*2b949d04SAndroid Build Coastguard Worker 
987*2b949d04SAndroid Build Coastguard Worker     ctx = rxkb_context_new(RXKB_CONTEXT_NO_DEFAULT_INCLUDES);
988*2b949d04SAndroid Build Coastguard Worker     assert(ctx);
989*2b949d04SAndroid Build Coastguard Worker     assert(!rxkb_context_parse_default_ruleset(ctx));
990*2b949d04SAndroid Build Coastguard Worker 
991*2b949d04SAndroid Build Coastguard Worker     rxkb_context_unref(ctx);
992*2b949d04SAndroid Build Coastguard Worker }
993*2b949d04SAndroid Build Coastguard Worker 
994*2b949d04SAndroid Build Coastguard Worker static void
test_invalid_include(void)995*2b949d04SAndroid Build Coastguard Worker test_invalid_include(void)
996*2b949d04SAndroid Build Coastguard Worker {
997*2b949d04SAndroid Build Coastguard Worker     struct rxkb_context *ctx;
998*2b949d04SAndroid Build Coastguard Worker 
999*2b949d04SAndroid Build Coastguard Worker     ctx = rxkb_context_new(RXKB_CONTEXT_NO_DEFAULT_INCLUDES);
1000*2b949d04SAndroid Build Coastguard Worker     assert(ctx);
1001*2b949d04SAndroid Build Coastguard Worker     assert(!rxkb_context_include_path_append(ctx, "/foo/bar/baz/bat"));
1002*2b949d04SAndroid Build Coastguard Worker     assert(!rxkb_context_parse_default_ruleset(ctx));
1003*2b949d04SAndroid Build Coastguard Worker 
1004*2b949d04SAndroid Build Coastguard Worker     rxkb_context_unref(ctx);
1005*2b949d04SAndroid Build Coastguard Worker }
1006*2b949d04SAndroid Build Coastguard Worker 
1007*2b949d04SAndroid Build Coastguard Worker int
main(void)1008*2b949d04SAndroid Build Coastguard Worker main(void)
1009*2b949d04SAndroid Build Coastguard Worker {
1010*2b949d04SAndroid Build Coastguard Worker     test_no_include_paths();
1011*2b949d04SAndroid Build Coastguard Worker     test_invalid_include();
1012*2b949d04SAndroid Build Coastguard Worker     test_load_basic();
1013*2b949d04SAndroid Build Coastguard Worker     test_load_full();
1014*2b949d04SAndroid Build Coastguard Worker     test_load_merge();
1015*2b949d04SAndroid Build Coastguard Worker     test_load_merge_no_overwrite();
1016*2b949d04SAndroid Build Coastguard Worker     test_load_languages();
1017*2b949d04SAndroid Build Coastguard Worker     test_load_invalid_languages();
1018*2b949d04SAndroid Build Coastguard Worker     test_popularity();
1019*2b949d04SAndroid Build Coastguard Worker 
1020*2b949d04SAndroid Build Coastguard Worker     return 0;
1021*2b949d04SAndroid Build Coastguard Worker }
1022