| OLD | NEW |
| (Empty) |
| 1 # -*- test-case-name: buildbot.test.test_changes -*- | |
| 2 | |
| 3 from twisted.trial import unittest | |
| 4 from twisted.internet import defer, reactor | |
| 5 | |
| 6 from buildbot import master | |
| 7 from buildbot.changes import pb | |
| 8 from buildbot.scripts import runner | |
| 9 | |
| 10 import sys | |
| 11 if sys.version_info[:3] < (2,4,0): | |
| 12 from sets import Set as set | |
| 13 | |
| 14 d1 = {'files': ["Project/foo.c", "Project/bar/boo.c"], | |
| 15 'who': "marvin", | |
| 16 'comments': "Some changes in Project"} | |
| 17 d2 = {'files': ["OtherProject/bar.c"], | |
| 18 'who': "zaphod", | |
| 19 'comments': "other changes"} | |
| 20 d3 = {'files': ["Project/baz.c", "OtherProject/bloo.c"], | |
| 21 'who': "alice", | |
| 22 'comments': "mixed changes"} | |
| 23 d4 = {'files': ["trunk/baz.c", "branches/foobranch/foo.c", "trunk/bar.c"], | |
| 24 'who': "alice", | |
| 25 'comments': "mixed changes"} | |
| 26 d5 = {'files': ["Project/foo.c"], | |
| 27 'who': "trillian", | |
| 28 'comments': "Some changes in Project", | |
| 29 'category': "categoryA"} | |
| 30 | |
| 31 class TestChangePerspective(unittest.TestCase): | |
| 32 | |
| 33 def setUp(self): | |
| 34 self.changes = [] | |
| 35 | |
| 36 def addChange(self, c): | |
| 37 self.changes.append(c) | |
| 38 | |
| 39 def testNoPrefix(self): | |
| 40 p = pb.ChangePerspective(self, None) | |
| 41 p.perspective_addChange(d1) | |
| 42 self.failUnlessEqual(len(self.changes), 1) | |
| 43 c1 = self.changes[0] | |
| 44 self.failUnlessEqual(set(c1.files), | |
| 45 set(["Project/foo.c", "Project/bar/boo.c"])) | |
| 46 self.failUnlessEqual(c1.comments, "Some changes in Project") | |
| 47 self.failUnlessEqual(c1.who, "marvin") | |
| 48 | |
| 49 def testPrefix(self): | |
| 50 p = pb.ChangePerspective(self, "Project/") | |
| 51 | |
| 52 p.perspective_addChange(d1) | |
| 53 self.failUnlessEqual(len(self.changes), 1) | |
| 54 c1 = self.changes[-1] | |
| 55 self.failUnlessEqual(set(c1.files), set(["foo.c", "bar/boo.c"])) | |
| 56 self.failUnlessEqual(c1.comments, "Some changes in Project") | |
| 57 self.failUnlessEqual(c1.who, "marvin") | |
| 58 | |
| 59 p.perspective_addChange(d2) # should be ignored | |
| 60 self.failUnlessEqual(len(self.changes), 1) | |
| 61 | |
| 62 p.perspective_addChange(d3) # should ignore the OtherProject file | |
| 63 self.failUnlessEqual(len(self.changes), 2) | |
| 64 | |
| 65 c3 = self.changes[-1] | |
| 66 self.failUnlessEqual(set(c3.files), set(["baz.c"])) | |
| 67 self.failUnlessEqual(c3.comments, "mixed changes") | |
| 68 self.failUnlessEqual(c3.who, "alice") | |
| 69 | |
| 70 def testPrefix2(self): | |
| 71 p = pb.ChangePerspective(self, "Project/bar/") | |
| 72 | |
| 73 p.perspective_addChange(d1) | |
| 74 self.failUnlessEqual(len(self.changes), 1) | |
| 75 c1 = self.changes[-1] | |
| 76 self.failUnlessEqual(set(c1.files), set(["boo.c"])) | |
| 77 self.failUnlessEqual(c1.comments, "Some changes in Project") | |
| 78 self.failUnlessEqual(c1.who, "marvin") | |
| 79 | |
| 80 p.perspective_addChange(d2) # should be ignored | |
| 81 self.failUnlessEqual(len(self.changes), 1) | |
| 82 | |
| 83 p.perspective_addChange(d3) # should ignore this too | |
| 84 self.failUnlessEqual(len(self.changes), 1) | |
| 85 | |
| 86 def testPrefix3(self): | |
| 87 p = pb.ChangePerspective(self, "trunk/") | |
| 88 | |
| 89 p.perspective_addChange(d4) | |
| 90 self.failUnlessEqual(len(self.changes), 1) | |
| 91 c1 = self.changes[-1] | |
| 92 self.failUnlessEqual(set(c1.files), set(["baz.c", "bar.c"])) | |
| 93 self.failUnlessEqual(c1.comments, "mixed changes") | |
| 94 | |
| 95 def testPrefix4(self): | |
| 96 p = pb.ChangePerspective(self, "branches/foobranch/") | |
| 97 | |
| 98 p.perspective_addChange(d4) | |
| 99 self.failUnlessEqual(len(self.changes), 1) | |
| 100 c1 = self.changes[-1] | |
| 101 self.failUnlessEqual(set(c1.files), set(["foo.c"])) | |
| 102 self.failUnlessEqual(c1.comments, "mixed changes") | |
| 103 | |
| 104 def testCategory(self): | |
| 105 p = pb.ChangePerspective(self, None) | |
| 106 p.perspective_addChange(d5) | |
| 107 self.failUnlessEqual(len(self.changes), 1) | |
| 108 c1 = self.changes[0] | |
| 109 self.failUnlessEqual(c1.category, "categoryA") | |
| 110 | |
| 111 config_empty = """ | |
| 112 BuildmasterConfig = c = {} | |
| 113 c['slaves'] = [] | |
| 114 c['builders'] = [] | |
| 115 c['schedulers'] = [] | |
| 116 c['slavePortnum'] = 0 | |
| 117 """ | |
| 118 | |
| 119 config_sender = config_empty + \ | |
| 120 """ | |
| 121 from buildbot.changes import pb | |
| 122 c['change_source'] = pb.PBChangeSource(port=None) | |
| 123 """ | |
| 124 | |
| 125 class Sender(unittest.TestCase): | |
| 126 def setUp(self): | |
| 127 self.master = master.BuildMaster(".") | |
| 128 def tearDown(self): | |
| 129 d = defer.maybeDeferred(self.master.stopService) | |
| 130 # TODO: something in Twisted-2.0.0 (and probably 2.0.1) doesn't shut | |
| 131 # down the Broker listening socket when it's supposed to. | |
| 132 # Twisted-1.3.0, and current SVN (which will be post-2.0.1) are ok. | |
| 133 # This iterate() is a quick hack to deal with the problem. I need to | |
| 134 # investigate more thoroughly and find a better solution. | |
| 135 d.addCallback(self.stall, 0.1) | |
| 136 return d | |
| 137 | |
| 138 def stall(self, res, timeout): | |
| 139 d = defer.Deferred() | |
| 140 reactor.callLater(timeout, d.callback, res) | |
| 141 return d | |
| 142 | |
| 143 def testSender(self): | |
| 144 self.master.loadConfig(config_empty) | |
| 145 self.master.startService() | |
| 146 # TODO: BuildMaster.loadChanges replaces the change_svc object, so we | |
| 147 # have to load it twice. Clean this up. | |
| 148 d = self.master.loadConfig(config_sender) | |
| 149 d.addCallback(self._testSender_1) | |
| 150 return d | |
| 151 | |
| 152 def _testSender_1(self, res): | |
| 153 self.cm = cm = self.master.change_svc | |
| 154 s1 = list(self.cm)[0] | |
| 155 port = self.master.slavePort._port.getHost().port | |
| 156 | |
| 157 self.options = {'username': "alice", | |
| 158 'master': "localhost:%d" % port, | |
| 159 'files': ["foo.c"], | |
| 160 'category': "categoryA", | |
| 161 } | |
| 162 | |
| 163 d = runner.sendchange(self.options) | |
| 164 d.addCallback(self._testSender_2) | |
| 165 return d | |
| 166 | |
| 167 def _testSender_2(self, res): | |
| 168 # now check that the change was received | |
| 169 self.failUnlessEqual(len(self.cm.changes), 1) | |
| 170 c = self.cm.changes.pop() | |
| 171 self.failUnlessEqual(c.who, "alice") | |
| 172 self.failUnlessEqual(c.files, ["foo.c"]) | |
| 173 self.failUnlessEqual(c.comments, "") | |
| 174 self.failUnlessEqual(c.revision, None) | |
| 175 self.failUnlessEqual(c.category, "categoryA") | |
| 176 | |
| 177 self.options['revision'] = "r123" | |
| 178 self.options['comments'] = "test change" | |
| 179 | |
| 180 d = runner.sendchange(self.options) | |
| 181 d.addCallback(self._testSender_3) | |
| 182 return d | |
| 183 | |
| 184 def _testSender_3(self, res): | |
| 185 self.failUnlessEqual(len(self.cm.changes), 1) | |
| 186 c = self.cm.changes.pop() | |
| 187 self.failUnlessEqual(c.who, "alice") | |
| 188 self.failUnlessEqual(c.files, ["foo.c"]) | |
| 189 self.failUnlessEqual(c.comments, "test change") | |
| 190 self.failUnlessEqual(c.revision, "r123") | |
| 191 self.failUnlessEqual(c.category, "categoryA") | |
| 192 | |
| 193 # test options['logfile'] by creating a temporary file | |
| 194 logfile = self.mktemp() | |
| 195 f = open(logfile, "wt") | |
| 196 f.write("longer test change") | |
| 197 f.close() | |
| 198 self.options['comments'] = None | |
| 199 self.options['logfile'] = logfile | |
| 200 | |
| 201 d = runner.sendchange(self.options) | |
| 202 d.addCallback(self._testSender_4) | |
| 203 return d | |
| 204 | |
| 205 def _testSender_4(self, res): | |
| 206 self.failUnlessEqual(len(self.cm.changes), 1) | |
| 207 c = self.cm.changes.pop() | |
| 208 self.failUnlessEqual(c.who, "alice") | |
| 209 self.failUnlessEqual(c.files, ["foo.c"]) | |
| 210 self.failUnlessEqual(c.comments, "longer test change") | |
| 211 self.failUnlessEqual(c.revision, "r123") | |
| 212 self.failUnlessEqual(c.category, "categoryA") | |
| 213 | |
| 214 # make sure that numeric revisions work too | |
| 215 self.options['logfile'] = None | |
| 216 del self.options['revision'] | |
| 217 self.options['revision_number'] = 42 | |
| 218 | |
| 219 d = runner.sendchange(self.options) | |
| 220 d.addCallback(self._testSender_5) | |
| 221 return d | |
| 222 | |
| 223 def _testSender_5(self, res): | |
| 224 self.failUnlessEqual(len(self.cm.changes), 1) | |
| 225 c = self.cm.changes.pop() | |
| 226 self.failUnlessEqual(c.who, "alice") | |
| 227 self.failUnlessEqual(c.files, ["foo.c"]) | |
| 228 self.failUnlessEqual(c.comments, "") | |
| 229 self.failUnlessEqual(c.revision, 42) | |
| 230 self.failUnlessEqual(c.category, "categoryA") | |
| 231 | |
| 232 # verify --branch too | |
| 233 self.options['branch'] = "branches/test" | |
| 234 | |
| 235 d = runner.sendchange(self.options) | |
| 236 d.addCallback(self._testSender_6) | |
| 237 return d | |
| 238 | |
| 239 def _testSender_6(self, res): | |
| 240 self.failUnlessEqual(len(self.cm.changes), 1) | |
| 241 c = self.cm.changes.pop() | |
| 242 self.failUnlessEqual(c.who, "alice") | |
| 243 self.failUnlessEqual(c.files, ["foo.c"]) | |
| 244 self.failUnlessEqual(c.comments, "") | |
| 245 self.failUnlessEqual(c.revision, 42) | |
| 246 self.failUnlessEqual(c.branch, "branches/test") | |
| 247 self.failUnlessEqual(c.category, "categoryA") | |
| OLD | NEW |