• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/usr/bin/env python
2
3#
4# Copyright (C) 2024 The Android Open Source Project
5#
6# Licensed under the Apache License, Version 2.0 (the "License");
7# you may not use this file except in compliance with the License.
8# You may obtain a copy of the License at
9#
10#      http://www.apache.org/licenses/LICENSE-2.0
11#
12# Unless required by applicable law or agreed to in writing, software
13# distributed under the License is distributed on an "AS IS" BASIS,
14# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15# See the License for the specific language governing permissions and
16# limitations under the License.
17#
18
19import json
20import sys
21import unittest
22
23from font_builder import parse_font_from_json_for_sanitization_test, parse_fonts_from_json_for_validation_test
24
25
26class FontBuilderTest(unittest.TestCase):
27
28  def test_parse_font_invalid_file(self):
29    # File must be string
30    self.assertRaises(
31        AssertionError,
32        parse_font_from_json_for_sanitization_test,
33        """{ "file": [] }""",
34    )
35    self.assertRaises(
36        AssertionError,
37        parse_font_from_json_for_sanitization_test,
38        """{ "file": -10 }""",
39    )
40    self.assertRaises(
41        AssertionError,
42        parse_font_from_json_for_sanitization_test,
43        """{ "file": 0.5 }""",
44    )
45
46  def test_parse_font_invalid_weight(self):
47    # Weight only accept integer or string as integer.
48    self.assertRaises(
49        AssertionError,
50        parse_font_from_json_for_sanitization_test,
51        """{ "weight": [] }""",
52    )
53    self.assertRaises(
54        AssertionError,
55        parse_font_from_json_for_sanitization_test,
56        """{ "weight": 0.5 }""",
57    )
58    self.assertRaises(
59        AssertionError,
60        parse_font_from_json_for_sanitization_test,
61        """{ "weight": "0.5" }""",
62    )
63    self.assertRaises(
64        AssertionError,
65        parse_font_from_json_for_sanitization_test,
66        """{ "weight": -10 }""",
67    )
68    self.assertRaises(
69        AssertionError,
70        parse_font_from_json_for_sanitization_test,
71        """{ "weight": 1001 }""",
72    )
73    self.assertRaises(
74        AssertionError,
75        parse_font_from_json_for_sanitization_test,
76        """{ "weight": "-10" }""",
77    )
78    self.assertRaises(
79        AssertionError,
80        parse_font_from_json_for_sanitization_test,
81        """{ "weight": "1001" }""",
82    )
83
84  def test_parse_font_invalid_style(self):
85    # Style only accept string "noromal" or "italic"
86    self.assertRaises(
87        AssertionError,
88        parse_font_from_json_for_sanitization_test,
89        """{ "style": [] }""",
90    )
91    self.assertRaises(
92        AssertionError,
93        parse_font_from_json_for_sanitization_test,
94        """{ "style": 0 }""",
95    )
96    self.assertRaises(
97        AssertionError,
98        parse_font_from_json_for_sanitization_test,
99        """{ "style": "foo" }""",
100    )
101
102  def test_parse_font_invalid_index(self):
103    # Index only accepts integer or string as integer that equals or larger than zero.
104    self.assertRaises(
105        AssertionError,
106        parse_font_from_json_for_sanitization_test,
107        """{ "index": [] }""",
108    )
109    self.assertRaises(
110        AssertionError,
111        parse_font_from_json_for_sanitization_test,
112        """{ "index": "foo" }""",
113    )
114    self.assertRaises(
115        AssertionError,
116        parse_font_from_json_for_sanitization_test,
117        """{ "index": -1 }""",
118    )
119    self.assertRaises(
120        AssertionError,
121        parse_font_from_json_for_sanitization_test,
122        """{ "index": "-1" }""",
123    )
124
125  def test_parse_font_invalid_supportedAxes(self):
126    # The supportedAxes only accepts wght or wght,ital.
127    self.assertRaises(
128        AssertionError,
129        parse_font_from_json_for_sanitization_test,
130        """{ "supportedAxes": [] }""",
131    )
132    self.assertRaises(
133        AssertionError,
134        parse_font_from_json_for_sanitization_test,
135        """{ "supportedAxes": 0 }""",
136    )
137    self.assertRaises(
138        AssertionError,
139        parse_font_from_json_for_sanitization_test,
140        """{ "supportedAxes": 0.5 }""",
141    )
142    self.assertRaises(
143        AssertionError,
144        parse_font_from_json_for_sanitization_test,
145        """{ "supportedAxes": "1" }""",
146    )
147    self.assertRaises(
148        AssertionError,
149        parse_font_from_json_for_sanitization_test,
150        """{ "supportedAxes": "ital" }""",
151    )
152    self.assertRaises(
153        AssertionError,
154        parse_font_from_json_for_sanitization_test,
155        """{ "supportedAxes": "wghtital" }""",
156    )
157
158  def test_parse_font_invalid_post_script_name(self):
159    # The postScriptName only accepts string.
160    self.assertRaises(
161        AssertionError,
162        parse_font_from_json_for_sanitization_test,
163        """{ "postScriptName": [] }""",
164    )
165    self.assertRaises(
166        AssertionError,
167        parse_font_from_json_for_sanitization_test,
168        """{ "postScriptName": 1 }""",
169    )
170    self.assertRaises(
171        AssertionError,
172        parse_font_from_json_for_sanitization_test,
173        """{ "postScriptName": 0.5 }""",
174    )
175
176  def test_parse_font_invalid_axes(self):
177    # The axes accept OpenType tag to float value.
178    self.assertRaises(
179        AssertionError,
180        parse_font_from_json_for_sanitization_test,
181        """{ "axes": [] }""",
182    )
183    self.assertRaises(
184        AssertionError,
185        parse_font_from_json_for_sanitization_test,
186        """{ "axes": "foo" }""",
187    )
188    self.assertRaises(
189        AssertionError,
190        parse_font_from_json_for_sanitization_test,
191        """{ "axes": 1 }""",
192    )
193    self.assertRaises(
194        AssertionError,
195        parse_font_from_json_for_sanitization_test,
196        """{
197                        "axes":{
198                          "wght": "ital"
199                        }
200                      }""",
201    )
202    self.assertRaises(
203        AssertionError,
204        parse_font_from_json_for_sanitization_test,
205        """{
206                        "axes":{
207                          "weight": 100
208                        }
209                      }""",
210    )
211
212  def test_parse_font_unknown_key(self):
213    self.assertRaises(
214        AssertionError,
215        parse_font_from_json_for_sanitization_test,
216        """{ "font": "Roboto-Regular.ttf" }""",
217    )
218
219  def test_parse_font_invalid_font(self):
220    # empty fonts are not allowed
221    self.assertRaises(
222        AssertionError, parse_fonts_from_json_for_validation_test, """[]"""
223    )
224    # At least file should be specified
225    self.assertRaises(
226        AssertionError, parse_fonts_from_json_for_validation_test, """[{}]"""
227    )
228    # If supportedAxes is not spccified, weight and style should be specified.
229    self.assertRaises(
230        AssertionError,
231        parse_fonts_from_json_for_validation_test,
232        """[{
233                        "file": "Roboto-Regular.ttf",
234                        "weight": 400
235                      }]""",
236    )
237    self.assertRaises(
238        AssertionError,
239        parse_fonts_from_json_for_validation_test,
240        """[{
241                        "file": "Roboto-Regular.ttf",
242                        "style": "normal"
243                      }]""",
244    )
245
246  def test_parse_font(self):
247    fonts = parse_fonts_from_json_for_validation_test("""[
248      {
249        "file": "Roboto-Regular.ttf",
250        "weight": 700,
251        "style": "normal",
252        "axes": {
253          "wght": 700
254        }
255      }, {
256        "file": "Roboto-Italic.ttf",
257        "weight": 700,
258        "style": "italic",
259        "axes": {
260          "wght": 700
261        }
262      }
263    ]""")
264    self.assertEqual(2, len(fonts))
265
266    self.assertEqual("Roboto-Regular.ttf", fonts[0].file)
267    self.assertEqual(700, fonts[0].weight)
268    self.assertEqual("normal", fonts[0].style)
269    self.assertEqual(1, len(fonts[0].axes))
270    self.assertEqual(700, fonts[0].axes["wght"])
271    self.assertIsNone(fonts[0].index)
272    self.assertIsNone(fonts[0].supported_axes)
273    self.assertIsNone(fonts[0].post_script_name)
274
275    self.assertEqual("Roboto-Italic.ttf", fonts[1].file)
276    self.assertEqual(700, fonts[1].weight)
277    self.assertEqual("italic", fonts[1].style)
278    self.assertEqual(1, len(fonts[1].axes))
279    self.assertEqual(700, fonts[1].axes["wght"])
280    self.assertIsNone(fonts[1].index)
281    self.assertIsNone(fonts[1].supported_axes)
282    self.assertIsNone(fonts[1].post_script_name)
283
284  def test_parse_font2(self):
285    fonts = parse_fonts_from_json_for_validation_test("""[
286      {
287        "file": "RobotoFlex-Regular.ttf",
288        "supportedAxes": "wght",
289        "axes": {
290          "wdth": 100
291        }
292      }
293    ]""")
294    self.assertEqual(1, len(fonts))
295
296    self.assertEqual("RobotoFlex-Regular.ttf", fonts[0].file)
297    self.assertEqual(1, len(fonts[0].axes))
298    self.assertEqual(100, fonts[0].axes["wdth"])
299    self.assertIsNone(fonts[0].index)
300    self.assertIsNone(fonts[0].weight)
301    self.assertIsNone(fonts[0].style)
302    self.assertIsNone(fonts[0].post_script_name)
303
304  def test_parse_font3(self):
305    fonts = parse_fonts_from_json_for_validation_test("""[
306      {
307        "file": "SourceSansPro-Regular.ttf",
308        "weight": 400,
309        "style": "normal"
310      }, {
311        "file": "SourceSansPro-Italic.ttf",
312        "weight": 400,
313        "style": "italic"
314      }, {
315        "file": "SourceSansPro-SemiBold.ttf",
316        "weight": 600,
317        "style": "normal"
318      }, {
319        "file": "SourceSansPro-SemiBoldItalic.ttf",
320        "weight": 600,
321        "style": "italic"
322      }, {
323        "file": "SourceSansPro-Bold.ttf",
324        "weight": 700,
325        "style": "normal"
326      }, {
327        "file": "SourceSansPro-BoldItalic.ttf",
328        "weight": 700,
329        "style": "italic"
330      }
331    ]""")
332
333    self.assertEqual(6, len(fonts))
334
335    self.assertEqual("SourceSansPro-Regular.ttf", fonts[0].file)
336    self.assertEqual(400, fonts[0].weight)
337    self.assertEqual("normal", fonts[0].style)
338
339    self.assertEqual("SourceSansPro-Italic.ttf", fonts[1].file)
340    self.assertEqual(400, fonts[1].weight)
341    self.assertEqual("italic", fonts[1].style)
342
343    self.assertEqual("SourceSansPro-SemiBold.ttf", fonts[2].file)
344    self.assertEqual(600, fonts[2].weight)
345    self.assertEqual("normal", fonts[2].style)
346
347    self.assertEqual("SourceSansPro-SemiBoldItalic.ttf", fonts[3].file)
348    self.assertEqual(600, fonts[3].weight)
349    self.assertEqual("italic", fonts[3].style)
350
351    self.assertEqual("SourceSansPro-Bold.ttf", fonts[4].file)
352    self.assertEqual(700, fonts[4].weight)
353    self.assertEqual("normal", fonts[4].style)
354
355    self.assertEqual("SourceSansPro-BoldItalic.ttf", fonts[5].file)
356    self.assertEqual(700, fonts[5].weight)
357    self.assertEqual("italic", fonts[5].style)
358
359  def test_parse_font4(self):
360    fonts = parse_fonts_from_json_for_validation_test("""[
361      {
362        "file": "NotoSerifCJK-Regular.ttc",
363        "postScriptName": "NotoSerifCJKjp-Regular",
364        "weight": "400",
365        "style": "normal",
366        "index": "2"
367      }
368    ]""")
369    self.assertEqual(1, len(fonts))
370
371    self.assertEqual("NotoSerifCJK-Regular.ttc", fonts[0].file)
372    self.assertEqual("NotoSerifCJKjp-Regular", fonts[0].post_script_name)
373    self.assertEqual(400, fonts[0].weight)
374    self.assertEqual("normal", fonts[0].style)
375    self.assertEqual(2, fonts[0].index)
376
377
378if __name__ == "__main__":
379  unittest.main(verbosity=2)
380