コード例 #1
0
    def test_addBuildsetForSourceStamp_combine_change_properties(self):
        sched = self.makeScheduler()

        self.master.db.insertTestData([
            fakedb.SourceStamp(id=98, branch='stable'),
            fakedb.Change(changeid=25, sourcestampid=98, branch='stable'),
            fakedb.ChangeProperty(changeid=25,
                                  property_name='color',
                                  property_value='["pink","Change"]'),
        ])

        bsid, brids = yield sched.addBuildsetForSourceStamps(reason='whynot',
                                                             waited_for=False,
                                                             sourcestamps=[98])
        self.assertEqual((bsid, brids), self.exp_bsid_brids)
        self.master.data.updates.addBuildset.assert_called_with(
            waited_for=False,
            builderids=[1, 2],
            external_idstring=None,
            properties={
                'scheduler': ('testsched', 'Scheduler'),
                'color': ('pink', 'Change')
            },
            reason='whynot',
            scheduler='testsched',
            sourcestamps=[98])
コード例 #2
0
    def test_addBuildsetForSourceStamp_list_of_renderable_builderNames(self):
        names = ['a', 'b', properties.Interpolate('%(prop:extra_builder)s')]
        sched = self.makeScheduler(name='n', builderNames=names)

        self.master.db.insertTestData([
            fakedb.Builder(id=1, name='a'),
            fakedb.Builder(id=2, name='b'),
            fakedb.Builder(id=3, name='c'),
            fakedb.SourceStamp(id=98, branch='stable'),
            fakedb.Change(changeid=25, sourcestampid=98, branch='stable'),
            fakedb.ChangeProperty(changeid=25, property_name='extra_builder',
                                  property_value='["c","Change"]'),
        ])

        bsid, brids = yield sched.addBuildsetForSourceStamps(reason=u'whynot',
                                                             waited_for=False,
                                                             sourcestamps=[98])
        self.assertEqual((bsid, brids), self.exp_bsid_brids)
        self.master.data.updates.addBuildset.assert_called_with(
            waited_for=False,
            builderids=[1, 2, 3],
            external_idstring=None,
            properties={
                u'scheduler': (u'n', u'Scheduler'),
                u'extra_builder': (u'c', u'Change')},
            reason=u'whynot',
            scheduler=u'n',
            sourcestamps=[98])
コード例 #3
0
    def test_bogus_row_jsoned_list(self):
        yield self.insertTestData([
            fakedb.SourceStamp(id=10),
            fakedb.ChangeProperty(changeid=13,
                                  property_name='devel',
                                  property_value='[1, 2]'),
            fakedb.Change(changeid=13, sourcestampid=10),
        ])

        c = yield self.db.changes.getChange(13)

        self.assertEqual(c['properties'], dict(devel=([1, 2], 'Change')))
コード例 #4
0
    def test_bogus_row_jsoned_list(self):
        d = self.insertTestData([
            fakedb.ChangeProperty(changeid=13, property_name='devel',
                                  property_value='[1, 2]'),
            fakedb.Change(changeid=13),
        ])

        def get13(_):
            return self.db.changes.getChange(13)
        d.addCallback(get13)

        def check13(c):
            self.assertEqual(c['properties'],
                             dict(devel=([1, 2], 'Change')))
        d.addCallback(check13)
        return d
コード例 #5
0
    def test_bogus_row_no_source(self):
        d = self.insertTestData([
            fakedb.SourceStamp(id=10),
            fakedb.ChangeProperty(changeid=13, property_name='devel',
                                  property_value='"no source"'),
            fakedb.Change(changeid=13, sourcestampid=10),
        ])

        @d.addCallback
        def get13(_):
            return self.db.changes.getChange(13)

        @d.addCallback
        def check13(c):
            self.assertEqual(c['properties'],
                             dict(devel=('no source', 'Change')))
        return d
