1# This file is part of Buildbot. Buildbot is free software: you can 2# redistribute it and/or modify it under the terms of the GNU General Public 3# License as published by the Free Software Foundation, version 2. 4# 5# This program is distributed in the hope that it will be useful, but WITHOUT 6# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 7# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more 8# details. 9# 10# You should have received a copy of the GNU General Public License along with 11# this program; if not, write to the Free Software Foundation, Inc., 51 12# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 13# 14# Copyright Buildbot Team Members 15 16 17import weakref 18 19import mock 20 21from twisted.internet import defer 22from twisted.internet import reactor 23 24from buildbot import config 25from buildbot.data.graphql import GraphQLConnector 26from buildbot.test import fakedb 27from buildbot.test.fake import bworkermanager 28from buildbot.test.fake import endpoint 29from buildbot.test.fake import fakedata 30from buildbot.test.fake import fakemq 31from buildbot.test.fake import pbmanager 32from buildbot.test.fake.botmaster import FakeBotMaster 33from buildbot.test.fake.machine import FakeMachineManager 34from buildbot.util import service 35 36 37class FakeCache: 38 39 """Emulate an L{AsyncLRUCache}, but without any real caching. This 40 I{does} do the weakref part, to catch un-weakref-able objects.""" 41 42 def __init__(self, name, miss_fn): 43 self.name = name 44 self.miss_fn = miss_fn 45 46 def get(self, key, **kwargs): 47 d = self.miss_fn(key, **kwargs) 48 49 @d.addCallback 50 def mkref(x): 51 if x is not None: 52 weakref.ref(x) 53 return x 54 return d 55 56 def put(self, key, val): 57 pass 58 59 60class FakeCaches: 61 62 def get_cache(self, name, miss_fn): 63 return FakeCache(name, miss_fn) 64 65 66class FakeBuilder: 67 68 def __init__(self, master=None, buildername="Builder"): 69 if master: 70 self.master = master 71 self.botmaster = master.botmaster 72 self.name = buildername 73 74 75class FakeLogRotation: 76 rotateLength = 42 77 maxRotatedFiles = 42 78 79 80class FakeMaster(service.MasterService): 81 82 """ 83 Create a fake Master instance: a Mock with some convenience 84 implementations: 85 86 - Non-caching implementation for C{self.caches} 87 """ 88 89 def __init__(self, reactor, 90 master_id=fakedb.FakeBuildRequestsComponent.MASTER_ID): 91 super().__init__() 92 self._master_id = master_id 93 self.reactor = reactor 94 self.objectids = {} 95 self.config = config.MasterConfig() 96 self.caches = FakeCaches() 97 self.pbmanager = pbmanager.FakePBManager() 98 self.initLock = defer.DeferredLock() 99 self.basedir = 'basedir' 100 self.botmaster = FakeBotMaster() 101 self.botmaster.setServiceParent(self) 102 self.name = 'fake:/master' 103 self.masterid = master_id 104 self.workers = bworkermanager.FakeWorkerManager() 105 self.workers.setServiceParent(self) 106 self.machine_manager = FakeMachineManager() 107 self.machine_manager.setServiceParent(self) 108 self.log_rotation = FakeLogRotation() 109 self.db = mock.Mock() 110 self.next_objectid = 0 111 self.config_version = 0 112 113 def getObjectId(sched_name, class_name): 114 k = (sched_name, class_name) 115 try: 116 rv = self.objectids[k] 117 except KeyError: 118 rv = self.objectids[k] = self.next_objectid 119 self.next_objectid += 1 120 return defer.succeed(rv) 121 self.db.state.getObjectId = getObjectId 122 123 def getObjectId(self): 124 return defer.succeed(self._master_id) 125 126 def subscribeToBuildRequests(self, callback): 127 pass 128 129# Leave this alias, in case we want to add more behavior later 130 131 132def make_master(testcase, wantMq=False, wantDb=False, wantData=False, 133 wantRealReactor=False, wantGraphql=False, url=None, **kwargs): 134 if wantRealReactor: 135 _reactor = reactor 136 else: 137 assert testcase is not None, "need testcase for fake reactor" 138 # The test case must inherit from TestReactorMixin and setup it. 139 _reactor = testcase.reactor 140 141 master = FakeMaster(_reactor, **kwargs) 142 if url: 143 master.buildbotURL = url 144 if wantData: 145 wantMq = wantDb = True 146 if wantMq: 147 assert testcase is not None, "need testcase for wantMq" 148 master.mq = fakemq.FakeMQConnector(testcase) 149 master.mq.setServiceParent(master) 150 if wantDb: 151 assert testcase is not None, "need testcase for wantDb" 152 master.db = fakedb.FakeDBConnector(testcase) 153 master.db.setServiceParent(master) 154 if wantData: 155 master.data = fakedata.FakeDataConnector(master, testcase) 156 if wantGraphql: 157 master.graphql = GraphQLConnector() 158 master.graphql.setServiceParent(master) 159 master.graphql.data = master.data.realConnector 160 master.data._scanModule(endpoint) 161 master.config.www = {'graphql': {"debug": True}} 162 try: 163 master.graphql.reconfigServiceWithBuildbotConfig(master.config) 164 except ImportError: 165 pass 166 return master 167