Blame test/test-conf.c

Packit 352660
/*
Packit 352660
 * fontconfig/test/test-conf.c
Packit 352660
 *
Packit 352660
 * Copyright © 2000 Keith Packard
Packit 352660
 * Copyright © 2018 Akira TAGOH
Packit 352660
 *
Packit 352660
 * Permission to use, copy, modify, distribute, and sell this software and its
Packit 352660
 * documentation for any purpose is hereby granted without fee, provided that
Packit 352660
 * the above copyright notice appear in all copies and that both that
Packit 352660
 * copyright notice and this permission notice appear in supporting
Packit 352660
 * documentation, and that the name of the author(s) not be used in
Packit 352660
 * advertising or publicity pertaining to distribution of the software without
Packit 352660
 * specific, written prior permission.  The authors make no
Packit 352660
 * representations about the suitability of this software for any purpose.  It
Packit 352660
 * is provided "as is" without express or implied warranty.
Packit 352660
 *
Packit 352660
 * THE AUTHOR(S) DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
Packit 352660
 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
Packit 352660
 * EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY SPECIAL, INDIRECT OR
Packit 352660
 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
Packit 352660
 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
Packit 352660
 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
Packit 352660
 * PERFORMANCE OF THIS SOFTWARE.
Packit 352660
 */
