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