OLD | NEW |
| (Empty) |
1 # Copyright (c) 2016 The Chromium Authors. All rights reserved. | |
2 # Use of this source code is governed by a BSD-style license that can be | |
3 # found in the LICENSE file. | |
4 | |
5 import os | |
6 import re | |
7 import sys | |
8 import unittest | |
9 import PRESUBMIT | |
10 | |
11 sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) | |
12 from PRESUBMIT_test_mocks import MockOutputApi, MockChange | |
13 | |
14 class MockInputApi(object): | |
15 """ Mocked input api for unit testing of presubmit. | |
16 This lets us mock things like file system operations and changed files. | |
17 """ | |
18 def __init__(self): | |
19 self.re = re | |
20 self.os_path = os.path | |
21 self.files = [] | |
22 self.is_committing = False | |
23 | |
24 def AffectedFiles(self): | |
25 return self.files | |
26 | |
27 def AffectedSourceFiles(self): | |
28 return self.files | |
29 | |
30 def ReadFile(self, f): | |
31 """ Returns the mock contents of f if they've been defined. | |
32 """ | |
33 for api_file in self.files: | |
34 if api_file.LocalPath() == f: | |
35 return api_file.NewContents() | |
36 | |
37 | |
38 class MockFile(object): | |
39 """Mock file object so that presubmit can act invoke file system operations. | |
40 """ | |
41 def __init__(self, local_path, new_contents): | |
42 self._local_path = local_path | |
43 self._new_contents = new_contents | |
44 self._changed_contents = ([(i + 1, l) for i, l in enumerate(new_contents)]) | |
45 | |
46 def ChangedContents(self): | |
47 return self._changed_contents | |
48 | |
49 def NewContents(self): | |
50 return self._new_contents | |
51 | |
52 def LocalPath(self): | |
53 return self._local_path | |
54 | |
55 def AbsoluteLocalPath(self): | |
56 return self._local_path | |
57 # Format string used as the contents of a mock sync.proto in order to | |
58 # test presubmit parsing of EntitySpecifics definition in that file. | |
59 MOCK_PROTOFILE_CONTENTS = ('\n' | |
60 'message EntitySpecifics {\n' | |
61 '//comment\n' | |
62 '\n' | |
63 'optional AutofillSpecifics autofill = 123;\n' | |
64 'optional AppSpecifics app = 456;\n' | |
65 'optional AppSettingSpecifics app_setting = 789;\n' | |
66 '//comment\n' | |
67 '}\n') | |
68 | |
69 | |
70 # Format string used as the contents of a mock model_type.cc | |
71 # in order to test presubmit parsing of the ModelTypeInfoMap in that file. | |
72 MOCK_MODELTYPE_CONTENTS =('\n' | |
73 'const ModelTypeInfo kModelTypeInfoMap[] = {\n' | |
74 '{APP_SETTINGS, "APP_SETTING", "app_settings", "App settings",\n' | |
75 'sync_pb::EntitySpecifics::kAppSettingFieldNumber, 13},\n' | |
76 '%s\n' | |
77 '};\n') | |
78 | |
79 | |
80 class ModelTypeInfoChangeTest(unittest.TestCase): | |
81 """Unit testing class that contains tests for sync/PRESUBMIT.py. | |
82 """ | |
83 def test_ValidChangeMultiLine(self): | |
84 results = self._testChange('{APPS, "APP", "apps", "Apps",\n' | |
85 'sync_pb::EntitySpecifics::kAppFieldNumber, 12},') | |
86 self.assertEqual(0, len(results)) | |
87 | |
88 def testValidChangeToleratesPluralization(self): | |
89 results = self._testChange('{APPS, "APP", "apps", "App",\n' | |
90 'sync_pb::EntitySpecifics::kAppFieldNumber, 12},') | |
91 self.assertEqual(0, len(results)) | |
92 | |
93 def testValidChangeGrandfatheredEntry(self): | |
94 results = self._testChange('{PROXY_TABS, "", "", "Tabs", -1, 25},') | |
95 self.assertEqual(0, len(results)) | |
96 | |
97 def testInvalidChangeMismatchedNotificationType(self): | |
98 results = self._testChange('{AUTOFILL, "AUTOFILL_WRONG", "autofill",\n' | |
99 '"Autofill",sync_pb::EntitySpecifics::kAutofillFieldNumber, 6},') | |
100 self.assertEqual(1, len(results)) | |
101 self.assertTrue('notification type' in results[0].message) | |
102 | |
103 def testInvalidChangeInconsistentModelType(self): | |
104 results = self._testChange('{AUTOFILL, "AUTOFILL", "autofill",\n' | |
105 '"Autofill Extra",sync_pb::EntitySpecifics::kAutofillFieldNumber, 6},') | |
106 self.assertEqual(1, len(results)) | |
107 self.assertTrue('model type string' in results[0].message) | |
108 | |
109 def testInvalidChangeNotTitleCased(self): | |
110 results = self._testChange('{AUTOFILL, "AUTOFILL", "autofill",\n' | |
111 '"autofill",sync_pb::EntitySpecifics::kAutofillFieldNumber, 6},') | |
112 self.assertEqual(1, len(results)) | |
113 self.assertTrue('title' in results[0].message) | |
114 | |
115 def testInvalidChangeInconsistentRootTag(self): | |
116 results = self._testChange('{AUTOFILL, "AUTOFILL", "autofill root",\n' | |
117 '"Autofill",sync_pb::EntitySpecifics::kAutofillFieldNumber, 6},') | |
118 self.assertEqual(1, len(results)) | |
119 self.assertTrue('root tag' in results[0].message) | |
120 | |
121 def testInvalidChangeDuplicatedValues(self): | |
122 results = self._testChange('{APP_SETTINGS, "APP_SETTING",\n' | |
123 '"app_settings", "App settings",\n' | |
124 'sync_pb::EntitySpecifics::kAppSettingFieldNumber, 13},\n') | |
125 self.assertEqual(6, len(results)) | |
126 self.assertTrue('APP_SETTINGS' in results[0].message) | |
127 | |
128 def _testChange(self, modeltype_literal): | |
129 mock_input_api = MockInputApi() | |
130 mock_input_api.files = [ | |
131 MockFile(os.path.abspath('./protocol/sync.proto'), | |
132 MOCK_PROTOFILE_CONTENTS), | |
133 MockFile(os.path.abspath('./syncable/model_type.cc'), | |
134 MOCK_MODELTYPE_CONTENTS % (modeltype_literal)) | |
135 ] | |
136 | |
137 return PRESUBMIT.CheckChangeOnCommit(mock_input_api, MockOutputApi()) | |
138 if __name__ == '__main__': | |
139 unittest.main() | |
OLD | NEW |