Packit 352660
#include <stdio.h>
Packit 352660
#include <string.h>
Packit 352660
#include <fontconfig/fontconfig.h>
Packit 352660
#include <json.h>
Packit 352660
Packit 352660
struct _FcConfig {
Packit 352660
    FcStrSet	*configDirs;	    /* directories to scan for fonts */
Packit 352660
    FcStrSet	*fontDirs;
Packit 352660
    FcStrSet	*cacheDirs;
Packit 352660
    FcStrSet	*configFiles;	    /* config files loaded */
Packit 352660
    void	*subst[FcMatchKindEnd];
Packit 352660
    int		maxObjects;	    /* maximum number of tests in all substs */
Packit 352660
    FcStrSet	*acceptGlobs;
Packit 352660
    FcStrSet	*rejectGlobs;
Packit 352660
    FcFontSet	*acceptPatterns;
Packit 352660
    FcFontSet	*rejectPatterns;
Packit 352660
    FcFontSet	*fonts[FcSetApplication + 1];
Packit 352660
};
Packit 352660
Packit 352660
static FcPattern *
Packit 352660
build_pattern (json_object *obj)
Packit 352660
{
Packit 352660
    json_object_iter iter;
Packit 352660
    FcPattern *pat = FcPatternCreate ();
Packit 352660
Packit 352660
    json_object_object_foreachC (obj, iter)
Packit 352660
    {
Packit 352660
	FcValue v;
Packit 352660
Packit 352660
	if (json_object_get_type (iter.val) == json_type_boolean)
Packit 352660
	{
Packit 352660
	    v.type = FcTypeBool;
Packit 352660
	    v.u.b = json_object_get_boolean (iter.val);
Packit 352660
	}
Packit 352660
	else if (json_object_get_type (iter.val) == json_type_double)
Packit 352660
	{
Packit 352660
	    v.type = FcTypeDouble;
Packit 352660
	    v.u.d = json_object_get_double (iter.val);
Packit 352660
	}
Packit 352660
	else if (json_object_get_type (iter.val) == json_type_int)
Packit 352660
	{
Packit 352660
	    v.type = FcTypeInteger;
Packit 352660
	    v.u.i = json_object_get_int (iter.val);
Packit 352660
	}
Packit 352660
	else if (json_object_get_type (iter.val) == json_type_string)
Packit 352660
	{
Packit 352660
	    v.type = FcTypeString;
Packit 352660
	    v.u.s = json_object_get_string (iter.val);
Packit 352660
	}
Packit 352660
	else if (json_object_get_type (iter.val) == json_type_null)
Packit 352660
	{
Packit 352660
	    v.type = FcTypeVoid;
Packit 352660
	}
Packit 352660
	else
Packit 352660
	{
Packit 352660
	    fprintf (stderr, "W: unexpected object to build a pattern: (%s %s)", iter.key, json_type_to_name (json_object_get_type (iter.val)));
Packit 352660
	    continue;
Packit 352660
	}
Packit 352660
	FcPatternAdd (pat, iter.key, v, FcTrue);
Packit 352660
    }
Packit 352660
    return pat;
Packit 352660
}
Packit 352660
Packit 352660
static FcBool
Packit 352660
build_fonts (FcConfig *config, json_object *root)
Packit 352660
{
Packit 352660
    json_object *fonts;
Packit 352660
    FcFontSet *fs;
Packit 352660
    int i, n;
Packit 352660
Packit 352660
    if (!json_object_object_get_ex (root, "fonts", &fonts) ||
Packit 352660
	json_object_get_type (fonts) != json_type_array)
Packit 352660
    {
Packit 352660
	fprintf (stderr, "W: No fonts defined\n");
Packit 352660
	return FcFalse;
Packit 352660
    }
Packit 352660
    fs = FcFontSetCreate ();
Packit 352660
    n = json_object_array_length (fonts);
Packit 352660
    for (i = 0; i < n; i++)
Packit 352660
    {
Packit 352660
	json_object *obj = json_object_array_get_idx (fonts, i);
Packit 352660
	FcPattern *pat;
Packit 352660
Packit 352660
	if (json_object_get_type (obj) != json_type_object)
Packit 352660
	    continue;
Packit 352660
	pat = build_pattern (obj);
Packit 352660
	FcFontSetAdd (fs, pat);
Packit 352660
    }
Packit 352660
    /* FcConfigSetFonts (config, fs, FcSetSystem); */
Packit 352660
    if (config->fonts[FcSetSystem])
Packit 352660
	FcFontSetDestroy (config->fonts[FcSetSystem]);
Packit 352660
    config->fonts[FcSetSystem] = fs;
Packit 352660
Packit 352660
    return FcTrue;
Packit 352660
}
Packit 352660
Packit 352660
static FcBool
Packit 352660
run_test (FcConfig *config, json_object *root)
Packit 352660
{
Packit 352660
    json_object *tests;
Packit 352660
    FcFontSet *fs;
Packit 352660
    int i, n, fail = 0;
Packit 352660
Packit 352660
    if (!json_object_object_get_ex (root, "tests", &tests) ||
Packit 352660
	json_object_get_type (tests) != json_type_array)
Packit 352660
    {
Packit 352660
	fprintf (stderr, "W: No test cases defined\n");
Packit 352660
	return FcFalse;
Packit 352660
    }
Packit 352660
    fs = FcFontSetCreate ();
Packit 352660
    n = json_object_array_length (tests);
Packit 352660
    for (i = 0; i < n; i++)
Packit 352660
    {
Packit 352660
	json_object *obj = json_object_array_get_idx (tests, i);
Packit 352660
	json_object_iter iter;
Packit 352660
	FcPattern *query, *result;
Packit 352660
	const char *method;
Packit 352660
Packit 352660
	if (json_object_get_type (obj) != json_type_object)
Packit 352660
	    continue;
Packit 352660
	json_object_object_foreachC (obj, iter)
Packit 352660
	{
Packit 352660
	    if (strcmp (iter.key, "method") == 0)
Packit 352660
	    {
Packit 352660
		if (json_object_get_type (iter.val) != json_type_string)
Packit 352660
		{
Packit 352660
		    fprintf (stderr, "W: invalid type of method: (%s)\n", json_type_to_name (json_object_get_type (iter.val)));
Packit 352660
		    continue;
Packit 352660
		}
Packit 352660
		method = json_object_get_string (iter.val);
Packit 352660
	    }
Packit 352660
	    else if (strcmp (iter.key, "query") == 0)
Packit 352660
	    {
Packit 352660
		if (json_object_get_type (iter.val) != json_type_object)
Packit 352660
		{
Packit 352660
		    fprintf (stderr, "W: invalid type of query: (%s)\n", json_type_to_name (json_object_get_type (iter.val)));
Packit 352660
		    continue;
Packit 352660
		}
Packit 352660
		query = build_pattern (iter.val);
Packit 352660
	    }
Packit 352660
	    else if (strcmp (iter.key, "result") == 0)
Packit 352660
	    {
Packit 352660
		if (json_object_get_type (iter.val) != json_type_object)
Packit 352660
		{
Packit 352660
		    fprintf (stderr, "W: invalid type of result: (%s)\n", json_type_to_name (json_object_get_type (iter.val)));
Packit 352660
		    continue;
Packit 352660
		}
Packit 352660
		result = build_pattern (iter.val);
Packit 352660
	    }
Packit 352660
	    else
Packit 352660
	    {
Packit 352660
		fprintf (stderr, "W: unknown object: %s\n", iter.key);
Packit 352660
	    }
Packit 352660
	}
Packit 352660
	if (strcmp (method, "match") == 0)
Packit 352660
	{
Packit 352660
	    FcPattern *match;
Packit 352660
	    FcResult res;
Packit 352660
Packit 352660
	    FcConfigSubstitute (config, query, FcMatchPattern);
Packit 352660
	    FcDefaultSubstitute (query);
Packit 352660
	    match = FcFontMatch (config, query, &res;;
Packit 352660
	    if (match)
Packit 352660
	    {
Packit 352660
		FcPatternIter iter;
Packit 352660
		int x, vc;
Packit 352660
Packit 352660
		FcPatternIterStart (result, &iter);
Packit 352660
		do
Packit 352660
		{
Packit 352660
		    vc = FcPatternIterValueCount (result, &iter);
Packit 352660
		    for (x = 0; x < vc; x++)
Packit 352660
		    {
Packit 352660
			FcValue vr, vm;
Packit 352660
Packit 352660
			if (FcPatternIterGetValue (result, &iter, x, &vr, NULL) != FcResultMatch)
Packit 352660
			{
Packit 352660
			    fprintf (stderr, "E: unable to obtain a value from the expected result\n");
Packit 352660
			    fail++;
Packit 352660
			    goto bail;
Packit 352660
			}
Packit 352660
			if (FcPatternGet (match, FcPatternIterGetObject (result, &iter), x, &vm) != FcResultMatch)
Packit 352660
			{
Packit 352660
			    vm.type = FcTypeVoid;
Packit 352660
			}
Packit 352660
			if (!FcValueEqual (vm, vr))
Packit 352660
			{
Packit 352660
			    printf ("E: failed to compare %s:\n", FcPatternIterGetObject (result, &iter));
Packit 352660
			    printf ("   actual result:");
Packit 352660
			    FcValuePrint (vm);
Packit 352660
			    printf ("\n   expected result:");
Packit 352660
			    FcValuePrint (vr);
Packit 352660
			    printf ("\n");
Packit 352660
			    fail++;
Packit 352660
			    goto bail;
Packit 352660
			}
Packit 352660
		    }
Packit 352660
		} while (FcPatternIterNext (result, &iter));
Packit 352660
	    bail:;
Packit 352660
	    }
Packit 352660
	    else
Packit 352660
	    {
Packit 352660
		fprintf (stderr, "E: no match\n");
Packit 352660
		fail++;
Packit 352660
	    }
Packit 352660
	}
Packit 352660
	else
Packit 352660
	{
Packit 352660
	    fprintf (stderr, "W: unknown testing method: %s\n", method);
Packit 352660
	}
Packit 352660
    }
Packit 352660
Packit 352660
    return fail == 0;
Packit 352660
}
Packit 352660
Packit 352660
static FcBool
Packit 352660
run_scenario (FcConfig *config, char *file)
Packit 352660
{
Packit 352660
    FcBool ret = FcTrue;
Packit 352660
    json_object *root, *scenario;
Packit 352660
Packit 352660
    root = json_object_from_file (file);
Packit 352660
    if (!root)
Packit 352660
    {
Packit 352660
	fprintf (stderr, "E: Unable to read the file: %s\n", file);
Packit 352660
	return FcFalse;
Packit 352660
    }
Packit 352660
    if (!build_fonts (config, root))
Packit 352660
    {
Packit 352660
	ret = FcFalse;
Packit 352660
	goto bail1;
Packit 352660
    }
Packit 352660
    if (!run_test (config, root))
Packit 352660
    {
Packit 352660
	ret = FcFalse;
Packit 352660
	goto bail1;
Packit 352660
    }
Packit 352660
Packit 352660
bail1:
Packit 352660
    json_object_put (root);
Packit 352660
Packit 352660
    return ret;
Packit 352660
}
Packit 352660
Packit 352660
static FcBool
Packit 352660
load_config (FcConfig *config, char *file)
Packit 352660
{
Packit 352660
    FILE *fp;
Packit 352660
    long len;
Packit 352660
    char *buf = NULL;
Packit 352660
    FcBool ret = FcTrue;
Packit 352660
Packit 352660
    if ((fp = fopen(file, "rb")) == NULL)
Packit 352660
	return FcFalse;
Packit 352660
    fseek (fp, 0L, SEEK_END);
Packit 352660
    len = ftell (fp);
Packit 352660
    fseek (fp, 0L, SEEK_SET);
Packit 352660
    buf = malloc (sizeof (char) * (len + 1));
Packit 352660
    if (!buf)
Packit 352660
    {
Packit 352660
	ret = FcFalse;
Packit 352660
	goto bail1;
Packit 352660
    }
Packit 352660
    fread (buf, (size_t)len, sizeof (char), fp);
Packit 352660
    buf[len] = 0;
Packit 352660
Packit 352660
    ret = FcConfigParseAndLoadFromMemory (config, buf, FcTrue);
Packit 352660
bail1:
Packit 352660
    fclose (fp);
Packit 352660
    if (buf)
Packit 352660
	free (buf);
Packit 352660
Packit 352660
    return ret;
Packit 352660
}
Packit 352660
Packit 352660
int
Packit 352660
main (int argc, char **argv)
Packit 352660
{
Packit 352660
    FcConfig *config;
Packit 352660
    int retval = 0;
Packit 352660
Packit 352660
    if (argc < 3)
Packit 352660
    {
Packit 352660
	fprintf(stderr, "Usage: %s <conf file> <test scenario>\n", argv[0]);
Packit 352660
	return 1;
Packit 352660
    }
Packit 352660
Packit 352660
    config = FcConfigCreate ();
Packit 352660
    if (!load_config (config, argv[1]))
Packit 352660
    {
Packit 352660
	fprintf(stderr, "E: Failed to load config\n");
Packit 352660
	retval = 1;
Packit 352660
	goto bail1;
Packit 352660
    }
Packit 352660
    if (!run_scenario (config, argv[2]))
Packit 352660
    {
Packit 352660
	retval = 1;
Packit 352660
	goto bail1;
Packit 352660
    }
Packit 352660
bail1:
Packit 352660
    FcConfigDestroy (config);
Packit 352660
Packit 352660
    return retval;
Packit 352660
}