Imported Upstream version 2.6.7
[platform/upstream/harfbuzz.git] / test / subset / run-tests.py
1 #!/usr/bin/env python3
2
3 # Runs a subsetting test suite. Compares the results of subsetting via harfbuzz
4 # to subsetting via fonttools.
5
6 from difflib import unified_diff
7 import os
8 import re
9 import subprocess
10 import sys
11 import tempfile
12 import shutil
13
14 from subset_test_suite import SubsetTestSuite
15
16 fonttools = shutil.which ("fonttools")
17 ots_sanitize = shutil.which ("ots-sanitize")
18
19 if not fonttools:
20         print ("fonttools is not present, skipping test.")
21         sys.exit (77)
22
23 def cmd (command):
24         p = subprocess.Popen (
25                 command, stdout=subprocess.PIPE, stderr=subprocess.PIPE,
26                 universal_newlines=True)
27         (stdoutdata, stderrdata) = p.communicate ()
28         print (stderrdata, end="", file=sys.stderr)
29         return stdoutdata, p.returncode
30
31 def read_binary (file_path):
32         with open (file_path, 'rb') as f:
33                 return f.read ()
34
35 def fail_test (test, cli_args, message):
36         print ('ERROR: %s' % message)
37         print ('Test State:')
38         print ('  test.font_path    %s' % os.path.abspath (test.font_path))
39         print ('  test.profile_path %s' % os.path.abspath (test.profile_path))
40         print ('  test.unicodes     %s' % test.unicodes ())
41         expected_file = os.path.join(test_suite.get_output_directory (),
42                                      test.get_font_name ())
43         print ('  expected_file     %s' % os.path.abspath (expected_file))
44         return 1
45
46 def run_test (test, should_check_ots):
47         out_file = os.path.join (tempfile.mkdtemp (), test.get_font_name () + '-subset' + test.get_font_extension ())
48         cli_args = [hb_subset,
49                     "--font-file=" + test.font_path,
50                     "--output-file=" + out_file,
51                     "--unicodes=%s" % test.unicodes (),
52                     "--drop-tables+=DSIG,GPOS,GSUB,GDEF",
53                     "--drop-tables-=sbix"]
54         cli_args.extend (test.get_profile_flags ())
55         print (' '.join (cli_args))
56         _, return_code = cmd (cli_args)
57
58         if return_code:
59                 return fail_test (test, cli_args, "%s returned %d" % (' '.join (cli_args), return_code))
60
61         expected_ttx = tempfile.mktemp ()
62         _, return_code = run_ttx (os.path.join (test_suite.get_output_directory (),
63                                                                                 test.get_font_name ()),
64                                                           expected_ttx)
65         if return_code:
66                 if os.path.exists (expected_ttx): os.remove (expected_ttx)
67                 return fail_test (test, cli_args, "ttx (expected) returned %d" % (return_code))
68
69         actual_ttx = tempfile.mktemp ()
70         _, return_code = run_ttx (out_file, actual_ttx)
71         if return_code:
72                 if os.path.exists (expected_ttx): os.remove (expected_ttx)
73                 if os.path.exists (actual_ttx): os.remove (actual_ttx)
74                 return fail_test (test, cli_args, "ttx (actual) returned %d" % (return_code))
75
76         with open (expected_ttx, encoding='utf-8') as f:
77                 expected_ttx_text = f.read ()
78         with open (actual_ttx, encoding='utf-8') as f:
79                 actual_ttx_text = f.read ()
80
81         # cleanup
82         try:
83                 os.remove (expected_ttx)
84                 os.remove (actual_ttx)
85         except:
86                 pass
87
88         print ("stripping checksums.")
89         expected_ttx_text = strip_check_sum (expected_ttx_text)
90         actual_ttx_text = strip_check_sum (actual_ttx_text)
91
92         if not actual_ttx_text == expected_ttx_text:
93                 for line in unified_diff (expected_ttx_text.splitlines (1), actual_ttx_text.splitlines (1)):
94                         sys.stdout.write (line)
95                 sys.stdout.flush ()
96                 return fail_test (test, cli_args, 'ttx for expected and actual does not match.')
97
98         if should_check_ots:
99                 print ("Checking output with ots-sanitize.")
100                 if not check_ots (out_file):
101                         return fail_test (test, cli_args, 'ots for subsetted file fails.')
102
103         return 0
104
105 def run_ttx (font_path, ttx_output_path):
106         print ("fonttools ttx %s" % font_path)
107         return cmd ([fonttools, "ttx", "-q", "-o", ttx_output_path, font_path])
108
109 def strip_check_sum (ttx_string):
110         return re.sub ('checkSumAdjustment value=["]0x([0-9a-fA-F])+["]',
111                        'checkSumAdjustment value="0x00000000"',
112                        ttx_string, count=1)
113
114 def has_ots ():
115         if not ots_sanitize:
116                 print("OTS is not present, skipping all ots checks.")
117                 return False
118         return True
119
120 def check_ots (path):
121         ots_report, returncode = cmd ([ots_sanitize, path])
122         if returncode:
123                 print ("OTS Failure: %s" % ots_report)
124                 return False
125         return True
126
127 args = sys.argv[1:]
128 if not args or sys.argv[1].find ('hb-subset') == -1 or not os.path.exists (sys.argv[1]):
129         sys.exit ("First argument does not seem to point to usable hb-subset.")
130 hb_subset, args = args[0], args[1:]
131
132 if not len (args):
133         sys.exit ("No tests supplied.")
134
135 has_ots = has_ots()
136
137 fails = 0
138 for path in args:
139         with open (path, mode="r", encoding="utf-8") as f:
140                 print ("Running tests in " + path)
141                 test_suite = SubsetTestSuite (path, f.read ())
142                 for test in test_suite.tests ():
143                         fails += run_test (test, has_ots)
144
145 if fails != 0:
146         sys.exit ("%d test(s) failed." % fails)
147 else:
148         print ("All tests passed.")