From b569597f93af7dfb3e10a954ba2f0cb672a12209 Mon Sep 17 00:00:00 2001 From: Marcus Lindblom Date: Sat, 23 Jan 2010 11:53:22 +0100 Subject: [PATCH] WebPartsRecursive test: add more builders/builds/logs, test # of pages/links and fix issues --- buildbot/status/web/build.py | 2 +- buildbot/status/web/templates/build.html | 2 + buildbot/status/web/templates/buildstep.html | 2 + buildbot/test/test_webparts.py | 108 +++++++++++++++---- 4 files changed, 91 insertions(+), 23 deletions(-) diff --git a/buildbot/status/web/build.py b/buildbot/status/web/build.py index ccd0802dcd4..6b3e4d5730f 100644 --- a/buildbot/status/web/build.py +++ b/buildbot/status/web/build.py @@ -98,7 +98,7 @@ def content(self, req, cxt): step['link'] = req.childLink("steps/%s" % urllib.quote(s.getName())) step['text'] = " ".join(s.getText()) - step['urls'] = map(lambda x:dict(url=x[0],logname=x[1]), s.getURLs().items()) + step['urls'] = map(lambda x:dict(url=x[1],logname=x[0]), s.getURLs().items()) step['logs']= [] for l in s.getLogs(): diff --git a/buildbot/status/web/templates/build.html b/buildbot/status/web/templates/build.html index c5182b624f1..4d27b38a945 100644 --- a/buildbot/status/web/templates/build.html +++ b/buildbot/status/web/templates/build.html @@ -104,6 +104,8 @@

Steps and Logfiles:

