xref: /aosp_15_r20/external/harfbuzz_ng/test/subset/run-repack-tests.py (revision 2d1272b857b1f7575e6e246373e1cb218663db8a)
1*2d1272b8SAndroid Build Coastguard Worker#!/usr/bin/env python3
2*2d1272b8SAndroid Build Coastguard Worker
3*2d1272b8SAndroid Build Coastguard Worker# Runs a subsetting test suite. Compares the results of subsetting via harfbuzz
4*2d1272b8SAndroid Build Coastguard Worker# to subsetting via fonttools.
5*2d1272b8SAndroid Build Coastguard Worker
6*2d1272b8SAndroid Build Coastguard Workerfrom difflib import unified_diff
7*2d1272b8SAndroid Build Coastguard Workerimport os
8*2d1272b8SAndroid Build Coastguard Workerimport re
9*2d1272b8SAndroid Build Coastguard Workerimport subprocess
10*2d1272b8SAndroid Build Coastguard Workerimport sys
11*2d1272b8SAndroid Build Coastguard Workerimport tempfile
12*2d1272b8SAndroid Build Coastguard Workerimport shutil
13*2d1272b8SAndroid Build Coastguard Workerimport io
14*2d1272b8SAndroid Build Coastguard Worker
15*2d1272b8SAndroid Build Coastguard Workerfrom repack_test import RepackTest
16*2d1272b8SAndroid Build Coastguard Worker
17*2d1272b8SAndroid Build Coastguard Workertry:
18*2d1272b8SAndroid Build Coastguard Worker	from fontTools.ttLib import TTFont
19*2d1272b8SAndroid Build Coastguard Workerexcept ImportError:
20*2d1272b8SAndroid Build Coastguard Worker	print ("fonttools is not present, skipping test.")
21*2d1272b8SAndroid Build Coastguard Worker	sys.exit (77)
22*2d1272b8SAndroid Build Coastguard Worker
23*2d1272b8SAndroid Build Coastguard Workerots_sanitize = shutil.which ("ots-sanitize")
24*2d1272b8SAndroid Build Coastguard Worker
25*2d1272b8SAndroid Build Coastguard Workerdef subset_cmd (command):
26*2d1272b8SAndroid Build Coastguard Worker	global hb_subset, process
27*2d1272b8SAndroid Build Coastguard Worker	print (hb_subset + ' ' + " ".join(command))
28*2d1272b8SAndroid Build Coastguard Worker	process.stdin.write ((';'.join (command) + '\n').encode ("utf-8"))
29*2d1272b8SAndroid Build Coastguard Worker	process.stdin.flush ()
30*2d1272b8SAndroid Build Coastguard Worker	return process.stdout.readline().decode ("utf-8").strip ()
31*2d1272b8SAndroid Build Coastguard Worker
32*2d1272b8SAndroid Build Coastguard Workerdef cmd (command):
33*2d1272b8SAndroid Build Coastguard Worker	p = subprocess.Popen (
34*2d1272b8SAndroid Build Coastguard Worker		command, stdout=subprocess.PIPE, stderr=subprocess.PIPE,
35*2d1272b8SAndroid Build Coastguard Worker		universal_newlines=True)
36*2d1272b8SAndroid Build Coastguard Worker	(stdoutdata, stderrdata) = p.communicate ()
37*2d1272b8SAndroid Build Coastguard Worker	print (stderrdata, end="", file=sys.stderr)
38*2d1272b8SAndroid Build Coastguard Worker	return stdoutdata, p.returncode
39*2d1272b8SAndroid Build Coastguard Worker
40*2d1272b8SAndroid Build Coastguard Workerdef fail_test (test, cli_args, message):
41*2d1272b8SAndroid Build Coastguard Worker	print ('ERROR: %s' % message)
42*2d1272b8SAndroid Build Coastguard Worker	print ('Test State:')
43*2d1272b8SAndroid Build Coastguard Worker	print ('  test.font_name    %s' % test.font_name)
44*2d1272b8SAndroid Build Coastguard Worker	print ('  test.test_path %s' % os.path.abspath (test.test_path))
45*2d1272b8SAndroid Build Coastguard Worker	return 1
46*2d1272b8SAndroid Build Coastguard Worker
47*2d1272b8SAndroid Build Coastguard Workerdef run_test (test, should_check_ots):
48*2d1272b8SAndroid Build Coastguard Worker	out_file = os.path.join (tempfile.mkdtemp (), test.font_name + '-subset.ttf')
49*2d1272b8SAndroid Build Coastguard Worker	cli_args = ["--font-file=" + test.font_path (),
50*2d1272b8SAndroid Build Coastguard Worker		    "--output-file=" + out_file,
51*2d1272b8SAndroid Build Coastguard Worker		    "--unicodes=%s" % test.codepoints_string (),
52*2d1272b8SAndroid Build Coastguard Worker		    "--drop-tables-=GPOS,GSUB,GDEF",]
53*2d1272b8SAndroid Build Coastguard Worker	print (' '.join (cli_args))
54*2d1272b8SAndroid Build Coastguard Worker	ret = subset_cmd (cli_args)
55*2d1272b8SAndroid Build Coastguard Worker
56*2d1272b8SAndroid Build Coastguard Worker	if ret != "success":
57*2d1272b8SAndroid Build Coastguard Worker		return fail_test (test, cli_args, "%s failed" % ' '.join (cli_args))
58*2d1272b8SAndroid Build Coastguard Worker
59*2d1272b8SAndroid Build Coastguard Worker	try:
60*2d1272b8SAndroid Build Coastguard Worker		with TTFont (out_file) as font:
61*2d1272b8SAndroid Build Coastguard Worker			pass
62*2d1272b8SAndroid Build Coastguard Worker	except Exception as e:
63*2d1272b8SAndroid Build Coastguard Worker		print (e)
64*2d1272b8SAndroid Build Coastguard Worker		return fail_test (test, cli_args, "ttx failed to parse the result")
65*2d1272b8SAndroid Build Coastguard Worker
66*2d1272b8SAndroid Build Coastguard Worker	if should_check_ots:
67*2d1272b8SAndroid Build Coastguard Worker		print ("Checking output with ots-sanitize.")
68*2d1272b8SAndroid Build Coastguard Worker		if not check_ots (out_file):
69*2d1272b8SAndroid Build Coastguard Worker			return fail_test (test, cli_args, 'ots for subsetted file fails.')
70*2d1272b8SAndroid Build Coastguard Worker
71*2d1272b8SAndroid Build Coastguard Worker	return 0
72*2d1272b8SAndroid Build Coastguard Worker
73*2d1272b8SAndroid Build Coastguard Workerdef has_ots ():
74*2d1272b8SAndroid Build Coastguard Worker	if not ots_sanitize:
75*2d1272b8SAndroid Build Coastguard Worker		print ("OTS is not present, skipping all ots checks.")
76*2d1272b8SAndroid Build Coastguard Worker		return False
77*2d1272b8SAndroid Build Coastguard Worker	return True
78*2d1272b8SAndroid Build Coastguard Worker
79*2d1272b8SAndroid Build Coastguard Workerdef check_ots (path):
80*2d1272b8SAndroid Build Coastguard Worker	ots_report, returncode = cmd ([ots_sanitize, path])
81*2d1272b8SAndroid Build Coastguard Worker	if returncode:
82*2d1272b8SAndroid Build Coastguard Worker		print ("OTS Failure: %s" % ots_report)
83*2d1272b8SAndroid Build Coastguard Worker		return False
84*2d1272b8SAndroid Build Coastguard Worker	return True
85*2d1272b8SAndroid Build Coastguard Worker
86*2d1272b8SAndroid Build Coastguard Workerargs = sys.argv[1:]
87*2d1272b8SAndroid Build Coastguard Workerif not args or sys.argv[1].find ('hb-subset') == -1 or not os.path.exists (sys.argv[1]):
88*2d1272b8SAndroid Build Coastguard Worker	sys.exit ("First argument does not seem to point to usable hb-subset.")
89*2d1272b8SAndroid Build Coastguard Workerhb_subset, args = args[0], args[1:]
90*2d1272b8SAndroid Build Coastguard Worker
91*2d1272b8SAndroid Build Coastguard Workerif len (args) != 1:
92*2d1272b8SAndroid Build Coastguard Worker	sys.exit ("No tests supplied.")
93*2d1272b8SAndroid Build Coastguard Worker
94*2d1272b8SAndroid Build Coastguard Workerhas_ots = has_ots()
95*2d1272b8SAndroid Build Coastguard Worker
96*2d1272b8SAndroid Build Coastguard Workerprocess = subprocess.Popen ([hb_subset, '--batch'],
97*2d1272b8SAndroid Build Coastguard Worker                            stdin=subprocess.PIPE,
98*2d1272b8SAndroid Build Coastguard Worker                            stdout=subprocess.PIPE,
99*2d1272b8SAndroid Build Coastguard Worker                            stderr=sys.stdout)
100*2d1272b8SAndroid Build Coastguard Worker
101*2d1272b8SAndroid Build Coastguard Workerfails = 0
102*2d1272b8SAndroid Build Coastguard Worker
103*2d1272b8SAndroid Build Coastguard Workerpath = args[0]
104*2d1272b8SAndroid Build Coastguard Workerif not path.endswith(".tests"):
105*2d1272b8SAndroid Build Coastguard Worker        sys.exit ("Not a valid test case path.")
106*2d1272b8SAndroid Build Coastguard Worker
107*2d1272b8SAndroid Build Coastguard Workerwith open (path, mode="r", encoding="utf-8") as f:
108*2d1272b8SAndroid Build Coastguard Worker	# TODO(garretrieger): re-enable OTS checking.
109*2d1272b8SAndroid Build Coastguard Worker	fails += run_test (RepackTest (path, f.read ()), False)
110*2d1272b8SAndroid Build Coastguard Worker
111*2d1272b8SAndroid Build Coastguard Worker
112*2d1272b8SAndroid Build Coastguard Workerif fails != 0:
113*2d1272b8SAndroid Build Coastguard Worker	sys.exit ("%d test(s) failed." % fails)
114*2d1272b8SAndroid Build Coastguard Workerelse:
115*2d1272b8SAndroid Build Coastguard Worker	print ("All tests passed.")
116