Index: PRESUBMIT_test.py |
diff --git a/PRESUBMIT_test.py b/PRESUBMIT_test.py |
index 3bebc678c616978a8494da5cee552004cc2b90a7..5a682a13390b1a57e89ad15c417c512fd3d29b1b 100755 |
--- a/PRESUBMIT_test.py |
+++ b/PRESUBMIT_test.py |
@@ -3,23 +3,43 @@ |
# Use of this source code is governed by a BSD-style license that can be |
# found in the LICENSE file. |
+import glob |
+import json |
import os |
import re |
+import subprocess |
+import sys |
import unittest |
import PRESUBMIT |
+_TEST_DATA_DIR = 'base/test/data/presubmit' |
+ |
+ |
class MockInputApi(object): |
def __init__(self): |
+ self.json = json |
self.re = re |
self.os_path = os.path |
+ self.python_executable = sys.executable |
+ self.subprocess = subprocess |
self.files = [] |
self.is_committing = False |
def AffectedFiles(self): |
return self.files |
+ def PresubmitLocalPath(self): |
+ return os.path.dirname(__file__) |
+ |
+ def ReadFile(self, filename, mode='rU'): |
+ for file_ in self.files: |
+ if file_.LocalPath() == filename: |
+ return '\n'.join(file_.NewContents()) |
+ # Otherwise, file is not in our mock API. |
+ raise IOError, "No such file or directory: '%s'" % filename |
+ |
class MockOutputApi(object): |
class PresubmitResult(object): |
@@ -431,5 +451,201 @@ class CheckAddedDepsHaveTetsApprovalsTest(unittest.TestCase): |
self.assertEqual(expected, files_to_check); |
+class JSONParsingTest(unittest.TestCase): |
+ def testSuccess(self): |
+ input_api = MockInputApi() |
+ filename = 'valid_json.json' |
+ contents = ['// This is a comment.', |
+ '{', |
+ ' "key1": ["value1", "value2"],', |
+ ' "key2": 3 // This is an inline comment.', |
+ '}' |
+ ] |
+ input_api.files = [MockFile(filename, contents)] |
+ self.assertEqual(None, |
+ PRESUBMIT._GetJSONParseError(input_api, filename)) |
+ |
+ def testFailure(self): |
+ input_api = MockInputApi() |
+ test_data = [ |
+ ('invalid_json_1.json', |
+ ['{ x }'], |
+ 'Expecting property name: line 1 column 2 (char 2)'), |
+ ('invalid_json_2.json', |
+ ['// Hello world!', |
+ '{ "hello": "world }'], |
+ 'Unterminated string starting at: line 2 column 12 (char 12)'), |
+ ('invalid_json_3.json', |
+ ['{ "a": "b", "c": "d", }'], |
+ 'Expecting property name: line 1 column 22 (char 22)'), |
+ ('invalid_json_4.json', |
+ ['{ "a": "b" "c": "d" }'], |
+ 'Expecting , delimiter: line 1 column 11 (char 11)'), |
+ ] |
+ |
+ 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.assertEqual(expected_error, str(actual_error)) |
+ |
+ def testNoEatComments(self): |
+ input_api = MockInputApi() |
+ file_with_comments = 'file_with_comments.json' |
+ contents_with_comments = ['// This is a comment.', |
+ '{', |
+ ' "key1": ["value1", "value2"],', |
+ ' "key2": 3 // This is an inline comment.', |
+ '}' |
+ ] |
+ file_without_comments = 'file_without_comments.json' |
+ contents_without_comments = ['{', |
+ ' "key1": ["value1", "value2"],', |
+ ' "key2": 3', |
+ '}' |
+ ] |
+ input_api.files = [MockFile(file_with_comments, contents_with_comments), |
+ MockFile(file_without_comments, |
+ contents_without_comments)] |
+ |
+ self.assertEqual('No JSON object could be decoded', |
+ str(PRESUBMIT._GetJSONParseError(input_api, |
+ file_with_comments, |
+ eat_comments=False))) |
+ self.assertEqual(None, |
+ PRESUBMIT._GetJSONParseError(input_api, |
+ file_without_comments, |
+ eat_comments=False)) |
+ |
+ |
+class IDLParsingTest(unittest.TestCase): |
+ 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_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)) |
+ |
+ |
if __name__ == '__main__': |
unittest.main() |