Index: tools/strict_enum_value_checker/strict_enum_value_checker_test.py |
diff --git a/tools/strict_enum_value_checker/strict_enum_value_checker_test.py b/tools/strict_enum_value_checker/strict_enum_value_checker_test.py |
new file mode 100755 |
index 0000000000000000000000000000000000000000..4f95efe0cfd66439dfad50775be5c9225ff4afdf |
--- /dev/null |
+++ b/tools/strict_enum_value_checker/strict_enum_value_checker_test.py |
@@ -0,0 +1,235 @@ |
+#!/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 difflib |
+import os |
+import re |
+import unittest |
+ |
+from strict_enum_value_checker import StrictEnumValueChecker |
+ |
+class MockLogging(object): |
+ def __init__(self): |
+ self.lines = [] |
+ |
+ def info(self, message): |
+ self.lines.append(message) |
+ |
+ def debug(self, message): |
+ self.lines.append(message) |
+ |
+class MockInputApi(object): |
+ def __init__(self): |
+ self.re = re |
+ self.os_path = os.path |
+ self.files = [] |
+ self.is_committing = False |
+ self.logging = MockLogging() |
+ |
+ def AffectedFiles(self, include_deletes=None): |
+ return self.files |
+ |
+ |
+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 MockFile(object): |
+ def __init__(self, local_path, old_contents, new_contents): |
+ self._local_path = local_path |
+ self._new_contents = new_contents |
+ self._old_contents = old_contents |
+ self._cached_changed_contents = None |
+ |
+ def ChangedContents(self): |
+ return self._changed_contents |
+ |
+ def NewContents(self): |
+ return self._new_contents |
+ |
+ def LocalPath(self): |
+ return self._local_path |
+ |
+ def IsDirectory(self): |
+ return False |
+ |
+ def GenerateScmDiff(self): |
+ result = "" |
+ for line in difflib.unified_diff(self._old_contents, self._new_contents, |
+ self._local_path, self._local_path): |
+ result += line |
+ return result |
+ |
+ # NOTE: This method is a copy of ChangeContents method of AffectedFile in |
+ # presubmit_support.py |
+ def ChangedContents(self): |
+ """Returns a list of tuples (line number, line text) of all new lines. |
+ |
+ This relies on the scm diff output describing each changed code section |
+ with a line of the form |
+ |
+ ^@@ <old line num>,<old size> <new line num>,<new size> @@$ |
+ """ |
+ if self._cached_changed_contents is not None: |
+ return self._cached_changed_contents[:] |
+ self._cached_changed_contents = [] |
+ line_num = 0 |
+ |
+ if self.IsDirectory(): |
+ return [] |
+ |
+ for line in self.GenerateScmDiff().splitlines(): |
+ m = re.match(r"^@@ [0-9\,\+\-]+ \+([0-9]+)\,[0-9]+ @@", line) |
+ if m: |
+ line_num = int(m.groups(1)[0]) |
+ continue |
+ if line.startswith("+") and not line.startswith("++"): |
+ self._cached_changed_contents.append((line_num, line[1:])) |
+ if not line.startswith("-"): |
+ line_num += 1 |
+ return self._cached_changed_contents[:] |
+ |
+ |
+class MockChange(object): |
+ def __init__(self, changed_files): |
+ self._changed_files = changed_files |
+ |
+ def LocalPaths(self): |
+ return self._changed_files |
+ |
+ |
+class StrictEnumValueCheckerTest(unittest.TestCase): |
+ TEST_FILE_PATTERN = "changed_file_%s.h" |
+ MOCK_FILE_LOCAL_PATH = "mock_enum.h" |
+ START_MARKER = "enum MockEnum {" |
+ END_MARKER = " mBoundary" |
+ |
+ def _ReadTextFileContents(self, path): |
+ """Given a path, returns a list of strings corresponding to the text lines |
+ in the file. Reads files in text format. |
+ |
+ """ |
+ fo = open(path, "r") |
+ try: |
+ contents = fo.readlines() |
+ finally: |
+ fo.close() |
+ return contents |
+ |
+ def _ReadInputFile(self): |
+ return self._ReadTextFileContents("mock_enum.h") |
+ |
+ def _PrepareTest(self, new_file_path): |
+ old_contents = self._ReadInputFile() |
+ if not new_file_path: |
+ new_contents = [] |
+ else: |
+ new_contents = self._ReadTextFileContents(new_file_path) |
+ input_api = MockInputApi() |
+ mock_file = MockFile(self.MOCK_FILE_LOCAL_PATH, |
+ old_contents, |
+ new_contents) |
+ input_api.files.append(mock_file) |
+ output_api = MockOutputApi() |
+ return input_api, output_api |
+ |
+ def _RunTest(self, new_file_path): |
+ input_api, output_api = self._PrepareTest(new_file_path) |
+ checker = StrictEnumValueChecker(input_api, output_api, self.START_MARKER, |
+ self.END_MARKER, self.MOCK_FILE_LOCAL_PATH) |
+ results = checker.Run() |
+ return results |
+ |
+ def testDeleteFile(self): |
+ results = self._RunTest(new_file_path=None) |
+ # TODO(rpaquay) How to check it's the expected warning?' |
+ self.assertEquals(1, len(results), |
+ "We should get a single warning about file deletion.") |
+ |
+ def testSimpleValidEdit(self): |
+ results = self._RunTest(self.TEST_FILE_PATTERN % "1") |
+ # TODO(rpaquay) How to check it's the expected warning?' |
+ self.assertEquals(0, len(results), |
+ "We should get no warning for simple edits.") |
+ |
+ def testSingleDeletionOfEntry(self): |
+ results = self._RunTest(self.TEST_FILE_PATTERN % "2") |
+ # TODO(rpaquay) How to check it's the expected warning?' |
+ self.assertEquals(1, len(results), |
+ "We should get a warning for an entry deletion.") |
+ |
+ def testSingleRenameOfEntry(self): |
+ results = self._RunTest(self.TEST_FILE_PATTERN % "3") |
+ # TODO(rpaquay) How to check it's the expected warning?' |
+ self.assertEquals(1, len(results), |
+ "We should get a warning for an entry rename, even " |
+ "though it is not optimal.") |
+ |
+ def testMissingEnumStartOfEntry(self): |
+ results = self._RunTest(self.TEST_FILE_PATTERN % "4") |
+ # TODO(rpaquay) How to check it's the expected warning?' |
+ self.assertEquals(1, len(results), |
+ "We should get a warning for a missing enum marker.") |
+ |
+ def testMissingEnumEndOfEntry(self): |
+ results = self._RunTest(self.TEST_FILE_PATTERN % "5") |
+ # TODO(rpaquay) How to check it's the expected warning?' |
+ self.assertEquals(1, len(results), |
+ "We should get a warning for a missing enum marker.") |
+ |
+ def testInvertedEnumMarkersOfEntry(self): |
+ results = self._RunTest(self.TEST_FILE_PATTERN % "6") |
+ # TODO(rpaquay) How to check it's the expected warning?' |
+ self.assertEquals(1, len(results), |
+ "We should get a warning for inverted enum markers.") |
+ |
+ def testMultipleInvalidEdits(self): |
+ results = self._RunTest(self.TEST_FILE_PATTERN % "7") |
+ # TODO(rpaquay) How to check it's the expected warning?' |
+ self.assertEquals(3, len(results), |
+ "We should get 3 warnings (one per edit).") |
+ |
+ def testSingleInvalidInserts(self): |
+ results = self._RunTest(self.TEST_FILE_PATTERN % "8") |
+ # TODO(rpaquay) How to check it's the expected warning?' |
+ self.assertEquals(1, len(results), |
+ "We should get a warning for a single invalid " |
+ "insertion inside the enum.") |
+ |
+ def testMulitpleValidInserts(self): |
+ results = self._RunTest(self.TEST_FILE_PATTERN % "9") |
+ # TODO(rpaquay) How to check it's the expected warning?' |
+ self.assertEquals(0, len(results), |
+ "We should not get a warning mulitple valid edits") |
+ |
+ def testSingleValidDeleteOutsideOfEnum(self): |
+ results = self._RunTest(self.TEST_FILE_PATTERN % "10") |
+ # TODO(rpaquay) How to check it's the expected warning?' |
+ self.assertEquals(0, len(results), |
+ "We should not get a warning for a deletion outside of " |
+ "the enum") |
+ |
+ |
+if __name__ == '__main__': |
+ unittest.main() |