| Index: third_party/buildbot_7_12/buildbot/test/test_status.py
|
| diff --git a/third_party/buildbot_7_12/buildbot/test/test_status.py b/third_party/buildbot_7_12/buildbot/test/test_status.py
|
| deleted file mode 100644
|
| index 9488ca5e929b644abe9fd56fd040e9b2a310d3b5..0000000000000000000000000000000000000000
|
| --- a/third_party/buildbot_7_12/buildbot/test/test_status.py
|
| +++ /dev/null
|
| @@ -1,1907 +0,0 @@
|
| -# -*- test-case-name: buildbot.test.test_status -*-
|
| -
|
| -import email, os
|
| -import operator
|
| -
|
| -from zope.interface import implements
|
| -from twisted.internet import defer, reactor
|
| -from twisted.trial import unittest
|
| -
|
| -from buildbot import interfaces
|
| -from buildbot.sourcestamp import SourceStamp
|
| -from buildbot.process.base import BuildRequest, Build
|
| -from buildbot.status import builder, base, words, progress
|
| -from buildbot.changes.changes import Change
|
| -from buildbot.process.builder import Builder
|
| -from time import sleep
|
| -
|
| -import sys
|
| -if sys.version_info[:3] < (2,4,0):
|
| - from sets import Set as set
|
| -
|
| -mail = None
|
| -try:
|
| - from buildbot.status import mail
|
| -except ImportError:
|
| - pass
|
| -from buildbot.status import progress, client # NEEDS COVERAGE
|
| -from buildbot.test.runutils import RunMixin, setupBuildStepStatus, rmtree
|
| -
|
| -class MyStep:
|
| - build = None
|
| - def getName(self):
|
| - return "step"
|
| - def getResults(self):
|
| - return (builder.SUCCESS, "yay")
|
| -
|
| -class MyLogFileProducer(builder.LogFileProducer):
|
| - # The reactor.callLater(0) in LogFileProducer.resumeProducing is a bit of
|
| - # a nuisance from a testing point of view. This subclass adds a Deferred
|
| - # to that call so we can find out when it is complete.
|
| - def resumeProducing(self):
|
| - d = defer.Deferred()
|
| - reactor.callLater(0, self._resumeProducing, d)
|
| - return d
|
| - def _resumeProducing(self, d):
|
| - builder.LogFileProducer._resumeProducing(self)
|
| - reactor.callLater(0, d.callback, None)
|
| -
|
| -class MyLog(builder.LogFile):
|
| - def __init__(self, basedir, name, text=None, step=None):
|
| - self.fakeBuilderBasedir = basedir
|
| - if not step:
|
| - step = MyStep()
|
| - builder.LogFile.__init__(self, step, name, name)
|
| - if text:
|
| - self.addStdout(text)
|
| - self.finish()
|
| - def getFilename(self):
|
| - return os.path.join(self.fakeBuilderBasedir, self.name)
|
| -
|
| - def subscribeConsumer(self, consumer):
|
| - p = MyLogFileProducer(self, consumer)
|
| - d = p.resumeProducing()
|
| - return d
|
| -
|
| -class MyHTMLLog(builder.HTMLLogFile):
|
| - def __init__(self, basedir, name, html):
|
| - step = MyStep()
|
| - builder.HTMLLogFile.__init__(self, step, name, name, html)
|
| -
|
| -class MyLogSubscriber:
|
| - def __init__(self):
|
| - self.chunks = []
|
| - def logChunk(self, build, step, log, channel, text):
|
| - self.chunks.append((channel, text))
|
| -
|
| -class MyLogConsumer:
|
| - def __init__(self, limit=None):
|
| - self.chunks = []
|
| - self.finished = False
|
| - self.limit = limit
|
| - def registerProducer(self, producer, streaming):
|
| - self.producer = producer
|
| - self.streaming = streaming
|
| - def unregisterProducer(self):
|
| - self.producer = None
|
| - def writeChunk(self, chunk):
|
| - self.chunks.append(chunk)
|
| - if self.limit:
|
| - self.limit -= 1
|
| - if self.limit == 0:
|
| - self.producer.pauseProducing()
|
| - def finish(self):
|
| - self.finished = True
|
| -
|
| -if mail:
|
| - class MyMailer(mail.MailNotifier):
|
| - def sendMessage(self, m, recipients):
|
| - self.parent.messages.append((m, recipients))
|
| -
|
| -class MyStatus:
|
| - def getBuildbotURL(self):
|
| - return self.url
|
| - def getURLForThing(self, thing):
|
| - return None
|
| - def getProjectName(self):
|
| - return "myproj"
|
| -
|
| -class MyBuilder(builder.BuilderStatus):
|
| - nextBuildNumber = 0
|
| - def newBuild(self):
|
| - number = self.nextBuildNumber
|
| - self.nextBuildNumber += 1
|
| - s = MyBuild(self, number, None, False)
|
| - s.waitUntilFinished().addCallback(self._buildFinished)
|
| - return s
|
| -
|
| -class MyBuild(builder.BuildStatus):
|
| - testlogs = []
|
| - def __init__(self, parent, number, results, finished=True):
|
| - builder.BuildStatus.__init__(self, parent, number)
|
| - self.results = results
|
| - self.source = SourceStamp(revision="1.14")
|
| - self.reason = "build triggered by changes"
|
| - self.finished = finished
|
| - def getLogs(self):
|
| - return self.testlogs
|
| - def buildStarted(self, build, started):
|
| - self.started = started
|
| - self.builder.buildStarted(self)
|
| -
|
| -class MyLookup:
|
| - implements(interfaces.IEmailLookup)
|
| -
|
| - def getAddress(self, user):
|
| - d = defer.Deferred()
|
| - # With me now is Mr Thomas Walters of West Hartlepool who is totally
|
| - # invisible.
|
| - if user == "Thomas_Walters":
|
| - d.callback(None)
|
| - else:
|
| - d.callback(user + "@" + "dev.com")
|
| - return d
|
| -
|
| -def customTextMailMessage(attrs):
|
| - logLines = 3
|
| - text = list()
|
| - text.append("STATUS: %s" % attrs['result'].title())
|
| - text.append("")
|
| - text.extend([c.asText() for c in attrs['changes']])
|
| - text.append("")
|
| - name, url, lines, status = attrs['logs'][-1]
|
| - text.append("Last %d lines of '%s':" % (logLines, name))
|
| - text.extend(["\t%s\n" % line for line in lines[len(lines)-logLines:]])
|
| - text.append("")
|
| - text.append("Build number was: %s" % attrs['buildProperties']['buildnumber'])
|
| - text.append("")
|
| - text.append("-buildbot")
|
| - return ("\n".join(text), 'plain')
|
| -
|
| -def customHTMLMailMessage(attrs):
|
| - logLines = 3
|
| - text = list()
|
| - text.append("<h3>STATUS <a href='%s'>%s</a>:</h3>" % (attrs['buildURL'],
|
| - attrs['result'].title()))
|
| - text.append("<h4>Recent Changes:</h4>")
|
| - text.extend([c.asHTML() for c in attrs['changes']])
|
| - name, url, lines, status = attrs['logs'][-1]
|
| - text.append("<h4>Last %d lines of '%s':</h4>" % (logLines, name))
|
| - text.append("<p>")
|
| - text.append("<br>".join([line for line in lines[len(lines)-logLines:]]))
|
| - text.append("</p>")
|
| - text.append("<p>Build number was: %s</p>" % attrs['buildProperties']['buildnumber'])
|
| - text.append("<br>")
|
| - text.append("<b>-<a href='%s'>buildbot</a></b>" % attrs['buildbotURL'])
|
| - return ("\n".join(text), 'html')
|
| -
|
| -class Mail(unittest.TestCase):
|
| -
|
| - def setUp(self):
|
| - self.builder = MyBuilder("builder1")
|
| -
|
| - def stall(self, res, timeout):
|
| - d = defer.Deferred()
|
| - reactor.callLater(timeout, d.callback, res)
|
| - return d
|
| -
|
| - def makeBuild(self, number, results):
|
| - return MyBuild(self.builder, number, results)
|
| -
|
| - def failUnlessIn(self, substring, string):
|
| - self.failUnless(string.find(substring) != -1,
|
| - "didn't see '%s' in '%s'" % (substring, string))
|
| -
|
| - def getProjectName(self):
|
| - return "PROJECT"
|
| -
|
| - def getBuildbotURL(self):
|
| - return "BUILDBOT_URL"
|
| -
|
| - def getURLForThing(self, thing):
|
| - return None
|
| -
|
| - def testBuild1(self):
|
| - mailer = MyMailer(fromaddr="buildbot@example.com",
|
| - extraRecipients=["recip@example.com",
|
| - "recip2@example.com"],
|
| - lookup=mail.Domain("dev.com"))
|
| - mailer.parent = self
|
| - mailer.master_status = self
|
| - self.messages = []
|
| -
|
| - b1 = self.makeBuild(3, builder.SUCCESS)
|
| - b1.blamelist = ["bob"]
|
| -
|
| - mailer.buildFinished("builder1", b1, b1.results)
|
| - self.failUnless(len(self.messages) == 1)
|
| - m,r = self.messages.pop()
|
| - t = m.as_string()
|
| - self.failUnlessIn("To: bob@dev.com\n", t)
|
| - self.failUnlessIn("CC: recip2@example.com, recip@example.com\n", t)
|
| - self.failUnlessIn("From: buildbot@example.com\n", t)
|
| - self.failUnlessIn("Subject: buildbot success in PROJECT on builder1\n", t)
|
| - self.failUnlessIn("Date: ", t)
|
| - self.failUnlessIn("Build succeeded!\n", t)
|
| - self.failUnlessIn("Buildbot URL: BUILDBOT_URL\n", t)
|
| -
|
| - def testBuild2(self):
|
| - mailer = MyMailer(fromaddr="buildbot@example.com",
|
| - extraRecipients=["recip@example.com",
|
| - "recip2@example.com"],
|
| - lookup="dev.com",
|
| - sendToInterestedUsers=False)
|
| - mailer.parent = self
|
| - mailer.master_status = self
|
| - self.messages = []
|
| -
|
| - b1 = self.makeBuild(3, builder.SUCCESS)
|
| - b1.blamelist = ["bob"]
|
| -
|
| - mailer.buildFinished("builder1", b1, b1.results)
|
| - self.failUnless(len(self.messages) == 1)
|
| - m,r = self.messages.pop()
|
| - t = m.as_string()
|
| - self.failUnlessIn("To: recip2@example.com, "
|
| - "recip@example.com\n", t)
|
| - self.failUnlessIn("From: buildbot@example.com\n", t)
|
| - self.failUnlessIn("Subject: buildbot success in PROJECT on builder1\n", t)
|
| - self.failUnlessIn("Build succeeded!\n", t)
|
| - self.failUnlessIn("Buildbot URL: BUILDBOT_URL\n", t)
|
| -
|
| - def testBuildStatusCategory(self):
|
| - # a status client only interested in a category should only receive
|
| - # from that category
|
| - mailer = MyMailer(fromaddr="buildbot@example.com",
|
| - extraRecipients=["recip@example.com",
|
| - "recip2@example.com"],
|
| - lookup="dev.com",
|
| - sendToInterestedUsers=False,
|
| - categories=["debug"])
|
| -
|
| - mailer.parent = self
|
| - mailer.master_status = self
|
| - self.messages = []
|
| -
|
| - b1 = self.makeBuild(3, builder.SUCCESS)
|
| - b1.blamelist = ["bob"]
|
| -
|
| - mailer.buildFinished("builder1", b1, b1.results)
|
| - self.failIf(self.messages)
|
| -
|
| - def testBuilderCategory(self):
|
| - # a builder in a certain category should notify status clients that
|
| - # did not list categories, or categories including this one
|
| - mailer1 = MyMailer(fromaddr="buildbot@example.com",
|
| - extraRecipients=["recip@example.com",
|
| - "recip2@example.com"],
|
| - lookup="dev.com",
|
| - sendToInterestedUsers=False)
|
| - mailer2 = MyMailer(fromaddr="buildbot@example.com",
|
| - extraRecipients=["recip@example.com",
|
| - "recip2@example.com"],
|
| - lookup="dev.com",
|
| - sendToInterestedUsers=False,
|
| - categories=["active"])
|
| - mailer3 = MyMailer(fromaddr="buildbot@example.com",
|
| - extraRecipients=["recip@example.com",
|
| - "recip2@example.com"],
|
| - lookup="dev.com",
|
| - sendToInterestedUsers=False,
|
| - categories=["active", "debug"])
|
| -
|
| - builderd = MyBuilder("builder2", "debug")
|
| -
|
| - mailer1.parent = self
|
| - mailer1.master_status = self
|
| - mailer2.parent = self
|
| - mailer2.master_status = self
|
| - mailer3.parent = self
|
| - mailer3.master_status = self
|
| - self.messages = []
|
| -
|
| - t = mailer1.builderAdded("builder2", builderd)
|
| - self.assertEqual(len(mailer1.watched), 1)
|
| - self.assertEqual(t, mailer1)
|
| - t = mailer2.builderAdded("builder2", builderd)
|
| - self.assertEqual(len(mailer2.watched), 0)
|
| - self.assertEqual(t, None)
|
| - t = mailer3.builderAdded("builder2", builderd)
|
| - self.assertEqual(len(mailer3.watched), 1)
|
| - self.assertEqual(t, mailer3)
|
| -
|
| - b2 = MyBuild(builderd, 3, builder.SUCCESS)
|
| - b2.blamelist = ["bob"]
|
| -
|
| - mailer1.buildFinished("builder2", b2, b2.results)
|
| - self.failUnlessEqual(len(self.messages), 1)
|
| - self.messages = []
|
| - mailer2.buildFinished("builder2", b2, b2.results)
|
| - self.failUnlessEqual(len(self.messages), 0)
|
| - self.messages = []
|
| - mailer3.buildFinished("builder2", b2, b2.results)
|
| - self.failUnlessEqual(len(self.messages), 1)
|
| -
|
| - def testCustomTextMessage(self):
|
| - basedir = "test_custom_text_mesg"
|
| - os.mkdir(basedir)
|
| - mailer = MyMailer(fromaddr="buildbot@example.com", mode="problem",
|
| - extraRecipients=["recip@example.com",
|
| - "recip2@example.com"],
|
| - lookup=MyLookup(),
|
| - customMesg=customTextMailMessage)
|
| - mailer.parent = self
|
| - mailer.master_status = self
|
| - self.messages = []
|
| -
|
| - b1 = self.makeBuild(4, builder.FAILURE)
|
| - b1.setProperty('buildnumber', 1, 'Build')
|
| - b1.setText(["snarkleack", "polarization", "failed"])
|
| - b1.blamelist = ["dev3", "dev3", "dev3", "dev4",
|
| - "Thomas_Walters"]
|
| - b1.source.changes = (Change(who = 'author1', files = ['file1'], comments = 'comment1', revision = 123),
|
| - Change(who = 'author2', files = ['file2'], comments = 'comment2', revision = 456))
|
| - b1.testlogs = [MyLog(basedir, 'compile', "Compile log here\n"),
|
| - MyLog(basedir, 'test', "Test log here\nTest 1 failed\nTest 2 failed\nTest 3 failed\nTest 4 failed\n")]
|
| -
|
| - mailer.buildFinished("builder1", b1, b1.results)
|
| - m,r = self.messages.pop()
|
| - t = m.as_string()
|
| - #
|
| - # Uncomment to review custom message
|
| - #
|
| - #self.fail(t)
|
| - self.failUnlessIn("comment1", t)
|
| - self.failUnlessIn("comment2", t)
|
| - self.failUnlessIn("Test 4 failed", t)
|
| - self.failUnlessIn("number was: 1", t)
|
| -
|
| -
|
| - def testCustomHTMLMessage(self):
|
| - basedir = "test_custom_HTML_mesg"
|
| - os.mkdir(basedir)
|
| - mailer = MyMailer(fromaddr="buildbot@example.com", mode="problem",
|
| - extraRecipients=["recip@example.com",
|
| - "recip2@example.com"],
|
| - lookup=MyLookup(),
|
| - customMesg=customHTMLMailMessage)
|
| - mailer.parent = self
|
| - mailer.master_status = self
|
| - self.messages = []
|
| -
|
| - b1 = self.makeBuild(4, builder.FAILURE)
|
| - b1.setProperty('buildnumber', 1, 'Build')
|
| - b1.setText(["snarkleack", "polarization", "failed"])
|
| - b1.blamelist = ["dev3", "dev3", "dev3", "dev4",
|
| - "Thomas_Walters"]
|
| - b1.source.changes = (Change(who = 'author1', files = ['file1'], comments = 'comment1', revision = 123),
|
| - Change(who = 'author2', files = ['file2'], comments = 'comment2', revision = 456))
|
| - b1.testlogs = [MyLog(basedir, 'compile', "Compile log here\n"),
|
| - MyLog(basedir, 'test', "Test log here\nTest 1 failed\nTest 2 failed\nTest 3 failed\nTest 4 failed\n")]
|
| -
|
| - mailer.buildFinished("builder1", b1, b1.results)
|
| - m,r = self.messages.pop()
|
| - t = m.as_string()
|
| - #
|
| - # Uncomment to review custom message
|
| - #
|
| - #self.fail(t)
|
| - self.failUnlessIn("<h4>Last 3 lines of 'step.test':</h4>", t)
|
| - self.failUnlessIn("<p>Changed by: <b>author2</b><br />", t)
|
| - self.failUnlessIn("Test 3 failed", t)
|
| - self.failUnlessIn("number was: 1", t)
|
| -
|
| - def testShouldAttachLog(self):
|
| - mailer = mail.MailNotifier(fromaddr="buildbot@example.com", addLogs=True)
|
| - self.assertTrue(mailer._shouldAttachLog('anything'))
|
| - mailer = mail.MailNotifier(fromaddr="buildbot@example.com", addLogs=False)
|
| - self.assertFalse(mailer._shouldAttachLog('anything'))
|
| - mailer = mail.MailNotifier(fromaddr="buildbot@example.com", addLogs=['something'])
|
| - self.assertFalse(mailer._shouldAttachLog('anything'))
|
| - self.assertTrue(mailer._shouldAttachLog('something'))
|
| -
|
| - def testShouldAttachPatches(self):
|
| - basedir = "test_should_attach_patches"
|
| - os.mkdir(basedir)
|
| - b1 = self.makeBuild(4, builder.FAILURE)
|
| - b1.setProperty('buildnumber', 1, 'Build')
|
| - b1.setText(["snarkleack", "polarization", "failed"])
|
| - b1.blamelist = ["dev3", "dev3", "dev3", "dev4",
|
| - "Thomas_Walters"]
|
| - b1.source.changes = (Change(who = 'author1', files = ['file1'], comments = 'comment1', revision = 123),
|
| - Change(who = 'author2', files = ['file2'], comments = 'comment2', revision = 456))
|
| - b1.testlogs = [MyLog(basedir, 'compile', "Compile log here\n"),
|
| - MyLog(basedir, 'test', "Test log here\nTest 1 failed\nTest 2 failed\nTest 3 failed\nTest 4 failed\n")]
|
| - b1.source.patch = (0, '--- /dev/null\n+++ a_file\n', None)
|
| -
|
| - mailer = MyMailer(fromaddr="buildbot@example.com", addPatch=True)
|
| - mailer.parent = self
|
| - mailer.master_status = self
|
| - self.messages = []
|
| - mailer.buildFinished("builder1", b1, b1.results)
|
| - m,r = self.messages.pop()
|
| - self.assertTrue(m.is_multipart())
|
| - self.assertEqual(len([True for i in m.walk()]), 3)
|
| -
|
| - mailer = MyMailer(fromaddr="buildbot@example.com", addPatch=False)
|
| - mailer.parent = self
|
| - mailer.master_status = self
|
| - self.messages = []
|
| - mailer.buildFinished("builder1", b1, b1.results)
|
| - m,r = self.messages.pop()
|
| - self.assertFalse(m.is_multipart())
|
| - self.assertEqual(len([True for i in m.walk()]), 1)
|
| -
|
| - mailer = MyMailer(fromaddr="buildbot@example.com")
|
| - mailer.parent = self
|
| - mailer.master_status = self
|
| - self.messages = []
|
| - mailer.buildFinished("builder1", b1, b1.results)
|
| - m,r = self.messages.pop()
|
| - self.assertTrue(m.is_multipart())
|
| - self.assertEqual(len([True for i in m.walk()]), 3)
|
| -
|
| -
|
| - def testFailure(self):
|
| - mailer = MyMailer(fromaddr="buildbot@example.com", mode="problem",
|
| - extraRecipients=["recip@example.com",
|
| - "recip2@example.com"],
|
| - lookup=MyLookup())
|
| - mailer.parent = self
|
| - mailer.master_status = self
|
| - self.messages = []
|
| -
|
| - b1 = self.makeBuild(3, builder.SUCCESS)
|
| - b1.blamelist = ["dev1", "dev2"]
|
| - b2 = self.makeBuild(4, builder.FAILURE)
|
| - b2.setText(["snarkleack", "polarization", "failed"])
|
| - b2.blamelist = ["dev3", "dev3", "dev3", "dev4",
|
| - "Thomas_Walters"]
|
| - mailer.buildFinished("builder1", b1, b1.results)
|
| - self.failIf(self.messages)
|
| - mailer.buildFinished("builder1", b2, b2.results)
|
| - self.failUnless(len(self.messages) == 1)
|
| - m,r = self.messages.pop()
|
| - t = m.as_string()
|
| - self.failUnlessIn("To: dev3@dev.com, dev4@dev.com\n", t)
|
| - self.failUnlessIn("CC: recip2@example.com, recip@example.com\n", t)
|
| - self.failUnlessIn("From: buildbot@example.com\n", t)
|
| - self.failUnlessIn("Subject: buildbot failure in PROJECT on builder1\n", t)
|
| - self.failUnlessIn("The Buildbot has detected a new failure", t)
|
| - self.failUnlessIn("BUILD FAILED: snarkleack polarization failed\n", t)
|
| - self.failUnlessEqual(set(r), set(["dev3@dev.com", "dev4@dev.com",
|
| - "recip2@example.com", "recip@example.com"]))
|
| -
|
| -
|
| - def testChange(self):
|
| - raise unittest.SkipTest("TODO: Fix Build/Builder mock objects to support getPrevBuild()")
|
| -
|
| - mailer = MyMailer(fromaddr="buildbot@example.com", mode="change",
|
| - extraRecipients=["bah@bah.bah"],
|
| - lookup=MyLookup())
|
| - mailer.parent = self
|
| - mailer.master_status = self
|
| - self.messages = []
|
| -
|
| - b1 = self.makeBuild(1, builder.SUCCESS)
|
| - b2 = self.makeBuild(2, builder.SUCCESS)
|
| - b3 = self.makeBuild(3, builder.FAILURE)
|
| - b4 = self.makeBuild(4, builder.FAILURE)
|
| - b5 = self.makeBuild(5, builder.SUCCESS)
|
| - b6 = self.makeBuild(6, builder.SUCCESS)
|
| -
|
| - # no message on first or repetetive success
|
| - mailer.buildFinished("builder1", b1, b1.results)
|
| - self.failIf(self.messages)
|
| - mailer.buildFinished("builder1", b2, b2.results)
|
| - self.failIf(self.messages)
|
| -
|
| - # message on first fail only
|
| - mailer.buildFinished("builder1", b3, b3.results)
|
| - self.failUnless(len(self.messages) == 1)
|
| - self.messages.pop()
|
| - mailer.buildFinished("builder1", b4, b4.results)
|
| - self.failIf(self.messages)
|
| -
|
| - # message on first following success
|
| - mailer.buildFinished("builder1", b5, b5.results)
|
| - self.failUnless(len(self.messages) == 1)
|
| - self.messages.pop()
|
| - mailer.buildFinished("builder1", b6, b6.results)
|
| - self.failIf(self.messages)
|
| -
|
| -
|
| - def testLogs(self):
|
| - basedir = "test_status_logs"
|
| - os.mkdir(basedir)
|
| - mailer = MyMailer(fromaddr="buildbot@example.com", addLogs=True,
|
| - extraRecipients=["recip@example.com",
|
| - "recip2@example.com"])
|
| - mailer.parent = self
|
| - mailer.master_status = self
|
| - self.messages = []
|
| -
|
| - b1 = self.makeBuild(3, builder.WARNINGS)
|
| - b1.testlogs = [MyLog(basedir, 'compile', "Compile log here\n"),
|
| - MyLog(basedir,
|
| - 'test', "Test log here\nTest 4 failed\n"),
|
| - ]
|
| - b1.text = ["unusual", "gnarzzler", "output"]
|
| - mailer.buildFinished("builder1", b1, b1.results)
|
| - self.failUnless(len(self.messages) == 1)
|
| - m,r = self.messages.pop()
|
| - t = m.as_string()
|
| - self.failUnlessIn("Subject: buildbot warnings in PROJECT on builder1\n", t)
|
| - m2 = email.message_from_string(t)
|
| - p = m2.get_payload()
|
| - self.failUnlessEqual(len(p), 3)
|
| -
|
| - self.failUnlessIn("Build Had Warnings: unusual gnarzzler output\n",
|
| - p[0].get_payload())
|
| -
|
| - self.failUnlessEqual(p[1].get_filename(), "step.compile")
|
| - self.failUnlessEqual(p[1].get_payload(), "Compile log here\n")
|
| -
|
| - self.failUnlessEqual(p[2].get_filename(), "step.test")
|
| - self.failUnlessIn("Test log here\n", p[2].get_payload())
|
| -
|
| - def testMail(self):
|
| - basedir = "test_status_mail"
|
| - os.mkdir(basedir)
|
| - dest = os.environ.get("BUILDBOT_TEST_MAIL")
|
| - if not dest:
|
| - raise unittest.SkipTest("define BUILDBOT_TEST_MAIL=dest to run this")
|
| - mailer = mail.MailNotifier(fromaddr="buildbot@example.com",
|
| - addLogs=True,
|
| - extraRecipients=[dest])
|
| - s = MyStatus()
|
| - s.url = "project URL"
|
| - mailer.master_status = s
|
| -
|
| - b1 = self.makeBuild(3, builder.SUCCESS)
|
| - b1.testlogs = [MyLog(basedir, 'compile', "Compile log here\n"),
|
| - MyLog(basedir,
|
| - 'test', "Test log here\nTest 4 failed\n"),
|
| - ]
|
| -
|
| - d = mailer.buildFinished("builder1", b1, b1.results)
|
| - # When this fires, the mail has been sent, but the SMTP connection is
|
| - # still up (because smtp.sendmail relies upon the server to hang up).
|
| - # Spin for a moment to avoid the "unclean reactor" warning that Trial
|
| - # gives us if we finish before the socket is disconnected. Really,
|
| - # sendmail() ought to hang up the connection once it is finished:
|
| - # otherwise a malicious SMTP server could make us consume lots of
|
| - # memory.
|
| - d.addCallback(self.stall, 0.1)
|
| - return d
|
| -
|
| -if not mail:
|
| - Mail.skip = "the Twisted Mail package is not installed"
|
| -
|
| -class Progress(unittest.TestCase):
|
| - def testWavg(self):
|
| - bp = progress.BuildProgress([])
|
| - e = progress.Expectations(bp)
|
| - # wavg(old, current)
|
| - self.failUnlessEqual(e.wavg(None, None), None)
|
| - self.failUnlessEqual(e.wavg(None, 3), 3)
|
| - self.failUnlessEqual(e.wavg(3, None), 3)
|
| - self.failUnlessEqual(e.wavg(3, 4), 3.5)
|
| - e.decay = 0.1
|
| - self.failUnlessEqual(e.wavg(3, 4), 3.1)
|
| -
|
| -
|
| -class Results(unittest.TestCase):
|
| -
|
| - def testAddResults(self):
|
| - b = builder.BuildStatus(builder.BuilderStatus("test"), 12)
|
| - testname = ("buildbot", "test", "test_status", "Results",
|
| - "testAddResults")
|
| - r1 = builder.TestResult(name=testname,
|
| - results=builder.SUCCESS,
|
| - text=["passed"],
|
| - logs={'output': ""},
|
| - )
|
| - b.addTestResult(r1)
|
| -
|
| - res = b.getTestResults()
|
| - self.failUnlessEqual(res.keys(), [testname])
|
| - t = res[testname]
|
| - self.failUnless(interfaces.ITestResult.providedBy(t))
|
| - self.failUnlessEqual(t.getName(), testname)
|
| - self.failUnlessEqual(t.getResults(), builder.SUCCESS)
|
| - self.failUnlessEqual(t.getText(), ["passed"])
|
| - self.failUnlessEqual(t.getLogs(), {'output': ""})
|
| -
|
| -class Log(unittest.TestCase):
|
| - basedir = "status_log_add"
|
| -
|
| - def setUp(self):
|
| - self.tearDown()
|
| - os.mkdir(self.basedir)
|
| -
|
| - def tearDown(self):
|
| - if os.path.exists(self.basedir):
|
| - rmtree(self.basedir)
|
| -
|
| - def testAdd(self):
|
| - l = MyLog(self.basedir, "compile", step=13)
|
| - self.failUnlessEqual(l.getName(), "compile")
|
| - self.failUnlessEqual(l.getStep(), 13)
|
| - l.addHeader("HEADER\n")
|
| - l.addStdout("Some text\n")
|
| - l.addStderr("Some error\n")
|
| - l.addStdout("Some more text\n")
|
| - self.failIf(l.isFinished())
|
| - l.finish()
|
| - self.failUnless(l.isFinished())
|
| - self.failUnlessEqual(l.getText(),
|
| - "Some text\nSome error\nSome more text\n")
|
| - self.failUnlessEqual(l.getTextWithHeaders(),
|
| - "HEADER\n" +
|
| - "Some text\nSome error\nSome more text\n")
|
| - self.failUnlessEqual(len(list(l.getChunks())), 4)
|
| -
|
| - self.failUnless(l.hasContents())
|
| - try:
|
| - os.unlink(l.getFilename())
|
| - except OSError:
|
| - os.unlink(l.getFilename() + ".bz2")
|
| - self.failIf(l.hasContents())
|
| -
|
| - def TODO_testDuplicate(self):
|
| - # create multiple logs for the same step with the same logname, make
|
| - # sure their on-disk filenames are suitably uniquified. This
|
| - # functionality actually lives in BuildStepStatus and BuildStatus, so
|
| - # this test must involve more than just the MyLog class.
|
| -
|
| - # naieve approach, doesn't work
|
| - l1 = MyLog(self.basedir, "duplicate")
|
| - l1.addStdout("Some text\n")
|
| - l1.finish()
|
| - l2 = MyLog(self.basedir, "duplicate")
|
| - l2.addStdout("Some more text\n")
|
| - l2.finish()
|
| - self.failIfEqual(l1.getFilename(), l2.getFilename())
|
| -
|
| - def testMerge1(self):
|
| - l = MyLog(self.basedir, "merge1")
|
| - l.addHeader("HEADER\n")
|
| - l.addStdout("Some text\n")
|
| - l.addStdout("Some more text\n")
|
| - l.addStdout("more\n")
|
| - l.finish()
|
| - self.failUnlessEqual(l.getText(),
|
| - "Some text\nSome more text\nmore\n")
|
| - self.failUnlessEqual(l.getTextWithHeaders(),
|
| - "HEADER\n" +
|
| - "Some text\nSome more text\nmore\n")
|
| - self.failUnlessEqual(len(list(l.getChunks())), 2)
|
| -
|
| - def testMerge2(self):
|
| - l = MyLog(self.basedir, "merge2")
|
| - l.addHeader("HEADER\n")
|
| - for i in xrange(1000):
|
| - l.addStdout("aaaa")
|
| - for i in xrange(30):
|
| - l.addStderr("bbbb")
|
| - for i in xrange(10):
|
| - l.addStdout("cc")
|
| - target = 1000*"aaaa" + 30 * "bbbb" + 10 * "cc"
|
| - self.failUnlessEqual(len(l.getText()), len(target))
|
| - self.failUnlessEqual(l.getText(), target)
|
| - l.finish()
|
| - self.failUnlessEqual(len(l.getText()), len(target))
|
| - self.failUnlessEqual(l.getText(), target)
|
| - self.failUnlessEqual(len(list(l.getChunks())), 4)
|
| -
|
| - def testMerge3(self):
|
| - l = MyLog(self.basedir, "merge3")
|
| - l.chunkSize = 100
|
| - l.addHeader("HEADER\n")
|
| - for i in xrange(8):
|
| - l.addStdout(10*"a")
|
| - for i in xrange(8):
|
| - l.addStdout(10*"a")
|
| - self.failUnlessEqual(list(l.getChunks()),
|
| - [(builder.HEADER, "HEADER\n"),
|
| - (builder.STDOUT, 100*"a"),
|
| - (builder.STDOUT, 60*"a")])
|
| - l.finish()
|
| - self.failUnlessEqual(l.getText(), 160*"a")
|
| -
|
| - def testReadlines(self):
|
| - l = MyLog(self.basedir, "chunks1")
|
| - l.addHeader("HEADER\n") # should be ignored
|
| - l.addStdout("Some text\n")
|
| - l.addStdout("Some More Text\nAnd Some More\n")
|
| - l.addStderr("Some Stderr\n")
|
| - l.addStdout("Last line\n")
|
| - l.finish()
|
| - alllines = list(l.readlines())
|
| - self.failUnlessEqual(len(alllines), 4)
|
| - self.failUnlessEqual(alllines[0], "Some text\n")
|
| - self.failUnlessEqual(alllines[2], "And Some More\n")
|
| - self.failUnlessEqual(alllines[3], "Last line\n")
|
| - stderr = list(l.readlines(interfaces.LOG_CHANNEL_STDERR))
|
| - self.failUnlessEqual(len(stderr), 1)
|
| - self.failUnlessEqual(stderr[0], "Some Stderr\n")
|
| - lines = l.readlines()
|
| - if False: # TODO: l.readlines() is not yet an iterator
|
| - # verify that it really is an iterator
|
| - line0 = lines.next()
|
| - self.failUnlessEqual(line0, "Some text\n")
|
| - line1 = lines.next()
|
| - line2 = lines.next()
|
| - self.failUnlessEqual(line2, "And Some More\n")
|
| -
|
| -
|
| - def testChunks(self):
|
| - l = MyLog(self.basedir, "chunks2")
|
| - c1 = l.getChunks()
|
| - l.addHeader("HEADER\n")
|
| - l.addStdout("Some text\n")
|
| - self.failUnlessEqual("".join(l.getChunks(onlyText=True)),
|
| - "HEADER\nSome text\n")
|
| - c2 = l.getChunks()
|
| -
|
| - l.addStdout("Some more text\n")
|
| - self.failUnlessEqual("".join(l.getChunks(onlyText=True)),
|
| - "HEADER\nSome text\nSome more text\n")
|
| - c3 = l.getChunks()
|
| -
|
| - l.addStdout("more\n")
|
| - l.finish()
|
| -
|
| - self.failUnlessEqual(list(c1), [])
|
| - self.failUnlessEqual(list(c2), [(builder.HEADER, "HEADER\n"),
|
| - (builder.STDOUT, "Some text\n")])
|
| - self.failUnlessEqual(list(c3), [(builder.HEADER, "HEADER\n"),
|
| - (builder.STDOUT,
|
| - "Some text\nSome more text\n")])
|
| -
|
| - self.failUnlessEqual(l.getText(),
|
| - "Some text\nSome more text\nmore\n")
|
| - self.failUnlessEqual(l.getTextWithHeaders(),
|
| - "HEADER\n" +
|
| - "Some text\nSome more text\nmore\n")
|
| - self.failUnlessEqual(len(list(l.getChunks())), 2)
|
| -
|
| - def testUpgrade(self):
|
| - l = MyLog(self.basedir, "upgrade")
|
| - l.addHeader("HEADER\n")
|
| - l.addStdout("Some text\n")
|
| - l.addStdout("Some more text\n")
|
| - l.addStdout("more\n")
|
| - l.finish()
|
| - self.failUnless(l.hasContents())
|
| - # now doctor it to look like a 0.6.4-era non-upgraded logfile
|
| - l.entries = list(l.getChunks())
|
| - del l.filename
|
| - try:
|
| - os.unlink(l.getFilename() + ".bz2")
|
| - except OSError:
|
| - os.unlink(l.getFilename())
|
| - # now make sure we can upgrade it
|
| - l.upgrade("upgrade")
|
| - self.failUnlessEqual(l.getText(),
|
| - "Some text\nSome more text\nmore\n")
|
| - self.failUnlessEqual(len(list(l.getChunks())), 2)
|
| - self.failIf(l.entries)
|
| -
|
| - # now, do it again, but make it look like an upgraded 0.6.4 logfile
|
| - # (i.e. l.filename is missing, but the contents are there on disk)
|
| - l.entries = list(l.getChunks())
|
| - del l.filename
|
| - l.upgrade("upgrade")
|
| - self.failUnlessEqual(l.getText(),
|
| - "Some text\nSome more text\nmore\n")
|
| - self.failUnlessEqual(len(list(l.getChunks())), 2)
|
| - self.failIf(l.entries)
|
| - self.failUnless(l.hasContents())
|
| -
|
| - def testHTMLUpgrade(self):
|
| - l = MyHTMLLog(self.basedir, "upgrade", "log contents")
|
| - l.upgrade("filename")
|
| -
|
| - def testSubscribe(self):
|
| - l1 = MyLog(self.basedir, "subscribe1")
|
| - l1.finish()
|
| - self.failUnless(l1.isFinished())
|
| -
|
| - s = MyLogSubscriber()
|
| - l1.subscribe(s, True)
|
| - l1.unsubscribe(s)
|
| - self.failIf(s.chunks)
|
| -
|
| - s = MyLogSubscriber()
|
| - l1.subscribe(s, False)
|
| - l1.unsubscribe(s)
|
| - self.failIf(s.chunks)
|
| -
|
| - finished = []
|
| - l2 = MyLog(self.basedir, "subscribe2")
|
| - l2.waitUntilFinished().addCallback(finished.append)
|
| - l2.addHeader("HEADER\n")
|
| - s1 = MyLogSubscriber()
|
| - l2.subscribe(s1, True)
|
| - s2 = MyLogSubscriber()
|
| - l2.subscribe(s2, False)
|
| - self.failUnlessEqual(s1.chunks, [(builder.HEADER, "HEADER\n")])
|
| - self.failUnlessEqual(s2.chunks, [])
|
| -
|
| - l2.addStdout("Some text\n")
|
| - self.failUnlessEqual(s1.chunks, [(builder.HEADER, "HEADER\n"),
|
| - (builder.STDOUT, "Some text\n")])
|
| - self.failUnlessEqual(s2.chunks, [(builder.STDOUT, "Some text\n")])
|
| - l2.unsubscribe(s1)
|
| -
|
| - l2.addStdout("Some more text\n")
|
| - self.failUnlessEqual(s1.chunks, [(builder.HEADER, "HEADER\n"),
|
| - (builder.STDOUT, "Some text\n")])
|
| - self.failUnlessEqual(s2.chunks, [(builder.STDOUT, "Some text\n"),
|
| - (builder.STDOUT, "Some more text\n"),
|
| - ])
|
| - self.failIf(finished)
|
| - l2.finish()
|
| - self.failUnlessEqual(finished, [l2])
|
| -
|
| - def testConsumer(self):
|
| - l1 = MyLog(self.basedir, "consumer1")
|
| - l1.finish()
|
| - self.failUnless(l1.isFinished())
|
| -
|
| - s = MyLogConsumer()
|
| - d = l1.subscribeConsumer(s)
|
| - d.addCallback(self._testConsumer_1, s)
|
| - return d
|
| - testConsumer.timeout = 5
|
| - def _testConsumer_1(self, res, s):
|
| - self.failIf(s.chunks)
|
| - self.failUnless(s.finished)
|
| - self.failIf(s.producer) # producer should be registered and removed
|
| -
|
| - l2 = MyLog(self.basedir, "consumer2")
|
| - l2.addHeader("HEADER\n")
|
| - l2.finish()
|
| - self.failUnless(l2.isFinished())
|
| -
|
| - s = MyLogConsumer()
|
| - d = l2.subscribeConsumer(s)
|
| - d.addCallback(self._testConsumer_2, s)
|
| - return d
|
| - def _testConsumer_2(self, res, s):
|
| - self.failUnlessEqual(s.chunks, [(builder.HEADER, "HEADER\n")])
|
| - self.failUnless(s.finished)
|
| - self.failIf(s.producer) # producer should be registered and removed
|
| -
|
| -
|
| - l2 = MyLog(self.basedir, "consumer3")
|
| - l2.chunkSize = 1000
|
| - l2.addHeader("HEADER\n")
|
| - l2.addStdout(800*"a")
|
| - l2.addStdout(800*"a") # should now have two chunks on disk, 1000+600
|
| - l2.addStdout(800*"b") # HEADER,1000+600*a on disk, 800*a in memory
|
| - l2.addStdout(800*"b") # HEADER,1000+600*a,1000+600*b on disk
|
| - l2.addStdout(200*"c") # HEADER,1000+600*a,1000+600*b on disk,
|
| - # 200*c in memory
|
| -
|
| - s = MyLogConsumer(limit=1)
|
| - d = l2.subscribeConsumer(s)
|
| - d.addCallback(self._testConsumer_3, l2, s)
|
| - return d
|
| - def _testConsumer_3(self, res, l2, s):
|
| - self.failUnless(s.streaming)
|
| - self.failUnlessEqual(s.chunks, [(builder.HEADER, "HEADER\n")])
|
| - s.limit = 1
|
| - d = s.producer.resumeProducing()
|
| - d.addCallback(self._testConsumer_4, l2, s)
|
| - return d
|
| - def _testConsumer_4(self, res, l2, s):
|
| - self.failUnlessEqual(s.chunks, [(builder.HEADER, "HEADER\n"),
|
| - (builder.STDOUT, 1000*"a"),
|
| - ])
|
| - s.limit = None
|
| - d = s.producer.resumeProducing()
|
| - d.addCallback(self._testConsumer_5, l2, s)
|
| - return d
|
| - def _testConsumer_5(self, res, l2, s):
|
| - self.failUnlessEqual(s.chunks, [(builder.HEADER, "HEADER\n"),
|
| - (builder.STDOUT, 1000*"a"),
|
| - (builder.STDOUT, 600*"a"),
|
| - (builder.STDOUT, 1000*"b"),
|
| - (builder.STDOUT, 600*"b"),
|
| - (builder.STDOUT, 200*"c")])
|
| - l2.addStdout(1000*"c") # HEADER,1600*a,1600*b,1200*c on disk
|
| - self.failUnlessEqual(s.chunks, [(builder.HEADER, "HEADER\n"),
|
| - (builder.STDOUT, 1000*"a"),
|
| - (builder.STDOUT, 600*"a"),
|
| - (builder.STDOUT, 1000*"b"),
|
| - (builder.STDOUT, 600*"b"),
|
| - (builder.STDOUT, 200*"c"),
|
| - (builder.STDOUT, 1000*"c")])
|
| - l2.finish()
|
| - self.failUnlessEqual(s.chunks, [(builder.HEADER, "HEADER\n"),
|
| - (builder.STDOUT, 1000*"a"),
|
| - (builder.STDOUT, 600*"a"),
|
| - (builder.STDOUT, 1000*"b"),
|
| - (builder.STDOUT, 600*"b"),
|
| - (builder.STDOUT, 200*"c"),
|
| - (builder.STDOUT, 1000*"c")])
|
| - self.failIf(s.producer)
|
| - self.failUnless(s.finished)
|
| -
|
| - def testLargeSummary(self):
|
| - bigtext = "a" * 200000 # exceed the NetstringReceiver 100KB limit
|
| - l = MyLog(self.basedir, "large", bigtext)
|
| - s = MyLogConsumer()
|
| - d = l.subscribeConsumer(s)
|
| - def _check(res):
|
| - for ctype,chunk in s.chunks:
|
| - self.failUnless(len(chunk) < 100000)
|
| - merged = "".join([c[1] for c in s.chunks])
|
| - self.failUnless(merged == bigtext)
|
| - d.addCallback(_check)
|
| - # when this fails, it fails with a timeout, and there is an exception
|
| - # sent to log.err(). This AttributeError exception is in
|
| - # NetstringReceiver.dataReceived where it does
|
| - # self.transport.loseConnection() because of the NetstringParseError,
|
| - # however self.transport is None
|
| - return d
|
| - testLargeSummary.timeout = 5
|
| -
|
| - def testLimit(self):
|
| - l = MyLog(self.basedir, "limit")
|
| - l.logMaxSize = 150
|
| - for i in range(1000):
|
| - l.addStdout("Some data")
|
| - l.finish()
|
| - t = l.getText()
|
| - # Compare against 175 since we truncate logs based on chunks, so we may
|
| - # go slightly over the limit
|
| - self.failIf(len(t) > 175, "Text too long (%i)" % len(t))
|
| - self.failUnless("truncated" in l.getTextWithHeaders(),
|
| - "No truncated message found")
|
| -
|
| -class CompressLog(unittest.TestCase):
|
| - # compression is not supported unless bz2 is installed
|
| - try:
|
| - import bz2
|
| - except:
|
| - skip = "compression not supported (no bz2 module available)"
|
| -
|
| - def testCompressLogs(self):
|
| - bss = setupBuildStepStatus("test-compress")
|
| - bss.build.builder.setLogCompressionLimit(1024)
|
| - l = bss.addLog('not-compress')
|
| - l.addStdout('a' * 512)
|
| - l.finish()
|
| - lc = bss.addLog('to-compress')
|
| - lc.addStdout('b' * 1024)
|
| - lc.finish()
|
| - d = bss.stepFinished(builder.SUCCESS)
|
| - self.failUnless(d is not None)
|
| - d.addCallback(self._verifyCompression, bss)
|
| - return d
|
| -
|
| - def _verifyCompression(self, result, bss):
|
| - self.failUnless(len(bss.getLogs()), 2)
|
| - (ncl, cl) = bss.getLogs() # not compressed, compressed log
|
| - self.failUnless(os.path.isfile(ncl.getFilename()))
|
| - self.failIf(os.path.isfile(ncl.getFilename() + ".bz2"))
|
| - self.failIf(os.path.isfile(cl.getFilename()))
|
| - self.failUnless(os.path.isfile(cl.getFilename() + ".bz2"))
|
| - content = ncl.getText()
|
| - self.failUnless(len(content), 512)
|
| - content = cl.getText()
|
| - self.failUnless(len(content), 1024)
|
| - pass
|
| -
|
| -config_base = """
|
| -from buildbot.process import factory
|
| -from buildbot.steps import dummy
|
| -from buildbot.buildslave import BuildSlave
|
| -from buildbot.config import BuilderConfig
|
| -s = factory.s
|
| -
|
| -f1 = factory.QuickBuildFactory('fakerep', 'cvsmodule', configure=None)
|
| -
|
| -f2 = factory.BuildFactory([
|
| - s(dummy.Dummy, timeout=1),
|
| - s(dummy.RemoteDummy, timeout=2),
|
| - ])
|
| -
|
| -BuildmasterConfig = c = {}
|
| -c['slaves'] = [BuildSlave('bot1', 'sekrit')]
|
| -c['schedulers'] = []
|
| -c['builders'] = [
|
| - BuilderConfig(name='quick', slavename='bot1', factory=f1),
|
| -]
|
| -c['slavePortnum'] = 0
|
| -"""
|
| -
|
| -config_2 = config_base + """
|
| -c['builders'] = [
|
| - BuilderConfig(name='dummy', slavename='bot1', factory=f2),
|
| - BuilderConfig(name='testdummy', slavename='bot1',
|
| - factory=f2, category='test'),
|
| -]
|
| -"""
|
| -
|
| -class STarget(base.StatusReceiver):
|
| - debug = False
|
| -
|
| - def __init__(self, mode):
|
| - self.mode = mode
|
| - self.events = []
|
| - def announce(self):
|
| - if self.debug:
|
| - print self.events[-1]
|
| -
|
| - def builderAdded(self, name, builder):
|
| - self.events.append(("builderAdded", name, builder))
|
| - self.announce()
|
| - if "builder" in self.mode:
|
| - return self
|
| - def builderChangedState(self, name, state):
|
| - self.events.append(("builderChangedState", name, state))
|
| - self.announce()
|
| - def buildStarted(self, name, build):
|
| - self.events.append(("buildStarted", name, build))
|
| - self.announce()
|
| - if "eta" in self.mode:
|
| - self.eta_build = build.getETA()
|
| - if "build" in self.mode:
|
| - return self
|
| - def buildETAUpdate(self, build, ETA):
|
| - self.events.append(("buildETAUpdate", build, ETA))
|
| - self.announce()
|
| - def changeAdded(self, change):
|
| - self.events.append(("changeAdded", change))
|
| - self.announce()
|
| - def stepStarted(self, build, step):
|
| - self.events.append(("stepStarted", build, step))
|
| - self.announce()
|
| - if 0 and "eta" in self.mode:
|
| - print "TIMES", step.getTimes()
|
| - print "ETA", step.getETA()
|
| - print "EXP", step.getExpectations()
|
| - if "step" in self.mode:
|
| - return self
|
| - def stepTextChanged(self, build, step, text):
|
| - self.events.append(("stepTextChanged", step, text))
|
| - def stepText2Changed(self, build, step, text2):
|
| - self.events.append(("stepText2Changed", step, text2))
|
| - def stepETAUpdate(self, build, step, ETA, expectations):
|
| - self.events.append(("stepETAUpdate", build, step, ETA, expectations))
|
| - self.announce()
|
| - def logStarted(self, build, step, log):
|
| - self.events.append(("logStarted", build, step, log))
|
| - self.announce()
|
| - def logFinished(self, build, step, log):
|
| - self.events.append(("logFinished", build, step, log))
|
| - self.announce()
|
| - def stepFinished(self, build, step, results):
|
| - self.events.append(("stepFinished", build, step, results))
|
| - if 0 and "eta" in self.mode:
|
| - print "post-EXP", step.getExpectations()
|
| - self.announce()
|
| - def buildFinished(self, name, build, results):
|
| - self.events.append(("buildFinished", name, build, results))
|
| - self.announce()
|
| - def builderRemoved(self, name):
|
| - self.events.append(("builderRemoved", name))
|
| - self.announce()
|
| - def slaveConnected(self, name):
|
| - self.events.append(("slaveConnected", name))
|
| - self.announce()
|
| - def slaveDisconnected(self, name):
|
| - self.events.append(("slaveDisconnected", name))
|
| - self.announce()
|
| -
|
| -class VerifyChangeAdded(RunMixin, unittest.TestCase):
|
| - def testChangeAdded(self):
|
| - m = self.master
|
| -
|
| - s = m.getStatus()
|
| - self.t1 = t1 = STarget(["builder"])
|
| - s.subscribe(t1)
|
| -
|
| - m.loadConfig(config_2)
|
| - m.readConfig = True
|
| - m.startService()
|
| -
|
| - cm = self.master.change_svc
|
| - c = Change("bob", ["Makefile", "foo/bar.c"], "changed stuff")
|
| - cm.addChange(c)
|
| - self.failUnlessEqual(t1.events[-1], ("changeAdded", c))
|
| -
|
| -class Subscription(RunMixin, unittest.TestCase):
|
| - # verify that StatusTargets can subscribe/unsubscribe properly
|
| -
|
| - def testSlave(self):
|
| - m = self.master
|
| - s = m.getStatus()
|
| - self.t1 = t1 = STarget(["builder"])
|
| - #t1.debug = True; print
|
| - s.subscribe(t1)
|
| - self.failUnlessEqual(len(t1.events), 0)
|
| -
|
| - self.t3 = t3 = STarget(["builder", "build", "step"])
|
| - s.subscribe(t3)
|
| -
|
| - m.loadConfig(config_2)
|
| - m.readConfig = True
|
| - m.startService()
|
| -
|
| - self.failUnlessEqual(len(t1.events), 4)
|
| - self.failUnlessEqual(t1.events[0][0:2], ("builderAdded", "dummy"))
|
| - self.failUnlessEqual(t1.events[1],
|
| - ("builderChangedState", "dummy", "offline"))
|
| - self.failUnlessEqual(t1.events[2][0:2], ("builderAdded", "testdummy"))
|
| - self.failUnlessEqual(t1.events[3],
|
| - ("builderChangedState", "testdummy", "offline"))
|
| - t1.events = []
|
| -
|
| - self.failUnlessEqual(s.getBuilderNames(), ["dummy", "testdummy"])
|
| - self.failUnlessEqual(s.getBuilderNames(categories=['test']),
|
| - ["testdummy"])
|
| - self.s1 = s1 = s.getBuilder("dummy")
|
| - self.failUnlessEqual(s1.getName(), "dummy")
|
| - self.failUnlessEqual(s1.getState(), ("offline", []))
|
| - self.failUnlessEqual(s1.getCurrentBuilds(), [])
|
| - self.failUnlessEqual(s1.getLastFinishedBuild(), None)
|
| - self.failUnlessEqual(s1.getBuild(-1), None)
|
| - #self.failUnlessEqual(s1.getEvent(-1), foo("created"))
|
| -
|
| - # status targets should, upon being subscribed, immediately get a
|
| - # list of all current builders matching their category
|
| - self.t2 = t2 = STarget([])
|
| - s.subscribe(t2)
|
| - self.failUnlessEqual(len(t2.events), 2)
|
| - self.failUnlessEqual(t2.events[0][0:2], ("builderAdded", "dummy"))
|
| - self.failUnlessEqual(t2.events[1][0:2], ("builderAdded", "testdummy"))
|
| -
|
| - d = self.connectSlave(builders=["dummy", "testdummy"])
|
| - d.addCallback(self._testSlave_1, t1)
|
| - return d
|
| -
|
| - def _testSlave_1(self, res, t1):
|
| - self.failUnlessEqual(len(t1.events), 3)
|
| - self.failUnlessEqual(t1.events[0],
|
| - ("slaveConnected", "bot1"))
|
| - self.failUnlessEqual(t1.events[1],
|
| - ("builderChangedState", "dummy", "idle"))
|
| - self.failUnlessEqual(t1.events[2],
|
| - ("builderChangedState", "testdummy", "idle"))
|
| - t1.events = []
|
| -
|
| - c = interfaces.IControl(self.master)
|
| - req = BuildRequest("forced build for testing", SourceStamp(), 'test_builder')
|
| - c.getBuilder("dummy").requestBuild(req)
|
| - d = req.waitUntilFinished()
|
| - d2 = self.master.botmaster.waitUntilBuilderIdle("dummy")
|
| - dl = defer.DeferredList([d, d2])
|
| - dl.addCallback(self._testSlave_2)
|
| - return dl
|
| -
|
| - def _testSlave_2(self, res):
|
| - # t1 subscribes to builds, but not anything lower-level
|
| - ev = self.t1.events
|
| - self.failUnlessEqual(len(ev), 4)
|
| - self.failUnlessEqual(ev[0][0:3],
|
| - ("builderChangedState", "dummy", "building"))
|
| - self.failUnlessEqual(ev[1][0], "buildStarted")
|
| - self.failUnlessEqual(ev[2][0:2]+ev[2][3:4],
|
| - ("buildFinished", "dummy", builder.SUCCESS))
|
| - self.failUnlessEqual(ev[3][0:3],
|
| - ("builderChangedState", "dummy", "idle"))
|
| -
|
| - self.failUnlessEqual([ev[0] for ev in self.t3.events],
|
| - ["builderAdded",
|
| - "builderChangedState", # offline
|
| - "builderAdded",
|
| - "builderChangedState", # idle
|
| - "slaveConnected",
|
| - "builderChangedState", # offline
|
| - "builderChangedState", # idle
|
| - "builderChangedState", # building
|
| - "buildStarted",
|
| - "stepStarted", "stepETAUpdate",
|
| - "stepTextChanged", "stepFinished",
|
| - "stepStarted", "stepETAUpdate",
|
| - "stepTextChanged", "logStarted", "logFinished",
|
| - "stepTextChanged", "stepText2Changed",
|
| - "stepFinished",
|
| - "buildFinished",
|
| - "builderChangedState", # idle
|
| - ])
|
| -
|
| - b = self.s1.getLastFinishedBuild()
|
| - self.failUnless(b)
|
| - self.failUnlessEqual(b.getBuilder().getName(), "dummy")
|
| - self.failUnlessEqual(b.getNumber(), 0)
|
| - self.failUnlessEqual(b.getSourceStamp().branch, None)
|
| - self.failUnlessEqual(b.getSourceStamp().patch, None)
|
| - self.failUnlessEqual(b.getSourceStamp().revision, None)
|
| - self.failUnlessEqual(b.getReason(), "forced build for testing")
|
| - self.failUnlessEqual(b.getChanges(), ())
|
| - self.failUnlessEqual(b.getResponsibleUsers(), [])
|
| - self.failUnless(b.isFinished())
|
| - self.failUnlessEqual(b.getText(), ['build', 'successful'])
|
| - self.failUnlessEqual(b.getResults(), builder.SUCCESS)
|
| -
|
| - steps = b.getSteps()
|
| - self.failUnlessEqual(len(steps), 2)
|
| -
|
| - eta = 0
|
| - st1 = steps[0]
|
| - self.failUnlessEqual(st1.getName(), "dummy")
|
| - self.failUnless(st1.isFinished())
|
| - self.failUnlessEqual(st1.getText(), ["delay", "1 secs"])
|
| - start,finish = st1.getTimes()
|
| - self.failUnless(0.5 < (finish-start) < 10)
|
| - self.failUnlessEqual(st1.getExpectations(), [])
|
| - self.failUnlessEqual(st1.getLogs(), [])
|
| - eta += finish-start
|
| -
|
| - st2 = steps[1]
|
| - self.failUnlessEqual(st2.getName(), "remote dummy")
|
| - self.failUnless(st2.isFinished())
|
| - self.failUnlessEqual(st2.getText(),
|
| - ["remote", "delay", "2 secs"])
|
| - start,finish = st2.getTimes()
|
| - self.failUnless(1.5 < (finish-start) < 10)
|
| - eta += finish-start
|
| - self.failUnlessEqual(st2.getExpectations(), [('output', 38, None)])
|
| - logs = st2.getLogs()
|
| - self.failUnlessEqual(len(logs), 1)
|
| - self.failUnlessEqual(logs[0].getName(), "stdio")
|
| - self.failUnlessEqual(logs[0].getText(), "data")
|
| -
|
| - self.eta = eta
|
| - # now we run it a second time, and we should have an ETA
|
| -
|
| - self.t4 = t4 = STarget(["builder", "build", "eta"])
|
| - self.master.getStatus().subscribe(t4)
|
| - c = interfaces.IControl(self.master)
|
| - req = BuildRequest("forced build for testing", SourceStamp(), 'test_builder')
|
| - c.getBuilder("dummy").requestBuild(req)
|
| - d = req.waitUntilFinished()
|
| - d2 = self.master.botmaster.waitUntilBuilderIdle("dummy")
|
| - dl = defer.DeferredList([d, d2])
|
| - dl.addCallback(lambda ign: self.shutdownAllSlaves())
|
| - dl.addCallback(self._testSlave_3)
|
| - return dl
|
| -
|
| - def _testSlave_3(self, res):
|
| - t4 = self.t4
|
| - eta = self.eta
|
| - self.failUnless(eta-1 < t4.eta_build < eta+1, # should be 3 seconds
|
| - "t4.eta_build was %g, not in (%g,%g)"
|
| - % (t4.eta_build, eta-1, eta+1))
|
| -
|
| - self.failUnlessEqual([ev[0] for ev in self.t4.events],
|
| - ["builderAdded",
|
| - "builderChangedState", # offline
|
| - "builderAdded",
|
| - "builderChangedState", # idle
|
| - "builderChangedState", # building
|
| - "buildStarted",
|
| - "stepStarted", "stepFinished",
|
| - "stepStarted", "stepFinished",
|
| - "buildFinished",
|
| - "builderChangedState",
|
| - "slaveDisconnected",
|
| - "builderChangedState",
|
| - "builderChangedState",
|
| - ])
|
| -
|
| -class Client(unittest.TestCase):
|
| - def testAdaptation(self):
|
| - b = builder.BuilderStatus("bname")
|
| - b2 = client.makeRemote(b)
|
| - self.failUnless(isinstance(b2, client.RemoteBuilder))
|
| - b3 = client.makeRemote(None)
|
| - self.failUnless(b3 is None)
|
| -
|
| -
|
| -class ContactTester(unittest.TestCase):
|
| - def test_notify_invalid_syntax(self):
|
| - irc = MyContact()
|
| - self.assertRaises(words.UsageError, lambda args, who: irc.command_NOTIFY(args, who), "", "mynick")
|
| -
|
| - def test_notify_list(self):
|
| - irc = MyContact()
|
| - irc.command_NOTIFY("list", "mynick")
|
| - self.failUnlessEqual(irc.message, "The following events are being notified: []", "empty notify list")
|
| -
|
| - irc.message = ""
|
| - irc.command_NOTIFY("on started", "mynick")
|
| - self.failUnlessEqual(irc.message, "The following events are being notified: ['started']", "on started")
|
| -
|
| - irc.message = ""
|
| - irc.command_NOTIFY("on finished", "mynick")
|
| - self.failUnlessEqual(irc.message, "The following events are being notified: ['started', 'finished']", "on finished")
|
| -
|
| - irc.message = ""
|
| - irc.command_NOTIFY("off", "mynick")
|
| - self.failUnlessEqual(irc.message, "The following events are being notified: []", "off all")
|
| -
|
| - irc.message = ""
|
| - irc.command_NOTIFY("on", "mynick")
|
| - self.failUnlessEqual(irc.message, "The following events are being notified: ['started', 'finished']", "on default set")
|
| -
|
| - irc.message = ""
|
| - irc.command_NOTIFY("off started", "mynick")
|
| - self.failUnlessEqual(irc.message, "The following events are being notified: ['finished']", "off started")
|
| -
|
| - irc.message = ""
|
| - irc.command_NOTIFY("on success failure exception", "mynick")
|
| - self.failUnlessEqual(irc.message, "The following events are being notified: ['failure', 'finished', 'exception', 'success']", "on multiple events")
|
| -
|
| - def test_notification_default(self):
|
| - irc = MyContact()
|
| -
|
| - my_builder = MyBuilder("builder78")
|
| - my_build = MyIrcBuild(my_builder, 23, builder.SUCCESS)
|
| -
|
| - irc.buildStarted(my_builder.getName(), my_build)
|
| - self.failUnlessEqual(irc.message, "", "No notification with default settings")
|
| -
|
| - irc.buildFinished(my_builder.getName(), my_build, None)
|
| - self.failUnlessEqual(irc.message, "", "No notification with default settings")
|
| -
|
| - def test_notification_started(self):
|
| - irc = MyContact()
|
| -
|
| - my_builder = MyBuilder("builder78")
|
| - my_build = MyIrcBuild(my_builder, 23, builder.SUCCESS)
|
| - my_build.changes = (
|
| - Change(who = 'author1', files = ['file1'], comments = 'comment1', revision = 123),
|
| - Change(who = 'author2', files = ['file2'], comments = 'comment2', revision = 456),
|
| - )
|
| -
|
| - irc.command_NOTIFY("on started", "mynick")
|
| -
|
| - irc.message = ""
|
| - irc.buildStarted(my_builder.getName(), my_build)
|
| - self.failUnlessEqual(irc.message, "build #23 of builder78 started including [123, 456]", "Start notification generated with notify_events=['started']")
|
| -
|
| - irc.message = ""
|
| - irc.buildFinished(my_builder.getName(), my_build, None)
|
| - self.failUnlessEqual(irc.message, "", "No finished notification with notify_events=['started']")
|
| -
|
| - def test_notification_finished(self):
|
| - irc = MyContact()
|
| -
|
| - my_builder = MyBuilder("builder834")
|
| - my_build = MyIrcBuild(my_builder, 862, builder.SUCCESS)
|
| - my_build.changes = (
|
| - Change(who = 'author1', files = ['file1'], comments = 'comment1', revision = 943),
|
| - )
|
| -
|
| - irc.command_NOTIFY("on finished", "mynick")
|
| -
|
| - irc.message = ""
|
| - irc.buildStarted(my_builder.getName(), my_build)
|
| - self.failUnlessEqual(irc.message, "", "No started notification with notify_events=['finished']")
|
| -
|
| - irc.message = ""
|
| - irc.buildFinished(my_builder.getName(), my_build, None)
|
| - self.failUnlessEqual(irc.message, "build #862 of builder834 is complete: Success [step1 step2] Build details are at http://myserver/mypath?build=765", "Finish notification generated with notify_events=['finished']")
|
| -
|
| - def test_notification_success(self):
|
| - irc = MyContact()
|
| -
|
| - my_builder = MyBuilder("builder834")
|
| - my_build = MyIrcBuild(my_builder, 862, builder.SUCCESS)
|
| - my_build.changes = (
|
| - Change(who = 'author1', files = ['file1'], comments = 'comment1', revision = 943),
|
| - )
|
| -
|
| - irc.command_NOTIFY("on success", "mynick")
|
| -
|
| - irc.message = ""
|
| - irc.buildStarted(my_builder.getName(), my_build)
|
| - self.failUnlessEqual(irc.message, "", "No started notification with notify_events=['success']")
|
| -
|
| - irc.message = ""
|
| - irc.buildFinished(my_builder.getName(), my_build, None)
|
| - self.failUnlessEqual(irc.message, "build #862 of builder834 is complete: Success [step1 step2] Build details are at http://myserver/mypath?build=765", "Finish notification generated on success with notify_events=['success']")
|
| -
|
| - irc.message = ""
|
| - my_build.results = builder.FAILURE
|
| - irc.buildFinished(my_builder.getName(), my_build, None)
|
| - self.failUnlessEqual(irc.message, "", "No finish notification generated on failure with notify_events=['success']")
|
| -
|
| - irc.message = ""
|
| - my_build.results = builder.EXCEPTION
|
| - irc.buildFinished(my_builder.getName(), my_build, None)
|
| - self.failUnlessEqual(irc.message, "", "No finish notification generated on exception with notify_events=['success']")
|
| -
|
| - def test_notification_failed(self):
|
| - irc = MyContact()
|
| -
|
| - my_builder = MyBuilder("builder834")
|
| - my_build = MyIrcBuild(my_builder, 862, builder.FAILURE)
|
| - my_build.changes = (
|
| - Change(who = 'author1', files = ['file1'], comments = 'comment1', revision = 943),
|
| - )
|
| -
|
| - irc.command_NOTIFY("on failure", "mynick")
|
| -
|
| - irc.message = ""
|
| - irc.buildStarted(my_builder.getName(), my_build)
|
| - self.failUnlessEqual(irc.message, "", "No started notification with notify_events=['failed']")
|
| -
|
| - irc.message = ""
|
| - irc.channel.showBlameList = True
|
| - irc.buildFinished(my_builder.getName(), my_build, None)
|
| - self.failUnlessEqual(irc.message, "build #862 of builder834 is complete: Failure [step1 step2] Build details are at http://myserver/mypath?build=765 blamelist: author1", "Finish notification generated on failure with notify_events=['failed']")
|
| - irc.channel.showBlameList = False
|
| -
|
| - irc.message = ""
|
| - my_build.results = builder.SUCCESS
|
| - irc.buildFinished(my_builder.getName(), my_build, None)
|
| - self.failUnlessEqual(irc.message, "", "No finish notification generated on success with notify_events=['failed']")
|
| -
|
| - irc.message = ""
|
| - my_build.results = builder.EXCEPTION
|
| - irc.buildFinished(my_builder.getName(), my_build, None)
|
| - self.failUnlessEqual(irc.message, "", "No finish notification generated on exception with notify_events=['failed']")
|
| -
|
| - def test_notification_exception(self):
|
| - irc = MyContact()
|
| -
|
| - my_builder = MyBuilder("builder834")
|
| - my_build = MyIrcBuild(my_builder, 862, builder.EXCEPTION)
|
| - my_build.changes = (
|
| - Change(who = 'author1', files = ['file1'], comments = 'comment1', revision = 943),
|
| - )
|
| -
|
| - irc.command_NOTIFY("on exception", "mynick")
|
| -
|
| - irc.message = ""
|
| - irc.buildStarted(my_builder.getName(), my_build)
|
| - self.failUnlessEqual(irc.message, "", "No started notification with notify_events=['exception']")
|
| -
|
| - irc.message = ""
|
| - irc.buildFinished(my_builder.getName(), my_build, None)
|
| - self.failUnlessEqual(irc.message, "build #862 of builder834 is complete: Exception [step1 step2] Build details are at http://myserver/mypath?build=765", "Finish notification generated on failure with notify_events=['exception']")
|
| -
|
| - irc.message = ""
|
| - irc.channel.showBlameList = True
|
| - irc.buildFinished(my_builder.getName(), my_build, None)
|
| - self.failUnlessEqual(irc.message, "build #862 of builder834 is complete: Exception [step1 step2] Build details are at http://myserver/mypath?build=765 blamelist: author1", "Finish notification generated on failure with notify_events=['exception']")
|
| - irc.channel.showBlameList = False
|
| -
|
| - irc.message = ""
|
| - my_build.results = builder.SUCCESS
|
| - irc.buildFinished(my_builder.getName(), my_build, None)
|
| - self.failUnlessEqual(irc.message, "", "No finish notification generated on success with notify_events=['exception']")
|
| -
|
| - irc.message = ""
|
| - my_build.results = builder.FAILURE
|
| - irc.buildFinished(my_builder.getName(), my_build, None)
|
| - self.failUnlessEqual(irc.message, "", "No finish notification generated on exception with notify_events=['exception']")
|
| -
|
| - def do_x_to_y_notification_test(self, notify, previous_result, new_result, expected_msg):
|
| - irc = MyContact()
|
| - irc.command_NOTIFY("on %s" % notify, "mynick")
|
| -
|
| - my_builder = MyBuilder("builder834")
|
| - my_build = MyIrcBuild(my_builder, 862, builder.FAILURE)
|
| - my_build.changes = (
|
| - Change(who = 'author1', files = ['file1'], comments = 'comment1', revision = 943),
|
| - )
|
| -
|
| - previous_build = MyIrcBuild(my_builder, 861, previous_result)
|
| - my_build.setPreviousBuild(previous_build)
|
| -
|
| - irc.message = ""
|
| - my_build.results = new_result
|
| - irc.buildFinished(my_builder.getName(), my_build, None)
|
| - self.failUnlessEqual(irc.message, expected_msg, "Finish notification generated on failure with notify_events=['successToFailure']")
|
| -
|
| - def test_notification_successToFailure(self):
|
| - self.do_x_to_y_notification_test(notify="successToFailure", previous_result=builder.SUCCESS, new_result=builder.FAILURE,
|
| - expected_msg="build #862 of builder834 is complete: Failure [step1 step2] Build details are at http://myserver/mypath?build=765" )
|
| -
|
| - self.do_x_to_y_notification_test(notify="successToFailure", previous_result=builder.SUCCESS, new_result=builder.SUCCESS,
|
| - expected_msg = "" )
|
| -
|
| - self.do_x_to_y_notification_test(notify="successToFailure", previous_result=builder.SUCCESS, new_result=builder.WARNINGS,
|
| - expected_msg = "" )
|
| -
|
| - self.do_x_to_y_notification_test(notify="successToFailure", previous_result=builder.SUCCESS, new_result=builder.EXCEPTION,
|
| - expected_msg = "" )
|
| -
|
| - def test_notification_successToWarnings(self):
|
| - self.do_x_to_y_notification_test(notify="successToWarnings", previous_result=builder.SUCCESS, new_result=builder.WARNINGS,
|
| - expected_msg="build #862 of builder834 is complete: Warnings [step1 step2] Build details are at http://myserver/mypath?build=765" )
|
| -
|
| - self.do_x_to_y_notification_test(notify="successToWarnings", previous_result=builder.SUCCESS, new_result=builder.SUCCESS,
|
| - expected_msg = "" )
|
| -
|
| - self.do_x_to_y_notification_test(notify="successToWarnings", previous_result=builder.SUCCESS, new_result=builder.FAILURE,
|
| - expected_msg = "" )
|
| -
|
| - self.do_x_to_y_notification_test(notify="successToWarnings", previous_result=builder.SUCCESS, new_result=builder.EXCEPTION,
|
| - expected_msg = "" )
|
| -
|
| - def test_notification_successToException(self):
|
| - self.do_x_to_y_notification_test(notify="successToException", previous_result=builder.SUCCESS, new_result=builder.EXCEPTION,
|
| - expected_msg="build #862 of builder834 is complete: Exception [step1 step2] Build details are at http://myserver/mypath?build=765" )
|
| -
|
| - self.do_x_to_y_notification_test(notify="successToException", previous_result=builder.SUCCESS, new_result=builder.SUCCESS,
|
| - expected_msg = "" )
|
| -
|
| - self.do_x_to_y_notification_test(notify="successToException", previous_result=builder.SUCCESS, new_result=builder.FAILURE,
|
| - expected_msg = "" )
|
| -
|
| - self.do_x_to_y_notification_test(notify="successToException", previous_result=builder.SUCCESS, new_result=builder.WARNINGS,
|
| - expected_msg = "" )
|
| -
|
| -
|
| -
|
| -
|
| -
|
| - def test_notification_failureToSuccess(self):
|
| - self.do_x_to_y_notification_test(notify="failureToSuccess", previous_result=builder.FAILURE,new_result=builder.SUCCESS,
|
| - expected_msg="build #862 of builder834 is complete: Success [step1 step2] Build details are at http://myserver/mypath?build=765" )
|
| -
|
| - self.do_x_to_y_notification_test(notify="failureToSuccess", previous_result=builder.FAILURE,new_result=builder.FAILURE,
|
| - expected_msg = "" )
|
| -
|
| - self.do_x_to_y_notification_test(notify="failureToSuccess", previous_result=builder.FAILURE,new_result=builder.WARNINGS,
|
| - expected_msg = "" )
|
| -
|
| - self.do_x_to_y_notification_test(notify="failureToSuccess", previous_result=builder.FAILURE,new_result=builder.EXCEPTION,
|
| - expected_msg = "" )
|
| -
|
| - def test_notification_failureToWarnings(self):
|
| - self.do_x_to_y_notification_test(notify="failureToWarnings", previous_result=builder.FAILURE, new_result=builder.WARNINGS,
|
| - expected_msg="build #862 of builder834 is complete: Warnings [step1 step2] Build details are at http://myserver/mypath?build=765" )
|
| -
|
| - self.do_x_to_y_notification_test(notify="failureToWarnings", previous_result=builder.FAILURE, new_result=builder.SUCCESS,
|
| - expected_msg = "" )
|
| -
|
| - self.do_x_to_y_notification_test(notify="failureToWarnings", previous_result=builder.FAILURE, new_result=builder.FAILURE,
|
| - expected_msg = "" )
|
| -
|
| - self.do_x_to_y_notification_test(notify="failureToWarnings", previous_result=builder.FAILURE, new_result=builder.EXCEPTION,
|
| - expected_msg = "" )
|
| -
|
| - def test_notification_failureToException(self):
|
| - self.do_x_to_y_notification_test(notify="failureToException", previous_result=builder.FAILURE, new_result=builder.EXCEPTION,
|
| - expected_msg="build #862 of builder834 is complete: Exception [step1 step2] Build details are at http://myserver/mypath?build=765" )
|
| -
|
| - self.do_x_to_y_notification_test(notify="failureToException", previous_result=builder.FAILURE, new_result=builder.SUCCESS,
|
| - expected_msg = "" )
|
| -
|
| - self.do_x_to_y_notification_test(notify="failureToException", previous_result=builder.FAILURE, new_result=builder.FAILURE,
|
| - expected_msg = "" )
|
| -
|
| - self.do_x_to_y_notification_test(notify="failureToException", previous_result=builder.FAILURE, new_result=builder.WARNINGS,
|
| - expected_msg = "" )
|
| -
|
| -
|
| -
|
| -
|
| -
|
| - def test_notification_warningsToFailure(self):
|
| - self.do_x_to_y_notification_test(notify="warningsToFailure", previous_result=builder.WARNINGS, new_result=builder.FAILURE,
|
| - expected_msg="build #862 of builder834 is complete: Failure [step1 step2] Build details are at http://myserver/mypath?build=765" )
|
| -
|
| - self.do_x_to_y_notification_test(notify="warningsToFailure", previous_result=builder.WARNINGS, new_result=builder.SUCCESS,
|
| - expected_msg = "" )
|
| -
|
| - self.do_x_to_y_notification_test(notify="warningsToFailure", previous_result=builder.WARNINGS, new_result=builder.WARNINGS,
|
| - expected_msg = "" )
|
| -
|
| - self.do_x_to_y_notification_test(notify="warningsToFailure", previous_result=builder.WARNINGS, new_result=builder.EXCEPTION,
|
| - expected_msg = "" )
|
| -
|
| - def test_notification_warningsToSuccess(self):
|
| - self.do_x_to_y_notification_test(notify="warningsToSuccess", previous_result=builder.WARNINGS, new_result=builder.SUCCESS,
|
| - expected_msg="build #862 of builder834 is complete: Success [step1 step2] Build details are at http://myserver/mypath?build=765" )
|
| -
|
| - self.do_x_to_y_notification_test(notify="warningsToSuccess", previous_result=builder.WARNINGS, new_result=builder.WARNINGS,
|
| - expected_msg = "" )
|
| -
|
| - self.do_x_to_y_notification_test(notify="warningsToSuccess", previous_result=builder.WARNINGS, new_result=builder.FAILURE,
|
| - expected_msg = "" )
|
| -
|
| - self.do_x_to_y_notification_test(notify="warningsToSuccess", previous_result=builder.WARNINGS, new_result=builder.EXCEPTION,
|
| - expected_msg = "" )
|
| -
|
| - def test_notification_warningsToException(self):
|
| - self.do_x_to_y_notification_test(notify="warningsToException", previous_result=builder.WARNINGS, new_result=builder.EXCEPTION,
|
| - expected_msg="build #862 of builder834 is complete: Exception [step1 step2] Build details are at http://myserver/mypath?build=765" )
|
| -
|
| - self.do_x_to_y_notification_test(notify="warningsToException", previous_result=builder.WARNINGS, new_result=builder.SUCCESS,
|
| - expected_msg = "" )
|
| -
|
| - self.do_x_to_y_notification_test(notify="warningsToException", previous_result=builder.WARNINGS, new_result=builder.FAILURE,
|
| - expected_msg = "" )
|
| -
|
| - self.do_x_to_y_notification_test(notify="warningsToException", previous_result=builder.WARNINGS, new_result=builder.WARNINGS,
|
| - expected_msg = "" )
|
| -
|
| -
|
| -
|
| -
|
| - def test_notification_exceptionToFailure(self):
|
| - self.do_x_to_y_notification_test(notify="exceptionToFailure", previous_result=builder.EXCEPTION, new_result=builder.FAILURE,
|
| - expected_msg="build #862 of builder834 is complete: Failure [step1 step2] Build details are at http://myserver/mypath?build=765" )
|
| -
|
| - self.do_x_to_y_notification_test(notify="exceptionToFailure", previous_result=builder.EXCEPTION, new_result=builder.SUCCESS,
|
| - expected_msg = "" )
|
| -
|
| - self.do_x_to_y_notification_test(notify="exceptionToFailure", previous_result=builder.EXCEPTION, new_result=builder.WARNINGS,
|
| - expected_msg = "" )
|
| -
|
| - self.do_x_to_y_notification_test(notify="exceptionToFailure", previous_result=builder.EXCEPTION, new_result=builder.EXCEPTION,
|
| - expected_msg = "" )
|
| -
|
| - def test_notification_exceptionToWarnings(self):
|
| - self.do_x_to_y_notification_test(notify="exceptionToWarnings", previous_result=builder.EXCEPTION, new_result=builder.WARNINGS,
|
| - expected_msg="build #862 of builder834 is complete: Warnings [step1 step2] Build details are at http://myserver/mypath?build=765" )
|
| -
|
| - self.do_x_to_y_notification_test(notify="exceptionToWarnings", previous_result=builder.EXCEPTION, new_result=builder.SUCCESS,
|
| - expected_msg = "" )
|
| -
|
| - self.do_x_to_y_notification_test(notify="exceptionToWarnings", previous_result=builder.EXCEPTION, new_result=builder.FAILURE,
|
| - expected_msg = "" )
|
| -
|
| - self.do_x_to_y_notification_test(notify="exceptionToWarnings", previous_result=builder.EXCEPTION, new_result=builder.EXCEPTION,
|
| - expected_msg = "" )
|
| -
|
| - def test_notification_exceptionToSuccess(self):
|
| - self.do_x_to_y_notification_test(notify="exceptionToSuccess", previous_result=builder.EXCEPTION, new_result=builder.SUCCESS,
|
| - expected_msg="build #862 of builder834 is complete: Success [step1 step2] Build details are at http://myserver/mypath?build=765" )
|
| -
|
| - self.do_x_to_y_notification_test(notify="exceptionToSuccess", previous_result=builder.EXCEPTION, new_result=builder.EXCEPTION,
|
| - expected_msg = "" )
|
| -
|
| - self.do_x_to_y_notification_test(notify="exceptionToSuccess", previous_result=builder.EXCEPTION, new_result=builder.FAILURE,
|
| - expected_msg = "" )
|
| -
|
| - self.do_x_to_y_notification_test(notify="exceptionToSuccess", previous_result=builder.EXCEPTION, new_result=builder.WARNINGS,
|
| - expected_msg = "" )
|
| -
|
| - def test_notification_set_in_config(self):
|
| - irc = MyContact(channel = MyChannel(notify_events = {'success': 1}))
|
| -
|
| - my_builder = MyBuilder("builder834")
|
| - my_build = MyIrcBuild(my_builder, 862, builder.SUCCESS)
|
| - my_build.changes = (
|
| - Change(who = 'author1', files = ['file1'], comments = 'comment1', revision = 943),
|
| - )
|
| -
|
| - irc.message = ""
|
| - irc.buildFinished(my_builder.getName(), my_build, None)
|
| - self.failUnlessEqual(irc.message, "build #862 of builder834 is complete: Success [step1 step2] Build details are at http://myserver/mypath?build=765", "Finish notification generated on success with notify_events=['success']")
|
| -
|
| -class MyIrcBuild(builder.BuildStatus):
|
| - results = None
|
| -
|
| - def __init__(self, parent, number, results):
|
| - builder.BuildStatus.__init__(self, parent, number)
|
| - self.results = results
|
| - self.previousBuild = None
|
| -
|
| - def getResults(self):
|
| - return self.results
|
| -
|
| - def getText(self):
|
| - return ('step1', 'step2')
|
| -
|
| - def setPreviousBuild(self, pb):
|
| - self.previousBuild = pb
|
| -
|
| - def getPreviousBuild(self):
|
| - return self.previousBuild
|
| -
|
| -class URLProducer:
|
| - def getURLForThing(self, build):
|
| - return 'http://myserver/mypath?build=765'
|
| -
|
| -class MyChannel:
|
| - categories = None
|
| - status = URLProducer()
|
| - notify_events = {}
|
| -
|
| - def __init__(self, notify_events = {}):
|
| - self.notify_events = notify_events
|
| - self.showBlameList = False
|
| -
|
| -class MyContact(words.Contact):
|
| - message = ""
|
| -
|
| - def __init__(self, channel = MyChannel()):
|
| - words.Contact.__init__(self, channel)
|
| - self.message = ""
|
| -
|
| - def subscribe_to_build_events(self):
|
| - pass
|
| -
|
| - def unsubscribe_from_build_events(self):
|
| - pass
|
| -
|
| - def send(self, msg):
|
| - self.message += msg
|
| -
|
| -class MyIrcStatusBot(words.IrcStatusBot):
|
| - def msg(self, dest, message):
|
| - self.message = ['msg', dest, message]
|
| -
|
| - def notice(self, dest, message):
|
| - self.message = ['notice', dest, message]
|
| -
|
| -class IrcStatusBotTester(unittest.TestCase):
|
| - def testMsgOrNotice(self):
|
| - channel = MyIrcStatusBot('alice', 'pa55w0od', ['#here'],
|
| - builder.SUCCESS, None, {})
|
| - channel.msgOrNotice('bob', 'hello')
|
| - self.failUnlessEqual(channel.message, ['msg', 'bob', 'hello'])
|
| -
|
| - channel.msgOrNotice('#here', 'hello')
|
| - self.failUnlessEqual(channel.message, ['msg', '#here', 'hello'])
|
| -
|
| - channel.noticeOnChannel = True
|
| -
|
| - channel.msgOrNotice('bob', 'hello')
|
| - self.failUnlessEqual(channel.message, ['msg', 'bob', 'hello'])
|
| -
|
| - channel.msgOrNotice('#here', 'hello')
|
| - self.failUnlessEqual(channel.message, ['notice', '#here', 'hello'])
|
| -
|
| -class StepStatistics(unittest.TestCase):
|
| - def testStepStatistics(self):
|
| - status = builder.BuildStatus(builder.BuilderStatus("test"), 123)
|
| - status.addStepWithName('step1')
|
| - status.addStepWithName('step2')
|
| - status.addStepWithName('step3')
|
| - status.addStepWithName('step4')
|
| -
|
| - steps = status.getSteps()
|
| - (step1, step2, step3, step4) = steps
|
| -
|
| - step1.setStatistic('test-prop', 1)
|
| - step3.setStatistic('test-prop', 2)
|
| - step4.setStatistic('test-prop', 4)
|
| -
|
| - step1.setStatistic('other-prop', 27)
|
| - # Just to have some other properties around
|
| -
|
| - self.failUnlessEqual(step1.getStatistic('test-prop'), 1,
|
| - 'Retrieve an existing property')
|
| - self.failUnlessEqual(step1.getStatistic('test-prop', 99), 1,
|
| - "Don't default an existing property")
|
| - self.failUnlessEqual(step2.getStatistic('test-prop', 99), 99,
|
| - 'Default a non-existant property')
|
| -
|
| - self.failUnlessEqual(
|
| - status.getSummaryStatistic('test-prop', operator.add), 7,
|
| - 'Sum property across the build')
|
| -
|
| - self.failUnlessEqual(
|
| - status.getSummaryStatistic('test-prop', operator.add, 13), 20,
|
| - 'Sum property across the build with initial value')
|
| -
|
| -class BuildExpectation(unittest.TestCase):
|
| - class MyBuilderStatus:
|
| - implements(interfaces.IBuilderStatus)
|
| -
|
| - def setSlavenames(self, slaveName):
|
| - pass
|
| -
|
| - class MyBuilder(Builder):
|
| - def __init__(self, name):
|
| - Builder.__init__(self, {
|
| - 'name': name,
|
| - 'builddir': '/tmp/somewhere',
|
| - 'slavebuilddir': '/tmp/somewhere_else',
|
| - 'factory': 'aFactory'
|
| - }, BuildExpectation.MyBuilderStatus())
|
| -
|
| - class MyBuild(Build):
|
| - def __init__(self, b):
|
| - self.builder = b
|
| - self.remote = None
|
| -
|
| - step1_progress = progress.StepProgress('step1', ['elapsed'])
|
| - self.progress = progress.BuildProgress([step1_progress])
|
| - step1_progress.setBuildProgress(self.progress)
|
| -
|
| - step1_progress.start()
|
| - sleep(1);
|
| - step1_progress.finish()
|
| -
|
| - self.deferred = defer.Deferred()
|
| - self.locks = []
|
| - self.build_status = builder.BuildStatus(b.builder_status, 1)
|
| -
|
| -
|
| - def testBuildExpectation_BuildSuccess(self):
|
| - b = BuildExpectation.MyBuilder("builder1")
|
| - build = BuildExpectation.MyBuild(b)
|
| -
|
| - build.buildFinished(['sometext'], builder.SUCCESS)
|
| - self.failIfEqual(b.expectations.expectedBuildTime(), 0, 'Non-Zero expectation for a failed build')
|
| -
|
| - def testBuildExpectation_BuildFailure(self):
|
| - b = BuildExpectation.MyBuilder("builder1")
|
| - build = BuildExpectation.MyBuild(b)
|
| -
|
| - build.buildFinished(['sometext'], builder.FAILURE)
|
| - self.failUnlessEqual(b.expectations, None, 'Zero expectation for a failed build')
|
| -
|
| -class Pruning(unittest.TestCase):
|
| - def runTest(self, files, buildHorizon, logHorizon):
|
| - bstat = builder.BuilderStatus("foo")
|
| - bstat.buildHorizon = buildHorizon
|
| - bstat.logHorizon = logHorizon
|
| - bstat.basedir = "prune-test"
|
| -
|
| - rmtree(bstat.basedir)
|
| - os.mkdir(bstat.basedir)
|
| - for filename in files:
|
| - open(os.path.join(bstat.basedir, filename), "w").write("TEST")
|
| - bstat.determineNextBuildNumber()
|
| -
|
| - bstat.prune()
|
| -
|
| - remaining = os.listdir(bstat.basedir)
|
| - remaining.sort()
|
| - return remaining
|
| -
|
| - files_base = [
|
| - '10',
|
| - '11',
|
| - '12', '12-log-bar', '12-log-foo',
|
| - '13', '13-log-foo',
|
| - '14', '14-log-bar', '14-log-foo',
|
| - ]
|
| -
|
| - def test_rmlogs(self):
|
| - remaining = self.runTest(self.files_base, 5, 2)
|
| - self.failUnlessEqual(remaining, [
|
| - '10',
|
| - '11',
|
| - '12',
|
| - '13', '13-log-foo',
|
| - '14', '14-log-bar', '14-log-foo',
|
| - ])
|
| -
|
| - def test_rmbuilds(self):
|
| - remaining = self.runTest(self.files_base, 2, 0)
|
| - self.failUnlessEqual(remaining, [
|
| - '13', '13-log-foo',
|
| - '14', '14-log-bar', '14-log-foo',
|
| - ])
|
| -
|
| -class EventGenerator(unittest.TestCase):
|
| - def makeGenerator(self, reasons=[], minTime=0):
|
| - b = MyBuilder("bname")
|
| - b1 = b.newBuild()
|
| - b1.setSourceStamp(SourceStamp(changes=[Change("foo", [], "")]))
|
| - b1.buildStarted(b1, 1)
|
| - b2 = b.newBuild()
|
| - b2.setSourceStamp(SourceStamp(changes=[Change("bar", [], "")]))
|
| - b2.buildStarted(b2, 2)
|
| - return b.eventGenerator([], [], reasons, minTime)
|
| -
|
| - def testEventGenerator_Unfiltered(self):
|
| - gen = self.makeGenerator()
|
| - self.failUnlessEqual(len([e for e in gen]), 2)
|
| -
|
| - def testEventGenerator_Filtered(self):
|
| - gen = self.makeGenerator(["foo"])
|
| - self.failUnlessEqual(len([e for e in gen]), 1)
|
| -
|
| - def testEventGenerator_MinTime(self):
|
| - gen = self.makeGenerator([], 2)
|
| - self.failUnlessEqual(len([e for e in gen]), 1)
|
|
|