xref: /aosp_15_r20/external/harfbuzz_ng/test/subset/subset_test_suite.py (revision 2d1272b857b1f7575e6e246373e1cb218663db8a)
1#!/usr/bin/env python3
2
3import os
4
5# A single test in a subset test suite. Identifies a font
6# a subsetting profile, and a subset to be cut.
7class Test:
8	def __init__(self, font_path, profile_path, subset, instance, iup_optimize, options):
9		self.font_path = font_path
10		self.profile_path = profile_path
11		self.subset = subset
12		self.instance = instance
13		self.iup_optimize = iup_optimize
14		self.options = options
15
16	def unicodes(self):
17		import re
18		if self.subset == '*':
19			return self.subset[0]
20		elif self.subset == "no-unicodes":
21			return ""
22		elif re.match("^U\+", self.subset):
23			s = re.sub (r"U\+", "", self.subset)
24			return s
25		else:
26			return ",".join("%X" % ord(c) for (i, c) in enumerate(self.subset))
27
28	def instance_name(self):
29		if not self.instance:
30			return self.instance
31		else:
32			s = "." + self.instance.replace(':', '-')
33			if self.iup_optimize:
34				s += ".iup_optimize"
35			return s
36
37	def get_profile_flags(self):
38		with open (self.profile_path, mode="r", encoding="utf-8") as f:
39		    return f.read().splitlines()
40
41	def get_instance_flags(self):
42		if not self.instance:
43			return []
44		else:
45			return self.instance.split(',')
46
47	def get_font_name(self):
48		font_base_name = os.path.basename(self.font_path)
49		font_base_name_parts = os.path.splitext(font_base_name)
50		profile_name = os.path.splitext(os.path.basename(self.profile_path))[0]
51
52		if self.unicodes() == "*":
53			return "%s.%s.all%s%s" % (font_base_name_parts[0],
54				       profile_name,
55				       self.instance_name(),
56				       font_base_name_parts[1])
57		elif self.unicodes() == "":
58			return "%s.%s.no-unicodes%s%s" % (font_base_name_parts[0],
59				       profile_name,
60				       self.instance_name(),
61				       font_base_name_parts[1])
62		else:
63			return "%s.%s.%s%s%s" % (font_base_name_parts[0],
64				       profile_name,
65				       self.unicodes(),
66				       self.instance_name(),
67				       font_base_name_parts[1])
68
69	def get_font_extension(self):
70		font_base_name = os.path.basename(self.font_path)
71		font_base_name_parts = os.path.splitext(font_base_name)
72		return font_base_name_parts[1]
73
74# A group of tests to perform on the subsetter. Each test
75# Identifies a font a subsetting profile, and a subset to be cut.
76class SubsetTestSuite:
77
78	def __init__(self, test_path, definition):
79		self.test_path = test_path
80		self.fonts = []
81		self.profiles = []
82		self.subsets = []
83		self.instances = []
84		self.options = []
85		self.iup_options = []
86		self._parse(definition)
87
88	def get_output_directory(self):
89		test_name = os.path.splitext(os.path.basename(self.test_path))[0]
90		data_dir = os.path.join(os.path.dirname(self.test_path), "..")
91
92		output_dir = os.path.normpath(os.path.join(data_dir, "expected", test_name))
93		if not os.path.exists(output_dir):
94			os.mkdir(output_dir)
95		if not os.path.isdir(output_dir):
96			raise Exception("%s is not a directory." % output_dir)
97
98		return output_dir
99
100	def tests(self):
101		for font in self.fonts:
102			font = os.path.join(self._base_path(), "fonts", font)
103			for profile in self.profiles:
104				profile = os.path.join(self._base_path(), "profiles", profile)
105				for subset in self.subsets:
106					if self.instances:
107						for instance in self.instances:
108							if self.iup_options:
109								for iup_option in self.iup_options:
110									yield Test(font, profile, subset, instance, iup_option == 'Yes', options=self.options)
111							else:
112								yield Test(font, profile, subset, instance, False, options=self.options)
113					else:
114						yield Test(font, profile, subset, "", False, options=self.options)
115
116	def _base_path(self):
117		return os.path.dirname(os.path.dirname(self.test_path))
118
119	def _parse(self, definition):
120		destinations = {
121				"FONTS:": self.fonts,
122				"PROFILES:": self.profiles,
123				"SUBSETS:": self.subsets,
124				"INSTANCES:": self.instances,
125				"OPTIONS:": self.options,
126				"IUP_OPTIONS:": self.iup_options,
127		}
128
129		current_destination = None
130		for line in definition.splitlines():
131			line = line.strip()
132
133			if line.startswith("#"):
134				continue
135
136			if not line:
137				continue
138
139			if line in destinations:
140				current_destination = destinations[line]
141			elif current_destination is not None:
142				current_destination.append(line)
143			else:
144				raise Exception("Failed to parse test suite file.")
145