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