aboutsummaryrefslogtreecommitdiffstats
path: root/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/test/fake/fakedb.py
diff options
context:
space:
mode:
Diffstat (limited to 'lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/test/fake/fakedb.py')
-rw-r--r--lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/test/fake/fakedb.py1224
1 files changed, 0 insertions, 1224 deletions
diff --git a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/test/fake/fakedb.py b/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/test/fake/fakedb.py
deleted file mode 100644
index db9b409c..00000000
--- a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/test/fake/fakedb.py
+++ /dev/null
@@ -1,1224 +0,0 @@
-# This file is part of Buildbot. Buildbot is free software: you can
-# redistribute it and/or modify it under the terms of the GNU General Public
-# License as published by the Free Software Foundation, version 2.
-#
-# This program is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
-# details.
-#
-# You should have received a copy of the GNU General Public License along with
-# this program; if not, write to the Free Software Foundation, Inc., 51
-# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-#
-# Copyright Buildbot Team Members
-
-"""
-A complete re-implementation of the database connector components, but without
-using a database. These classes should pass the same tests as are applied to
-the real connector components.
-"""
-
-import base64
-from buildbot.util import json, epoch2datetime, datetime2epoch
-from twisted.python import failure
-from twisted.internet import defer, reactor
-from buildbot.db import buildrequests
-
-# Fake DB Rows
-
-class Row(object):
- """
- Parent class for row classes, which are used to specify test data for
- database-related tests.
-
- @cvar defaults: default values for columns
- @type defaults: dictionary
-
- @cvar table: the table name
-
- @cvar id_column: specify a column that should be assigned an
- auto-incremented id. Auto-assigned id's begin at 1000, so any explicitly
- specified ID's should be less than 1000.
-
- @cvar required_columns: a tuple of columns that must be given in the
- constructor
-
- @ivar values: the values to be inserted into this row
- """
-
- id_column = ()
- required_columns = ()
- lists = ()
- dicts = ()
-
- def __init__(self, **kwargs):
- self.values = self.defaults.copy()
- self.values.update(kwargs)
- if self.id_column:
- if self.values[self.id_column] is None:
- self.values[self.id_column] = self.nextId()
- for col in self.required_columns:
- assert col in kwargs, "%s not specified" % col
- for col in self.lists:
- setattr(self, col, [])
- for col in self.dicts:
- setattr(self, col, {})
- for col in kwargs.keys():
- assert col in self.defaults, "%s is not a valid column" % col
- # make the values appear as attributes
- self.__dict__.update(self.values)
-
- def nextId(self):
- if not hasattr(self.__class__, '_next_id'):
- self.__class__._next_id = 1000
- else:
- self.__class__._next_id += 1
- return self.__class__._next_id
-
-
-class BuildRequest(Row):
- table = "buildrequests"
-
- defaults = dict(
- id = None,
- buildsetid = None,
- buildername = "bldr",
- priority = 0,
- complete = 0,
- results = -1,
- submitted_at = 0,
- complete_at = 0,
- )
-
- id_column = 'id'
- required_columns = ('buildsetid',)
-
-
-class BuildRequestClaim(Row):
- table = "buildrequest_claims"
-
- defaults = dict(
- brid = None,
- objectid = None,
- claimed_at = None
- )
-
- required_columns = ('brid', 'objectid', 'claimed_at')
-
-
-class Change(Row):
- table = "changes"
-
- defaults = dict(
- changeid = None,
- author = 'frank',
- comments = 'test change',
- is_dir = 0,
- branch = 'master',
- revision = 'abcd',
- revlink = 'http://vc/abcd',
- when_timestamp = 1200000,
- category = 'cat',
- repository = 'repo',
- codebase = '',
- project = 'proj',
- )
-
- lists = ('files',)
- dicts = ('properties',)
- id_column = 'changeid'
-
-
-class ChangeFile(Row):
- table = "change_files"
-
- defaults = dict(
- changeid = None,
- filename = None,
- )
-
- required_columns = ('changeid',)
-
-
-class ChangeProperty(Row):
- table = "change_properties"
-
- defaults = dict(
- changeid = None,
- property_name = None,
- property_value = None,
- )
-
- required_columns = ('changeid',)
-
-class ChangeUser(Row):
- table = "change_users"
-
- defaults = dict(
- changeid = None,
- uid = None,
- )
-
- required_columns = ('changeid',)
-
-class Patch(Row):
- table = "patches"
-
- defaults = dict(
- id = None,
- patchlevel = 0,
- patch_base64 = 'aGVsbG8sIHdvcmxk', # 'hello, world',
- patch_author = None,
- patch_comment = None,
- subdir = None,
- )
-
- id_column = 'id'
-
-
-class SourceStampChange(Row):
- table = "sourcestamp_changes"
-
- defaults = dict(
- sourcestampid = None,
- changeid = None,
- )
-
- required_columns = ('sourcestampid', 'changeid')
-
-class SourceStampSet(Row):
- table = "sourcestampsets"
- defaults = dict(
- id = None,
- )
- id_column = 'id'
-
-class SourceStamp(Row):
- table = "sourcestamps"
-
- defaults = dict(
- id = None,
- branch = 'master',
- revision = 'abcd',
- patchid = None,
- repository = 'repo',
- codebase = '',
- project = 'proj',
- sourcestampsetid = None,
- )
-
- id_column = 'id'
-
-
-class SchedulerChange(Row):
- table = "scheduler_changes"
-
- defaults = dict(
- objectid = None,
- changeid = None,
- important = 1,
- )
-
- required_columns = ( 'objectid', 'changeid' )
-
-
-class Buildset(Row):
- table = "buildsets"
-
- defaults = dict(
- id = None,
- external_idstring = 'extid',
- reason = 'because',
- sourcestampsetid = None,
- submitted_at = 12345678,
- complete = 0,
- complete_at = None,
- results = -1,
- )
-
- id_column = 'id'
- required_columns = ( 'sourcestampsetid', )
-
-
-class BuildsetProperty(Row):
- table = "buildset_properties"
-
- defaults = dict(
- buildsetid = None,
- property_name = 'prop',
- property_value = '[22, "fakedb"]',
- )
-
- required_columns = ( 'buildsetid', )
-
-
-class Object(Row):
- table = "objects"
-
- defaults = dict(
- id = None,
- name = 'nam',
- class_name = 'cls',
- )
-
- id_column = 'id'
-
-
-class ObjectState(Row):
- table = "object_state"
-
- defaults = dict(
- objectid = None,
- name = 'nam',
- value_json = '{}',
- )
-
- required_columns = ( 'objectid', )
-
-class User(Row):
- table = "users"
-
- defaults = dict(
- uid = None,
- identifier = 'soap',
- bb_username = None,
- bb_password = None,
- )
-
- id_column = 'uid'
-
-class UserInfo(Row):
- table = "users_info"
-
- defaults = dict(
- uid = None,
- attr_type = 'git',
- attr_data = 'Tyler Durden <tyler@mayhem.net>',
- )
-
- required_columns = ( 'uid', )
-
-class Build(Row):
- table = "builds"
-
- defaults = dict(
- id = None,
- number = 29,
- brid = 39,
- start_time = 1304262222,
- finish_time = None)
-
- id_column = 'id'
-
-# Fake DB Components
-
-# TODO: test these using the same test methods as are used against the real
-# database
-
-class FakeDBComponent(object):
-
- def __init__(self, db, testcase):
- self.db = db
- self.t = testcase
- self.setUp()
-
-
-class FakeChangesComponent(FakeDBComponent):
-
- def setUp(self):
- self.changes = {}
-
- def insertTestData(self, rows):
- for row in rows:
- if isinstance(row, Change):
- self.changes[row.changeid] = row
-
- elif isinstance(row, ChangeFile):
- ch = self.changes[row.changeid]
- ch.files.append(row.filename)
-
- elif isinstance(row, ChangeProperty):
- ch = self.changes[row.changeid]
- n, vs = row.property_name, row.property_value
- v, s = json.loads(vs)
- ch.properties.setProperty(n, v, s)
-
- elif isinstance(row, ChangeUser):
- ch = self.changes[row.changeid]
- ch.uid = row.uid
-
- # component methods
-
- def addChange(self, author=None, files=None, comments=None, is_dir=0,
- revision=None, when_timestamp=None, branch=None,
- category=None, revlink='', properties={}, repository='',
- project='', codebase='', uid=None):
- if self.changes:
- changeid = max(self.changes.iterkeys()) + 1
- else:
- changeid = 500
-
- self.changes[changeid] = ch = Change(
- changeid=changeid,
- author=author,
- comments=comments,
- is_dir=is_dir,
- revision=revision,
- when_timestamp=datetime2epoch(when_timestamp),
- branch=branch,
- category=category,
- revlink=revlink,
- repository=repository,
- project=project,
- codebase=codebase)
- ch.files = files
- ch.properties = properties
-
- return defer.succeed(changeid)
-
- def getLatestChangeid(self):
- if self.changes:
- return defer.succeed(max(self.changes.iterkeys()))
- return defer.succeed(None)
-
- def getChange(self, changeid):
- try:
- row = self.changes[changeid]
- except KeyError:
- return defer.succeed(None)
-
- chdict = dict(
- changeid=row.changeid,
- author=row.author,
- files=row.files,
- comments=row.comments,
- is_dir=row.is_dir,
- revision=row.revision,
- when_timestamp=epoch2datetime(row.when_timestamp),
- branch=row.branch,
- category=row.category,
- revlink=row.revlink,
- properties=row.properties,
- repository=row.repository,
- codebase=row.codebase,
- project=row.project)
-
- return defer.succeed(chdict)
-
- def getChangeUids(self, changeid):
- try:
- ch_uids = [self.changes[changeid].uid]
- except KeyError:
- ch_uids = []
- return defer.succeed(ch_uids)
-
- # TODO: getRecentChanges
-
- # fake methods
-
- def fakeAddChangeInstance(self, change):
- if not hasattr(change, 'number') or not change.number:
- if self.changes:
- changeid = max(self.changes.iterkeys()) + 1
- else:
- changeid = 500
- else:
- changeid = change.number
-
- # make a row from the change
- row = dict(
- changeid=changeid,
- author=change.who,
- files=change.files,
- comments=change.comments,
- is_dir=change.isdir,
- revision=change.revision,
- when_timestamp=change.when,
- branch=change.branch,
- category=change.category,
- revlink=change.revlink,
- properties=change.properties,
- repository=change.repository,
- codebase=change.codebase,
- project=change.project)
- self.changes[changeid] = row
-
-class FakeSchedulersComponent(FakeDBComponent):
-
- def setUp(self):
- self.states = {}
- self.classifications = {}
-
- def insertTestData(self, rows):
- for row in rows:
- if isinstance(row, SchedulerChange):
- cls = self.classifications.setdefault(row.objectid, {})
- cls[row.changeid] = row.important
-
- # component methods
-
- def classifyChanges(self, objectid, classifications):
- self.classifications.setdefault(objectid, {}).update(classifications)
- return defer.succeed(None)
-
- def flushChangeClassifications(self, objectid, less_than=None):
- if less_than is not None:
- classifications = self.classifications.setdefault(objectid, {})
- for changeid in classifications.keys():
- if changeid < less_than:
- del classifications[changeid]
- else:
- self.classifications[objectid] = {}
- return defer.succeed(None)
-
- def getChangeClassifications(self, objectid, branch=-1, repository=-1,
- project=-1, codebase=-1):
- classifications = self.classifications.setdefault(objectid, {})
-
- sentinel = dict(branch=object(), repository=object(),
- project=object(), codebase=object())
-
- if branch != -1:
- # filter out the classifications for the requested branch
- classifications = dict(
- (k,v) for (k,v) in classifications.iteritems()
- if self.db.changes.changes.get(k, sentinel)['branch'] == branch )
-
- if repository != -1:
- # filter out the classifications for the requested branch
- classifications = dict(
- (k,v) for (k,v) in classifications.iteritems()
- if self.db.changes.changes.get(k, sentinel)['repository'] == repository )
-
- if project != -1:
- # filter out the classifications for the requested branch
- classifications = dict(
- (k,v) for (k,v) in classifications.iteritems()
- if self.db.changes.changes.get(k, sentinel)['project'] == project )
-
- if codebase != -1:
- # filter out the classifications for the requested branch
- classifications = dict(
- (k,v) for (k,v) in classifications.iteritems()
- if self.db.changes.changes.get(k, sentinel)['codebase'] == codebase )
-
- return defer.succeed(classifications)
-
- # fake methods
-
- def fakeClassifications(self, objectid, classifications):
- """Set the set of classifications for a scheduler"""
- self.classifications[objectid] = classifications
-
- # assertions
-
- def assertClassifications(self, objectid, classifications):
- self.t.assertEqual(
- self.classifications.get(objectid, {}),
- classifications)
-
-
-class FakeSourceStampSetsComponent(FakeDBComponent):
- def setUp(self):
- self.sourcestampsets = {}
-
- def insertTestData(self, rows):
- for row in rows:
- if isinstance(row, SourceStampSet):
- self.sourcestampsets[row.id] = dict()
-
- def addSourceStampSet(self):
- id = len(self.sourcestampsets) + 100
- while id in self.sourcestampsets:
- id += 1
- self.sourcestampsets[id] = dict()
- return defer.succeed(id)
-
-class FakeSourceStampsComponent(FakeDBComponent):
-
- def setUp(self):
- self.sourcestamps = {}
- self.patches = {}
-
- def insertTestData(self, rows):
- for row in rows:
- if isinstance(row, Patch):
- self.patches[row.id] = dict(
- patch_level=row.patchlevel,
- patch_body=base64.b64decode(row.patch_base64),
- patch_author=row.patch_author,
- patch_comment=row.patch_comment,
- patch_subdir=row.subdir)
-
- for row in rows:
- if isinstance(row, SourceStamp):
- ss = self.sourcestamps[row.id] = row.values.copy()
- ss['changeids'] = set()
-
- for row in rows:
- if isinstance(row, SourceStampChange):
- ss = self.sourcestamps[row.sourcestampid]
- ss['changeids'].add(row.changeid)
-
- # component methods
-
- def addSourceStamp(self, branch, revision, repository, project, sourcestampsetid,
- codebase = '', patch_body=None, patch_level=0, patch_author=None,
- patch_comment=None, patch_subdir=None, changeids=[]):
- id = len(self.sourcestamps) + 100
- while id in self.sourcestamps:
- id += 1
-
- changeids = set(changeids)
-
- if patch_body:
- patchid = len(self.patches) + 100
- while patchid in self.patches:
- patchid += 1
- self.patches[patchid] = dict(
- patch_level=patch_level,
- patch_body=patch_body,
- patch_subdir=patch_subdir,
- patch_author=patch_author,
- patch_comment=patch_comment
- )
- else:
- patchid = None
-
- self.sourcestamps[id] = dict(id=id, sourcestampsetid=sourcestampsetid, branch=branch, revision=revision, codebase=codebase,
- patchid=patchid, repository=repository, project=project,
- changeids=changeids)
- return defer.succeed(id)
-
- def getSourceStamp(self, ssid):
- return defer.succeed(self._getSourceStamp(ssid))
-
- def _getSourceStamp(self, ssid):
- if ssid in self.sourcestamps:
- ssdict = self.sourcestamps[ssid].copy()
- del ssdict['id']
- ssdict['ssid'] = ssid
- patchid = ssdict['patchid']
- if patchid:
- ssdict.update(self.patches[patchid])
- else:
- ssdict['patch_body'] = None
- ssdict['patch_level'] = None
- ssdict['patch_subdir'] = None
- ssdict['patch_author'] = None
- ssdict['patch_comment'] = None
- del ssdict['patchid']
- return ssdict
- else:
- return None
-
- def getSourceStamps(self, sourcestampsetid):
- sslist = []
- for ssdict in self.sourcestamps.itervalues():
- if ssdict['sourcestampsetid'] == sourcestampsetid:
- ssdictcpy = self._getSourceStamp(ssdict['id'])
- sslist.append(ssdictcpy)
- return defer.succeed(sslist)
-
-class FakeBuildsetsComponent(FakeDBComponent):
-
- def setUp(self):
- self.buildsets = {}
- self.completed_bsids = set()
- self.buildset_subs = []
-
- def insertTestData(self, rows):
- for row in rows:
- if isinstance(row, Buildset):
- bs = self.buildsets[row.id] = row.values.copy()
- bs['properties'] = {}
-
- for row in rows:
- if isinstance(row, BuildsetProperty):
- assert row.buildsetid in self.buildsets
- n = row.property_name
- v, src = tuple(json.loads(row.property_value))
- self.buildsets[row.buildsetid]['properties'][n] = (v, src)
-
- # component methods
-
- def _newBsid(self):
- bsid = 200
- while bsid in self.buildsets:
- bsid += 1
- return bsid
-
- def addBuildset(self, sourcestampsetid, reason, properties, builderNames,
- external_idstring=None, _reactor=reactor):
- bsid = self._newBsid()
- br_rows = []
- for buildername in builderNames:
- br_rows.append(
- BuildRequest(buildsetid=bsid, buildername=buildername))
- self.db.buildrequests.insertTestData(br_rows)
-
- # make up a row and keep its dictionary, with the properties tacked on
- bsrow = Buildset(sourcestampsetid=sourcestampsetid, reason=reason, external_idstring=external_idstring)
- self.buildsets[bsid] = bsrow.values.copy()
- self.buildsets[bsid]['properties'] = properties
-
- return defer.succeed((bsid,
- dict([ (br.buildername, br.id) for br in br_rows ])))
-
- def completeBuildset(self, bsid, results, complete_at=None,
- _reactor=reactor):
- self.buildsets[bsid]['results'] = results
- self.buildsets[bsid]['complete'] = 1
- self.buildsets[bsid]['complete_at'] = complete_at or _reactor.seconds()
- return defer.succeed(None)
-
- def getBuildset(self, bsid):
- if bsid not in self.buildsets:
- return defer.succeed(None)
- row = self.buildsets[bsid]
- return defer.succeed(self._row2dict(row))
-
- def getBuildsets(self, complete=None):
- rv = []
- for bs in self.buildsets.itervalues():
- if complete is not None:
- if complete and bs['complete']:
- rv.append(self._row2dict(bs))
- elif not complete and not bs['complete']:
- rv.append(self._row2dict(bs))
- else:
- rv.append(self._row2dict(bs))
- return defer.succeed(rv)
-
- def _row2dict(self, row):
- row = row.copy()
- if row['complete_at']:
- row['complete_at'] = epoch2datetime(row['complete_at'])
- else:
- row['complete_at'] = None
- row['submitted_at'] = row['submitted_at'] and \
- epoch2datetime(row['submitted_at'])
- row['complete'] = bool(row['complete'])
- row['bsid'] = row['id']
- del row['id']
- return row
-
- def getBuildsetProperties(self, buildsetid):
- if buildsetid in self.buildsets:
- return defer.succeed(
- self.buildsets[buildsetid]['properties'])
- else:
- return defer.succeed({})
-
- # fake methods
-
- def fakeBuildsetCompletion(self, bsid, result):
- assert bsid in self.buildsets
- self.buildsets[bsid]['results'] = result
- self.completed_bsids.add(bsid)
-
- def flushBuildsets(self):
- """
- Flush the set of buildsets, for example after C{assertBuildset}
- """
- self.buildsets = {}
- self.completed_bsids = set()
-
- # assertions
-
- def assertBuildsets(self, count):
- """Assert that exactly COUNT buildsets were added"""
- self.t.assertEqual(len(self.buildsets), count,
- "buildsets are %r" % (self.buildsets,))
-
- def assertBuildset(self, bsid, expected_buildset, expected_sourcestamps):
- """Assert that the buildset and its attached sourcestamp look as
- expected; the ssid parameter of the buildset is omitted. Properties
- are converted with asList and sorted. Sourcestamp patches are inlined
- (patch_body, patch_level, patch_subdir), and changeids are represented
- as a set, but omitted if empty. If bsid is '?', then assert there is
- only one new buildset, and use that."""
- if bsid == '?':
- self.assertBuildsets(1)
- bsid = self.buildsets.keys()[0]
- else:
- self.t.assertIn(bsid, self.buildsets)
-
- buildset = self.buildsets[bsid].copy()
-
- dictOfssDict= {}
- for sourcestamp in self.db.sourcestamps.sourcestamps.itervalues():
- if sourcestamp['sourcestampsetid'] == buildset['sourcestampsetid']:
- ssdict = sourcestamp.copy()
- ss_repository = ssdict['codebase']
- dictOfssDict[ss_repository] = ssdict
-
- if 'id' in buildset:
- del buildset['id']
-
- # clear out some columns if the caller doesn't care
- for col in 'complete complete_at submitted_at results'.split():
- if col not in expected_buildset:
- del buildset[col]
-
- if buildset['properties']:
- buildset['properties'] = sorted(buildset['properties'].items())
-
- # only add brids if we're expecting them (sometimes they're unknown)
- if 'brids' in expected_buildset:
- buildset['brids'] = self.allBuildRequests(bsid)
-
- if 'builders' in expected_buildset:
- buildset['builders'] = self.allBuildRequests(bsid).keys()
-
- for ss in dictOfssDict.itervalues():
- if 'id' in ss:
- del ss['id']
- if not ss['changeids']:
- del ss['changeids']
-
- # incorporate patch info if we have it
- if 'patchid' in ss and ss['patchid']:
- ss.update(self.db.sourcestamps.patches[ss['patchid']])
- del ss['patchid']
-
- self.t.assertEqual(
- dict(buildset=buildset, sourcestamps=dictOfssDict),
- dict(buildset=expected_buildset, sourcestamps=expected_sourcestamps))
- return bsid
-
- def allBuildsetIds(self):
- return self.buildsets.keys()
-
- def allBuildRequests(self, bsid=None):
- if bsid is not None:
- is_same_bsid = lambda br: br.buildsetid==bsid
- else:
- is_same_bsid = lambda br: True
- return dict([ (br.buildername, br.id)
- for br in self.db.buildrequests.reqs.values()
- if is_same_bsid(br) ])
-
-
-class FakeStateComponent(FakeDBComponent):
-
- def setUp(self):
- self.objects = {}
- self.states = {}
-
- def insertTestData(self, rows):
- for row in rows:
- if isinstance(row, Object):
- self.objects[(row.name, row.class_name)] = row.id
- self.states[row.id] = {}
-
- for row in rows:
- if isinstance(row, ObjectState):
- assert row.objectid in self.objects.values()
- self.states[row.objectid][row.name] = row.value_json
-
- # component methods
-
- def _newId(self):
- id = 100
- while id in self.states:
- id += 1
- return id
-
- def getObjectId(self, name, class_name):
- try:
- id = self.objects[(name, class_name)]
- except:
- # invent a new id and add it
- id = self.objects[(name, class_name)] = self._newId()
- self.states[id] = {}
- return defer.succeed(id)
-
- def getState(self, objectid, name, default=object):
- try:
- json_value = self.states[objectid][name]
- except KeyError:
- if default is not object:
- return defer.succeed(default)
- raise
- return defer.succeed(json.loads(json_value))
-
- def setState(self, objectid, name, value):
- self.states[objectid][name] = json.dumps(value)
- return defer.succeed(None)
-
- # fake methods
-
- def fakeState(self, name, class_name, **kwargs):
- id = self.objects[(name, class_name)] = self._newId()
- self.objects[(name, class_name)] = id
- self.states[id] = dict( (k, json.dumps(v))
- for k,v in kwargs.iteritems() )
- return id
-
- # assertions
-
- def assertState(self, objectid, missing_keys=[], **kwargs):
- state = self.states[objectid]
- for k in missing_keys:
- self.t.assertFalse(k in state, "%s in %s" % (k, state))
- for k,v in kwargs.iteritems():
- self.t.assertIn(k, state)
- self.t.assertEqual(json.loads(state[k]), v,
- "state is %r" % (state,))
-
- def assertStateByClass(self, name, class_name, **kwargs):
- objectid = self.objects[(name, class_name)]
- state = self.states[objectid]
- for k,v in kwargs.iteritems():
- self.t.assertIn(k, state)
- self.t.assertEqual(json.loads(state[k]), v,
- "state is %r" % (state,))
-
-
-class FakeBuildRequestsComponent(FakeDBComponent):
-
- # for use in determining "my" requests
- MASTER_ID = 824
-
- # override this to set reactor.seconds
- _reactor = reactor
-
- def setUp(self):
- self.reqs = {}
- self.claims = {}
-
- def insertTestData(self, rows):
- for row in rows:
- if isinstance(row, BuildRequest):
- self.reqs[row.id] = row
-
- if isinstance(row, BuildRequestClaim):
- self.claims[row.brid] = row
-
- # component methods
-
- def getBuildRequest(self, brid):
- try:
- return defer.succeed(self._brdictFromRow(self.reqs[brid]))
- except:
- return defer.succeed(None)
-
- def getBuildRequests(self, buildername=None, complete=None, claimed=None,
- bsid=None):
- rv = []
- for br in self.reqs.itervalues():
- if buildername and br.buildername != buildername:
- continue
- if complete is not None:
- if complete and not br.complete:
- continue
- if not complete and br.complete:
- continue
- if claimed is not None:
- claim_row = self.claims.get(br.id)
- if claimed == "mine":
- if not claim_row or claim_row.objectid != self.MASTER_ID:
- continue
- elif claimed:
- if not claim_row:
- continue
- else:
- if claim_row:
- continue
- if bsid is not None:
- if br.buildsetid != bsid:
- continue
- rv.append(self._brdictFromRow(br))
- return defer.succeed(rv)
-
- def claimBuildRequests(self, brids, claimed_at=None):
- for brid in brids:
- if brid not in self.reqs or brid in self.claims:
- return defer.fail(
- failure.Failure(buildrequests.AlreadyClaimedError))
-
- claimed_at = datetime2epoch(claimed_at)
- if not claimed_at:
- claimed_at = self._reactor.seconds()
-
- # now that we've thrown any necessary exceptions, get started
- for brid in brids:
- self.claims[brid] = BuildRequestClaim(brid=brid,
- objectid=self.MASTER_ID, claimed_at=claimed_at)
- return defer.succeed(None)
-
- def reclaimBuildRequests(self, brids):
- for brid in brids:
- if brid not in self.claims:
- print "trying to reclaim brid %d, but it's not claimed" % brid
- return defer.fail(
- failure.Failure(buildrequests.AlreadyClaimedError))
- # now that we've thrown any necessary exceptions, get started
- for brid in brids:
- self.claims[brid] = BuildRequestClaim(brid=brid,
- objectid=self.MASTER_ID, claimed_at=self._reactor.seconds())
- return defer.succeed(None)
-
- def unclaimBuildRequests(self, brids):
- for brid in brids:
- try:
- self.claims.pop(brid)
- except KeyError:
- print "trying to unclaim brid %d, but it's not claimed" % brid
- return defer.fail(
- failure.Failure(buildrequests.AlreadyClaimedError))
-
- return defer.succeed(None)
-
- # Code copied from buildrequests.BuildRequestConnectorComponent
- def _brdictFromRow(self, row):
- claimed = mine = False
- claimed_at = None
- claim_row = self.claims.get(row.id, None)
- if claim_row:
- claimed = True
- claimed_at = claim_row.claimed_at
- mine = claim_row.objectid == self.MASTER_ID
-
- submitted_at = epoch2datetime(row.submitted_at)
- complete_at = epoch2datetime(row.complete_at)
-
- return dict(brid=row.id, buildsetid=row.buildsetid,
- buildername=row.buildername, priority=row.priority,
- claimed=claimed, claimed_at=claimed_at, mine=mine,
- complete=bool(row.complete), results=row.results,
- submitted_at=submitted_at, complete_at=complete_at)
-
- # fake methods
-
- def fakeClaimBuildRequest(self, brid, claimed_at=None, objectid=None):
- if objectid is None:
- objectid = self.MASTER_ID
- self.claims[brid] = BuildRequestClaim(brid=brid,
- objectid=objectid, claimed_at=self._reactor.seconds())
-
- def fakeUnclaimBuildRequest(self, brid):
- del self.claims[brid]
-
- # assertions
-
- def assertMyClaims(self, claimed_brids):
- self.t.assertEqual(
- [ id for (id, brc) in self.claims.iteritems()
- if brc.objectid == self.MASTER_ID ],
- claimed_brids)
-
-
-class FakeBuildsComponent(FakeDBComponent):
-
- def setUp(self):
- self.builds = {}
-
- def insertTestData(self, rows):
- for row in rows:
- if isinstance(row, Build):
- self.builds[row.id] = row
-
- # component methods
-
- def _newId(self):
- id = 100
- while id in self.builds:
- id += 1
- return id
-
- def getBuild(self, bid):
- row = self.builds.get(bid)
- if not row:
- return defer.succeed(None)
-
- return defer.succeed(dict(
- bid=row.id,
- brid=row.brid,
- number=row.number,
- start_time=epoch2datetime(row.start_time),
- finish_time=epoch2datetime(row.finish_time)))
-
- def getBuildsForRequest(self, brid):
- ret = []
-
- for (id, row) in self.builds.items():
- if row.brid == brid:
- ret.append(dict(bid = row.id,
- brid=row.brid,
- number=row.number,
- start_time=epoch2datetime(row.start_time),
- finish_time=epoch2datetime(row.finish_time)))
-
- return defer.succeed(ret)
-
- def addBuild(self, brid, number, _reactor=reactor):
- bid = self._newId()
- self.builds[bid] = Build(id=bid, number=number, brid=brid,
- start_time=_reactor.seconds, finish_time=None)
- return bid
-
- def finishBuilds(self, bids, _reactor=reactor):
- now = _reactor.seconds()
- for bid in bids:
- b = self.builds.get(bid)
- if b:
- b.finish_time = now
-
-class FakeUsersComponent(FakeDBComponent):
-
- def setUp(self):
- self.users = {}
- self.users_info = {}
- self.id_num = 0
-
- def insertTestData(self, rows):
- for row in rows:
- if isinstance(row, User):
- self.users[row.uid] = dict(identifier=row.identifier,
- bb_username=row.bb_username,
- bb_password=row.bb_password)
-
- if isinstance(row, UserInfo):
- assert row.uid in self.users
- if row.uid not in self.users_info:
- self.users_info[row.uid] = [dict(attr_type=row.attr_type,
- attr_data=row.attr_data)]
- else:
- self.users_info[row.uid].append(
- dict(attr_type=row.attr_type,
- attr_data=row.attr_data))
-
- def _user2dict(self, uid):
- usdict = None
- if uid in self.users:
- usdict = self.users[uid]
- if uid in self.users_info:
- infos = self.users_info[uid]
- for attr in infos:
- usdict[attr['attr_type']] = attr['attr_data']
- usdict['uid'] = uid
- return usdict
-
- def nextId(self):
- self.id_num += 1
- return self.id_num
-
- # component methods
-
- def findUserByAttr(self, identifier, attr_type, attr_data):
- for uid in self.users_info:
- attrs = self.users_info[uid]
- for attr in attrs:
- if (attr_type == attr['attr_type'] and
- attr_data == attr['attr_data']):
- return defer.succeed(uid)
-
- uid = self.nextId()
- self.db.insertTestData([User(uid=uid, identifier=identifier)])
- self.db.insertTestData([UserInfo(uid=uid,
- attr_type=attr_type,
- attr_data=attr_data)])
- return defer.succeed(uid)
-
- def getUser(self, uid):
- usdict = None
- if uid in self.users:
- usdict = self._user2dict(uid)
- return defer.succeed(usdict)
-
- def getUserByUsername(self, username):
- usdict = None
- for uid in self.users:
- user = self.users[uid]
- if user['bb_username'] == username:
- usdict = self._user2dict(uid)
- return defer.succeed(usdict)
-
- def updateUser(self, uid=None, identifier=None, bb_username=None,
- bb_password=None, attr_type=None, attr_data=None):
- assert uid is not None
-
- if identifier is not None:
- self.users[uid]['identifier'] = identifier
-
- if bb_username is not None:
- assert bb_password is not None
- try:
- user = self.users[uid]
- user['bb_username'] = bb_username
- user['bb_password'] = bb_password
- except KeyError:
- pass
-
- if attr_type is not None:
- assert attr_data is not None
- try:
- infos = self.users_info[uid]
- for attr in infos:
- if attr_type == attr['attr_type']:
- attr['attr_data'] = attr_data
- break
- else:
- infos.append(dict(attr_type=attr_type,
- attr_data=attr_data))
- except KeyError:
- pass
-
- return defer.succeed(None)
-
- def removeUser(self, uid):
- if uid in self.users:
- self.users.pop(uid)
- self.users_info.pop(uid)
- return defer.succeed(None)
-
- def identifierToUid(self, identifier):
- for uid in self.users:
- if identifier == self.users[uid]['identifier']:
- return defer.succeed(uid)
- return defer.succeed(None)
-
-class FakeDBConnector(object):
- """
- A stand-in for C{master.db} that operates without an actual database
- backend. This also implements a test-data interface similar to the
- L{buildbot.test.util.db.RealDatabaseMixin.insertTestData} method.
-
- The child classes implement various useful assertions and faking methods;
- see their documentation for more.
- """
-
- def __init__(self, testcase):
- self._components = []
- self.changes = comp = FakeChangesComponent(self, testcase)
- self._components.append(comp)
- self.schedulers = comp = FakeSchedulersComponent(self, testcase)
- self._components.append(comp)
- self.sourcestampsets = comp = FakeSourceStampSetsComponent(self,testcase)
- self._components.append(comp)
- self.sourcestamps = comp = FakeSourceStampsComponent(self, testcase)
- self._components.append(comp)
- self.buildsets = comp = FakeBuildsetsComponent(self, testcase)
- self._components.append(comp)
- self.state = comp = FakeStateComponent(self, testcase)
- self._components.append(comp)
- self.buildrequests = comp = FakeBuildRequestsComponent(self, testcase)
- self._components.append(comp)
- self.builds = comp = FakeBuildsComponent(self, testcase)
- self._components.append(comp)
- self.users = comp = FakeUsersComponent(self, testcase)
- self._components.append(comp)
-
- def setup(self):
- self.is_setup = True
- return defer.succeed(None)
-
- def insertTestData(self, rows):
- """Insert a list of Row instances into the database; this method can be
- called synchronously or asynchronously (it completes immediately) """
- for comp in self._components:
- comp.insertTestData(rows)
- return defer.succeed(None)