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