{% set item_class = cycler('alt', '') %} {% for l in s.logs %}
  • {{ l.name }}
  • + {% else %} +
  • - no logs -
  • {% endfor %} {% for u in s.urls %} diff --git a/buildbot/status/web/templates/buildstep.html b/buildbot/status/web/templates/buildstep.html index 42f3e87f7ca..80122396b8a 100644 --- a/buildbot/status/web/templates/buildstep.html +++ b/buildbot/status/web/templates/buildstep.html @@ -53,6 +53,8 @@

    Logs

    {{ l.name|e }} {% endif %} +{% else %} +
  • - No logs -
  • {% endfor %} diff --git a/buildbot/test/test_webparts.py b/buildbot/test/test_webparts.py index acc739b615c..be8e0dfe829 100644 --- a/buildbot/test/test_webparts.py +++ b/buildbot/test/test_webparts.py @@ -168,9 +168,9 @@ class WebpartsRecursive(_WebpartsTest): and validate all, so this test is skipped if lxml is not installed. ''' - + log = False # Set to True to list pages being checked - + def setUp(self): try: from lxml import etree @@ -237,22 +237,31 @@ def describe(self): c['slaves'] = [BuildSlave('bot1', 'sekrit'), BuildSlave('bot2', 'sekrit')] c['change_source'] = DummyChangeSource() -c['schedulers'] = [DiscardScheduler('discard', None, 60, ['builder1'])] +c['schedulers'] = [DiscardScheduler('discard1', None, 60, ['builder1']), + DiscardScheduler('discard2', 'release', 30, ['builder1'])] c['slavePortnum'] = 0 f = factory.BuildFactory([s(dummy.RemoteDummy, timeout=1)]) c['builders'] = [ BuilderConfig(name='builder1', slavenames=['bot1', 'bot2'], factory=f), + BuilderConfig(name='builder2', slavenames=['bot1'], factory=f), + BuilderConfig(name='builder3', slavenames=['bot2'], factory=f), ] c['buildbotURL'] = 'http://dummy.example.org:8010/' +c['projectName'] = 'BuildBot Trial Test' +c['projectURL'] = 'http://server.net/home' """ self.startMaster(extraconfig) for i in range(5): + if i % 2 == 0: + branch = "release" + else: + branch = None c = Change("user", ["foo.c"] * i, "see ticket #%i" % i, - revision=str(42+i), when=0.1*i) + revision=str(42+i), when=0.1*i, branch=branch) self.master.change_svc.addChange(c) ss = sourcestamp.SourceStamp(revision=42) @@ -266,12 +275,23 @@ def describe(self): bs.setProperty("revision", "42", "testcase") bs.setProperty("got_revision", "47", "testcase") + bs.setProperty("branch", "release", "testcase") step1 = BuildStep(name="setup") step1.setBuild(build1) bss = bs.addStepWithName("setup") step1.setStepStatus(bss) bss.stepStarted() + + step2 = BuildStep(name="build") + step2.setBuild(build1) + bss = bs.addStepWithName("build") + step2.setStepStatus(bss) + bss.stepStarted() + + step1.addURL("url1", "http://logurl.net/1") + step1.addURL("url2", "http://logurl.net/2") + step1.addURL("url3", "http://logurl.net/3") log1 = step1.addLog("output") log1.addStdout(u"some stdout\n") # FIXME: Unicode here fails validation @@ -299,9 +319,30 @@ def describe(self): log5.addStderr("errors go here") log5.addEntry(5, "non-standard content on channel 5") log5.addStderr(" and some trailing stderr") - - d = defer.maybeDeferred(step1.step_status.stepFinished, - builder.SUCCESS) + + + d = defer.succeed(None) + + for i in range(1,3): + ss = sourcestamp.SourceStamp(revision=42+i, branch='release') + req = base.BuildRequest("reason", ss, 'test_builder') + build = base.Build([req] * i) + bs = self.master.status.getBuilder("builder%i" % i).newBuild() + bs.setReason("reason") + bs.buildStarted(build) + bs.setSourceStamp(ss) + + s = BuildStep(name="setup") + s.setBuild(build1) + bss = bs.addStepWithName("setup") + s.setStepStatus(bss) + bss.stepStarted() + log = s.addLog("stdio") + log.finish() + + + d.chainDeferred(defer.maybeDeferred(step1.step_status.stepFinished, + builder.SUCCESS)) bs.buildFinished() return d @@ -314,53 +355,74 @@ def testAllPagesValidate(self): self.parser.resolvers.add(self.CustomResolver()) self.errors = [] self.error_count = 0 + self.link_count = 0 self.visited_urls = [self.baseurl] self.skipped_urls = [] + self.log = True # uncomment to see logs d = defer.succeed(None) - d.addCallback(self._check_pages, [self.baseurl]) + d.addCallback(self._check_pages, [self.baseurl], "") d.addCallback(self._reporterrors) return d def _reporterrors(self, _): - if self.errors: + url_count = len(self.visited_urls) + skip_count = len(self.skipped_urls) + + if self.errors or self.error_count: fail_summary = u"%i/%i urls contains errors:\n %s" % \ - (self.error_count, len(self.visited_urls), - u"\n ".join(self.errors)) + (self.error_count, url_count, u"\n ".join(self.errors)) self.fail(fail_summary) elif self.log: - print "%i urls ok" % len(self.visited_urls) - + print "%i urls ok, %i urls skipped in %i links" % \ + (url_count, skip_count, self.link_count) + + # these numbers need adjustment when web layout changes + # but should catch empty pages + self.failIf(url_count < 55, + "Only %i urls visited, expected at least 55" % url_count) + self.failIf(skip_count < 15, + "Only %i urls skipped, expected at least 15" % skip_count) + self.failIf(self.link_count < 770, + "Only %i links encountered, expected at least 770" % self.link_count) def _getpage(self, _, url): return client.getPage(url) - def _show_weberror(self, why, url): + def _show_weberror(self, why, url, source): self.error_count += 1 why.trap(WebError) + url = url.replace(self.baseurl, '') + source = source.replace(self.baseurl, '') self.errors.append("*** %s: %s" % (url, why.getErrorMessage())) + self.errors.append(" * from: %s" % source) - def _check_links(self, res, urls): + def _check_links(self, res, urls, source): d = defer.succeed(None) for url in urls: d.addCallback(self._getpage, url) - d.addErrback(self._show_weberror, url) + d.addErrback(self._show_weberror, url, source) return d - def _check_pages(self, _, urls): + def _check_pages(self, _, urls, source): d = defer.succeed(None) for url in urls: d.addCallback(self._getpage, url) - d.addErrback(self._show_weberror, url) + d.addErrback(self._show_weberror, url, source) d.addCallback(self._validate_and_recurse, url) - + from twisted.python import log + d.addErrback(log.err) + return d def _validate_and_recurse(self, page, url): if not page: + # this happens mostly on errors, which are reported elsewhere + if self.log: + print "Empty: %s" % url return from lxml import etree, html @@ -400,6 +462,8 @@ def _validate_and_recurse(self, page, url): pages = [] links = [] for element, attr, link, pos in xhtml.iterlinks(): + self.link_count += 1 + if link.endswith('/None'): continue @@ -418,7 +482,7 @@ def _validate_and_recurse(self, page, url): tag = element.tag.split('}')[1] # FIXME: rebuild redirects to a bad place in this test - untestable = ['/rebuild'] + untestable = ['/rebuild', '/stop'] if any (map(lambda e: link.endswith(e), untestable)): continue @@ -440,8 +504,8 @@ def _validate_and_recurse(self, page, url): if pages or links: d = defer.succeed(None) if pages: - d.addCallback(self._check_pages, pages) + d.addCallback(self._check_pages, pages, url) if links: - d.addCallback(self._check_links, links) + d.addCallback(self._check_links, links, url) return d