• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
2#
3# Use of this source code is governed by a BSD-style license
4# that can be found in the LICENSE file in the root of the source
5# tree. An additional intellectual property rights grant can be found
6# in the file PATENTS.  All contributing project authors may
7# be found in the AUTHORS file in the root of the source tree.
8
9# This file is inspired to [1].
10# [1] - https://cs.chromium.org/chromium/src/PRESUBMIT_test_mocks.py
11
12import os.path
13import re
14
15
16class MockInputApi(object):
17  """Mock class for the InputApi class.
18
19  This class can be used for unittests for presubmit by initializing the files
20  attribute as the list of changed files.
21  """
22
23  def __init__(self):
24    self.change = MockChange([], [])
25    self.files = []
26    self.presubmit_local_path = os.path.dirname(__file__)
27
28  def AffectedSourceFiles(self, file_filter=None):
29    return self.AffectedFiles(file_filter=file_filter)
30
31  def AffectedFiles(self, file_filter=None, include_deletes=False):
32    # pylint: disable=unused-argument
33    return self.files
34
35  @classmethod
36  def FilterSourceFile(cls, affected_file, white_list=(), black_list=()):
37    # pylint: disable=unused-argument
38    return True
39
40  def PresubmitLocalPath(self):
41    return self.presubmit_local_path
42
43  def ReadFile(self, affected_file, mode='rU'):
44    filename = affected_file.AbsoluteLocalPath()
45    for f in self.files:
46      if f.LocalPath() == filename:
47        with open(filename, mode) as f:
48          return f.read()
49    # Otherwise, file is not in our mock API.
50    raise IOError, "No such file or directory: '%s'" % filename
51
52
53class MockOutputApi(object):
54  """Mock class for the OutputApi class.
55
56  An instance of this class can be passed to presubmit unittests for outputing
57  various types of results.
58  """
59
60  class PresubmitResult(object):
61    def __init__(self, message, items=None, long_text=''):
62      self.message = message
63      self.items = items
64      self.long_text = long_text
65
66    def __repr__(self):
67      return self.message
68
69  class PresubmitError(PresubmitResult):
70    def __init__(self, message, items=None, long_text=''):
71      MockOutputApi.PresubmitResult.__init__(self, message, items, long_text)
72      self.type = 'error'
73
74
75class MockChange(object):
76  """Mock class for Change class.
77
78  This class can be used in presubmit unittests to mock the query of the
79  current change.
80  """
81
82  def __init__(self, changed_files, bugs_from_description, tags=None):
83    self._changed_files = changed_files
84    self._bugs_from_description = bugs_from_description
85    self.tags = dict() if not tags else tags
86
87  def BugsFromDescription(self):
88    return self._bugs_from_description
89
90  def __getattr__(self, attr):
91    """Return tags directly as attributes on the object."""
92    if not re.match(r"^[A-Z_]*$", attr):
93      raise AttributeError(self, attr)
94    return self.tags.get(attr)
95
96
97class MockFile(object):
98  """Mock class for the File class.
99
100  This class can be used to form the mock list of changed files in
101  MockInputApi for presubmit unittests.
102  """
103
104  def __init__(self, local_path, new_contents=None, old_contents=None,
105      action='A'):
106    if new_contents is None:
107      new_contents = ["Data"]
108    self._local_path = local_path
109    self._new_contents = new_contents
110    self._changed_contents = [(i + 1, l) for i, l in enumerate(new_contents)]
111    self._action = action
112    self._old_contents = old_contents
113
114  def Action(self):
115    return self._action
116
117  def ChangedContents(self):
118    return self._changed_contents
119
120  def NewContents(self):
121    return self._new_contents
122
123  def LocalPath(self):
124    return self._local_path
125
126  def AbsoluteLocalPath(self):
127    return self._local_path
128
129  def OldContents(self):
130    return self._old_contents
131