blob: 4a724386cd2c0393d30922b16aeb41c6803e9d99 [file] [log] [blame]
#!/usr/bin/env python
# Copyright 2017 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import os
import sys
import unittest
import checkxmlstyle
import helpers
sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(
os.path.dirname(os.path.abspath(__file__))))))
from PRESUBMIT_test_mocks import MockFile, MockInputApi, MockOutputApi
class IncludedFilesTest(unittest.TestCase):
def testFileIncluded(self):
lines = []
mock_input_api = MockInputApi()
mock_input_api.files = [
MockFile('chrome/java/res_test/test.xml', lines),
MockFile('ui/test/java/res/test.xml', lines),
MockFile('content/java/res_test/test.xml', lines),
MockFile('components/test/java/res_test/test.xml', lines)
]
self.assertEqual(4,
len(list(checkxmlstyle.IncludedFiles(mock_input_api))))
def testFileExcluded(self):
lines = []
mock_input_api = MockInputApi()
mock_input_api.files = [
MockFile('chrome/res_test/test.xml', lines),
MockFile('ui/test/test.xml', lines),
MockFile('content/java/res.xml', lines),
MockFile('components/java/test.xml', lines),
MockFile('test/java/res/test.xml', lines)
]
self.assertEqual(0,
len(list(checkxmlstyle.IncludedFiles(mock_input_api))))
class ColorFormatTest(unittest.TestCase):
def testColorFormatIgnoredFile(self):
lines = ['<color name="color1">#61000000</color>',
'<color name="color2">#FFFFFF</color>',
'<color name="color3">#CCC</color>']
mock_input_api = MockInputApi()
mock_input_api.files = [MockFile('chrome/java/res_test/test.java', lines)]
errors = checkxmlstyle._CheckColorFormat(mock_input_api, MockOutputApi())
self.assertEqual(0, len(errors))
def testColorFormatTooShort(self):
lines = ['<color name="color1">#61000000</color>',
'<color name="color2">#FFFFFF</color>',
'<color name="color3">#CCC</color>']
mock_input_api = MockInputApi()
mock_input_api.files = [MockFile('chrome/java/res_test/test.xml', lines)]
errors = checkxmlstyle._CheckColorFormat(mock_input_api, MockOutputApi())
self.assertEqual(1, len(errors))
self.assertEqual(1, len(errors[0].items))
self.assertEqual(' chrome/java/res_test/test.xml:3',
errors[0].items[0].splitlines()[0])
def testColorInvalidAlphaValue(self):
lines = ['<color name="color1">#61000000</color>',
'<color name="color2">#FEFFFFFF</color>',
'<color name="color3">#FFCCCCCC</color>']
mock_input_api = MockInputApi()
mock_input_api.files = [MockFile('chrome/java/res_test/test.xml', lines)]
errors = checkxmlstyle._CheckColorFormat(mock_input_api, MockOutputApi())
self.assertEqual(1, len(errors))
self.assertEqual(1, len(errors[0].items))
self.assertEqual(' chrome/java/res_test/test.xml:3',
errors[0].items[0].splitlines()[0])
def testColorFormatLowerCase(self):
lines = ['<color name="color1">#61000000</color>',
'<color name="color2">#EFFFFFFF</color>',
'<color name="color3">#CcCcCC</color>']
mock_input_api = MockInputApi()
mock_input_api.files = [MockFile('chrome/java/res_test/test.xml', lines)]
errors = checkxmlstyle._CheckColorFormat(mock_input_api, MockOutputApi())
self.assertEqual(1, len(errors))
self.assertEqual(1, len(errors[0].items))
self.assertEqual(' chrome/java/res_test/test.xml:3',
errors[0].items[0].splitlines()[0])
class ColorReferencesTest(unittest.TestCase):
def testVectorDrawbleIgnored(self):
lines = ['<vector',
'tools:targetApi="21"',
'android:fillColor="#CCCCCC">',
'</vector>']
mock_input_api = MockInputApi()
mock_input_api.files = [MockFile('chrome/java/res_test/test.xml', lines)]
result = checkxmlstyle._CheckColorReferences(
mock_input_api, MockOutputApi())
self.assertEqual(1, len(result))
self.assertEqual(result[0].type, 'warning')
def testInvalidReference(self):
lines = ['<TextView',
'android:textColor="#FFFFFF" />']
mock_input_api = MockInputApi()
mock_input_api.files = [MockFile('chrome/java/res_test/test.xml', lines)]
errors = checkxmlstyle._CheckColorReferences(
mock_input_api, MockOutputApi())
self.assertEqual(1, len(errors))
self.assertEqual(1, len(errors[0].items))
self.assertEqual(' chrome/java/res_test/test.xml:2',
errors[0].items[0].splitlines()[0])
def testValidReference(self):
lines = ['<TextView',
'android:textColor="@color/color1" />']
mock_input_api = MockInputApi()
mock_input_api.files = [MockFile('chrome/java/res_test/test.xml', lines)]
errors = checkxmlstyle._CheckColorReferences(
mock_input_api, MockOutputApi())
self.assertEqual(0, len(errors))
def testValidReferenceInColorResources(self):
lines = ['<color name="color1">#61000000</color>']
mock_input_api = MockInputApi()
mock_input_api.files = [
MockFile(helpers.COLOR_PALETTE_RELATIVE_PATH, lines)]
errors = checkxmlstyle._CheckColorReferences(
mock_input_api, MockOutputApi())
self.assertEqual(0, len(errors))
def testReferenceInSemanticColors(self):
mock_input_api = MockInputApi()
mock_input_api.files = [
MockFile(helpers.COLOR_PALETTE_PATH,
['<resources><color name="a">#f0f0f0</color></resources>']),
MockFile('ui/android/java/res/values/semantic_colors_non_adaptive.xml',
[
'<color name="b">@color/hello<color>',
'<color name="c">@color/a<color>'
]),
MockFile('ui/android/java/res/values/semantic_colors_adaptive.xml',
['<color name="c">@color/a<color>'])
]
errors = checkxmlstyle._CheckSemanticColorsReferences(
mock_input_api, MockOutputApi())
self.assertEqual(1, len(errors))
def testReferenceInColorPalette(self):
mock_input_api = MockInputApi()
mock_input_api.files = [
MockFile(helpers.COLOR_PALETTE_PATH,
['<resources><color name="foo">#f0f0f0</color></resources>']),
MockFile('ui/android/java/res/values/semantic_colors_adaptive.xml',
['<color name="b">@color/foo<color>']),
MockFile('ui/android/java/res/values/colors.xml', [
'<color name="c">@color/b</color>',
'<color name="d">@color/b</color>',
'<color name="e">@color/foo</color>'
])
]
warnings = checkxmlstyle._CheckColorPaletteReferences(
mock_input_api, MockOutputApi())
self.assertEqual(1, len(warnings))
class DuplicateColorsTest(unittest.TestCase):
def testFailure(self):
lines = ['<color name="color1">#61000000</color>',
'<color name="color2">#61000000</color>']
mock_input_api = MockInputApi()
mock_input_api.files = [
MockFile(helpers.COLOR_PALETTE_RELATIVE_PATH, lines)]
errors = checkxmlstyle._CheckDuplicateColors(
mock_input_api, MockOutputApi())
self.assertEqual(1, len(errors))
self.assertEqual(2, len(errors[0].items))
self.assertEqual(' %s:1' % helpers.COLOR_PALETTE_RELATIVE_PATH,
errors[0].items[0].splitlines()[0])
self.assertEqual(' %s:2' % helpers.COLOR_PALETTE_RELATIVE_PATH,
errors[0].items[1].splitlines()[0])
def testSucess(self):
lines = ['<color name="color1">#61000000</color>',
'<color name="color1">#FFFFFF</color>']
mock_input_api = MockInputApi()
mock_input_api.files = [MockFile('chrome/java/res_test/colors.xml', lines)]
errors = checkxmlstyle._CheckDuplicateColors(
mock_input_api, MockOutputApi())
self.assertEqual(0, len(errors))
class XmlNamespacePrefixesTest(unittest.TestCase):
def testFailure(self):
lines = ['xmlns:chrome="http://schemas.android.com/apk/res-auto"']
mock_input_api = MockInputApi()
mock_input_api.files = [MockFile('chrome/java/res_test/file.xml', lines)]
errors = checkxmlstyle._CheckXmlNamespacePrefixes(
mock_input_api, MockOutputApi())
self.assertEqual(1, len(errors))
self.assertEqual(1, len(errors[0].items))
self.assertEqual(' chrome/java/res_test/file.xml:1',
errors[0].items[0].splitlines()[0])
def testSucess(self):
lines = ['xmlns:app="http://schemas.android.com/apk/res-auto"']
mock_input_api = MockInputApi()
mock_input_api.files = [MockFile('chrome/java/res_test/file.xml', lines)]
errors = checkxmlstyle._CheckXmlNamespacePrefixes(
mock_input_api, MockOutputApi())
self.assertEqual(0, len(errors))
class TextAppearanceTest(unittest.TestCase):
def testFailure_Style(self):
lines = [
'<resource>',
'<style name="TestTextAppearance">',
'<item name="android:textColor">@color/default_text_color_link</item>',
'<item name="android:textSize">14sp</item>',
'<item name="android:textStyle">bold</item>',
'<item name="android:fontFamily">some-font</item>',
'<item name="android:textAllCaps">true</item>',
'</style>',
'</resource>']
mock_input_api = MockInputApi()
mock_input_api.files = [MockFile('chrome/java/res_test/test.xml', lines)]
errors = checkxmlstyle._CheckTextAppearance(mock_input_api, MockOutputApi())
self.assertEqual(1, len(errors))
self.assertEqual(5, len(errors[0].items))
self.assertEqual(
(' chrome/java/res_test/test.xml:2 contains attribute '
'android:textColor'),
errors[0].items[0].splitlines()[0])
self.assertEqual(
' chrome/java/res_test/test.xml:2 contains attribute android:textSize',
errors[0].items[1].splitlines()[0])
self.assertEqual(
(' chrome/java/res_test/test.xml:2 contains attribute '
'android:textStyle'),
errors[0].items[2].splitlines()[0])
self.assertEqual(
(' chrome/java/res_test/test.xml:2 contains attribute '
'android:fontFamily'),
errors[0].items[3].splitlines()[0])
self.assertEqual(
(' chrome/java/res_test/test.xml:2 contains attribute '
'android:textAllCaps'),
errors[0].items[4].splitlines()[0])
def testSuccess_Style(self):
lines = [
'<resource>',
'<style name="TextAppearance.Test">',
'<item name="android:textColor">@color/default_text_color_link</item>',
'<item name="android:textSize">14sp</item>',
'<item name="android:textStyle">bold</item>',
'<item name="android:fontFamily">some-font</item>',
'<item name="android:textAllCaps">true</item>',
'</style>',
'<style name="TestStyle">',
'<item name="android:background">some_background</item>',
'</style>',
'</resource>']
mock_input_api = MockInputApi()
mock_input_api.files = [MockFile('chrome/java/res_test/test.xml', lines)]
errors = checkxmlstyle._CheckTextAppearance(mock_input_api, MockOutputApi())
self.assertEqual(0, len(errors))
def testFailure_Widget(self):
lines_top_level = [
'<TextView',
'xmlns:android="http://schemas.android.com/apk/res/android"',
'android:layout_width="match_parent"',
'android:layout_height="@dimen/snippets_article_header_height"',
'android:textColor="@color/snippets_list_header_text_color"',
'android:textSize="14sp" />']
lines_subcomponent_widget = [
'<RelativeLayout',
'xmlns:android="http://schemas.android.com/apk/res/android"',
'android:layout_width="match_parent"',
'android:layout_height="wrap_content">',
'<View',
'android:textColor="@color/error_text_color"',
'android:textSize="@dimen/text_size_medium"',
'android:textAllCaps="true"',
'android:background="@drawable/infobar_shadow_top"',
'android:visibility="gone" />',
'</RelativeLayout>']
mock_input_api = MockInputApi()
mock_input_api.files = [
MockFile('chrome/java/res_test/test1.xml', lines_top_level),
MockFile('chrome/java/res_test/test2.xml', lines_subcomponent_widget)]
errors = checkxmlstyle._CheckTextAppearance(mock_input_api, MockOutputApi())
self.assertEqual(1, len(errors))
self.assertEqual(5, len(errors[0].items))
self.assertEqual(
(' chrome/java/res_test/test1.xml:5 contains attribute '
'android:textColor'),
errors[0].items[0].splitlines()[0])
self.assertEqual(
(' chrome/java/res_test/test1.xml:6 contains attribute '
'android:textSize'),
errors[0].items[1].splitlines()[0])
self.assertEqual(
(' chrome/java/res_test/test2.xml:6 contains attribute '
'android:textColor'),
errors[0].items[2].splitlines()[0])
self.assertEqual(
(' chrome/java/res_test/test2.xml:7 contains attribute '
'android:textSize'),
errors[0].items[3].splitlines()[0])
self.assertEqual(
(' chrome/java/res_test/test2.xml:8 contains attribute '
'android:textAllCaps'),
errors[0].items[4].splitlines()[0])
def testSuccess_Widget(self):
lines = [
'<RelativeLayout',
'xmlns:android="http://schemas.android.com/apk/res/android"',
'android:layout_width="match_parent"',
'android:layout_height="wrap_content">',
'<View',
'android:background="@drawable/infobar_shadow_top"',
'android:visibility="gone" />',
'</RelativeLayout>']
mock_input_api = MockInputApi()
mock_input_api.files = [MockFile('chrome/java/res_test/test.xml', lines)]
errors = checkxmlstyle._CheckTextAppearance(
mock_input_api, MockOutputApi())
self.assertEqual(0, len(errors))
class NewTextAppearanceTest(unittest.TestCase):
def testFailure(self):
lines = [
'<resource>',
'<style name="TextAppearance.Test">',
'<item name="android:textColor">@color/default_text_color_link</item>',
'<item name="android:textSize">14sp</item>',
'</style>',
'</resource>']
mock_input_api = MockInputApi()
mock_input_api.files = [MockFile('chrome/java/res_test/test.xml', lines)]
errors = checkxmlstyle._CheckNewTextAppearance(
mock_input_api, MockOutputApi())
self.assertEqual(1, len(errors))
self.assertEqual(1, len(errors[0].items))
self.assertEqual(
' chrome/java/res_test/test.xml:2',
errors[0].items[0].splitlines()[0])
def testSuccess(self):
lines = [
'<resource>',
'<style name="TextAppearanceTest">',
'<item name="android:textColor">@color/default_text_color_link</item>',
'<item name="android:textSize">14sp</item>',
'</style>',
'</resource>']
mock_input_api = MockInputApi()
mock_input_api.files = [MockFile('chrome/java/res_test/test.xml', lines)]
errors = checkxmlstyle._CheckNewTextAppearance(
mock_input_api, MockOutputApi())
self.assertEqual(0, len(errors))
class UnfavoredLayoutAttributesTest(unittest.TestCase):
def testLineSpacingAttributesUsage(self):
xmlChanges = [
'<TextView android:id="@+id/test"',
' android:lineSpacingExtra="42dp"',
' android:lineSpacingMultiplier="42dp"',
'/>',
'<TextViewWithLeading android:id="@+id/test2"',
' app:leading="42dp"',
'/>'
]
mock_input_api = MockInputApi()
mock_input_api.files = [
MockFile('ui/android/java/res/layout/new_textview.xml', xmlChanges)
]
result = checkxmlstyle._CheckLineSpacingAttribute(
mock_input_api, MockOutputApi())
self.assertEqual(1, len(result))
self.assertEqual(2, len(result[0].items))
self.assertEqual(' ui/android/java/res/layout/new_textview.xml:2',
result[0].items[0].splitlines()[0])
self.assertEqual(' ui/android/java/res/layout/new_textview.xml:3',
result[0].items[1].splitlines()[0])
class UnfavoredWidgetsTest(unittest.TestCase):
def testButtonCompatUsage(self):
xmlChanges = [
'<Button',
' android:text="@string/hello"',
' android:text="@color/modern_blue_600"',
'/>',
'',
'<android.support.v7.widget.AppCompatButton',
' android:text="@string/welcome"',
' android:color="@color/modern_purple_300"',
'/>',
'<org.chromium.ui.widget.ButtonCompat',
' android:id="@+id/action_button"',
'/>'
]
mock_input_api = MockInputApi()
mock_input_api.files = [
MockFile('ui/android/java/res/layout/dropdown_item.xml', xmlChanges)
]
result = checkxmlstyle._CheckButtonCompatWidgetUsage(
mock_input_api, MockOutputApi())
self.assertEqual(1, len(result))
self.assertEqual(2, len(result[0].items))
self.assertEqual(' ui/android/java/res/layout/dropdown_item.xml:1',
result[0].items[0].splitlines()[0])
self.assertEqual(' ui/android/java/res/layout/dropdown_item.xml:6',
result[0].items[1].splitlines()[0])
class StringResourcesTest(unittest.TestCase):
def testInfavoredQuotations(self):
xmlChanges = (u'''<grit><release><messages>
<message name="IDS_TEST_0">
<ph><ex>Hi</ex></ph>, it\u0027s a good idea
</message>
<message name="IDS_TEST_1">
<ph><ex>Yes</ex></ph>, it\u2019s a good idea
</message>
<message name="IDS_TEST_2">
Go to \u0022Settings\u0022 and
\u0022Menus\u0022
</message>
<message name="IDS_TEST_3">
Go to \u201CSettings\u201D
\u0022Menus\u0023
</message>
<message name="IDS_TEST_4">
Go to \u201CSettings\u201D
\u201CMenus\u201D
</message>
</messages></release></grit>'''.encode('utf-8')).splitlines()
mock_input_api = MockInputApi()
mock_input_api.files = [
MockFile('ui/android/string/chrome_android_string.grd', xmlChanges)
]
result = checkxmlstyle._CheckStringResourcePunctuations(
mock_input_api, MockOutputApi())
self.assertEqual(1, len(result))
self.assertEqual(4, len(result[0].items))
self.assertEqual(' ui/android/string/chrome_android_string.grd:3',
result[0].items[0].splitlines()[0])
self.assertEqual(' ui/android/string/chrome_android_string.grd:9',
result[0].items[1].splitlines()[0])
self.assertEqual(' ui/android/string/chrome_android_string.grd:10',
result[0].items[2].splitlines()[0])
self.assertEqual(' ui/android/string/chrome_android_string.grd:14',
result[0].items[3].splitlines()[0])
if __name__ == '__main__':
unittest.main()