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 sys 20import unittest 21 22from family_builder import parse_family_from_json 23from family_builder import parse_family_from_json_for_sanitization_test 24 25_VALID_FONT_JSON = """[{ "file": "a.ttf", "weight": 400, "style": "normal" }]""" 26 27 28class FamilyBuilderTest(unittest.TestCase): 29 30 def test_parse_family_invalid_id(self): 31 self.assertRaises( 32 AssertionError, 33 parse_family_from_json_for_sanitization_test, 34 """{ "id": [] }""", 35 ) 36 self.assertRaises( 37 AssertionError, 38 parse_family_from_json_for_sanitization_test, 39 """{ "id": 1 }""", 40 ) 41 self.assertRaises( 42 AssertionError, 43 parse_family_from_json_for_sanitization_test, 44 """{ "id": 0.5 }""", 45 ) 46 47 def test_parse_family_invalid_lang(self): 48 self.assertRaises( 49 AssertionError, 50 parse_family_from_json_for_sanitization_test, 51 """{ "lang": [] }""", 52 ) 53 self.assertRaises( 54 AssertionError, 55 parse_family_from_json_for_sanitization_test, 56 """{ "lang": 1 }""", 57 ) 58 self.assertRaises( 59 AssertionError, 60 parse_family_from_json_for_sanitization_test, 61 """{ "lang": 0.5 }""", 62 ) 63 64 def test_parse_family_invalid_name(self): 65 self.assertRaises( 66 AssertionError, 67 parse_family_from_json_for_sanitization_test, 68 """{ "name": [] }""", 69 ) 70 self.assertRaises( 71 AssertionError, 72 parse_family_from_json_for_sanitization_test, 73 """{ "name": 1 }""", 74 ) 75 self.assertRaises( 76 AssertionError, 77 parse_family_from_json_for_sanitization_test, 78 """{ "name": 0.5 }""", 79 ) 80 81 def test_parse_family_invalid_variant(self): 82 self.assertRaises( 83 AssertionError, 84 parse_family_from_json_for_sanitization_test, 85 """{ "variant": [] }""", 86 ) 87 self.assertRaises( 88 AssertionError, 89 parse_family_from_json_for_sanitization_test, 90 """{ "variant": 1 }""", 91 ) 92 self.assertRaises( 93 AssertionError, 94 parse_family_from_json_for_sanitization_test, 95 """{ "variant": 0.5 }""", 96 ) 97 self.assertRaises( 98 AssertionError, 99 parse_family_from_json_for_sanitization_test, 100 """{ "variant": "default" }""", 101 ) 102 103 def test_parse_family_invalid_fallback_for(self): 104 self.assertRaises( 105 AssertionError, 106 parse_family_from_json_for_sanitization_test, 107 """{ "fallbackFor": [] }""", 108 ) 109 self.assertRaises( 110 AssertionError, 111 parse_family_from_json_for_sanitization_test, 112 """{ "fallbackFor": 1 }""", 113 ) 114 self.assertRaises( 115 AssertionError, 116 parse_family_from_json_for_sanitization_test, 117 """{ "name": 0.5 }""", 118 ) 119 120 def test_parse_invalid_family(self): 121 # fallbackFor and target should be specified altogether 122 self.assertRaises( 123 AssertionError, 124 parse_family_from_json, 125 """{ "fallbackFor": "serif", "fonts": %s } """ % _VALID_FONT_JSON, 126 ) 127 self.assertRaises( 128 AssertionError, 129 parse_family_from_json, 130 """{ "target": "Roboto", "fonts": %s } """ % _VALID_FONT_JSON, 131 ) 132 133 # Invalid fonts 134 self.assertRaises(AssertionError, parse_family_from_json, """{} """) 135 self.assertRaises( 136 AssertionError, 137 parse_family_from_json, 138 """{ "fonts": [] } """, 139 ) 140 self.assertRaises( 141 AssertionError, 142 parse_family_from_json, 143 """{ "fonts": {} } """, 144 ) 145 146 def test_parse_family(self): 147 family = parse_family_from_json(""" 148 { 149 "lang": "und-Arab", 150 "variant": "compact", 151 "fonts": [{ 152 "file": "NotoNaskhArabicUI-Regular.ttf", 153 "postScriptName": "NotoNaskhArabicUI", 154 "weight": "400", 155 "style": "normal" 156 }, { 157 "file": "NotoNaskhArabicUI-Bold.ttf", 158 "weight": "700", 159 "style": "normal" 160 }] 161 }""") 162 163 self.assertEqual("und-Arab", family.lang) 164 self.assertEqual("compact", family.variant) 165 self.assertEqual(2, len(family.fonts)) 166 self.assertIsNone(family.id) 167 self.assertIsNone(family.name) 168 self.assertIsNone(family.fallback_for) 169 self.assertIsNone(family.target) 170 171 def test_parse_family2(self): 172 family = parse_family_from_json(""" 173 { 174 "id": "NotoSansCJK_zh-Hans", 175 "lang": "zh-Hans", 176 "fonts": [{ 177 "file": "NotoSansCJK-Regular.ttc", 178 "postScriptName": "NotoSansCJKJP-Regular", 179 "weight": "400", 180 "style": "normal", 181 "supportedAxes": "wght", 182 "axes": { 183 "wght": "400" 184 }, 185 "index": "2" 186 }] 187 }""") 188 189 self.assertEqual("NotoSansCJK_zh-Hans", family.id) 190 self.assertEqual("zh-Hans", family.lang) 191 self.assertEqual(1, len(family.fonts)) 192 self.assertIsNone(family.name) 193 self.assertIsNone(family.target) 194 195 def test_parse_family3(self): 196 family = parse_family_from_json(""" 197 { 198 "lang": "zh-Hans", 199 "fonts": [{ 200 "file": "NotoSerifCJK-Regular.ttc", 201 "postScriptName": "NotoSerifCJKjp-Regular", 202 "weight": "400", 203 "style": "normal", 204 "index": "2" 205 }], 206 "target": "NotoSansCJK_zh-Hans", 207 "fallbackFor": "serif" 208 } 209 """) 210 211 self.assertEqual("zh-Hans", family.lang) 212 self.assertEqual(1, len(family.fonts)) 213 self.assertEqual("serif", family.fallback_for) 214 self.assertEqual("NotoSansCJK_zh-Hans", family.target) 215 self.assertIsNone(family.name) 216 self.assertIsNone(family.variant) 217 218 def test_parse_family4(self): 219 family = parse_family_from_json(""" 220 { 221 "name": "sans-serif", 222 "fonts": [{ 223 "file": "Roboto-Regular.ttf", 224 "supportedAxes": "wght,ital", 225 "axes": { 226 "wdth": "100" 227 } 228 }] 229 } 230 """) 231 232 self.assertEqual("sans-serif", family.name) 233 self.assertEqual(1, len(family.fonts)) 234 self.assertIsNone(family.lang) 235 self.assertIsNone(family.fallback_for) 236 self.assertIsNone(family.target) 237 self.assertIsNone(family.variant) 238 239 240if __name__ == "__main__": 241 unittest.main(verbosity=2) 242