| #!/usr/bin/env python | |
| # Copyright 2014 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 unittest | |
| import PRESUBMIT | |
| class MockInputApi(object): | |
| 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, fn): | |
| # we'll just pretend everything is a source file for the sake of simplicity | |
| return self.files | |
| def ReadFile(self, f): | |
| return f.NewContents() | |
| class MockOutputApi(object): | |
| class PresubmitResult(object): | |
| def __init__(self, message, items=None, long_text=''): | |
| self.message = message | |
| self.items = items | |
| self.long_text = long_text | |
| class PresubmitError(PresubmitResult): | |
| def __init__(self, message, items, long_text=''): | |
| MockOutputApi.PresubmitResult.__init__(self, message, items, long_text) | |
| self.type = 'error' | |
| class PresubmitPromptWarning(PresubmitResult): | |
| def __init__(self, message, items, long_text=''): | |
| MockOutputApi.PresubmitResult.__init__(self, message, items, long_text) | |
| self.type = 'warning' | |
| class PresubmitNotifyResult(PresubmitResult): | |
| def __init__(self, message, items, long_text=''): | |
| MockOutputApi.PresubmitResult.__init__(self, message, items, long_text) | |
| self.type = 'notify' | |
| class PresubmitPromptOrNotify(PresubmitResult): | |
| def __init__(self, message, items, long_text=''): | |
| MockOutputApi.PresubmitResult.__init__(self, message, items, long_text) | |
| self.type = 'promptOrNotify' | |
| class MockFile(object): | |
| 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 | |
| class MockChange(object): | |
| def __init__(self, changed_files): | |
| self._changed_files = changed_files | |
| def LocalPaths(self): | |
| return self._changed_files | |
| class HistogramOffByOneTest(unittest.TestCase): | |
| # Take an input and make sure the problems found equals the expectation. | |
| def simpleCheck(self, contents, expected_errors): | |
| input_api = MockInputApi() | |
| input_api.files.append(MockFile('test.cc', contents)) | |
| results = PRESUBMIT._CheckForHistogramOffByOne(input_api, MockOutputApi()) | |
| if expected_errors: | |
| self.assertEqual(1, len(results)) | |
| self.assertEqual(expected_errors, len(results[0].items)) | |
| else: | |
| self.assertEqual(0, len(results)) | |
| def testValid(self): | |
| self.simpleCheck('UMA_HISTOGRAM_ENUMERATION("test", kFoo, kFooMax + 1);', 0) | |
| def testValidComments(self): | |
| self.simpleCheck('UMA_HISTOGRAM_ENUMERATION("test", /*...*/ kFoo, /*...*/' | |
| 'kFooMax + 1);', 0) | |
| def testValidMultiLine(self): | |
| self.simpleCheck('UMA_HISTOGRAM_ENUMERATION("test",\n' | |
| ' kFoo,\n' | |
| ' kFooMax + 1);', 0) | |
| def testValidMultiLineComments(self): | |
| self.simpleCheck('UMA_HISTOGRAM_ENUMERATION("test", // This is the name\n' | |
| ' kFoo, /* The value */\n' | |
| ' kFooMax + 1 /* The max */ );', | |
| 0) | |
| def testNoPlusOne(self): | |
| self.simpleCheck('UMA_HISTOGRAM_ENUMERATION("test", kFoo, kFooMax);', 1) | |
| def testInvalidWithIgnore(self): | |
| self.simpleCheck('UMA_HISTOGRAM_ENUMERATION("test", kFoo, kFooMax); ' | |
| '// PRESUBMIT_IGNORE_UMA_MAX', 0) | |
| def testNoMax(self): | |
| self.simpleCheck('UMA_HISTOGRAM_ENUMERATION("test", kFoo, kFoo + 1);', 1) | |
| def testNoMaxNoPlusOne(self): | |
| self.simpleCheck('UMA_HISTOGRAM_ENUMERATION("test", kFoo, kFoo);', 1) | |
| def testMultipleErrors(self): | |
| self.simpleCheck('UMA_HISTOGRAM_ENUMERATION("test", kFoo, kFoo);\n' | |
| 'printf("hello, world!");\n' | |
| 'UMA_HISTOGRAM_ENUMERATION("test", kBar, kBarMax);', 2) | |
| def testValidAndInvalid(self): | |
| self.simpleCheck('UMA_HISTOGRAM_ENUMERATION("test", kFoo, kFoo);\n' | |
| 'UMA_HISTOGRAM_ENUMERATION("test", kFoo, kFooMax + 1);' | |
| 'UMA_HISTOGRAM_ENUMERATION("test", kBar, kBarMax);', 2) | |
| def testInvalidMultiLine(self): | |
| self.simpleCheck('UMA_HISTOGRAM_ENUMERATION("test",\n' | |
| ' kFoo,\n' | |
| ' kFooMax + 2);', 1) | |
| def testInvalidComments(self): | |
| self.simpleCheck('UMA_HISTOGRAM_ENUMERATION("test", /*...*/, val, /*...*/,' | |
| 'Max);\n', 1) | |
| def testInvalidMultiLineComments(self): | |
| self.simpleCheck('UMA_HISTOGRAM_ENUMERATION("test", // This is the name\n' | |
| ' kFoo, /* The value */\n' | |
| ' kFooMax + 2 /* The max */ );', | |
| 1) | |
| if __name__ == '__main__': | |
| unittest.main() |