blob: df563a07c2ea9d1657d63f86fbbc46668c58400c [file] [log] [blame]
#!/usr/bin/env python
# Copyright 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 MockChange, MockOutputApi
class MockCannedChecks(object):
def CheckChangeLintsClean(self, input_api, output_api, source_filter,
lint_filters, verbose_level):
return []
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.canned_checks = MockCannedChecks()
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'
' oneof specifics_variant {\n'
' AutofillSpecifics autofill = 123;\n'
' AppSpecifics app = 456;\n'
' AppSettingSpecifics app_setting = 789;\n'
' ExtensionSettingSpecifics extension_setting = 910;\n'
' ManagedUserSharedSettingSpecifics managed_user_shared_setting'
' = 915;\n'
' //comment\n'
' }\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'
'// Some comment \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 testValidChangeDeprecatedEntry(self):
results = self._testChange('{DEPRECATED_SUPERVISED_USER_SHARED_SETTINGS,'
'"MANAGED_USER_SHARED_SETTING", "managed_user_shared_settings",'
'"Managed User Shared Settings",'
'sync_pb::EntitySpecifics::kManagedUserSharedSettingFieldNumber, 30},')
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()