• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/usr/bin/env python3
2
3import sys, os, subprocess, hashlib
4
5def cmd(command):
6	print (command)
7	global process
8	process.stdin.write ((':'.join (command) + '\n').encode ("utf-8"))
9	process.stdin.flush ()
10	return process.stdout.readline().decode ("utf-8").strip ()
11
12args = sys.argv[1:]
13
14reference = False
15if len (args) and args[0] == "--reference":
16	reference = True
17	args = args[1:]
18
19have_freetype = bool(int(os.getenv ('HAVE_FREETYPE', '1')))
20
21if not args or args[0].find('hb-shape') == -1 or not os.path.exists (args[0]):
22	sys.exit ("""First argument does not seem to point to usable hb-shape.""")
23hb_shape, args = args[0], args[1:]
24
25process = subprocess.Popen ([hb_shape, '--batch'],
26			    stdin=subprocess.PIPE,
27			    stdout=subprocess.PIPE,
28			    stderr=sys.stdout)
29
30passes = 0
31fails = 0
32skips = 0
33
34if not len (args):
35	args = ['-']
36
37for filename in args:
38	if not reference:
39		if filename == '-':
40			print ("Running tests from standard input")
41		else:
42			print ("Running tests in " + filename)
43
44	if filename == '-':
45		f = sys.stdin
46	else:
47		f = open (filename, encoding='utf8')
48
49	for line in f:
50		comment = False
51		if line.startswith ("#"):
52			comment = True
53			line = line[1:]
54
55			if line.startswith (' '):
56				if not reference:
57					print ("#%s" % line)
58				continue
59
60		line = line.strip ()
61		if not line:
62			continue
63
64		fontfile, options, unicodes, glyphs_expected = line.split (":")
65		options = options.split ()
66		if fontfile.startswith ('/') or fontfile.startswith ('"/'):
67			if os.name == 'nt': # Skip on Windows
68				continue
69
70			fontfile, expected_hash = (fontfile.split('@') + [''])[:2]
71
72			try:
73				with open (fontfile, 'rb') as ff:
74					if expected_hash:
75						actual_hash = hashlib.sha1 (ff.read()).hexdigest ().strip ()
76						if actual_hash != expected_hash:
77							print ('different version of %s found; Expected hash %s, got %s; skipping.' %
78								   (fontfile, expected_hash, actual_hash))
79							skips += 1
80							continue
81			except IOError:
82				print ('%s not found, skip.' % fontfile)
83				skips += 1
84				continue
85		else:
86			cwd = os.path.dirname(filename)
87			fontfile = os.path.normpath (os.path.join (cwd, fontfile))
88
89		extra_options = ["--shaper=ot"]
90		if glyphs_expected != '*':
91			extra_options.append("--verify")
92
93		if comment:
94			if not reference:
95				print ('# %s "%s" --unicodes %s' % (hb_shape, fontfile, unicodes))
96			continue
97
98		if not reference:
99			print ('%s "%s" %s %s --unicodes %s' %
100					 (hb_shape, fontfile, ' '.join(extra_options), ' '.join(options), unicodes))
101
102		if "--font-funcs=ft" in options and not have_freetype:
103			skips += 1
104			continue
105
106		if "--font-funcs=ot" in options or not have_freetype:
107			glyphs1 = cmd ([hb_shape, fontfile, "--font-funcs=ot"] + extra_options + ["--unicodes", unicodes] + options)
108		else:
109			glyphs1 = cmd ([hb_shape, fontfile, "--font-funcs=ft"] + extra_options + ["--unicodes", unicodes] + options)
110			glyphs2 = cmd ([hb_shape, fontfile, "--font-funcs=ot"] + extra_options + ["--unicodes", unicodes] + options)
111
112			if glyphs1 != glyphs2 and glyphs_expected != '*':
113				print ("FT funcs: " + glyphs1, file=sys.stderr)
114				print ("OT funcs: " + glyphs2, file=sys.stderr)
115				fails += 1
116			else:
117				passes += 1
118
119		if reference:
120			print (":".join ([fontfile, " ".join(options), unicodes, glyphs1]))
121			continue
122
123		if glyphs1.strip() != glyphs_expected and glyphs_expected != '*':
124			print ("Actual:   " + glyphs1, file=sys.stderr)
125			print ("Expected: " + glyphs_expected, file=sys.stderr)
126			fails += 1
127		else:
128			passes += 1
129
130if not reference:
131	print ("%d tests passed; %d failed; %d skipped." % (passes, fails, skips), file=sys.stderr)
132	if not (fails + passes):
133		print ("No tests ran.")
134	elif not (fails + skips):
135		print ("All tests passed.")
136
137if fails:
138	sys.exit (1)
139elif passes:
140	sys.exit (0)
141else:
142	sys.exit (77)
143