コード例 #6
0
    def test_getPropertiesFromDb(self):
        d = self.insertTestData([
            fakedb.Change(changeid=13),
            fakedb.ChangeProperty(changeid=13,
                                  property_name='foo',
                                  property_value='"my prop"'),
            fakedb.SourceStamp(id=23),
            fakedb.Buildset(id=33, sourcestampid=23),
            fakedb.BuildsetProperty(buildsetid=33,
                                    property_name='bar',
                                    property_value='["other prop", "BS"]'),
        ])

        def do_test(_):
            cprops = self.dbc.get_properties_from_db("change_properties",
                                                     "changeid", 13)
            bprops = self.dbc.get_properties_from_db("buildset_properties",
                                                     "buildsetid", 33)
            self.assertEqual(cprops.asList() + bprops.asList(),
                             [('foo', 'my prop', 'Change'),
                              ('bar', 'other prop', 'BS')])

        d.addCallback(do_test)
        return d
コード例 #7
0
class Change(unittest.TestCase):

    change23_rows = [
        fakedb.Change(changeid=23,
                      author="dustin",
                      comments="fix whitespace",
                      branch="warnerdb",
                      revision="deadbeef",
                      when_timestamp=266738404,
                      revlink='http://warner/0e92a098b',
                      category='devel',
                      repository='git://warner',
                      codebase='mainapp',
                      project='Buildbot'),
        fakedb.ChangeFile(changeid=23, filename='master/README.txt'),
        fakedb.ChangeFile(changeid=23, filename='worker/README.txt'),
        fakedb.ChangeProperty(changeid=23,
                              property_name='notest',
                              property_value='["no","Change"]'),
        fakedb.ChangeUser(changeid=23, uid=27),
    ]

    def setUp(self):
        self.master = fakemaster.make_master(testcase=self, wantDb=True)
        self.change23 = changes.Change(
            **dict(  # using **dict(..) forces kwargs
                category='devel',
                repository=u'git://warner',
                codebase=u'mainapp',
                who=u'dustin',
                when=266738404,
                comments=u'fix whitespace',
                project=u'Buildbot',
                branch=u'warnerdb',
                revlink=u'http://warner/0e92a098b',
                properties={'notest': "no"},
                files=[u'master/README.txt', u'worker/README.txt'],
                revision=u'deadbeef'))
        self.change23.number = 23

    @defer.inlineCallbacks
    def test_fromChdict(self):
        # get a real honest-to-goodness chdict from the fake db
        yield self.master.db.insertTestData(self.change23_rows)
        chdict = yield self.master.db.changes.getChange(23)

        exp = self.change23
        got = yield changes.Change.fromChdict(self.master, chdict)

        # compare
        ok = True
        ok = ok and got.number == exp.number
        ok = ok and got.who == exp.who
        ok = ok and sorted(got.files) == sorted(exp.files)
        ok = ok and got.comments == exp.comments
        ok = ok and got.revision == exp.revision
        ok = ok and got.when == exp.when
        ok = ok and got.branch == exp.branch
        ok = ok and got.category == exp.category
        ok = ok and got.revlink == exp.revlink
        ok = ok and got.properties == exp.properties
        ok = ok and got.repository == exp.repository
        ok = ok and got.codebase == exp.codebase
        ok = ok and got.project == exp.project
        if not ok:

            def printable(c):
                return pprint.pformat(c.__dict__)

            self.fail("changes do not match; expected\n%s\ngot\n%s" %
                      (printable(exp), printable(got)))

    def test_str(self):
        string = str(self.change23)
        self.assertTrue(re.match(r"Change\(.*\)", string), string)

    def test_asText(self):
        text = self.change23.asText()
        self.assertTrue(
            re.match(
                textwrap.dedent(u'''\
            Files:
             master/README.txt
             worker/README.txt
            On: git://warner
            For: Buildbot
            At: .*
            Changed By: dustin
            Comments: fix whitespaceProperties:.
              notest: no

            '''), text), text)

    def test_asDict(self):
        dict = self.change23.asDict()
        self.assertIn('1978', dict['at'])  # timezone-sensitive
        del dict['at']
        self.assertEqual(
            dict, {
                'branch':
                u'warnerdb',
                'category':
                u'devel',
                'codebase':
                u'mainapp',
                'comments':
                u'fix whitespace',
                'files': [{
                    'name': u'master/README.txt'
                }, {
                    'name': u'worker/README.txt'
                }],
                'number':
                23,
                'project':
                u'Buildbot',
                'properties': [('notest', 'no', 'Change')],
                'repository':
                u'git://warner',
                'rev':
                u'deadbeef',
                'revision':
                u'deadbeef',
                'revlink':
                u'http://warner/0e92a098b',
                'when':
                266738404,
                'who':
                u'dustin'
            })

    def test_getShortAuthor(self):
        self.assertEqual(self.change23.getShortAuthor(), 'dustin')

    def test_getTime(self):
        # careful, or timezones will hurt here
        self.assertIn('Jun 1978', self.change23.getTime())

    def test_getTimes(self):
        self.assertEqual(self.change23.getTimes(), (266738404, None))

    def test_getText(self):
        self.change23.who = 'nasty < nasty'  # test the html escaping (ugh!)
        self.assertEqual(self.change23.getText(), ['nasty &lt; nasty'])

    def test_getLogs(self):
        self.assertEqual(self.change23.getLogs(), {})
