def testUserMetricsActionNotAddedToActions(self): input_api = MockInputApi() file_with_user_action = 'file_with_user_action.cc' contents_with_user_action = [ 'base::UserMetricsAction("NotInActionsXml")' ] input_api.files = [MockFile(file_with_user_action, contents_with_user_action)] output = PRESUBMIT._CheckUserActionUpdate(input_api, MockOutputApi()) self.assertEqual( ('File %s line %d: %s is missing in ' 'tools/metrics/actions/actions.xml. Please run ' 'tools/metrics/actions/extract_actions.py to update.' % (file_with_user_action, 1, 'NotInActionsXml')), output[0].message)
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 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 testFailure(self): lines = [ '<color name="color1">#61000000</color>', '<color name="color2">#61000000</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(1, len(errors)) self.assertEqual(2, len(errors[0].items)) self.assertEqual(' chrome/java/res_test/colors.xml:1', errors[0].items[0].splitlines()[0]) self.assertEqual(' chrome/java/res_test/colors.xml:2', errors[0].items[1].splitlines()[0])
def testCheckCrbugLinksHaveHttps(self): input_api = MockInputApi() input_api.files = [ MockFile('somewhere/file.cc', [ '// TODO(developer): crbug.com should be linkified', '// TODO(developer): (crbug.com) should be linkified', '// TODO(developer): crbug/123 should be well formed', '// TODO(developer): http://crbug.com it\'s OK', '// TODO(developer): https://crbug.com is just great', '// TODO(crbug.com/123456): this pattern it\'s also OK' ]), ] warnings = PRESUBMIT._CheckCrbugLinksHaveHttps(input_api, MockOutputApi()) self.assertEqual(1, len(warnings)) self.assertEqual(3, warnings[0].message.count('\n'))
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 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('ui/java/res/test.java', 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))))
def testIfElifElseEndif(self): mock_input_api = MockInputApi() contents = ['#include "e.h"', '#define foo', '#include "f.h"', '#undef foo', '#include "e.h"', '#if foo', '#include "d.h"', '#elif bar', '#include "c.h"', '#else', '#include "b.h"', '#endif', '#include "a.h"'] mock_file = MockFile('', contents) warnings = PRESUBMIT._CheckIncludeOrderInFile( mock_input_api, mock_file, range(1, len(contents) + 1)) self.assertEqual(0, len(warnings))
def _runChecks(self, file_contents): tmp_args = {'suffix': '.js', 'dir': _HERE_PATH, 'delete': False} with tempfile.NamedTemporaryFile(**tmp_args) as f: self._tmp_file = f.name f.write(file_contents) input_api = MockInputApi() input_api.files = [MockFile(os.path.abspath(self._tmp_file), '')] input_api.presubmit_local_path = _HERE_PATH checker = js_checker.JSChecker(input_api, MockOutputApi()) try: return checker.RunEsLintChecks(input_api.AffectedFiles(), format='json') except RuntimeError as err: # Extract ESLint's JSON error output from the error message. json_error = err.message[err.message.index('['):] return json.loads(json_error)[0].get('messages')
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])
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> <part file="site_settings.grdp" /> </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._CheckStringResourceQuotesPunctuations( 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])
def testSuccess(self): input_api = MockInputApi() filename = 'valid_idl_basics.idl' contents = ['// Tests a valid IDL file.', 'namespace idl_basics {', ' enum EnumType {', ' name1,', ' name2', ' };', '', ' dictionary MyType1 {', ' DOMString a;', ' };', '', ' callback Callback1 = void();', ' callback Callback2 = void(long x);', ' callback Callback3 = void(MyType1 arg);', ' callback Callback4 = void(EnumType type);', '', ' interface Functions {', ' static void function1();', ' static void function2(long x);', ' static void function3(MyType1 arg);', ' static void function4(Callback1 cb);', ' static void function5(Callback2 cb);', ' static void function6(Callback3 cb);', ' static void function7(Callback4 cb);', ' };', '', ' interface Events {', ' static void onFoo1();', ' static void onFoo2(long x);', ' static void onFoo2(MyType1 arg);', ' static void onFoo3(EnumType type);', ' };', '};' ] input_api.files = [MockFile(filename, contents)] self.assertEqual(None, PRESUBMIT._GetIDLParseError(input_api, filename))
def testFailure(self): input_api = MockInputApi() test_data = [ ('invalid_json_1.json', ['{ x }'], 'Expecting property name:'), ('invalid_json_2.json', ['// Hello world!', '{ "hello": "world }'], 'Unterminated string starting at:'), ('invalid_json_3.json', ['{ "a": "b", "c": "d", }'], 'Expecting property name:'), ('invalid_json_4.json', ['{ "a": "b" "c": "d" }'], 'Expecting , delimiter:'), ] input_api.files = [ MockFile(filename, contents) for (filename, contents, _) in test_data ] for (filename, _, expected_error) in test_data: actual_error = PRESUBMIT._GetJSONParseError(input_api, filename) self.assertTrue( expected_error in str(actual_error), "'%s' not found in '%s'" % (expected_error, actual_error))
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])
def testFalsePositives(self): """Examples of when AlertDialog.Builder should not be flagged.""" mock_input = MockInputApi() mock_input.files = [ MockFile( 'chrome/android/java/src/org/chromium/chrome/browser/payments/' 'AndroidPaymentApp.java', ['new AlertDialog.Builder()']), MockFile('path/One.java', ['AlertDialog.Builder']), MockFile('path/Two.java', ['// do not: new AlertDialog.Builder()']), MockFile('path/Three.java', [ '/** ChromeAlertDialogBuilder', ' * replaces: new AlertDialog.Builder()']), MockFile('path/PRESUBMIT.py', ['new AlertDialog.Builder()']), MockFile('path/Four.java', ['new AlertDialog.Builder()'], action='D'), ] errors = PRESUBMIT._CheckAlertDialogBuilder( mock_input, MockOutputApi()) self.assertEqual(0, len(errors))
def testFalsePositives(self): """Examples of when Notification.Builder should not be flagged.""" mock_input = MockInputApi() mock_input.files = [ MockFile( 'chrome/android/java/src/org/chromium/chrome/browser/notifications/' 'NotificationBuilder.java', ['new Notification.Builder()']), MockFile( 'chrome/android/java/src/org/chromium/chrome/browser/notifications/' 'NotificationCompatBuilder.java', ['new NotificationCompat.Builder()']), MockFile('path/One.java', ['Notification.Builder']), MockFile('path/Two.java', ['// do not: new Notification.Builder()']), MockFile('path/Three.java', [ '/** ChromeNotificationBuilder', ' * replaces: new Notification.Builder()']), MockFile('path/PRESUBMIT.py', ['new Notification.Builder()']), MockFile('path/Four.java', ['new NotificationCompat.Builder()'], action='D'), ] errors = PRESUBMIT._CheckNotificationConstructors( mock_input, MockOutputApi()) self.assertEqual(0, len(errors))
def testBannedCppFunctions(self): input_api = MockInputApi() input_api.files = [ MockFile('some/cpp/problematic/file.cc', ['using namespace std;']), MockFile('third_party/some/cpp/problematic/file.cc', ['using namespace std;']), MockFile('some/cpp/ok/file.cc', ['using std::string;']), MockFile('some/cpp/nocheck/file.cc', ['using namespace std; // nocheck']), MockFile('some/cpp/comment/file.cc', [' // A comment about `using namespace std;`']), MockFile('some/cpp/v8/get-current.cc', ['v8::Isolate::GetCurrent()']), MockFile('some/cpp/v8/try-get-current.cc', ['v8::Isolate::TryGetCurrent()']), ] results = PRESUBMIT._CheckNoBannedFunctions(input_api, MockOutputApi()) # There are no warnings to test, so add an empty warning to keep the test # extendable for the future. This block can be removed once warnings are # added. self.assertEqual(1, len(results)) results.insert(0, MockOutputApi().PresubmitPromptWarning('')) # warnings are results[0], errors are results[1] self.assertEqual(2, len(results)) self.assertTrue('some/cpp/problematic/file.cc' in results[1].message) self.assertFalse( 'third_party/some/cpp/problematic/file.cc' in results[1].message) self.assertFalse('some/cpp/ok/file.cc' in results[1].message) self.assertFalse('some/cpp/nocheck/file.cc' in results[0].message) self.assertFalse('some/cpp/nocheck/file.cc' in results[1].message) self.assertFalse('some/cpp/comment/file.cc' in results[0].message) self.assertFalse('some/cpp/comment/file.cc' in results[1].message) self.assertTrue('some/cpp/v8/get-current.cc' in results[1].message) self.assertTrue('some/cpp/v8/try-get-current.cc' in results[1].message)
def testValidIfDefinedMacroNames(self): lines = ['#if defined(FOO)', '#ifdef BAR',] errors = PRESUBMIT._CheckForInvalidIfDefinedMacrosInFile( MockInputApi(), MockFile('some/path/source.cc', lines)) self.assertEqual(0, len(errors))
def testValidOSMacroNames(self): lines = ['#if defined(%s)' % m for m in PRESUBMIT._VALID_OS_MACROS] errors = PRESUBMIT._CheckForInvalidOSMacrosInFile( MockInputApi(), MockFile('some/path/foo_platform.cc', lines)) self.assertEqual(0, len(errors))
def testChromeDoesNotUseOSIOS(self): lines = ['#if defined(OS_IOS)', '#error OS_IOS not allowed', '#endif'] errors = PRESUBMIT._CheckNoOSIOSMacrosInChromeFile( MockInputApi(), MockFile('chrome/path/foo_platform.cc', lines)) self.assertEqual(1, len(errors)) self.assertEqual(' chrome/path/foo_platform.cc:1', errors[0])
def _create_file(self, contents, filename): self.input_api.files.append(MockFile(filename, contents.splitlines()))
def _runChecks(self, files): input_api = MockInputApi() input_api.files = [MockFile(f, '') for f in files] output_api = MockOutputApi() checker = ExternsChecker(input_api, output_api, self.API_PAIRS) return checker.RunChecks()
def testFailure(self): input_api = MockInputApi() test_data = [ ('invalid_idl_1.idl', ['//', 'namespace test {', ' dictionary {', ' DOMString s;', ' };', '};'], 'Unexpected "{" after keyword "dictionary".\n'), # TODO(yoz): Disabled because it causes the IDL parser to hang. # See crbug.com/363830. # ('invalid_idl_2.idl', # (['namespace test {', # ' dictionary MissingSemicolon {', # ' DOMString a', # ' DOMString b;', # ' };', # '};'], # 'Unexpected symbol DOMString after symbol a.'), ('invalid_idl_3.idl', ['//', 'namespace test {', ' enum MissingComma {', ' name1', ' name2', ' };', '};'], 'Unexpected symbol name2 after symbol name1.'), ('invalid_idl_4.idl', ['//', 'namespace test {', ' enum TrailingComma {', ' name1,', ' name2,', ' };', '};'], 'Trailing comma in block.'), ('invalid_idl_5.idl', ['//', 'namespace test {', ' callback Callback1 = void(;', '};'], 'Unexpected ";" after "(".'), ('invalid_idl_6.idl', ['//', 'namespace test {', ' callback Callback1 = void(long );', '};'], 'Unexpected ")" after symbol long.'), ('invalid_idl_7.idl', ['//', 'namespace test {', ' interace Events {', ' static void onFoo1();', ' };', '};'], 'Unexpected symbol Events after symbol interace.'), ('invalid_idl_8.idl', ['//', 'namespace test {', ' interface NotEvent {', ' static void onFoo1();', ' };', '};'], 'Did not process Interface Interface(NotEvent)'), ('invalid_idl_9.idl', ['//', 'namespace test {', ' interface {', ' static void function1();', ' };', '};'], 'Interface missing name.'), ] input_api.files = [MockFile(filename, contents) for (filename, contents, _) in test_data] for (filename, _, expected_error) in test_data: actual_error = PRESUBMIT._GetIDLParseError(input_api, filename) self.assertTrue(expected_error in str(actual_error), "'%s' not found in '%s'" % (expected_error, actual_error))
def mockFileWithLines(self, file_path, lines): mock_file = MockFile(file_path, lines) self.mock_input_api.files.append(mock_file)