tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

resource_utils_test.py (9800B)


      1 #!/usr/bin/env python3
      2 # coding: utf-8
      3 # Copyright 2018 The Chromium Authors
      4 # Use of this source code is governed by a BSD-style license that can be
      5 # found in the LICENSE file.
      6 
      7 import collections
      8 import os
      9 import sys
     10 import unittest
     11 
     12 sys.path.insert(
     13    0, os.path.abspath(os.path.join(os.path.dirname(__file__), os.pardir)))
     14 from util import build_utils
     15 
     16 # Required because the following import needs build/android/gyp in the
     17 # Python path to import util.build_utils.
     18 _BUILD_ANDROID_GYP_ROOT = os.path.abspath(
     19    os.path.join(os.path.dirname(__file__), os.pardir))
     20 sys.path.insert(1, _BUILD_ANDROID_GYP_ROOT)
     21 
     22 import resource_utils
     23 
     24 # pylint: disable=line-too-long
     25 
     26 _TEST_XML_INPUT_1 = '''<?xml version="1.0" encoding="utf-8"?>
     27 <resources xmlns:android="http://schemas.android.com/apk/res/android">
     28 <string name="copy_to_clipboard_failure_message">"Lõikelauale kopeerimine ebaõnnestus"</string>
     29 <string name="low_memory_error">"Eelmist toimingut ei saa vähese mälu tõttu lõpetada"</string>
     30 <string name="opening_file_error">"Valit. faili avamine ebaõnnestus"</string>
     31 <string name="structured_text">"This is <android:g id="STRUCTURED_TEXT">%s</android:g>"</string>
     32 </resources>
     33 '''
     34 
     35 _TEST_XML_OUTPUT_2 = '''<?xml version="1.0" encoding="utf-8"?>
     36 <resources xmlns:android="http://schemas.android.com/apk/res/android">
     37 <string name="low_memory_error">"Eelmist toimingut ei saa vähese mälu tõttu lõpetada"</string>
     38 <string name="structured_text">"This is <android:g id="STRUCTURED_TEXT">%s</android:g>"</string>
     39 </resources>
     40 '''
     41 
     42 # pylint: enable=line-too-long
     43 
     44 _TEST_XML_OUTPUT_EMPTY = '''<?xml version="1.0" encoding="utf-8"?>
     45 <resources>
     46 <!-- this file intentionally empty -->
     47 </resources>
     48 '''
     49 
     50 _TEST_RESOURCES_MAP_1 = {
     51    'low_memory_error': 'Eelmist toimingut ei saa vähese mälu tõttu lõpetada',
     52    'opening_file_error': 'Valit. faili avamine ebaõnnestus',
     53    'copy_to_clipboard_failure_message': 'Lõikelauale kopeerimine ebaõnnestus',
     54    'structured_text': 'This is <android:g id="STRUCTURED_TEXT">%s</android:g>',
     55 }
     56 
     57 _TEST_NAMESPACES_1 = {'android': 'http://schemas.android.com/apk/res/android'}
     58 
     59 _TEST_RESOURCES_ALLOWLIST_1 = ['low_memory_error', 'structured_text']
     60 
     61 # Extracted from one generated Chromium R.txt file, with string resource
     62 # names shuffled randomly.
     63 _TEST_R_TXT = r'''int anim abc_fade_in 0x7f050000
     64 int anim abc_fade_out 0x7f050001
     65 int anim abc_grow_fade_in_from_bottom 0x7f050002
     66 int array DefaultCookiesSettingEntries 0x7f120002
     67 int array DefaultCookiesSettingValues 0x7f120003
     68 int array DefaultGeolocationSettingEntries 0x7f120004
     69 int attr actionBarDivider 0x7f0100e7
     70 int attr actionBarStyle 0x7f0100e2
     71 int string AllowedDomainsForAppsDesc 0x7f0c0105
     72 int string AlternateErrorPagesEnabledDesc 0x7f0c0107
     73 int string AuthAndroidNegotiateAccountTypeDesc 0x7f0c0109
     74 int string AllowedDomainsForAppsTitle 0x7f0c0104
     75 int string AlternateErrorPagesEnabledTitle 0x7f0c0106
     76 int[] styleable SnackbarLayout { 0x0101011f, 0x7f010076, 0x7f0100ba }
     77 int styleable SnackbarLayout_android_maxWidth 0
     78 int styleable SnackbarLayout_elevation 2
     79 '''
     80 
     81 # Test allowlist R.txt file. Note that AlternateErrorPagesEnabledTitle is
     82 # listed as an 'anim' and should thus be skipped. Similarly the string
     83 # 'ThisStringDoesNotAppear' should not be in the final result.
     84 _TEST_ALLOWLIST_R_TXT = r'''int anim AlternateErrorPagesEnabledTitle 0x7f0eeeee
     85 int string AllowedDomainsForAppsDesc 0x7f0c0105
     86 int string AlternateErrorPagesEnabledDesc 0x7f0c0107
     87 int string ThisStringDoesNotAppear 0x7f0fffff
     88 '''
     89 
     90 _TEST_R_TEXT_RESOURCES_IDS = {
     91    0x7f0c0105: 'AllowedDomainsForAppsDesc',
     92    0x7f0c0107: 'AlternateErrorPagesEnabledDesc',
     93 }
     94 
     95 # Names of string resources in _TEST_R_TXT, should be sorted!
     96 _TEST_R_TXT_STRING_RESOURCE_NAMES = sorted([
     97    'AllowedDomainsForAppsDesc',
     98    'AllowedDomainsForAppsTitle',
     99    'AlternateErrorPagesEnabledDesc',
    100    'AlternateErrorPagesEnabledTitle',
    101    'AuthAndroidNegotiateAccountTypeDesc',
    102 ])
    103 
    104 
    105 def _CreateTestFile(tmp_dir, file_name, file_data):
    106  file_path = os.path.join(tmp_dir, file_name)
    107  with open(file_path, 'wt') as f:
    108    f.write(file_data)
    109  return file_path
    110 
    111 
    112 
    113 class ResourceUtilsTest(unittest.TestCase):
    114 
    115  def test_GetRTxtStringResourceNames(self):
    116    with build_utils.TempDir() as tmp_dir:
    117      tmp_file = _CreateTestFile(tmp_dir, "test_R.txt", _TEST_R_TXT)
    118      self.assertListEqual(
    119          resource_utils.GetRTxtStringResourceNames(tmp_file),
    120          _TEST_R_TXT_STRING_RESOURCE_NAMES)
    121 
    122  def test_GenerateStringResourcesAllowList(self):
    123    with build_utils.TempDir() as tmp_dir:
    124      tmp_module_rtxt_file = _CreateTestFile(tmp_dir, "test_R.txt", _TEST_R_TXT)
    125      tmp_allowlist_rtxt_file = _CreateTestFile(tmp_dir, "test_allowlist_R.txt",
    126                                                _TEST_ALLOWLIST_R_TXT)
    127      self.assertDictEqual(
    128          resource_utils.GenerateStringResourcesAllowList(
    129              tmp_module_rtxt_file, tmp_allowlist_rtxt_file),
    130          _TEST_R_TEXT_RESOURCES_IDS)
    131 
    132  def test_IsAndroidLocaleQualifier(self):
    133    good_locales = [
    134        'en',
    135        'en-rUS',
    136        'fil',
    137        'fil-rPH',
    138        'iw',
    139        'iw-rIL',
    140        'b+en',
    141        'b+en+US',
    142        'b+ja+Latn',
    143        'b+ja+JP+Latn',
    144        'b+cmn+Hant-TW',
    145    ]
    146    bad_locales = [
    147        'e', 'english', 'en-US', 'en_US', 'en-rus', 'b+e', 'b+english', 'b+ja+'
    148    ]
    149    for locale in good_locales:
    150      self.assertTrue(
    151          resource_utils.IsAndroidLocaleQualifier(locale),
    152          msg="'%s' should be a good locale!" % locale)
    153 
    154    for locale in bad_locales:
    155      self.assertFalse(
    156          resource_utils.IsAndroidLocaleQualifier(locale),
    157          msg="'%s' should be a bad locale!" % locale)
    158 
    159  def test_ToAndroidLocaleName(self):
    160    _TEST_CHROMIUM_TO_ANDROID_LOCALE_MAP = {
    161        'en': 'en',
    162        'en-US': 'en-rUS',
    163        'en-FOO': 'en-rFOO',
    164        'fil': 'tl',
    165        'tl': 'tl',
    166        'he': 'iw',
    167        'he-IL': 'iw-rIL',
    168        'id': 'in',
    169        'id-BAR': 'in-rBAR',
    170        'nb': 'nb',
    171        'yi': 'ji'
    172    }
    173    for chromium_locale, android_locale in \
    174        _TEST_CHROMIUM_TO_ANDROID_LOCALE_MAP.items():
    175      result = resource_utils.ToAndroidLocaleName(chromium_locale)
    176      self.assertEqual(result, android_locale)
    177 
    178  def test_ToChromiumLocaleName(self):
    179    _TEST_ANDROID_TO_CHROMIUM_LOCALE_MAP = {
    180        'foo': 'foo',
    181        'foo-rBAR': 'foo-BAR',
    182        'b+lll': 'lll',
    183        'b+ll+Extra': 'll',
    184        'b+ll+RR': 'll-RR',
    185        'b+lll+RR+Extra': 'lll-RR',
    186        'b+ll+RRR+Extra': 'll-RRR',
    187        'b+ll+Ssss': 'll-Ssss',
    188        'b+ll+Ssss+Extra': 'll-Ssss',
    189        'b+ll+Ssss+RR': 'll-Ssss-RR',
    190        'b+ll+Ssss+RRR': 'll-Ssss-RRR',
    191        'b+ll+Ssss+RRR+Extra': 'll-Ssss-RRR',
    192        'b+ll+Whatever': 'll',
    193        'en': 'en',
    194        'en-rUS': 'en-US',
    195        'en-US': None,
    196        'en-FOO': None,
    197        'en-rFOO': 'en-FOO',
    198        'es-rES': 'es-ES',
    199        'es-rUS': 'es-419',
    200        'tl': 'fil',
    201        'fil': 'fil',
    202        'iw': 'he',
    203        'iw-rIL': 'he-IL',
    204        'b+iw+IL': 'he-IL',
    205        'in': 'id',
    206        'in-rBAR': 'id-BAR',
    207        'id-rBAR': 'id-BAR',
    208        'nb': 'nb',
    209        'no': 'nb',  # http://crbug.com/920960
    210    }
    211    for android_locale, chromium_locale in \
    212        _TEST_ANDROID_TO_CHROMIUM_LOCALE_MAP.items():
    213      result = resource_utils.ToChromiumLocaleName(android_locale)
    214      self.assertEqual(result, chromium_locale)
    215 
    216  def test_FindLocaleInStringResourceFilePath(self):
    217    self.assertEqual(
    218        None,
    219        resource_utils.FindLocaleInStringResourceFilePath(
    220            'res/values/whatever.xml'))
    221    self.assertEqual(
    222        'foo',
    223        resource_utils.FindLocaleInStringResourceFilePath(
    224            'res/values-foo/whatever.xml'))
    225    self.assertEqual(
    226        'foo-rBAR',
    227        resource_utils.FindLocaleInStringResourceFilePath(
    228            'res/values-foo-rBAR/whatever.xml'))
    229    self.assertEqual(
    230        None,
    231        resource_utils.FindLocaleInStringResourceFilePath(
    232            'res/values-foo/ignore-subdirs/whatever.xml'))
    233 
    234  def test_ParseAndroidResourceStringsFromXml(self):
    235    ret, namespaces = resource_utils.ParseAndroidResourceStringsFromXml(
    236        _TEST_XML_INPUT_1)
    237    self.assertDictEqual(ret, _TEST_RESOURCES_MAP_1)
    238    self.assertDictEqual(namespaces, _TEST_NAMESPACES_1)
    239 
    240  def test_GenerateAndroidResourceStringsXml(self):
    241    # Fist, an empty strings map, with no namespaces
    242    result = resource_utils.GenerateAndroidResourceStringsXml({})
    243    self.assertEqual(result.decode('utf8'), _TEST_XML_OUTPUT_EMPTY)
    244 
    245    result = resource_utils.GenerateAndroidResourceStringsXml(
    246        _TEST_RESOURCES_MAP_1, _TEST_NAMESPACES_1)
    247    self.assertEqual(result.decode('utf8'), _TEST_XML_INPUT_1)
    248 
    249  @staticmethod
    250  def _CreateTestResourceFile(output_dir, locale, string_map, namespaces):
    251    values_dir = os.path.join(output_dir, 'values-' + locale)
    252    build_utils.MakeDirectory(values_dir)
    253    file_path = os.path.join(values_dir, 'strings.xml')
    254    with open(file_path, 'wb') as f:
    255      file_data = resource_utils.GenerateAndroidResourceStringsXml(
    256          string_map, namespaces)
    257      f.write(file_data)
    258    return file_path
    259 
    260  def _CheckTestResourceFile(self, file_path, expected_data):
    261    with open(file_path) as f:
    262      file_data = f.read()
    263    self.assertEqual(file_data, expected_data)
    264 
    265  def test_FilterAndroidResourceStringsXml(self):
    266    with build_utils.TempDir() as tmp_path:
    267      test_file = self._CreateTestResourceFile(
    268          tmp_path, 'foo', _TEST_RESOURCES_MAP_1, _TEST_NAMESPACES_1)
    269      resource_utils.FilterAndroidResourceStringsXml(
    270          test_file, lambda x: x in _TEST_RESOURCES_ALLOWLIST_1)
    271      self._CheckTestResourceFile(test_file, _TEST_XML_OUTPUT_2)
    272 
    273 
    274 if __name__ == '__main__':
    275  unittest.main()