コード例 #8
0
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 range(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
コード例 #9
0
ファイル: test_db_changes.py プロジェクト: crogers1/buildbot
class TestChangesConnectorComponent(
    connector_component.ConnectorComponentMixin,
        unittest.TestCase):

    def setUp(self):
        d = self.setUpConnectorComponent(
            table_names=['changes', 'change_files',
                         'change_properties', 'scheduler_changes', 'objects',
                         'sourcestampsets', 'sourcestamps', 'sourcestamp_changes',
                         'patches', 'change_users', 'users'])

        def finish_setup(_):
            self.db.changes = changes.ChangesConnectorComponent(self.db)
        d.addCallback(finish_setup)

        return d

    def tearDown(self):
        return self.tearDownConnectorComponent()

    # common sample data

    change13_rows = [
        fakedb.Change(changeid=13, author="dustin", comments="fix spelling",
                      is_dir=0, branch="master", revision="deadbeef",
                      when_timestamp=266738400, revlink=None, category=None,
                      repository='', codebase='', project=''),

        fakedb.ChangeFile(changeid=13, filename='master/README.txt'),
        fakedb.ChangeFile(changeid=13, filename='slave/README.txt'),

        fakedb.ChangeProperty(changeid=13, property_name='notest',
                              property_value='["no","Change"]'),
    ]

    change14_rows = [
        fakedb.Change(changeid=14, author="warner", comments="fix whitespace",
                      is_dir=0, branch="warnerdb", revision="0e92a098b",
                      when_timestamp=266738404, revlink='http://warner/0e92a098b',
                      category='devel', repository='git://warner', codebase='mainapp',
                      project='Buildbot'),

        fakedb.ChangeFile(changeid=14, filename='master/buildbot/__init__.py'),
    ]

    change14_dict = {
        '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',
        'codebase': u'mainapp',
        'revision': u'0e92a098b',
        'revlink': u'http://warner/0e92a098b',
        'when_timestamp': epoch2datetime(266738404),
    }

    def change14(self):
        c = Change(**dict(
            category='devel',
            isdir=0,
            repository=u'git://warner',
            codebase=u'mainapp',
            who=u'warner',
            when=266738404,
            comments=u'fix whitespace',
            project=u'Buildbot',
            branch=u'warnerdb',
            revlink=u'http://warner/0e92a098b',
            properties={},
            files=[u'master/buildbot/__init__.py'],
            revision=u'0e92a098b'))
        c.number = 14
        return c

    # assertions

    def assertChangesEqual(self, ca, cb):
        ok = True
        ok = ok and ca.number == cb.number
        ok = ok and ca.who == cb.who
        ok = ok and sorted(ca.files) == sorted(cb.files)
        ok = ok and ca.comments == cb.comments
        ok = ok and bool(ca.isdir) == bool(cb.isdir)
        ok = ok and ca.revision == cb.revision
        ok = ok and ca.when == cb.when
        ok = ok and ca.branch == cb.branch
        ok = ok and ca.category == cb.category
        ok = ok and ca.revlink == cb.revlink
        ok = ok and ca.properties == cb.properties
        ok = ok and ca.repository == cb.repository
        ok = ok and ca.codebase == cb.codebase
        ok = ok and ca.project == cb.project
        if not ok:
            def printable(c):
                return pprint.pformat(c.__dict__)
            self.fail("changes do not match; expected\n%s\ngot\n%s" %
                      (printable(ca), printable(cb)))

    # tests

    def test_getChange(self):
        d = self.insertTestData(self.change14_rows)

        def get14(_):
            return self.db.changes.getChange(14)
        d.addCallback(get14)

        def check14(chdict):
            self.assertEqual(chdict, self.change14_dict)
        d.addCallback(check14)
        return d

    def test_Change_fromChdict_with_chdict(self):
        # test that the chdict getChange returns works with Change.fromChdict
        d = Change.fromChdict(mock.Mock(), self.change14_dict)

        def check(c):
            self.assertChangesEqual(c, self.change14())
        d.addCallback(check)
        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_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_addChange(self):
        d = self.db.changes.addChange(
            author=u'dustin',
            files=[u'master/LICENSING.txt', u'slave/LICENSING.txt'],
            comments=u'fix spelling',
            is_dir=0,
            revision=u'2d6caa52',
            when_timestamp=epoch2datetime(266738400),
            branch=u'master',
            category=None,
            revlink=None,
            properties={u'platform': (u'linux', 'Change')},
            repository=u'',
            codebase=u'',
            project=u'')
        # 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.assertFalse(r[0].is_dir)
                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, '')
                self.assertEqual(r[0].project, '')
            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, 'slave/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)
        return d

    def test_addChange_when_timestamp_None(self):
        clock = task.Clock()
        clock.advance(1239898353)
        d = self.db.changes.addChange(
            author=u'dustin',
            files=[],
            comments=u'fix spelling',
            is_dir=0,
            revision=u'2d6caa52',
            when_timestamp=None,
            branch=u'master',
            category=None,
            revlink=None,
            properties={},
            repository=u'',
            codebase=u'',
            project=u'',
            _reactor=clock)
        # check all of the columns of the four 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, 1239898353)
            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), 0)
            return self.db.pool.do(thd)
        d.addCallback(check_change_users)
        return d

    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',
                          is_dir=0,
                          revision=u'2d6caa52',
                          when_timestamp=epoch2datetime(1239898353),
                          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, 1239898353)
            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 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.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_pruneChanges(self):
        d = self.insertTestData(
            [
                fakedb.Object(id=29),
                fakedb.SourceStamp(id=234),

                fakedb.Change(changeid=11),

                fakedb.Change(changeid=12),
                fakedb.SchedulerChange(objectid=29, changeid=12),
                fakedb.SourceStampChange(sourcestampid=234, changeid=12),
            ] +

            self.change13_rows +
            [
                fakedb.SchedulerChange(objectid=29, changeid=13),
            ] +

            self.change14_rows +
            [
                fakedb.SchedulerChange(objectid=29, changeid=14),

                fakedb.Change(changeid=15),
                fakedb.SourceStampChange(sourcestampid=234, changeid=15),
            ]
        )

        # pruning with a horizon of 2 should delete changes 11, 12 and 13
        d.addCallback(lambda _: self.db.changes.pruneChanges(2))

        def check(_):
            def thd(conn):
                results = {}
                for tbl_name in ('scheduler_changes', 'sourcestamp_changes',
                                 'change_files', 'change_properties',
                                 'changes'):
                    tbl = self.db.model.metadata.tables[tbl_name]
                    res = conn.execute(sa.select([tbl.c.changeid]))
                    results[tbl_name] = sorted([row[0] for row in res.fetchall()])
                self.assertEqual(results, {
                    'scheduler_changes': [14],
                    'sourcestamp_changes': [15],
                    'change_files': [14],
                    'change_properties': [],
                    'changes': [14, 15],
                })
            return self.db.pool.do(thd)
        d.addCallback(check)
        return d

    def test_pruneChanges_lots(self):
        d = self.insertTestData([
            fakedb.Change(changeid=n)
            for n in xrange(1, 151)
        ])

        d.addCallback(lambda _: self.db.changes.pruneChanges(1))

        def check(_):
            def thd(conn):
                results = {}
                for tbl_name in ('scheduler_changes', 'sourcestamp_changes',
                                 'change_files', 'change_properties',
                                 'changes'):
                    tbl = self.db.model.metadata.tables[tbl_name]
                    res = conn.execute(sa.select([tbl.c.changeid]))
                    results[tbl_name] = len([row for row in res.fetchall()])
                self.assertEqual(results, {
                    'scheduler_changes': 0,
                    'sourcestamp_changes': 0,
                    'change_files': 0,
                    'change_properties': 0,
                    'changes': 1,
                })
            return self.db.pool.do(thd)
        d.addCallback(check)
        return d

    def test_pruneChanges_None(self):
        d = self.insertTestData(self.change13_rows)

        d.addCallback(lambda _: self.db.changes.pruneChanges(None))

        def check(_):
            def thd(conn):
                tbl = self.db.model.changes
                res = conn.execute(tbl.select())
                self.assertEqual([row.changeid for row in res.fetchall()],
                                 [13])
            return self.db.pool.do(thd)
        d.addCallback(check)
        return d

    def test_getRecentChanges_subset(self):
        d = self.insertTestData([
            fakedb.Change(changeid=8),
            fakedb.Change(changeid=9),
            fakedb.Change(changeid=10),
            fakedb.Change(changeid=11),
            fakedb.Change(changeid=12),
        ] + self.change13_rows + self.change14_rows)
        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_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)
        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 5, but only got 2
            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', 'slave/README.txt']))
            self.assertEqual(changes[0]['properties'],
                             {'notest': ('no', 'Change')})
        d.addCallback(check)
        return d
