Flutter Engine
The Flutter Engine
test.py
Go to the documentation of this file.
1#!/usr/bin/env python3
2#
3# Copyright 2013 The Flutter Authors. All rights reserved.
4# Use of this source code is governed by a BSD-style license that can be
5# found in the LICENSE file.
6
7'''
8Tests for font-subset
9'''
10
11import argparse
12import filecmp
13import os
14import subprocess
15import sys
16from zipfile import ZipFile
17
18SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
19SRC_DIR = os.path.normpath(os.path.join(SCRIPT_DIR, '..', '..', '..'))
20MATERIAL_TTF = os.path.join(SCRIPT_DIR, 'fixtures', 'MaterialIcons-Regular.ttf')
21VARIABLE_MATERIAL_TTF = os.path.join(SCRIPT_DIR, 'fixtures', 'MaterialSymbols-Variable.ttf')
22
23COMPARE_TESTS = (
24 (True, '1.ttf', MATERIAL_TTF, [r'57347']),
25 (True, '1.ttf', MATERIAL_TTF, [r'0xE003']),
26 (True, '1.ttf', MATERIAL_TTF, [r'\uE003']),
27 (False, '1.ttf', MATERIAL_TTF, [r'57348']), # False because different codepoint
28 (True, '2.ttf', MATERIAL_TTF, [r'0xE003', r'0xE004']),
29 (True, '2.ttf', MATERIAL_TTF, [r'0xE003',
30 r'optional:0xE004']), # Optional codepoint that is found
31 (True, '2.ttf', MATERIAL_TTF, [
32 r'0xE003',
33 r'0xE004',
34 r'optional:0x12',
35 ]), # Optional codepoint that is not found
36 (True, '2.ttf', MATERIAL_TTF, [
37 r'0xE003',
38 r'0xE004',
39 r'57347',
40 ]), # Duplicated codepoint
41 (True, '3.ttf', MATERIAL_TTF, [
42 r'0xE003',
43 r'0xE004',
44 r'0xE021',
45 ]),
46 # repeat tests with variable input font and verified variable output goldens
47 (True, '1variable.ttf', VARIABLE_MATERIAL_TTF, [r'57347']),
48 (True, '1variable.ttf', VARIABLE_MATERIAL_TTF, [r'0xE003']),
49 (True, '1variable.ttf', VARIABLE_MATERIAL_TTF, [r'\uE003']),
50 (False, '1variable.ttf', VARIABLE_MATERIAL_TTF, [r'57348'
51 ]), # False because different codepoint
52 (True, '2variable.ttf', VARIABLE_MATERIAL_TTF, [r'0xE003', r'0xE004']),
53 (True, '2variable.ttf', VARIABLE_MATERIAL_TTF, [
54 r'0xE003',
55 r'0xE004',
56 r'57347',
57 ]), # Duplicated codepoint
58 (True, '3variable.ttf', VARIABLE_MATERIAL_TTF, [
59 r'0xE003',
60 r'0xE004',
61 r'0xE021',
62 ]),
63)
64
65
66def fail_tests(font_subset):
67 return [
68 ([font_subset, 'output.ttf', 'does-not-exist.ttf'], [
69 '1',
70 ]), # non-existent input font
71 ([font_subset, 'output.ttf', MATERIAL_TTF], [
72 '0xFFFFFFFF',
73 ]), # Value too big.
74 ([font_subset, 'output.ttf', MATERIAL_TTF], [
75 '-1',
76 ]), # invalid value
77 ([font_subset, 'output.ttf', MATERIAL_TTF], [
78 'foo',
79 ]), # no valid values
80 ([font_subset, 'output.ttf', MATERIAL_TTF], [
81 '0xE003',
82 '0x12',
83 '0xE004',
84 ]), # codepoint not in font
85 ([font_subset, 'non-existent-dir/output.ttf', MATERIAL_TTF], [
86 '0xE003',
87 ]), # dir doesn't exist
88 ([font_subset, 'output.ttf', MATERIAL_TTF], [
89 ' ',
90 ]), # empty input
91 ([font_subset, 'output.ttf', MATERIAL_TTF], []), # empty input
92 ([font_subset, 'output.ttf', MATERIAL_TTF], ['']), # empty input
93 # repeat tests with variable input font
94 ([font_subset, 'output.ttf', VARIABLE_MATERIAL_TTF], [
95 '0xFFFFFFFF',
96 ]), # Value too big.
97 ([font_subset, 'output.ttf', VARIABLE_MATERIAL_TTF], [
98 '-1',
99 ]), # invalid value
100 ([font_subset, 'output.ttf', VARIABLE_MATERIAL_TTF], [
101 'foo',
102 ]), # no valid values
103 ([font_subset, 'output.ttf', VARIABLE_MATERIAL_TTF], [
104 '0xE003',
105 '0x12',
106 '0xE004',
107 ]), # codepoint not in font
108 ([font_subset, 'non-existent-dir/output.ttf', VARIABLE_MATERIAL_TTF], [
109 '0xE003',
110 ]), # dir doesn't exist
111 ([font_subset, 'output.ttf', VARIABLE_MATERIAL_TTF], [
112 ' ',
113 ]), # empty input
114 ([font_subset, 'output.ttf', VARIABLE_MATERIAL_TTF], []), # empty input
115 ([font_subset, 'output.ttf', VARIABLE_MATERIAL_TTF], ['']), # empty input
116 ]
117
118
119def run_cmd(cmd, codepoints, fail=False):
120 print('Running command:')
121 print(' %s' % ' '.join(cmd))
122 print('STDIN: "%s"' % ' '.join(codepoints))
123 p = subprocess.Popen(
124 cmd, stdout=subprocess.PIPE, stdin=subprocess.PIPE, stderr=subprocess.PIPE, cwd=SRC_DIR
125 )
126 stdout_data, stderr_data = p.communicate(input=' '.join(codepoints).encode())
127 if p.returncode != 0 and fail == False:
128 print('FAILURE: %s' % p.returncode)
129 print('STDOUT:')
130 print(stdout_data)
131 print('STDERR:')
132 print(stderr_data)
133 elif p.returncode == 0 and fail == True:
134 print('FAILURE - test passed but should have failed.')
135 print('STDOUT:')
136 print(stdout_data)
137 print('STDERR:')
138 print(stderr_data)
139 else:
140 print('Success.')
141
142 return p.returncode
143
144
145def test_zip(font_subset_zip, exe):
146 with ZipFile(font_subset_zip, 'r') as zip:
147 files = zip.namelist()
148 if 'font-subset%s' % exe not in files:
149 print('expected %s to contain font-subset%s' % (files, exe))
150 return 1
151 return 0
152
153
154# Maps the platform name to the output directory of the font artifacts.
155def platform_to_path(os, cpu):
156 d = {
157 'darwin': 'darwin-',
158 'linux': 'linux-',
159 'linux2': 'linux-',
160 'cygwin': 'windows-',
161 'win': 'windows-',
162 'win32': 'windows-',
163 }
164 return d[os] + cpu
165
166
167def main():
168 parser = argparse.ArgumentParser(description='Runs font-subset tests.')
169 parser.add_argument('--variant', type=str, required=True)
170 parser.add_argument('--target-cpu', type=str, default='x64')
171 args = parser.parse_args()
172 variant = args.variant
173
174 is_windows = sys.platform.startswith(('cygwin', 'win'))
175 exe = '.exe' if is_windows else ''
176 font_subset = os.path.join(SRC_DIR, 'out', variant, 'font-subset' + exe)
177 font_subset_zip = os.path.join(
178 SRC_DIR, 'out', variant, 'zip_archives', platform_to_path(sys.platform, args.target_cpu),
179 'font-subset.zip'
180 )
181 if not os.path.isfile(font_subset):
182 raise Exception(
183 'Could not locate font-subset%s in %s - build before running this script.' % (exe, variant)
184 )
185
186 print('Using font subset binary at %s (%s)' % (font_subset, font_subset_zip))
187 failures = 0
188
189 failures += test_zip(font_subset_zip, exe)
190
191 for should_pass, golden_font, input_font, codepoints in COMPARE_TESTS:
192 gen_ttf = os.path.join(SCRIPT_DIR, 'gen', golden_font)
193 golden_ttf = os.path.join(SCRIPT_DIR, 'fixtures', golden_font)
194 cmd = [font_subset, gen_ttf, input_font]
195 run_cmd(cmd, codepoints)
196 cmp = filecmp.cmp(gen_ttf, golden_ttf, shallow=False)
197 if (should_pass and not cmp) or (not should_pass and cmp):
198 print('Test case %s failed.' % cmd)
199 failures += 1
200
201 with open(os.devnull, 'w') as devnull:
202 for cmd, codepoints in fail_tests(font_subset):
203 if run_cmd(cmd, codepoints, fail=True) == 0:
204 failures += 1
205
206 if failures > 0:
207 print('%s test(s) failed.' % failures)
208 return 1
209
210 print('All tests passed')
211 return 0
212
213
214if __name__ == '__main__':
215 sys.exit(main())
static void encode(uint8_t output[16], const uint32_t input[4])
Definition: SkMD5.cpp:240
Definition: main.py:1
def print(*args, **kwargs)
Definition: run_tests.py:49
def test_zip(font_subset_zip, exe)
Definition: test.py:145
def platform_to_path(os, cpu)
Definition: test.py:155
def fail_tests(font_subset)
Definition: test.py:66
def main()
Definition: test.py:167
def run_cmd(cmd, codepoints, fail=False)
Definition: test.py:119
static SkString join(const CommandLineFlags::StringArray &)
Definition: skpbench.cpp:741