def cb(_): self.assertAllCommandsRan() self.assertEqual( self.poller.lastRev, { "master": "4423cdbcbb89c14e50dd5f4152415afd686c5241", "release": "9118f4ab71963d23d02d4bdc54876ac8bf05acf2", }, ) self.assertEqual(len(self.changes_added), 3) self.assertEqual(self.changes_added[0]["author"], "by:4423cdbc") self.assertEqual(self.changes_added[0]["when_timestamp"], epoch2datetime(1273258009)) self.assertEqual(self.changes_added[0]["comments"], "hello!") self.assertEqual(self.changes_added[0]["branch"], "master") self.assertEqual(self.changes_added[0]["files"], ["/etc/442"]) self.assertEqual(self.changes_added[0]["src"], "git") self.assertEqual(self.changes_added[1]["author"], "by:64a5dc2a") self.assertEqual(self.changes_added[1]["when_timestamp"], epoch2datetime(1273258009)) self.assertEqual(self.changes_added[1]["comments"], "hello!") self.assertEqual(self.changes_added[1]["files"], ["/etc/64a"]) self.assertEqual(self.changes_added[1]["src"], "git") self.assertEqual(self.changes_added[2]["author"], "by:9118f4ab") self.assertEqual(self.changes_added[2]["when_timestamp"], epoch2datetime(1273258009)) self.assertEqual(self.changes_added[2]["comments"], "hello!") self.assertEqual(self.changes_added[2]["files"], ["/etc/911"]) self.assertEqual(self.changes_added[2]["src"], "git")
def check_changes(_): self.assertEqual(self.poller.lastRev, { 'master': '4423cdbcbb89c14e50dd5f4152415afd686c5241' }) self.assertEqual(len(self.changes_added), 2) self.assertEqual(self.changes_added[0]['author'], 'by:4423cdbc') self.assertEqual(self.changes_added[0]['when_timestamp'], epoch2datetime(1273258009)) self.assertEqual(self.changes_added[0]['comments'], 'hello!') self.assertEqual(self.changes_added[0]['branch'], 'master') self.assertEqual(self.changes_added[0]['files'], [ '/etc/442' ]) self.assertEqual(self.changes_added[0]['src'], 'git') self.assertEqual(self.changes_added[1]['author'], 'by:64a5dc2a') self.assertEqual(self.changes_added[1]['when_timestamp'], epoch2datetime(1273258009)) self.assertEqual(self.changes_added[1]['comments'], 'hello!') self.assertEqual(self.changes_added[1]['files'], [ '/etc/64a' ]) self.assertEqual(self.changes_added[1]['src'], 'git') self.assertAllCommandsRan() self.master.db.state.assertStateByClass( name=self.REPOURL, class_name='GitPoller', lastRev={ 'master': '4423cdbcbb89c14e50dd5f4152415afd686c5241' })
def check_changes(_): self.assertEqual(len(self.changes_added), 2) change = self.changes_added[0] self.assertEqual(change['revision'], '64a5dc2') self.assertEqual(change['author'], 'Joe Test <*****@*****.**>') self.assertEqual(change['when_timestamp'], epoch2datetime(1273258009)), self.assertEqual(change['files'], ['file1', 'file2']) self.assertEqual(change['src'], 'hg') self.assertEqual(change['branch'], 'default') self.assertEqual(change['comments'], os.linesep.join(('Multi-line', 'Comment for rev 0'))) change = self.changes_added[1] self.assertEqual(change['revision'], '4423cdb') self.assertEqual(change['author'], 'Bob Test <*****@*****.**>') self.assertEqual(change['when_timestamp'], epoch2datetime(1273258100)), self.assertEqual(change['files'], ['file1', 'dir/file2']) self.assertEqual(change['src'], 'hg') self.assertEqual(change['branch'], 'default') self.assertEqual(change['comments'], 'This is rev 1')
def test_claimBuildRequests_single_explicit_claimed_at(self): return self.do_test_claimBuildRequests([ fakedb.BuildRequest( id=44, buildsetid=self.BSID, builderid=self.BLDRID1), ], 1300305712, [44], [(44, epoch2datetime(14000000), self.MASTER_ID)], claimed_at=epoch2datetime(14000000))
def cb(_): self.assertAllCommandsRan() self.assertEqual(self.poller.lastRev, { 'master': '4423cdbcbb89c14e50dd5f4152415afd686c5241', 'release': '9118f4ab71963d23d02d4bdc54876ac8bf05acf2' }) self.assertEqual(len(self.changes_added), 3) self.assertEqual(self.changes_added[0]['author'], 'by:4423cdbc') self.assertEqual(self.changes_added[0]['when_timestamp'], epoch2datetime(1273258009)) self.assertEqual(self.changes_added[0]['comments'], 'hello!') self.assertEqual(self.changes_added[0]['branch'], 'master') self.assertEqual(self.changes_added[0]['files'], [ '/etc/442' ]) self.assertEqual(self.changes_added[0]['src'], 'git') self.assertEqual(self.changes_added[1]['author'], 'by:64a5dc2a') self.assertEqual(self.changes_added[1]['when_timestamp'], epoch2datetime(1273258009)) self.assertEqual(self.changes_added[1]['comments'], 'hello!') self.assertEqual(self.changes_added[1]['files'], [ '/etc/64a' ]) self.assertEqual(self.changes_added[1]['src'], 'git') self.assertEqual(self.changes_added[2]['author'], 'by:9118f4ab') self.assertEqual(self.changes_added[2]['when_timestamp'], epoch2datetime(1273258009)) self.assertEqual(self.changes_added[2]['comments'], 'hello!') self.assertEqual(self.changes_added[2]['files'], [ '/etc/911' ]) self.assertEqual(self.changes_added[2]['src'], 'git')
def cb(_): self.assertAllCommandsRan() # The release branch id should remain unchanged, # because it was ignorned. self.assertEqual( self.poller.lastRev, { "refs/heads/master": "4423cdbcbb89c14e50dd5f4152415afd686c5241", "refs/heads/release": "bf0b01df6d00ae8d1ffa0b2e2acbe642a6cd35d5", }, ) self.assertEqual(len(self.changes_added), 2) self.assertEqual(self.changes_added[0]["author"], "by:4423cdbc") self.assertEqual(self.changes_added[0]["when_timestamp"], epoch2datetime(1273258009)) self.assertEqual(self.changes_added[0]["comments"], "hello!") self.assertEqual(self.changes_added[0]["branch"], "master") self.assertEqual(self.changes_added[0]["files"], ["/etc/442"]) self.assertEqual(self.changes_added[0]["src"], "git") self.assertEqual(self.changes_added[1]["author"], "by:64a5dc2a") self.assertEqual(self.changes_added[1]["when_timestamp"], epoch2datetime(1273258009)) self.assertEqual(self.changes_added[1]["comments"], "hello!") self.assertEqual(self.changes_added[1]["files"], ["/etc/64a"]) self.assertEqual(self.changes_added[1]["src"], "git")
def test_masterActive(self): self.reactor.advance(60) self.master.db.insertTestData([ fakedb.Master(id=13, name='myname', active=0, last_active=0), fakedb.Master(id=14, name='other', active=1, last_active=0), fakedb.Master(id=15, name='other2', active=1, last_active=0), ]) # initial checkin yield self.rtype.masterActive(name='myname', masterid=13) master = yield self.master.db.masters.getMaster(13) self.assertEqual(master, dict(id=13, name='myname', active=True, last_active=epoch2datetime(60))) self.assertEqual(self.master.mq.productions, [ (('masters', '13', 'started'), dict(masterid=13, name='myname', active=True)), ]) self.master.mq.productions = [] # updated checkin time, re-activation self.reactor.advance(60) yield self.master.db.masters.markMasterInactive(13) yield self.rtype.masterActive('myname', masterid=13) master = yield self.master.db.masters.getMaster(13) self.assertEqual(master, dict(id=13, name='myname', active=True, last_active=epoch2datetime(120))) self.assertEqual(self.master.mq.productions, [ (('masters', '13', 'started'), dict(masterid=13, name='myname', active=True)), ]) self.master.mq.productions = []
def test_startStep(self): self.patch(reactor, 'seconds', lambda: TIME1) yield self.master.db.steps.addStep(buildid=10, name=u'ten', state_strings=[u'pending']) yield self.rtype.startStep(stepid=100) msgBody = { 'buildid': 10, 'complete': False, 'complete_at': None, 'name': u'ten', 'number': 0, 'results': None, 'started_at': epoch2datetime(TIME1), 'state_strings': [u'pending'], 'stepid': 100, 'urls': [], } self.master.mq.assertProductions([ (('builds', '10', 'steps', str(100), 'started'), msgBody), (('steps', str(100), 'started'), msgBody), ]) step = yield self.master.db.steps.getStep(100) self.assertEqual(step, { 'buildid': 10, 'complete_at': None, 'id': 100, 'name': u'ten', 'number': 0, 'results': None, 'started_at': epoch2datetime(TIME1), 'state_strings': [u'pending'], 'urls': [], })
def test_schedulerEnable(self): SOMETIME = 1348971992 yield self.master.db.insertTestData([ fakedb.Master(id=22, active=0, last_active=SOMETIME), fakedb.Scheduler(id=13, name='some:scheduler'), fakedb.SchedulerMaster(schedulerid=13, masterid=22), ]) yield self.rtype.schedulerEnable(13, False) self.master.mq.assertProductions( [(('schedulers', '13', 'updated'), {'enabled': False, 'master': {'active': False, 'last_active': epoch2datetime(SOMETIME), 'masterid': 22, 'name': 'some:master'}, 'name': 'some:scheduler', 'schedulerid': 13})]) yield self.rtype.schedulerEnable(13, True) self.master.mq.assertProductions( [(('schedulers', '13', 'updated'), {'enabled': True, 'master': {'active': False, 'last_active': epoch2datetime(SOMETIME), 'masterid': 22, 'name': 'some:master'}, 'name': 'some:scheduler', 'schedulerid': 13})])
def check(sourcestamps): self.assertEqual(sorted(sourcestamps), sorted([{ 'branch': u'b', 'codebase': u'c', 'patch_author': u'bar', 'patchid': 99, 'patch_body': 'hello, world', 'patch_comment': u'foo', 'patch_level': 3, 'patch_subdir': u'/foo', 'project': u'p', 'repository': u'rep', 'revision': u'r', 'created_at': epoch2datetime(CREATED_AT), 'ssid': 234, }, { 'branch': u'b2', 'codebase': u'c2', 'patchid': None, 'patch_author': None, 'patch_body': None, 'patch_comment': None, 'patch_level': None, 'patch_subdir': None, 'project': u'p2', 'repository': u'rep2', 'revision': u'r2', 'created_at': epoch2datetime(CREATED_AT + 10), 'ssid': 235, }]))
def cb(_): self.assertAllCommandsRan() # The release branch id should remain unchanged, # because it was ignorned. self.assertEqual(self.poller.lastRev, { 'refs/heads/master': '4423cdbcbb89c14e50dd5f4152415afd686c5241', 'refs/heads/release': 'bf0b01df6d00ae8d1ffa0b2e2acbe642a6cd35d5' }) self.assertEqual(len(self.changes_added), 2) self.assertEqual(self.changes_added[0]['author'], 'by:4423cdbc') self.assertEqual(self.changes_added[0]['when_timestamp'], epoch2datetime(1273258009)) self.assertEqual(self.changes_added[0]['comments'], 'hello!') self.assertEqual(self.changes_added[0]['branch'], 'master') self.assertEqual(self.changes_added[0]['files'], ['/etc/442']) self.assertEqual(self.changes_added[0]['src'], 'git') self.assertEqual(self.changes_added[1]['author'], 'by:64a5dc2a') self.assertEqual(self.changes_added[1]['when_timestamp'], epoch2datetime(1273258009)) self.assertEqual(self.changes_added[1]['comments'], 'hello!') self.assertEqual(self.changes_added[1]['files'], ['/etc/64a']) self.assertEqual(self.changes_added[1]['src'], 'git')
def test_addChange_withParent(self): yield self.insertTestData(self.change14_rows) clock = task.Clock() clock.advance(SOMETIME) changeid = yield self.db.changes.addChange( author=u"delanne", files=[], comments=u"child of changeid14", revision=u"50adad56", when_timestamp=epoch2datetime(OTHERTIME), branch=u"warnerdb", category=u"devel", revlink=None, properties={}, repository=u"git://warner", codebase=u"mainapp", project=u"Buildbot", _reactor=clock, ) chdict = yield self.db.changes.getChange(changeid) validation.verifyDbDict(self, "chdict", chdict) chdict = chdict.copy() ss = yield self.db.sourcestamps.getSourceStamp(chdict["sourcestampid"]) chdict["sourcestampid"] = ss self.assertEqual( chdict, { "author": u"delanne", "branch": u"warnerdb", "category": u"devel", "changeid": changeid, "parent_changeids": [14], "codebase": u"mainapp", "comments": u"child of changeid14", "files": [], "project": u"Buildbot", "properties": {}, "repository": u"git://warner", "revision": u"50adad56", "revlink": None, "sourcestampid": { "branch": u"warnerdb", "codebase": u"mainapp", "created_at": epoch2datetime(SOMETIME), "patch_author": None, "patch_body": None, "patch_comment": None, "patch_level": None, "patch_subdir": None, "patchid": None, "project": u"Buildbot", "repository": u"git://warner", "revision": u"50adad56", "ssid": ss["ssid"], }, "when_timestamp": epoch2datetime(OTHERTIME), }, )
def check(results): self.assertEqual(sorted( (r['brid'], r['claimed_at'], r['mine']) for r in results ), [ (44, epoch2datetime(1300103810), True), (45, epoch2datetime(1300103810), False), ])
def check(bdicts): self.assertEqual(sorted(bdicts), sorted([ dict(bid=50, number=5, brid=42, start_time=epoch2datetime(1304262222), finish_time=None), dict(bid=52, number=7, brid=42, start_time=epoch2datetime(1304262224), finish_time=epoch2datetime(1304262235)), ]))
def test_completeBuildRequests_explicit_time(self): return self.do_test_completeBuildRequests([ fakedb.BuildRequest(id=44, buildsetid=self.BSID), fakedb.BuildRequestClaim(brid=44, objectid=self.MASTER_ID, claimed_at=1300103810), ], 1300305712, [ (44, True, 7, epoch2datetime(999999)) ], complete_at=epoch2datetime(999999))
def check(results): self.assertEqual(sorted( (r['buildrequestid'], r['claimed_at'], r['claimed_by_masterid']) for r in results ), [ (44, epoch2datetime(1300103810), self.MASTER_ID), (45, epoch2datetime(1300103810), self.OTHER_MASTER_ID), ])
def test_addChange_getChange(self): clock = task.Clock() clock.advance(SOMETIME) changeid = yield self.db.changes.addChange( author=u"dustin", files=[], comments=u"fix spelling", revision=u"2d6caa52", when_timestamp=epoch2datetime(OTHERTIME), branch=u"master", category=None, revlink=None, properties={}, repository=u"repo://", codebase=u"cb", project=u"proj", _reactor=clock, ) chdict = yield self.db.changes.getChange(changeid) validation.verifyDbDict(self, "chdict", chdict) chdict = chdict.copy() ss = yield self.db.sourcestamps.getSourceStamp(chdict["sourcestampid"]) chdict["sourcestampid"] = ss self.assertEqual( chdict, { "author": u"dustin", "branch": u"master", "category": None, "changeid": changeid, "parent_changeids": [], "codebase": u"cb", "comments": u"fix spelling", "files": [], "project": u"proj", "properties": {}, "repository": u"repo://", "revision": u"2d6caa52", "revlink": None, "sourcestampid": { "branch": u"master", "codebase": u"cb", "patch_author": None, "patch_body": None, "patch_comment": None, "patch_level": None, "patch_subdir": None, "patchid": None, "project": u"proj", "repository": u"repo://", "revision": u"2d6caa52", "created_at": epoch2datetime(SOMETIME), "ssid": ss["ssid"], }, "when_timestamp": epoch2datetime(OTHERTIME), }, )
def test_addChange_withParent(self): yield self.insertTestData(self.change14_rows) clock = task.Clock() clock.advance(SOMETIME) changeid = yield self.db.changes.addChange( author=u'delanne', files=[], comments=u'child of changeid14', revision=u'50adad56', when_timestamp=epoch2datetime(OTHERTIME), branch=u'warnerdb', category=u'devel', revlink=None, properties={}, repository=u'git://warner', codebase=u'mainapp', project=u'Buildbot', _reactor=clock) chdict = yield self.db.changes.getChange(changeid) validation.verifyDbDict(self, 'chdict', chdict) chdict = chdict.copy() ss = yield self.db.sourcestamps.getSourceStamp(chdict['sourcestampid']) chdict['sourcestampid'] = ss self.assertEqual(chdict, { 'author': u'delanne', 'branch': u'warnerdb', 'category': u'devel', 'changeid': changeid, 'parent_changeids': [14], 'codebase': u'mainapp', 'comments': u'child of changeid14', 'files': [], 'project': u'Buildbot', 'properties': {}, 'repository': u'git://warner', 'revision': u'50adad56', 'revlink': None, 'sourcestampid': { 'branch': u'warnerdb', 'codebase': u'mainapp', 'created_at': epoch2datetime(SOMETIME), 'patch_author': None, 'patch_body': None, 'patch_comment': None, 'patch_level': None, 'patch_subdir': None, 'patchid': None, 'project': u'Buildbot', 'repository': u'git://warner', 'revision': u'50adad56', 'ssid': ss['ssid'] }, 'when_timestamp': epoch2datetime(OTHERTIME), })
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 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 test_claimBuildRequests_multiple(self): return self.do_test_claimBuildRequests([ fakedb.BuildRequest(id=44, buildsetid=self.BSID), fakedb.BuildRequest(id=45, buildsetid=self.BSID), fakedb.BuildRequest(id=46, buildsetid=self.BSID), ], 1300305712, [ 44, 46 ], [ (44, epoch2datetime(1300305712), True), (45, None, False), (46, epoch2datetime(1300305712), True), ])
def test_addChange_getChange(self): clock = task.Clock() clock.advance(SOMETIME) changeid = yield self.db.changes.addChange( author=u'dustin', files=[], comments=u'fix spelling', revision=u'2d6caa52', when_timestamp=epoch2datetime(OTHERTIME), branch=u'master', category=None, revlink=None, properties={}, repository=u'repo://', codebase=u'cb', project=u'proj', _reactor=clock) chdict = yield self.db.changes.getChange(changeid) validation.verifyDbDict(self, 'chdict', chdict) chdict = chdict.copy() ss = yield self.db.sourcestamps.getSourceStamp(chdict['sourcestampid']) chdict['sourcestampid'] = ss self.assertEqual(chdict, { 'author': u'dustin', 'branch': u'master', 'category': None, 'changeid': changeid, 'parent_changeids': [], 'codebase': u'cb', 'comments': u'fix spelling', 'files': [], 'project': u'proj', 'properties': {}, 'repository': u'repo://', 'revision': u'2d6caa52', 'revlink': None, 'sourcestampid': { 'branch': u'master', 'codebase': u'cb', 'patch_author': None, 'patch_body': None, 'patch_comment': None, 'patch_level': None, 'patch_subdir': None, 'patchid': None, 'project': u'proj', 'repository': u'repo://', 'revision': u'2d6caa52', 'created_at': epoch2datetime(SOMETIME), 'ssid': ss['ssid'], }, 'when_timestamp': epoch2datetime(OTHERTIME), })
def _builddictFromRow(self, row): return dict( id=row.id, number=row.number, builderid=row.builderid, buildrequestid=row.buildrequestid, workerid=row.workerid, masterid=row.masterid, started_at=epoch2datetime(row.started_at), complete_at=epoch2datetime(row.complete_at), state_string=row.state_string, results=row.results)
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 _stepdictFromRow(self, row): return dict( id=row.id, number=row.number, name=row.name, buildid=row.buildid, started_at=epoch2datetime(row.started_at), complete_at=epoch2datetime(row.complete_at), state_string=row.state_string, results=row.results, urls=json.loads(row.urls_json), hidden=bool(row.hidden))
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 test_finishBuild(self): self.reactor.advance(TIME4) yield self.insertTestData(self.backgroundData + [self.threeBuilds[0]]) yield self.db.builds.finishBuild(buildid=50, results=7) bdict = yield self.db.builds.getBuild(50) validation.verifyDbDict(self, 'dbbuilddict', bdict) self.assertEqual(bdict, dict(id=50, number=5, buildrequestid=42, masterid=88, builderid=77, workerid=13, started_at=epoch2datetime(TIME1), complete_at=epoch2datetime(TIME4), state_string='build 5', results=7))
def check(_): self.assertEqual(len(self.changes_added), 2) self.assertEqual(self.changes_added[0]['author'], 'by:4423cdbc') self.assertEqual(self.changes_added[0]['when_timestamp'], epoch2datetime(1273258009)) self.assertEqual(self.changes_added[0]['comments'], 'hello!') self.assertEqual(self.changes_added[0]['branch'], 'master') self.assertEqual(self.changes_added[0]['files'], [ '/etc/442' ]) self.assertEqual(self.changes_added[1]['author'], 'by:64a5dc2a') self.assertEqual(self.changes_added[1]['when_timestamp'], epoch2datetime(1273258009)) self.assertEqual(self.changes_added[1]['comments'], 'hello!') self.assertEqual(self.changes_added[1]['files'], [ '/etc/64a' ])
def test_claimBuildRequests_multiple(self): return self.do_test_claimBuildRequests( [ fakedb.BuildRequest(id=44, buildsetid=self.BSID, builderid=self.BLDRID1), fakedb.BuildRequest(id=45, buildsetid=self.BSID, builderid=self.BLDRID1), fakedb.BuildRequest(id=46, buildsetid=self.BSID, builderid=self.BLDRID1), ], 1300305712, [44, 46], [ (44, epoch2datetime(1300305712), self.MASTER_ID), (45, None, None), (46, epoch2datetime(1300305712), self.MASTER_ID), ])
def test_finishBuild(self): clock = task.Clock() clock.advance(TIME4) yield self.insertTestData(self.backgroundData + [self.threeBuilds[0]]) yield self.db.builds.finishBuild(buildid=50, results=7, _reactor=clock) bdict = yield self.db.builds.getBuild(50) validation.verifyDbDict(self, 'builddict', bdict) self.assertEqual(bdict, dict(id=50, number=5, buildrequestid=42, masterid=88, builderid=77, buildslaveid=13, started_at=epoch2datetime(TIME1), complete_at=epoch2datetime(TIME4), state_strings=[u'test'], results=7))
class Build(interfaces.InterfaceTests, unittest.TestCase): new_build_event = { 'builderid': 10, 'buildid': 100, 'buildrequestid': 13, 'buildslaveid': 20, 'complete': False, 'complete_at': None, 'masterid': 824, 'number': 1, 'results': None, 'started_at': epoch2datetime(1), 'state_string': u'created' } def setUp(self): self.master = fakemaster.make_master(testcase=self, wantMq=True, wantDb=True, wantData=True) self.rtype = builds.Build(self.master) @defer.inlineCallbacks def do_test_callthrough(self, dbMethodName, method, exp_args=None, exp_kwargs=None, *args, **kwargs): rv = (1, 2) m = mock.Mock(return_value=defer.succeed(rv)) setattr(self.master.db.builds, dbMethodName, m) res = yield method(*args, **kwargs) self.assertIdentical(res, rv) m.assert_called_with(*(exp_args or args), **(exp_kwargs or kwargs)) @defer.inlineCallbacks def do_test_event(self, method, exp_events=[], *args, **kwargs): self.patch(reactor, "seconds", lambda: 1) yield method(*args, **kwargs) self.master.mq.assertProductions(exp_events) def test_signature_newBuild(self): @self.assertArgSpecMatches( self.master.data.updates.newBuild, # fake self.rtype.newBuild) # real def newBuild(self, builderid, buildrequestid, buildslaveid): pass def test_newBuild(self): return self.do_test_callthrough('addBuild', self.rtype.newBuild, builderid=10, buildrequestid=13, buildslaveid=20, exp_kwargs=dict( builderid=10, buildrequestid=13, buildslaveid=20, masterid=self.master.masterid, state_string=u'created')) def test_newBuildEvent(self): return self.do_test_event(self.rtype.newBuild, builderid=10, buildrequestid=13, buildslaveid=20, exp_events=[(('builders', '10', 'builds', '1', 'new'), self.new_build_event), (('builds', '100', 'new'), self.new_build_event)]) def test_signature_setBuildStateString(self): @self.assertArgSpecMatches( self.master.data.updates.setBuildStateString, # fake self.rtype.setBuildStateString) # real def setBuildStateString(self, buildid, state_string): pass def test_setBuildStateString(self): return self.do_test_callthrough('setBuildStateString', self.rtype.setBuildStateString, buildid=10, state_string=u'a b') def test_signature_finishBuild(self): @self.assertArgSpecMatches( self.master.data.updates.finishBuild, # fake self.rtype.finishBuild) # real def finishBuild(self, buildid, results): pass def test_finishBuild(self): return self.do_test_callthrough('finishBuild', self.rtype.finishBuild, buildid=15, results=3)
def addChange(self, author=None, files=None, comments='', is_dir=0, links=None, revision=None, when_timestamp=None, branch=None, category=None, revlink='', properties={}, repository='', project='', _reactor=reactor): """Add the a Change with the given attributes to the database; returns a Change instance via a deferred. All arguments are keyword arguments. @param author: the author of this change @type author: unicode string @param files: a list of filenames that were changed @type branch: list of unicode strings @param comments: user comments on the change @type branch: unicode string @param is_dir: deprecated @param links: a list of links related to this change, e.g., to web viewers or review pages @type links: list of unicode strings @param revision: the revision identifier for this change @type revision: unicode string @param when_timestamp: when this change occurred, or the current time if None @type when_timestamp: datetime instance or None @param branch: the branch on which this change took place @type branch: unicode string @param category: category for this change (arbitrary use by Buildbot users) @type category: unicode string @param revlink: link to a web view of this revision @type revlink: unicode string @param properties: properties to set on this change @type properties: dictionary, where values are tuples of (value, source). At the moment, the source must be C{'Change'}, although this may be relaxed in later versions. @param repository: the repository in which this change took place @type repository: unicode string @param project: the project this change is a part of @type project: unicode string @param _reactor: for testing @returns: new change's ID via Deferred """ assert project is not None, "project must be a string, not None" assert repository is not None, "repository must be a string, not None" if when_timestamp is None: when_timestamp = epoch2datetime(_reactor.seconds()) # verify that source is 'Change' for each property for pv in properties.values(): assert pv[1] == 'Change', ("properties must be qualified with" "source 'Change'") def thd(conn): # note that in a read-uncommitted database like SQLite this # transaction does not buy atomicitiy - other database users may # still come across a change without its links, files, properties, # etc. That's OK, since we don't announce the change until it's # all in the database, but beware. transaction = conn.begin() ins = self.db.model.changes.insert() r = conn.execute( ins, dict(author=author, comments=comments[:1024], is_dir=is_dir, branch=branch, revision=revision, revlink=revlink, when_timestamp=datetime2epoch(when_timestamp), category=category, repository=repository, project=project)) changeid = r.inserted_primary_key[0] if links: ins = self.db.model.change_links.insert() conn.execute(ins, [dict(changeid=changeid, link=l) for l in links]) if files: ins = self.db.model.change_files.insert() conn.execute( ins, [dict(changeid=changeid, filename=f) for f in files]) if properties: ins = self.db.model.change_properties.insert() conn.execute(ins, [ dict(changeid=changeid, property_name=k, property_value=json.dumps(v)) for k, v in properties.iteritems() ]) transaction.commit() return changeid d = self.db.pool.do(thd) return d
def check(rqtime): self.assertEqual(rqtime, epoch2datetime(1000))
class Change(interfaces.InterfaceTests, unittest.TestCase): changeEvent = { 'author': u'warner', 'branch': u'warnerdb', 'category': u'devel', 'codebase': u'', 'comments': u'fix whitespace', 'changeid': 500, 'files': [u'master/buildbot/__init__.py'], 'project': u'Buildbot', 'properties': {u'foo': (20, u'Change')}, 'repository': u'git://warner', 'revision': u'0e92a098b', 'revlink': u'http://warner/0e92a098b', 'when_timestamp': 256738404, 'sourcestamp': { 'branch': u'warnerdb', 'codebase': u'', 'patch': None, 'project': u'Buildbot', 'repository': u'git://warner', 'revision': u'0e92a098b', 'created_at': epoch2datetime(10000000), 'ssid': 100, }, # uid } def setUp(self): self.master = fakemaster.make_master(wantMq=True, wantDb=True, wantData=True, testcase=self) self.rtype = changes.Change(self.master) def test_signature_addChange(self): @self.assertArgSpecMatches( self.master.data.updates.addChange, # fake self.rtype.addChange) # real def addChange(self, files=None, comments=None, author=None, revision=None, when_timestamp=None, branch=None, category=None, revlink=u'', properties={}, repository=u'', codebase=None, project=u'', src=None): pass def do_test_addChange(self, kwargs, expectedRoutingKey, expectedMessage, expectedRow, expectedChangeUsers=[]): clock = task.Clock() clock.advance(10000000) d = self.rtype.addChange(_reactor=clock, **kwargs) def check(changeid): self.assertEqual(changeid, 500) # check the correct message was received self.master.mq.assertProductions([ (expectedRoutingKey, expectedMessage), ]) # and that the correct data was inserted into the db self.master.db.changes.assertChange(500, expectedRow) self.master.db.changes.assertChangeUsers(500, expectedChangeUsers) d.addCallback(check) return d def test_addChange(self): # src and codebase are default here kwargs = dict(author=u'warner', branch=u'warnerdb', category=u'devel', comments=u'fix whitespace', files=[u'master/buildbot/__init__.py'], project=u'Buildbot', repository=u'git://warner', revision=u'0e92a098b', revlink=u'http://warner/0e92a098b', when_timestamp=256738404, properties={u'foo': 20}) expectedRoutingKey = ('changes', '500', 'new') expectedMessage = self.changeEvent expectedRow = fakedb.Change( changeid=500, author='warner', comments='fix whitespace', branch='warnerdb', revision='0e92a098b', revlink='http://warner/0e92a098b', when_timestamp=256738404, category='devel', repository='git://warner', codebase='', project='Buildbot', sourcestampid=100, ) return self.do_test_addChange(kwargs, expectedRoutingKey, expectedMessage, expectedRow) def test_addChange_src_codebase(self): createUserObject = mock.Mock(spec=users.createUserObject) createUserObject.return_value = defer.succeed(123) self.patch(users, 'createUserObject', createUserObject) kwargs = dict(author=u'warner', branch=u'warnerdb', category=u'devel', comments=u'fix whitespace', files=[u'master/buildbot/__init__.py'], project=u'Buildbot', repository=u'git://warner', revision=u'0e92a098b', revlink=u'http://warner/0e92a098b', when_timestamp=256738404, properties={u'foo': 20}, src=u'git', codebase=u'cb') expectedRoutingKey = ('changes', '500', 'new') expectedMessage = { 'author': u'warner', 'branch': u'warnerdb', 'category': u'devel', 'codebase': u'cb', 'comments': u'fix whitespace', 'changeid': 500, 'files': [u'master/buildbot/__init__.py'], 'project': u'Buildbot', 'properties': {u'foo': (20, u'Change')}, 'repository': u'git://warner', 'revision': u'0e92a098b', 'revlink': u'http://warner/0e92a098b', 'when_timestamp': 256738404, 'sourcestamp': { 'branch': u'warnerdb', 'codebase': u'cb', 'patch': None, 'project': u'Buildbot', 'repository': u'git://warner', 'revision': u'0e92a098b', 'created_at': epoch2datetime(10000000), 'ssid': 100, }, # uid } expectedRow = fakedb.Change( changeid=500, author='warner', comments='fix whitespace', branch='warnerdb', revision='0e92a098b', revlink='http://warner/0e92a098b', when_timestamp=256738404, category='devel', repository='git://warner', codebase='cb', project='Buildbot', sourcestampid=100, ) d = self.do_test_addChange(kwargs, expectedRoutingKey, expectedMessage, expectedRow, expectedChangeUsers=[123]) @d.addCallback def check(_): createUserObject.assert_called_once_with( self.master, 'warner', 'git') return d def test_addChange_src_codebaseGenerator(self): self.master.config = mock.Mock(name='master.config') self.master.config.codebaseGenerator = \ lambda change: 'cb-%s' % change['category'] kwargs = dict(author=u'warner', branch=u'warnerdb', category=u'devel', comments=u'fix whitespace', files=[u'master/buildbot/__init__.py'], project=u'Buildbot', repository=u'git://warner', revision=u'0e92a098b', revlink=u'http://warner/0e92a098b', when_timestamp=256738404, properties={u'foo': 20}) expectedRoutingKey = ('changes', '500', 'new') expectedMessage = { 'author': u'warner', 'branch': u'warnerdb', 'category': u'devel', 'codebase': u'cb-devel', 'comments': u'fix whitespace', 'changeid': 500, 'files': [u'master/buildbot/__init__.py'], 'project': u'Buildbot', 'properties': {u'foo': (20, u'Change')}, 'repository': u'git://warner', 'revision': u'0e92a098b', 'revlink': u'http://warner/0e92a098b', 'when_timestamp': 256738404, 'sourcestamp': { 'branch': u'warnerdb', 'codebase': u'cb-devel', 'patch': None, 'project': u'Buildbot', 'repository': u'git://warner', 'revision': u'0e92a098b', 'created_at': epoch2datetime(10000000), 'ssid': 100, }, # uid } expectedRow = fakedb.Change( changeid=500, author='warner', comments='fix whitespace', branch='warnerdb', revision='0e92a098b', revlink='http://warner/0e92a098b', when_timestamp=256738404, category='devel', repository='git://warner', codebase='cb-devel', project='Buildbot', sourcestampid=100, ) return self.do_test_addChange(kwargs, expectedRoutingKey, expectedMessage, expectedRow)
class Tests(TestReactorMixin, interfaces.InterfaceTests): # common sample data backgroundData = [ fakedb.Worker(id=47, name='linux'), fakedb.Buildset(id=20), fakedb.Builder(id=88, name='b1'), fakedb.BuildRequest(id=41, buildsetid=20, builderid=88), fakedb.Master(id=88), fakedb.Build(id=30, buildrequestid=41, number=7, masterid=88, builderid=88, workerid=47), fakedb.Build(id=31, buildrequestid=41, number=8, masterid=88, builderid=88, workerid=47), ] stepRows = [ fakedb.Step(id=70, number=0, name='one', buildid=30, started_at=TIME1, complete_at=TIME2, state_string='test', results=0), fakedb.Step(id=71, number=1, name='two', buildid=30, started_at=TIME2, complete_at=TIME3, state_string='test', results=2, urls_json='["http://url"]', hidden=1), fakedb.Step(id=72, number=2, name='three', buildid=30, started_at=TIME3), fakedb.Step(id=73, number=0, name='wrong-build', buildid=31), ] stepDicts = [ { 'id': 70, 'buildid': 30, 'number': 0, 'name': 'one', 'results': 0, 'started_at': epoch2datetime(TIME1), 'complete_at': epoch2datetime(TIME2), 'state_string': 'test', 'urls': [], 'hidden': False }, { 'id': 71, 'buildid': 30, 'number': 1, 'name': 'two', 'results': 2, 'started_at': epoch2datetime(TIME2), 'complete_at': epoch2datetime(TIME3), 'state_string': 'test', 'urls': ['http://url'], 'hidden': True }, { 'id': 72, 'buildid': 30, 'number': 2, 'name': 'three', 'results': None, 'started_at': epoch2datetime(TIME3), 'complete_at': None, 'state_string': '', 'urls': [], 'hidden': False }, ] def setUp(self): self.setUpTestReactor() # signature tests def test_signature_getStep(self): @self.assertArgSpecMatches(self.db.steps.getStep) def getStep(self, stepid=None, buildid=None, number=None, name=None): pass def test_signature_getSteps(self): @self.assertArgSpecMatches(self.db.steps.getSteps) def getSteps(self, buildid): pass def test_signature_addStep(self): @self.assertArgSpecMatches(self.db.steps.addStep) def addStep(self, buildid, name, state_string): pass def test_signature_startStep(self): @self.assertArgSpecMatches(self.db.steps.startStep) def addStep(self, stepid): pass def test_signature_setStepStateString(self): @self.assertArgSpecMatches(self.db.steps.setStepStateString) def setStepStateString(self, stepid, state_string): pass def test_signature_finishStep(self): @self.assertArgSpecMatches(self.db.steps.finishStep) def finishStep(self, stepid, results, hidden): pass # method tests @defer.inlineCallbacks def test_getStep(self): yield self.insertTestData(self.backgroundData + [self.stepRows[0]]) stepdict = yield self.db.steps.getStep(70) validation.verifyDbDict(self, 'stepdict', stepdict) self.assertEqual(stepdict, self.stepDicts[0]) @defer.inlineCallbacks def test_getStep_missing(self): stepdict = yield self.db.steps.getStep(50) self.assertEqual(stepdict, None) @defer.inlineCallbacks def test_getStep_number(self): yield self.insertTestData(self.backgroundData + [self.stepRows[1]]) stepdict = yield self.db.steps.getStep(buildid=30, number=1) validation.verifyDbDict(self, 'stepdict', stepdict) self.assertEqual(stepdict['id'], 71) @defer.inlineCallbacks def test_getStep_number_missing(self): yield self.insertTestData(self.backgroundData + [self.stepRows[1]]) stepdict = yield self.db.steps.getStep(buildid=30, number=9) self.assertEqual(stepdict, None) @defer.inlineCallbacks def test_getStep_name(self): yield self.insertTestData(self.backgroundData + [self.stepRows[2]]) stepdict = yield self.db.steps.getStep(buildid=30, name='three') validation.verifyDbDict(self, 'stepdict', stepdict) self.assertEqual(stepdict['id'], 72) @defer.inlineCallbacks def test_getStep_name_missing(self): yield self.insertTestData(self.backgroundData + [self.stepRows[2]]) stepdict = yield self.db.steps.getStep(buildid=30, name='five') self.assertEqual(stepdict, None) @defer.inlineCallbacks def test_getStep_invalid(self): d = self.db.steps.getStep(buildid=30) yield self.assertFailure(d, RuntimeError) @defer.inlineCallbacks def test_getSteps(self): yield self.insertTestData(self.backgroundData + self.stepRows) stepdicts = yield self.db.steps.getSteps(buildid=30) [ validation.verifyDbDict(self, 'stepdict', stepdict) for stepdict in stepdicts ] self.assertEqual(stepdicts, self.stepDicts[:3]) @defer.inlineCallbacks def test_getSteps_none(self): yield self.insertTestData(self.backgroundData + self.stepRows) stepdicts = yield self.db.steps.getSteps(buildid=33) self.assertEqual(stepdicts, []) @defer.inlineCallbacks def test_addStep_getStep(self): self.reactor.advance(TIME1) yield self.insertTestData(self.backgroundData) stepid, number, name = yield self.db.steps.addStep(buildid=30, name='new', state_string='new') yield self.db.steps.startStep(stepid=stepid) self.assertEqual((number, name), (0, 'new')) stepdict = yield self.db.steps.getStep(stepid=stepid) validation.verifyDbDict(self, 'stepdict', stepdict) self.assertEqual( stepdict, { 'id': stepid, 'buildid': 30, 'name': 'new', 'number': 0, 'started_at': epoch2datetime(TIME1), 'complete_at': None, 'results': None, 'state_string': 'new', 'urls': [], 'hidden': False }) @defer.inlineCallbacks def test_addStep_getStep_existing_step(self): self.reactor.advance(TIME1) yield self.insertTestData(self.backgroundData + [self.stepRows[0]]) stepid, number, name = yield self.db.steps.addStep(buildid=30, name='new', state_string='new') yield self.db.steps.startStep(stepid=stepid) self.assertEqual((number, name), (1, 'new')) stepdict = yield self.db.steps.getStep(stepid=stepid) validation.verifyDbDict(self, 'stepdict', stepdict) self.assertEqual(stepdict['number'], number) self.assertEqual(stepdict['name'], name) @defer.inlineCallbacks def test_addStep_getStep_name_collisions(self): self.reactor.advance(TIME1) yield self.insertTestData(self.backgroundData + [ fakedb.Step(id=73, number=0, name='new', buildid=30), fakedb.Step(id=74, number=1, name='new_1', buildid=30), fakedb.Step(id=75, number=2, name='new_2', buildid=30), fakedb.Step(id=76, number=3, name='new_step', buildid=30), ]) stepid, number, name = yield self.db.steps.addStep(buildid=30, name='new', state_string='new') yield self.db.steps.startStep(stepid=stepid) self.assertEqual((number, name), (4, 'new_3')) stepdict = yield self.db.steps.getStep(stepid=stepid) validation.verifyDbDict(self, 'stepdict', stepdict) self.assertEqual(stepdict['number'], number) self.assertEqual(stepdict['name'], name) @defer.inlineCallbacks def test_setStepStateString(self): yield self.insertTestData(self.backgroundData + [self.stepRows[2]]) yield self.db.steps.setStepStateString(stepid=72, state_string='aaa') stepdict = yield self.db.steps.getStep(stepid=72) self.assertEqual(stepdict['state_string'], 'aaa') @defer.inlineCallbacks def test_addURL(self): yield self.insertTestData(self.backgroundData + [self.stepRows[2]]) yield self.db.steps.addURL(stepid=72, name='foo', url='bar') stepdict = yield self.db.steps.getStep(stepid=72) self.assertEqual(stepdict['urls'], [{'name': 'foo', 'url': 'bar'}]) @defer.inlineCallbacks def test_addURL_race(self): yield self.insertTestData(self.backgroundData + [self.stepRows[2]]) yield defer.gatherResults([ # only a tiny sleep is required to see the problem. self.db.steps.addURL(stepid=72, name='foo', url='bar', _racehook=lambda: time.sleep(.01)), self.db.steps.addURL(stepid=72, name='foo2', url='bar2') ]) stepdict = yield self.db.steps.getStep(stepid=72) def urlKey(url): return url['name'] # order is not guaranteed though self.assertEqual( sorted(stepdict['urls'], key=urlKey), sorted([{ 'name': 'foo', 'url': 'bar' }, { 'name': 'foo2', 'url': 'bar2' }], key=urlKey)) @defer.inlineCallbacks def test_addURL_no_duplicate(self): yield self.insertTestData(self.backgroundData + [self.stepRows[2]]) yield defer.gatherResults([ self.db.steps.addURL(stepid=72, name='foo', url='bar'), self.db.steps.addURL(stepid=72, name='foo', url='bar') ]) stepdict = yield self.db.steps.getStep(stepid=72) self.assertEqual(stepdict['urls'], [{'name': 'foo', 'url': 'bar'}]) @defer.inlineCallbacks def test_finishStep(self): self.reactor.advance(TIME2) yield self.insertTestData(self.backgroundData + [self.stepRows[2]]) yield self.db.steps.finishStep(stepid=72, results=11, hidden=False) stepdict = yield self.db.steps.getStep(stepid=72) self.assertEqual(stepdict['results'], 11) self.assertEqual(stepdict['complete_at'], epoch2datetime(TIME2)) self.assertEqual(stepdict['hidden'], False) @defer.inlineCallbacks def test_finishStep_hidden(self): yield self.insertTestData(self.backgroundData + [self.stepRows[2]]) yield self.db.steps.finishStep(stepid=72, results=11, hidden=True) stepdict = yield self.db.steps.getStep(stepid=72) self.assertEqual(stepdict['hidden'], True)
def test_addChange_repository_revision(self): self.master.config = mock.Mock(name='master.config') self.master.config.revlink = lambda rev, repo: 'foo%sbar%sbaz' % (repo, rev) # revlink is default here kwargs = dict(author=u'warner', branch=u'warnerdb', category=u'devel', comments=u'fix whitespace', files=[u'master/buildbot/__init__.py'], project=u'Buildbot', repository=u'git://warner', codebase=u'', revision=u'0e92a098b', when_timestamp=256738404, properties={u'foo': 20}) expectedRoutingKey = ('changes', '500', 'new') # When no revlink is passed to addChange, but a repository and revision is # passed, the revlink should be constructed by calling the revlink callable # in the config. We thus expect a revlink of 'foogit://warnerbar0e92a098bbaz' expectedMessage = { 'author': u'warner', 'branch': u'warnerdb', 'category': u'devel', 'codebase': u'', 'comments': u'fix whitespace', 'changeid': 500, 'files': [u'master/buildbot/__init__.py'], 'parent_changeids': [], 'project': u'Buildbot', 'properties': { u'foo': (20, u'Change') }, 'repository': u'git://warner', 'revision': u'0e92a098b', 'revlink': u'foogit://warnerbar0e92a098bbaz', 'when_timestamp': 256738404, 'sourcestamp': { 'branch': u'warnerdb', 'codebase': u'', 'patch': None, 'project': u'Buildbot', 'repository': u'git://warner', 'revision': u'0e92a098b', 'created_at': epoch2datetime(10000000), 'ssid': 100, }, # uid } expectedRow = fakedb.Change( changeid=500, author='warner', comments='fix whitespace', branch='warnerdb', revision='0e92a098b', revlink='foogit://warnerbar0e92a098bbaz', when_timestamp=256738404, category='devel', repository='git://warner', codebase='', project='Buildbot', sourcestampid=100, ) return self.do_test_addChange(kwargs, expectedRoutingKey, expectedMessage, expectedRow)
def test_addChange_src_codebase(self): createUserObject = mock.Mock(spec=users.createUserObject) createUserObject.return_value = defer.succeed(123) self.patch(users, 'createUserObject', createUserObject) kwargs = dict(author=u'warner', branch=u'warnerdb', category=u'devel', comments=u'fix whitespace', files=[u'master/buildbot/__init__.py'], project=u'Buildbot', repository=u'git://warner', revision=u'0e92a098b', revlink=u'http://warner/0e92a098b', when_timestamp=256738404, properties={u'foo': 20}, src=u'git', codebase=u'cb') expectedRoutingKey = ('changes', '500', 'new') expectedMessage = { 'author': u'warner', 'branch': u'warnerdb', 'category': u'devel', 'codebase': u'cb', 'comments': u'fix whitespace', 'changeid': 500, 'files': [u'master/buildbot/__init__.py'], 'parent_changeids': [], 'project': u'Buildbot', 'properties': { u'foo': (20, u'Change') }, 'repository': u'git://warner', 'revision': u'0e92a098b', 'revlink': u'http://warner/0e92a098b', 'when_timestamp': 256738404, 'sourcestamp': { 'branch': u'warnerdb', 'codebase': u'cb', 'patch': None, 'project': u'Buildbot', 'repository': u'git://warner', 'revision': u'0e92a098b', 'created_at': epoch2datetime(10000000), 'ssid': 100, }, # uid } expectedRow = fakedb.Change( changeid=500, author='warner', comments='fix whitespace', branch='warnerdb', revision='0e92a098b', revlink='http://warner/0e92a098b', when_timestamp=256738404, category='devel', repository='git://warner', codebase='cb', project='Buildbot', sourcestampid=100, ) yield self.do_test_addChange(kwargs, expectedRoutingKey, expectedMessage, expectedRow, expectedChangeUsers=[123]) createUserObject.assert_called_once_with(self.master, 'warner', 'git')
def test_addChange(self): clock = task.Clock() clock.advance(SOMETIME) d = self.db.changes.addChange( author=u'dustin', files=[u'master/LICENSING.txt', u'worker/LICENSING.txt'], comments=u'fix spelling', revision=u'2d6caa52', when_timestamp=epoch2datetime(266738400), branch=u'master', category=None, revlink=None, properties={u'platform': (u'linux', 'Change')}, repository=u'', codebase=u'cb', project=u'', _reactor=clock) # check all of the columns of the four relevant tables def check_change(changeid): def thd(conn): self.assertEqual(changeid, 1) r = conn.execute(self.db.model.changes.select()) r = r.fetchall() self.assertEqual(len(r), 1) self.assertEqual(r[0].changeid, changeid) self.assertEqual(r[0].author, 'dustin') self.assertEqual(r[0].comments, 'fix spelling') self.assertEqual(r[0].branch, 'master') self.assertEqual(r[0].revision, '2d6caa52') self.assertEqual(r[0].when_timestamp, 266738400) self.assertEqual(r[0].category, None) self.assertEqual(r[0].repository, '') self.assertEqual(r[0].codebase, u'cb') self.assertEqual(r[0].project, '') self.assertEqual(r[0].sourcestampid, 1) return self.db.pool.do(thd) d.addCallback(check_change) def check_change_files(_): def thd(conn): query = self.db.model.change_files.select() query.where(self.db.model.change_files.c.changeid == 1) query.order_by(self.db.model.change_files.c.filename) r = conn.execute(query) r = r.fetchall() self.assertEqual(len(r), 2) self.assertEqual(r[0].filename, 'master/LICENSING.txt') self.assertEqual(r[1].filename, 'worker/LICENSING.txt') return self.db.pool.do(thd) d.addCallback(check_change_files) def check_change_properties(_): def thd(conn): query = self.db.model.change_properties.select() query.where(self.db.model.change_properties.c.changeid == 1) query.order_by(self.db.model.change_properties.c.property_name) r = conn.execute(query) r = r.fetchall() self.assertEqual(len(r), 1) self.assertEqual(r[0].property_name, 'platform') self.assertEqual(r[0].property_value, '["linux", "Change"]') return self.db.pool.do(thd) d.addCallback(check_change_properties) def check_change_users(_): def thd(conn): query = self.db.model.change_users.select() r = conn.execute(query) r = r.fetchall() self.assertEqual(len(r), 0) return self.db.pool.do(thd) d.addCallback(check_change_users) def check_change_sourcestamps(_): def thd(conn): query = self.db.model.sourcestamps.select() r = conn.execute(query) self.assertEqual( [dict(row) for row in r.fetchall()], [{ 'branch': u'master', 'codebase': u'cb', 'id': 1, 'patchid': None, 'project': u'', 'repository': u'', 'revision': u'2d6caa52', 'created_at': SOMETIME, 'ss_hash': 'b777dbd10d1d4c76651335f6a78e278e88b010d6', }]) return self.db.pool.do(thd) d.addCallback(check_change_sourcestamps) return d
def _masterdictFromRow(self, row): return MasterDict(id=row.id, name=row.name, active=bool(row.active), last_active=epoch2datetime(row.last_active))
def test_gort_bldr_name_not_identifier(self): # this is a regression test for #2940 yield self.makeBuilder(name='foo@bar') rqtime = yield self.bldr.getOldestRequestTime() self.assertEqual(rqtime, epoch2datetime(2800))
def test_gnct_completed(self): yield self.makeBuilder(name='bldr1') rqtime = yield self.bldr.getNewestCompleteTime() self.assertEqual(rqtime, epoch2datetime(4000))
def test_gort_unclaimed(self): yield self.makeBuilder(name='bldr1') rqtime = yield self.bldr.getOldestRequestTime() self.assertEqual(rqtime, epoch2datetime(1000))
def addChange(self, author=None, files=None, comments=None, is_dir=None, revision=None, when_timestamp=None, branch=None, category=None, revlink='', properties=None, repository='', codebase='', project='', uid=None, _reactor=reactor): assert project is not None, "project must be a string, not None" assert repository is not None, "repository must be a string, not None" if is_dir is not None: log.msg("WARNING: change source is providing deprecated " "value is_dir (ignored)") if when_timestamp is None: when_timestamp = epoch2datetime(_reactor.seconds()) if properties is None: properties = {} # verify that source is 'Change' for each property for pv in itervalues(properties): assert pv[1] == 'Change', ("properties must be qualified with" "source 'Change'") ch_tbl = self.db.model.changes self.checkLength(ch_tbl.c.author, author) self.checkLength(ch_tbl.c.branch, branch) self.checkLength(ch_tbl.c.revision, revision) self.checkLength(ch_tbl.c.revlink, revlink) self.checkLength(ch_tbl.c.category, category) self.checkLength(ch_tbl.c.repository, repository) self.checkLength(ch_tbl.c.project, project) # calculate the sourcestamp first, before adding it ssid = yield self.db.sourcestamps.findSourceStampId( revision=revision, branch=branch, repository=repository, codebase=codebase, project=project, _reactor=_reactor) parent_changeids = yield self.getParentChangeIds( branch, repository, project, codebase) # Someday, changes will have multiple parents. # But for the moment, a Change can only have 1 parent parent_changeid = parent_changeids[0] if parent_changeids else None def thd(conn): # note that in a read-uncommitted database like SQLite this # transaction does not buy atomicity - other database users may # still come across a change without its files, properties, # etc. That's OK, since we don't announce the change until it's # all in the database, but beware. transaction = conn.begin() r = conn.execute( ch_tbl.insert(), dict(author=author, comments=comments, branch=branch, revision=revision, revlink=revlink, when_timestamp=datetime2epoch(when_timestamp), category=category, repository=repository, codebase=codebase, project=project, sourcestampid=ssid, parent_changeids=parent_changeid)) changeid = r.inserted_primary_key[0] if files: tbl = self.db.model.change_files for f in files: self.checkLength(tbl.c.filename, f) conn.execute( tbl.insert(), [dict(changeid=changeid, filename=f) for f in files]) if properties: tbl = self.db.model.change_properties inserts = [ dict(changeid=changeid, property_name=k, property_value=json.dumps(v)) for k, v in iteritems(properties) ] for i in inserts: self.checkLength(tbl.c.property_name, i['property_name']) self.checkLength(tbl.c.property_value, i['property_value']) conn.execute(tbl.insert(), inserts) if uid: ins = self.db.model.change_users.insert() conn.execute(ins, dict(changeid=changeid, uid=uid)) transaction.commit() return changeid defer.returnValue((yield self.db.pool.do(thd)))
class Change(TestReactorMixin, interfaces.InterfaceTests, unittest.TestCase): changeEvent = { 'author': 'warner', 'committer': 'david', 'branch': 'warnerdb', 'category': 'devel', 'codebase': '', 'comments': 'fix whitespace', 'changeid': 500, 'files': ['master/buildbot/__init__.py'], 'parent_changeids': [], 'project': 'Buildbot', 'properties': {'foo': (20, 'Change')}, 'repository': 'git://warner', 'revision': '0e92a098b', 'revlink': 'http://warner/0e92a098b', 'when_timestamp': 256738404, 'sourcestamp': { 'branch': 'warnerdb', 'codebase': '', 'patch': None, 'project': 'Buildbot', 'repository': 'git://warner', 'revision': '0e92a098b', 'created_at': epoch2datetime(10000000), 'ssid': 100, }, # uid } def setUp(self): self.setUpTestReactor() self.master = fakemaster.make_master(self, wantMq=True, wantDb=True, wantData=True) self.rtype = changes.Change(self.master) def test_signature_addChange(self): @self.assertArgSpecMatches( self.master.data.updates.addChange, # fake self.rtype.addChange) # real def addChange(self, files=None, comments=None, author=None, committer=None, revision=None, when_timestamp=None, branch=None, category=None, revlink='', properties=None, repository='', codebase=None, project='', src=None): pass @defer.inlineCallbacks def do_test_addChange(self, kwargs, expectedRoutingKey, expectedMessage, expectedRow, expectedChangeUsers=None): if expectedChangeUsers is None: expectedChangeUsers = [] self.reactor.advance(10000000) changeid = yield self.rtype.addChange(**kwargs) self.assertEqual(changeid, 500) # check the correct message was received self.master.mq.assertProductions([ (expectedRoutingKey, expectedMessage), ]) # and that the correct data was inserted into the db self.master.db.changes.assertChange(500, expectedRow) self.master.db.changes.assertChangeUsers(500, expectedChangeUsers) def test_addChange(self): # src and codebase are default here kwargs = dict(author='warner', committer='david', branch='warnerdb', category='devel', comments='fix whitespace', files=['master/buildbot/__init__.py'], project='Buildbot', repository='git://warner', revision='0e92a098b', revlink='http://warner/0e92a098b', when_timestamp=256738404, properties={'foo': 20}) expectedRoutingKey = ('changes', '500', 'new') expectedMessage = self.changeEvent expectedRow = fakedb.Change( changeid=500, author='warner', committer='david', comments='fix whitespace', branch='warnerdb', revision='0e92a098b', revlink='http://warner/0e92a098b', when_timestamp=256738404, category='devel', repository='git://warner', codebase='', project='Buildbot', sourcestampid=100, ) return self.do_test_addChange(kwargs, expectedRoutingKey, expectedMessage, expectedRow) @defer.inlineCallbacks def test_addChange_src_codebase(self): createUserObject = mock.Mock(spec=users.createUserObject) createUserObject.return_value = defer.succeed(123) self.patch(users, 'createUserObject', createUserObject) kwargs = dict(author='warner', committer='david', branch='warnerdb', category='devel', comments='fix whitespace', files=['master/buildbot/__init__.py'], project='Buildbot', repository='git://warner', revision='0e92a098b', revlink='http://warner/0e92a098b', when_timestamp=256738404, properties={'foo': 20}, src='git', codebase='cb') expectedRoutingKey = ('changes', '500', 'new') expectedMessage = { 'author': 'warner', 'committer': 'david', 'branch': 'warnerdb', 'category': 'devel', 'codebase': 'cb', 'comments': 'fix whitespace', 'changeid': 500, 'files': ['master/buildbot/__init__.py'], 'parent_changeids': [], 'project': 'Buildbot', 'properties': {'foo': (20, 'Change')}, 'repository': 'git://warner', 'revision': '0e92a098b', 'revlink': 'http://warner/0e92a098b', 'when_timestamp': 256738404, 'sourcestamp': { 'branch': 'warnerdb', 'codebase': 'cb', 'patch': None, 'project': 'Buildbot', 'repository': 'git://warner', 'revision': '0e92a098b', 'created_at': epoch2datetime(10000000), 'ssid': 100, }, # uid } expectedRow = fakedb.Change( changeid=500, author='warner', committer='david', comments='fix whitespace', branch='warnerdb', revision='0e92a098b', revlink='http://warner/0e92a098b', when_timestamp=256738404, category='devel', repository='git://warner', codebase='cb', project='Buildbot', sourcestampid=100, ) yield self.do_test_addChange(kwargs, expectedRoutingKey, expectedMessage, expectedRow, expectedChangeUsers=[123]) createUserObject.assert_called_once_with(self.master, 'warner', 'git') def test_addChange_src_codebaseGenerator(self): def preChangeGenerator(**kwargs): return kwargs self.master.config = mock.Mock(name='master.config') self.master.config.preChangeGenerator = preChangeGenerator self.master.config.codebaseGenerator = \ lambda change: 'cb-%s' % change['category'] kwargs = dict(author='warner', committer='david', branch='warnerdb', category='devel', comments='fix whitespace', files=['master/buildbot/__init__.py'], project='Buildbot', repository='git://warner', revision='0e92a098b', revlink='http://warner/0e92a098b', when_timestamp=256738404, properties={'foo': 20}) expectedRoutingKey = ('changes', '500', 'new') expectedMessage = { 'author': 'warner', 'committer': 'david', 'branch': 'warnerdb', 'category': 'devel', 'codebase': 'cb-devel', 'comments': 'fix whitespace', 'changeid': 500, 'files': ['master/buildbot/__init__.py'], 'parent_changeids': [], 'project': 'Buildbot', 'properties': {'foo': (20, 'Change')}, 'repository': 'git://warner', 'revision': '0e92a098b', 'revlink': 'http://warner/0e92a098b', 'when_timestamp': 256738404, 'sourcestamp': { 'branch': 'warnerdb', 'codebase': 'cb-devel', 'patch': None, 'project': 'Buildbot', 'repository': 'git://warner', 'revision': '0e92a098b', 'created_at': epoch2datetime(10000000), 'ssid': 100, }, # uid } expectedRow = fakedb.Change( changeid=500, author='warner', committer='david', comments='fix whitespace', branch='warnerdb', revision='0e92a098b', revlink='http://warner/0e92a098b', when_timestamp=256738404, category='devel', repository='git://warner', codebase='cb-devel', project='Buildbot', sourcestampid=100, ) return self.do_test_addChange(kwargs, expectedRoutingKey, expectedMessage, expectedRow) def test_addChange_repository_revision(self): self.master.config = mock.Mock(name='master.config') self.master.config.revlink = lambda rev, repo: 'foo%sbar%sbaz' % (repo, rev) # revlink is default here kwargs = dict(author='warner', committer='david', branch='warnerdb', category='devel', comments='fix whitespace', files=['master/buildbot/__init__.py'], project='Buildbot', repository='git://warner', codebase='', revision='0e92a098b', when_timestamp=256738404, properties={'foo': 20}) expectedRoutingKey = ('changes', '500', 'new') # When no revlink is passed to addChange, but a repository and revision is # passed, the revlink should be constructed by calling the revlink callable # in the config. We thus expect a revlink of 'foogit://warnerbar0e92a098bbaz' expectedMessage = { 'author': 'warner', 'committer': 'david', 'branch': 'warnerdb', 'category': 'devel', 'codebase': '', 'comments': 'fix whitespace', 'changeid': 500, 'files': ['master/buildbot/__init__.py'], 'parent_changeids': [], 'project': 'Buildbot', 'properties': {'foo': (20, 'Change')}, 'repository': 'git://warner', 'revision': '0e92a098b', 'revlink': 'foogit://warnerbar0e92a098bbaz', 'when_timestamp': 256738404, 'sourcestamp': { 'branch': 'warnerdb', 'codebase': '', 'patch': None, 'project': 'Buildbot', 'repository': 'git://warner', 'revision': '0e92a098b', 'created_at': epoch2datetime(10000000), 'ssid': 100, }, # uid } expectedRow = fakedb.Change( changeid=500, author='warner', committer='david', comments='fix whitespace', branch='warnerdb', revision='0e92a098b', revlink='foogit://warnerbar0e92a098bbaz', when_timestamp=256738404, category='devel', repository='git://warner', codebase='', project='Buildbot', sourcestampid=100, ) return self.do_test_addChange(kwargs, expectedRoutingKey, expectedMessage, expectedRow)
def test_change_subscription(self): changeid = 918 chdict = { 'changeid': 14, 'author': u'warner', 'branch': u'warnerdb', 'category': u'devel', 'comments': u'fix whitespace', 'files': [u'master/buildbot/__init__.py'], 'is_dir': 0, 'project': u'Buildbot', 'properties': {}, 'repository': u'git://warner', 'revision': u'0e92a098b', 'revlink': u'http://warner/0e92a098b', 'when_timestamp': epoch2datetime(266738404), } newchange = mock.Mock(name='newchange') # patch out everything we're about to call self.master.db = mock.Mock() self.master.db.changes.addChange.return_value = \ defer.succeed(changeid) self.master.db.changes.getChange.return_value = \ defer.succeed(chdict) self.patch( changes.Change, 'fromChdict', classmethod(lambda cls, master, chdict: defer.succeed(newchange))) cb = mock.Mock() sub = self.master.subscribeToChanges(cb) self.assertIsInstance(sub, subscription.Subscription) d = self.master.addChange() def check(change): # master called the right thing in the db component, including with # appropriate default values self.master.db.changes.addChange.assert_called_with( author=None, files=None, comments=None, is_dir=0, revision=None, when_timestamp=None, branch=None, codebase='', category=None, revlink='', properties={}, repository='', project='', uid=None) self.master.db.changes.getChange.assert_called_with(changeid) # addChange returned the right value self.failUnless(change is newchange) # fromChdict's return value # and the notification sub was called correctly cb.assert_called_with(newchange) d.addCallback(check) return d
def addBuildset(self, waited_for, scheduler=None, sourcestamps=None, reason=u'', properties=None, builderids=None, external_idstring=None, parent_buildid=None, parent_relationship=None, _reactor=reactor): if sourcestamps is None: sourcestamps = [] if properties is None: properties = {} if builderids is None: builderids = [] submitted_at = int(_reactor.seconds()) bsid, brids = yield self.master.db.buildsets.addBuildset( sourcestamps=sourcestamps, reason=reason, properties=properties, builderids=builderids, waited_for=waited_for, external_idstring=external_idstring, submitted_at=epoch2datetime(submitted_at), parent_buildid=parent_buildid, parent_relationship=parent_relationship) yield BuildRequestCollapser(self.master, list(itervalues(brids))).collapse() # get each of the sourcestamps for this buildset (sequentially) bsdict = yield self.master.db.buildsets.getBuildset(bsid) sourcestamps = [(yield self.master.data.get( ('sourcestamps', str(ssid)))).copy() for ssid in bsdict['sourcestamps']] # notify about the component build requests brResource = self.master.data.getResourceType("buildrequest") brResource.generateEvent(list(itervalues(brids)), 'new') # and the buildset itself msg = dict(bsid=bsid, external_idstring=external_idstring, reason=reason, submitted_at=submitted_at, complete=False, complete_at=None, results=None, scheduler=scheduler, sourcestamps=sourcestamps) # TODO: properties=properties) self.produceEvent(msg, "new") log.msg("added buildset %d to database" % bsid) # if there are no builders, then this is done already, so send the # appropriate messages for that if not builderids: yield self.maybeBuildsetComplete(bsid, _reactor=_reactor) defer.returnValue((bsid, brids))
class Tests(interfaces.InterfaceTests): # common sample data change13_rows = [ fakedb.SourceStamp(id=92, branch="thirteen"), fakedb.Change(changeid=13, author="dustin", comments="fix spelling", branch="master", revision="deadbeef", when_timestamp=266738400, revlink=None, category=None, repository='', codebase='', project='', sourcestampid=92), fakedb.ChangeFile(changeid=13, filename='master/README.txt'), fakedb.ChangeFile(changeid=13, filename='worker/README.txt'), fakedb.ChangeProperty(changeid=13, property_name='notest', property_value='["no","Change"]'), ] change14_rows = [ fakedb.SourceStamp(id=233, branch="fourteen"), fakedb.Change(changeid=14, author="warner", comments="fix whitespace", branch="warnerdb", revision="0e92a098b", when_timestamp=266738404, revlink='http://warner/0e92a098b', category='devel', repository='git://warner', codebase='mainapp', project='Buildbot', sourcestampid=233), fakedb.ChangeFile(changeid=14, filename='master/buildbot/__init__.py'), ] change14_dict = { 'changeid': 14, 'parent_changeids': [], 'author': u'warner', 'branch': u'warnerdb', 'category': u'devel', 'comments': u'fix whitespace', 'files': [u'master/buildbot/__init__.py'], 'project': u'Buildbot', 'properties': {}, 'repository': u'git://warner', 'codebase': u'mainapp', 'revision': u'0e92a098b', 'revlink': u'http://warner/0e92a098b', 'when_timestamp': epoch2datetime(266738404), 'sourcestampid': 233, } # tests def test_signature_addChange(self): @self.assertArgSpecMatches(self.db.changes.addChange) def addChange(self, author=None, files=None, comments=None, is_dir=None, revision=None, when_timestamp=None, branch=None, category=None, revlink='', properties=None, repository='', codebase='', project='', uid=None): pass def test_signature_getChange(self): @self.assertArgSpecMatches(self.db.changes.getChange) def getChange(self, key, no_cache=False): pass @defer.inlineCallbacks def test_addChange_getChange(self): clock = task.Clock() clock.advance(SOMETIME) changeid = yield self.db.changes.addChange( author=u'dustin', files=[], comments=u'fix spelling', revision=u'2d6caa52', when_timestamp=epoch2datetime(OTHERTIME), branch=u'master', category=None, revlink=None, properties={}, repository=u'repo://', codebase=u'cb', project=u'proj', _reactor=clock) chdict = yield self.db.changes.getChange(changeid) validation.verifyDbDict(self, 'chdict', chdict) chdict = chdict.copy() ss = yield self.db.sourcestamps.getSourceStamp(chdict['sourcestampid']) chdict['sourcestampid'] = ss self.assertEqual( chdict, { 'author': u'dustin', 'branch': u'master', 'category': None, 'changeid': changeid, 'parent_changeids': [], 'codebase': u'cb', 'comments': u'fix spelling', 'files': [], 'project': u'proj', 'properties': {}, 'repository': u'repo://', 'revision': u'2d6caa52', 'revlink': None, 'sourcestampid': { 'branch': u'master', 'codebase': u'cb', 'patch_author': None, 'patch_body': None, 'patch_comment': None, 'patch_level': None, 'patch_subdir': None, 'patchid': None, 'project': u'proj', 'repository': u'repo://', 'revision': u'2d6caa52', 'created_at': epoch2datetime(SOMETIME), 'ssid': ss['ssid'], }, 'when_timestamp': epoch2datetime(OTHERTIME), }) @defer.inlineCallbacks def test_addChange_withParent(self): yield self.insertTestData(self.change14_rows) clock = task.Clock() clock.advance(SOMETIME) changeid = yield self.db.changes.addChange( author=u'delanne', files=[], comments=u'child of changeid14', revision=u'50adad56', when_timestamp=epoch2datetime(OTHERTIME), branch=u'warnerdb', category=u'devel', revlink=None, properties={}, repository=u'git://warner', codebase=u'mainapp', project=u'Buildbot', _reactor=clock) chdict = yield self.db.changes.getChange(changeid) validation.verifyDbDict(self, 'chdict', chdict) chdict = chdict.copy() ss = yield self.db.sourcestamps.getSourceStamp(chdict['sourcestampid']) chdict['sourcestampid'] = ss self.assertEqual( chdict, { 'author': u'delanne', 'branch': u'warnerdb', 'category': u'devel', 'changeid': changeid, 'parent_changeids': [14], 'codebase': u'mainapp', 'comments': u'child of changeid14', 'files': [], 'project': u'Buildbot', 'properties': {}, 'repository': u'git://warner', 'revision': u'50adad56', 'revlink': None, 'sourcestampid': { 'branch': u'warnerdb', 'codebase': u'mainapp', 'created_at': epoch2datetime(SOMETIME), 'patch_author': None, 'patch_body': None, 'patch_comment': None, 'patch_level': None, 'patch_subdir': None, 'patchid': None, 'project': u'Buildbot', 'repository': u'git://warner', 'revision': u'50adad56', 'ssid': ss['ssid'] }, 'when_timestamp': epoch2datetime(OTHERTIME), }) def test_getChange_chdict(self): d = self.insertTestData(self.change14_rows) def get14(_): return self.db.changes.getChange(14) d.addCallback(get14) def check14(chdict): validation.verifyDbDict(self, 'chdict', chdict) self.assertEqual(chdict, self.change14_dict) d.addCallback(check14) return d def test_getChange_missing(self): d = defer.succeed(None) def get14(_): return self.db.changes.getChange(14) d.addCallback(get14) def check14(chdict): self.failUnless(chdict is None) d.addCallback(check14) return d def test_signature_getChangeUids(self): @self.assertArgSpecMatches(self.db.changes.getChangeUids) def getChangeUids(self, changeid): pass def test_getChangeUids_missing(self): d = self.db.changes.getChangeUids(1) def check(res): self.assertEqual(res, []) d.addCallback(check) return d def test_getChangeUids_found(self): d = self.insertTestData(self.change14_rows + [ fakedb.SourceStamp(id=92), fakedb.User(uid=1), fakedb.ChangeUser(changeid=14, uid=1), ]) d.addCallback(lambda _: self.db.changes.getChangeUids(14)) def check(res): self.assertEqual(res, [1]) d.addCallback(check) return d def test_getChangeUids_multi(self): d = self.insertTestData(self.change14_rows + self.change13_rows + [ fakedb.User(uid=1, identifier="one"), fakedb.User(uid=2, identifier="two"), fakedb.User(uid=99, identifier="nooo"), fakedb.ChangeUser(changeid=14, uid=1), fakedb.ChangeUser(changeid=14, uid=2), fakedb.ChangeUser(changeid=13, uid=99), # not selected ]) d.addCallback(lambda _: self.db.changes.getChangeUids(14)) def check(res): self.assertEqual(sorted(res), [1, 2]) d.addCallback(check) return d def test_signature_getRecentChanges(self): @self.assertArgSpecMatches(self.db.changes.getRecentChanges) def getRecentChanges(self, count): pass def test_signature_getChanges(self): @self.assertArgSpecMatches(self.db.changes.getChanges) def getChanges(self): pass def insert7Changes(self): return self.insertTestData([ fakedb.SourceStamp(id=922), fakedb.Change(changeid=8, sourcestampid=922), fakedb.Change(changeid=9, sourcestampid=922), fakedb.Change(changeid=10, sourcestampid=922), fakedb.Change(changeid=11, sourcestampid=922), fakedb.Change(changeid=12, sourcestampid=922), ] + self.change13_rows + self.change14_rows) def test_getRecentChanges_subset(self): d = self.insert7Changes() d.addCallback(lambda _: self.db.changes.getRecentChanges(5)) def check(changes): changeids = [c['changeid'] for c in changes] self.assertEqual(changeids, [10, 11, 12, 13, 14]) d.addCallback(check) return d def test_getChangesCount(self): d = self.insert7Changes() d.addCallback(lambda _: self.db.changes.getChangesCount()) def check(n): self.assertEqual(n, 7) d.addCallback(check) return d def test_getChangesHugeCount(self): d = self.insertTestData([ fakedb.SourceStamp(id=92), ] + [fakedb.Change(changeid=i) for i in xrange(2, 102)]) d.addCallback(lambda _: self.db.changes.getChangesCount()) def check(n): self.assertEqual(n, 100) d.addCallback(check) return d def test_getRecentChanges_empty(self): d = defer.succeed(None) d.addCallback(lambda _: self.db.changes.getRecentChanges(5)) def check(changes): changeids = [c['changeid'] for c in changes] self.assertEqual(changeids, []) d.addCallback(check) d.addCallback(lambda _: self.db.changes.getChanges()) d.addCallback(check) return d def test_getRecentChanges_missing(self): d = self.insertTestData(self.change13_rows + self.change14_rows) d.addCallback(lambda _: self.db.changes.getRecentChanges(5)) def check(changes): # requested all, but only got 2 # sort by changeid, since we assert on change 13 at index 0 changes.sort(key=lambda c: c['changeid']) changeids = [c['changeid'] for c in changes] self.assertEqual(changeids, [13, 14]) # double-check that they have .files, etc. self.assertEqual( sorted(changes[0]['files']), sorted(['master/README.txt', 'worker/README.txt'])) self.assertEqual(changes[0]['properties'], {'notest': ('no', 'Change')}) d.addCallback(check) d.addCallback(lambda _: self.db.changes.getChanges()) d.addCallback(check) return d def test_signature_getLatestChangeid(self): @self.assertArgSpecMatches(self.db.changes.getLatestChangeid) def getLatestChangeid(self): pass def test_getLatestChangeid(self): d = self.insertTestData(self.change13_rows) def get(_): return self.db.changes.getLatestChangeid() d.addCallback(get) def check(changeid): self.assertEqual(changeid, 13) d.addCallback(check) return d def test_getLatestChangeid_empty(self): d = defer.succeed(None) def get(_): return self.db.changes.getLatestChangeid() d.addCallback(get) def check(changeid): self.assertEqual(changeid, None) d.addCallback(check) return d def test_signature_getParentChangeIds(self): @self.assertArgSpecMatches(self.db.changes.getParentChangeIds) def getParentChangeIds(self, branch, repository, project, codebase): pass def test_getParentChangeIds(self): d = self.insertTestData(self.change14_rows + self.change13_rows) def getParent(_): return self.db.changes.getParentChangeIds( branch='warnerdb', repository='git://warner', project='Buildbot', codebase='mainapp') d.addCallback(getParent) def check(changeid): self.assertEqual(changeid, [14]) d.addCallback(check) return d
def addChange(self, files=None, comments=None, author=None, revision=None, when_timestamp=None, branch=None, category=None, revlink=u'', properties=None, repository=u'', codebase=None, project=u'', src=None, _reactor=reactor): metrics.MetricCountEvent.log("added_changes", 1) if properties is None: properties = {} # add the source to the properties for k in properties: properties[k] = (properties[k], u'Change') # get a user id if src: # create user object, returning a corresponding uid uid = yield users.createUserObject(self.master, author, src) else: uid = None if callable(category): pre_change = self.master.config.preChangeGenerator( author=author, files=files, comments=comments, revision=revision, when_timestamp=when_timestamp, branch=branch, revlink=revlink, properties=properties, repository=repository, project=project) category = category(pre_change) # set the codebase, either the default, supplied, or generated if codebase is None \ and self.master.config.codebaseGenerator is not None: pre_change = self.master.config.preChangeGenerator( author=author, files=files, comments=comments, revision=revision, when_timestamp=when_timestamp, branch=branch, category=category, revlink=revlink, properties=properties, repository=repository, project=project) codebase = self.master.config.codebaseGenerator(pre_change) codebase = unicode(codebase) else: codebase = codebase or u'' # add the Change to the database changeid = yield self.master.db.changes.addChange( author=author, files=files, comments=comments, revision=revision, when_timestamp=epoch2datetime(when_timestamp), branch=branch, category=category, revlink=revlink, properties=properties, repository=repository, codebase=codebase, project=project, uid=uid, _reactor=_reactor) # get the change and munge the result for the notification change = yield self.master.data.get(('changes', str(changeid))) change = copy.deepcopy(change) self.produceEvent(change, 'new') # log, being careful to handle funny characters msg = u"added change with revision %s to database" % (revision, ) log.msg(msg.encode('utf-8', 'replace')) defer.returnValue(changeid)
class Tests(interfaces.InterfaceTests): # common sample data backgroundData = [ fakedb.Buildset(id=20), fakedb.Builder(id=77, name="b1"), fakedb.Builder(id=88, name="b2"), fakedb.BuildRequest(id=40, buildsetid=20, builderid=77), fakedb.BuildRequest(id=41, buildsetid=20, builderid=77), fakedb.BuildRequest(id=42, buildsetid=20, builderid=88), fakedb.Master(id=88), fakedb.Master(id=89, name="bar"), fakedb.Worker(id=13, name='sl'), fakedb.Worker(id=12, name='sl2'), ] threeBuilds = [ fakedb.Build(id=50, buildrequestid=42, number=5, masterid=88, builderid=77, workerid=13, state_string="test", started_at=TIME1), fakedb.Build(id=51, buildrequestid=41, number=6, masterid=88, builderid=88, workerid=13, state_string="test", started_at=TIME2), fakedb.Build(id=52, buildrequestid=42, number=7, masterid=88, builderid=77, workerid=12, state_string="test", started_at=TIME3, complete_at=TIME4, results=5), ] threeBdicts = { 50: { 'id': 50, 'buildrequestid': 42, 'builderid': 77, 'masterid': 88, 'number': 5, 'workerid': 13, 'started_at': epoch2datetime(TIME1), 'complete_at': None, 'state_string': 'test', 'results': None }, 51: { 'id': 51, 'buildrequestid': 41, 'builderid': 88, 'masterid': 88, 'number': 6, 'workerid': 13, 'started_at': epoch2datetime(TIME2), 'complete_at': None, 'state_string': 'test', 'results': None }, 52: { 'id': 52, 'buildrequestid': 42, 'builderid': 77, 'masterid': 88, 'number': 7, 'workerid': 12, 'started_at': epoch2datetime(TIME3), 'complete_at': epoch2datetime(TIME4), 'state_string': 'test', 'results': 5 }, } # signature tests def test_signature_getBuild(self): @self.assertArgSpecMatches(self.db.builds.getBuild) def getBuild(self, buildid): pass def test_signature_getBuildByNumber(self): @self.assertArgSpecMatches(self.db.builds.getBuildByNumber) def getBuild(self, builderid, number): pass def test_signature_getBuilds(self): @self.assertArgSpecMatches(self.db.builds.getBuilds) def getBuilds(self, builderid=None, buildrequestid=None, workerid=None, complete=None, resultSpec=None): pass def test_signature_addBuild(self): @self.assertArgSpecMatches(self.db.builds.addBuild) def addBuild(self, builderid, buildrequestid, workerid, masterid, state_string): pass def test_signature_setBuildStateString(self): @self.assertArgSpecMatches(self.db.builds.setBuildStateString) def setBuildStateString(self, buildid, state_string): pass def test_signature_finishBuild(self): @self.assertArgSpecMatches(self.db.builds.finishBuild) def finishBuild(self, buildid, results): pass def test_signature_getBuildProperties(self): @self.assertArgSpecMatches(self.db.builds.getBuildProperties) def getBuildProperties(self, bid): pass def test_signature_setBuildProperty(self): @self.assertArgSpecMatches(self.db.builds.setBuildProperty) def setBuildProperty(self, bid, name, value, source): pass # method tests @defer.inlineCallbacks def test_getBuild(self): yield self.insertTestData(self.backgroundData + [self.threeBuilds[0]]) bdict = yield self.db.builds.getBuild(50) validation.verifyDbDict(self, 'dbbuilddict', bdict) self.assertEqual( bdict, dict(id=50, number=5, buildrequestid=42, masterid=88, builderid=77, workerid=13, started_at=epoch2datetime(TIME1), complete_at=None, state_string=u'test', results=None)) @defer.inlineCallbacks def test_getBuild_missing(self): bdict = yield self.db.builds.getBuild(50) self.assertEqual(bdict, None) @defer.inlineCallbacks def test_getBuildByNumber(self): yield self.insertTestData(self.backgroundData + [self.threeBuilds[0]]) bdict = yield self.db.builds.getBuildByNumber(builderid=77, number=5) validation.verifyDbDict(self, 'dbbuilddict', bdict) self.assertEqual(bdict['id'], 50) @defer.inlineCallbacks def test_getBuilds(self): yield self.insertTestData(self.backgroundData + self.threeBuilds) bdicts = yield self.db.builds.getBuilds() for bdict in bdicts: validation.verifyDbDict(self, 'dbbuilddict', bdict) self.assertEqual( sorted(bdicts, key=lambda bd: bd['id']), [self.threeBdicts[50], self.threeBdicts[51], self.threeBdicts[52]]) @defer.inlineCallbacks def test_getBuilds_builderid(self): yield self.insertTestData(self.backgroundData + self.threeBuilds) bdicts = yield self.db.builds.getBuilds(builderid=88) for bdict in bdicts: validation.verifyDbDict(self, 'dbbuilddict', bdict) self.assertEqual(sorted(bdicts, key=lambda bd: bd['id']), [self.threeBdicts[51]]) @defer.inlineCallbacks def test_getBuilds_buildrequestid(self): yield self.insertTestData(self.backgroundData + self.threeBuilds) bdicts = yield self.db.builds.getBuilds(buildrequestid=42) for bdict in bdicts: validation.verifyDbDict(self, 'dbbuilddict', bdict) self.assertEqual(sorted(bdicts, key=lambda bd: bd['id']), [self.threeBdicts[50], self.threeBdicts[52]]) @defer.inlineCallbacks def test_getBuilds_workerid(self): yield self.insertTestData(self.backgroundData + self.threeBuilds) bdicts = yield self.db.builds.getBuilds(workerid=13) for bdict in bdicts: validation.verifyDbDict(self, 'dbbuilddict', bdict) self.assertEqual(sorted(bdicts, key=lambda bd: bd['id']), [self.threeBdicts[50], self.threeBdicts[51]]) @defer.inlineCallbacks def test_getBuilds_complete(self): yield self.insertTestData(self.backgroundData + self.threeBuilds) bdicts = yield self.db.builds.getBuilds(complete=True) for bdict in bdicts: validation.verifyDbDict(self, 'dbbuilddict', bdict) self.assertEqual(sorted(bdicts, key=lambda bd: bd['id']), [self.threeBdicts[52]]) @defer.inlineCallbacks def test_addBuild_first(self): clock = task.Clock() clock.advance(TIME1) yield self.insertTestData(self.backgroundData) id, number = yield self.db.builds.addBuild(builderid=77, buildrequestid=41, workerid=13, masterid=88, state_string=u'test test2', _reactor=clock) bdict = yield self.db.builds.getBuild(id) validation.verifyDbDict(self, 'dbbuilddict', bdict) self.assertEqual( bdict, { 'buildrequestid': 41, 'builderid': 77, 'id': id, 'masterid': 88, 'number': number, 'workerid': 13, 'started_at': epoch2datetime(TIME1), 'complete_at': None, 'state_string': u'test test2', 'results': None }) @defer.inlineCallbacks def test_addBuild_existing(self): clock = task.Clock() clock.advance(TIME1) yield self.insertTestData(self.backgroundData + [ fakedb.Build(number=10, buildrequestid=41, builderid=77, masterid=88, workerid=13), ]) id, number = yield self.db.builds.addBuild(builderid=77, buildrequestid=41, workerid=13, masterid=88, state_string=u'test test2', _reactor=clock) bdict = yield self.db.builds.getBuild(id) validation.verifyDbDict(self, 'dbbuilddict', bdict) self.assertEqual(number, 11) self.assertEqual( bdict, { 'buildrequestid': 41, 'builderid': 77, 'id': id, 'masterid': 88, 'number': number, 'workerid': 13, 'started_at': epoch2datetime(TIME1), 'complete_at': None, 'state_string': u'test test2', 'results': None }) @defer.inlineCallbacks def test_setBuildStateString(self): yield self.insertTestData(self.backgroundData + [self.threeBuilds[0]]) yield self.db.builds.setBuildStateString(buildid=50, state_string=u'test test2') bdict = yield self.db.builds.getBuild(50) validation.verifyDbDict(self, 'dbbuilddict', bdict) self.assertEqual( bdict, dict(id=50, number=5, buildrequestid=42, masterid=88, builderid=77, workerid=13, started_at=epoch2datetime(TIME1), complete_at=None, state_string=u'test test2', results=None)) @defer.inlineCallbacks def test_finishBuild(self): clock = task.Clock() clock.advance(TIME4) yield self.insertTestData(self.backgroundData + [self.threeBuilds[0]]) yield self.db.builds.finishBuild(buildid=50, results=7, _reactor=clock) bdict = yield self.db.builds.getBuild(50) validation.verifyDbDict(self, 'dbbuilddict', bdict) self.assertEqual( bdict, dict(id=50, number=5, buildrequestid=42, masterid=88, builderid=77, workerid=13, started_at=epoch2datetime(TIME1), complete_at=epoch2datetime(TIME4), state_string=u'test', results=7)) @defer.inlineCallbacks def testgetBuildPropertiesEmpty(self): yield self.insertTestData(self.backgroundData + self.threeBuilds) for buildid in (50, 51, 52): props = yield self.db.builds.getBuildProperties(buildid) self.assertEqual(0, len(props)) @defer.inlineCallbacks def testsetandgetProperties(self): yield self.insertTestData(self.backgroundData + self.threeBuilds) yield self.db.builds.setBuildProperty(50, 'prop', 42, 'test') props = yield self.db.builds.getBuildProperties(50) self.assertEqual(props, {'prop': (42, 'test')}) @defer.inlineCallbacks def testsetgetsetProperties(self): yield self.insertTestData(self.backgroundData + self.threeBuilds) props = yield self.db.builds.getBuildProperties(50) self.assertEqual(props, {}) yield self.db.builds.setBuildProperty(50, 'prop', 42, 'test') props = yield self.db.builds.getBuildProperties(50) self.assertEqual(props, {'prop': (42, 'test')}) # set a new value yield self.db.builds.setBuildProperty(50, 'prop', 45, 'test') props = yield self.db.builds.getBuildProperties(50) self.assertEqual(props, {'prop': (45, 'test')}) # set a new source yield self.db.builds.setBuildProperty(50, 'prop', 45, 'test_source') props = yield self.db.builds.getBuildProperties(50) self.assertEqual(props, {'prop': (45, 'test_source')}) # set the same yield self.db.builds.setBuildProperty(50, 'prop', 45, 'test_source') props = yield self.db.builds.getBuildProperties(50) self.assertEqual(props, {'prop': (45, 'test_source')})
def mkdt(epoch): if epoch: return epoch2datetime(epoch)
def test_addChange_src_codebaseGenerator(self): def preChangeGenerator(**kwargs): return kwargs self.master.config = mock.Mock(name='master.config') self.master.config.preChangeGenerator = preChangeGenerator self.master.config.codebaseGenerator = \ lambda change: 'cb-%s' % change['category'] kwargs = dict(author=u'warner', branch=u'warnerdb', category=u'devel', comments=u'fix whitespace', files=[u'master/buildbot/__init__.py'], project=u'Buildbot', repository=u'git://warner', revision=u'0e92a098b', revlink=u'http://warner/0e92a098b', when_timestamp=256738404, properties={u'foo': 20}) expectedRoutingKey = ('changes', '500', 'new') expectedMessage = { 'author': u'warner', 'branch': u'warnerdb', 'category': u'devel', 'codebase': u'cb-devel', 'comments': u'fix whitespace', 'changeid': 500, 'files': [u'master/buildbot/__init__.py'], 'parent_changeids': [], 'project': u'Buildbot', 'properties': { u'foo': (20, u'Change') }, 'repository': u'git://warner', 'revision': u'0e92a098b', 'revlink': u'http://warner/0e92a098b', 'when_timestamp': 256738404, 'sourcestamp': { 'branch': u'warnerdb', 'codebase': u'cb-devel', 'patch': None, 'project': u'Buildbot', 'repository': u'git://warner', 'revision': u'0e92a098b', 'created_at': epoch2datetime(10000000), 'ssid': 100, }, # uid } expectedRow = fakedb.Change( changeid=500, author='warner', comments='fix whitespace', branch='warnerdb', revision='0e92a098b', revlink='http://warner/0e92a098b', when_timestamp=256738404, category='devel', repository='git://warner', codebase='cb-devel', project='Buildbot', sourcestampid=100, ) return self.do_test_addChange(kwargs, expectedRoutingKey, expectedMessage, expectedRow)
# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. # # Copyright Buildbot Team Members from twisted.internet import defer from twisted.trial import unittest from buildbot.db import masters from buildbot.test import fakedb from buildbot.test.util import connector_component from buildbot.test.util import interfaces from buildbot.test.util import validation from buildbot.util import epoch2datetime SOMETIME = 1348971992 SOMETIME_DT = epoch2datetime(SOMETIME) OTHERTIME = 1008971992 OTHERTIME_DT = epoch2datetime(OTHERTIME) class Tests(interfaces.InterfaceTests): # common sample data master_row = [ fakedb.Master(id=7, name="some:master", active=1, last_active=SOMETIME), ] # tests
def _process_changes(self, unused_output): # get the change list revListArgs = ['log', '%s..origin/%s' % (self.branch, self.branch), r'--format=%H'] self.changeCount = 0 d = utils.getProcessOutput(self.gitbin, revListArgs, path=self.workdir, env=dict(PATH=os.environ['PATH']), errortoo=False ) wfd = defer.waitForDeferred(d) yield wfd results = wfd.getResult() # process oldest change first revList = results.split() if not revList: return revList.reverse() self.changeCount = len(revList) log.msg('LLVMGitPoller: processing %d changes: %s in "%s"' % (self.changeCount, revList, self.workdir) ) for rev in revList: #log.msg('LLVMGitPoller: waiting defer for revision: %s' % rev) dl = defer.DeferredList([ self._get_commit_timestamp(rev), self._get_commit_name(rev), self._get_commit_files(rev), self._get_commit_comments(rev), ], consumeErrors=True) wfd = defer.waitForDeferred(dl) yield wfd results = wfd.getResult() #log.msg('LLVMGitPoller: got defer results: %s' % results) # check for failures failures = [ r[1] for r in results if not r[0] ] if failures: # just fail on the first error; they're probably all related! raise failures[0] #log.msg('LLVMGitPoller: begin change adding cycle for revision: %s' % rev) timestamp, name, files, comments = [ r[1] for r in results ] where = self._transform_path(files) #log.msg('LLVMGitPoller: walking over transformed path/projects: %s' % where) for wh in where: where_project, where_project_files = wh #log.msg('LLVMGitPoller: processing transformed pair: %s, files:' % where_project, where_project_files) properties = dict() if self.cleanRe.search(comments) or \ any([m for f in where_project_files for m in [self.cleanCfg.search(f)] if m]): log.msg("LLVMGitPoller: creating a change with the 'clean' property for r%s" % rev) properties['clean_obj'] = (True, "change") log.msg("LLVMGitPoller: creating a change rev=%s" % rev) d = self.master.addChange( author=name, revision=rev, files=where_project_files, comments=comments, when_timestamp=epoch2datetime(timestamp), branch=self.branch, category=self._categories.get(where_project, self.category), project=where_project, repository=self.repourl, src='git', properties=properties) wfd = defer.waitForDeferred(d) yield wfd results = wfd.getResult()
def perspective_addChange(self, changedict): log.msg("perspective_addChange called") if 'revlink' in changedict and not changedict['revlink']: changedict['revlink'] = '' if 'repository' in changedict and not changedict['repository']: changedict['repository'] = '' if 'project' in changedict and not changedict['project']: changedict['project'] = '' if 'files' not in changedict or not changedict['files']: changedict['files'] = [] # rename arguments to new names. Note that the client still uses the # "old" names (who, when, and isdir), as they are not deprecated yet, # although the master will accept the new names (author, # when_timestamp, and is_dir). After a few revisions have passed, we # can switch the client to use the new names. if 'isdir' in changedict: changedict['is_dir'] = changedict['isdir'] del changedict['isdir'] if 'who' in changedict: changedict['author'] = changedict['who'] del changedict['who'] if 'when' in changedict: when = None if changedict['when'] is not None: when = epoch2datetime(changedict['when']) changedict['when_timestamp'] = when del changedict['when'] # turn any bytestring keys into unicode, assuming utf8 but just # replacing unknown characters. Ideally client would send us unicode # in the first place, but older clients do not, so this fallback is # useful. for key in changedict: if isinstance(changedict[key], str): changedict[key] = changedict[key].decode('utf8', 'replace') changedict['files'] = list(changedict['files']) for i, file in enumerate(changedict.get('files', [])): if isinstance(file, str): changedict['files'][i] = file.decode('utf8', 'replace') files = [] for path in changedict['files']: if self.prefix: if not path.startswith(self.prefix): # this file does not start with the prefix, so ignore it continue path = path[len(self.prefix):] files.append(path) changedict['files'] = files if not files: log.msg("No files listed in change... bit strange, but not fatal.") if "links" in changedict: log.msg("Found links: " + repr(changedict['links'])) del changedict['links'] d = self.master.addChange(**changedict) # since this is a remote method, we can't return a Change instance, so # this just sets the return value to None: d.addCallback(lambda _: None) return d
def check(results): # check that [1,1000) were not claimed, and 1000 is still claimed self.assertEqual([ (r['buildrequestid'], r['claimed_by_masterid'], r['claimed_at']) for r in results ][:10], [(1000, self.OTHER_MASTER_ID, epoch2datetime(1300103810))])
def test_addChange_with_uid(self): d = self.insertTestData([ fakedb.User(uid=1, identifier="one"), ]) d.addCallback(lambda _: self.db.changes.addChange( author=u'dustin', files=[], comments=u'fix spelling', revision=u'2d6caa52', when_timestamp=epoch2datetime(OTHERTIME), branch=u'master', category=None, revlink=None, properties={}, repository=u'', codebase=u'', project=u'', uid=1)) # check all of the columns of the five relevant tables def check_change(changeid): def thd(conn): r = conn.execute(self.db.model.changes.select()) r = r.fetchall() self.assertEqual(len(r), 1) self.assertEqual(r[0].changeid, changeid) self.assertEqual(r[0].when_timestamp, OTHERTIME) return self.db.pool.do(thd) d.addCallback(check_change) def check_change_files(_): def thd(conn): query = self.db.model.change_files.select() r = conn.execute(query) r = r.fetchall() self.assertEqual(len(r), 0) return self.db.pool.do(thd) d.addCallback(check_change_files) def check_change_properties(_): def thd(conn): query = self.db.model.change_properties.select() r = conn.execute(query) r = r.fetchall() self.assertEqual(len(r), 0) return self.db.pool.do(thd) d.addCallback(check_change_properties) def check_change_users(_): def thd(conn): query = self.db.model.change_users.select() r = conn.execute(query) r = r.fetchall() self.assertEqual(len(r), 1) self.assertEqual(r[0].changeid, 1) self.assertEqual(r[0].uid, 1) return self.db.pool.do(thd) d.addCallback(check_change_users) return d
def makeTime(self, timestring): datefmt = '%Y/%m/%d %H:%M:%S' when = time.mktime(time.strptime(timestring, datefmt)) return epoch2datetime(when)
def test_getSourceStampsForBuild_3CodeBases(self): rows = [ fakedb.Master(id=88, name="bar"), fakedb.Worker(id=13, name='one'), fakedb.Builder(id=77, name='A'), fakedb.SourceStamp(id=234, codebase='A', created_at=CREATED_AT, revision="aaa"), fakedb.SourceStamp(id=235, codebase='B', created_at=CREATED_AT + 10, revision="bbb"), fakedb.SourceStamp(id=236, codebase='C', created_at=CREATED_AT + 20, revision="ccc"), # fakedb.Change(changeid=14, codebase='A', sourcestampid=234), fakedb.Buildset(id=30, reason='foo', submitted_at=1300305712, results=-1), fakedb.BuildsetSourceStamp(sourcestampid=234, buildsetid=30), fakedb.BuildsetSourceStamp(sourcestampid=235, buildsetid=30), fakedb.BuildsetSourceStamp(sourcestampid=236, buildsetid=30), fakedb.BuildRequest(id=19, buildsetid=30, builderid=77, priority=13, submitted_at=1300305712, results=-1), fakedb.Build(id=50, buildrequestid=19, number=5, masterid=88, builderid=77, state_string="test", workerid=13, started_at=1304262222), ] expected = [{ 'branch': 'master', 'codebase': 'A', 'created_at': epoch2datetime(CREATED_AT), 'patch_author': None, 'patch_body': None, 'patch_comment': None, 'patch_level': None, 'patch_subdir': None, 'patchid': None, 'project': 'proj', 'repository': 'repo', 'revision': 'aaa', 'ssid': 234 }, { 'branch': 'master', 'codebase': 'B', 'created_at': epoch2datetime(CREATED_AT + 10), 'patch_author': None, 'patch_body': None, 'patch_comment': None, 'patch_level': None, 'patch_subdir': None, 'patchid': None, 'project': 'proj', 'repository': 'repo', 'revision': 'bbb', 'ssid': 235 }, { 'branch': 'master', 'codebase': 'C', 'created_at': epoch2datetime(CREATED_AT + 20), 'patch_author': None, 'patch_body': None, 'patch_comment': None, 'patch_level': None, 'patch_subdir': None, 'patchid': None, 'project': 'proj', 'repository': 'repo', 'revision': 'ccc', 'ssid': 236 }] return self.do_test_getSourceStampsForBuild(rows, 50, expected)
def test_addChange_args_when(self): # when should come through as when_timestamp, as a datetime return self.do_test_addChange_args( kwargs=dict(when=892293875), exp_db_kwargs=dict(when_timestamp=epoch2datetime(892293875)))
def _processChanges(self, page): result = json.loads(page, encoding=self.encoding) for pr in result['values']: branch = pr['source']['branch']['name'] nr = int(pr['id']) # Note that this is a short hash. The full length hash can be accessed via the # commit api resource but we want to avoid requesting multiple pages as long as # we are not sure that the pull request is new or updated. revision = pr['source']['commit']['hash'] # check branch if not self.branch or branch in self.branch: current = yield self._getCurrentRev(nr) # compare _short_ hashes to check if the PR has been updated if not current or current[0:12] != revision[0:12]: # parse pull request api page (required for the filter) page = yield client.getPage( str(pr['links']['self']['href'])) pr_json = json.loads(page, encoding=self.encoding) # filter pull requests by user function if not self.pullrequest_filter(pr_json): log.msg('pull request does not match filter') continue # access additional information author = pr['author']['display_name'] prlink = pr['links']['html']['href'] # Get time updated time. Note that the timezone offset is # ignored. if self.useTimestamps: updated = datetime.strptime( pr['updated_on'].split('.')[0], '%Y-%m-%dT%H:%M:%S') else: updated = epoch2datetime(reactor.seconds()) title = pr['title'] # parse commit api page page = yield client.getPage( str(pr['source']['commit']['links']['self']['href'])) commit_json = json.loads(page, encoding=self.encoding) # use the full-length hash from now on revision = commit_json['hash'] revlink = commit_json['links']['html']['href'] # parse repo api page page = yield client.getPage( str(pr['source']['repository']['links']['self'] ['href'])) repo_json = json.loads(page, encoding=self.encoding) repo = repo_json['links']['html']['href'] # update database yield self._setCurrentRev(nr, revision) # emit the change yield self.master.data.updates.addChange( author=ascii2unicode(author), revision=ascii2unicode(revision), revlink=ascii2unicode(revlink), comments=u'pull-request #%d: %s\n%s' % (nr, title, prlink), when_timestamp=datetime2epoch(updated), branch=self.branch, category=self.category, project=self.project, repository=ascii2unicode(repo), src=u'bitbucket', )