summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSzunti <Szunti@users.noreply.github.com>2020-12-06 12:52:44 +0100
committerAkira TAGOH <akira@tagoh.org>2020-12-17 04:51:20 +0000
commitdf29933e1a06b7aa7af229bd7cd03c62d957f15f (patch)
tree333cc1d0e3f66ed50a0f5754f21bb1199510b1ca
parent921ede9f460fb661146182809557a1da2dd7afd7 (diff)
Check qual and compare for family tests
Fixes #267. Hash table lookups assumed qual="any" compare="eq". Add a test too.
-rw-r--r--src/fccfg.c16
-rw-r--r--test/Makefile.am4
-rw-r--r--test/meson.build1
-rw-r--r--test/test-family-matching.c228
4 files changed, 248 insertions, 1 deletions
diff --git a/src/fccfg.c b/src/fccfg.c
index 7b857bf..00a94e5 100644
--- a/src/fccfg.c
+++ b/src/fccfg.c
@@ -1714,6 +1714,7 @@ FcConfigMatchValueList (FcPattern *p,
FcExpr *e = t->expr;
FcValue value;
FcValueList *v;
+ FcOp op;
while (e)
{
@@ -1731,10 +1732,23 @@ FcConfigMatchValueList (FcPattern *p,
if (t->object == FC_FAMILY_OBJECT && table)
{
- if (!FamilyTableLookup (table, t->op, FcValueString (&value)))
+ op = FC_OP_GET_OP (t->op);
+ if (op == FcOpEqual || op == FcOpListing)
{
+ if (!FamilyTableLookup (table, t->op, FcValueString (&value)))
+ {
ret = 0;
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))
diff --git a/test/Makefile.am b/test/Makefile.am
index 1a9b293..30d8c2a 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -167,6 +167,10 @@ check_PROGRAMS += test-issue180
test_issue180_LDADD = $(top_builddir)/src/libfontconfig.la
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
CLEANFILES = \
diff --git a/test/meson.build b/test/meson.build
index 96b30a9..59de427 100644
--- a/test/meson.build
+++ b/test/meson.build
@@ -6,6 +6,7 @@ tests = [
['test-bz106618.c'],
['test-bz1744377.c'],
['test-issue180.c'],
+ ['test-family-matching.c'],
]
if host_machine.system() != 'windows'
diff --git a/test/test-family-matching.c b/test/test-family-matching.c
new file mode 100644
index 0000000..9fab36c
--- /dev/null
+++ b/test/test-family-matching.c
@@ -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 ());
+}