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