Imported Upstream version 2.14.2
[platform/upstream/fontconfig.git] / test / test-family-matching.c
1 /*
2  * fontconfig/test/test-family-matching.c
3  *
4  * Copyright © 2020 Zoltan Vandrus
5  *
6  * Permission to use, copy, modify, distribute, and sell this software and its
7  * documentation for any purpose is hereby granted without fee, provided that
8  * the above copyright notice appear in all copies and that both that
9  * copyright notice and this permission notice appear in supporting
10  * documentation, and that the name of the author(s) not be used in
11  * advertising or publicity pertaining to distribution of the software without
12  * specific, written prior permission.  The authors make no
13  * representations about the suitability of this software for any purpose.  It
14  * is provided "as is" without express or implied warranty.
15  *
16  * THE AUTHOR(S) DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
17  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
18  * EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY SPECIAL, INDIRECT OR
19  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
20  * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
21  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
22  * PERFORMANCE OF THIS SOFTWARE.
23  */
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <fontconfig/fontconfig.h>
27
28 #define FC_TEST_RESULT "testresult"
29
30 typedef enum _TestMatchResult {
31     TestMatch,
32     TestNoMatch,
33     TestMatchError
34 } TestMatchResult;
35
36 typedef enum _TestResult {
37     TestPassed,
38     TestFailed,
39     TestError
40 } TestResult;
41
42 static TestMatchResult
43 TestMatchPattern (const char *test, FcPattern *p)
44 {
45     const FcChar8 *xml_pre = (const FcChar8 *) ""
46         "<fontconfig>\n"
47         "  <match>\n"
48         "";
49
50     const FcChar8 *xml_post = (const FcChar8 *) ""
51         "    <edit name=\""FC_TEST_RESULT"\">\n"
52         "      <bool>true</bool>\n"
53         "    </edit>\n"
54         "  </match>\n"
55         "</fontconfig>\n"
56         "";
57
58     FcPattern *pat = NULL;
59     FcChar8 *concat = NULL;
60     FcChar8 *xml = NULL;
61     FcConfig *cfg = NULL;
62     FcResult result;
63     FcBool dummy;
64     TestMatchResult ret = TestMatchError;
65
66     pat = FcPatternDuplicate (p);
67     if (!pat)
68     {
69         fprintf (stderr, "Unable to duplicate pattern.\n");
70         goto bail;
71     }
72
73     concat = FcStrPlus (xml_pre, (const FcChar8 *) test);
74     if (!concat)
75     {
76         fprintf (stderr, "Concatenation failed.\n");
77         goto bail;
78     }
79
80     xml = FcStrPlus (concat, xml_post);
81     if (!xml)
82     {
83         fprintf (stderr, "Concatenation failed.\n");
84         goto bail;
85     }
86
87     cfg = FcConfigCreate ();
88     if (!cfg)
89     {
90         fprintf (stderr, "Unable to create a new empty config.\n");
91         goto bail;
92     }
93
94     if (!FcConfigParseAndLoadFromMemory (cfg, xml, FcTrue))
95     {
96         fprintf (stderr, "Unable to load a config from memory.\n");
97         goto bail;
98     }
99
100     if (!FcConfigSubstitute (cfg, pat, FcMatchPattern))
101     {
102         fprintf (stderr, "Unable to substitute config.\n");
103         goto bail;
104     }
105
106     result = FcPatternGetBool (pat, FC_TEST_RESULT, 0, &dummy);
107     switch (result) {
108     case FcResultMatch:
109         ret = TestMatch;
110         break;
111     case FcResultNoMatch:
112         ret = TestNoMatch;
113         break;
114     default:
115         fprintf (stderr, "Unable to check pattern.\n");
116         break;
117     }
118
119 bail:
120     if (cfg)
121         FcConfigDestroy (cfg);
122     if (xml)
123         FcStrFree (xml);
124     if (concat)
125         FcStrFree (concat);
126     if (pat)
127         FcPatternDestroy (pat);
128     return ret;
129 }
130
131 static TestResult
132 TestShouldMatchPattern(const char* test, FcPattern *pat, int negate)
133 {
134     switch (TestMatchPattern (test, pat)) {
135     case TestMatch:
136         if (!negate) {
137             return TestPassed;
138         }
139         else
140         {
141             printf ("Following test unexpectedly matched:\n%s", test);
142             printf ("on\n");
143             FcPatternPrint (pat);
144             return TestFailed;
145         }
146         break;
147     case TestNoMatch:
148         if (!negate) {
149             printf ("Following test should have matched:\n%s", test);
150             printf ("on\n");
151             FcPatternPrint (pat);
152             return TestFailed;
153         }
154         else
155         {
156             return TestPassed;
157         }
158         break;
159     case TestMatchError:
160         return TestError;
161         break;
162     default:
163         fprintf (stderr, "This shouldn't have been reached.\n");
164         return TestError;
165     }
166 }
167
168 #define MAX(a,b) ((a) > (b) ? (a) : (b))
169
170 static TestResult
171 UpdateResult (TestResult* res, TestResult resNew)
172 {
173     *res = MAX(*res, resNew);
174     return *res;
175 }
176
177 static TestResult
178 TestFamily (void)
179 {
180     const char *test;
181     TestResult res = TestPassed;
182
183     FcPattern *pat = FcPatternBuild (NULL,
184         FC_FAMILY, FcTypeString, "family1",
185         FC_FAMILY, FcTypeString, "family2",
186         FC_FAMILY, FcTypeString, "family3",
187         NULL);
188
189     if (!pat)
190     {
191         fprintf (stderr, "Unable to build pattern.\n");
192         return TestError;
193     }
194
195     #define SHOULD_MATCH(p,t) \
196         UpdateResult (&res, TestShouldMatchPattern (t, p, 0))
197     #define SHOULD_NOT_MATCH(p,t) \
198         UpdateResult (&res, TestShouldMatchPattern (t, p, 1))
199
200     test = "<test qual=\"all\" name=\"family\" compare=\"not_eq\">\n"
201            "    <string>foo</string>\n"
202            "</test>\n"
203            "";
204     SHOULD_MATCH(pat, test);
205
206     test = ""
207            "<test qual=\"all\" name=\"family\" compare=\"not_eq\">\n"
208            "    <string>family2</string>\n"
209            "</test>\n"
210            "";
211     SHOULD_NOT_MATCH(pat, test);
212
213     test = ""
214            "<test qual=\"any\" name=\"family\" compare=\"eq\">\n"
215            "    <string>family3</string>\n"
216            "</test>\n"
217            "";
218     SHOULD_MATCH(pat, test);
219
220     test = ""
221            "<test qual=\"any\" name=\"family\" compare=\"eq\">\n"
222            "    <string>foo</string>\n"
223            "</test>\n"
224            "";
225     SHOULD_NOT_MATCH(pat, test);
226
227     FcPatternDestroy (pat);
228     return res;
229 }
230
231 int
232 main (void)
233 {
234     return (TestFamily ());
235 }