[M94 Migration] Load ErrorPage for HTTP Error 404
[platform/framework/web/chromium-efl.git] / PRESUBMIT_test_mocks.py
1 # Copyright 2014 The Chromium Authors. All rights reserved.
2 # Use of this source code is governed by a BSD-style license that can be
3 # found in the LICENSE file.
4
5 from collections import defaultdict
6 import fnmatch
7 import json
8 import os
9 import re
10 import subprocess
11 import sys
12
13 # TODO(dcheng): It's kind of horrible that this is copy and pasted from
14 # presubmit_canned_checks.py, but it's far easier than any of the alternatives.
15 def _ReportErrorFileAndLine(filename, line_num, dummy_line):
16   """Default error formatter for _FindNewViolationsOfRule."""
17   return '%s:%s' % (filename, line_num)
18
19
20 class MockCannedChecks(object):
21   def _FindNewViolationsOfRule(self, callable_rule, input_api,
22                                source_file_filter=None,
23                                error_formatter=_ReportErrorFileAndLine):
24     """Find all newly introduced violations of a per-line rule (a callable).
25
26     Arguments:
27       callable_rule: a callable taking a file extension and line of input and
28         returning True if the rule is satisfied and False if there was a
29         problem.
30       input_api: object to enumerate the affected files.
31       source_file_filter: a filter to be passed to the input api.
32       error_formatter: a callable taking (filename, line_number, line) and
33         returning a formatted error string.
34
35     Returns:
36       A list of the newly-introduced violations reported by the rule.
37     """
38     errors = []
39     for f in input_api.AffectedFiles(include_deletes=False,
40                                      file_filter=source_file_filter):
41       # For speed, we do two passes, checking first the full file.  Shelling out
42       # to the SCM to determine the changed region can be quite expensive on
43       # Win32.  Assuming that most files will be kept problem-free, we can
44       # skip the SCM operations most of the time.
45       extension = str(f.LocalPath()).rsplit('.', 1)[-1]
46       if all(callable_rule(extension, line) for line in f.NewContents()):
47         continue  # No violation found in full text: can skip considering diff.
48
49       for line_num, line in f.ChangedContents():
50         if not callable_rule(extension, line):
51           errors.append(error_formatter(f.LocalPath(), line_num, line))
52
53     return errors
54
55
56 class MockInputApi(object):
57   """Mock class for the InputApi class.
58
59   This class can be used for unittests for presubmit by initializing the files
60   attribute as the list of changed files.
61   """
62
63   DEFAULT_FILES_TO_SKIP = ()
64
65   def __init__(self):
66     self.canned_checks = MockCannedChecks()
67     self.fnmatch = fnmatch
68     self.json = json
69     self.re = re
70     self.os_path = os.path
71     self.platform = sys.platform
72     self.python_executable = sys.executable
73     self.platform = sys.platform
74     self.subprocess = subprocess
75     self.sys = sys
76     self.files = []
77     self.is_committing = False
78     self.change = MockChange([])
79     self.presubmit_local_path = os.path.dirname(__file__)
80
81   def CreateMockFileInPath(self, f_list):
82     self.os_path.exists = lambda x: x in f_list
83
84   def AffectedFiles(self, file_filter=None, include_deletes=False):
85     for file in self.files:
86       if file_filter and not file_filter(file):
87         continue
88       if not include_deletes and file.Action() == 'D':
89         continue
90       yield file
91
92   def AffectedSourceFiles(self, file_filter=None):
93     return self.AffectedFiles(file_filter=file_filter)
94
95   def FilterSourceFile(self, file,
96                        files_to_check=(), files_to_skip=()):
97     local_path = file.LocalPath()
98     found_in_files_to_check = not files_to_check
99     if files_to_check:
100       if type(files_to_check) is str:
101         raise TypeError('files_to_check should be an iterable of strings')
102       for pattern in files_to_check:
103         compiled_pattern = re.compile(pattern)
104         if compiled_pattern.search(local_path):
105           found_in_files_to_check = True
106           break
107     if files_to_skip:
108       if type(files_to_skip) is str:
109         raise TypeError('files_to_skip should be an iterable of strings')
110       for pattern in files_to_skip:
111         compiled_pattern = re.compile(pattern)
112         if compiled_pattern.search(local_path):
113           return False
114     return found_in_files_to_check
115
116   def LocalPaths(self):
117     return [file.LocalPath() for file in self.files]
118
119   def PresubmitLocalPath(self):
120     return self.presubmit_local_path
121
122   def ReadFile(self, filename, mode='rU'):
123     if hasattr(filename, 'AbsoluteLocalPath'):
124        filename = filename.AbsoluteLocalPath()
125     for file_ in self.files:
126       if file_.LocalPath() == filename:
127         return '\n'.join(file_.NewContents())
128     # Otherwise, file is not in our mock API.
129     raise IOError("No such file or directory: '%s'" % filename)
130
131
132 class MockOutputApi(object):
133   """Mock class for the OutputApi class.
134
135   An instance of this class can be passed to presubmit unittests for outputing
136   various types of results.
137   """
138
139   class PresubmitResult(object):
140     def __init__(self, message, items=None, long_text=''):
141       self.message = message
142       self.items = items
143       self.long_text = long_text
144
145     def __repr__(self):
146       return self.message
147
148   class PresubmitError(PresubmitResult):
149     def __init__(self, message, items=None, long_text=''):
150       MockOutputApi.PresubmitResult.__init__(self, message, items, long_text)
151       self.type = 'error'
152
153   class PresubmitPromptWarning(PresubmitResult):
154     def __init__(self, message, items=None, long_text=''):
155       MockOutputApi.PresubmitResult.__init__(self, message, items, long_text)
156       self.type = 'warning'
157
158   class PresubmitNotifyResult(PresubmitResult):
159     def __init__(self, message, items=None, long_text=''):
160       MockOutputApi.PresubmitResult.__init__(self, message, items, long_text)
161       self.type = 'notify'
162
163   class PresubmitPromptOrNotify(PresubmitResult):
164     def __init__(self, message, items=None, long_text=''):
165       MockOutputApi.PresubmitResult.__init__(self, message, items, long_text)
166       self.type = 'promptOrNotify'
167
168   def __init__(self):
169     self.more_cc = []
170
171   def AppendCC(self, more_cc):
172     self.more_cc.extend(more_cc)
173
174
175 class MockFile(object):
176   """Mock class for the File class.
177
178   This class can be used to form the mock list of changed files in
179   MockInputApi for presubmit unittests.
180   """
181
182   def __init__(self, local_path, new_contents, old_contents=None, action='A',
183                scm_diff=None):
184     self._local_path = local_path
185     self._new_contents = new_contents
186     self._changed_contents = [(i + 1, l) for i, l in enumerate(new_contents)]
187     self._action = action
188     if scm_diff:
189       self._scm_diff = scm_diff
190     else:
191       self._scm_diff = (
192         "--- /dev/null\n+++ %s\n@@ -0,0 +1,%d @@\n" %
193             (local_path, len(new_contents)))
194       for l in new_contents:
195         self._scm_diff += "+%s\n" % l
196     self._old_contents = old_contents
197
198   def Action(self):
199     return self._action
200
201   def ChangedContents(self):
202     return self._changed_contents
203
204   def NewContents(self):
205     return self._new_contents
206
207   def LocalPath(self):
208     return self._local_path
209
210   def AbsoluteLocalPath(self):
211     return self._local_path
212
213   def GenerateScmDiff(self):
214     return self._scm_diff
215
216   def OldContents(self):
217     return self._old_contents
218
219   def rfind(self, p):
220     """os.path.basename is called on MockFile so we need an rfind method."""
221     return self._local_path.rfind(p)
222
223   def __getitem__(self, i):
224     """os.path.basename is called on MockFile so we need a get method."""
225     return self._local_path[i]
226
227   def __len__(self):
228     """os.path.basename is called on MockFile so we need a len method."""
229     return len(self._local_path)
230
231   def replace(self, altsep, sep):
232     """os.path.basename is called on MockFile so we need a replace method."""
233     return self._local_path.replace(altsep, sep)
234
235
236 class MockAffectedFile(MockFile):
237   def AbsoluteLocalPath(self):
238     return self._local_path
239
240
241 class MockChange(object):
242   """Mock class for Change class.
243
244   This class can be used in presubmit unittests to mock the query of the
245   current change.
246   """
247
248   def __init__(self, changed_files):
249     self._changed_files = changed_files
250     self.footers = defaultdict(list)
251
252   def LocalPaths(self):
253     return self._changed_files
254
255   def AffectedFiles(self, include_dirs=False, include_deletes=True,
256                     file_filter=None):
257     return self._changed_files
258
259   def GitFootersFromDescription(self):
260     return self.footers
261