2 # Copyright 2014 The Chromium Authors. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file.
11 from strict_enum_value_checker
import StrictEnumValueChecker
13 class MockLogging(object):
17 def info(self
, message
):
18 self
.lines
.append(message
)
20 def debug(self
, message
):
21 self
.lines
.append(message
)
23 class MockInputApi(object):
26 self
.os_path
= os
.path
28 self
.is_committing
= False
29 self
.logging
= MockLogging()
31 def AffectedFiles(self
, include_deletes
=None):
35 class MockOutputApi(object):
36 class PresubmitResult(object):
37 def __init__(self
, message
, items
=None, long_text
=""):
38 self
.message
= message
40 self
.long_text
= long_text
42 class PresubmitError(PresubmitResult
):
43 def __init__(self
, message
, items
, long_text
=""):
44 MockOutputApi
.PresubmitResult
.__init
__(self
, message
, items
, long_text
)
47 class PresubmitPromptWarning(PresubmitResult
):
48 def __init__(self
, message
, items
, long_text
=""):
49 MockOutputApi
.PresubmitResult
.__init
__(self
, message
, items
, long_text
)
52 class PresubmitNotifyResult(PresubmitResult
):
53 def __init__(self
, message
, items
, long_text
=""):
54 MockOutputApi
.PresubmitResult
.__init
__(self
, message
, items
, long_text
)
58 class MockFile(object):
59 def __init__(self
, local_path
, old_contents
, new_contents
):
60 self
._local
_path
= local_path
61 self
._new
_contents
= new_contents
62 self
._old
_contents
= old_contents
63 self
._cached
_changed
_contents
= None
65 def ChangedContents(self
):
66 return self
._changed
_contents
68 def NewContents(self
):
69 return self
._new
_contents
72 return self
._local
_path
74 def IsDirectory(self
):
77 def GenerateScmDiff(self
):
79 for line
in difflib
.unified_diff(self
._old
_contents
, self
._new
_contents
,
80 self
._local
_path
, self
._local
_path
):
84 # NOTE: This method is a copy of ChangeContents method of AffectedFile in
85 # presubmit_support.py
86 def ChangedContents(self
):
87 """Returns a list of tuples (line number, line text) of all new lines.
89 This relies on the scm diff output describing each changed code section
90 with a line of the form
92 ^@@ <old line num>,<old size> <new line num>,<new size> @@$
94 if self
._cached
_changed
_contents
is not None:
95 return self
._cached
_changed
_contents
[:]
96 self
._cached
_changed
_contents
= []
99 if self
.IsDirectory():
102 for line
in self
.GenerateScmDiff().splitlines():
103 m
= re
.match(r
"^@@ [0-9\,\+\-]+ \+([0-9]+)\,[0-9]+ @@", line
)
105 line_num
= int(m
.groups(1)[0])
107 if line
.startswith("+") and not line
.startswith("++"):
108 self
._cached
_changed
_contents
.append((line_num
, line
[1:]))
109 if not line
.startswith("-"):
111 return self
._cached
_changed
_contents
[:]
114 class MockChange(object):
115 def __init__(self
, changed_files
):
116 self
._changed
_files
= changed_files
118 def LocalPaths(self
):
119 return self
._changed
_files
122 class StrictEnumValueCheckerTest(unittest
.TestCase
):
123 TEST_FILE_PATTERN
= "changed_file_%s.h"
124 MOCK_FILE_LOCAL_PATH
= "mock_enum.h"
125 START_MARKER
= "enum MockEnum {"
126 END_MARKER
= " mBoundary"
128 def _ReadTextFileContents(self
, path
):
129 """Given a path, returns a list of strings corresponding to the text lines
130 in the file. Reads files in text format.
135 contents
= fo
.readlines()
140 def _ReadInputFile(self
):
141 return self
._ReadTextFileContents
("mock_enum.h")
143 def _PrepareTest(self
, new_file_path
):
144 old_contents
= self
._ReadInputFile
()
145 if not new_file_path
:
148 new_contents
= self
._ReadTextFileContents
(new_file_path
)
149 input_api
= MockInputApi()
150 mock_file
= MockFile(self
.MOCK_FILE_LOCAL_PATH
,
153 input_api
.files
.append(mock_file
)
154 output_api
= MockOutputApi()
155 return input_api
, output_api
157 def _RunTest(self
, new_file_path
):
158 input_api
, output_api
= self
._PrepareTest
(new_file_path
)
159 checker
= StrictEnumValueChecker(input_api
, output_api
, self
.START_MARKER
,
160 self
.END_MARKER
, self
.MOCK_FILE_LOCAL_PATH
)
161 results
= checker
.Run()
164 def testDeleteFile(self
):
165 results
= self
._RunTest
(new_file_path
=None)
166 # TODO(rpaquay) How to check it's the expected warning?'
167 self
.assertEquals(1, len(results
),
168 "We should get a single warning about file deletion.")
170 def testSimpleValidEdit(self
):
171 results
= self
._RunTest
(self
.TEST_FILE_PATTERN
% "1")
172 # TODO(rpaquay) How to check it's the expected warning?'
173 self
.assertEquals(0, len(results
),
174 "We should get no warning for simple edits.")
176 def testSingleDeletionOfEntry(self
):
177 results
= self
._RunTest
(self
.TEST_FILE_PATTERN
% "2")
178 # TODO(rpaquay) How to check it's the expected warning?'
179 self
.assertEquals(1, len(results
),
180 "We should get a warning for an entry deletion.")
182 def testSingleRenameOfEntry(self
):
183 results
= self
._RunTest
(self
.TEST_FILE_PATTERN
% "3")
184 # TODO(rpaquay) How to check it's the expected warning?'
185 self
.assertEquals(1, len(results
),
186 "We should get a warning for an entry rename, even "
187 "though it is not optimal.")
189 def testMissingEnumStartOfEntry(self
):
190 results
= self
._RunTest
(self
.TEST_FILE_PATTERN
% "4")
191 # TODO(rpaquay) How to check it's the expected warning?'
192 self
.assertEquals(1, len(results
),
193 "We should get a warning for a missing enum marker.")
195 def testMissingEnumEndOfEntry(self
):
196 results
= self
._RunTest
(self
.TEST_FILE_PATTERN
% "5")
197 # TODO(rpaquay) How to check it's the expected warning?'
198 self
.assertEquals(1, len(results
),
199 "We should get a warning for a missing enum marker.")
201 def testInvertedEnumMarkersOfEntry(self
):
202 results
= self
._RunTest
(self
.TEST_FILE_PATTERN
% "6")
203 # TODO(rpaquay) How to check it's the expected warning?'
204 self
.assertEquals(1, len(results
),
205 "We should get a warning for inverted enum markers.")
207 def testMultipleInvalidEdits(self
):
208 results
= self
._RunTest
(self
.TEST_FILE_PATTERN
% "7")
209 # TODO(rpaquay) How to check it's the expected warning?'
210 self
.assertEquals(3, len(results
),
211 "We should get 3 warnings (one per edit).")
213 def testSingleInvalidInserts(self
):
214 results
= self
._RunTest
(self
.TEST_FILE_PATTERN
% "8")
215 # TODO(rpaquay) How to check it's the expected warning?'
216 self
.assertEquals(1, len(results
),
217 "We should get a warning for a single invalid "
218 "insertion inside the enum.")
220 def testMulitpleValidInserts(self
):
221 results
= self
._RunTest
(self
.TEST_FILE_PATTERN
% "9")
222 # TODO(rpaquay) How to check it's the expected warning?'
223 self
.assertEquals(0, len(results
),
224 "We should not get a warning mulitple valid edits")
226 def testSingleValidDeleteOutsideOfEnum(self
):
227 results
= self
._RunTest
(self
.TEST_FILE_PATTERN
% "10")
228 # TODO(rpaquay) How to check it's the expected warning?'
229 self
.assertEquals(0, len(results
),
230 "We should not get a warning for a deletion outside of "
234 if __name__
== '__main__':