コード例 #10
0
class TestChangesConnectorComponent(
        connector_component.ConnectorComponentMixin, unittest.TestCase):
    def setUp(self):
        d = self.setUpConnectorComponent(table_names=[
            'changes', 'change_links', 'change_files', 'change_properties',
            'scheduler_changes', 'schedulers', 'sourcestamps',
            'sourcestamp_changes', 'patches'
        ])

        def finish_setup(_):
            self.db.changes = changes.ChangesConnectorComponent(self.db)

        d.addCallback(finish_setup)

        return d

    def tearDown(self):
        return self.tearDownConnectorComponent()

    # common sample data

    change13_rows = [
        fakedb.Change(changeid=13,
                      author="dustin",
                      comments="fix spelling",
                      is_dir=0,
                      branch="master",
                      revision="deadbeef",
                      when_timestamp=266738400,
                      revlink=None,
                      category=None,
                      repository='',
                      project=''),
        fakedb.ChangeLink(changeid=13, link='http://buildbot.net'),
        fakedb.ChangeLink(changeid=13, link='http://sf.net/projects/buildbot'),
        fakedb.ChangeFile(changeid=13, filename='master/README.txt'),
        fakedb.ChangeFile(changeid=13, filename='slave/README.txt'),
        fakedb.ChangeProperty(changeid=13,
                              property_name='notest',
                              property_value='"no"'),
    ]

    def change13(self):
        c = Change(**dict(
            category=None,
            isdir=0,
            repository=u'',
            links=[u'http://buildbot.net', u'http://sf.net/projects/buildbot'],
            who=u'dustin',
            when=266738400,
            comments=u'fix spelling',
            project=u'',
            branch=u'master',
            revlink=None,
            properties={u'notest': u'no'},
            files=[u'master/README.txt', u'slave/README.txt'],
            revision=u'deadbeef'))
        c.number = 13
        return c

    change14_rows = [
        fakedb.Change(changeid=14,
                      author="warner",
                      comments="fix whitespace",
                      is_dir=0,
                      branch="warnerdb",
                      revision="0e92a098b",
                      when_timestamp=266738404,
                      revlink='http://warner/0e92a098b',
                      category='devel',
                      repository='git://warner',
                      project='Buildbot'),
        fakedb.ChangeFile(changeid=14, filename='master/buildbot/__init__.py'),
    ]

    def change14(self):
        c = Change(**dict(category='devel',
                          isdir=0,
                          repository=u'git://warner',
                          links=[],
                          who=u'warner',
                          when=266738404,
                          comments=u'fix whitespace',
                          project=u'Buildbot',
                          branch=u'warnerdb',
                          revlink=u'http://warner/0e92a098b',
                          properties={},
                          files=[u'master/buildbot/__init__.py'],
                          revision=u'0e92a098b'))
        c.number = 14
        return c

    # assertions

    def assertChangesEqual(self, a, b):
        if len(a) != len(b):
            ok = False
        else:
            ok = True
            for i in xrange(len(a)):
                ca = a[i]
                cb = b[i]
                ok = ok and ca.number == cb.number
                ok = ok and ca.who == cb.who
                ok = ok and sorted(ca.files) == sorted(cb.files)
                ok = ok and ca.comments == cb.comments
                ok = ok and bool(ca.isdir) == bool(cb.isdir)
                ok = ok and sorted(ca.links) == sorted(cb.links)
                ok = ok and ca.revision == cb.revision
                ok = ok and ca.when == cb.when
                ok = ok and ca.branch == cb.branch
                ok = ok and ca.category == cb.category
                ok = ok and ca.revlink == cb.revlink
                ok = ok and ca.properties == cb.properties
                ok = ok and ca.repository == cb.repository
                ok = ok and ca.project == cb.project
                if not ok: break
        if not ok:

            def printable(clist):
                return pprint.pformat([c.__dict__ for c in clist])

            self.fail("changes do not match; expected\n%s\ngot\n%s" %
                      (printable(a), printable(b)))

    # tests

    def test_getChangeInstance(self):
        d = self.insertTestData(self.change14_rows)

        def get14(_):
            return self.db.changes.getChangeInstance(14)

        d.addCallback(get14)

        def check14(c):
            self.assertChangesEqual([c], [self.change14()])

        d.addCallback(check14)
        return d

    def test_getChangeInstance_missing(self):
        d = defer.succeed(None)

        def get14(_):
            return self.db.changes.getChangeInstance(14)

        d.addCallback(get14)

        def check14(c):
            self.failUnless(c is None)

        d.addCallback(check14)
        return d

    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_addChange(self):
        d = self.db.changes.addChange(
            who=u'dustin',
            files=[u'master/LICENSING.txt', u'slave/LICENSING.txt'],
            comments=u'fix spelling',
            isdir=0,
            links=[u'http://slashdot.org', u'http://wired.com/g'],
            revision=u'2d6caa52ab39fbac83cee03dcf2ccb7e41eaad86',
            when=266738400,
            branch=u'master',
            category=None,
            revlink=None,
            properties={u'platform': u'linux'},
            repository=u'',
            project=u'')

        # check all of the columns of the four relevant tables
        def check_change(change):
            self.assertEqual(change.number, 1)
            self.assertEqual(change.who, 'dustin')
            self.assertEqual(
                sorted(change.files),
                sorted([u'master/LICENSING.txt', u'slave/LICENSING.txt']))
            self.assertEqual(change.comments, 'fix spelling')
            self.assertFalse(change.isdir)
            self.assertEqual(
                sorted(change.links),
                sorted([u'http://slashdot.org', u'http://wired.com/g']))
            self.assertEqual(change.revision,
                             '2d6caa52ab39fbac83cee03dcf2ccb7e41eaad86')
            self.assertEqual(change.when, 266738400)
            self.assertEqual(change.category, None)
            self.assertEqual(change.revlink, None)
            self.assertEqual(change.properties.asList(),
                             [('platform', 'linux', 'Change')])
            self.assertEqual(change.repository, '')
            self.assertEqual(change.project, '')

            def thd(conn):
                r = conn.execute(self.db.model.changes.select())
                r = r.fetchall()
                self.assertEqual(len(r), 1)
                self.assertEqual(r[0].changeid, 1)
                self.assertEqual(r[0].author, 'dustin')
                self.assertEqual(r[0].comments, 'fix spelling')
                self.assertFalse(r[0].is_dir)
                self.assertEqual(r[0].branch, 'master')
                self.assertEqual(r[0].revision,
                                 '2d6caa52ab39fbac83cee03dcf2ccb7e41eaad86')
                self.assertEqual(r[0].when_timestamp, 266738400)
                self.assertEqual(r[0].category, None)
                self.assertEqual(r[0].repository, '')
                self.assertEqual(r[0].project, '')

            return self.db.pool.do(thd)

        d.addCallback(check_change)

        def check_change_links(_):
            def thd(conn):
                query = self.db.model.change_links.select()
                query.where(self.db.model.change_links.c.changeid == 1)
                query.order_by([self.db.model.change_links.c.link])
                r = conn.execute(query)
                r = r.fetchall()
                self.assertEqual(len(r), 2)
                self.assertEqual(r[0].link, 'http://slashdot.org')
                self.assertEqual(r[1].link, 'http://wired.com/g')

            return self.db.pool.do(thd)

        d.addCallback(check_change_links)

        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, 'slave/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"')  # JSON-encoded

            return self.db.pool.do(thd)

        d.addCallback(check_change_properties)
        return d

    def test_prune_changes(self):
        self.db.changes.changeHorizon = 1

        # prune_changes prunes from a lot of tables
        # TODO: add data to them to check!
        d = self.insertTestData(self.change13_rows + self.change14_rows)
        d.addCallback(lambda _: self.db.changes._prune_changes(14))

        def check(_):
            def thd(conn):
                changes_tbl = self.db.model.changes
                r = conn.execute(sa.select([changes_tbl.c.changeid]))
                self.assertEqual([r.changeid for r in r.fetchall()], [14])

            return self.db.pool.do(thd)

        d.addCallback(check)
        return d

    def test_getRecentChangeInstances_subset(self):
        d = self.insertTestData([
            fakedb.Change(changeid=8),
            fakedb.Change(changeid=9),
            fakedb.Change(changeid=10),
            fakedb.Change(changeid=11),
            fakedb.Change(changeid=12),
        ] + self.change13_rows + self.change14_rows)
        d.addCallback(lambda _: self.db.changes.getRecentChangeInstances(5))

        def check(changes):
            changeids = [c.number for c in changes]
            self.assertEqual(changeids, [10, 11, 12, 13, 14])

        d.addCallback(check)
        return d

    def test_getRecentChangeInstances_empty(self):
        d = defer.succeed(None)
        d.addCallback(lambda _: self.db.changes.getRecentChangeInstances(5))

        def check(changes):
            changeids = [c.number for c in changes]
            self.assertEqual(changeids, [])

        d.addCallback(check)
        return d

    def test_getRecentChangeInstances_missing(self):
        d = self.insertTestData(self.change13_rows + self.change14_rows)
        d.addCallback(lambda _: self.db.changes.getRecentChangeInstances(5))

        def check(changes):
            # requested 5, but only got 2
            changeids = [c.number 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', 'slave/README.txt']))
            self.assertEqual(
                sorted(changes[0].links),
                sorted(
                    ['http://buildbot.net',
                     'http://sf.net/projects/buildbot']))
            self.assertEqual(changes[0].properties.asList(),
                             [('notest', 'no', 'Change')])

        d.addCallback(check)
        return d
コード例 #11
0
class Change(unittest.TestCase):

    change23_rows = [
        fakedb.Change(changeid=23,
                      author="dustin",
                      comments="fix whitespace",
                      is_dir=0,
                      branch="warnerdb",
                      revision="deadbeef",
                      when_timestamp=266738404,
                      revlink='http://warner/0e92a098b',
                      category='devel',
                      repository='git://warner',
                      codebase='mainapp',
                      project='Buildbot'),
        fakedb.ChangeFile(changeid=23, filename='master/README.txt'),
        fakedb.ChangeFile(changeid=23, filename='slave/README.txt'),
        fakedb.ChangeProperty(changeid=23,
                              property_name='notest',
                              property_value='["no","Change"]'),
        fakedb.ChangeUser(changeid=23, uid=27),
    ]

    def setUp(self):
        self.change23 = changes.Change(
            **dict(  # using **dict(..) forces kwargs
                category='devel',
                isdir=0,
                repository=u'git://warner',
                codebase=u'mainapp',
                who=u'dustin',
                when=266738404,
                comments=u'fix whitespace',
                project=u'Buildbot',
                branch=u'warnerdb',
                revlink=u'http://warner/0e92a098b',
                properties={'notest': "no"},
                files=[u'master/README.txt', u'slave/README.txt'],
                revision=u'deadbeef'))
        self.change23.number = 23

    def test_str(self):
        string = str(self.change23)
        self.assertTrue(re.match(r"Change\(.*\)", string), string)

    def test_asText(self):
        text = self.change23.asText()
        self.assertTrue(
            re.match(
                textwrap.dedent(u'''\
            Files:
             master/README.txt
             slave/README.txt
            On: git://warner
            For: Buildbot
            At: .*
            Changed By: dustin
            Comments: fix whitespaceProperties: 
              notest: no

            '''), text), text)

    def test_asDict(self):
        dict = self.change23.asDict()
        self.assertIn('1978', dict['at'])  # timezone-sensitive
        del dict['at']
        self.assertEqual(
            dict, {
                'branch':
                u'warnerdb',
                'category':
                u'devel',
                'codebase':
                u'mainapp',
                'comments':
                u'fix whitespace',
                'files': [{
                    'name': u'master/README.txt'
                }, {
                    'name': u'slave/README.txt'
                }],
                'number':
                23,
                'project':
                u'Buildbot',
                'properties': [('notest', 'no', 'Change')],
                'repository':
                u'git://warner',
                'rev':
                u'deadbeef',
                'revision':
                u'deadbeef',
                'revlink':
                u'http://warner/0e92a098b',
                'when':
                266738404,
                'who':
                u'dustin'
            })

    def test_getShortAuthor(self):
        self.assertEqual(self.change23.getShortAuthor(), 'dustin')

    def test_getTime(self):
        # careful, or timezones will hurt here
        self.assertIn('Jun 1978', self.change23.getTime())

    def test_getTimes(self):
        self.assertEqual(self.change23.getTimes(), (266738404, None))

    def test_getText(self):
        self.change23.who = 'nasty < nasty'  # test the html escaping (ugh!)
        self.assertEqual(self.change23.getText(), ['nasty &lt; nasty'])

    def test_getLogs(self):
        self.assertEqual(self.change23.getLogs(), {})