Check qual and compare for family tests
Fixes #267. Hash table lookups assumed qual="any" compare="eq". Add a test too.
This commit is contained in:
parent
921ede9f46
commit
df29933e1a
14
src/fccfg.c
14
src/fccfg.c
|
@ -1714,6 +1714,7 @@ FcConfigMatchValueList (FcPattern *p,
|
||||||
FcExpr *e = t->expr;
|
FcExpr *e = t->expr;
|
||||||
FcValue value;
|
FcValue value;
|
||||||
FcValueList *v;
|
FcValueList *v;
|
||||||
|
FcOp op;
|
||||||
|
|
||||||
while (e)
|
while (e)
|
||||||
{
|
{
|
||||||
|
@ -1730,6 +1731,9 @@ FcConfigMatchValueList (FcPattern *p,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (t->object == FC_FAMILY_OBJECT && table)
|
if (t->object == FC_FAMILY_OBJECT && table)
|
||||||
|
{
|
||||||
|
op = FC_OP_GET_OP (t->op);
|
||||||
|
if (op == FcOpEqual || op == FcOpListing)
|
||||||
{
|
{
|
||||||
if (!FamilyTableLookup (table, t->op, FcValueString (&value)))
|
if (!FamilyTableLookup (table, t->op, FcValueString (&value)))
|
||||||
{
|
{
|
||||||
|
@ -1737,6 +1741,16 @@ FcConfigMatchValueList (FcPattern *p,
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (op == FcOpNotEqual && t->qual == FcQualAll)
|
||||||
|
{
|
||||||
|
ret = 0;
|
||||||
|
if (!FamilyTableLookup (table, t->op, FcValueString (&value)))
|
||||||
|
{
|
||||||
|
ret = values;
|
||||||
|
}
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
}
|
||||||
for (v = values; v; v = FcValueListNext(v))
|
for (v = values; v; v = FcValueListNext(v))
|
||||||
{
|
{
|
||||||
/* Compare the pattern value to the match expression value */
|
/* Compare the pattern value to the match expression value */
|
||||||
|
|
|
@ -167,6 +167,10 @@ check_PROGRAMS += test-issue180
|
||||||
test_issue180_LDADD = $(top_builddir)/src/libfontconfig.la
|
test_issue180_LDADD = $(top_builddir)/src/libfontconfig.la
|
||||||
TESTS += test-issue180
|
TESTS += test-issue180
|
||||||
|
|
||||||
|
check_PROGRAMS += test-family-matching
|
||||||
|
test_family_matching_LDADD = $(top_builddir)/src/libfontconfig.la
|
||||||
|
TESTS += test-family-matching
|
||||||
|
|
||||||
EXTRA_DIST=run-test.sh run-test-conf.sh $(LOG_COMPILER) $(TESTDATA) out.expected-long-family-names out.expected-no-long-family-names
|
EXTRA_DIST=run-test.sh run-test-conf.sh $(LOG_COMPILER) $(TESTDATA) out.expected-long-family-names out.expected-no-long-family-names
|
||||||
|
|
||||||
CLEANFILES = \
|
CLEANFILES = \
|
||||||
|
|
|
@ -6,6 +6,7 @@ tests = [
|
||||||
['test-bz106618.c'],
|
['test-bz106618.c'],
|
||||||
['test-bz1744377.c'],
|
['test-bz1744377.c'],
|
||||||
['test-issue180.c'],
|
['test-issue180.c'],
|
||||||
|
['test-family-matching.c'],
|
||||||
]
|
]
|
||||||
|
|
||||||
if host_machine.system() != 'windows'
|
if host_machine.system() != 'windows'
|
||||||
|
|
|
@ -0,0 +1,228 @@
|
||||||
|
/*
|
||||||
|
* fontconfig/test/test-family-matching.c
|
||||||
|
*
|
||||||
|
* Copyright © 2020 Zoltan Vandrus
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, distribute, and sell this software and its
|
||||||
|
* documentation for any purpose is hereby granted without fee, provided that
|
||||||
|
* the above copyright notice appear in all copies and that both that
|
||||||
|
* copyright notice and this permission notice appear in supporting
|
||||||
|
* documentation, and that the name of the author(s) not be used in
|
||||||
|
* advertising or publicity pertaining to distribution of the software without
|
||||||
|
* specific, written prior permission. The authors make no
|
||||||
|
* representations about the suitability of this software for any purpose. It
|
||||||
|
* is provided "as is" without express or implied warranty.
|
||||||
|
*
|
||||||
|
* THE AUTHOR(S) DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
||||||
|
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
|
||||||
|
* EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
||||||
|
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
|
||||||
|
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||||
|
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||||
|
* PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <fontconfig/fontconfig.h>
|
||||||
|
|
||||||
|
#define FC_TEST_RESULT "testresult"
|
||||||
|
|
||||||
|
typedef enum _TestMatchResult {
|
||||||
|
TestMatch,
|
||||||
|
TestNoMatch,
|
||||||
|
TestMatchError
|
||||||
|
} TestMatchResult;
|
||||||
|
|
||||||
|
typedef enum _TestResult {
|
||||||
|
TestPassed,
|
||||||
|
TestFailed,
|
||||||
|
TestError
|
||||||
|
} TestResult;
|
||||||
|
|
||||||
|
static TestMatchResult
|
||||||
|
TestMatchPattern (const char *test, FcPattern *p)
|
||||||
|
{
|
||||||
|
const FcChar8 *xml_pre = (const FcChar8 *) ""
|
||||||
|
"<fontconfig>\n"
|
||||||
|
" <match>\n"
|
||||||
|
"";
|
||||||
|
|
||||||
|
const FcChar8 *xml_post = (const FcChar8 *) ""
|
||||||
|
" <edit name=\""FC_TEST_RESULT"\">\n"
|
||||||
|
" <bool>true</bool>\n"
|
||||||
|
" </edit>\n"
|
||||||
|
" </match>\n"
|
||||||
|
"</fontconfig>\n"
|
||||||
|
"";
|
||||||
|
|
||||||
|
FcChar8 *xml, *concat;
|
||||||
|
FcConfig *cfg;
|
||||||
|
FcResult result;
|
||||||
|
FcBool dummy;
|
||||||
|
TestResult ret = TestMatchError;
|
||||||
|
|
||||||
|
FcPattern *pat = FcPatternDuplicate (p);
|
||||||
|
if (!pat)
|
||||||
|
{
|
||||||
|
fprintf (stderr, "Unable to duplicate pattern.\n");
|
||||||
|
goto bail0;
|
||||||
|
}
|
||||||
|
|
||||||
|
concat = FcStrPlus (xml_pre, (const FcChar8 *) test);
|
||||||
|
if (!concat)
|
||||||
|
{
|
||||||
|
fprintf (stderr, "Concatenation failed.\n");
|
||||||
|
goto bail0;
|
||||||
|
}
|
||||||
|
|
||||||
|
xml = FcStrPlus (concat, xml_post);
|
||||||
|
FcStrFree (concat);
|
||||||
|
if (!xml)
|
||||||
|
{
|
||||||
|
fprintf (stderr, "Concatenation failed.\n");
|
||||||
|
goto bail0;
|
||||||
|
}
|
||||||
|
|
||||||
|
cfg = FcConfigCreate ();
|
||||||
|
if (!cfg)
|
||||||
|
{
|
||||||
|
fprintf (stderr, "Unable to create a new empty config.\n");
|
||||||
|
return TestMatchError;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!FcConfigParseAndLoadFromMemory (cfg, xml, FcTrue))
|
||||||
|
{
|
||||||
|
fprintf (stderr, "Unable to load a config from memory.\n");
|
||||||
|
goto bail1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!FcConfigSubstitute (cfg, pat, FcMatchPattern))
|
||||||
|
{
|
||||||
|
fprintf (stderr, "Unable to substitute config.\n");
|
||||||
|
goto bail1;
|
||||||
|
}
|
||||||
|
|
||||||
|
result = FcPatternGetBool (pat, FC_TEST_RESULT, 0, &dummy);
|
||||||
|
switch (result) {
|
||||||
|
case FcResultMatch:
|
||||||
|
ret = TestMatch;
|
||||||
|
break;
|
||||||
|
case FcResultNoMatch:
|
||||||
|
ret = TestNoMatch;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
fprintf (stderr, "Unable to check pattern.\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
bail1:
|
||||||
|
FcConfigDestroy (cfg);
|
||||||
|
bail0:
|
||||||
|
FcPatternDestroy (pat);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static TestResult
|
||||||
|
TestShouldMatchPattern(const char* test, FcPattern *pat, int negate)
|
||||||
|
{
|
||||||
|
switch (TestMatchPattern (test, pat)) {
|
||||||
|
case TestMatch:
|
||||||
|
if (!negate) {
|
||||||
|
return TestPassed;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printf ("Following test unexpectedly matched:\n%s", test);
|
||||||
|
printf ("on\n");
|
||||||
|
FcPatternPrint (pat);
|
||||||
|
return TestFailed;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case TestNoMatch:
|
||||||
|
if (!negate) {
|
||||||
|
printf ("Following test should have matched:\n%s", test);
|
||||||
|
printf ("on\n");
|
||||||
|
FcPatternPrint (pat);
|
||||||
|
return TestFailed;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return TestPassed;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case TestMatchError:
|
||||||
|
return TestError;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
fprintf (stderr, "This shouldn't have been reached.\n");
|
||||||
|
return TestError;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#define MAX(a,b) ((a) > (b) ? (a) : (b))
|
||||||
|
|
||||||
|
static TestResult
|
||||||
|
UpdateResult (TestResult* res, TestResult resNew)
|
||||||
|
{
|
||||||
|
*res = MAX(*res, resNew);
|
||||||
|
return *res;
|
||||||
|
}
|
||||||
|
|
||||||
|
static TestResult
|
||||||
|
TestFamily (void)
|
||||||
|
{
|
||||||
|
const char *test;
|
||||||
|
TestResult res = TestPassed;
|
||||||
|
|
||||||
|
FcPattern *pat = FcPatternBuild (NULL,
|
||||||
|
FC_FAMILY, FcTypeString, "family1",
|
||||||
|
FC_FAMILY, FcTypeString, "family2",
|
||||||
|
FC_FAMILY, FcTypeString, "family3",
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
if (!pat)
|
||||||
|
{
|
||||||
|
fprintf (stderr, "Unable to build pattern.\n");
|
||||||
|
return TestError;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define SHOULD_MATCH(p,t) \
|
||||||
|
UpdateResult (&res, TestShouldMatchPattern (t, p, 0))
|
||||||
|
#define SHOULD_NOT_MATCH(p,t) \
|
||||||
|
UpdateResult (&res, TestShouldMatchPattern (t, p, 1))
|
||||||
|
|
||||||
|
test = "<test qual=\"all\" name=\"family\" compare=\"not_eq\">\n"
|
||||||
|
" <string>foo</string>\n"
|
||||||
|
"</test>\n"
|
||||||
|
"";
|
||||||
|
SHOULD_MATCH(pat, test);
|
||||||
|
|
||||||
|
test = ""
|
||||||
|
"<test qual=\"all\" name=\"family\" compare=\"not_eq\">\n"
|
||||||
|
" <string>family2</string>\n"
|
||||||
|
"</test>\n"
|
||||||
|
"";
|
||||||
|
SHOULD_NOT_MATCH(pat, test);
|
||||||
|
|
||||||
|
test = ""
|
||||||
|
"<test qual=\"any\" name=\"family\" compare=\"eq\">\n"
|
||||||
|
" <string>family3</string>\n"
|
||||||
|
"</test>\n"
|
||||||
|
"";
|
||||||
|
SHOULD_MATCH(pat, test);
|
||||||
|
|
||||||
|
test = ""
|
||||||
|
"<test qual=\"any\" name=\"family\" compare=\"eq\">\n"
|
||||||
|
" <string>foo</string>\n"
|
||||||
|
"</test>\n"
|
||||||
|
"";
|
||||||
|
SHOULD_NOT_MATCH(pat, test);
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
main (void)
|
||||||
|
{
|
||||||
|
return (TestFamily ());
|
||||||
|
}
|
Loading…
Reference in New Issue