diff --git a/configure.ac b/configure.ac index d7f1e2673..db596bc4c 100644 --- a/configure.ac +++ b/configure.ac @@ -432,6 +432,7 @@ test/shaping/data/in-house/Makefile test/shaping/data/text-rendering-tests/Makefile test/subset/Makefile test/subset/data/Makefile +test/subset/data/repack_tests/Makefile docs/Makefile docs/version.xml ]) diff --git a/test/subset/Makefile.am b/test/subset/Makefile.am index 47b003932..cfd739b31 100644 --- a/test/subset/Makefile.am +++ b/test/subset/Makefile.am @@ -13,7 +13,9 @@ libs: EXTRA_DIST += \ meson.build \ run-tests.py \ + run-repack-tests.py \ subset_test_suite.py \ + repack_test.py \ $(NULL) CLEANFILES += \ diff --git a/test/subset/data/Makefile.am b/test/subset/data/Makefile.am index daebed90b..73585f85c 100644 --- a/test/subset/data/Makefile.am +++ b/test/subset/data/Makefile.am @@ -3,7 +3,7 @@ NULL = EXTRA_DIST = CLEANFILES = -SUBDIRS = +SUBDIRS = repack_tests EXTRA_DIST += \ $(TESTS) \ diff --git a/test/subset/data/fonts/NotoNastaliqUrdu-Bold.ttf b/test/subset/data/fonts/NotoNastaliqUrdu-Bold.ttf new file mode 100644 index 000000000..d05dabe0b Binary files /dev/null and b/test/subset/data/fonts/NotoNastaliqUrdu-Bold.ttf differ diff --git a/test/subset/data/repack_tests/Makefile.am b/test/subset/data/repack_tests/Makefile.am new file mode 100644 index 000000000..8e814fb2c --- /dev/null +++ b/test/subset/data/repack_tests/Makefile.am @@ -0,0 +1,22 @@ +# Process this file with automake to produce Makefile.in + +NULL = +EXTRA_DIST = +CLEANFILES = +SUBDIRS = + +EXTRA_DIST += + $(TESTS) \ + $(NULL) + +# Convenience targets: +lib: libs # Always build subsetter lib in this subdir +libs: + @$(MAKE) $(AM_MAKEFLAGS) -C $(top_builddir)/src libs + +TEST_EXTENSIONS = .tests +TESTS_LOG_COMPILER = $(srcdir)/../../run-repack-tests.py $(top_builddir)/util/hb-subset$(EXEEXT) +include Makefile.sources + + +-include $(top_srcdir)/git.mk diff --git a/test/subset/data/repack_tests/Makefile.sources b/test/subset/data/repack_tests/Makefile.sources new file mode 100644 index 000000000..e778e52a7 --- /dev/null +++ b/test/subset/data/repack_tests/Makefile.sources @@ -0,0 +1,12 @@ +TESTS = \ + basic.tests \ + prioritization.tests \ + table_duplication.tests \ + $(NULL) + +XFAIL_TESTS = \ + advanced_prioritization.tests \ + $(NULL) + +DISABLED_TESTS = \ + $(NULL) diff --git a/test/subset/data/repack_tests/advanced_prioritization.tests b/test/subset/data/repack_tests/advanced_prioritization.tests new file mode 100644 index 000000000..adcbb001b --- /dev/null +++ b/test/subset/data/repack_tests/advanced_prioritization.tests @@ -0,0 +1,72 @@ +NotoNastaliqUrdu-Bold.ttf +0x0020 +0x0028 +0x0029 +0x002C +0x002D +0x002E +0x0030 +0x0031 +0x0032 +0x0033 +0x0034 +0x0035 +0x0036 +0x0037 +0x0038 +0x0039 +0x003A +0x060C +0x061F +0x0621 +0x0622 +0x0623 +0x0624 +0x0625 +0x0626 +0x0627 +0x0628 +0x0629 +0x062A +0x062B +0x062C +0x062D +0x062E +0x062F +0x0630 +0x0631 +0x0632 +0x0633 +0x0634 +0x0635 +0x0636 +0x0637 +0x0638 +0x0639 +0x063A +0x0640 +0x0641 +0x0642 +0x0643 +0x0644 +0x0645 +0x0646 +0x0647 +0x0648 +0x0649 +0x064A +0x064B +0x064C +0x064F +0x0651 +0x067E +0x0686 +0x0698 +0x06A9 +0x06AF +0x06BE +0x06CC +0x200C +0x200D +0x200E + diff --git a/test/subset/data/repack_tests/basic.tests b/test/subset/data/repack_tests/basic.tests new file mode 100644 index 000000000..896cc9b48 --- /dev/null +++ b/test/subset/data/repack_tests/basic.tests @@ -0,0 +1,52 @@ +NotoNastaliqUrdu-Bold.ttf +0x060C +0x061F +0x0621 +0x0622 +0x0623 +0x0624 +0x0625 +0x0626 +0x0627 +0x0628 +0x0629 +0x062A +0x062B +0x062C +0x062D +0x062E +0x062F +0x0630 +0x0631 +0x0632 +0x0633 +0x0634 +0x0635 +0x0636 +0x0637 +0x0638 +0x0639 +0x063A +0x0640 +0x0641 +0x0642 +0x0643 +0x0644 +0x0645 +0x0646 +0x0647 +0x0648 +0x0649 +0x064A +0x064B +0x064F +0x0651 +0x067E +0x0686 +0x0698 +0x06A9 +0x06AF +0x06CC +0x200C +0x200D +0x200E diff --git a/test/subset/data/repack_tests/prioritization.tests b/test/subset/data/repack_tests/prioritization.tests new file mode 100644 index 000000000..63b437c92 --- /dev/null +++ b/test/subset/data/repack_tests/prioritization.tests @@ -0,0 +1,77 @@ +NotoNastaliqUrdu-Bold.ttf +0x0020 +0x0028 +0x0029 +0x002C +0x002D +0x002E +0x0030 +0x0031 +0x0032 +0x0033 +0x0034 +0x0035 +0x0036 +0x0037 +0x0038 +0x0039 +0x003A +0x060C +0x061F +0x0621 +0x0622 +0x0623 +0x0624 +0x0625 +0x0626 +0x0627 +0x0628 +0x0629 +0x062A +0x062B +0x062C +0x062D +0x062E +0x062F +0x0630 +0x0631 +0x0632 +0x0633 +0x0634 +0x0635 +0x0636 +0x0637 +0x0638 +0x0639 +0x063A +0x0640 +0x0641 +0x0642 +0x0643 +0x0644 +0x0645 +0x0646 +0x0647 +0x0648 +0x0649 +0x064A +0x064B +0x064F +0x0651 +0x0653 +0x0679 +0x067E +0x0686 +0x0688 +0x0691 +0x0698 +0x06A9 +0x06AF +0x06BA +0x06BE +0x06C1 +0x06CC +0x06D2 +0x200C +0x200D +0x200E diff --git a/test/subset/data/repack_tests/table_duplication.tests b/test/subset/data/repack_tests/table_duplication.tests new file mode 100644 index 000000000..3cc90d6bc --- /dev/null +++ b/test/subset/data/repack_tests/table_duplication.tests @@ -0,0 +1,97 @@ +NotoNastaliqUrdu-Bold.ttf +0x0028 +0x0029 +0x002C +0x002D +0x002E +0x0030 +0x0031 +0x0032 +0x0033 +0x0034 +0x0035 +0x0036 +0x0037 +0x0038 +0x0039 +0x003A +0x0041 +0x0042 +0x0043 +0x0044 +0x0045 +0x0046 +0x0047 +0x0048 +0x0049 +0x004C +0x004D +0x004E +0x004F +0x0050 +0x0052 +0x0053 +0x0054 +0x0055 +0x0056 +0x0057 +0x0061 +0x0062 +0x0063 +0x0064 +0x0065 +0x0066 +0x0067 +0x0068 +0x0069 +0x006B +0x006C +0x006D +0x006E +0x006F +0x0070 +0x0072 +0x0073 +0x0074 +0x0075 +0x0076 +0x0077 +0x0078 +0x0079 +0x060C +0x0626 +0x0627 +0x0628 +0x062A +0x062C +0x062D +0x062E +0x062F +0x0631 +0x0632 +0x0633 +0x0634 +0x0635 +0x0636 +0x0637 +0x0638 +0x0639 +0x0641 +0x0642 +0x0644 +0x0645 +0x0646 +0x0648 +0x0653 +0x0679 +0x067E +0x0686 +0x0688 +0x0691 +0x06A9 +0x06AF +0x06BA +0x06BE +0x06C1 +0x06CC +0x06D2 diff --git a/test/subset/meson.build b/test/subset/meson.build index 458bf9646..5da61a9e0 100644 --- a/test/subset/meson.build +++ b/test/subset/meson.build @@ -28,6 +28,13 @@ tests = [ 'cbdt', ] +repack_tests = [ + 'basic', + 'prioritization', + 'table_duplication', +] + + run_test = find_program('run-tests.py') foreach t : tests @@ -45,3 +52,18 @@ foreach t : tests suite: ['subset', 'slow'], ) endforeach + +run_repack_test = find_program('run-repack-tests.py') + +foreach t : repack_tests + fname = '@0@.tests'.format(t) + + test(t, run_repack_test, + args: [ + hb_subset, + join_paths(meson.current_source_dir(), 'data', 'repack_tests', fname), + ], + workdir: join_paths(meson.current_build_dir(), '..', '..'), + suite: ['subset', 'repack'], + ) +endforeach diff --git a/test/subset/repack_test.py b/test/subset/repack_test.py new file mode 100644 index 000000000..2b53dd333 --- /dev/null +++ b/test/subset/repack_test.py @@ -0,0 +1,36 @@ +#!/usr/bin/env python3 + +import os + +# Parses a single repacking test file. The first line of the file is +# the name of the font to use and the remaining lines define the set of +# codepoints in the subset. +class RepackTest: + + def __init__(self, test_path, definition): + self.test_path = test_path + self.font_name = None + self.codepoints = set () + self._parse(definition) + + def font_path(self): + return os.path.join (self._base_path (), "fonts", self.font_name) + + def codepoints_string (self): + return ",".join (self.codepoints) + + def _base_path(self): + return os.path.join( + os.path.dirname(self.test_path), + "../") + + + def _parse(self, definition): + lines = definition.splitlines () + self.font_name = lines.pop (0) + for line in lines: + line = line.strip() + if not line: + continue + + self.codepoints.add (line) diff --git a/test/subset/run-repack-tests.py b/test/subset/run-repack-tests.py new file mode 100755 index 000000000..22154ba9f --- /dev/null +++ b/test/subset/run-repack-tests.py @@ -0,0 +1,104 @@ +#!/usr/bin/env python3 + +# Runs a subsetting test suite. Compares the results of subsetting via harfbuzz +# to subsetting via fonttools. + +from difflib import unified_diff +import os +import re +import subprocess +import sys +import tempfile +import shutil +import io + +from repack_test import RepackTest + +try: + from fontTools.ttLib import TTFont +except ImportError: + print ("fonttools is not present, skipping test.") + sys.exit (77) + +ots_sanitize = shutil.which ("ots-sanitize") + +def cmd (command): + p = subprocess.Popen ( + command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, + universal_newlines=True) + (stdoutdata, stderrdata) = p.communicate () + print (stderrdata, end="", file=sys.stderr) + return stdoutdata, p.returncode + +def fail_test (test, cli_args, message): + print ('ERROR: %s' % message) + print ('Test State:') + print (' test.font_name %s' % test.font_name) + print (' test.test_path %s' % os.path.abspath (test.test_path)) + return 1 + +def run_test (test, should_check_ots): + out_file = os.path.join (tempfile.mkdtemp (), test.font_name + '-subset.ttf') + cli_args = [hb_subset, + "--font-file=" + test.font_path (), + "--output-file=" + out_file, + "--unicodes=%s" % test.codepoints_string (), + "--drop-tables-=GPOS,GSUB,GDEF",] + print (' '.join (cli_args)) + _, return_code = cmd (cli_args) + + if return_code: + return fail_test (test, cli_args, "%s returned %d" % (' '.join (cli_args), return_code)) + + try: + with TTFont (out_file) as font: + pass + except Exception as e: + print (e) + return fail_test (test, cli_args, "ttx failed to parse the result") + + if should_check_ots: + print ("Checking output with ots-sanitize.") + if not check_ots (out_file): + return fail_test (test, cli_args, 'ots for subsetted file fails.') + + return 0 + +def has_ots (): + if not ots_sanitize: + print ("OTS is not present, skipping all ots checks.") + return False + return True + +def check_ots (path): + ots_report, returncode = cmd ([ots_sanitize, path]) + if returncode: + print ("OTS Failure: %s" % ots_report) + return False + return True + +args = sys.argv[1:] +if not args or sys.argv[1].find ('hb-subset') == -1 or not os.path.exists (sys.argv[1]): + sys.exit ("First argument does not seem to point to usable hb-subset.") +hb_subset, args = args[0], args[1:] + +if len (args) != 1: + sys.exit ("No tests supplied.") + +has_ots = has_ots() + +fails = 0 + +path = args[0] +if not path.endswith(".tests"): + sys.exit ("Not a valid test case path.") + +with open (path, mode="r", encoding="utf-8") as f: + # TODO(garretrieger): re-enable OTS checking. + fails += run_test (RepackTest (path, f.read ()), False) + + +if fails != 0: + sys.exit ("%d test(s) failed." % fails) +else: + print ("All tests passed.")