blob: feb8ffcebc278852920c3bdfd5e261ba9c908cea [file] [log] [blame]
Lei Zhang5db76de2017-11-11 05:30:431#!/usr/bin/env python
2# Copyright 2016 The Chromium Authors. All rights reserved.
pnolanddfef663b2016-04-08 19:49:543# Use of this source code is governed by a BSD-style license that can be
4# found in the LICENSE file.
5
6import os
7import re
8import sys
9import unittest
Lei Zhang5db76de2017-11-11 05:30:4310
pnolanddfef663b2016-04-08 19:49:5411import PRESUBMIT
12
pnoland4feacb1e2016-10-21 21:50:0313sys.path.append(
14 os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))))
Lei Zhang5db76de2017-11-11 05:30:4315from PRESUBMIT_test_mocks import MockChange, MockOutputApi
16
17class MockCannedChecks(object):
18 def CheckChangeLintsClean(self, input_api, output_api, source_filter,
19 lint_filters, verbose_level):
20 return []
21
pnolanddfef663b2016-04-08 19:49:5422
23class MockInputApi(object):
24 """ Mocked input api for unit testing of presubmit.
25 This lets us mock things like file system operations and changed files.
26 """
27 def __init__(self):
Lei Zhang5db76de2017-11-11 05:30:4328 self.canned_checks = MockCannedChecks()
pnolanddfef663b2016-04-08 19:49:5429 self.re = re
30 self.os_path = os.path
31 self.files = []
32 self.is_committing = False
33
34 def AffectedFiles(self):
35 return self.files
36
37 def AffectedSourceFiles(self):
38 return self.files
39
40 def ReadFile(self, f):
41 """ Returns the mock contents of f if they've been defined.
42 """
43 for api_file in self.files:
44 if api_file.LocalPath() == f:
45 return api_file.NewContents()
46
47
48class MockFile(object):
49 """Mock file object so that presubmit can act invoke file system operations.
50 """
51 def __init__(self, local_path, new_contents):
52 self._local_path = local_path
53 self._new_contents = new_contents
54 self._changed_contents = ([(i + 1, l) for i, l in enumerate(new_contents)])
55
56 def ChangedContents(self):
57 return self._changed_contents
58
59 def NewContents(self):
60 return self._new_contents
61
62 def LocalPath(self):
63 return self._local_path
64
65 def AbsoluteLocalPath(self):
66 return self._local_path
Lei Zhang5db76de2017-11-11 05:30:4367
68
pnolanddfef663b2016-04-08 19:49:5469# Format string used as the contents of a mock sync.proto in order to
70# test presubmit parsing of EntitySpecifics definition in that file.
71MOCK_PROTOFILE_CONTENTS = ('\n'
72 'message EntitySpecifics {\n'
Jan Krcala87a02de2018-07-24 16:57:3373 ' //comment\n'
pnolanddfef663b2016-04-08 19:49:5474 '\n'
Jan Krcala87a02de2018-07-24 16:57:3375 ' oneof specifics_variant {\n'
76 ' AutofillSpecifics autofill = 123;\n'
77 ' AppSpecifics app = 456;\n'
78 ' AppSettingSpecifics app_setting = 789;\n'
79 ' ExtensionSettingSpecifics extension_setting = 910;\n'
Jan Krcala87a02de2018-07-24 16:57:3380 ' //comment\n'
81 ' }\n'
82 '}\n'
83 )
pnolanddfef663b2016-04-08 19:49:5484
85
86# Format string used as the contents of a mock model_type.cc
87# in order to test presubmit parsing of the ModelTypeInfoMap in that file.
88MOCK_MODELTYPE_CONTENTS =('\n'
89 'const ModelTypeInfo kModelTypeInfoMap[] = {\n'
vitaliii30e9dbf42018-05-11 13:27:0490 '// Some comment \n'
pnolanddfef663b2016-04-08 19:49:5491 '{APP_SETTINGS, "APP_SETTING", "app_settings", "App settings",\n'
92 'sync_pb::EntitySpecifics::kAppSettingFieldNumber, 13},\n'
93 '%s\n'
94 '};\n')
95
96
97class ModelTypeInfoChangeTest(unittest.TestCase):
98 """Unit testing class that contains tests for sync/PRESUBMIT.py.
99 """
100 def test_ValidChangeMultiLine(self):
101 results = self._testChange('{APPS, "APP", "apps", "Apps",\n'
102 'sync_pb::EntitySpecifics::kAppFieldNumber, 12},')
103 self.assertEqual(0, len(results))
104
105 def testValidChangeToleratesPluralization(self):
106 results = self._testChange('{APPS, "APP", "apps", "App",\n'
107 'sync_pb::EntitySpecifics::kAppFieldNumber, 12},')
108 self.assertEqual(0, len(results))
109
110 def testValidChangeGrandfatheredEntry(self):
111 results = self._testChange('{PROXY_TABS, "", "", "Tabs", -1, 25},')
112 self.assertEqual(0, len(results))
113
Victor Hugo Vianna Silva8d782af2021-01-27 19:18:09114 # TODO(crbug.com/1170749): The only remaining deprecated type doesn't satisfy
115 # this test, revisit it.
116 def DISABLED_testValidChangeDeprecatedEntry(self):
117 results = self._testChange('{DEPRECATED_SUPERVISED_USER_ALLOWLISTS,\n'
118 '"MANAGED_USER_WHITELIST",\n'
119 '"managed_user_whitelists", "Managed User Whitelists",\n'
120 'sync_pb::EntitySpecifics::kManagedUserWhitelistFieldNumber, 33},')
Marc Treib39804b22020-02-04 17:12:20121 self.assertEqual(0, len(results))
122
pnolanddfef663b2016-04-08 19:49:54123 def testInvalidChangeMismatchedNotificationType(self):
124 results = self._testChange('{AUTOFILL, "AUTOFILL_WRONG", "autofill",\n'
125 '"Autofill",sync_pb::EntitySpecifics::kAutofillFieldNumber, 6},')
126 self.assertEqual(1, len(results))
127 self.assertTrue('notification type' in results[0].message)
128
129 def testInvalidChangeInconsistentModelType(self):
130 results = self._testChange('{AUTOFILL, "AUTOFILL", "autofill",\n'
131 '"Autofill Extra",sync_pb::EntitySpecifics::kAutofillFieldNumber, 6},')
132 self.assertEqual(1, len(results))
133 self.assertTrue('model type string' in results[0].message)
134
135 def testInvalidChangeNotTitleCased(self):
136 results = self._testChange('{AUTOFILL, "AUTOFILL", "autofill",\n'
137 '"autofill",sync_pb::EntitySpecifics::kAutofillFieldNumber, 6},')
138 self.assertEqual(1, len(results))
139 self.assertTrue('title' in results[0].message)
140
141 def testInvalidChangeInconsistentRootTag(self):
142 results = self._testChange('{AUTOFILL, "AUTOFILL", "autofill root",\n'
143 '"Autofill",sync_pb::EntitySpecifics::kAutofillFieldNumber, 6},')
144 self.assertEqual(1, len(results))
145 self.assertTrue('root tag' in results[0].message)
146
147 def testInvalidChangeDuplicatedValues(self):
148 results = self._testChange('{APP_SETTINGS, "APP_SETTING",\n'
149 '"app_settings", "App settings",\n'
150 'sync_pb::EntitySpecifics::kAppSettingFieldNumber, 13},\n')
151 self.assertEqual(6, len(results))
152 self.assertTrue('APP_SETTINGS' in results[0].message)
153
Toby Huanga7246afa2021-04-13 15:48:45154 def testBlocklistedRootTag(self):
pnoland4feacb1e2016-10-21 21:50:03155 results = self._testChange('{EXTENSION_SETTING, "EXTENSION_SETTING",\n'
156 '"_mts_schema_descriptor","Extension Setting",\n'
157 'sync_pb::EntitySpecifics::kExtensionSettingFieldNumber, 6},')
158 self.assertEqual(2, len(results))
159 self.assertTrue('_mts_schema_descriptor' in results[0].message)
Toby Huanga7246afa2021-04-13 15:48:45160 self.assertTrue("blocklist" in results[0].message)
pnoland4feacb1e2016-10-21 21:50:03161
pnolanddfef663b2016-04-08 19:49:54162 def _testChange(self, modeltype_literal):
163 mock_input_api = MockInputApi()
164 mock_input_api.files = [
165 MockFile(os.path.abspath('./protocol/sync.proto'),
166 MOCK_PROTOFILE_CONTENTS),
Mikel Astizcb6827e2019-04-02 12:33:46167 MockFile(os.path.abspath('./base/model_type.cc'),
pnolanddfef663b2016-04-08 19:49:54168 MOCK_MODELTYPE_CONTENTS % (modeltype_literal))
169 ]
170
171 return PRESUBMIT.CheckChangeOnCommit(mock_input_api, MockOutputApi())
Lei Zhang5db76de2017-11-11 05:30:43172
173
pnolanddfef663b2016-04-08 19:49:54174if __name__ == '__main__':
175 unittest.main()