diff options
Diffstat (limited to 'test')
29 files changed, 6611 insertions, 0 deletions
diff --git a/test/Makefile.am b/test/Makefile.am new file mode 100644 index 0000000..16a3cd2 --- /dev/null +++ b/test/Makefile.am @@ -0,0 +1,5 @@ +# Process this file with automake to produce Makefile.in + +SUBDIRS = api shaping + +-include $(top_srcdir)/git.mk diff --git a/test/Makefile.in b/test/Makefile.in new file mode 100644 index 0000000..dee13f6 --- /dev/null +++ b/test/Makefile.in @@ -0,0 +1,593 @@ +# Makefile.in generated by automake 1.11.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, +# Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +# Process this file with automake to produce Makefile.in +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = test +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +AM_V_GEN = $(am__v_GEN_$(V)) +am__v_GEN_ = $(am__v_GEN_$(AM_DEFAULT_VERBOSITY)) +am__v_GEN_0 = @echo " GEN " $@; +AM_V_at = $(am__v_at_$(V)) +am__v_at_ = $(am__v_at_$(AM_DEFAULT_VERBOSITY)) +am__v_at_0 = @ +SOURCES = +DIST_SOURCES = +RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \ + html-recursive info-recursive install-data-recursive \ + install-dvi-recursive install-exec-recursive \ + install-html-recursive install-info-recursive \ + install-pdf-recursive install-ps-recursive install-recursive \ + installcheck-recursive installdirs-recursive pdf-recursive \ + ps-recursive uninstall-recursive +RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ + distclean-recursive maintainer-clean-recursive +AM_RECURSIVE_TARGETS = $(RECURSIVE_TARGETS:-recursive=) \ + $(RECURSIVE_CLEAN_TARGETS:-recursive=) tags TAGS ctags CTAGS \ + distdir +ETAGS = etags +CTAGS = ctags +DIST_SUBDIRS = $(SUBDIRS) +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +am__relativize = \ + dir0=`pwd`; \ + sed_first='s,^\([^/]*\)/.*$$,\1,'; \ + sed_rest='s,^[^/]*/*,,'; \ + sed_last='s,^.*/\([^/]*\)$$,\1,'; \ + sed_butlast='s,/*[^/]*$$,,'; \ + while test -n "$$dir1"; do \ + first=`echo "$$dir1" | sed -e "$$sed_first"`; \ + if test "$$first" != "."; then \ + if test "$$first" = ".."; then \ + dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ + dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ + else \ + first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ + if test "$$first2" = "$$first"; then \ + dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ + else \ + dir2="../$$dir2"; \ + fi; \ + dir0="$$dir0"/"$$first"; \ + fi; \ + fi; \ + dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ + done; \ + reldir="$$dir2" +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CAIRO_CFLAGS = @CAIRO_CFLAGS@ +CAIRO_FT_CFLAGS = @CAIRO_FT_CFLAGS@ +CAIRO_FT_LIBS = @CAIRO_FT_LIBS@ +CAIRO_LIBS = @CAIRO_LIBS@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CORETEXT_CFLAGS = @CORETEXT_CFLAGS@ +CORETEXT_LIBS = @CORETEXT_LIBS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +FREETYPE_CFLAGS = @FREETYPE_CFLAGS@ +FREETYPE_LIBS = @FREETYPE_LIBS@ +GLIB_CFLAGS = @GLIB_CFLAGS@ +GLIB_LIBS = @GLIB_LIBS@ +GLIB_MKENUMS = @GLIB_MKENUMS@ +GOBJECT_CFLAGS = @GOBJECT_CFLAGS@ +GOBJECT_LIBS = @GOBJECT_LIBS@ +GRAPHITE2_CFLAGS = @GRAPHITE2_CFLAGS@ +GRAPHITE2_LIBS = @GRAPHITE2_LIBS@ +GREP = @GREP@ +GTHREAD_CFLAGS = @GTHREAD_CFLAGS@ +GTHREAD_LIBS = @GTHREAD_LIBS@ +HB_LIBTOOL_VERSION_INFO = @HB_LIBTOOL_VERSION_INFO@ +HB_VERSION = @HB_VERSION@ +HB_VERSION_MAJOR = @HB_VERSION_MAJOR@ +HB_VERSION_MICRO = @HB_VERSION_MICRO@ +HB_VERSION_MINOR = @HB_VERSION_MINOR@ +ICU_CFLAGS = @ICU_CFLAGS@ +ICU_LIBS = @ICU_LIBS@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PKG_CONFIG = @PKG_CONFIG@ +RANLIB = @RANLIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +UNISCRIBE_CFLAGS = @UNISCRIBE_CFLAGS@ +UNISCRIBE_LIBS = @UNISCRIBE_LIBS@ +VERSION = @VERSION@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +lt_ECHO = @lt_ECHO@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +SUBDIRS = api shaping +all: all-recursive + +.SUFFIXES: +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnits test/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnits test/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +# This directory's subdirectories are mostly independent; you can cd +# into them and run `make' without going through this Makefile. +# To change the values of `make' variables: instead of editing Makefiles, +# (1) if the variable is set in `config.status', edit `config.status' +# (which will cause the Makefiles to be regenerated when you run `make'); +# (2) otherwise, pass the desired values on the `make' command line. +$(RECURSIVE_TARGETS): + @fail= failcom='exit 1'; \ + for f in x $$MAKEFLAGS; do \ + case $$f in \ + *=* | --[!k]*);; \ + *k*) failcom='fail=yes';; \ + esac; \ + done; \ + dot_seen=no; \ + target=`echo $@ | sed s/-recursive//`; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + dot_seen=yes; \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done; \ + if test "$$dot_seen" = "no"; then \ + $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ + fi; test -z "$$fail" + +$(RECURSIVE_CLEAN_TARGETS): + @fail= failcom='exit 1'; \ + for f in x $$MAKEFLAGS; do \ + case $$f in \ + *=* | --[!k]*);; \ + *k*) failcom='fail=yes';; \ + esac; \ + done; \ + dot_seen=no; \ + case "$@" in \ + distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ + *) list='$(SUBDIRS)' ;; \ + esac; \ + rev=''; for subdir in $$list; do \ + if test "$$subdir" = "."; then :; else \ + rev="$$subdir $$rev"; \ + fi; \ + done; \ + rev="$$rev ."; \ + target=`echo $@ | sed s/-recursive//`; \ + for subdir in $$rev; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done && test -z "$$fail" +tags-recursive: + list='$(SUBDIRS)'; for subdir in $$list; do \ + test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \ + done +ctags-recursive: + list='$(SUBDIRS)'; for subdir in $$list; do \ + test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \ + done + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + set x; \ + here=`pwd`; \ + if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ + include_option=--etags-include; \ + empty_fix=.; \ + else \ + include_option=--include; \ + empty_fix=; \ + fi; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test ! -f $$subdir/TAGS || \ + set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ + fi; \ + done; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: CTAGS +CTAGS: ctags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done + @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test -d "$(distdir)/$$subdir" \ + || $(MKDIR_P) "$(distdir)/$$subdir" \ + || exit 1; \ + fi; \ + done + @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ + $(am__relativize); \ + new_distdir=$$reldir; \ + dir1=$$subdir; dir2="$(top_distdir)"; \ + $(am__relativize); \ + new_top_distdir=$$reldir; \ + echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ + echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ + ($(am__cd) $$subdir && \ + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="$$new_top_distdir" \ + distdir="$$new_distdir" \ + am__remove_distdir=: \ + am__skip_length_check=: \ + am__skip_mode_fix=: \ + distdir) \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-recursive +all-am: Makefile +installdirs: installdirs-recursive +installdirs-am: +install: install-recursive +install-exec: install-exec-recursive +install-data: install-data-recursive +uninstall: uninstall-recursive + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-recursive +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-recursive + +clean-am: clean-generic clean-libtool mostlyclean-am + +distclean: distclean-recursive + -rm -f Makefile +distclean-am: clean-am distclean-generic distclean-tags + +dvi: dvi-recursive + +dvi-am: + +html: html-recursive + +html-am: + +info: info-recursive + +info-am: + +install-data-am: + +install-dvi: install-dvi-recursive + +install-dvi-am: + +install-exec-am: + +install-html: install-html-recursive + +install-html-am: + +install-info: install-info-recursive + +install-info-am: + +install-man: + +install-pdf: install-pdf-recursive + +install-pdf-am: + +install-ps: install-ps-recursive + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-recursive + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-recursive + +mostlyclean-am: mostlyclean-generic mostlyclean-libtool + +pdf: pdf-recursive + +pdf-am: + +ps: ps-recursive + +ps-am: + +uninstall-am: + +.MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) ctags-recursive \ + install-am install-strip tags-recursive + +.PHONY: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) CTAGS GTAGS \ + all all-am check check-am clean clean-generic clean-libtool \ + ctags ctags-recursive distclean distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am install-info \ + install-info-am install-man install-pdf install-pdf-am \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs installdirs-am maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-generic \ + mostlyclean-libtool pdf pdf-am ps ps-am tags tags-recursive \ + uninstall uninstall-am + + +-include $(top_srcdir)/git.mk + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/test/api/Makefile.am b/test/api/Makefile.am new file mode 100644 index 0000000..e6c0c01 --- /dev/null +++ b/test/api/Makefile.am @@ -0,0 +1,125 @@ +# Process this file with automake to produce Makefile.in + +NULL = +EXTRA_DIST = +CLEANFILES = +DISTCLEANFILES = +MAINTAINERCLEANFILES = + +if HAVE_GLIB +AM_CPPFLAGS = -DSRCDIR="\"$(srcdir)\"" -I$(top_srcdir)/src/ -I$(top_builddir)/src/ $(GLIB_CFLAGS) $(GTHREAD_CFLAGS) +LDADD = $(top_builddir)/src/libharfbuzz.la $(GLIB_LIBS) $(GTHREAD_LIBS) + +EXTRA_DIST += hb-test.h + +check_PROGRAMS = $(TEST_PROGS) +noinst_PROGRAMS = $(TEST_PROGS) + +TEST_PROGS = \ + test-blob \ + test-buffer \ + test-common \ + test-font \ + test-object \ + test-shape \ + test-unicode \ + test-version \ + $(NULL) + +if HAVE_OT +TEST_PROGS += \ + test-ot-tag \ + $(NULL) +endif + +# Tests for header compilation +TEST_PROGS += \ + test-c \ + test-cplusplus \ + $(NULL) +test_cplusplus_SOURCES = test-cplusplus.cc +test_c_CPPFLAGS = $(AM_CPPFLAGS) +test_cplusplus_CPPFLAGS = $(AM_CPPFLAGS) +if HAVE_ICU +test_c_CPPFLAGS += $(ICU_CFLAGS) +test_cplusplus_CPPFLAGS += $(ICU_CFLAGS) +endif +if HAVE_FREETYPE +test_c_CPPFLAGS += $(FREETYPE_CFLAGS) +test_cplusplus_CPPFLAGS += $(FREETYPE_CFLAGS) +endif + + +# Default test running environment +TESTS = $(TEST_PROGS) +TESTS_ENVIRONMENT = \ + MALLOC_CHECK_=2 \ + MALLOC_PERTURB_=$$(($${RANDOM:-256} % 256)) \ + G_DEBUG=gc-friendly \ + G_SLICE=always-malloc \ + srcdir=$(srcdir) \ + $(ENV) + + +# check-tool: Run tests under $(TOOL) +check-tool: + $(AM_V_at)$(MAKE) $(AM_MAKEFLAGS) check \ + TESTS_ENVIRONMENT='$(TESTS_ENVIRONMENT) $(top_builddir)/libtool --mode=execute \ + env $(TOOL)' +# check-tool-raw: Run tests under $(TOOL), but don't run under libtool +check-tool-raw: + $(AM_V_at)$(MAKE) $(AM_MAKEFLAGS) check \ + TESTS_ENVIRONMENT='$(TESTS_ENVIRONMENT) \ + env $(TOOL)' + +# check-gtester: Run tests under gtester +GTESTER = gtester +check-gtester: + $(AM_V_at)$(MAKE) $(AM_MAKEFLGS) check-tool-raw TOOL="$(GTESTER) --verbose --keep-going" + + +# Check tests under valgrind. Saves log to log-valgrind.txt +VALGRIND_FLAGS = \ + --tool=memcheck --suppressions=$(srcdir)/.valgrind-suppressions \ + --track-origins=yes \ + --leak-check=yes + $(EXTRA_VALGRIND_FLAGS) +# Can't do for now: --show-reachable=yes +CLEANFILES += log-valgrind.txt +valgrind_verbose = $(valgrind_verbose_$(V)) +valgrind_verbose_ = $(valgrind_verbose_$(AM_DEFAULT_VERBOSITY)) +valgrind_verbose_0 = | \ + grep '\(^[^=]\|ERROR SUMMARY\|definitely lost\|indirectly lost\)' | grep -v ': 0' +# TODO: The following check does not fail if valgrind finds error. It should. +check-valgrind: + $(AM_V_at)$(MAKE) $(AM_MAKEFLGS) check-tool TOOL="valgrind $(VALGRIND_FLAGS)" \ + 2>&1 | tee log-valgrind.txt $(valgrind_verbose) + + +# check-symbols: Finds untested API symbols +symbols-tested.txt: $(TEST_PROGS) + $(AM_V_GEN)$(top_builddir)/libtool --mode=execute nm $^ \ + | grep ' U hb_' | sed 's/.* U hb_/hb_/' \ + | sort | uniq > $@.tmp && mv $@.tmp $@ +symbols-exported.txt: $(top_builddir)/src/.libs/libharfbuzz.so + $(AM_V_GEN)$(top_builddir)/libtool --mode=execute nm $^ \ + | grep ' T ' | sed 's/.* T //' | grep -v '^\(_init\|_fini\)$$' \ + | sort | uniq > $@.tmp && mv $@.tmp $@ +symbols-untested.txt: symbols-tested.txt symbols-exported.txt + $(AM_V_GEN)diff $^ > $@.tmp; mv $@.tmp $@ +CLEANFILES += symbols-tested.txt symbols-exported.txt symbols-untested.txt +check-symbols: symbols-untested.txt + @! cat $^ | grep . + + + +else +check-am: err-glib +err-glib: + @echo "You need to have glib support enabled to run the tests" + @exit 77 +endif + +.PHONY: check-symbols check-tool check-valgrind + +-include $(top_srcdir)/git.mk diff --git a/test/api/Makefile.in b/test/api/Makefile.in new file mode 100644 index 0000000..d6c087a --- /dev/null +++ b/test/api/Makefile.in @@ -0,0 +1,914 @@ +# Makefile.in generated by automake 1.11.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, +# Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +# Process this file with automake to produce Makefile.in + +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +@HAVE_GLIB_TRUE@am__append_1 = hb-test.h +@HAVE_GLIB_TRUE@check_PROGRAMS = $(am__EXEEXT_3) +@HAVE_GLIB_TRUE@noinst_PROGRAMS = $(am__EXEEXT_3) +@HAVE_GLIB_TRUE@@HAVE_OT_TRUE@am__append_2 = \ +@HAVE_GLIB_TRUE@@HAVE_OT_TRUE@ test-ot-tag \ +@HAVE_GLIB_TRUE@@HAVE_OT_TRUE@ $(NULL) + +@HAVE_GLIB_TRUE@@HAVE_ICU_TRUE@am__append_3 = $(ICU_CFLAGS) +@HAVE_GLIB_TRUE@@HAVE_ICU_TRUE@am__append_4 = $(ICU_CFLAGS) +@HAVE_FREETYPE_TRUE@@HAVE_GLIB_TRUE@am__append_5 = $(FREETYPE_CFLAGS) +@HAVE_FREETYPE_TRUE@@HAVE_GLIB_TRUE@am__append_6 = $(FREETYPE_CFLAGS) +@HAVE_GLIB_TRUE@TESTS = $(am__EXEEXT_3) +# Can't do for now: --show-reachable=yes +@HAVE_GLIB_TRUE@am__append_7 = log-valgrind.txt symbols-tested.txt \ +@HAVE_GLIB_TRUE@ symbols-exported.txt symbols-untested.txt +subdir = test/api +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +am__EXEEXT_1 = +@HAVE_GLIB_TRUE@@HAVE_OT_TRUE@am__EXEEXT_2 = test-ot-tag$(EXEEXT) \ +@HAVE_GLIB_TRUE@@HAVE_OT_TRUE@ $(am__EXEEXT_1) +@HAVE_GLIB_TRUE@am__EXEEXT_3 = test-blob$(EXEEXT) test-buffer$(EXEEXT) \ +@HAVE_GLIB_TRUE@ test-common$(EXEEXT) test-font$(EXEEXT) \ +@HAVE_GLIB_TRUE@ test-object$(EXEEXT) test-shape$(EXEEXT) \ +@HAVE_GLIB_TRUE@ test-unicode$(EXEEXT) test-version$(EXEEXT) \ +@HAVE_GLIB_TRUE@ $(am__EXEEXT_1) $(am__EXEEXT_2) \ +@HAVE_GLIB_TRUE@ test-c$(EXEEXT) test-cplusplus$(EXEEXT) \ +@HAVE_GLIB_TRUE@ $(am__EXEEXT_1) +PROGRAMS = $(noinst_PROGRAMS) +test_blob_SOURCES = test-blob.c +test_blob_OBJECTS = test-blob.$(OBJEXT) +test_blob_LDADD = $(LDADD) +am__DEPENDENCIES_1 = +@HAVE_GLIB_TRUE@test_blob_DEPENDENCIES = \ +@HAVE_GLIB_TRUE@ $(top_builddir)/src/libharfbuzz.la \ +@HAVE_GLIB_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) +AM_V_lt = $(am__v_lt_$(V)) +am__v_lt_ = $(am__v_lt_$(AM_DEFAULT_VERBOSITY)) +am__v_lt_0 = --silent +test_buffer_SOURCES = test-buffer.c +test_buffer_OBJECTS = test-buffer.$(OBJEXT) +test_buffer_LDADD = $(LDADD) +@HAVE_GLIB_TRUE@test_buffer_DEPENDENCIES = \ +@HAVE_GLIB_TRUE@ $(top_builddir)/src/libharfbuzz.la \ +@HAVE_GLIB_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) +test_c_SOURCES = test-c.c +test_c_OBJECTS = test_c-test-c.$(OBJEXT) +test_c_LDADD = $(LDADD) +@HAVE_GLIB_TRUE@test_c_DEPENDENCIES = \ +@HAVE_GLIB_TRUE@ $(top_builddir)/src/libharfbuzz.la \ +@HAVE_GLIB_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) +test_common_SOURCES = test-common.c +test_common_OBJECTS = test-common.$(OBJEXT) +test_common_LDADD = $(LDADD) +@HAVE_GLIB_TRUE@test_common_DEPENDENCIES = \ +@HAVE_GLIB_TRUE@ $(top_builddir)/src/libharfbuzz.la \ +@HAVE_GLIB_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) +am__test_cplusplus_SOURCES_DIST = test-cplusplus.cc +@HAVE_GLIB_TRUE@am_test_cplusplus_OBJECTS = \ +@HAVE_GLIB_TRUE@ test_cplusplus-test-cplusplus.$(OBJEXT) +test_cplusplus_OBJECTS = $(am_test_cplusplus_OBJECTS) +test_cplusplus_LDADD = $(LDADD) +@HAVE_GLIB_TRUE@test_cplusplus_DEPENDENCIES = \ +@HAVE_GLIB_TRUE@ $(top_builddir)/src/libharfbuzz.la \ +@HAVE_GLIB_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) +test_font_SOURCES = test-font.c +test_font_OBJECTS = test-font.$(OBJEXT) +test_font_LDADD = $(LDADD) +@HAVE_GLIB_TRUE@test_font_DEPENDENCIES = \ +@HAVE_GLIB_TRUE@ $(top_builddir)/src/libharfbuzz.la \ +@HAVE_GLIB_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) +test_object_SOURCES = test-object.c +test_object_OBJECTS = test-object.$(OBJEXT) +test_object_LDADD = $(LDADD) +@HAVE_GLIB_TRUE@test_object_DEPENDENCIES = \ +@HAVE_GLIB_TRUE@ $(top_builddir)/src/libharfbuzz.la \ +@HAVE_GLIB_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) +test_ot_tag_SOURCES = test-ot-tag.c +test_ot_tag_OBJECTS = test-ot-tag.$(OBJEXT) +test_ot_tag_LDADD = $(LDADD) +@HAVE_GLIB_TRUE@test_ot_tag_DEPENDENCIES = \ +@HAVE_GLIB_TRUE@ $(top_builddir)/src/libharfbuzz.la \ +@HAVE_GLIB_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) +test_shape_SOURCES = test-shape.c +test_shape_OBJECTS = test-shape.$(OBJEXT) +test_shape_LDADD = $(LDADD) +@HAVE_GLIB_TRUE@test_shape_DEPENDENCIES = \ +@HAVE_GLIB_TRUE@ $(top_builddir)/src/libharfbuzz.la \ +@HAVE_GLIB_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) +test_unicode_SOURCES = test-unicode.c +test_unicode_OBJECTS = test-unicode.$(OBJEXT) +test_unicode_LDADD = $(LDADD) +@HAVE_GLIB_TRUE@test_unicode_DEPENDENCIES = \ +@HAVE_GLIB_TRUE@ $(top_builddir)/src/libharfbuzz.la \ +@HAVE_GLIB_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) +test_version_SOURCES = test-version.c +test_version_OBJECTS = test-version.$(OBJEXT) +test_version_LDADD = $(LDADD) +@HAVE_GLIB_TRUE@test_version_DEPENDENCIES = \ +@HAVE_GLIB_TRUE@ $(top_builddir)/src/libharfbuzz.la \ +@HAVE_GLIB_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_$(V)) +am__v_CC_ = $(am__v_CC_$(AM_DEFAULT_VERBOSITY)) +am__v_CC_0 = @echo " CC " $@; +AM_V_at = $(am__v_at_$(V)) +am__v_at_ = $(am__v_at_$(AM_DEFAULT_VERBOSITY)) +am__v_at_0 = @ +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_$(V)) +am__v_CCLD_ = $(am__v_CCLD_$(AM_DEFAULT_VERBOSITY)) +am__v_CCLD_0 = @echo " CCLD " $@; +CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) +LTCXXCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CXXFLAGS) $(CXXFLAGS) +AM_V_CXX = $(am__v_CXX_$(V)) +am__v_CXX_ = $(am__v_CXX_$(AM_DEFAULT_VERBOSITY)) +am__v_CXX_0 = @echo " CXX " $@; +CXXLD = $(CXX) +CXXLINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \ + $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CXXLD = $(am__v_CXXLD_$(V)) +am__v_CXXLD_ = $(am__v_CXXLD_$(AM_DEFAULT_VERBOSITY)) +am__v_CXXLD_0 = @echo " CXXLD " $@; +AM_V_GEN = $(am__v_GEN_$(V)) +am__v_GEN_ = $(am__v_GEN_$(AM_DEFAULT_VERBOSITY)) +am__v_GEN_0 = @echo " GEN " $@; +SOURCES = test-blob.c test-buffer.c test-c.c test-common.c \ + $(test_cplusplus_SOURCES) test-font.c test-object.c \ + test-ot-tag.c test-shape.c test-unicode.c test-version.c +DIST_SOURCES = test-blob.c test-buffer.c test-c.c test-common.c \ + $(am__test_cplusplus_SOURCES_DIST) test-font.c test-object.c \ + test-ot-tag.c test-shape.c test-unicode.c test-version.c +ETAGS = etags +CTAGS = ctags +am__tty_colors = \ +red=; grn=; lgn=; blu=; std= +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CAIRO_CFLAGS = @CAIRO_CFLAGS@ +CAIRO_FT_CFLAGS = @CAIRO_FT_CFLAGS@ +CAIRO_FT_LIBS = @CAIRO_FT_LIBS@ +CAIRO_LIBS = @CAIRO_LIBS@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CORETEXT_CFLAGS = @CORETEXT_CFLAGS@ +CORETEXT_LIBS = @CORETEXT_LIBS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +FREETYPE_CFLAGS = @FREETYPE_CFLAGS@ +FREETYPE_LIBS = @FREETYPE_LIBS@ +GLIB_CFLAGS = @GLIB_CFLAGS@ +GLIB_LIBS = @GLIB_LIBS@ +GLIB_MKENUMS = @GLIB_MKENUMS@ +GOBJECT_CFLAGS = @GOBJECT_CFLAGS@ +GOBJECT_LIBS = @GOBJECT_LIBS@ +GRAPHITE2_CFLAGS = @GRAPHITE2_CFLAGS@ +GRAPHITE2_LIBS = @GRAPHITE2_LIBS@ +GREP = @GREP@ +GTHREAD_CFLAGS = @GTHREAD_CFLAGS@ +GTHREAD_LIBS = @GTHREAD_LIBS@ +HB_LIBTOOL_VERSION_INFO = @HB_LIBTOOL_VERSION_INFO@ +HB_VERSION = @HB_VERSION@ +HB_VERSION_MAJOR = @HB_VERSION_MAJOR@ +HB_VERSION_MICRO = @HB_VERSION_MICRO@ +HB_VERSION_MINOR = @HB_VERSION_MINOR@ +ICU_CFLAGS = @ICU_CFLAGS@ +ICU_LIBS = @ICU_LIBS@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PKG_CONFIG = @PKG_CONFIG@ +RANLIB = @RANLIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +UNISCRIBE_CFLAGS = @UNISCRIBE_CFLAGS@ +UNISCRIBE_LIBS = @UNISCRIBE_LIBS@ +VERSION = @VERSION@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +lt_ECHO = @lt_ECHO@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +NULL = +EXTRA_DIST = $(am__append_1) +CLEANFILES = $(am__append_7) +DISTCLEANFILES = +MAINTAINERCLEANFILES = +@HAVE_GLIB_TRUE@AM_CPPFLAGS = -DSRCDIR="\"$(srcdir)\"" -I$(top_srcdir)/src/ -I$(top_builddir)/src/ $(GLIB_CFLAGS) $(GTHREAD_CFLAGS) +@HAVE_GLIB_TRUE@LDADD = $(top_builddir)/src/libharfbuzz.la $(GLIB_LIBS) $(GTHREAD_LIBS) + +# Tests for header compilation +@HAVE_GLIB_TRUE@TEST_PROGS = test-blob test-buffer test-common \ +@HAVE_GLIB_TRUE@ test-font test-object test-shape test-unicode \ +@HAVE_GLIB_TRUE@ test-version $(NULL) $(am__append_2) test-c \ +@HAVE_GLIB_TRUE@ test-cplusplus $(NULL) +@HAVE_GLIB_TRUE@test_cplusplus_SOURCES = test-cplusplus.cc +@HAVE_GLIB_TRUE@test_c_CPPFLAGS = $(AM_CPPFLAGS) $(am__append_3) \ +@HAVE_GLIB_TRUE@ $(am__append_5) +@HAVE_GLIB_TRUE@test_cplusplus_CPPFLAGS = $(AM_CPPFLAGS) \ +@HAVE_GLIB_TRUE@ $(am__append_4) $(am__append_6) +@HAVE_GLIB_TRUE@TESTS_ENVIRONMENT = \ +@HAVE_GLIB_TRUE@ MALLOC_CHECK_=2 \ +@HAVE_GLIB_TRUE@ MALLOC_PERTURB_=$$(($${RANDOM:-256} % 256)) \ +@HAVE_GLIB_TRUE@ G_DEBUG=gc-friendly \ +@HAVE_GLIB_TRUE@ G_SLICE=always-malloc \ +@HAVE_GLIB_TRUE@ srcdir=$(srcdir) \ +@HAVE_GLIB_TRUE@ $(ENV) + + +# check-gtester: Run tests under gtester +@HAVE_GLIB_TRUE@GTESTER = gtester + +# Check tests under valgrind. Saves log to log-valgrind.txt +@HAVE_GLIB_TRUE@VALGRIND_FLAGS = \ +@HAVE_GLIB_TRUE@ --tool=memcheck --suppressions=$(srcdir)/.valgrind-suppressions \ +@HAVE_GLIB_TRUE@ --track-origins=yes \ +@HAVE_GLIB_TRUE@ --leak-check=yes + +@HAVE_GLIB_TRUE@valgrind_verbose = $(valgrind_verbose_$(V)) +@HAVE_GLIB_TRUE@valgrind_verbose_ = $(valgrind_verbose_$(AM_DEFAULT_VERBOSITY)) +@HAVE_GLIB_TRUE@valgrind_verbose_0 = | \ +@HAVE_GLIB_TRUE@ grep '\(^[^=]\|ERROR SUMMARY\|definitely lost\|indirectly lost\)' | grep -v ': 0' + +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .cc .lo .o .obj +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnits test/api/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnits test/api/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +clean-checkPROGRAMS: + @list='$(check_PROGRAMS)'; test -n "$$list" || exit 0; \ + echo " rm -f" $$list; \ + rm -f $$list || exit $$?; \ + test -n "$(EXEEXT)" || exit 0; \ + list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f" $$list; \ + rm -f $$list + +clean-noinstPROGRAMS: + @list='$(noinst_PROGRAMS)'; test -n "$$list" || exit 0; \ + echo " rm -f" $$list; \ + rm -f $$list || exit $$?; \ + test -n "$(EXEEXT)" || exit 0; \ + list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f" $$list; \ + rm -f $$list +test-blob$(EXEEXT): $(test_blob_OBJECTS) $(test_blob_DEPENDENCIES) + @rm -f test-blob$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(test_blob_OBJECTS) $(test_blob_LDADD) $(LIBS) +test-buffer$(EXEEXT): $(test_buffer_OBJECTS) $(test_buffer_DEPENDENCIES) + @rm -f test-buffer$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(test_buffer_OBJECTS) $(test_buffer_LDADD) $(LIBS) +test-c$(EXEEXT): $(test_c_OBJECTS) $(test_c_DEPENDENCIES) + @rm -f test-c$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(test_c_OBJECTS) $(test_c_LDADD) $(LIBS) +test-common$(EXEEXT): $(test_common_OBJECTS) $(test_common_DEPENDENCIES) + @rm -f test-common$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(test_common_OBJECTS) $(test_common_LDADD) $(LIBS) +test-cplusplus$(EXEEXT): $(test_cplusplus_OBJECTS) $(test_cplusplus_DEPENDENCIES) + @rm -f test-cplusplus$(EXEEXT) + $(AM_V_CXXLD)$(CXXLINK) $(test_cplusplus_OBJECTS) $(test_cplusplus_LDADD) $(LIBS) +test-font$(EXEEXT): $(test_font_OBJECTS) $(test_font_DEPENDENCIES) + @rm -f test-font$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(test_font_OBJECTS) $(test_font_LDADD) $(LIBS) +test-object$(EXEEXT): $(test_object_OBJECTS) $(test_object_DEPENDENCIES) + @rm -f test-object$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(test_object_OBJECTS) $(test_object_LDADD) $(LIBS) +test-ot-tag$(EXEEXT): $(test_ot_tag_OBJECTS) $(test_ot_tag_DEPENDENCIES) + @rm -f test-ot-tag$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(test_ot_tag_OBJECTS) $(test_ot_tag_LDADD) $(LIBS) +test-shape$(EXEEXT): $(test_shape_OBJECTS) $(test_shape_DEPENDENCIES) + @rm -f test-shape$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(test_shape_OBJECTS) $(test_shape_LDADD) $(LIBS) +test-unicode$(EXEEXT): $(test_unicode_OBJECTS) $(test_unicode_DEPENDENCIES) + @rm -f test-unicode$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(test_unicode_OBJECTS) $(test_unicode_LDADD) $(LIBS) +test-version$(EXEEXT): $(test_version_OBJECTS) $(test_version_DEPENDENCIES) + @rm -f test-version$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(test_version_OBJECTS) $(test_version_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-blob.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-buffer.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-common.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-font.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-object.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-ot-tag.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-shape.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-unicode.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-version.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_c-test-c.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_cplusplus-test-cplusplus.Po@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< + +test_c-test-c.o: test-c.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_c_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_c-test-c.o -MD -MP -MF $(DEPDIR)/test_c-test-c.Tpo -c -o test_c-test-c.o `test -f 'test-c.c' || echo '$(srcdir)/'`test-c.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_c-test-c.Tpo $(DEPDIR)/test_c-test-c.Po +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='test-c.c' object='test_c-test-c.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_c_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_c-test-c.o `test -f 'test-c.c' || echo '$(srcdir)/'`test-c.c + +test_c-test-c.obj: test-c.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_c_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_c-test-c.obj -MD -MP -MF $(DEPDIR)/test_c-test-c.Tpo -c -o test_c-test-c.obj `if test -f 'test-c.c'; then $(CYGPATH_W) 'test-c.c'; else $(CYGPATH_W) '$(srcdir)/test-c.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_c-test-c.Tpo $(DEPDIR)/test_c-test-c.Po +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='test-c.c' object='test_c-test-c.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_c_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_c-test-c.obj `if test -f 'test-c.c'; then $(CYGPATH_W) 'test-c.c'; else $(CYGPATH_W) '$(srcdir)/test-c.c'; fi` + +.cc.o: +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ $< + +.cc.obj: +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.cc.lo: +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LTCXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LTCXXCOMPILE) -c -o $@ $< + +test_cplusplus-test-cplusplus.o: test-cplusplus.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_cplusplus_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT test_cplusplus-test-cplusplus.o -MD -MP -MF $(DEPDIR)/test_cplusplus-test-cplusplus.Tpo -c -o test_cplusplus-test-cplusplus.o `test -f 'test-cplusplus.cc' || echo '$(srcdir)/'`test-cplusplus.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_cplusplus-test-cplusplus.Tpo $(DEPDIR)/test_cplusplus-test-cplusplus.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='test-cplusplus.cc' object='test_cplusplus-test-cplusplus.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_cplusplus_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o test_cplusplus-test-cplusplus.o `test -f 'test-cplusplus.cc' || echo '$(srcdir)/'`test-cplusplus.cc + +test_cplusplus-test-cplusplus.obj: test-cplusplus.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_cplusplus_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT test_cplusplus-test-cplusplus.obj -MD -MP -MF $(DEPDIR)/test_cplusplus-test-cplusplus.Tpo -c -o test_cplusplus-test-cplusplus.obj `if test -f 'test-cplusplus.cc'; then $(CYGPATH_W) 'test-cplusplus.cc'; else $(CYGPATH_W) '$(srcdir)/test-cplusplus.cc'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_cplusplus-test-cplusplus.Tpo $(DEPDIR)/test_cplusplus-test-cplusplus.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='test-cplusplus.cc' object='test_cplusplus-test-cplusplus.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_cplusplus_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o test_cplusplus-test-cplusplus.obj `if test -f 'test-cplusplus.cc'; then $(CYGPATH_W) 'test-cplusplus.cc'; else $(CYGPATH_W) '$(srcdir)/test-cplusplus.cc'; fi` + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + set x; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +check-TESTS: $(TESTS) + @failed=0; all=0; xfail=0; xpass=0; skip=0; \ + srcdir=$(srcdir); export srcdir; \ + list=' $(TESTS) '; \ + $(am__tty_colors); \ + if test -n "$$list"; then \ + for tst in $$list; do \ + if test -f ./$$tst; then dir=./; \ + elif test -f $$tst; then dir=; \ + else dir="$(srcdir)/"; fi; \ + if $(TESTS_ENVIRONMENT) $${dir}$$tst; then \ + all=`expr $$all + 1`; \ + case " $(XFAIL_TESTS) " in \ + *[\ \ ]$$tst[\ \ ]*) \ + xpass=`expr $$xpass + 1`; \ + failed=`expr $$failed + 1`; \ + col=$$red; res=XPASS; \ + ;; \ + *) \ + col=$$grn; res=PASS; \ + ;; \ + esac; \ + elif test $$? -ne 77; then \ + all=`expr $$all + 1`; \ + case " $(XFAIL_TESTS) " in \ + *[\ \ ]$$tst[\ \ ]*) \ + xfail=`expr $$xfail + 1`; \ + col=$$lgn; res=XFAIL; \ + ;; \ + *) \ + failed=`expr $$failed + 1`; \ + col=$$red; res=FAIL; \ + ;; \ + esac; \ + else \ + skip=`expr $$skip + 1`; \ + col=$$blu; res=SKIP; \ + fi; \ + echo "$${col}$$res$${std}: $$tst"; \ + done; \ + if test "$$all" -eq 1; then \ + tests="test"; \ + All=""; \ + else \ + tests="tests"; \ + All="All "; \ + fi; \ + if test "$$failed" -eq 0; then \ + if test "$$xfail" -eq 0; then \ + banner="$$All$$all $$tests passed"; \ + else \ + if test "$$xfail" -eq 1; then failures=failure; else failures=failures; fi; \ + banner="$$All$$all $$tests behaved as expected ($$xfail expected $$failures)"; \ + fi; \ + else \ + if test "$$xpass" -eq 0; then \ + banner="$$failed of $$all $$tests failed"; \ + else \ + if test "$$xpass" -eq 1; then passes=pass; else passes=passes; fi; \ + banner="$$failed of $$all $$tests did not behave as expected ($$xpass unexpected $$passes)"; \ + fi; \ + fi; \ + dashes="$$banner"; \ + skipped=""; \ + if test "$$skip" -ne 0; then \ + if test "$$skip" -eq 1; then \ + skipped="($$skip test was not run)"; \ + else \ + skipped="($$skip tests were not run)"; \ + fi; \ + test `echo "$$skipped" | wc -c` -le `echo "$$banner" | wc -c` || \ + dashes="$$skipped"; \ + fi; \ + report=""; \ + if test "$$failed" -ne 0 && test -n "$(PACKAGE_BUGREPORT)"; then \ + report="Please report to $(PACKAGE_BUGREPORT)"; \ + test `echo "$$report" | wc -c` -le `echo "$$banner" | wc -c` || \ + dashes="$$report"; \ + fi; \ + dashes=`echo "$$dashes" | sed s/./=/g`; \ + if test "$$failed" -eq 0; then \ + echo "$$grn$$dashes"; \ + else \ + echo "$$red$$dashes"; \ + fi; \ + echo "$$banner"; \ + test -z "$$skipped" || echo "$$skipped"; \ + test -z "$$report" || echo "$$report"; \ + echo "$$dashes$$std"; \ + test "$$failed" -eq 0; \ + else :; fi + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am + $(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS) + $(MAKE) $(AM_MAKEFLAGS) check-TESTS +check: check-am +all-am: Makefile $(PROGRAMS) +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + -test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." + -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES) +clean: clean-am + +clean-am: clean-checkPROGRAMS clean-generic clean-libtool \ + clean-noinstPROGRAMS mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: + +.MAKE: check-am install-am install-strip + +.PHONY: CTAGS GTAGS all all-am check check-TESTS check-am clean \ + clean-checkPROGRAMS clean-generic clean-libtool \ + clean-noinstPROGRAMS ctags distclean distclean-compile \ + distclean-generic distclean-libtool distclean-tags distdir dvi \ + dvi-am html html-am info info-am install install-am \ + install-data install-data-am install-dvi install-dvi-am \ + install-exec install-exec-am install-html install-html-am \ + install-info install-info-am install-man install-pdf \ + install-pdf-am install-ps install-ps-am install-strip \ + installcheck installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags uninstall uninstall-am + + +# check-tool: Run tests under $(TOOL) +@HAVE_GLIB_TRUE@check-tool: +@HAVE_GLIB_TRUE@ $(AM_V_at)$(MAKE) $(AM_MAKEFLAGS) check \ +@HAVE_GLIB_TRUE@ TESTS_ENVIRONMENT='$(TESTS_ENVIRONMENT) $(top_builddir)/libtool --mode=execute \ +@HAVE_GLIB_TRUE@ env $(TOOL)' +# check-tool-raw: Run tests under $(TOOL), but don't run under libtool +@HAVE_GLIB_TRUE@check-tool-raw: +@HAVE_GLIB_TRUE@ $(AM_V_at)$(MAKE) $(AM_MAKEFLAGS) check \ +@HAVE_GLIB_TRUE@ TESTS_ENVIRONMENT='$(TESTS_ENVIRONMENT) \ +@HAVE_GLIB_TRUE@ env $(TOOL)' +@HAVE_GLIB_TRUE@check-gtester: +@HAVE_GLIB_TRUE@ $(AM_V_at)$(MAKE) $(AM_MAKEFLGS) check-tool-raw TOOL="$(GTESTER) --verbose --keep-going" +@HAVE_GLIB_TRUE@ $(EXTRA_VALGRIND_FLAGS) +# TODO: The following check does not fail if valgrind finds error. It should. +@HAVE_GLIB_TRUE@check-valgrind: +@HAVE_GLIB_TRUE@ $(AM_V_at)$(MAKE) $(AM_MAKEFLGS) check-tool TOOL="valgrind $(VALGRIND_FLAGS)" \ +@HAVE_GLIB_TRUE@ 2>&1 | tee log-valgrind.txt $(valgrind_verbose) + +# check-symbols: Finds untested API symbols +@HAVE_GLIB_TRUE@symbols-tested.txt: $(TEST_PROGS) +@HAVE_GLIB_TRUE@ $(AM_V_GEN)$(top_builddir)/libtool --mode=execute nm $^ \ +@HAVE_GLIB_TRUE@ | grep ' U hb_' | sed 's/.* U hb_/hb_/' \ +@HAVE_GLIB_TRUE@ | sort | uniq > $@.tmp && mv $@.tmp $@ +@HAVE_GLIB_TRUE@symbols-exported.txt: $(top_builddir)/src/.libs/libharfbuzz.so +@HAVE_GLIB_TRUE@ $(AM_V_GEN)$(top_builddir)/libtool --mode=execute nm $^ \ +@HAVE_GLIB_TRUE@ | grep ' T ' | sed 's/.* T //' | grep -v '^\(_init\|_fini\)$$' \ +@HAVE_GLIB_TRUE@ | sort | uniq > $@.tmp && mv $@.tmp $@ +@HAVE_GLIB_TRUE@symbols-untested.txt: symbols-tested.txt symbols-exported.txt +@HAVE_GLIB_TRUE@ $(AM_V_GEN)diff $^ > $@.tmp; mv $@.tmp $@ +@HAVE_GLIB_TRUE@check-symbols: symbols-untested.txt +@HAVE_GLIB_TRUE@ @! cat $^ | grep . + +@HAVE_GLIB_FALSE@check-am: err-glib +@HAVE_GLIB_FALSE@err-glib: +@HAVE_GLIB_FALSE@ @echo "You need to have glib support enabled to run the tests" +@HAVE_GLIB_FALSE@ @exit 77 + +.PHONY: check-symbols check-tool check-valgrind + +-include $(top_srcdir)/git.mk + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/test/api/hb-test.h b/test/api/hb-test.h new file mode 100644 index 0000000..8655f41 --- /dev/null +++ b/test/api/hb-test.h @@ -0,0 +1,268 @@ +/* + * Copyright © 2011 Google, Inc. + * + * This is part of HarfBuzz, a text shaping library. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and its documentation for any purpose, provided that the + * above copyright notice and the following two paragraphs appear in + * all copies of this software. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + * + * Google Author(s): Behdad Esfahbod + */ + +#ifndef HB_TEST_H +#define HB_TEST_H + +#include <config.h> + +#include <hb-glib.h> + +#include <stdlib.h> +#include <string.h> +#include <stdio.h> + +HB_BEGIN_DECLS + +/* Just in case */ +#undef G_DISABLE_ASSERT + + +/* Misc */ + +/* This is too ugly to be public API, but quite handy. */ +#define HB_TAG_CHAR4(s) (HB_TAG(((const char *) s)[0], \ + ((const char *) s)[1], \ + ((const char *) s)[2], \ + ((const char *) s)[3])) + + +static inline const char * +srcdir (void) +{ + static const char *s; + + if (!s) { + s = getenv ("srcdir"); + +#ifdef SRCDIR + if (!s || !s[0]) + s = SRCDIR; +#endif + + if (!s || !s[0]) + s = "."; + } + + return s; +} + + +/* Helpers */ + +static inline void +hb_test_init (int *argc, char ***argv) +{ +#if !GLIB_CHECK_VERSION(2,32,0) + g_thread_init (NULL); +#endif + g_test_init (argc, argv, NULL); +} + +static inline int +hb_test_run (void) +{ + return g_test_run (); +} + + +/* Bugzilla helpers */ + +static inline void +hb_test_bug (const char *uri_base, unsigned int number) +{ + char *s = g_strdup_printf ("%u", number); + + g_test_bug_base (uri_base); + g_test_bug (s); + + g_free (s); +} + +static inline void +hb_test_bug_freedesktop (unsigned int number) +{ + hb_test_bug ("http://bugs.freedesktop.org/", number); +} + +static inline void +hb_test_bug_gnome (unsigned int number) +{ + hb_test_bug ("http://bugzilla.gnome.org/", number); +} + +static inline void +hb_test_bug_mozilla (unsigned int number) +{ + hb_test_bug ("http://bugzilla.mozilla.org/", number); +} + +static inline void +hb_test_bug_redhat (unsigned int number) +{ + hb_test_bug ("http://bugzilla.redhat.com/", number); +} + + +/* Wrap glib test functions to simplify. Should have been in glib already. */ + +/* Drops the "test_" prefix and converts '_' to '/'. + * Essentially builds test path from function name. */ +static inline char * +hb_test_normalize_path (const char *path) +{ + char *s, *p; + + g_assert (0 == strncmp (path, "test_", 5)); + path += 4; + + s = g_strdup (path); + for (p = s; *p; p++) + if (*p == '_') + *p = '/'; + + return s; +} + + +#if GLIB_CHECK_VERSION(2,25,12) +typedef GTestFunc hb_test_func_t; +typedef GTestDataFunc hb_test_data_func_t; +typedef GTestFixtureFunc hb_test_fixture_func_t; +#else +typedef void (*hb_test_func_t) (void); +typedef void (*hb_test_data_func_t) (gconstpointer user_data); +typedef void (*hb_test_fixture_func_t) (void); +#endif + +#if !GLIB_CHECK_VERSION(2,30,0) +#define g_test_fail() g_error("Test failed") +#endif + +static inline void +hb_test_add_func (const char *test_path, + hb_test_func_t test_func) +{ + char *normal_path = hb_test_normalize_path (test_path); + g_test_add_func (normal_path, test_func); + g_free (normal_path); +} +#define hb_test_add(Func) hb_test_add_func (#Func, Func) + +static inline void +hb_test_add_func_flavor (const char *test_path, + const char *flavor, + hb_test_func_t test_func) +{ + char *path = g_strdup_printf ("%s/%s", test_path, flavor); + hb_test_add_func (path, test_func); + g_free (path); +} +#define hb_test_add_flavor(Flavor, Func) hb_test_add_func (#Func, Flavor, Func) + +static inline void +hb_test_add_data_func (const char *test_path, + gconstpointer test_data, + hb_test_data_func_t test_func) +{ + char *normal_path = hb_test_normalize_path (test_path); + g_test_add_data_func (normal_path, test_data, test_func); + g_free (normal_path); +} +#define hb_test_add_data(UserData, Func) hb_test_add_data_func (#Func, UserData, Func) + +static inline void +hb_test_add_data_func_flavor (const char *test_path, + const char *flavor, + gconstpointer test_data, + hb_test_data_func_t test_func) +{ + char *path = g_strdup_printf ("%s/%s", test_path, flavor); + hb_test_add_data_func (path, test_data, test_func); + g_free (path); +} +#define hb_test_add_data_flavor(UserData, Flavor, Func) hb_test_add_data_func_flavor (#Func, Flavor, UserData, Func) + + +static inline void +hb_test_add_vtable (const char *test_path, + gsize data_size, + gconstpointer test_data, + hb_test_fixture_func_t data_setup, + hb_test_fixture_func_t data_test, + hb_test_fixture_func_t data_teardown) +{ + char *normal_path = hb_test_normalize_path (test_path); + g_test_add_vtable (normal_path, data_size, test_data, data_setup, data_test, data_teardown); + g_free (normal_path); +} +#define hb_test_add_fixture(FixturePrefix, UserData, Func) \ +G_STMT_START { \ + typedef G_PASTE (FixturePrefix, _t) Fixture; \ + void (*add_vtable) (const char*, gsize, gconstpointer, \ + void (*) (Fixture*, gconstpointer), \ + void (*) (Fixture*, gconstpointer), \ + void (*) (Fixture*, gconstpointer)) \ + = (void (*) (const gchar *, gsize, gconstpointer, \ + void (*) (Fixture*, gconstpointer), \ + void (*) (Fixture*, gconstpointer), \ + void (*) (Fixture*, gconstpointer))) hb_test_add_vtable; \ + add_vtable (#Func, sizeof (G_PASTE (FixturePrefix, _t)), UserData, \ + G_PASTE (FixturePrefix, _init), Func, G_PASTE (FixturePrefix, _finish)); \ +} G_STMT_END + +static inline void +hb_test_add_vtable_flavor (const char *test_path, + const char *flavor, + gsize data_size, + gconstpointer test_data, + hb_test_fixture_func_t data_setup, + hb_test_fixture_func_t data_test, + hb_test_fixture_func_t data_teardown) +{ + char *path = g_strdup_printf ("%s/%s", test_path, flavor); + hb_test_add_vtable (path, data_size, test_data, data_setup, data_test, data_teardown); + g_free (path); +} +#define hb_test_add_fixture_flavor(FixturePrefix, UserData, Flavor, Func) \ +G_STMT_START { \ + typedef G_PASTE (FixturePrefix, _t) Fixture; \ + void (*add_vtable) (const char*, const char *, gsize, gconstpointer, \ + void (*) (Fixture*, gconstpointer), \ + void (*) (Fixture*, gconstpointer), \ + void (*) (Fixture*, gconstpointer)) \ + = (void (*) (const gchar *, const char *, gsize, gconstpointer, \ + void (*) (Fixture*, gconstpointer), \ + void (*) (Fixture*, gconstpointer), \ + void (*) (Fixture*, gconstpointer))) hb_test_add_vtable_flavor; \ + add_vtable (#Func, Flavor, sizeof (G_PASTE (FixturePrefix, _t)), UserData, \ + G_PASTE (FixturePrefix, _init), Func, G_PASTE (FixturePrefix, _finish)); \ +} G_STMT_END + + +HB_END_DECLS + +#endif /* HB_TEST_H */ diff --git a/test/api/test-blob.c b/test/api/test-blob.c new file mode 100644 index 0000000..0e65e2f --- /dev/null +++ b/test/api/test-blob.c @@ -0,0 +1,301 @@ +/* + * Copyright © 2011 Google, Inc. + * + * This is part of HarfBuzz, a text shaping library. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and its documentation for any purpose, provided that the + * above copyright notice and the following two paragraphs appear in + * all copies of this software. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + * + * Google Author(s): Behdad Esfahbod + */ + +#include "hb-test.h" + +/* Unit tests for hb-blob.h */ + +#if defined(HAVE_SYS_MMAN_H) && defined(HAVE_MPROTECT) && defined(HAVE_MMAP) + +# define TEST_MMAP 1 + +#ifdef HAVE_SYS_MMAN_H +#ifdef HAVE_UNISTD_H +#include <unistd.h> +#endif /* HAVE_UNISTD_H */ +#include <sys/mman.h> +#endif /* HAVE_SYS_MMAN_H */ + +#endif + + +static void +test_blob_empty (void) +{ + hb_blob_t *blob; + unsigned int len; + const char *data; + char *data_writable; + + g_assert (hb_blob_is_immutable (hb_blob_get_empty ())); + g_assert (hb_blob_get_empty () != NULL); + g_assert (hb_blob_get_empty () == hb_blob_create (NULL, 0, HB_MEMORY_MODE_READONLY, NULL, NULL)); + + blob = hb_blob_get_empty (); + g_assert (blob == hb_blob_get_empty ()); + + len = hb_blob_get_length (blob); + g_assert_cmpint (len, ==, 0); + + data = hb_blob_get_data (blob, NULL); + g_assert (data == NULL); + + data = hb_blob_get_data (blob, &len); + g_assert (data == NULL); + g_assert_cmpint (len, ==, 0); + + data_writable = hb_blob_get_data_writable (blob, NULL); + g_assert (data_writable == NULL); + + data_writable = hb_blob_get_data_writable (blob, &len); + g_assert (data_writable == NULL); + g_assert_cmpint (len, ==, 0); +} + +static const char test_data[] = "test\0data"; + +static const char *blob_names[] = { + "duplicate", + "readonly", + "writable" +#ifdef TEST_MMAP + , "readonly-may-make-writable" +#endif +}; + +typedef struct +{ + hb_blob_t *blob; + int freed; + char *data; + unsigned int len; +} fixture_t; + +static void +free_up (fixture_t *fixture) +{ + g_assert_cmpint (fixture->freed, ==, 0); + fixture->freed++; +} + +static void +free_up_free (fixture_t *fixture) +{ + free_up (fixture); + free (fixture->data); +} + + +#ifdef TEST_MMAP +static uintptr_t +get_pagesize (void) +{ + uintptr_t pagesize = -1; + +#if defined(HAVE_SYSCONF) && defined(_SC_PAGE_SIZE) + pagesize = (uintptr_t) sysconf (_SC_PAGE_SIZE); +#elif defined(HAVE_SYSCONF) && defined(_SC_PAGESIZE) + pagesize = (uintptr_t) sysconf (_SC_PAGESIZE); +#elif defined(HAVE_GETPAGESIZE) + pagesize = (uintptr_t) getpagesize (); +#endif + + g_assert (pagesize != (uintptr_t) -1); + + return pagesize; +} + +static void +free_up_munmap (fixture_t *fixture) +{ + free_up (fixture); + munmap (fixture->data, get_pagesize ()); +} +#endif + +#include <errno.h> +static void +fixture_init (fixture_t *fixture, gconstpointer user_data) +{ + hb_memory_mode_t mm = (hb_memory_mode_t) GPOINTER_TO_INT (user_data); + unsigned int len; + const char *data; + hb_destroy_func_t free_func; + + switch (GPOINTER_TO_INT (user_data)) + { + case HB_MEMORY_MODE_DUPLICATE: + data = test_data; + len = sizeof (test_data); + free_func = (hb_destroy_func_t) free_up; + break; + + case HB_MEMORY_MODE_READONLY: + data = test_data; + len = sizeof (test_data); + free_func = (hb_destroy_func_t) free_up; + break; + + case HB_MEMORY_MODE_WRITABLE: + data = malloc (sizeof (test_data)); + memcpy ((char *) data, test_data, sizeof (test_data)); + len = sizeof (test_data); + free_func = (hb_destroy_func_t) free_up_free; + break; + +#ifdef TEST_MMAP + case HB_MEMORY_MODE_READONLY_MAY_MAKE_WRITABLE: + { + uintptr_t pagesize = get_pagesize (); + + data = mmap (NULL, pagesize, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0); + g_assert (data != (char *) -1); + memcpy ((char *) data, test_data, sizeof (test_data)); + mprotect ((char *) data, pagesize, PROT_READ); + len = sizeof (test_data); + free_func = (hb_destroy_func_t) free_up_munmap; + break; + } +#endif + + default: + g_assert_not_reached (); + } + + fixture->freed = 0; + fixture->data = (char *) data; + fixture->len = len; + fixture->blob = hb_blob_create (data, len, mm, fixture, free_func); +} + +static void +fixture_finish (fixture_t *fixture, gconstpointer user_data) +{ + hb_blob_destroy (fixture->blob); + g_assert_cmpint (fixture->freed, ==, 1); +} + + +static void +test_blob (fixture_t *fixture, gconstpointer user_data) +{ + hb_blob_t *b = fixture->blob; + hb_memory_mode_t mm = GPOINTER_TO_INT (user_data); + unsigned int len; + const char *data; + char *data_writable; + unsigned int i; + + g_assert (b); + + len = hb_blob_get_length (b); + g_assert_cmpint (len, ==, fixture->len); + + data = hb_blob_get_data (b, &len); + g_assert_cmpint (len, ==, fixture->len); + if (mm == HB_MEMORY_MODE_DUPLICATE) { + g_assert (data != fixture->data); + g_assert_cmpint (fixture->freed, ==, 1); + mm = HB_MEMORY_MODE_WRITABLE; + } else { + g_assert (data == fixture->data); + g_assert_cmpint (fixture->freed, ==, 0); + } + + data_writable = hb_blob_get_data_writable (b, &len); + g_assert_cmpint (len, ==, fixture->len); + g_assert (data_writable); + g_assert (0 == memcmp (data_writable, fixture->data, fixture->len)); + if (mm == HB_MEMORY_MODE_READONLY) { + g_assert (data_writable != data); + g_assert_cmpint (fixture->freed, ==, 1); + } else { + g_assert (data_writable == data); + } + + data = hb_blob_get_data (b, &len); + g_assert_cmpint (len, ==, fixture->len); + g_assert (data == data_writable); + + memset (data_writable, 0, fixture->len); + + /* Now, make it immutable and watch get_data_writable() fail */ + + g_assert (!hb_blob_is_immutable (b)); + hb_blob_make_immutable (b); + g_assert (hb_blob_is_immutable (b)); + + data_writable = hb_blob_get_data_writable (b, &len); + g_assert (!data_writable); + g_assert_cmpint (len, ==, 0); + + data = hb_blob_get_data (b, &len); + g_assert_cmpint (len, ==, fixture->len); + for (i = 0; i < len; i++) + g_assert ('\0' == data[i]); +} + +static void +test_blob_subblob (fixture_t *fixture, gconstpointer user_data) +{ + hb_blob_t *b = fixture->blob; + + fixture->len -= 2; + fixture->data++; + fixture->blob = hb_blob_create_sub_blob (b, 1, fixture->len); + hb_blob_destroy (b); + + test_blob (fixture, user_data); + + fixture->data--; + fixture->len += 2; +} + + +int +main (int argc, char **argv) +{ + unsigned int i; + + hb_test_init (&argc, &argv); + + hb_test_add (test_blob_empty); + + for (i = 0; i < G_N_ELEMENTS (blob_names); i++) + { + const void *blob_type = GINT_TO_POINTER (i); + const char *blob_name = blob_names[i]; + + hb_test_add_fixture_flavor (fixture, blob_type, blob_name, test_blob); + hb_test_add_fixture_flavor (fixture, blob_type, blob_name, test_blob_subblob); + } + + /* + * create_sub_blob + */ + + return hb_test_run (); +} diff --git a/test/api/test-buffer.c b/test/api/test-buffer.c new file mode 100644 index 0000000..1ddc3d8 --- /dev/null +++ b/test/api/test-buffer.c @@ -0,0 +1,783 @@ +/* + * Copyright © 2011 Google, Inc. + * + * This is part of HarfBuzz, a text shaping library. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and its documentation for any purpose, provided that the + * above copyright notice and the following two paragraphs appear in + * all copies of this software. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + * + * Google Author(s): Behdad Esfahbod + */ + +#include "hb-test.h" + +/* Unit tests for hb-buffer.h */ + + +static const char utf8[10] = "ab\360\240\200\200defg"; +static const uint16_t utf16[8] = {'a', 'b', 0xD840, 0xDC00, 'd', 'e', 'f', 'g'}; +static const uint32_t utf32[7] = {'a', 'b', 0x20000, 'd', 'e', 'f', 'g'}; + + +typedef enum { + BUFFER_EMPTY, + BUFFER_ONE_BY_ONE, + BUFFER_UTF32, + BUFFER_UTF16, + BUFFER_UTF8, + BUFFER_NUM_TYPES, +} buffer_type_t; + +static const char *buffer_names[] = { + "empty", + "one-by-one", + "utf32", + "utf16", + "utf8" +}; + +typedef struct +{ + hb_buffer_t *buffer; +} fixture_t; + +static void +fixture_init (fixture_t *fixture, gconstpointer user_data) +{ + hb_buffer_t *b; + unsigned int i; + + b = fixture->buffer = hb_buffer_create (); + + switch (GPOINTER_TO_INT (user_data)) + { + case BUFFER_EMPTY: + break; + + case BUFFER_ONE_BY_ONE: + for (i = 1; i < G_N_ELEMENTS (utf32) - 1; i++) + hb_buffer_add (b, utf32[i], 1, i); + break; + + case BUFFER_UTF32: + hb_buffer_add_utf32 (b, utf32, G_N_ELEMENTS (utf32), 1, G_N_ELEMENTS (utf32) - 2); + break; + + case BUFFER_UTF16: + hb_buffer_add_utf16 (b, utf16, G_N_ELEMENTS (utf16), 1, G_N_ELEMENTS (utf16) - 2); + break; + + case BUFFER_UTF8: + hb_buffer_add_utf8 (b, utf8, G_N_ELEMENTS (utf8), 1, G_N_ELEMENTS (utf8) - 2); + break; + + default: + g_assert_not_reached (); + } +} + +static void +fixture_finish (fixture_t *fixture, gconstpointer user_data) +{ + hb_buffer_destroy (fixture->buffer); +} + + +static void +test_buffer_properties (fixture_t *fixture, gconstpointer user_data) +{ + hb_buffer_t *b = fixture->buffer; + hb_unicode_funcs_t *ufuncs; + + /* test default properties */ + + g_assert (hb_buffer_get_unicode_funcs (b) == hb_unicode_funcs_get_default ()); + g_assert (hb_buffer_get_direction (b) == HB_DIRECTION_INVALID); + g_assert (hb_buffer_get_script (b) == HB_SCRIPT_INVALID); + g_assert (hb_buffer_get_language (b) == NULL); + + + /* test property changes are retained */ + ufuncs = hb_unicode_funcs_create (NULL); + hb_buffer_set_unicode_funcs (b, ufuncs); + hb_unicode_funcs_destroy (ufuncs); + g_assert (hb_buffer_get_unicode_funcs (b) == ufuncs); + + hb_buffer_set_direction (b, HB_DIRECTION_RTL); + g_assert (hb_buffer_get_direction (b) == HB_DIRECTION_RTL); + + hb_buffer_set_script (b, HB_SCRIPT_ARABIC); + g_assert (hb_buffer_get_script (b) == HB_SCRIPT_ARABIC); + + hb_buffer_set_language (b, hb_language_from_string ("fa", -1)); + g_assert (hb_buffer_get_language (b) == hb_language_from_string ("Fa", -1)); + + + /* test reset clears properties */ + + hb_buffer_reset (b); + + g_assert (hb_buffer_get_unicode_funcs (b) == hb_unicode_funcs_get_default ()); + g_assert (hb_buffer_get_direction (b) == HB_DIRECTION_INVALID); + g_assert (hb_buffer_get_script (b) == HB_SCRIPT_INVALID); + g_assert (hb_buffer_get_language (b) == NULL); +} + +static void +test_buffer_contents (fixture_t *fixture, gconstpointer user_data) +{ + hb_buffer_t *b = fixture->buffer; + unsigned int i, len, len2; + buffer_type_t buffer_type = GPOINTER_TO_INT (user_data); + hb_glyph_info_t *glyphs; + + if (buffer_type == BUFFER_EMPTY) { + g_assert_cmpint (hb_buffer_get_length (b), ==, 0); + return; + } + + len = hb_buffer_get_length (b); + hb_buffer_get_glyph_infos (b, NULL); /* test NULL */ + glyphs = hb_buffer_get_glyph_infos (b, &len2); + g_assert_cmpint (len, ==, len2); + g_assert_cmpint (len, ==, 5); + + for (i = 0; i < len; i++) { + g_assert_cmphex (glyphs[i].mask, ==, 1); + g_assert_cmphex (glyphs[i].var1.u32, ==, 0); + g_assert_cmphex (glyphs[i].var2.u32, ==, 0); + } + + for (i = 0; i < len; i++) { + unsigned int cluster; + cluster = 1+i; + if (i >= 2) { + if (buffer_type == BUFFER_UTF16) + cluster++; + else if (buffer_type == BUFFER_UTF8) + cluster += 3; + } + g_assert_cmphex (glyphs[i].codepoint, ==, utf32[1+i]); + g_assert_cmphex (glyphs[i].cluster, ==, cluster); + } + + /* reverse, test, and reverse back */ + + hb_buffer_reverse (b); + for (i = 0; i < len; i++) + g_assert_cmphex (glyphs[i].codepoint, ==, utf32[len-i]); + + hb_buffer_reverse (b); + for (i = 0; i < len; i++) + g_assert_cmphex (glyphs[i].codepoint, ==, utf32[1+i]); + + /* reverse_clusters works same as reverse for now since each codepoint is + * in its own cluster */ + + hb_buffer_reverse_clusters (b); + for (i = 0; i < len; i++) + g_assert_cmphex (glyphs[i].codepoint, ==, utf32[len-i]); + + hb_buffer_reverse_clusters (b); + for (i = 0; i < len; i++) + g_assert_cmphex (glyphs[i].codepoint, ==, utf32[1+i]); + + /* now form a cluster and test again */ + glyphs[2].cluster = glyphs[1].cluster; + + /* reverse, test, and reverse back */ + + hb_buffer_reverse (b); + for (i = 0; i < len; i++) + g_assert_cmphex (glyphs[i].codepoint, ==, utf32[len-i]); + + hb_buffer_reverse (b); + for (i = 0; i < len; i++) + g_assert_cmphex (glyphs[i].codepoint, ==, utf32[1+i]); + + /* reverse_clusters twice still should return the original string, + * but when applied once, the 1-2 cluster should be retained. */ + + hb_buffer_reverse_clusters (b); + for (i = 0; i < len; i++) { + unsigned int j = len-1-i; + if (j == 1) + j = 2; + else if (j == 2) + j = 1; + g_assert_cmphex (glyphs[i].codepoint, ==, utf32[1+j]); + } + + hb_buffer_reverse_clusters (b); + for (i = 0; i < len; i++) + g_assert_cmphex (glyphs[i].codepoint, ==, utf32[1+i]); + + + /* test setting length */ + + /* enlarge */ + g_assert (hb_buffer_set_length (b, 10)); + glyphs = hb_buffer_get_glyph_infos (b, NULL); + g_assert_cmpint (hb_buffer_get_length (b), ==, 10); + for (i = 0; i < 5; i++) + g_assert_cmphex (glyphs[i].codepoint, ==, utf32[1+i]); + for (i = 5; i < 10; i++) + g_assert_cmphex (glyphs[i].codepoint, ==, 0); + /* shrink */ + g_assert (hb_buffer_set_length (b, 3)); + glyphs = hb_buffer_get_glyph_infos (b, NULL); + g_assert_cmpint (hb_buffer_get_length (b), ==, 3); + for (i = 0; i < 3; i++) + g_assert_cmphex (glyphs[i].codepoint, ==, utf32[1+i]); + + + g_assert (hb_buffer_allocation_successful (b)); + + + /* test reset clears content */ + + hb_buffer_reset (b); + g_assert_cmpint (hb_buffer_get_length (b), ==, 0); +} + +static void +test_buffer_positions (fixture_t *fixture, gconstpointer user_data) +{ + hb_buffer_t *b = fixture->buffer; + unsigned int i, len, len2; + hb_glyph_position_t *positions; + + /* Without shaping, positions should all be zero */ + len = hb_buffer_get_length (b); + hb_buffer_get_glyph_positions (b, NULL); /* test NULL */ + positions = hb_buffer_get_glyph_positions (b, &len2); + g_assert_cmpint (len, ==, len2); + for (i = 0; i < len; i++) { + g_assert_cmpint (0, ==, positions[i].x_advance); + g_assert_cmpint (0, ==, positions[i].y_advance); + g_assert_cmpint (0, ==, positions[i].x_offset); + g_assert_cmpint (0, ==, positions[i].y_offset); + g_assert_cmpint (0, ==, positions[i].var.i32); + } + + /* test reset clears content */ + hb_buffer_reset (b); + g_assert_cmpint (hb_buffer_get_length (b), ==, 0); +} + +static void +test_buffer_allocation (fixture_t *fixture, gconstpointer user_data) +{ + hb_buffer_t *b = fixture->buffer; + + g_assert_cmpint (hb_buffer_get_length (b), ==, 0); + + g_assert (hb_buffer_pre_allocate (b, 100)); + g_assert_cmpint (hb_buffer_get_length (b), ==, 0); + g_assert (hb_buffer_allocation_successful (b)); + + /* lets try a huge allocation, make sure it fails */ + g_assert (!hb_buffer_pre_allocate (b, (unsigned int) -1)); + g_assert_cmpint (hb_buffer_get_length (b), ==, 0); + g_assert (!hb_buffer_allocation_successful (b)); + + /* small one again */ + g_assert (hb_buffer_pre_allocate (b, 50)); + g_assert_cmpint (hb_buffer_get_length (b), ==, 0); + g_assert (!hb_buffer_allocation_successful (b)); + + hb_buffer_reset (b); + g_assert (hb_buffer_allocation_successful (b)); + + /* all allocation and size */ + g_assert (!hb_buffer_pre_allocate (b, ((unsigned int) -1) / 20 + 1)); + g_assert (!hb_buffer_allocation_successful (b)); + + hb_buffer_reset (b); + g_assert (hb_buffer_allocation_successful (b)); + + /* technically, this one can actually pass on 64bit machines, but + * I'm doubtful that any malloc allows 4GB allocations at a time. + * But let's only enable it on a 32-bit machine. */ + if (sizeof (long) == 4) { + g_assert (!hb_buffer_pre_allocate (b, ((unsigned int) -1) / 20 - 1)); + g_assert (!hb_buffer_allocation_successful (b)); + } + + hb_buffer_reset (b); + g_assert (hb_buffer_allocation_successful (b)); +} + + +typedef struct { + const char utf8[8]; + const uint32_t codepoints[8]; +} utf8_conversion_test_t; + +/* note: we skip the first and last byte when adding to buffer */ +static const utf8_conversion_test_t utf8_conversion_tests[] = { + {"a\303\207", {-1}}, + {"a\303\207b", {0xC7}}, + {"ab\303cd", {'b', -1, 'c'}}, + {"ab\303\302\301cd", {'b', -1, -1, -1, 'c'}} +}; + +static void +test_buffer_utf8_conversion (void) +{ + hb_buffer_t *b; + hb_glyph_info_t *glyphs; + unsigned int bytes, chars, i, j, len; + + b = hb_buffer_create (); + + for (i = 0; i < G_N_ELEMENTS (utf8_conversion_tests); i++) + { + const utf8_conversion_test_t *test = &utf8_conversion_tests[i]; + char *escaped; + + escaped = g_strescape (test->utf8, NULL); + g_test_message ("UTF-8 test #%d: %s", i, escaped); + g_free (escaped); + + bytes = strlen (test->utf8); + for (chars = 0; test->codepoints[chars]; chars++) + ; + + hb_buffer_reset (b); + hb_buffer_add_utf8 (b, test->utf8, bytes, 1, bytes - 2); + + glyphs = hb_buffer_get_glyph_infos (b, &len); + g_assert_cmpint (len, ==, chars); + for (j = 0; j < chars; j++) + g_assert_cmphex (glyphs[j].codepoint, ==, test->codepoints[j]); + } + + hb_buffer_destroy (b); +} + + + +/* Following test table is adapted from glib/glib/tests/utf8-validate.c + * with relicensing permission from Matthias Clasen. */ + +typedef struct { + const char *utf8; + int max_len; + unsigned int offset; + gboolean valid; +} utf8_validity_test_t; + +static const utf8_validity_test_t utf8_validity_tests[] = { + /* some tests to check max_len handling */ + /* length 1 */ + { "abcde", -1, 5, TRUE }, + { "abcde", 3, 3, TRUE }, + { "abcde", 5, 5, TRUE }, + /* length 2 */ + { "\xc2\xa9\xc2\xa9\xc2\xa9", -1, 6, TRUE }, + { "\xc2\xa9\xc2\xa9\xc2\xa9", 1, 0, FALSE }, + { "\xc2\xa9\xc2\xa9\xc2\xa9", 2, 2, TRUE }, + { "\xc2\xa9\xc2\xa9\xc2\xa9", 3, 2, FALSE }, + { "\xc2\xa9\xc2\xa9\xc2\xa9", 4, 4, TRUE }, + { "\xc2\xa9\xc2\xa9\xc2\xa9", 5, 4, FALSE }, + { "\xc2\xa9\xc2\xa9\xc2\xa9", 6, 6, TRUE }, + /* length 3 */ + { "\xe2\x89\xa0\xe2\x89\xa0", -1, 6, TRUE }, + { "\xe2\x89\xa0\xe2\x89\xa0", 1, 0, FALSE }, + { "\xe2\x89\xa0\xe2\x89\xa0", 2, 0, FALSE }, + { "\xe2\x89\xa0\xe2\x89\xa0", 3, 3, TRUE }, + { "\xe2\x89\xa0\xe2\x89\xa0", 4, 3, FALSE }, + { "\xe2\x89\xa0\xe2\x89\xa0", 5, 3, FALSE }, + { "\xe2\x89\xa0\xe2\x89\xa0", 6, 6, TRUE }, + + /* examples from http://www.cl.cam.ac.uk/~mgk25/ucs/examples/UTF-8-test.txt */ + /* greek 'kosme' */ + { "\xce\xba\xe1\xbd\xb9\xcf\x83\xce\xbc\xce\xb5", -1, 11, TRUE }, + /* first sequence of each length */ + { "\x00", -1, 0, TRUE }, + { "\xc2\x80", -1, 2, TRUE }, + { "\xe0\xa0\x80", -1, 3, TRUE }, + { "\xf0\x90\x80\x80", -1, 4, TRUE }, + { "\xf8\x88\x80\x80\x80", -1, 0, FALSE }, + { "\xfc\x84\x80\x80\x80\x80", -1, 0, FALSE }, + /* last sequence of each length */ + { "\x7f", -1, 1, TRUE }, + { "\xdf\xbf", -1, 2, TRUE }, + { "\xef\xbf\xbf", -1, 0, TRUE }, + { "\xf7\xbf\xbf\xbf", -1, 0, TRUE }, + { "\xfb\xbf\xbf\xbf\xbf", -1, 0, FALSE }, + { "\xfd\xbf\xbf\xbf\xbf\xbf", -1, 0, FALSE }, + /* other boundary conditions */ + { "\xed\x9f\xbf", -1, 3, TRUE }, + { "\xee\x80\x80", -1, 3, TRUE }, + { "\xef\xbf\xbd", -1, 3, TRUE }, + { "\xf4\x8f\xbf\xbf", -1, 0, TRUE }, + /* malformed sequences */ + /* continuation bytes */ + { "\x80", -1, 0, FALSE }, + { "\xbf", -1, 0, FALSE }, + { "\x80\xbf", -1, 0, FALSE }, + { "\x80\xbf\x80", -1, 0, FALSE }, + { "\x80\xbf\x80\xbf", -1, 0, FALSE }, + { "\x80\xbf\x80\xbf\x80", -1, 0, FALSE }, + { "\x80\xbf\x80\xbf\x80\xbf", -1, 0, FALSE }, + { "\x80\xbf\x80\xbf\x80\xbf\x80", -1, 0, FALSE }, + + /* all possible continuation byte */ + { "\x80", -1, 0, FALSE }, + { "\x81", -1, 0, FALSE }, + { "\x82", -1, 0, FALSE }, + { "\x83", -1, 0, FALSE }, + { "\x84", -1, 0, FALSE }, + { "\x85", -1, 0, FALSE }, + { "\x86", -1, 0, FALSE }, + { "\x87", -1, 0, FALSE }, + { "\x88", -1, 0, FALSE }, + { "\x89", -1, 0, FALSE }, + { "\x8a", -1, 0, FALSE }, + { "\x8b", -1, 0, FALSE }, + { "\x8c", -1, 0, FALSE }, + { "\x8d", -1, 0, FALSE }, + { "\x8e", -1, 0, FALSE }, + { "\x8f", -1, 0, FALSE }, + { "\x90", -1, 0, FALSE }, + { "\x91", -1, 0, FALSE }, + { "\x92", -1, 0, FALSE }, + { "\x93", -1, 0, FALSE }, + { "\x94", -1, 0, FALSE }, + { "\x95", -1, 0, FALSE }, + { "\x96", -1, 0, FALSE }, + { "\x97", -1, 0, FALSE }, + { "\x98", -1, 0, FALSE }, + { "\x99", -1, 0, FALSE }, + { "\x9a", -1, 0, FALSE }, + { "\x9b", -1, 0, FALSE }, + { "\x9c", -1, 0, FALSE }, + { "\x9d", -1, 0, FALSE }, + { "\x9e", -1, 0, FALSE }, + { "\x9f", -1, 0, FALSE }, + { "\xa0", -1, 0, FALSE }, + { "\xa1", -1, 0, FALSE }, + { "\xa2", -1, 0, FALSE }, + { "\xa3", -1, 0, FALSE }, + { "\xa4", -1, 0, FALSE }, + { "\xa5", -1, 0, FALSE }, + { "\xa6", -1, 0, FALSE }, + { "\xa7", -1, 0, FALSE }, + { "\xa8", -1, 0, FALSE }, + { "\xa9", -1, 0, FALSE }, + { "\xaa", -1, 0, FALSE }, + { "\xab", -1, 0, FALSE }, + { "\xac", -1, 0, FALSE }, + { "\xad", -1, 0, FALSE }, + { "\xae", -1, 0, FALSE }, + { "\xaf", -1, 0, FALSE }, + { "\xb0", -1, 0, FALSE }, + { "\xb1", -1, 0, FALSE }, + { "\xb2", -1, 0, FALSE }, + { "\xb3", -1, 0, FALSE }, + { "\xb4", -1, 0, FALSE }, + { "\xb5", -1, 0, FALSE }, + { "\xb6", -1, 0, FALSE }, + { "\xb7", -1, 0, FALSE }, + { "\xb8", -1, 0, FALSE }, + { "\xb9", -1, 0, FALSE }, + { "\xba", -1, 0, FALSE }, + { "\xbb", -1, 0, FALSE }, + { "\xbc", -1, 0, FALSE }, + { "\xbd", -1, 0, FALSE }, + { "\xbe", -1, 0, FALSE }, + { "\xbf", -1, 0, FALSE }, + /* lone start characters */ + { "\xc0\x20", -1, 0, FALSE }, + { "\xc1\x20", -1, 0, FALSE }, + { "\xc2\x20", -1, 0, FALSE }, + { "\xc3\x20", -1, 0, FALSE }, + { "\xc4\x20", -1, 0, FALSE }, + { "\xc5\x20", -1, 0, FALSE }, + { "\xc6\x20", -1, 0, FALSE }, + { "\xc7\x20", -1, 0, FALSE }, + { "\xc8\x20", -1, 0, FALSE }, + { "\xc9\x20", -1, 0, FALSE }, + { "\xca\x20", -1, 0, FALSE }, + { "\xcb\x20", -1, 0, FALSE }, + { "\xcc\x20", -1, 0, FALSE }, + { "\xcd\x20", -1, 0, FALSE }, + { "\xce\x20", -1, 0, FALSE }, + { "\xcf\x20", -1, 0, FALSE }, + { "\xd0\x20", -1, 0, FALSE }, + { "\xd1\x20", -1, 0, FALSE }, + { "\xd2\x20", -1, 0, FALSE }, + { "\xd3\x20", -1, 0, FALSE }, + { "\xd4\x20", -1, 0, FALSE }, + { "\xd5\x20", -1, 0, FALSE }, + { "\xd6\x20", -1, 0, FALSE }, + { "\xd7\x20", -1, 0, FALSE }, + { "\xd8\x20", -1, 0, FALSE }, + { "\xd9\x20", -1, 0, FALSE }, + { "\xda\x20", -1, 0, FALSE }, + { "\xdb\x20", -1, 0, FALSE }, + { "\xdc\x20", -1, 0, FALSE }, + { "\xdd\x20", -1, 0, FALSE }, + { "\xde\x20", -1, 0, FALSE }, + { "\xdf\x20", -1, 0, FALSE }, + { "\xe0\x20", -1, 0, FALSE }, + { "\xe1\x20", -1, 0, FALSE }, + { "\xe2\x20", -1, 0, FALSE }, + { "\xe3\x20", -1, 0, FALSE }, + { "\xe4\x20", -1, 0, FALSE }, + { "\xe5\x20", -1, 0, FALSE }, + { "\xe6\x20", -1, 0, FALSE }, + { "\xe7\x20", -1, 0, FALSE }, + { "\xe8\x20", -1, 0, FALSE }, + { "\xe9\x20", -1, 0, FALSE }, + { "\xea\x20", -1, 0, FALSE }, + { "\xeb\x20", -1, 0, FALSE }, + { "\xec\x20", -1, 0, FALSE }, + { "\xed\x20", -1, 0, FALSE }, + { "\xee\x20", -1, 0, FALSE }, + { "\xef\x20", -1, 0, FALSE }, + { "\xf0\x20", -1, 0, FALSE }, + { "\xf1\x20", -1, 0, FALSE }, + { "\xf2\x20", -1, 0, FALSE }, + { "\xf3\x20", -1, 0, FALSE }, + { "\xf4\x20", -1, 0, FALSE }, + { "\xf5\x20", -1, 0, FALSE }, + { "\xf6\x20", -1, 0, FALSE }, + { "\xf7\x20", -1, 0, FALSE }, + { "\xf8\x20", -1, 0, FALSE }, + { "\xf9\x20", -1, 0, FALSE }, + { "\xfa\x20", -1, 0, FALSE }, + { "\xfb\x20", -1, 0, FALSE }, + { "\xfc\x20", -1, 0, FALSE }, + { "\xfd\x20", -1, 0, FALSE }, + /* missing continuation bytes */ + { "\x20\xc0", -1, 1, FALSE }, + { "\x20\xe0\x80", -1, 1, FALSE }, + { "\x20\xf0\x80\x80", -1, 1, FALSE }, + { "\x20\xf8\x80\x80\x80", -1, 1, FALSE }, + { "\x20\xfc\x80\x80\x80\x80", -1, 1, FALSE }, + { "\x20\xdf", -1, 1, FALSE }, + { "\x20\xef\xbf", -1, 1, FALSE }, + { "\x20\xf7\xbf\xbf", -1, 1, FALSE }, + { "\x20\xfb\xbf\xbf\xbf", -1, 1, FALSE }, + { "\x20\xfd\xbf\xbf\xbf\xbf", -1, 1, FALSE }, + /* impossible bytes */ + { "\x20\xfe\x20", -1, 1, FALSE }, + { "\x20\xff\x20", -1, 1, FALSE }, +#if 0 + /* XXX fix these, or document that we don't detect them? */ + /* overlong sequences */ + { "\x20\xc0\xaf\x20", -1, 1, FALSE }, + { "\x20\xe0\x80\xaf\x20", -1, 1, FALSE }, + { "\x20\xf0\x80\x80\xaf\x20", -1, 1, FALSE }, + { "\x20\xf8\x80\x80\x80\xaf\x20", -1, 1, FALSE }, + { "\x20\xfc\x80\x80\x80\x80\xaf\x20", -1, 1, FALSE }, + { "\x20\xc1\xbf\x20", -1, 1, FALSE }, + { "\x20\xe0\x9f\xbf\x20", -1, 1, FALSE }, + { "\x20\xf0\x8f\xbf\xbf\x20", -1, 1, FALSE }, + { "\x20\xf8\x87\xbf\xbf\xbf\x20", -1, 1, FALSE }, + { "\x20\xfc\x83\xbf\xbf\xbf\xbf\x20", -1, 1, FALSE }, + { "\x20\xc0\x80\x20", -1, 1, FALSE }, + { "\x20\xe0\x80\x80\x20", -1, 1, FALSE }, + { "\x20\xf0\x80\x80\x80\x20", -1, 1, FALSE }, + { "\x20\xf8\x80\x80\x80\x80\x20", -1, 1, FALSE }, + { "\x20\xfc\x80\x80\x80\x80\x80\x20", -1, 1, FALSE }, + /* illegal code positions */ + { "\x20\xed\xa0\x80\x20", -1, 1, FALSE }, + { "\x20\xed\xad\xbf\x20", -1, 1, FALSE }, + { "\x20\xed\xae\x80\x20", -1, 1, FALSE }, + { "\x20\xed\xaf\xbf\x20", -1, 1, FALSE }, + { "\x20\xed\xb0\x80\x20", -1, 1, FALSE }, + { "\x20\xed\xbe\x80\x20", -1, 1, FALSE }, + { "\x20\xed\xbf\xbf\x20", -1, 1, FALSE }, + { "\x20\xed\xa0\x80\xed\xb0\x80\x20", -1, 1, FALSE }, + { "\x20\xed\xa0\x80\xed\xbf\xbf\x20", -1, 1, FALSE }, + { "\x20\xed\xad\xbf\xed\xb0\x80\x20", -1, 1, FALSE }, + { "\x20\xed\xad\xbf\xed\xbf\xbf\x20", -1, 1, FALSE }, + { "\x20\xed\xae\x80\xed\xb0\x80\x20", -1, 1, FALSE }, + { "\x20\xed\xae\x80\xed\xbf\xbf\x20", -1, 1, FALSE }, + { "\x20\xed\xaf\xbf\xed\xb0\x80\x20", -1, 1, FALSE }, + { "\x20\xed\xaf\xbf\xed\xbf\xbf\x20", -1, 1, FALSE }, + { "\x20\xef\xbf\xbe\x20", -1, 1, FALSE }, + { "\x20\xef\xbf\xbf\x20", -1, 1, FALSE }, +#endif + { "", -1, 0, TRUE } +}; + +static void +test_buffer_utf8_validity (void) +{ + hb_buffer_t *b; + unsigned int i; + + b = hb_buffer_create (); + + for (i = 0; i < G_N_ELEMENTS (utf8_validity_tests); i++) + { + const utf8_validity_test_t *test = &utf8_validity_tests[i]; + unsigned int text_bytes, segment_bytes, j, len; + hb_glyph_info_t *glyphs; + char *escaped; + + escaped = g_strescape (test->utf8, NULL); + g_test_message ("UTF-8 test #%d: %s", i, escaped); + g_free (escaped); + + text_bytes = strlen (test->utf8); + if (test->max_len == -1) + segment_bytes = text_bytes; + else + segment_bytes = test->max_len; + + hb_buffer_reset (b); + hb_buffer_add_utf8 (b, test->utf8, text_bytes, 0, segment_bytes); + + glyphs = hb_buffer_get_glyph_infos (b, &len); + for (j = 0; j < len; j++) + if (glyphs[j].codepoint == (hb_codepoint_t) -1) + break; + + g_assert (test->valid ? j == len : j < len); + if (!test->valid) + g_assert (glyphs[j].cluster == test->offset); + } + + hb_buffer_destroy (b); +} + + +typedef struct { + const uint16_t utf16[8]; + const uint32_t codepoints[8]; +} utf16_conversion_test_t; + +/* note: we skip the first and last item from utf16 when adding to buffer */ +static const utf16_conversion_test_t utf16_conversion_tests[] = { + {{0x41, 0x004D, 0x0430, 0x4E8C, 0xD800, 0xDF02, 0x61} , {0x004D, 0x0430, 0x4E8C, 0x10302}}, + {{0x41, 0xD800, 0xDF02, 0x61}, {0x10302}}, + {{0x41, 0xD800, 0xDF02}, {-1}}, + {{0x41, 0x61, 0xD800, 0xDF02}, {0x61, -1}}, + {{0x41, 0xD800, 0x61, 0xDF02}, {-1, 0x61}}, + {{0x41, 0x61}, {}} +}; + +static void +test_buffer_utf16_conversion (void) +{ + hb_buffer_t *b; + unsigned int i; + + b = hb_buffer_create (); + + for (i = 0; i < G_N_ELEMENTS (utf16_conversion_tests); i++) + { + const utf16_conversion_test_t *test = &utf16_conversion_tests[i]; + unsigned int u_len, chars, j, len; + hb_glyph_info_t *glyphs; + + g_test_message ("UTF-16 test #%d", i); + + for (u_len = 0; test->utf16[u_len]; u_len++) + ; + for (chars = 0; test->codepoints[chars]; chars++) + ; + + hb_buffer_reset (b); + hb_buffer_add_utf16 (b, test->utf16, u_len, 1, u_len - 2); + + glyphs = hb_buffer_get_glyph_infos (b, &len); + g_assert_cmpint (len, ==, chars); + for (j = 0; j < chars; j++) + g_assert_cmphex (glyphs[j].codepoint, ==, test->codepoints[j]); + } + + hb_buffer_destroy (b); +} + +static void +test_empty (hb_buffer_t *b) +{ + g_assert_cmpint (hb_buffer_get_length (b), ==, 0); + g_assert (!hb_buffer_get_glyph_infos (b, NULL)); + g_assert (!hb_buffer_get_glyph_positions (b, NULL)); +} + +static void +test_buffer_empty (void) +{ + hb_buffer_t *b = hb_buffer_get_empty (); + + g_assert (hb_buffer_get_empty ()); + g_assert (hb_buffer_get_empty () == b); + + g_assert (!hb_buffer_allocation_successful (b)); + + test_empty (b); + + hb_buffer_add_utf32 (b, utf32, G_N_ELEMENTS (utf32), 1, G_N_ELEMENTS (utf32) - 2); + + test_empty (b); + + hb_buffer_reverse (b); + hb_buffer_reverse_clusters (b); + + g_assert (!hb_buffer_set_length (b, 10)); + + test_empty (b); + + g_assert (hb_buffer_set_length (b, 0)); + + test_empty (b); + + g_assert (!hb_buffer_allocation_successful (b)); + + hb_buffer_reset (b); + + test_empty (b); + + g_assert (!hb_buffer_allocation_successful (b)); +} + +int +main (int argc, char **argv) +{ + unsigned int i; + + hb_test_init (&argc, &argv); + + for (i = 0; i < BUFFER_NUM_TYPES; i++) + { + const void *buffer_type = GINT_TO_POINTER (i); + const char *buffer_name = buffer_names[i]; + + hb_test_add_fixture_flavor (fixture, buffer_type, buffer_name, test_buffer_properties); + hb_test_add_fixture_flavor (fixture, buffer_type, buffer_name, test_buffer_contents); + hb_test_add_fixture_flavor (fixture, buffer_type, buffer_name, test_buffer_positions); + } + + hb_test_add_fixture (fixture, GINT_TO_POINTER (BUFFER_EMPTY), test_buffer_allocation); + + hb_test_add (test_buffer_utf8_conversion); + hb_test_add (test_buffer_utf8_validity); + hb_test_add (test_buffer_utf16_conversion); + hb_test_add (test_buffer_empty); + + return hb_test_run(); +} diff --git a/test/api/test-c.c b/test/api/test-c.c new file mode 100644 index 0000000..25a38e5 --- /dev/null +++ b/test/api/test-c.c @@ -0,0 +1,58 @@ +/* + * Copyright © 2011 Google, Inc. + * + * This is part of HarfBuzz, a text shaping library. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and its documentation for any purpose, provided that the + * above copyright notice and the following two paragraphs appear in + * all copies of this software. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + * + * Google Author(s): Behdad Esfahbod + */ + +/* This file tests that all headers can be included from .c files */ + + +#include <config.h> + +#include <hb.h> + +#ifdef HAVE_GLIB +#include <hb-glib.h> +#endif + +#ifdef HAVE_ICU +#include <hb-icu.h> +#endif + +#ifdef HAVE_FREETYPE +#include <hb-ft.h> +#endif + +#ifdef HAVE_OT +#include <hb-ot.h> +#endif + +#ifdef HAVE_UNISCRIBE +#include <hb-uniscribe.h> +#endif + +int +main (int argc, char **argv) +{ + return !*hb_shape_list_shapers (); +} diff --git a/test/api/test-common.c b/test/api/test-common.c new file mode 100644 index 0000000..74b50be --- /dev/null +++ b/test/api/test-common.c @@ -0,0 +1,225 @@ +/* + * Copyright © 2011 Google, Inc. + * + * This is part of HarfBuzz, a text shaping library. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and its documentation for any purpose, provided that the + * above copyright notice and the following two paragraphs appear in + * all copies of this software. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + * + * Google Author(s): Behdad Esfahbod + */ + +#include "hb-test.h" + +/* Unit tests for hb-common.h */ + + +static void +test_types_int (void) +{ + /* We already ASSERT_STATIC these in hb-private.h, but anyway */ + g_assert_cmpint (sizeof (int8_t), ==, 1); + g_assert_cmpint (sizeof (uint8_t), ==, 1); + g_assert_cmpint (sizeof (int16_t), ==, 2); + g_assert_cmpint (sizeof (uint16_t), ==, 2); + g_assert_cmpint (sizeof (int32_t), ==, 4); + g_assert_cmpint (sizeof (uint32_t), ==, 4); + g_assert_cmpint (sizeof (int64_t), ==, 8); + g_assert_cmpint (sizeof (uint64_t), ==, 8); + + g_assert_cmpint (sizeof (hb_codepoint_t), ==, 4); + g_assert_cmpint (sizeof (hb_position_t), ==, 4); + g_assert_cmpint (sizeof (hb_mask_t), ==, 4); + g_assert_cmpint (sizeof (hb_var_int_t), ==, 4); +} + +static void +test_types_direction (void) +{ + g_assert_cmpint ((signed) HB_DIRECTION_INVALID, ==, 0); + g_assert_cmpint (HB_DIRECTION_LTR, !=, 0); + + g_assert (HB_DIRECTION_IS_HORIZONTAL (HB_DIRECTION_LTR)); + g_assert (HB_DIRECTION_IS_HORIZONTAL (HB_DIRECTION_RTL)); + g_assert (!HB_DIRECTION_IS_HORIZONTAL (HB_DIRECTION_TTB)); + g_assert (!HB_DIRECTION_IS_HORIZONTAL (HB_DIRECTION_BTT)); + g_assert (!HB_DIRECTION_IS_HORIZONTAL (HB_DIRECTION_INVALID)); + + g_assert (!HB_DIRECTION_IS_VERTICAL (HB_DIRECTION_LTR)); + g_assert (!HB_DIRECTION_IS_VERTICAL (HB_DIRECTION_RTL)); + g_assert (HB_DIRECTION_IS_VERTICAL (HB_DIRECTION_TTB)); + g_assert (HB_DIRECTION_IS_VERTICAL (HB_DIRECTION_BTT)); + g_assert (!HB_DIRECTION_IS_VERTICAL (HB_DIRECTION_INVALID)); + + g_assert (HB_DIRECTION_IS_FORWARD (HB_DIRECTION_LTR)); + g_assert (HB_DIRECTION_IS_FORWARD (HB_DIRECTION_TTB)); + g_assert (!HB_DIRECTION_IS_FORWARD (HB_DIRECTION_RTL)); + g_assert (!HB_DIRECTION_IS_FORWARD (HB_DIRECTION_BTT)); + g_assert (!HB_DIRECTION_IS_FORWARD (HB_DIRECTION_INVALID)); + + g_assert (!HB_DIRECTION_IS_BACKWARD (HB_DIRECTION_LTR)); + g_assert (!HB_DIRECTION_IS_BACKWARD (HB_DIRECTION_TTB)); + g_assert (HB_DIRECTION_IS_BACKWARD (HB_DIRECTION_RTL)); + g_assert (HB_DIRECTION_IS_BACKWARD (HB_DIRECTION_BTT)); + g_assert (!HB_DIRECTION_IS_BACKWARD (HB_DIRECTION_INVALID)); + + g_assert (HB_DIRECTION_IS_VALID (HB_DIRECTION_LTR)); + g_assert (HB_DIRECTION_IS_VALID (HB_DIRECTION_TTB)); + g_assert (HB_DIRECTION_IS_VALID (HB_DIRECTION_RTL)); + g_assert (HB_DIRECTION_IS_VALID (HB_DIRECTION_BTT)); + g_assert (!HB_DIRECTION_IS_VALID (HB_DIRECTION_INVALID)); + g_assert (!HB_DIRECTION_IS_VALID ((hb_direction_t) 0x12345678)); + + g_assert_cmpint (HB_DIRECTION_REVERSE (HB_DIRECTION_LTR), ==, HB_DIRECTION_RTL); + g_assert_cmpint (HB_DIRECTION_REVERSE (HB_DIRECTION_RTL), ==, HB_DIRECTION_LTR); + g_assert_cmpint (HB_DIRECTION_REVERSE (HB_DIRECTION_TTB), ==, HB_DIRECTION_BTT); + g_assert_cmpint (HB_DIRECTION_REVERSE (HB_DIRECTION_BTT), ==, HB_DIRECTION_TTB); + //g_assert_cmpint (HB_DIRECTION_REVERSE (HB_DIRECTION_INVALID), ==, HB_DIRECTION_INVALID); + + g_assert_cmpint (HB_DIRECTION_INVALID, ==, hb_direction_from_string (NULL, -1)); + g_assert_cmpint (HB_DIRECTION_INVALID, ==, hb_direction_from_string ("", -1)); + g_assert_cmpint (HB_DIRECTION_INVALID, ==, hb_direction_from_string ("t", 0)); + g_assert_cmpint (HB_DIRECTION_INVALID, ==, hb_direction_from_string ("x", -1)); + g_assert_cmpint (HB_DIRECTION_RTL, ==, hb_direction_from_string ("r", -1)); + g_assert_cmpint (HB_DIRECTION_RTL, ==, hb_direction_from_string ("rtl", -1)); + g_assert_cmpint (HB_DIRECTION_RTL, ==, hb_direction_from_string ("RtL", -1)); + g_assert_cmpint (HB_DIRECTION_RTL, ==, hb_direction_from_string ("right-to-left", -1)); + g_assert_cmpint (HB_DIRECTION_TTB, ==, hb_direction_from_string ("ttb", -1)); + + g_assert (0 == strcmp ("ltr", hb_direction_to_string (HB_DIRECTION_LTR))); + g_assert (0 == strcmp ("rtl", hb_direction_to_string (HB_DIRECTION_RTL))); + g_assert (0 == strcmp ("ttb", hb_direction_to_string (HB_DIRECTION_TTB))); + g_assert (0 == strcmp ("btt", hb_direction_to_string (HB_DIRECTION_BTT))); + g_assert (0 == strcmp ("invalid", hb_direction_to_string (HB_DIRECTION_INVALID))); +} + +static void +test_types_tag (void) +{ + g_assert_cmphex (HB_TAG_NONE, ==, 0); + + g_assert_cmphex (HB_TAG ('a','B','c','D'), ==, 0x61426344); + + g_assert_cmphex (hb_tag_from_string ("aBcDe", -1), ==, 0x61426344); + g_assert_cmphex (hb_tag_from_string ("aBcD", -1), ==, 0x61426344); + g_assert_cmphex (hb_tag_from_string ("aBc", -1), ==, 0x61426320); + g_assert_cmphex (hb_tag_from_string ("aB", -1), ==, 0x61422020); + g_assert_cmphex (hb_tag_from_string ("a", -1), ==, 0x61202020); + g_assert_cmphex (hb_tag_from_string ("aBcDe", 1), ==, 0x61202020); + g_assert_cmphex (hb_tag_from_string ("aBcDe", 2), ==, 0x61422020); + g_assert_cmphex (hb_tag_from_string ("aBcDe", 3), ==, 0x61426320); + g_assert_cmphex (hb_tag_from_string ("aBcDe", 4), ==, 0x61426344); + g_assert_cmphex (hb_tag_from_string ("aBcDe", 4), ==, 0x61426344); + + g_assert_cmphex (hb_tag_from_string ("", -1), ==, HB_TAG_NONE); + g_assert_cmphex (hb_tag_from_string ("x", 0), ==, HB_TAG_NONE); + g_assert_cmphex (hb_tag_from_string (NULL, -1), ==, HB_TAG_NONE); +} + +static void +test_types_script (void) +{ + hb_tag_t arab = HB_TAG_CHAR4 ("arab"); + hb_tag_t Arab = HB_TAG_CHAR4 ("Arab"); + hb_tag_t ARAB = HB_TAG_CHAR4 ("ARAB"); + + hb_tag_t wWyZ = HB_TAG_CHAR4 ("wWyZ"); + hb_tag_t Wwyz = HB_TAG_CHAR4 ("Wwyz"); + + hb_tag_t x123 = HB_TAG_CHAR4 ("x123"); + + g_assert_cmpint (HB_SCRIPT_INVALID, ==, (hb_script_t) HB_TAG_NONE); + g_assert_cmphex (HB_SCRIPT_ARABIC, !=, HB_SCRIPT_LATIN); + + g_assert_cmphex (HB_SCRIPT_INVALID, ==, hb_script_from_string (NULL, -1)); + g_assert_cmphex (HB_SCRIPT_INVALID, ==, hb_script_from_string ("", -1)); + g_assert_cmphex (HB_SCRIPT_INVALID, ==, hb_script_from_string ("x", 0)); + g_assert_cmphex (HB_SCRIPT_UNKNOWN, ==, hb_script_from_string ("x", -1)); + + g_assert_cmphex (HB_SCRIPT_ARABIC, ==, hb_script_from_string ("arab", -1)); + g_assert_cmphex (HB_SCRIPT_ARABIC, ==, hb_script_from_string ("Arab", -1)); + g_assert_cmphex (HB_SCRIPT_ARABIC, ==, hb_script_from_string ("ARAB", -1)); + g_assert_cmphex (HB_SCRIPT_ARABIC, ==, hb_script_from_string ("Arabic", 6)); + g_assert_cmphex (HB_SCRIPT_ARABIC, !=, hb_script_from_string ("Arabic", 3)); + + g_assert_cmphex (HB_SCRIPT_ARABIC, ==, hb_script_from_iso15924_tag (arab)); + g_assert_cmphex (HB_SCRIPT_ARABIC, ==, hb_script_from_iso15924_tag (Arab)); + g_assert_cmphex (HB_SCRIPT_ARABIC, ==, hb_script_from_iso15924_tag (ARAB)); + + /* Arbitrary tags that look like may be valid ISO 15924 should be preserved. */ + g_assert_cmphex (HB_SCRIPT_UNKNOWN, !=, hb_script_from_string ("wWyZ", -1)); + g_assert_cmphex (HB_SCRIPT_UNKNOWN, !=, hb_script_from_iso15924_tag (wWyZ)); + /* Otherwise, UNKNOWN should be returned. */ + g_assert_cmphex (HB_SCRIPT_UNKNOWN, ==, hb_script_from_string ("x123", -1)); + g_assert_cmphex (HB_SCRIPT_UNKNOWN, ==, hb_script_from_iso15924_tag (x123)); + + g_assert_cmphex (hb_script_to_iso15924_tag (HB_SCRIPT_ARABIC), ==, Arab); + g_assert_cmphex (hb_script_to_iso15924_tag (hb_script_from_iso15924_tag (wWyZ)), ==, Wwyz); + + g_assert_cmpint (hb_script_get_horizontal_direction (HB_SCRIPT_LATIN), ==, HB_DIRECTION_LTR); + g_assert_cmpint (hb_script_get_horizontal_direction (HB_SCRIPT_ARABIC), ==, HB_DIRECTION_RTL); + g_assert_cmpint (hb_script_get_horizontal_direction (hb_script_from_iso15924_tag (wWyZ)), ==, HB_DIRECTION_LTR); +} + +static void +test_types_language (void) +{ + hb_language_t fa = hb_language_from_string ("fa", -1); + hb_language_t fa_IR = hb_language_from_string ("fa_IR", -1); + hb_language_t fa_ir = hb_language_from_string ("fa-ir", -1); + hb_language_t en = hb_language_from_string ("en", -1); + + g_assert (HB_LANGUAGE_INVALID == NULL); + + g_assert (fa != NULL); + g_assert (fa_IR != NULL); + g_assert (fa_IR == fa_ir); + + g_assert (en != NULL); + g_assert (en != fa); + + /* Test recall */ + g_assert (en == hb_language_from_string ("en", -1)); + g_assert (en == hb_language_from_string ("eN", -1)); + g_assert (en == hb_language_from_string ("Enx", 2)); + + g_assert (HB_LANGUAGE_INVALID == hb_language_from_string (NULL, -1)); + g_assert (HB_LANGUAGE_INVALID == hb_language_from_string ("", -1)); + g_assert (HB_LANGUAGE_INVALID == hb_language_from_string ("en", 0)); + g_assert (HB_LANGUAGE_INVALID != hb_language_from_string ("en", 1)); + g_assert (NULL == hb_language_to_string (HB_LANGUAGE_INVALID)); + + /* Not sure how to test this better. Setting env vars + * here doesn't sound like the right approach, and I'm + * not sure that it even works. */ + g_assert (HB_LANGUAGE_INVALID != hb_language_get_default ()); +} + +int +main (int argc, char **argv) +{ + hb_test_init (&argc, &argv); + + hb_test_add (test_types_int); + hb_test_add (test_types_direction); + hb_test_add (test_types_tag); + hb_test_add (test_types_script); + hb_test_add (test_types_language); + + return hb_test_run(); +} diff --git a/test/api/test-cplusplus.cc b/test/api/test-cplusplus.cc new file mode 100644 index 0000000..3313d74 --- /dev/null +++ b/test/api/test-cplusplus.cc @@ -0,0 +1,30 @@ +/* + * Copyright © 2011 Google, Inc. + * + * This is part of HarfBuzz, a text shaping library. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and its documentation for any purpose, provided that the + * above copyright notice and the following two paragraphs appear in + * all copies of this software. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + * + * Google Author(s): Behdad Esfahbod + */ + +/* This file tests that all headers can be included from .cc files */ + + +#include "test-c.c" diff --git a/test/api/test-font.c b/test/api/test-font.c new file mode 100644 index 0000000..40540c4 --- /dev/null +++ b/test/api/test-font.c @@ -0,0 +1,502 @@ +/* + * Copyright © 2011 Google, Inc. + * + * This is part of HarfBuzz, a text shaping library. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and its documentation for any purpose, provided that the + * above copyright notice and the following two paragraphs appear in + * all copies of this software. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + * + * Google Author(s): Behdad Esfahbod + */ + +#include "hb-test.h" + +/* Unit tests for hb-font.h */ + + +static const char test_data[] = "test\0data"; + + +static void +test_face_empty (void) +{ + g_assert (hb_face_get_empty ()); + g_assert (hb_face_get_empty () == hb_face_create (hb_blob_get_empty (), 0)); + g_assert (hb_face_get_empty () == hb_face_create (NULL, 0)); + + g_assert (hb_face_reference_table (hb_face_get_empty (), HB_TAG ('h','e','a','d')) == hb_blob_get_empty ()); + + g_assert_cmpint (hb_face_get_upem (hb_face_get_empty ()), ==, 1000); +} + +static void +test_face_create (void) +{ + hb_face_t *face; + hb_blob_t *blob; + + blob = hb_blob_create (test_data, sizeof (test_data), HB_MEMORY_MODE_READONLY, NULL, NULL); + face = hb_face_create (blob, 0); + hb_blob_destroy (blob); + + g_assert (hb_face_reference_table (face, HB_TAG ('h','e','a','d')) == hb_blob_get_empty ()); + + g_assert_cmpint (hb_face_get_upem (face), ==, 1000); + + hb_face_destroy (face); +} + + +static void +free_up (void *user_data) +{ + int *freed = (int *) user_data; + + g_assert (!*freed); + + (*freed)++; +} + +static hb_blob_t * +get_table (hb_face_t *face, hb_tag_t tag, void *user_data) +{ + if (tag == HB_TAG ('a','b','c','d')) + return hb_blob_create (test_data, sizeof (test_data), HB_MEMORY_MODE_READONLY, NULL, NULL); + + return hb_blob_get_empty (); +} + +static void +test_face_createfortables (void) +{ + hb_face_t *face; + hb_blob_t *blob; + const char *data; + unsigned int len; + int freed = 0; + + face = hb_face_create_for_tables (get_table, &freed, free_up); + g_assert (!freed); + + g_assert (hb_face_reference_table (face, HB_TAG ('h','e','a','d')) == hb_blob_get_empty ()); + + blob = hb_face_reference_table (face, HB_TAG ('a','b','c','d')); + g_assert (blob != hb_blob_get_empty ()); + + data = hb_blob_get_data (blob, &len); + g_assert_cmpint (len, ==, sizeof (test_data)); + g_assert (0 == memcmp (data, test_data, sizeof (test_data))); + hb_blob_destroy (blob); + + g_assert_cmpint (hb_face_get_upem (face), ==, 1000); + + hb_face_destroy (face); + g_assert (freed); +} + +static void +_test_font_nil_funcs (hb_font_t *font) +{ + hb_codepoint_t glyph; + hb_position_t x, y; + hb_glyph_extents_t extents; + + x = y = 13; + g_assert (!hb_font_get_glyph_contour_point (font, 17, 2, &x, &y)); + g_assert_cmpint (x, ==, 0); + g_assert_cmpint (y, ==, 0); + + x = hb_font_get_glyph_h_advance (font, 17); + g_assert_cmpint (x, ==, 0); + + extents.x_bearing = extents.y_bearing = 13; + extents.width = extents.height = 15; + hb_font_get_glyph_extents (font, 17, &extents); + g_assert_cmpint (extents.x_bearing, ==, 0); + g_assert_cmpint (extents.y_bearing, ==, 0); + g_assert_cmpint (extents.width, ==, 0); + g_assert_cmpint (extents.height, ==, 0); + + glyph = 3; + g_assert (!hb_font_get_glyph (font, 17, 2, &glyph)); + g_assert_cmpint (glyph, ==, 0); + + x = 13; + x = hb_font_get_glyph_h_kerning (font, 17, 19); + g_assert_cmpint (x, ==, 0); +} + +static void +_test_fontfuncs_nil (hb_font_funcs_t *ffuncs) +{ + hb_blob_t *blob; + hb_face_t *face; + hb_font_t *font; + hb_font_t *subfont; + int freed = 0; + + blob = hb_blob_create (test_data, sizeof (test_data), HB_MEMORY_MODE_READONLY, NULL, NULL); + face = hb_face_create (blob, 0); + hb_blob_destroy (blob); + g_assert (!hb_face_is_immutable (face)); + font = hb_font_create (face); + g_assert (font); + g_assert (hb_face_is_immutable (face)); + hb_face_destroy (face); + + + hb_font_set_funcs (font, ffuncs, &freed, free_up); + g_assert_cmpint (freed, ==, 0); + + _test_font_nil_funcs (font); + + subfont = hb_font_create_sub_font (font); + g_assert (subfont); + + g_assert_cmpint (freed, ==, 0); + hb_font_destroy (font); + g_assert_cmpint (freed, ==, 0); + + _test_font_nil_funcs (subfont); + + hb_font_destroy (subfont); + g_assert_cmpint (freed, ==, 1); +} + +static void +test_fontfuncs_empty (void) +{ + g_assert (hb_font_funcs_get_empty ()); + g_assert (hb_font_funcs_is_immutable (hb_font_funcs_get_empty ())); + _test_fontfuncs_nil (hb_font_funcs_get_empty ()); +} + +static void +test_fontfuncs_nil (void) +{ + hb_font_funcs_t *ffuncs; + + ffuncs = hb_font_funcs_create (); + + g_assert (!hb_font_funcs_is_immutable (ffuncs)); + _test_fontfuncs_nil (hb_font_funcs_get_empty ()); + + hb_font_funcs_destroy (ffuncs); +} + +static hb_bool_t +contour_point_func1 (hb_font_t *font, void *font_data, + hb_codepoint_t glyph, unsigned int point_index, + hb_position_t *x, hb_position_t *y, + void *user_data) +{ + if (glyph == 1) { + *x = 2; + *y = 3; + return TRUE; + } + if (glyph == 2) { + *x = 4; + *y = 5; + return TRUE; + } + + return FALSE; +} + +static hb_bool_t +contour_point_func2 (hb_font_t *font, void *font_data, + hb_codepoint_t glyph, unsigned int point_index, + hb_position_t *x, hb_position_t *y, + void *user_data) +{ + if (glyph == 1) { + *x = 6; + *y = 7; + return TRUE; + } + + return hb_font_get_glyph_contour_point (hb_font_get_parent (font), + glyph, point_index, x, y); +} + +static hb_position_t +glyph_h_advance_func1 (hb_font_t *font, void *font_data, + hb_codepoint_t glyph, + void *user_data) +{ + if (glyph == 1) + return 8; + + return 0; +} + +static void +test_fontfuncs_subclassing (void) +{ + hb_blob_t *blob; + hb_face_t *face; + + hb_font_funcs_t *ffuncs1; + hb_font_funcs_t *ffuncs2; + + hb_font_t *font1; + hb_font_t *font2; + hb_font_t *font3; + + hb_position_t x; + hb_position_t y; + + blob = hb_blob_create (test_data, sizeof (test_data), HB_MEMORY_MODE_READONLY, NULL, NULL); + face = hb_face_create (blob, 0); + hb_blob_destroy (blob); + font1 = hb_font_create (face); + hb_face_destroy (face); + hb_font_set_scale (font1, 10, 10); + + /* setup font1 */ + ffuncs1 = hb_font_funcs_create (); + hb_font_funcs_set_glyph_contour_point_func (ffuncs1, contour_point_func1, NULL, NULL); + hb_font_funcs_set_glyph_h_advance_func (ffuncs1, glyph_h_advance_func1, NULL, NULL); + hb_font_set_funcs (font1, ffuncs1, NULL, NULL); + hb_font_funcs_destroy (ffuncs1); + + x = y = 1; + g_assert (hb_font_get_glyph_contour_point_for_origin (font1, 1, 2, HB_DIRECTION_LTR, &x, &y)); + g_assert_cmpint (x, ==, 2); + g_assert_cmpint (y, ==, 3); + g_assert (hb_font_get_glyph_contour_point_for_origin (font1, 2, 5, HB_DIRECTION_LTR, &x, &y)); + g_assert_cmpint (x, ==, 4); + g_assert_cmpint (y, ==, 5); + g_assert (!hb_font_get_glyph_contour_point_for_origin (font1, 3, 7, HB_DIRECTION_RTL, &x, &y)); + g_assert_cmpint (x, ==, 0); + g_assert_cmpint (y, ==, 0); + x = hb_font_get_glyph_h_advance (font1, 1); + g_assert_cmpint (x, ==, 8); + x = hb_font_get_glyph_h_advance (font1, 2); + g_assert_cmpint (x, ==, 0); + + + font2 = hb_font_create_sub_font (font1); + g_assert (hb_font_is_immutable (font1)); + hb_font_destroy (font1); + + /* setup font2 to override some funcs */ + ffuncs2 = hb_font_funcs_create (); + hb_font_funcs_set_glyph_contour_point_func (ffuncs2, contour_point_func2, NULL, NULL); + hb_font_set_funcs (font2, ffuncs2, NULL, NULL); + hb_font_funcs_destroy (ffuncs2); + + x = y = 1; + g_assert (hb_font_get_glyph_contour_point_for_origin (font2, 1, 2, HB_DIRECTION_LTR, &x, &y)); + g_assert_cmpint (x, ==, 6); + g_assert_cmpint (y, ==, 7); + g_assert (hb_font_get_glyph_contour_point_for_origin (font2, 2, 5, HB_DIRECTION_RTL, &x, &y)); + g_assert_cmpint (x, ==, 4); + g_assert_cmpint (y, ==, 5); + g_assert (!hb_font_get_glyph_contour_point_for_origin (font2, 3, 7, HB_DIRECTION_LTR, &x, &y)); + g_assert_cmpint (x, ==, 0); + g_assert_cmpint (y, ==, 0); + x = hb_font_get_glyph_h_advance (font2, 1); + g_assert_cmpint (x, ==, 8); + x = hb_font_get_glyph_h_advance (font2, 2); + g_assert_cmpint (x, ==, 0); + + + font3 = hb_font_create_sub_font (font2); + g_assert (hb_font_is_immutable (font2)); + hb_font_destroy (font2); + + /* setup font3 to override scale */ + hb_font_set_scale (font3, 20, 30); + + x = y = 1; + g_assert (hb_font_get_glyph_contour_point_for_origin (font3, 1, 2, HB_DIRECTION_RTL, &x, &y)); + g_assert_cmpint (x, ==, 6*2); + g_assert_cmpint (y, ==, 7*3); + g_assert (hb_font_get_glyph_contour_point_for_origin (font3, 2, 5, HB_DIRECTION_LTR, &x, &y)); + g_assert_cmpint (x, ==, 4*2); + g_assert_cmpint (y, ==, 5*3); + g_assert (!hb_font_get_glyph_contour_point_for_origin (font3, 3, 7, HB_DIRECTION_LTR, &x, &y)); + g_assert_cmpint (x, ==, 0*2); + g_assert_cmpint (y, ==, 0*3); + x = hb_font_get_glyph_h_advance (font3, 1); + g_assert_cmpint (x, ==, 8*2); + x = hb_font_get_glyph_h_advance (font3, 2); + g_assert_cmpint (x, ==, 0*2); + + + hb_font_destroy (font3); +} + + +static void +test_font_empty (void) +{ + g_assert (hb_font_get_empty ()); + g_assert (hb_font_get_empty () == hb_font_create (hb_face_get_empty ())); + g_assert (hb_font_get_empty () == hb_font_create (NULL)); + g_assert (hb_font_get_empty () == hb_font_create_sub_font (NULL)); + g_assert (hb_font_is_immutable (hb_font_get_empty ())); + + g_assert (hb_font_get_face (hb_font_get_empty ()) == hb_face_get_empty ()); + g_assert (hb_font_get_parent (hb_font_get_empty ()) == NULL); +} + +static void +test_font_properties (void) +{ + hb_blob_t *blob; + hb_face_t *face; + hb_font_t *font; + hb_font_t *subfont; + int x_scale, y_scale; + unsigned int x_ppem, y_ppem; + + blob = hb_blob_create (test_data, sizeof (test_data), HB_MEMORY_MODE_READONLY, NULL, NULL); + face = hb_face_create (blob, 0); + hb_blob_destroy (blob); + font = hb_font_create (face); + hb_face_destroy (face); + + + g_assert (hb_font_get_face (font) == face); + g_assert (hb_font_get_parent (font) == NULL); + + + /* Check scale */ + + hb_font_get_scale (font, NULL, NULL); + x_scale = y_scale = 13; + hb_font_get_scale (font, &x_scale, NULL); + g_assert_cmpint (x_scale, ==, 0); + x_scale = y_scale = 13; + hb_font_get_scale (font, NULL, &y_scale); + g_assert_cmpint (y_scale, ==, 0); + x_scale = y_scale = 13; + hb_font_get_scale (font, &x_scale, &y_scale); + g_assert_cmpint (x_scale, ==, 0); + g_assert_cmpint (y_scale, ==, 0); + + hb_font_set_scale (font, 17, 19); + + x_scale = y_scale = 13; + hb_font_get_scale (font, &x_scale, &y_scale); + g_assert_cmpint (x_scale, ==, 17); + g_assert_cmpint (y_scale, ==, 19); + + + /* Check ppem */ + + hb_font_get_ppem (font, NULL, NULL); + x_ppem = y_ppem = 13; + hb_font_get_ppem (font, &x_ppem, NULL); + g_assert_cmpint (x_ppem, ==, 0); + x_ppem = y_ppem = 13; + hb_font_get_ppem (font, NULL, &y_ppem); + g_assert_cmpint (y_ppem, ==, 0); + x_ppem = y_ppem = 13; + hb_font_get_ppem (font, &x_ppem, &y_ppem); + g_assert_cmpint (x_ppem, ==, 0); + g_assert_cmpint (y_ppem, ==, 0); + + hb_font_set_ppem (font, 17, 19); + + x_ppem = y_ppem = 13; + hb_font_get_ppem (font, &x_ppem, &y_ppem); + g_assert_cmpint (x_ppem, ==, 17); + g_assert_cmpint (y_ppem, ==, 19); + + + /* Check immutable */ + + g_assert (!hb_font_is_immutable (font)); + hb_font_make_immutable (font); + g_assert (hb_font_is_immutable (font)); + + hb_font_set_scale (font, 10, 12); + x_scale = y_scale = 13; + hb_font_get_scale (font, &x_scale, &y_scale); + g_assert_cmpint (x_scale, ==, 17); + g_assert_cmpint (y_scale, ==, 19); + + hb_font_set_ppem (font, 10, 12); + x_ppem = y_ppem = 13; + hb_font_get_ppem (font, &x_ppem, &y_ppem); + g_assert_cmpint (x_ppem, ==, 17); + g_assert_cmpint (y_ppem, ==, 19); + + + /* sub_font now */ + subfont = hb_font_create_sub_font (font); + hb_font_destroy (font); + + g_assert (hb_font_get_parent (subfont) == font); + g_assert (hb_font_get_face (subfont) == face); + + /* scale */ + x_scale = y_scale = 13; + hb_font_get_scale (subfont, &x_scale, &y_scale); + g_assert_cmpint (x_scale, ==, 17); + g_assert_cmpint (y_scale, ==, 19); + hb_font_set_scale (subfont, 10, 12); + x_scale = y_scale = 13; + hb_font_get_scale (subfont, &x_scale, &y_scale); + g_assert_cmpint (x_scale, ==, 10); + g_assert_cmpint (y_scale, ==, 12); + x_scale = y_scale = 13; + hb_font_get_scale (font, &x_scale, &y_scale); + g_assert_cmpint (x_scale, ==, 17); + g_assert_cmpint (y_scale, ==, 19); + + /* ppem */ + x_ppem = y_ppem = 13; + hb_font_get_ppem (subfont, &x_ppem, &y_ppem); + g_assert_cmpint (x_ppem, ==, 17); + g_assert_cmpint (y_ppem, ==, 19); + hb_font_set_ppem (subfont, 10, 12); + x_ppem = y_ppem = 13; + hb_font_get_ppem (subfont, &x_ppem, &y_ppem); + g_assert_cmpint (x_ppem, ==, 10); + g_assert_cmpint (y_ppem, ==, 12); + x_ppem = y_ppem = 13; + hb_font_get_ppem (font, &x_ppem, &y_ppem); + g_assert_cmpint (x_ppem, ==, 17); + g_assert_cmpint (y_ppem, ==, 19); + + hb_font_destroy (subfont); +} + +int +main (int argc, char **argv) +{ + hb_test_init (&argc, &argv); + + hb_test_add (test_face_empty); + hb_test_add (test_face_create); + hb_test_add (test_face_createfortables); + + hb_test_add (test_fontfuncs_empty); + hb_test_add (test_fontfuncs_nil); + hb_test_add (test_fontfuncs_subclassing); + + hb_test_add (test_font_empty); + hb_test_add (test_font_properties); + + return hb_test_run(); +} diff --git a/test/api/test-object.c b/test/api/test-object.c new file mode 100644 index 0000000..66e8d33 --- /dev/null +++ b/test/api/test-object.c @@ -0,0 +1,367 @@ +/* + * Copyright © 2011 Google, Inc. + * + * This is part of HarfBuzz, a text shaping library. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and its documentation for any purpose, provided that the + * above copyright notice and the following two paragraphs appear in + * all copies of this software. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + * + * Google Author(s): Behdad Esfahbod + */ + +#include "hb-test.h" + +/* Unit tests for hb-object-private.h */ + + +static void * +create_blob (void) +{ + static char data[] = "test data"; + return hb_blob_create (data, sizeof (data), HB_MEMORY_MODE_READONLY, NULL, NULL); +} +static void * +create_blob_inert (void) +{ + return hb_blob_create (NULL, 0, HB_MEMORY_MODE_DUPLICATE, NULL, NULL); +} + +static void * +create_buffer (void) +{ + return hb_buffer_create (); +} +static void * +create_buffer_inert (void) +{ + return NULL; +} + +static void * +create_face (void) +{ + hb_blob_t *blob = (hb_blob_t *) create_blob (); + hb_face_t *face = hb_face_create (blob, 0); + hb_blob_destroy (blob); + return face; +} +static void * +create_face_inert (void) +{ + return hb_face_create (hb_blob_get_empty (), 0); +} + +static void * +create_font (void) +{ + hb_face_t *face = (hb_face_t *) create_face (); + hb_font_t *font = hb_font_create (face); + hb_face_destroy (face); + return font; +} +static void * +create_font_inert (void) +{ + return hb_font_create (hb_face_get_empty ()); +} + +static void * +create_font_funcs (void) +{ + return hb_font_funcs_create (); +} +static void * +create_font_funcs_inert (void) +{ + return NULL; +} + +static void * +create_unicode_funcs (void) +{ + return hb_unicode_funcs_create (NULL); +} +static void * +create_unicode_funcs_inert (void) +{ + return hb_unicode_funcs_get_default (); +} + + + +typedef void *(*create_func_t) (void); +typedef void *(*reference_func_t) (void *obj); +typedef void (*destroy_func_t) (void *obj); +typedef hb_bool_t (*set_user_data_func_t) (void *obj, hb_user_data_key_t *key, void *data, hb_destroy_func_t destroy, hb_bool_t replace); +typedef void * (*get_user_data_func_t) (void *obj, hb_user_data_key_t *key); +typedef void (*make_immutable_func_t) (void *obj); +typedef hb_bool_t (*is_immutable_func_t) (void *obj); + +typedef struct { + create_func_t create; + create_func_t create_inert; + create_func_t get_empty; + reference_func_t reference; + destroy_func_t destroy; + set_user_data_func_t set_user_data; + get_user_data_func_t get_user_data; + make_immutable_func_t make_immutable; + is_immutable_func_t is_immutable; + const char *name; +} object_t; + +#define OBJECT_WITHOUT_IMMUTABILITY(name) \ + { \ + (create_func_t) create_##name, \ + (create_func_t) create_##name##_inert, \ + (create_func_t) hb_##name##_get_empty, \ + (reference_func_t) hb_##name##_reference, \ + (destroy_func_t) hb_##name##_destroy, \ + (set_user_data_func_t) hb_##name##_set_user_data, \ + (get_user_data_func_t) hb_##name##_get_user_data, \ + (make_immutable_func_t) NULL, \ + (is_immutable_func_t) NULL, \ + #name, \ + } +#define OBJECT_WITH_IMMUTABILITY(name) \ + { \ + (create_func_t) create_##name, \ + (create_func_t) create_##name##_inert, \ + (create_func_t) hb_##name##_get_empty, \ + (reference_func_t) hb_##name##_reference, \ + (destroy_func_t) hb_##name##_destroy, \ + (set_user_data_func_t) hb_##name##_set_user_data, \ + (get_user_data_func_t) hb_##name##_get_user_data, \ + (make_immutable_func_t) hb_##name##_make_immutable, \ + (is_immutable_func_t) hb_##name##_is_immutable, \ + #name, \ + } +static const object_t objects[] = +{ + OBJECT_WITHOUT_IMMUTABILITY (buffer), + OBJECT_WITH_IMMUTABILITY (blob), + OBJECT_WITH_IMMUTABILITY (face), + OBJECT_WITH_IMMUTABILITY (font), + OBJECT_WITH_IMMUTABILITY (font_funcs), + OBJECT_WITH_IMMUTABILITY (unicode_funcs) +}; +#undef OBJECT + + +#define MAGIC0 0x12345678 +#define MAGIC1 0x76543210 + +typedef struct { + int value; + gboolean freed; +} data_t; + +static int global_data; + +static void global_free_up (void *p G_GNUC_UNUSED) +{ + global_data++; +} + +static void free_up0 (void *p) +{ + data_t *data = (data_t *) p; + + g_assert_cmphex (data->value, ==, MAGIC0); + g_assert (!data->freed); + data->freed = TRUE; +} + +static void free_up1 (void *p) +{ + data_t *data = (data_t *) p; + + g_assert_cmphex (data->value, ==, MAGIC1); + g_assert (!data->freed); + data->freed = TRUE; +} + + +typedef struct { + const object_t *klass; + void *object; + hb_user_data_key_t key; +} deadlock_test_t; + +static void free_deadlock_test (void *p) +{ + deadlock_test_t *t = (deadlock_test_t *) p; + + g_assert (NULL == t->klass->get_user_data (t->object, &t->key)); +} + + +static void +test_object (void) +{ + unsigned int i; + + for (i = 0; i < G_N_ELEMENTS (objects); i++) { + const object_t *o = &objects[i]; + void *obj; + hb_user_data_key_t key[2]; + + { + unsigned int j; + data_t data[2] = {{MAGIC0, FALSE}, {MAGIC1, FALSE}}; + deadlock_test_t deadlock_test; + + g_test_message ("Testing object %s", o->name); + + g_test_message ("->create()"); + obj = o->create (); + g_assert (obj); + + g_assert (obj == o->reference (obj)); + o->destroy (obj); + + if (o->is_immutable) + g_assert (!o->is_immutable (obj)); + + g_assert (o->set_user_data (obj, &key[0], &data[0], free_up0, TRUE)); + g_assert (o->get_user_data (obj, &key[0]) == &data[0]); + + if (o->is_immutable) { + o->make_immutable (obj); + g_assert (o->is_immutable (obj)); + } + + /* Should still work even if object is made immutable */ + g_assert (o->set_user_data (obj, &key[1], &data[1], free_up1, TRUE)); + g_assert (o->get_user_data (obj, &key[1]) == &data[1]); + + g_assert (!o->set_user_data (obj, NULL, &data[0], free_up0, TRUE)); + g_assert (o->get_user_data (obj, &key[0]) == &data[0]); + g_assert (o->set_user_data (obj, &key[0], &data[1], NULL, TRUE)); + g_assert (data[0].freed); + g_assert (o->get_user_data (obj, &key[0]) == &data[1]); + g_assert (!data[1].freed); + + data[0].freed = FALSE; + g_assert (o->set_user_data (obj, &key[0], &data[0], free_up0, TRUE)); + g_assert (!data[0].freed); + g_assert (o->set_user_data (obj, &key[0], NULL, NULL, TRUE)); + g_assert (data[0].freed); + + data[0].freed = FALSE; + global_data = 0; + g_assert (o->set_user_data (obj, &key[0], &data[0], free_up0, TRUE)); + g_assert (!o->set_user_data (obj, &key[0], &data[0], free_up0, FALSE)); + g_assert_cmpuint (global_data, ==, 0); + g_assert (o->set_user_data (obj, &key[0], NULL, global_free_up, TRUE)); + g_assert_cmpuint (global_data, ==, 0); + g_assert (o->set_user_data (obj, &key[0], NULL, NULL, TRUE)); + g_assert_cmpuint (global_data, ==, 1); + + global_data = 0; + for (j = 2; j < 1000; j++) + g_assert (o->set_user_data (obj, &key[j], &data[j], global_free_up, TRUE)); + for (j = 2; j < 1000; j++) + g_assert (o->get_user_data (obj, &key[j]) == &data[j]); + for (j = 100; j < 1000; j++) + g_assert (o->set_user_data (obj, &key[j], NULL, NULL, TRUE)); + for (j = 2; j < 100; j++) + g_assert (o->get_user_data (obj, &key[j]) == &data[j]); + for (j = 100; j < 1000; j++) + g_assert (!o->get_user_data (obj, &key[j])); + g_assert_cmpuint (global_data, ==, 900); + + /* Test set_user_data where the destroy() func calls user_data functions. + * Make sure it doesn't deadlock or corrupt memory. */ + deadlock_test.klass = o; + deadlock_test.object = obj; + g_assert (o->set_user_data (obj, &deadlock_test.key, &deadlock_test, free_deadlock_test, TRUE)); + g_assert (o->set_user_data (obj, &deadlock_test.key, NULL, NULL, TRUE)); + + g_assert (!data[1].freed); + o->destroy (obj); + g_assert (data[0].freed); + g_assert (data[1].freed); + g_assert_cmpuint (global_data, ==, 1000-2); + } + + { + data_t data[2] = {{MAGIC0, FALSE}, {MAGIC1, FALSE}}; + + g_test_message ("->get_empty()"); + obj = o->get_empty (); + g_assert (obj); + + g_assert (obj == o->reference (obj)); + o->destroy (obj); + + if (o->is_immutable) + g_assert (o->is_immutable (obj)); + + g_assert (!o->set_user_data (obj, &key[0], &data[0], free_up0, TRUE)); + g_assert (!o->get_user_data (obj, &key[0])); + + o->destroy (obj); + o->destroy (obj); + o->destroy (obj); + o->destroy (obj); + o->destroy (obj); + + g_assert (!data[0].freed); + } + + { + data_t data[2] = {{MAGIC0, FALSE}, {MAGIC1, FALSE}}; + + g_test_message ("->create_inert()"); + obj = o->create_inert (); + if (!obj) + continue; + if (obj == o->get_empty ()) + continue; /* Tested already */ + + g_assert (obj == o->reference (obj)); + o->destroy (obj); + + if (o->is_immutable) + g_assert (o->is_immutable (obj)); + + g_assert (!o->set_user_data (obj, &key[0], &data[0], free_up0, TRUE)); + g_assert (!o->get_user_data (obj, &key[0])); + + o->destroy (obj); + o->destroy (obj); + o->destroy (obj); + o->destroy (obj); + o->destroy (obj); + + g_assert (!data[0].freed); + } + } +} + + +int +main (int argc, char **argv) +{ + hb_test_init (&argc, &argv); + + hb_test_add (test_object); + + return hb_test_run (); +} diff --git a/test/api/test-ot-tag.c b/test/api/test-ot-tag.c new file mode 100644 index 0000000..81b6678 --- /dev/null +++ b/test/api/test-ot-tag.c @@ -0,0 +1,241 @@ +/* + * Copyright © 2011 Google, Inc. + * + * This is part of HarfBuzz, a text shaping library. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and its documentation for any purpose, provided that the + * above copyright notice and the following two paragraphs appear in + * all copies of this software. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + * + * Google Author(s): Behdad Esfahbod + */ + +#include "hb-test.h" + +#include <hb-ot.h> + +/* Unit tests for hb-ot-tag.h */ + + +/* https://www.microsoft.com/typography/otspec/scripttags.htm */ + +static void +test_simple_tags (const char *s, hb_script_t script) +{ + hb_script_t tag; + hb_script_t t1, t2; + + g_test_message ("Testing script %c%c%c%c: tag %s", HB_UNTAG (hb_script_to_iso15924_tag (script)), s); + tag = hb_tag_from_string (s, -1); + + hb_ot_tags_from_script (script, &t1, &t2); + + g_assert_cmphex (t1, ==, tag); + g_assert_cmphex (t2, ==, HB_OT_TAG_DEFAULT_SCRIPT); + + g_assert_cmphex (hb_ot_tag_to_script (tag), ==, script); +} + +static void +test_indic_tags (const char *s1, const char *s2, hb_script_t script) +{ + hb_script_t tag1, tag2; + hb_script_t t1, t2; + + g_test_message ("Testing script %c%c%c%c: new tag %s, old tag %s", HB_UNTAG (hb_script_to_iso15924_tag (script)), s1, s2); + tag1 = hb_tag_from_string (s1, -1); + tag2 = hb_tag_from_string (s2, -1); + + hb_ot_tags_from_script (script, &t1, &t2); + + g_assert_cmphex (t1, ==, tag1); + g_assert_cmphex (t2, ==, tag2); + + g_assert_cmphex (hb_ot_tag_to_script (tag1), ==, script); + g_assert_cmphex (hb_ot_tag_to_script (tag2), ==, script); +} + +static void +test_ot_tag_script_degenerate (void) +{ + hb_script_t t1, t2; + + g_assert_cmphex (HB_TAG_CHAR4 ("DFLT"), ==, HB_OT_TAG_DEFAULT_SCRIPT); + + /* HIRAGANA and KATAKANA both map to 'kana' */ + test_simple_tags ("kana", HB_SCRIPT_KATAKANA); + hb_ot_tags_from_script (HB_SCRIPT_HIRAGANA, &t1, &t2); + g_assert_cmphex (t1, ==, HB_TAG_CHAR4 ("kana")); + g_assert_cmphex (t2, ==, HB_OT_TAG_DEFAULT_SCRIPT); + + test_simple_tags ("DFLT", HB_SCRIPT_INVALID); + + /* Spaces are replaced */ + g_assert_cmphex (hb_ot_tag_to_script (HB_TAG_CHAR4 ("be ")), ==, hb_script_from_string ("Beee", -1)); +} + +static void +test_ot_tag_script_simple (void) +{ + /* Arbitrary non-existent script */ + test_simple_tags ("wwyz", hb_script_from_string ("wWyZ", -1)); + + /* These we don't really care about */ + test_simple_tags ("zyyy", HB_SCRIPT_COMMON); + test_simple_tags ("zinh", HB_SCRIPT_INHERITED); + test_simple_tags ("zzzz", HB_SCRIPT_UNKNOWN); + + test_simple_tags ("arab", HB_SCRIPT_ARABIC); + test_simple_tags ("copt", HB_SCRIPT_COPTIC); + test_simple_tags ("kana", HB_SCRIPT_KATAKANA); + test_simple_tags ("latn", HB_SCRIPT_LATIN); + + /* These are trickier since their OT script tags have space. */ + test_simple_tags ("lao ", HB_SCRIPT_LAO); + test_simple_tags ("yi ", HB_SCRIPT_YI); + /* Unicode-5.0 additions */ + test_simple_tags ("nko ", HB_SCRIPT_NKO); + /* Unicode-5.1 additions */ + test_simple_tags ("vai ", HB_SCRIPT_VAI); + + /* https://www.microsoft.com/typography/otspec160/scripttagsProposed.htm */ + + /* Unicode-5.2 additions */ + test_simple_tags ("mtei", HB_SCRIPT_MEETEI_MAYEK); + /* Unicode-6.0 additions */ + test_simple_tags ("mand", HB_SCRIPT_MANDAIC); +} + +static void +test_ot_tag_script_indic (void) +{ + test_indic_tags ("bng2", "beng", HB_SCRIPT_BENGALI); + test_indic_tags ("dev2", "deva", HB_SCRIPT_DEVANAGARI); + test_indic_tags ("gjr2", "gujr", HB_SCRIPT_GUJARATI); + test_indic_tags ("gur2", "guru", HB_SCRIPT_GURMUKHI); + test_indic_tags ("knd2", "knda", HB_SCRIPT_KANNADA); + test_indic_tags ("mlm2", "mlym", HB_SCRIPT_MALAYALAM); + test_indic_tags ("ory2", "orya", HB_SCRIPT_ORIYA); + test_indic_tags ("tml2", "taml", HB_SCRIPT_TAMIL); + test_indic_tags ("tel2", "telu", HB_SCRIPT_TELUGU); +} + + + +/* https://www.microsoft.com/typography/otspec/languagetags.htm */ + +static void +test_language_two_way (const char *tag_s, const char *lang_s) +{ + hb_language_t lang = hb_language_from_string (lang_s, -1); + hb_tag_t tag = hb_tag_from_string (tag_s, -1); + + g_test_message ("Testing language %s <-> tag %s", lang_s, tag_s); + + g_assert_cmphex (tag, ==, hb_ot_tag_from_language (lang)); + g_assert (lang == hb_ot_tag_to_language (tag)); +} + +static void +test_tag_from_language (const char *tag_s, const char *lang_s) +{ + hb_language_t lang = hb_language_from_string (lang_s, -1); + hb_tag_t tag = hb_tag_from_string (tag_s, -1); + + g_test_message ("Testing language %s -> tag %s", lang_s, tag_s); + + g_assert_cmphex (tag, ==, hb_ot_tag_from_language (lang)); +} + +static void +test_tag_to_language (const char *tag_s, const char *lang_s) +{ + hb_language_t lang = hb_language_from_string (lang_s, -1); + hb_tag_t tag = hb_tag_from_string (tag_s, -1); + + g_test_message ("Testing tag %s -> language %s", tag_s, lang_s); + + g_assert (lang == hb_ot_tag_to_language (tag)); +} + +static void +test_ot_tag_language (void) +{ + g_assert_cmphex (HB_TAG_CHAR4 ("dflt"), ==, HB_OT_TAG_DEFAULT_LANGUAGE); + test_language_two_way ("dflt", NULL); + + test_language_two_way ("ARA", "ar"); + + test_language_two_way ("AZE", "az"); + test_tag_from_language ("AZE", "az-ir"); + test_tag_from_language ("AZE", "az-az"); + + test_language_two_way ("ENG", "en"); + test_tag_from_language ("ENG", "en_US"); + + test_language_two_way ("EVN", "eve"); + + test_language_two_way ("FAR", "fa"); + test_tag_from_language ("FAR", "fa_IR"); + + test_language_two_way ("ZHH", "zh-hk"); /* Chinese (Hong Kong) */ + + test_tag_from_language ("ZHS", "zh-cn"); /* Chinese (China) */ + test_tag_from_language ("ZHS", "zh-sg"); /* Chinese (Singapore) */ + test_tag_from_language ("ZHT", "zh-mo"); /* Chinese (Macao) */ + test_tag_from_language ("ZHT", "zh-tw"); /* Chinese (Taiwan) */ + + test_tag_from_language ("ZHS", "zh"); /* Chinese */ + test_tag_from_language ("ZHS", "zh-xx"); + + test_tag_to_language ("ZHS", "zh-x-hbotzhs"); + test_tag_to_language ("ZHT", "zh-x-hbotzht"); + test_tag_to_language ("ZHP", "zh-x-hbotzhp"); + + test_language_two_way ("ABC", "x-hbotabc"); + test_tag_from_language ("ABC", "asdf-asdf-wer-x-hbotabc-zxc"); + test_tag_from_language ("ABC", "asdf-asdf-wer-x-hbotabc"); + test_tag_from_language ("ABCD", "asdf-asdf-wer-x-hbotabcd"); + + test_tag_from_language ("dflt", "asdf-asdf-wer-x-hbot-zxc"); + + test_tag_from_language ("dflt", "xy"); + test_tag_from_language ("XYZ", "xyz"); /* Unknown ISO 639-3 */ + test_tag_from_language ("XYZ", "xyz-qw"); /* Unknown ISO 639-3 */ + + /* Test that x-hbot overrides the base language */ + test_tag_from_language ("ABC", "fa-x-hbotabc-zxc"); + test_tag_from_language ("ABC", "fa-ir-x-hbotabc-zxc"); + test_tag_from_language ("ABC", "zh-x-hbotabc-zxc"); + test_tag_from_language ("ABC", "zh-cn-x-hbotabc-zxc"); + test_tag_from_language ("ABC", "zh-xy-x-hbotabc-zxc"); + test_tag_from_language ("ABC", "xyz-xy-x-hbotabc-zxc"); +} + +int +main (int argc, char **argv) +{ + hb_test_init (&argc, &argv); + + hb_test_add (test_ot_tag_script_degenerate); + hb_test_add (test_ot_tag_script_simple); + hb_test_add (test_ot_tag_script_indic); + + hb_test_add (test_ot_tag_language); + + return hb_test_run(); +} diff --git a/test/api/test-shape.c b/test/api/test-shape.c new file mode 100644 index 0000000..ccf6eed --- /dev/null +++ b/test/api/test-shape.c @@ -0,0 +1,165 @@ +/* + * Copyright © 2011 Google, Inc. + * + * This is part of HarfBuzz, a text shaping library. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and its documentation for any purpose, provided that the + * above copyright notice and the following two paragraphs appear in + * all copies of this software. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + * + * Google Author(s): Behdad Esfahbod + */ + +#include "hb-test.h" + +/* Unit tests for hb-shape.h */ + +/* + * This test provides a framework to test aspects of hb_shape() that are + * font-independent. Please add tests for any feature that fits that + * description. + */ + +/* TODO Make this test data-driven and add some real test data */ +/* TODO Test positions too. And test non-native direction. Test commit 2e18c6dbdfb */ + + +static const char test_data[] = "test\0data"; + +static hb_position_t +glyph_h_advance_func (hb_font_t *font, void *font_data, + hb_codepoint_t glyph, + void *user_data) +{ + switch (glyph) { + case 1: return 10; + case 2: return 6; + case 3: return 5; + } + return 0; +} + +static hb_bool_t +glyph_func (hb_font_t *font, void *font_data, + hb_codepoint_t unicode, hb_codepoint_t variant_selector, + hb_codepoint_t *glyph, + void *user_data) +{ + switch (unicode) { + case 'T': *glyph = 1; return TRUE; + case 'e': *glyph = 2; return TRUE; + case 's': *glyph = 3; return TRUE; + } + return FALSE; +} + +static hb_position_t +glyph_h_kerning_func (hb_font_t *font, void *font_data, + hb_codepoint_t left, hb_codepoint_t right, + void *user_data) +{ + if (left == 1 && right == 2) + return -2; + + return 0; +} + +static const char TesT[] = "TesT"; + +static void +test_shape (void) +{ + hb_blob_t *blob; + hb_face_t *face; + hb_font_funcs_t *ffuncs; + hb_font_t *font; + hb_buffer_t *buffer; + unsigned int len; + hb_glyph_info_t *glyphs; + hb_glyph_position_t *positions; + + blob = hb_blob_create (test_data, sizeof (test_data), HB_MEMORY_MODE_READONLY, NULL, NULL); + face = hb_face_create (blob, 0); + hb_blob_destroy (blob); + font = hb_font_create (face); + hb_face_destroy (face); + hb_font_set_scale (font, 10, 10); + + ffuncs = hb_font_funcs_create (); + hb_font_funcs_set_glyph_h_advance_func (ffuncs, glyph_h_advance_func, NULL, NULL); + hb_font_funcs_set_glyph_func (ffuncs, glyph_func, NULL, NULL); + hb_font_funcs_set_glyph_h_kerning_func (ffuncs, glyph_h_kerning_func, NULL, NULL); + hb_font_set_funcs (font, ffuncs, NULL, NULL); + hb_font_funcs_destroy (ffuncs); + + buffer = hb_buffer_create (); + hb_buffer_set_direction (buffer, HB_DIRECTION_LTR); + hb_buffer_add_utf8 (buffer, TesT, 4, 0, 4); + + hb_shape (font, buffer, NULL, 0); + + len = hb_buffer_get_length (buffer); + glyphs = hb_buffer_get_glyph_infos (buffer, NULL); + positions = hb_buffer_get_glyph_positions (buffer, NULL); + + { + const hb_codepoint_t output_glyphs[] = {1, 2, 3, 1}; + const hb_position_t output_x_advances[] = {9, 5, 5, 10}; + const hb_position_t output_x_offsets[] = {0, -1, 0, 0}; + unsigned int i; + g_assert_cmpint (len, ==, 4); + for (i = 0; i < len; i++) { + g_assert_cmphex (glyphs[i].codepoint, ==, output_glyphs[i]); + g_assert_cmphex (glyphs[i].cluster, ==, i); + } + for (i = 0; i < len; i++) { + g_assert_cmpint (output_x_advances[i], ==, positions[i].x_advance); + g_assert_cmpint (output_x_offsets [i], ==, positions[i].x_offset); + g_assert_cmpint (0, ==, positions[i].y_advance); + g_assert_cmpint (0, ==, positions[i].y_offset); + } + } + + hb_buffer_destroy (buffer); + hb_font_destroy (font); +} + +static void +test_shape_list (void) +{ + const char **shapers = hb_shape_list_shapers (); + + unsigned int i; + for (i = 0; shapers[i]; i++) + ; + + g_assert_cmpint (i, >, 1); + g_assert (!strcmp (shapers[i - 1], "fallback")); +} + +int +main (int argc, char **argv) +{ + hb_test_init (&argc, &argv); + + hb_test_add (test_shape); + /* TODO test fallback shaper */ + /* TODO test shaper_full */ + hb_test_add (test_shape_list); + + return hb_test_run(); +} diff --git a/test/api/test-unicode.c b/test/api/test-unicode.c new file mode 100644 index 0000000..96c61dd --- /dev/null +++ b/test/api/test-unicode.c @@ -0,0 +1,937 @@ +/* + * Copyright © 2011 Codethink Limited + * Copyright © 2011 Google, Inc. + * + * This is part of HarfBuzz, a text shaping library. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and its documentation for any purpose, provided that the + * above copyright notice and the following two paragraphs appear in + * all copies of this software. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + * + * Codethink Author(s): Ryan Lortie + * Google Author(s): Behdad Esfahbod + */ + +#include "hb-test.h" + +/* Unit tests for hb-unicode.h */ +/* Unit tests for hb-glib.h */ +/* Unit tests for hb-icu.h */ + + +#ifdef HAVE_GLIB +#include <hb-glib.h> +#endif +#ifdef HAVE_ICU +#include <hb-icu.h> +#endif + + +/* Some useful stuff */ + +#define MAGIC0 0x12345678 +#define MAGIC1 0x76543210 + +typedef struct { + int value; + gboolean freed; +} data_t; + +static void free_up (void *p) +{ + data_t *data = (data_t *) p; + + g_assert (data->value == MAGIC0 || data->value == MAGIC1); + g_assert (!data->freed); + data->freed = TRUE; +} + +static hb_script_t +simple_get_script (hb_unicode_funcs_t *ufuncs, + hb_codepoint_t codepoint, + void *user_data) +{ + data_t *data = (data_t *) user_data; + + g_assert (hb_unicode_funcs_get_parent (ufuncs) != NULL); + g_assert_cmphex (data->value, ==, MAGIC0); + g_assert (!data->freed); + + if ('a' <= codepoint && codepoint <= 'z') + return HB_SCRIPT_LATIN; + else + return HB_SCRIPT_UNKNOWN; +} + +static hb_script_t +a_is_for_arabic_get_script (hb_unicode_funcs_t *ufuncs, + hb_codepoint_t codepoint, + void *user_data) +{ + data_t *data = (data_t *) user_data; + + g_assert (hb_unicode_funcs_get_parent (ufuncs) != NULL); + g_assert_cmphex (data->value, ==, MAGIC1); + g_assert (!data->freed); + + if (codepoint == 'a') { + return HB_SCRIPT_ARABIC; + } else { + hb_unicode_funcs_t *parent = hb_unicode_funcs_get_parent (ufuncs); + + return hb_unicode_script (parent, codepoint); + } +} + + + +/* Check all properties */ + +/* Some of the following tables where adapted from glib/glib/tests/utf8-misc.c. + * The license is compatible. */ + +typedef struct { + hb_codepoint_t unicode; + unsigned int value; +} test_pair_t; + +static const test_pair_t combining_class_tests[] = +{ + { 0x0020, 0 }, + { 0x0334, 1 }, + { 0x093C, 7 }, + { 0x3099, 8 }, + { 0x094D, 9 }, + { 0x05B0, 10 }, + { 0x05B1, 11 }, + { 0x05B2, 12 }, + { 0x05B3, 13 }, + { 0x05B4, 14 }, + { 0x05B5, 15 }, + { 0x05B6, 16 }, + { 0x05B7, 17 }, + { 0x05B8, 18 }, + { 0x05B9, 19 }, + { 0x05BB, 20 }, + { 0x05BC, 21 }, + { 0x05BD, 22 }, + { 0x05BF, 23 }, + { 0x05C1, 24 }, + { 0x05C2, 25 }, + { 0xFB1E, 26 }, + { 0x064B, 27 }, + { 0x064C, 28 }, + { 0x064D, 29 }, + /* ... */ + { 0x05AE, 228 }, + { 0x0300, 230 }, + { 0x302C, 232 }, + { 0x0362, 233 }, + { 0x0360, 234 }, + { 0x0345, 240 }, + + { 0x111111, 0 } +}; +static const test_pair_t combining_class_tests_more[] = +{ + /* Unicode-5.1 character additions */ + { 0x1DCD, 234 }, + + /* Unicode-5.2 character additions */ + { 0xA8E0, 230 }, + + /* Unicode-6.0 character additions */ + { 0x135D, 230 }, + + { 0x111111, 0 } +}; + +static const test_pair_t eastasian_width_tests[] = +{ + /* Neutral */ + { 0x0000, 1 }, + { 0x0483, 1 }, + { 0x0641, 1 }, + { 0xFFFC, 1 }, + { 0x10000, 1 }, + { 0xE0001, 1 }, + + /* Narrow */ + { 0x0020, 1 }, + { 0x0041, 1 }, + { 0x27E6, 1 }, + + /* Halfwidth */ + { 0x20A9, 1 }, + { 0xFF61, 1 }, + { 0xFF69, 1 }, + { 0xFFEE, 1 }, + + /* Ambiguous */ + { 0x00A1, 1 }, + { 0x00D8, 1 }, + { 0x02DD, 1 }, + { 0xE0100, 1 }, + { 0x100000, 1 }, + + /* Fullwidth */ + { 0x3000, 2 }, + { 0xFF60, 2 }, + + /* Wide */ + { 0x2329, 2 }, + { 0x3001, 2 }, + { 0xFE69, 2 }, + { 0x30000, 2 }, + { 0x3FFFD, 2 }, + + { 0x111111, 1 } +}; +static const test_pair_t eastasian_width_tests_more[] = +{ + /* Default Wide blocks */ + { 0x4DBF, 2 }, + { 0x9FFF, 2 }, + { 0xFAFF, 2 }, + { 0x2A6DF, 2 }, + { 0x2B73F, 2 }, + { 0x2B81F, 2 }, + { 0x2FA1F, 2 }, + + /* Uniode-5.2 character additions */ + /* Wide */ + { 0x115F, 2 }, + + /* Uniode-6.0 character additions */ + /* Wide */ + { 0x2B740, 2 }, + { 0x1B000, 2 }, + + { 0x111111, 1 } +}; + +static const test_pair_t general_category_tests[] = +{ + { 0x000D, HB_UNICODE_GENERAL_CATEGORY_CONTROL }, + { 0x200E, HB_UNICODE_GENERAL_CATEGORY_FORMAT }, + { 0x0378, HB_UNICODE_GENERAL_CATEGORY_UNASSIGNED }, + { 0xE000, HB_UNICODE_GENERAL_CATEGORY_PRIVATE_USE }, + { 0xD800, HB_UNICODE_GENERAL_CATEGORY_SURROGATE }, + { 0x0061, HB_UNICODE_GENERAL_CATEGORY_LOWERCASE_LETTER }, + { 0x02B0, HB_UNICODE_GENERAL_CATEGORY_MODIFIER_LETTER }, + { 0x3400, HB_UNICODE_GENERAL_CATEGORY_OTHER_LETTER }, + { 0x01C5, HB_UNICODE_GENERAL_CATEGORY_TITLECASE_LETTER }, + { 0xFF21, HB_UNICODE_GENERAL_CATEGORY_UPPERCASE_LETTER }, + { 0x0903, HB_UNICODE_GENERAL_CATEGORY_SPACING_MARK }, + { 0x20DD, HB_UNICODE_GENERAL_CATEGORY_ENCLOSING_MARK }, + { 0xA806, HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK }, + { 0xFF10, HB_UNICODE_GENERAL_CATEGORY_DECIMAL_NUMBER }, + { 0x16EE, HB_UNICODE_GENERAL_CATEGORY_LETTER_NUMBER }, + { 0x17F0, HB_UNICODE_GENERAL_CATEGORY_OTHER_NUMBER }, + { 0x005F, HB_UNICODE_GENERAL_CATEGORY_CONNECT_PUNCTUATION }, + { 0x058A, HB_UNICODE_GENERAL_CATEGORY_DASH_PUNCTUATION }, + { 0x0F3B, HB_UNICODE_GENERAL_CATEGORY_CLOSE_PUNCTUATION }, + { 0x2019, HB_UNICODE_GENERAL_CATEGORY_FINAL_PUNCTUATION }, + { 0x2018, HB_UNICODE_GENERAL_CATEGORY_INITIAL_PUNCTUATION }, + { 0x2016, HB_UNICODE_GENERAL_CATEGORY_OTHER_PUNCTUATION }, + { 0x0F3A, HB_UNICODE_GENERAL_CATEGORY_OPEN_PUNCTUATION }, + { 0x20A0, HB_UNICODE_GENERAL_CATEGORY_CURRENCY_SYMBOL }, + { 0x309B, HB_UNICODE_GENERAL_CATEGORY_MODIFIER_SYMBOL }, + { 0xFB29, HB_UNICODE_GENERAL_CATEGORY_MATH_SYMBOL }, + { 0x00A6, HB_UNICODE_GENERAL_CATEGORY_OTHER_SYMBOL }, + { 0x2028, HB_UNICODE_GENERAL_CATEGORY_LINE_SEPARATOR }, + { 0x2029, HB_UNICODE_GENERAL_CATEGORY_PARAGRAPH_SEPARATOR }, + { 0x202F, HB_UNICODE_GENERAL_CATEGORY_SPACE_SEPARATOR }, + + { 0x111111, HB_UNICODE_GENERAL_CATEGORY_UNASSIGNED } +}; +static const test_pair_t general_category_tests_more[] = +{ + /* Unicode-5.2 character additions */ + { 0x1F131, HB_UNICODE_GENERAL_CATEGORY_OTHER_SYMBOL }, + + /* Unicode-6.0 character additions */ + { 0x0620, HB_UNICODE_GENERAL_CATEGORY_OTHER_LETTER }, + + { 0x111111, HB_UNICODE_GENERAL_CATEGORY_UNASSIGNED } +}; + +static const test_pair_t mirroring_tests[] = +{ + /* Some characters that do NOT mirror */ + { 0x0020, 0x0020 }, + { 0x0041, 0x0041 }, + { 0x00F0, 0x00F0 }, + { 0x27CC, 0x27CC }, + { 0xE01EF, 0xE01EF }, + { 0x1D7C3, 0x1D7C3 }, + { 0x100000, 0x100000 }, + + /* Some characters that do mirror */ + { 0x0029, 0x0028 }, + { 0x0028, 0x0029 }, + { 0x003E, 0x003C }, + { 0x003C, 0x003E }, + { 0x005D, 0x005B }, + { 0x005B, 0x005D }, + { 0x007D, 0x007B }, + { 0x007B, 0x007D }, + { 0x00BB, 0x00AB }, + { 0x00AB, 0x00BB }, + { 0x226B, 0x226A }, + { 0x226A, 0x226B }, + { 0x22F1, 0x22F0 }, + { 0x22F0, 0x22F1 }, + { 0xFF60, 0xFF5F }, + { 0xFF5F, 0xFF60 }, + { 0xFF63, 0xFF62 }, + { 0xFF62, 0xFF63 }, + + { 0x111111, 0x111111 }, +}; +static const test_pair_t mirroring_tests_more[] = +{ + /* No new mirroring characters have been encoded in recent Unicode versions. */ + { 0x111111, 0x111111 } +}; + +static const test_pair_t script_tests[] = +{ + { 0x002A, HB_SCRIPT_COMMON }, + { 0x0670, HB_SCRIPT_INHERITED }, + { 0x060D, HB_SCRIPT_ARABIC }, + { 0x0559, HB_SCRIPT_ARMENIAN }, + { 0x09CD, HB_SCRIPT_BENGALI }, + { 0x31B6, HB_SCRIPT_BOPOMOFO }, + { 0x13A2, HB_SCRIPT_CHEROKEE }, + { 0x2CFD, HB_SCRIPT_COPTIC }, + { 0x0482, HB_SCRIPT_CYRILLIC }, + { 0x10401, HB_SCRIPT_DESERET }, + { 0x094D, HB_SCRIPT_DEVANAGARI }, + { 0x1258, HB_SCRIPT_ETHIOPIC }, + { 0x10FC, HB_SCRIPT_GEORGIAN }, + { 0x10341, HB_SCRIPT_GOTHIC }, + { 0x0375, HB_SCRIPT_GREEK }, + { 0x0A83, HB_SCRIPT_GUJARATI }, + { 0x0A3C, HB_SCRIPT_GURMUKHI }, + { 0x3005, HB_SCRIPT_HAN }, + { 0x1100, HB_SCRIPT_HANGUL }, + { 0x05BF, HB_SCRIPT_HEBREW }, + { 0x309F, HB_SCRIPT_HIRAGANA }, + { 0x0CBC, HB_SCRIPT_KANNADA }, + { 0x30FF, HB_SCRIPT_KATAKANA }, + { 0x17DD, HB_SCRIPT_KHMER }, + { 0x0EDD, HB_SCRIPT_LAO }, + { 0x0061, HB_SCRIPT_LATIN }, + { 0x0D3D, HB_SCRIPT_MALAYALAM }, + { 0x1843, HB_SCRIPT_MONGOLIAN }, + { 0x1031, HB_SCRIPT_MYANMAR }, + { 0x169C, HB_SCRIPT_OGHAM }, + { 0x10322, HB_SCRIPT_OLD_ITALIC }, + { 0x0B3C, HB_SCRIPT_ORIYA }, + { 0x16EF, HB_SCRIPT_RUNIC }, + { 0x0DBD, HB_SCRIPT_SINHALA }, + { 0x0711, HB_SCRIPT_SYRIAC }, + { 0x0B82, HB_SCRIPT_TAMIL }, + { 0x0C03, HB_SCRIPT_TELUGU }, + { 0x07B1, HB_SCRIPT_THAANA }, + { 0x0E31, HB_SCRIPT_THAI }, + { 0x0FD4, HB_SCRIPT_TIBETAN }, + { 0x1401, HB_SCRIPT_CANADIAN_ABORIGINAL }, + { 0xA015, HB_SCRIPT_YI }, + { 0x1700, HB_SCRIPT_TAGALOG }, + { 0x1720, HB_SCRIPT_HANUNOO }, + { 0x1740, HB_SCRIPT_BUHID }, + { 0x1760, HB_SCRIPT_TAGBANWA }, + + /* Unicode-4.0 additions */ + { 0x2800, HB_SCRIPT_BRAILLE }, + { 0x10808, HB_SCRIPT_CYPRIOT }, + { 0x1932, HB_SCRIPT_LIMBU }, + { 0x10480, HB_SCRIPT_OSMANYA }, + { 0x10450, HB_SCRIPT_SHAVIAN }, + { 0x10000, HB_SCRIPT_LINEAR_B }, + { 0x1950, HB_SCRIPT_TAI_LE }, + { 0x1039F, HB_SCRIPT_UGARITIC }, + + /* Unicode-4.1 additions */ + { 0x1980, HB_SCRIPT_NEW_TAI_LUE }, + { 0x1A1F, HB_SCRIPT_BUGINESE }, + { 0x2C00, HB_SCRIPT_GLAGOLITIC }, + { 0x2D6F, HB_SCRIPT_TIFINAGH }, + { 0xA800, HB_SCRIPT_SYLOTI_NAGRI }, + { 0x103D0, HB_SCRIPT_OLD_PERSIAN }, + { 0x10A3F, HB_SCRIPT_KHAROSHTHI }, + + /* Unicode-5.0 additions */ + { 0x0378, HB_SCRIPT_UNKNOWN }, + { 0x1B04, HB_SCRIPT_BALINESE }, + { 0x12000, HB_SCRIPT_CUNEIFORM }, + { 0x10900, HB_SCRIPT_PHOENICIAN }, + { 0xA840, HB_SCRIPT_PHAGS_PA }, + { 0x07C0, HB_SCRIPT_NKO }, + + /* Unicode-5.1 additions */ + { 0xA900, HB_SCRIPT_KAYAH_LI }, + { 0x1C00, HB_SCRIPT_LEPCHA }, + { 0xA930, HB_SCRIPT_REJANG }, + { 0x1B80, HB_SCRIPT_SUNDANESE }, + { 0xA880, HB_SCRIPT_SAURASHTRA }, + { 0xAA00, HB_SCRIPT_CHAM }, + { 0x1C50, HB_SCRIPT_OL_CHIKI }, + { 0xA500, HB_SCRIPT_VAI }, + { 0x102A0, HB_SCRIPT_CARIAN }, + { 0x10280, HB_SCRIPT_LYCIAN }, + { 0x1093F, HB_SCRIPT_LYDIAN }, + + { 0x111111, HB_SCRIPT_UNKNOWN } +}; +static const test_pair_t script_tests_more[] = +{ + /* Unicode-5.2 additions */ + { 0x10B00, HB_SCRIPT_AVESTAN }, + { 0xA6A0, HB_SCRIPT_BAMUM }, + { 0x13000, HB_SCRIPT_EGYPTIAN_HIEROGLYPHS }, + { 0x10840, HB_SCRIPT_IMPERIAL_ARAMAIC }, + { 0x10B60, HB_SCRIPT_INSCRIPTIONAL_PAHLAVI }, + { 0x10B40, HB_SCRIPT_INSCRIPTIONAL_PARTHIAN }, + { 0xA980, HB_SCRIPT_JAVANESE }, + { 0x11082, HB_SCRIPT_KAITHI }, + { 0xA4D0, HB_SCRIPT_LISU }, + { 0xABE5, HB_SCRIPT_MEETEI_MAYEK }, + { 0x10A60, HB_SCRIPT_OLD_SOUTH_ARABIAN }, + { 0x10C00, HB_SCRIPT_OLD_TURKIC }, + { 0x0800, HB_SCRIPT_SAMARITAN }, + { 0x1A20, HB_SCRIPT_TAI_THAM }, + { 0xAA80, HB_SCRIPT_TAI_VIET }, + + /* Unicode-6.0 additions */ + { 0x1BC0, HB_SCRIPT_BATAK }, + { 0x11000, HB_SCRIPT_BRAHMI }, + { 0x0840, HB_SCRIPT_MANDAIC }, + + /* Unicode-5.2 character additions */ + { 0x1CED, HB_SCRIPT_INHERITED }, + { 0x1400, HB_SCRIPT_CANADIAN_ABORIGINAL }, + + { 0x111111, HB_SCRIPT_UNKNOWN } +}; + + +typedef unsigned int (*get_func_t) (hb_unicode_funcs_t *ufuncs, + hb_codepoint_t unicode, + void *user_data); +typedef unsigned int (*func_setter_func_t) (hb_unicode_funcs_t *ufuncs, + get_func_t func, + void *user_data, + hb_destroy_func_t destroy); +typedef unsigned int (*getter_func_t) (hb_unicode_funcs_t *ufuncs, + hb_codepoint_t unicode); + +typedef struct { + const char *name; + func_setter_func_t func_setter; + getter_func_t getter; + const test_pair_t *tests; + unsigned int num_tests; + const test_pair_t *tests_more; + unsigned int num_tests_more; + unsigned int default_value; +} property_t; + +#define RETURNS_UNICODE_ITSELF ((unsigned int) -1) + +#define PROPERTY(name, DEFAULT) \ + { \ + #name, \ + (func_setter_func_t) hb_unicode_funcs_set_##name##_func, \ + (getter_func_t) hb_unicode_##name, \ + name##_tests, \ + G_N_ELEMENTS (name##_tests), \ + name##_tests_more, \ + G_N_ELEMENTS (name##_tests_more), \ + DEFAULT \ + } +static const property_t properties[] = +{ + PROPERTY (combining_class, 0), + PROPERTY (eastasian_width, 1), + PROPERTY (general_category, (unsigned int) HB_UNICODE_GENERAL_CATEGORY_OTHER_LETTER), + PROPERTY (mirroring, RETURNS_UNICODE_ITSELF), + PROPERTY (script, (unsigned int) HB_SCRIPT_UNKNOWN) +}; +#undef PROPERTY + +static void +test_unicode_properties (gconstpointer user_data) +{ + hb_unicode_funcs_t *uf = (hb_unicode_funcs_t *) user_data; + unsigned int i, j; + gboolean failed = TRUE; + + g_assert (hb_unicode_funcs_is_immutable (uf)); + g_assert (hb_unicode_funcs_get_parent (uf)); + + for (i = 0; i < G_N_ELEMENTS (properties); i++) { + const property_t *p = &properties[i]; + const test_pair_t *tests; + + g_test_message ("Testing property %s", p->name); + tests = p->tests; + for (j = 0; j < p->num_tests; j++) { + g_test_message ("Test %s #%d: U+%04X", p->name, j, tests[j].unicode); + g_assert_cmphex (p->getter (uf, tests[j].unicode), ==, tests[j].value); + } + /* These tests are from Unicode 5.2 onward and older glib/ICU + * don't get them right. Just warn instead of assert. */ + tests = p->tests_more; + for (j = 0; j < p->num_tests_more; j++) { + g_test_message ("Test %s more #%d: U+%04X", p->name, j, tests[j].unicode); + if (p->getter (uf, tests[j].unicode) != tests[j].value) { + g_test_message ("Soft fail: Received %x, expected %x", p->getter (uf, tests[j].unicode), tests[j].value); + failed = TRUE; + } + } + } + + if (failed) + g_test_message ("Some property tests failed. You probably have an old version of one of the libraries used."); +} + +static hb_codepoint_t +default_value (hb_codepoint_t _default_value, hb_codepoint_t unicode) +{ + return _default_value == RETURNS_UNICODE_ITSELF ? unicode : _default_value; +} + +static void +_test_unicode_properties_nil (hb_unicode_funcs_t *uf) +{ + unsigned int i, j; + + for (i = 0; i < G_N_ELEMENTS (properties); i++) { + const property_t *p = &properties[i]; + const test_pair_t *tests; + + g_test_message ("Testing property %s", p->name); + tests = p->tests; + for (j = 0; j < p->num_tests; j++) { + g_test_message ("Test %s #%d: U+%04X", p->name, j, tests[j].unicode); + g_assert_cmphex (p->getter (uf, tests[j].unicode), ==, default_value (p->default_value, tests[j].unicode)); + } + tests = p->tests_more; + for (j = 0; j < p->num_tests_more; j++) { + g_test_message ("Test %s more #%d: U+%04X", p->name, j, tests[j].unicode); + g_assert_cmphex (p->getter (uf, tests[j].unicode), ==, default_value (p->default_value, tests[j].unicode)); + } + } +} + +static void +test_unicode_properties_nil (void) +{ + hb_unicode_funcs_t *uf = hb_unicode_funcs_create (NULL); + + g_assert (!hb_unicode_funcs_is_immutable (uf)); + _test_unicode_properties_nil (uf); + + hb_unicode_funcs_destroy (uf); +} + +static void +test_unicode_properties_empty (void) +{ + hb_unicode_funcs_t *uf = hb_unicode_funcs_get_empty (); + + g_assert (uf); + g_assert (hb_unicode_funcs_is_immutable (uf)); + _test_unicode_properties_nil (uf); +} + + +static void +test_unicode_chainup (void) +{ + hb_unicode_funcs_t *uf, *uf2; + + /* Chain-up to nil */ + + uf = hb_unicode_funcs_create (NULL); + g_assert (!hb_unicode_funcs_is_immutable (uf)); + + uf2 = hb_unicode_funcs_create (uf); + g_assert (hb_unicode_funcs_is_immutable (uf)); + hb_unicode_funcs_destroy (uf); + + g_assert (!hb_unicode_funcs_is_immutable (uf2)); + _test_unicode_properties_nil (uf2); + + hb_unicode_funcs_destroy (uf2); + + /* Chain-up to default */ + + uf = hb_unicode_funcs_create (hb_unicode_funcs_get_default ()); + g_assert (!hb_unicode_funcs_is_immutable (uf)); + + uf2 = hb_unicode_funcs_create (uf); + g_assert (hb_unicode_funcs_is_immutable (uf)); + hb_unicode_funcs_destroy (uf); + + g_assert (!hb_unicode_funcs_is_immutable (uf2)); + hb_unicode_funcs_make_immutable (uf2); + test_unicode_properties (uf2); + + hb_unicode_funcs_destroy (uf2); + +} + +static void +test_unicode_setters (void) +{ + hb_unicode_funcs_t *uf; + unsigned int i; + + /* This is cruel: we use script-returning functions to test all properties, + * but it works. */ + + for (i = 0; i < G_N_ELEMENTS (properties); i++) { + const property_t *p = &properties[i]; + data_t data[2] = {{MAGIC0, FALSE}, {MAGIC1, FALSE}}; + + g_test_message ("Testing property %s", p->name); + + uf = hb_unicode_funcs_create (NULL); + g_assert (!hb_unicode_funcs_is_immutable (uf)); + + p->func_setter (uf, (get_func_t) simple_get_script, &data[0], free_up); + + g_assert_cmphex (p->getter (uf, 'a'), ==, HB_SCRIPT_LATIN); + g_assert_cmphex (p->getter (uf, '0'), ==, HB_SCRIPT_UNKNOWN); + + p->func_setter (uf, (get_func_t) NULL, NULL, NULL); + g_assert (data[0].freed && !data[1].freed); + + g_assert (!hb_unicode_funcs_is_immutable (uf)); + hb_unicode_funcs_make_immutable (uf); + g_assert (hb_unicode_funcs_is_immutable (uf)); + + /* Since uf is immutable now, the following setter should do nothing. */ + p->func_setter (uf, (get_func_t) a_is_for_arabic_get_script, &data[1], free_up); + + g_assert (data[0].freed && !data[1].freed); + hb_unicode_funcs_destroy (uf); + g_assert (data[0].freed && !data[1].freed); + } +} + + + +typedef struct { + data_t data[2]; +} data_fixture_t; + +static void +data_fixture_init (data_fixture_t *f, gconstpointer user_data) +{ + f->data[0].value = MAGIC0; + f->data[1].value = MAGIC1; +} +static void +data_fixture_finish (data_fixture_t *f, gconstpointer user_data) +{ +} + +static void +test_unicode_subclassing_nil (data_fixture_t *f, gconstpointer user_data) +{ + hb_unicode_funcs_t *uf, *aa; + + uf = hb_unicode_funcs_create (NULL); + + aa = hb_unicode_funcs_create (uf); + + hb_unicode_funcs_destroy (uf); + + hb_unicode_funcs_set_script_func (aa, a_is_for_arabic_get_script, + &f->data[1], free_up); + + g_assert_cmphex (hb_unicode_script (aa, 'a'), ==, HB_SCRIPT_ARABIC); + g_assert_cmphex (hb_unicode_script (aa, 'b'), ==, HB_SCRIPT_UNKNOWN); + + g_assert (!f->data[0].freed && !f->data[1].freed); + hb_unicode_funcs_destroy (aa); + g_assert (!f->data[0].freed && f->data[1].freed); +} + +static void +test_unicode_subclassing_default (data_fixture_t *f, gconstpointer user_data) +{ + hb_unicode_funcs_t *uf, *aa; + + uf = hb_unicode_funcs_get_default (); + aa = hb_unicode_funcs_create (uf); + + hb_unicode_funcs_set_script_func (aa, a_is_for_arabic_get_script, + &f->data[1], free_up); + + g_assert_cmphex (hb_unicode_script (aa, 'a'), ==, HB_SCRIPT_ARABIC); + g_assert_cmphex (hb_unicode_script (aa, 'b'), ==, HB_SCRIPT_LATIN); + + g_assert (!f->data[0].freed && !f->data[1].freed); + hb_unicode_funcs_destroy (aa); + g_assert (!f->data[0].freed && f->data[1].freed); +} + +static void +test_unicode_subclassing_deep (data_fixture_t *f, gconstpointer user_data) +{ + hb_unicode_funcs_t *uf, *aa; + + uf = hb_unicode_funcs_create (NULL); + + hb_unicode_funcs_set_script_func (uf, simple_get_script, + &f->data[0], free_up); + + aa = hb_unicode_funcs_create (uf); + + hb_unicode_funcs_destroy (uf); + + /* make sure the 'uf' didn't get freed, since 'aa' holds a ref */ + g_assert (!f->data[0].freed); + + hb_unicode_funcs_set_script_func (aa, a_is_for_arabic_get_script, + &f->data[1], free_up); + + g_assert_cmphex (hb_unicode_script (aa, 'a'), ==, HB_SCRIPT_ARABIC); + g_assert_cmphex (hb_unicode_script (aa, 'b'), ==, HB_SCRIPT_LATIN); + g_assert_cmphex (hb_unicode_script (aa, '0'), ==, HB_SCRIPT_UNKNOWN); + + g_assert (!f->data[0].freed && !f->data[1].freed); + hb_unicode_funcs_destroy (aa); + g_assert (f->data[0].freed && f->data[1].freed); +} + + +static hb_script_t +script_roundtrip_default (hb_script_t script) +{ + return hb_script_from_iso15924_tag (hb_script_to_iso15924_tag (script)); +} + +#ifdef HAVE_GLIB +static hb_script_t +script_roundtrip_glib (hb_script_t script) +{ + return hb_glib_script_to_script (hb_glib_script_from_script (script)); +} +#endif + +#ifdef HAVE_ICU +static hb_script_t +script_roundtrip_icu (hb_script_t script) +{ + return hb_icu_script_to_script (hb_icu_script_from_script (script)); +} +#endif + +static void +test_unicode_script_roundtrip (gconstpointer user_data) +{ + typedef hb_script_t (*roundtrip_func_t) (hb_script_t); + roundtrip_func_t roundtrip_func = (roundtrip_func_t) user_data; + unsigned int i; + gboolean failed = FALSE; + + for (i = 0; i < G_N_ELEMENTS (script_tests); i++) { + const test_pair_t *test = &script_tests[i]; + hb_script_t script = test->value; + + g_test_message ("Test script roundtrip #%d: %x", i, script); + g_assert_cmphex (script, ==, roundtrip_func (script)); + } + for (i = 0; i < G_N_ELEMENTS (script_tests_more); i++) { + const test_pair_t *test = &script_tests_more[i]; + hb_script_t script = test->value; + + g_test_message ("Test script roundtrip more #%d: %x", i, script); + if (script != roundtrip_func (script)) { + g_test_message ("Soft fail: Received %x, expected %x", roundtrip_func (script), script); + failed = TRUE; + } + } + + g_assert_cmphex (HB_SCRIPT_INVALID, ==, roundtrip_func (HB_SCRIPT_INVALID)); + + if (failed) + g_test_message ("Some script roundtrip tests failed. You probably have an old version of one of the libraries used."); +} + + +static void +test_unicode_normalization (gconstpointer user_data) +{ + hb_unicode_funcs_t *uf = (hb_unicode_funcs_t *) user_data; + gunichar a, b, ab; + hb_codepoint_t decomposed[HB_UNICODE_MAX_DECOMPOSITION_LEN]; + + + /* Test compose() */ + + /* Not composable */ + g_assert (!hb_unicode_compose (uf, 0x0041, 0x0042, &ab) && ab == 0); + g_assert (!hb_unicode_compose (uf, 0x0041, 0, &ab) && ab == 0); + g_assert (!hb_unicode_compose (uf, 0x0066, 0x0069, &ab) && ab == 0); + + /* Singletons should not compose */ + g_assert (!hb_unicode_compose (uf, 0x212B, 0, &ab) && ab == 0); + g_assert (!hb_unicode_compose (uf, 0x00C5, 0, &ab) && ab == 0); + g_assert (!hb_unicode_compose (uf, 0x2126, 0, &ab) && ab == 0); + g_assert (!hb_unicode_compose (uf, 0x03A9, 0, &ab) && ab == 0); + + /* Non-starter pairs should not compose */ + g_assert (!hb_unicode_compose (uf, 0x0308, 0x0301, &ab) && ab == 0); /* !0x0344 */ + g_assert (!hb_unicode_compose (uf, 0x0F71, 0x0F72, &ab) && ab == 0); /* !0x0F73 */ + + /* Pairs */ + g_assert (hb_unicode_compose (uf, 0x0041, 0x030A, &ab) && ab == 0x00C5); + g_assert (hb_unicode_compose (uf, 0x006F, 0x0302, &ab) && ab == 0x00F4); + g_assert (hb_unicode_compose (uf, 0x1E63, 0x0307, &ab) && ab == 0x1E69); + g_assert (hb_unicode_compose (uf, 0x0073, 0x0323, &ab) && ab == 0x1E63); + g_assert (hb_unicode_compose (uf, 0x0064, 0x0307, &ab) && ab == 0x1E0B); + g_assert (hb_unicode_compose (uf, 0x0064, 0x0323, &ab) && ab == 0x1E0D); + + /* Hangul */ + g_assert (hb_unicode_compose (uf, 0xD4CC, 0x11B6, &ab) && ab == 0xD4DB); + g_assert (hb_unicode_compose (uf, 0x1111, 0x1171, &ab) && ab == 0xD4CC); + g_assert (hb_unicode_compose (uf, 0xCE20, 0x11B8, &ab) && ab == 0xCE31); + g_assert (hb_unicode_compose (uf, 0x110E, 0x1173, &ab) && ab == 0xCE20); + + + /* Test decompose() */ + + /* Not decomposable */ + g_assert (!hb_unicode_decompose (uf, 0x0041, &a, &b) && a == 0x0041 && b == 0); + g_assert (!hb_unicode_decompose (uf, 0xFB01, &a, &b) && a == 0xFB01 && b == 0); + g_assert (!hb_unicode_decompose (uf, 0x1F1EF, &a, &b) && a == 0x1F1EF && b == 0); + + /* Singletons */ + g_assert (hb_unicode_decompose (uf, 0x212B, &a, &b) && a == 0x00C5 && b == 0); + g_assert (hb_unicode_decompose (uf, 0x2126, &a, &b) && a == 0x03A9 && b == 0); + + /* Non-starter pairs decompose, but not compose */ + g_assert (hb_unicode_decompose (uf, 0x0344, &a, &b) && a == 0x0308 && b == 0x0301); + g_assert (hb_unicode_decompose (uf, 0x0F73, &a, &b) && a == 0x0F71 && b == 0x0F72); + + /* Pairs */ + g_assert (hb_unicode_decompose (uf, 0x00C5, &a, &b) && a == 0x0041 && b == 0x030A); + g_assert (hb_unicode_decompose (uf, 0x00F4, &a, &b) && a == 0x006F && b == 0x0302); + g_assert (hb_unicode_decompose (uf, 0x1E69, &a, &b) && a == 0x1E63 && b == 0x0307); + g_assert (hb_unicode_decompose (uf, 0x1E63, &a, &b) && a == 0x0073 && b == 0x0323); + g_assert (hb_unicode_decompose (uf, 0x1E0B, &a, &b) && a == 0x0064 && b == 0x0307); + g_assert (hb_unicode_decompose (uf, 0x1E0D, &a, &b) && a == 0x0064 && b == 0x0323); + + /* Hangul */ + g_assert (hb_unicode_decompose (uf, 0xD4DB, &a, &b) && a == 0xD4CC && b == 0x11B6); + g_assert (hb_unicode_decompose (uf, 0xD4CC, &a, &b) && a == 0x1111 && b == 0x1171); + g_assert (hb_unicode_decompose (uf, 0xCE31, &a, &b) && a == 0xCE20 && b == 0x11B8); + g_assert (hb_unicode_decompose (uf, 0xCE20, &a, &b) && a == 0x110E && b == 0x1173); + + + /* Test decompose_compatibility() */ + + /* Not decomposable */ + g_assert (hb_unicode_decompose_compatibility (uf, 0x0041, decomposed) == 0); + g_assert (hb_unicode_decompose_compatibility (uf, 0x1F632, decomposed) == 0); + + /* Singletons */ + g_assert (hb_unicode_decompose_compatibility (uf, 0x00B5, decomposed) == 1 && decomposed[0] == 0x03BC); + g_assert (hb_unicode_decompose_compatibility (uf, 0x03D6, decomposed) == 1 && decomposed[0] == 0x03C0); + + /* Arabic compatibility */ + g_assert (hb_unicode_decompose_compatibility (uf, 0xFB54, decomposed) == 1 && decomposed[0] == 0x067B); + + /* Longest decomposition ever */ + g_assert (18 <= HB_UNICODE_MAX_DECOMPOSITION_LEN); + g_assert (hb_unicode_decompose_compatibility (uf, 0xFDFA, decomposed) == 18 && decomposed[17] == 0x0645); + + /* Note: we deliberately don't test characters that have canonical decompositions but no + * compatibility decomposition against the decompose_compatibility() function as that we + * leave up to implementations (for now). */ + + /* Spaces */ + g_assert (hb_unicode_decompose_compatibility (uf, 0x2002, decomposed) == 1 && decomposed[0] == 0x0020); + g_assert (hb_unicode_decompose_compatibility (uf, 0x2003, decomposed) == 1 && decomposed[0] == 0x0020); + g_assert (hb_unicode_decompose_compatibility (uf, 0x2004, decomposed) == 1 && decomposed[0] == 0x0020); + g_assert (hb_unicode_decompose_compatibility (uf, 0x2005, decomposed) == 1 && decomposed[0] == 0x0020); + g_assert (hb_unicode_decompose_compatibility (uf, 0x2006, decomposed) == 1 && decomposed[0] == 0x0020); + g_assert (hb_unicode_decompose_compatibility (uf, 0x2008, decomposed) == 1 && decomposed[0] == 0x0020); + g_assert (hb_unicode_decompose_compatibility (uf, 0x2009, decomposed) == 1 && decomposed[0] == 0x0020); + g_assert (hb_unicode_decompose_compatibility (uf, 0x200A, decomposed) == 1 && decomposed[0] == 0x0020); + + /* Pairs */ + g_assert (hb_unicode_decompose_compatibility (uf, 0x0587, decomposed) == 2 && + decomposed[0] == 0x0565 && decomposed[1] == 0x0582); + g_assert (hb_unicode_decompose_compatibility (uf, 0x2017, decomposed) == 2 && + decomposed[0] == 0x0020 && decomposed[1] == 0x0333); + g_assert (hb_unicode_decompose_compatibility (uf, 0x2025, decomposed) == 2 && + decomposed[0] == 0x002E && decomposed[1] == 0x002E); + g_assert (hb_unicode_decompose_compatibility (uf, 0x2033, decomposed) == 2 && + decomposed[0] == 0x2032 && decomposed[1] == 0x2032); + + /* Triples */ + g_assert (hb_unicode_decompose_compatibility (uf, 0x2026, decomposed) == 3 && + decomposed[0] == 0x002E && decomposed[1] == 0x002E && decomposed[2] == 0x002E); + g_assert (hb_unicode_decompose_compatibility (uf, 0x2034, decomposed) == 3 && + decomposed[0] == 0x2032 && decomposed[1] == 0x2032 && decomposed[2] == 0x2032); + g_assert (hb_unicode_decompose_compatibility (uf, 0x213B, decomposed) == 3 && + decomposed[0] == 0x0046 && decomposed[1] == 0x0041 && decomposed[2] == 0x0058); +} + + + +int +main (int argc, char **argv) +{ + hb_test_init (&argc, &argv); + + hb_test_add (test_unicode_properties_nil); + hb_test_add (test_unicode_properties_empty); + + hb_test_add_data_flavor (hb_unicode_funcs_get_default (), "default", test_unicode_properties); + hb_test_add_data_flavor (hb_unicode_funcs_get_default (), "default", test_unicode_normalization); + hb_test_add_data_flavor ((gconstpointer) script_roundtrip_default, "default", test_unicode_script_roundtrip); +#ifdef HAVE_GLIB + hb_test_add_data_flavor (hb_glib_get_unicode_funcs (), "glib", test_unicode_properties); + hb_test_add_data_flavor (hb_glib_get_unicode_funcs (), "glib", test_unicode_normalization); + hb_test_add_data_flavor ((gconstpointer) script_roundtrip_glib, "glib", test_unicode_script_roundtrip); +#endif +#ifdef HAVE_ICU + hb_test_add_data_flavor (hb_icu_get_unicode_funcs (), "icu", test_unicode_properties); + hb_test_add_data_flavor (hb_icu_get_unicode_funcs (), "icu", test_unicode_normalization); + hb_test_add_data_flavor ((gconstpointer) script_roundtrip_icu, "icu", test_unicode_script_roundtrip); +#endif + + hb_test_add (test_unicode_chainup); + + hb_test_add (test_unicode_setters); + + hb_test_add_fixture (data_fixture, NULL, test_unicode_subclassing_nil); + hb_test_add_fixture (data_fixture, NULL, test_unicode_subclassing_default); + hb_test_add_fixture (data_fixture, NULL, test_unicode_subclassing_deep); + + return hb_test_run (); +} diff --git a/test/api/test-version.c b/test/api/test-version.c new file mode 100644 index 0000000..4c9bd37 --- /dev/null +++ b/test/api/test-version.c @@ -0,0 +1,80 @@ +/* + * Copyright © 2011 Google, Inc. + * + * This is part of HarfBuzz, a text shaping library. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and its documentation for any purpose, provided that the + * above copyright notice and the following two paragraphs appear in + * all copies of this software. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + * + * Google Author(s): Behdad Esfahbod + */ + +#include "hb-test.h" + +/* Unit tests for hb-version.h */ + + +static void +test_version (void) +{ + unsigned int major, minor, micro; + char *s; + + hb_version (&major, &minor, µ); + + g_assert_cmpint (major, ==, HB_VERSION_MAJOR); + g_assert_cmpint (minor, ==, HB_VERSION_MINOR); + g_assert_cmpint (micro, ==, HB_VERSION_MICRO); + + s = g_strdup_printf ("%u.%u.%u", major, minor, micro); + g_assert (0 == strcmp (HB_VERSION_STRING, s)); + g_free (s); + g_assert (0 == strcmp (HB_VERSION_STRING, hb_version_string ())); + + g_assert (HB_VERSION_CHECK (major, minor, micro)); + g_assert (HB_VERSION_CHECK (major+1, minor, micro)); + g_assert (HB_VERSION_CHECK (major, minor+1, micro)); + g_assert (HB_VERSION_CHECK (major, minor, micro+1)); + if (major) + g_assert (!HB_VERSION_CHECK (major-1, minor, micro)); + if (minor) + g_assert (!HB_VERSION_CHECK (major, minor-1, micro)); + if (micro) + g_assert (!HB_VERSION_CHECK (major, minor, micro-1)); + + g_assert (hb_version_check (major, minor, micro)); + g_assert (hb_version_check (major+1, minor, micro)); + g_assert (hb_version_check (major, minor+1, micro)); + g_assert (hb_version_check (major, minor, micro+1)); + if (major) + g_assert (!hb_version_check (major-1, minor, micro)); + if (minor) + g_assert (!hb_version_check (major, minor-1, micro)); + if (micro) + g_assert (!hb_version_check (major, minor, micro-1)); +} + +int +main (int argc, char **argv) +{ + hb_test_init (&argc, &argv); + + hb_test_add (test_version); + + return hb_test_run(); +} diff --git a/test/shaping/Makefile.am b/test/shaping/Makefile.am new file mode 100644 index 0000000..4fb762c --- /dev/null +++ b/test/shaping/Makefile.am @@ -0,0 +1,35 @@ +# Process this file with automake to produce Makefile.in + +NULL = +EXTRA_DIST = +CLEANFILES = +DISTCLEANFILES = +MAINTAINERCLEANFILES = + +manifests: + @$(srcdir)/hb-manifest-update "$(srcdir)/texts" "$(srcdir)/fonts" + +EXTRA_DIST += \ + hb-diff \ + hb-diff-colorize \ + hb-diff-filter-failures \ + hb-diff-ngrams \ + hb-diff-stat \ + hb-manifest-read \ + hb-manifest-update \ + hb-unicode-decode \ + hb-unicode-encode \ + hb-unicode-prettyname \ + $(NULL) + +# TODO Figure out Python stuff +EXTRA_DIST += \ + hb_test_tools.py \ + $(NULL) +CLEANFILES += \ + hb_test_tools.py[co] \ + $(NULL) + +.PHONY: manifests + +-include $(top_srcdir)/git.mk diff --git a/test/shaping/Makefile.in b/test/shaping/Makefile.in new file mode 100644 index 0000000..6273f9d --- /dev/null +++ b/test/shaping/Makefile.in @@ -0,0 +1,408 @@ +# Makefile.in generated by automake 1.11.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, +# Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +# Process this file with automake to produce Makefile.in +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = test/shaping +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +AM_V_GEN = $(am__v_GEN_$(V)) +am__v_GEN_ = $(am__v_GEN_$(AM_DEFAULT_VERBOSITY)) +am__v_GEN_0 = @echo " GEN " $@; +AM_V_at = $(am__v_at_$(V)) +am__v_at_ = $(am__v_at_$(AM_DEFAULT_VERBOSITY)) +am__v_at_0 = @ +SOURCES = +DIST_SOURCES = +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CAIRO_CFLAGS = @CAIRO_CFLAGS@ +CAIRO_FT_CFLAGS = @CAIRO_FT_CFLAGS@ +CAIRO_FT_LIBS = @CAIRO_FT_LIBS@ +CAIRO_LIBS = @CAIRO_LIBS@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CORETEXT_CFLAGS = @CORETEXT_CFLAGS@ +CORETEXT_LIBS = @CORETEXT_LIBS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +FREETYPE_CFLAGS = @FREETYPE_CFLAGS@ +FREETYPE_LIBS = @FREETYPE_LIBS@ +GLIB_CFLAGS = @GLIB_CFLAGS@ +GLIB_LIBS = @GLIB_LIBS@ +GLIB_MKENUMS = @GLIB_MKENUMS@ +GOBJECT_CFLAGS = @GOBJECT_CFLAGS@ +GOBJECT_LIBS = @GOBJECT_LIBS@ +GRAPHITE2_CFLAGS = @GRAPHITE2_CFLAGS@ +GRAPHITE2_LIBS = @GRAPHITE2_LIBS@ +GREP = @GREP@ +GTHREAD_CFLAGS = @GTHREAD_CFLAGS@ +GTHREAD_LIBS = @GTHREAD_LIBS@ +HB_LIBTOOL_VERSION_INFO = @HB_LIBTOOL_VERSION_INFO@ +HB_VERSION = @HB_VERSION@ +HB_VERSION_MAJOR = @HB_VERSION_MAJOR@ +HB_VERSION_MICRO = @HB_VERSION_MICRO@ +HB_VERSION_MINOR = @HB_VERSION_MINOR@ +ICU_CFLAGS = @ICU_CFLAGS@ +ICU_LIBS = @ICU_LIBS@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PKG_CONFIG = @PKG_CONFIG@ +RANLIB = @RANLIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +UNISCRIBE_CFLAGS = @UNISCRIBE_CFLAGS@ +UNISCRIBE_LIBS = @UNISCRIBE_LIBS@ +VERSION = @VERSION@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +lt_ECHO = @lt_ECHO@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +NULL = + +# TODO Figure out Python stuff +EXTRA_DIST = hb-diff hb-diff-colorize hb-diff-filter-failures \ + hb-diff-ngrams hb-diff-stat hb-manifest-read \ + hb-manifest-update hb-unicode-decode hb-unicode-encode \ + hb-unicode-prettyname $(NULL) hb_test_tools.py $(NULL) +CLEANFILES = hb_test_tools.py[co] $(NULL) +DISTCLEANFILES = +MAINTAINERCLEANFILES = +all: all-am + +.SUFFIXES: +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnits test/shaping/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnits test/shaping/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs +tags: TAGS +TAGS: + +ctags: CTAGS +CTAGS: + + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + -test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." + -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES) +clean: clean-am + +clean-am: clean-generic clean-libtool mostlyclean-am + +distclean: distclean-am + -rm -f Makefile +distclean-am: clean-am distclean-generic + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-generic mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: + +.MAKE: install-am install-strip + +.PHONY: all all-am check check-am clean clean-generic clean-libtool \ + distclean distclean-generic distclean-libtool distdir dvi \ + dvi-am html html-am info info-am install install-am \ + install-data install-data-am install-dvi install-dvi-am \ + install-exec install-exec-am install-html install-html-am \ + install-info install-info-am install-man install-pdf \ + install-pdf-am install-ps install-ps-am install-strip \ + installcheck installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-generic \ + mostlyclean-libtool pdf pdf-am ps ps-am uninstall uninstall-am + + +manifests: + @$(srcdir)/hb-manifest-update "$(srcdir)/texts" "$(srcdir)/fonts" + +.PHONY: manifests + +-include $(top_srcdir)/git.mk + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/test/shaping/hb-diff b/test/shaping/hb-diff new file mode 100755 index 0000000..6a13fa2 --- /dev/null +++ b/test/shaping/hb-diff @@ -0,0 +1,10 @@ +#!/usr/bin/python + +from hb_test_tools import * +import sys, os + +if len (sys.argv) < 2: + print "usage: %s FILES..." % sys.argv[0] + sys.exit (1) + +ZipDiffer.diff_files (FileHelpers.open_file_or_stdin (f) for f in sys.argv[1:]) diff --git a/test/shaping/hb-diff-colorize b/test/shaping/hb-diff-colorize new file mode 100755 index 0000000..4e045d2 --- /dev/null +++ b/test/shaping/hb-diff-colorize @@ -0,0 +1,7 @@ +#!/usr/bin/python + +from hb_test_tools import * + +formatter = ColorFormatter.Auto (sys.argv) +colorizer = DiffColorizer (formatter=formatter) +UtilMains.process_multiple_files (FilterHelpers.filter_printer_function_no_newline (colorizer.colorize_diff)) diff --git a/test/shaping/hb-diff-filter-failures b/test/shaping/hb-diff-filter-failures new file mode 100755 index 0000000..4fe218a --- /dev/null +++ b/test/shaping/hb-diff-filter-failures @@ -0,0 +1,5 @@ +#!/usr/bin/python + +from hb_test_tools import * + +UtilMains.process_multiple_files (FilterHelpers.filter_printer_function_no_newline (DiffFilters.filter_failures)) diff --git a/test/shaping/hb-diff-ngrams b/test/shaping/hb-diff-ngrams new file mode 100755 index 0000000..a496447 --- /dev/null +++ b/test/shaping/hb-diff-ngrams @@ -0,0 +1,5 @@ +#!/usr/bin/python + +from hb_test_tools import * + +UtilMains.process_multiple_files (DiffSinks.print_ngrams) diff --git a/test/shaping/hb-diff-stat b/test/shaping/hb-diff-stat new file mode 100755 index 0000000..81626e1 --- /dev/null +++ b/test/shaping/hb-diff-stat @@ -0,0 +1,5 @@ +#!/usr/bin/python + +from hb_test_tools import * + +UtilMains.process_multiple_files (DiffSinks.print_stat) diff --git a/test/shaping/hb-manifest-read b/test/shaping/hb-manifest-read new file mode 100755 index 0000000..f486bcc --- /dev/null +++ b/test/shaping/hb-manifest-read @@ -0,0 +1,5 @@ +#!/usr/bin/python + +from hb_test_tools import * + +UtilMains.process_multiple_args (FilterHelpers.filter_printer_function (Manifest.read), mnemonic="DIR") diff --git a/test/shaping/hb-manifest-update b/test/shaping/hb-manifest-update new file mode 100755 index 0000000..b963f22 --- /dev/null +++ b/test/shaping/hb-manifest-update @@ -0,0 +1,5 @@ +#!/usr/bin/python + +from hb_test_tools import * + +UtilMains.process_multiple_args (Manifest.update_recursive, mnemonic="DIR") diff --git a/test/shaping/hb-unicode-decode b/test/shaping/hb-unicode-decode new file mode 100755 index 0000000..5b00eae --- /dev/null +++ b/test/shaping/hb-unicode-decode @@ -0,0 +1,5 @@ +#!/usr/bin/python + +from hb_test_tools import * + +UtilMains.filter_multiple_strings_or_stdin (Unicode.decode, "UNICODE_STRING") diff --git a/test/shaping/hb-unicode-encode b/test/shaping/hb-unicode-encode new file mode 100755 index 0000000..11bf365 --- /dev/null +++ b/test/shaping/hb-unicode-encode @@ -0,0 +1,5 @@ +#!/usr/bin/python + +from hb_test_tools import * + +UtilMains.filter_multiple_strings_or_stdin (Unicode.encode, "UNICODE_STRING", '') diff --git a/test/shaping/hb-unicode-prettyname b/test/shaping/hb-unicode-prettyname new file mode 100755 index 0000000..ecc26cc --- /dev/null +++ b/test/shaping/hb-unicode-prettyname @@ -0,0 +1,6 @@ +#!/usr/bin/python + +from hb_test_tools import * + +UtilMains.filter_multiple_strings_or_stdin (Unicode.pretty_names, "UNICODE_CODEPOINTS", \ + concat_separator = ' ') diff --git a/test/shaping/hb_test_tools.py b/test/shaping/hb_test_tools.py new file mode 100644 index 0000000..ce46588 --- /dev/null +++ b/test/shaping/hb_test_tools.py @@ -0,0 +1,516 @@ +#!/usr/bin/python + +import sys, os, re, difflib, unicodedata, errno, cgi +from itertools import * + +diff_symbols = "-+=*&^%$#@!~/" +diff_colors = ['red', 'green', 'blue'] + +class ColorFormatter: + + class Null: + @staticmethod + def start_color (c): return '' + @staticmethod + def end_color (): return '' + @staticmethod + def escape (s): return s + @staticmethod + def newline (): return '\n' + + class ANSI: + @staticmethod + def start_color (c): + return { + 'red': '\033[41;37;1m', + 'green': '\033[42;37;1m', + 'blue': '\033[44;37;1m', + }[c] + @staticmethod + def end_color (): + return '\033[m' + @staticmethod + def escape (s): return s + @staticmethod + def newline (): return '\n' + + class HTML: + @staticmethod + def start_color (c): + return '<span style="background:%s">' % c + @staticmethod + def end_color (): + return '</span>' + @staticmethod + def escape (s): return cgi.escape (s) + @staticmethod + def newline (): return '<br/>\n' + + @staticmethod + def Auto (argv = [], out = sys.stdout): + format = ColorFormatter.ANSI + if "--format" in argv: + argv.remove ("--format") + format = ColorFormatter.ANSI + if "--format=ansi" in argv: + argv.remove ("--format=ansi") + format = ColorFormatter.ANSI + if "--format=html" in argv: + argv.remove ("--format=html") + format = ColorFormatter.HTML + if "--no-format" in argv: + argv.remove ("--no-format") + format = ColorFormatter.Null + return format + + +class DiffColorizer: + + diff_regex = re.compile ('([a-za-z0-9_]*)([^a-za-z0-9_]?)') + + def __init__ (self, formatter, colors=diff_colors, symbols=diff_symbols): + self.formatter = formatter + self.colors = colors + self.symbols = symbols + + def colorize_lines (self, lines): + lines = (l if l else '' for l in lines) + ss = [self.diff_regex.sub (r'\1\n\2\n', l).splitlines (True) for l in lines] + oo = ["",""] + st = [False, False] + for l in difflib.Differ().compare (*ss): + if l[0] == '?': + continue + if l[0] == ' ': + for i in range(2): + if st[i]: + oo[i] += self.formatter.end_color () + st[i] = False + oo = [o + self.formatter.escape (l[2:]) for o in oo] + continue + if l[0] in self.symbols: + i = self.symbols.index (l[0]) + if not st[i]: + oo[i] += self.formatter.start_color (self.colors[i]) + st[i] = True + oo[i] += self.formatter.escape (l[2:]) + continue + for i in range(2): + if st[i]: + oo[i] += self.formatter.end_color () + st[i] = False + oo = [o.replace ('\n', '') for o in oo] + return [s1+s2+self.formatter.newline () for (s1,s2) in zip (self.symbols, oo) if s2] + + def colorize_diff (self, f): + lines = [None, None] + for l in f: + if l[0] not in self.symbols: + yield self.formatter.escape (l).replace ('\n', self.formatter.newline ()) + continue + i = self.symbols.index (l[0]) + if lines[i]: + # Flush + for line in self.colorize_lines (lines): + yield line + lines = [None, None] + lines[i] = l[1:] + if (all (lines)): + # Flush + for line in self.colorize_lines (lines): + yield line + lines = [None, None] + if (any (lines)): + # Flush + for line in self.colorize_lines (lines): + yield line + + +class ZipDiffer: + + @staticmethod + def diff_files (files, symbols=diff_symbols): + files = tuple (files) # in case it's a generator, copy it + try: + for lines in izip_longest (*files): + if all (lines[0] == line for line in lines[1:]): + sys.stdout.writelines ([" ", lines[0]]) + continue + + for i, l in enumerate (lines): + if l: + sys.stdout.writelines ([symbols[i], l]) + except IOError as e: + if e.errno != errno.EPIPE: + print >> sys.stderr, "%s: %s: %s" % (sys.argv[0], e.filename, e.strerror) + sys.exit (1) + + +class DiffFilters: + + @staticmethod + def filter_failures (f): + for key, lines in DiffHelpers.separate_test_cases (f): + lines = list (lines) + if not DiffHelpers.test_passed (lines): + for l in lines: yield l + +class Stat: + + def __init__ (self): + self.count = 0 + self.freq = 0 + + def add (self, test): + self.count += 1 + self.freq += test.freq + +class Stats: + + def __init__ (self): + self.passed = Stat () + self.failed = Stat () + self.total = Stat () + + def add (self, test): + self.total.add (test) + if test.passed: + self.passed.add (test) + else: + self.failed.add (test) + + def mean (self): + return float (self.passed.count) / self.total.count + + def variance (self): + return (float (self.passed.count) / self.total.count) * \ + (float (self.failed.count) / self.total.count) + + def stddev (self): + return self.variance () ** .5 + + def zscore (self, population): + """Calculate the standard score. + Population is the Stats for population. + Self is Stats for sample. + Returns larger absolute value if sample is highly unlikely to be random. + Anything outside of -3..+3 is very unlikely to be random. + See: http://en.wikipedia.org/wiki/Standard_score""" + + return (self.mean () - population.mean ()) / population.stddev () + + + + +class DiffSinks: + + @staticmethod + def print_stat (f): + passed = 0 + failed = 0 + # XXX port to Stats, but that would really slow us down here + for key, lines in DiffHelpers.separate_test_cases (f): + if DiffHelpers.test_passed (lines): + passed += 1 + else: + failed += 1 + total = passed + failed + print "%d out of %d tests passed. %d failed (%g%%)" % (passed, total, failed, 100. * failed / total) + + @staticmethod + def print_ngrams (f, ns=(1,2,3)): + gens = tuple (Ngram.generator (n) for n in ns) + allstats = Stats () + allgrams = {} + for key, lines in DiffHelpers.separate_test_cases (f): + test = Test (lines) + allstats.add (test) + + for gen in gens: + for ngram in gen (test.unicodes): + if ngram not in allgrams: + allgrams[ngram] = Stats () + allgrams[ngram].add (test) + + importantgrams = {} + for ngram, stats in allgrams.iteritems (): + if stats.failed.count >= 30: # for statistical reasons + importantgrams[ngram] = stats + allgrams = importantgrams + del importantgrams + + for ngram, stats in allgrams.iteritems (): + print "zscore: %9f failed: %6d passed: %6d ngram: <%s>" % (stats.zscore (allstats), stats.failed.count, stats.passed.count, ','.join ("U+%04X" % u for u in ngram)) + + + +class Test: + + def __init__ (self, lines): + self.freq = 1 + self.passed = True + self.identifier = None + self.text = None + self.unicodes = None + self.glyphs = None + for l in lines: + symbol = l[0] + if symbol != ' ': + self.passed = False + i = 1 + if ':' in l: + i = l.index (':') + if not self.identifier: + self.identifier = l[1:i] + i = i + 2 # Skip colon and space + j = -1 + if l[j] == '\n': + j -= 1 + brackets = l[i] + l[j] + l = l[i+1:-2] + if brackets == '()': + self.text = l + elif brackets == '<>': + self.unicodes = Unicode.parse (l) + elif brackets == '[]': + # XXX we don't handle failed tests here + self.glyphs = l + + +class DiffHelpers: + + @staticmethod + def separate_test_cases (f): + '''Reads lines from f, and if the lines have identifiers, ie. + have a colon character, groups them by identifier, + yielding lists of all lines with the same identifier.''' + + def identifier (l): + if ':' in l[1:]: + return l[1:l.index (':')] + return l + return groupby (f, key=identifier) + + @staticmethod + def test_passed (lines): + lines = list (lines) + # XXX This is a hack, but does the job for now. + if any (l.find("space|space") >= 0 for l in lines): return True + if any (l.find("uni25CC") >= 0 for l in lines): return True + if any (l.find("dottedcircle") >= 0 for l in lines): return True + return all (l[0] == ' ' for l in lines) + + +class FilterHelpers: + + @staticmethod + def filter_printer_function (filter_callback): + def printer (f): + for line in filter_callback (f): + print line + return printer + + @staticmethod + def filter_printer_function_no_newline (filter_callback): + def printer (f): + for line in filter_callback (f): + sys.stdout.writelines ([line]) + return printer + + +class Ngram: + + @staticmethod + def generator (n): + + def gen (f): + l = [] + for x in f: + l.append (x) + if len (l) == n: + yield tuple (l) + l[:1] = [] + + gen.n = n + return gen + + +class UtilMains: + + @staticmethod + def process_multiple_files (callback, mnemonic = "FILE"): + + if "--help" in sys.argv: + print "Usage: %s %s..." % (sys.argv[0], mnemonic) + sys.exit (1) + + try: + files = sys.argv[1:] if len (sys.argv) > 1 else ['-'] + for s in files: + callback (FileHelpers.open_file_or_stdin (s)) + except IOError as e: + if e.errno != errno.EPIPE: + print >> sys.stderr, "%s: %s: %s" % (sys.argv[0], e.filename, e.strerror) + sys.exit (1) + + @staticmethod + def process_multiple_args (callback, mnemonic): + + if len (sys.argv) == 1 or "--help" in sys.argv: + print "Usage: %s %s..." % (sys.argv[0], mnemonic) + sys.exit (1) + + try: + for s in sys.argv[1:]: + callback (s) + except IOError as e: + if e.errno != errno.EPIPE: + print >> sys.stderr, "%s: %s: %s" % (sys.argv[0], e.filename, e.strerror) + sys.exit (1) + + @staticmethod + def filter_multiple_strings_or_stdin (callback, mnemonic, \ + separator = " ", \ + concat_separator = False): + + if "--help" in sys.argv: + print "Usage:\n %s %s...\nor:\n %s\n\nWhen called with no arguments, input is read from standard input." \ + % (sys.argv[0], mnemonic, sys.argv[0]) + sys.exit (1) + + try: + if len (sys.argv) == 1: + while (1): + line = sys.stdin.readline () + if not len (line): + break + if line[-1] == '\n': + line = line[:-1] + print callback (line) + else: + args = sys.argv[1:] + if concat_separator != False: + args = [concat_separator.join (args)] + print separator.join (callback (x) for x in (args)) + except IOError as e: + if e.errno != errno.EPIPE: + print >> sys.stderr, "%s: %s: %s" % (sys.argv[0], e.filename, e.strerror) + sys.exit (1) + + +class Unicode: + + @staticmethod + def decode (s): + return '<' + u','.join ("U+%04X" % ord (u) for u in unicode (s, 'utf-8')).encode ('utf-8') + '>' + + @staticmethod + def parse (s): + s = re.sub (r"[<+>,\\uU\n ]", " ", s) + s = re.sub (r"0[xX]", " ", s) + return [int (x, 16) for x in s.split (' ') if len (x)] + + @staticmethod + def encode (s): + return u''.join (unichr (x) for x in Unicode.parse (s)).encode ('utf-8') + + shorthands = { + "ZERO WIDTH NON-JOINER": "ZWNJ", + "ZERO WIDTH JOINER": "ZWJ", + "NARROW NO-BREAK SPACE": "NNBSP", + "COMBINING GRAPHEME JOINER": "CGJ", + "LEFT-TO-RIGHT MARK": "LRM", + "RIGHT-TO-LEFT MARK": "RLM", + "LEFT-TO-RIGHT EMBEDDING": "LRE", + "RIGHT-TO-LEFT EMBEDDING": "RLE", + "POP DIRECTIONAL FORMATTING": "PDF", + "LEFT-TO-RIGHT OVERRIDE": "LRO", + "RIGHT-TO-LEFT OVERRIDE": "RLO", + } + + @staticmethod + def pretty_name (u): + try: + s = unicodedata.name (u) + except ValueError: + return "XXX" + s = re.sub (".* LETTER ", "", s) + s = re.sub (".* VOWEL SIGN (.*)", r"\1-MATRA", s) + s = re.sub (".* SIGN ", "", s) + s = re.sub (".* COMBINING ", "", s) + if re.match (".* VIRAMA", s): + s = "HALANT" + if s in Unicode.shorthands: + s = Unicode.shorthands[s] + return s + + @staticmethod + def pretty_names (s): + s = re.sub (r"[<+>\\uU]", " ", s) + s = re.sub (r"0[xX]", " ", s) + s = [unichr (int (x, 16)) for x in re.split ('[, \n]', s) if len (x)] + return u' + '.join (Unicode.pretty_name (x) for x in s).encode ('utf-8') + + +class FileHelpers: + + @staticmethod + def open_file_or_stdin (f): + if f == '-': + return sys.stdin + return file (f) + + +class Manifest: + + @staticmethod + def read (s, strict = True): + + if not os.path.exists (s): + if strict: + print >> sys.stderr, "%s: %s does not exist" % (sys.argv[0], s) + sys.exit (1) + return + + s = os.path.normpath (s) + + if os.path.isdir (s): + + try: + m = file (os.path.join (s, "MANIFEST")) + items = [x.strip () for x in m.readlines ()] + for f in items: + for p in Manifest.read (os.path.join (s, f)): + yield p + except IOError: + if strict: + print >> sys.stderr, "%s: %s does not exist" % (sys.argv[0], os.path.join (s, "MANIFEST")) + sys.exit (1) + return + else: + yield s + + @staticmethod + def update_recursive (s): + + for dirpath, dirnames, filenames in os.walk (s, followlinks=True): + + for f in ["MANIFEST", "README", "LICENSE", "COPYING", "AUTHORS", "SOURCES", "ChangeLog"]: + if f in dirnames: + dirnames.remove (f) + if f in filenames: + filenames.remove (f) + dirnames.sort () + filenames.sort () + ms = os.path.join (dirpath, "MANIFEST") + print " GEN %s" % ms + m = open (ms, "w") + for f in filenames: + print >> m, f + for f in dirnames: + print >> m, f + for f in dirnames: + Manifest.update_recursive (os.path.join (dirpath, f)) + +if __name__ == '__main__': + pass |