From 03126350473f440e3bba416729091aae4a3f56ab Mon Sep 17 00:00:00 2001 From: Alan Coopersmith Date: Sun, 8 Feb 2015 10:42:51 -0800 Subject: Add some unit testing utilities The test/utils directory contains some standalone test programs for testing libXfont funtionality without needing a full X server session. They could be used to generate automated unit testing in the future, but that work has not yet been done. Signed-off-by: Alan Coopersmith --- Makefile.am | 2 +- configure.ac | 2 + test/Makefile.am | 2 + test/utils/Makefile.am | 35 ++++++++ test/utils/README | 18 ++++ test/utils/font-test-utils.c | 205 +++++++++++++++++++++++++++++++++++++++++++ test/utils/font-test-utils.h | 48 ++++++++++ test/utils/lsfontdir.c | 74 ++++++++++++++++ 8 files changed, 385 insertions(+), 1 deletion(-) create mode 100644 test/Makefile.am create mode 100644 test/utils/Makefile.am create mode 100644 test/utils/README create mode 100644 test/utils/font-test-utils.c create mode 100644 test/utils/font-test-utils.h create mode 100644 test/utils/lsfontdir.c diff --git a/Makefile.am b/Makefile.am index 7ec3188..8c9af56 100644 --- a/Makefile.am +++ b/Makefile.am @@ -19,7 +19,7 @@ # TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR # PERFORMANCE OF THIS SOFTWARE. -SUBDIRS=doc src +SUBDIRS=doc src test libXfontincludedir = $(includedir)/X11/fonts libXfontinclude_HEADERS = \ diff --git a/configure.ac b/configure.ac index 6f3a154..ea9c0e4 100644 --- a/configure.ac +++ b/configure.ac @@ -229,5 +229,7 @@ AC_CONFIG_FILES([Makefile src/fc/Makefile src/util/Makefile src/stubs/Makefile + test/Makefile + test/utils/Makefile xfont.pc]) AC_OUTPUT diff --git a/test/Makefile.am b/test/Makefile.am new file mode 100644 index 0000000..3357ac9 --- /dev/null +++ b/test/Makefile.am @@ -0,0 +1,2 @@ +# Tests for libXfont +SUBDIRS=utils diff --git a/test/utils/Makefile.am b/test/utils/Makefile.am new file mode 100644 index 0000000..03398b6 --- /dev/null +++ b/test/utils/Makefile.am @@ -0,0 +1,35 @@ +# +# Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. +# +# Permission is hereby granted, free of charge, to any person obtaining a +# copy of this software and associated documentation files (the "Software"), +# to deal in the Software without restriction, including without limitation +# the rights to use, copy, modify, merge, publish, distribute, sublicense, +# and/or sell copies of the Software, and to permit persons to whom the +# Software is furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice (including the next +# paragraph) shall be included in all copies or substantial portions of the +# Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +# DEALINGS IN THE SOFTWARE. +# + +noinst_PROGRAMS = lsfontdir + +EXTRA_DIST = README + +AM_CPPFLAGS = -I$(top_srcdir)/include +AM_CFLAGS = $(XFONT_CFLAGS) $(OS_CFLAGS) $(CWARNFLAGS) + +LDADD = $(top_builddir)/src/libXfont.la + +UTIL_SRCS = font-test-utils.c font-test-utils.h + +lsfontdir_SOURCES = lsfontdir.c $(UTIL_SRCS) diff --git a/test/utils/README b/test/utils/README new file mode 100644 index 0000000..ce093a4 --- /dev/null +++ b/test/utils/README @@ -0,0 +1,18 @@ +This directory contains utilities which can be used for adhoc testing of +libXfont by developers, and which are hoped to be useful for building up +automated testing in the future. + +They are not intended for distros to package and ship to end users - they +are not documented, and are full of assert() and fatal err() calls where +end user software would have error handling. + +No promises of interface stability are made for these - they may change at +any time to allow better testing. + +Utilities include: + +lsfontdir: + Reads & prints the contents of fonts.dir files. + Takes a list of font path entries on the command line, uses defaults + if none specified. + For use with afl fuzzer, you must use afl -f fonts.dir lsfontdir @@ diff --git a/test/utils/font-test-utils.c b/test/utils/font-test-utils.c new file mode 100644 index 0000000..bfe68da --- /dev/null +++ b/test/utils/font-test-utils.c @@ -0,0 +1,205 @@ +/* Common utility code for interacting with libXfont from test utilities + * + * Note that this code is designed for test programs, and thus uses assert() + * and fatal err() calls in places that real code would do error handling, + * since the goal is to catch bugs faster, not help users get past problems. + */ + +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +/* Based on code from xorg-server/dix/dixfont.c covered by this notice: + +Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +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 Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL 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 "font-test-utils.h" +#include +#include +#include +#include +#include + +static FPEFunctions *fpe_functions = NULL; +static int num_fpe_types = 0; + +/* Callback from libXfont when each fpe handler is registered */ +_X_EXPORT int +RegisterFPEFunctions(NameCheckFunc name_func, + InitFpeFunc init_func, + FreeFpeFunc free_func, + ResetFpeFunc reset_func, + OpenFontFunc open_func, + CloseFontFunc close_func, + ListFontsFunc list_func, + StartLfwiFunc start_lfwi_func, + NextLfwiFunc next_lfwi_func, + WakeupFpeFunc wakeup_func, + ClientDiedFunc client_died, + LoadGlyphsFunc load_glyphs, + StartLaFunc start_list_alias_func, + NextLaFunc next_list_alias_func, + SetPathFunc set_path_func) +{ + FPEFunctions *new; + + /* grow the list */ + new = realloc(fpe_functions, (num_fpe_types + 1) * sizeof(FPEFunctions)); + assert (new != NULL); + fpe_functions = new; + + fpe_functions[num_fpe_types].name_check = name_func; + fpe_functions[num_fpe_types].open_font = open_func; + fpe_functions[num_fpe_types].close_font = close_func; + fpe_functions[num_fpe_types].wakeup_fpe = wakeup_func; + fpe_functions[num_fpe_types].list_fonts = list_func; + fpe_functions[num_fpe_types].start_list_fonts_with_info = start_lfwi_func; + fpe_functions[num_fpe_types].list_next_font_with_info = next_lfwi_func; + fpe_functions[num_fpe_types].init_fpe = init_func; + fpe_functions[num_fpe_types].free_fpe = free_func; + fpe_functions[num_fpe_types].reset_fpe = reset_func; + fpe_functions[num_fpe_types].client_died = client_died; + fpe_functions[num_fpe_types].load_glyphs = load_glyphs; + fpe_functions[num_fpe_types].start_list_fonts_and_aliases = + start_list_alias_func; + fpe_functions[num_fpe_types].list_next_font_or_alias = next_list_alias_func; + fpe_functions[num_fpe_types].set_path_hook = set_path_func; + + return num_fpe_types++; +} + +FPEFunctions * +init_font_handlers(int *fpe_function_count) +{ + register_fpe_functions(); + /* make sure our callbacks were called & worked */ + assert (fpe_functions != NULL); + assert (num_fpe_types > 0); + *fpe_function_count = num_fpe_types; + return fpe_functions; +} + + +/* does the necessary magic to figure out the fpe type */ +static int +DetermineFPEType(const char *pathname) +{ + int i; + + /* make sure init_font_handlers was called first */ + assert (num_fpe_types > 0); + + for (i = 0; i < num_fpe_types; i++) { + if ((*fpe_functions[i].name_check) (pathname)) + return i; + } + return -1; +} + + +static const char * const default_fpes[] = { + "catalogue:/etc/X11/fontpath.d", + "built-ins" +}; +#define num_default_fpes (sizeof(default_fpes) / sizeof(*default_fpes)) + +FontPathElementPtr * +init_font_paths(const char * const *font_paths, int *num_fpes) +{ + FontPathElementPtr *fpe_list; + int i; + + /* make sure init_font_handlers was called first */ + assert (num_fpe_types > 0); + + /* Use default if caller didn't supply any */ + if (*num_fpes == 0) { + font_paths = default_fpes; + *num_fpes = num_default_fpes; + } + + fpe_list = calloc(*num_fpes, sizeof(FontPathElementPtr)); + assert(fpe_list != NULL); + + for (i = 0; i < *num_fpes; i++) { + int result; + FontPathElementPtr fpe = calloc(1, sizeof(FontPathElementRec)); + assert(fpe != NULL); + + fpe->name = strdup(font_paths[i]); + assert(fpe->name != NULL); + fpe->name_length = strlen(fpe->name); + assert(fpe->name_length > 0); + /* If path is to fonts.dir file, trim it off and use the full + directory path instead. Simplifies testing with afl. */ + if (fpe->name_length > sizeof("/fonts.dir")) { + char *tail = fpe->name + fpe->name_length - + (sizeof("/fonts.dir") - 1); + + if (strcmp(tail, "/fonts.dir") == 0) { + char *fullpath; + + *tail = '\0'; + fullpath = realpath(fpe->name, NULL); + assert(fullpath != NULL); + free(fpe->name); + fpe->name = fullpath; + fpe->name_length = strlen(fpe->name); + assert(fpe->name_length > 0); + } + } + fpe->type = DetermineFPEType(fpe->name); + if (fpe->type == -1) + err(BadFontPath, "Unable to find handler for font path %s", + fpe->name); + result = (*fpe_functions[fpe->type].init_fpe) (fpe); + if (result != Successful) + err(result, "init_fpe failed for font path %s: error %d", + fpe->name, result); + + printf("Initialized font path element #%d: %s\n", i, fpe->name); + fpe_list[i] = fpe; + } + printf("\n"); + + return fpe_list; +} diff --git a/test/utils/font-test-utils.h b/test/utils/font-test-utils.h new file mode 100644 index 0000000..4aa41fa --- /dev/null +++ b/test/utils/font-test-utils.h @@ -0,0 +1,48 @@ +/* Common utility code for interacting with libXfont from test utilities */ + +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include +#include +#include + +/* Returns pointer to array of functions for each type of font_path_entry + * handler, and puts count of entries in that array into fpe_function_count. + * Must be called before init_font_paths(). + */ +extern FPEFunctions *init_font_handlers(int *fpe_function_count); + +/* Returns pointer to array of FontPathElement structs for each font path + * entry passed in. num_fpes must be set to the number of entries in the + * font_paths array when called - will be set to the number of entries in + * the returned array. May be called with (NULL, 0) to use default font + * path of "catalogue:/etc/X11/fontpath.d" & "built-ins". + */ +extern FontPathElementPtr *init_font_paths(const char * const *font_paths, + int *num_fpes); diff --git a/test/utils/lsfontdir.c b/test/utils/lsfontdir.c new file mode 100644 index 0000000..c623c96 --- /dev/null +++ b/test/utils/lsfontdir.c @@ -0,0 +1,74 @@ +/* lsfontdir [ ...] + * + * Lists entries from fonts.dir file in given directory paths. + * Defaults to "catalogue:/etc/X11/fontpath.d" & "built-ins" if no paths given. + */ + +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#include "font-test-utils.h" +#include +#include +#include + +int +main(int argc, char **argv) +{ + FontPathElementPtr *fpe_list; + FPEFunctions *fpe_functions; + int fpe_function_count, fpe_list_count; + int i, n; + + fpe_functions = init_font_handlers(&fpe_function_count); + + fpe_list_count = argc - 1; + fpe_list = init_font_paths((const char **) argv + 1, &fpe_list_count); + + for (i = 0; i < fpe_list_count; i++) { + FontPathElementPtr fpe = fpe_list[i]; + FontNamesPtr names; + const int max_names_count = 8192; + const char *pattern = "*"; + int result; + + /* Don't allocate max size up front to allow testing expansion code */ + names = MakeFontNamesRecord(max_names_count / 16); + assert(names != NULL); + + result = (*fpe_functions[fpe->type].list_fonts) + (NULL, fpe, pattern, strlen(pattern), max_names_count, names); + if (result != Successful) + err(result, "list_font failed for font path %s: error %d", + fpe->name, result); + + printf("--- %s:\n", fpe->name); + for (n = 0 ; n < names->nnames; n++) { + printf("%s\n", names->names[n]); + } + + FreeFontNames(names); + } + + return 0; +} -- cgit v1.2.3