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