[Checkins] SVN: Sandbox/adamg/zope.wineggbuilder/trunk/ started adding tests

Adam Groszer agroszer at gmail.com
Fri Jun 25 05:21:54 EDT 2010


Log message for revision 113820:
  started adding tests

Changed:
  U   Sandbox/adamg/zope.wineggbuilder/trunk/master.cfg
  U   Sandbox/adamg/zope.wineggbuilder/trunk/server-setup.txt

-=-
Modified: Sandbox/adamg/zope.wineggbuilder/trunk/master.cfg
===================================================================
--- Sandbox/adamg/zope.wineggbuilder/trunk/master.cfg	2010-06-25 07:35:22 UTC (rev 113819)
+++ Sandbox/adamg/zope.wineggbuilder/trunk/master.cfg	2010-06-25 09:21:53 UTC (rev 113820)
@@ -1,17 +1,20 @@
 # -*- python -*-
 # ex: set syntax=python:
 
+import re
+import time
 import sys
 import os.path
 import subprocess
 from twisted.python import log
+from twisted.internet import reactor
 
 from buildbot import locks
 
 from buildbot.changes.svnpoller import SVNPoller, split_file_branches
-from buildbot.steps.source import SVN
-from buildbot.steps.shell import Compile
-from buildbot.process.factory import BuildFactory
+from buildbot.steps import source
+from buildbot.steps import shell
+from buildbot.process import factory
 
 from buildbot.process.base import Build
 from buildbot.status import html
@@ -50,26 +53,180 @@
 
 
 ######################################
+# Custom helper classes
+
+class SVN(source.SVN):
+
+    show_revno = False # the LastChange step does it better
+
+    def createSummary(self, log):
+        log_text = log.getText()
+        if self.show_revno:
+            revno = self.extractRevno(log_text)
+            if revno:
+                self.descriptionDone = self.descriptionDone + ['r%s' % revno]
+
+    def extractRevno(self, log_text):
+        try:
+            start_idx = log_text.rindex('At revision')
+            end_idx = log_text.find('\n', start_idx)
+        except ValueError:
+            return None
+        line = log_text[start_idx:end_idx]
+        try:
+            return re.findall('([0-9]+)', line)[0]
+        except IndexError:
+            return None
+
+
+class LastChange(shell.ShellCommand):
+
+    command = ['svn', 'log', '--limit', '1']
+    name = 'svn-last-change'
+    description = ['svn log --limit 1']
+    descriptionDone = ['last change']
+
+    # xxx hardcoded
+    url_template = 'http://zope3.pov.lt/trac/log/zope.release?rev=%s'
+
+    def createSummary(self, log):
+        log_text = log.getText()
+        revno = self.extractRevno(log_text)
+        if revno:
+            text = self.formatRevno(revno)
+            self.descriptionDone = self.descriptionDone + [text]
+
+    def formatRevno(self, revno):
+        text = 'r%s' % revno
+        if self.url_template:
+            url = self.url_template % revno
+            text = '<a class="revlink" href="%s">%s</a>' % (url, text)
+        return text
+
+    def extractRevno(self, log_text):
+        for line in log_text.splitlines():
+            if line.startswith('r'):
+                return line.split()[0][1:]
+        return None
+
+class Test(shell.Test):
+
+    started = None
+    stopped = None
+
+    tick_every = 10 # seconds
+
+    def __init__(self, *args, **kw):
+        shell.Test.__init__(self, *args, **kw)
+        if 'name' in args:
+            self.name = args['name']
+
+    def start(self):
+        shell.Test.start(self)
+        self.started = time.time()
+        reactor.callLater(self.tick_every, self.tick)
+
+    def finished(self, results):
+        if not self.stopped:
+            self.stopped = time.time()
+        shell.Test.finished(self, results)
+
+    def tick(self):
+        if not self.stopped:
+            self.step_status.setText(self.describe(False))
+            reactor.callLater(self.tick_every, self.tick)
+
+    def describe(self, done=False):
+        description = [self.name]
+        if not done and self.started:
+            running = time.time() - self.started
+            description = [self.name, self.formatTime(running)]
+        return description
+
+    def createSummary(self, log):
+        if not self.started:
+            # just in case something async happens
+            self.started = time.time()
+        self.stopped = time.time()
+        log_text = log.getText()
+        totals = self.extractTotals(log_text)
+        if totals:
+            self.descriptionDone = self.descriptionDone + [totals]
+        # the test runner lies about the time
+        ## time_info = self.extractTime(log_text)
+        time_info = self.formatTime(self.stopped - self.started)
+        if time_info:
+            self.descriptionDone = self.descriptionDone + [time_info]
+        summary = self.extractSummary(log_text)
+        if summary:
+            self.addCompleteLog('summary', summary)
+
+    def formatTime(self, seconds):
+        return '%dm%02ds' % divmod(seconds, 60)
+
+    def extractTotalsLine(self, log_text):
+        try:
+            start_idx = log_text.rindex('Total:')
+            end_idx = log_text.find('\n', start_idx)
+        except ValueError:
+            return None
+        return log_text[start_idx:end_idx]
+
+    def extractTotals(self, log_text):
+        totals_line = self.extractTotalsLine(log_text)
+        if not totals_line:
+            return None
+        # Total: X tests, X failures, X errors in X minutes X.Y seconds.
+        ntests, nfail, nerr = re.findall('([0-9.]+)', totals_line)[:3]
+        return '%s/%s/%s' % (ntests, nfail, nerr)
+
+    def extractTime(self, log_text):
+        totals_line = self.extractTotalsLine(log_text)
+        if not totals_line:
+            return None
+        # Total: X tests, X failures, X errors in [X minutes] X.Y seconds.
+        time = totals_line.split(' in ')[-1]
+        time = time.replace(' minutes ', 'm')
+        time = time.replace(' seconds.', 's')
+        time = re.sub('[.][0-9]+s', 's', time)
+        return time
+
+    def extractSummary(self, log_text):
+        summary_idx = len(log_text)
+        for interesting in ['Tests with errors:',
+                            'Tests with failures:',
+                            'Total:']:
+            try:
+                summary_idx = min(summary_idx,
+                                  log_text.rindex('Tests with errors:'))
+            except ValueError:
+                pass
+        return log_text[summary_idx:]
+
+# Custom helper classes
+######################################
+
+######################################
 # egg building
 
 def makeEGGfactory():
     svn_url = 'svn://svn.zope.org/repos/main/Sandbox/adamg/zope.wineggbuilder/trunk'
 
-    f = BuildFactory()
-    f.addStep(SVN(svnurl=svn_url, mode='clobber'))
+    f = factory.BuildFactory()
+    f.addStep(source.SVN(svnurl=svn_url, mode='clobber'))
 
 
-    f.addStep(Compile(name='bootstrap',
+    f.addStep(shell.Compile(name='bootstrap',
                 command='python bootstrap.py',
                 description=['bootstrapping'],
                 descriptionDone=['bootstrap']))
 
-    f.addStep(Compile(name="buildout",
+    f.addStep(shell.Compile(name="buildout",
                 command="bin\\buildout.exe",
                 description=['buildout'],
                 descriptionDone=['buildout']))
 
-    f.addStep(Compile(name="release eggs",
+    f.addStep(shell.Compile(name="release eggs",
                 command="bin\\build.exe -s rackspace.ini",
                 description=['releasing eggs'],
                 descriptionDone=['release eggs'],
@@ -88,21 +245,140 @@
     })
 
     c['schedulers'].append(Nightly(
-                "Nightly egg build", ['wineggbuilder'], hour=[3],
+                "Nightly egg build", ['wineggbuilder'], hour=[01],
                 branch="trunk"))
 
+# egg building
 ######################################
 
+class Platform(object):
+    python = ''
+    buildout = ''
+    name = ''
+    title = ''
 
-slow_lock = locks.SlaveLock("cpu", maxCount=2)
+    def __init__(self, **kw):
+        for k,v in kw.items():
+            setattr(self, k, v)
 
+PLATFORMS = dict(
+    py_244_win32 = r'c:\Python24_32\python.exe',
+    py_254_win32 = r'c:\Python25_32\python.exe',
+    py_265_win32 = r'c:\Python26_32\python.exe',
+    py_265_win64 = r'c:\Python26_64\python.exe',
+)
+
+
+#these python's have the right settings to be able to compile binary eggs
+ZTK_DEV_PLATFORMS = dict(
+    py_244_win32 = Platform(
+        name='py_244_win32',
+        title='Python 2.4.4 win32',
+        python=r'c:\Python24_32\python.exe',
+        buildout=r'cmd /c c:\Python24_32\setupcompilerandexecute.bat bin\buildout.exe'),
+    py_254_win32 = Platform(
+        name='py_254_win32',
+        title='Python 2.5.4 win32',
+        python=r'c:\Python25_32\python.exe',
+        buildout=r'cmd /c c:\Python25_32\setupcompilerandexecute.bat bin\buildout.exe'),
+    py_265_win32 = Platform(
+        name='py_265_win32',
+        title='Python 2.6.5 win32',
+        python=r'c:\Python26_32\python.exe',
+        buildout=r'cmd /c c:\Python26_32\setupcompilerandexecute.bat bin\buildout.exe'),
+    py_265_win64 = Platform(
+        name='py_265_win64',
+        title='Python 2.6.5 win64',
+        python=r'c:\Python26_64\python.exe',
+        buildout=r'cmd /c c:\Python26_64\setupcompilerandexecute.bat bin\buildout.exe'),
+)
+
+######################################
+# ZTK tests
+
+def ztk_dev_builder(name, slavename, platform, locks):
+    builddir = name.replace(' ', '-')
+    f = factory.BuildFactory()
+    f.addStep(SVN(
+              svnurl="svn://svn.zope.org/repos/main/zopetoolkit/trunk",
+              haltOnFailure=True,
+              mode="update"))
+
+    lc = LastChange()
+    lc.url_template = 'http://zope3.pov.lt/trac/log/zopetoolkit?rev=%s'
+    f.addStep(lc)
+
+    #f.addStep(shell.ShellCommand(
+    #          command=["/usr/bin/virtualenv", "--distribute", "-p", python, "--no-site-packages", "sandbox"],
+    #          haltOnFailure=True,
+    #          name="virtualenv",
+    #          description="virtualenv"))
+    f.addStep(shell.ShellCommand(
+              command=[platform.python, "bootstrap.py"],
+              haltOnFailure=True,
+              name="bootstrap",
+              description="bootstrap"))
+    f.addStep(shell.ShellCommand(
+              command=["sed", "-i", "s/svn+ssh/svn/", "ztk.cfg", "zopeapp.cfg"],
+              haltOnFailure=True,
+              name="disable ssh for svn",
+              description="disable ssh for svn"))
+    f.addStep(shell.ShellCommand(
+              command="%s -c development.cfg" % platform.buildout,
+              haltOnFailure=True,
+              name="buildout",
+              description="buildout",
+              timeout=3600))
+    f.addStep(shell.ShellCommand(
+              command=["svn", "revert", "ztk.cfg", "zopeapp.cfg"],
+              haltOnFailure=True,
+              name="revert ztk.cfg and zopeapp.cfg",
+              description="revert ztk.cfg and zopeapp.cfg"))
+    f.addStep(Test(
+              command=[r"bin\test-ztk.exe", "--exit-with-status", "-1"],
+              haltOnFailure=False,
+              name="test ztk",
+              description="test ztk trunks"))
+    f.addStep(Test(
+              command=[r"bin\test-zopeapp.exe", "--exit-with-status", "-1"],
+              haltOnFailure=False,
+              name="test zopeapp trunks",
+              description="test zopeapp"))
+    return dict(name=name,
+                slavename=slavename,
+                builddir=builddir,
+                factory=f,
+                locks=locks)
+
+def setupZTK_dev_tests(slow_lock):
+    hour = 02
+    for pname in sorted(ZTK_DEV_PLATFORMS.keys()):
+        platform = ZTK_DEV_PLATFORMS[pname]
+        name = "ztk_dev_%s" % platform.name
+        c['builders'].append(
+            ztk_dev_builder(name, 'local', platform, [slow_lock]))
+
+        c['schedulers'].append(
+            Nightly( "%s_nightly" % name, [name], hour=hour))
+
+# ZTK tests
+######################################
+
+#let's stick with ONE test
+slow_lock = locks.SlaveLock("cpu", maxCount=1)
+
 c['schedulers'] = []
 c['builders'] = []
 
 setupEggBuild(slow_lock)
+setupZTK_dev_tests(slow_lock)
 
 c['status'] = []
-#c['status'].append(html.WebStatus(http_port=8010, allowForce=True))
+
+#NO proxy via apache, so it can be kicked locally at least
+c['status'].append(html.WebStatus(http_port=8009, allowForce=True))
+
+#proxy THIS via apache
 c['status'].append(html.WebStatus(http_port=8010, allowForce=False))
 
 

Modified: Sandbox/adamg/zope.wineggbuilder/trunk/server-setup.txt
===================================================================
--- Sandbox/adamg/zope.wineggbuilder/trunk/server-setup.txt	2010-06-25 07:35:22 UTC (rev 113819)
+++ Sandbox/adamg/zope.wineggbuilder/trunk/server-setup.txt	2010-06-25 09:21:53 UTC (rev 113820)
@@ -1,4 +1,6 @@
-- windows basics
+windows basics
+==============
+
   - kill unneeded services
     - ALG
     - Automatic Updates (yes!)
@@ -71,4 +73,37 @@
     - grant permissions to user buildbot
     - beat it until it works (permissions, etc....)
 
-  - put an apache in front of the whole
\ No newline at end of file
+  - put an apache in front of the whole
+
+Buildbot for tests
+==================
+
+  - for py24_32 and py25_32:
+    - Create a file called 'distutils.cfg' in "C:\Python_xxx\Lib\distutils".
+
+[build]
+compiler=mingw32
+
+  - Create a file called 'setupcompilerandexecute.bat' in "C:\Python24_32".
+
+set PATH=%PATH%;c:\mingw\bin
+%*
+
+  - Create a file called 'setupcompilerandexecute.bat' in "C:\Python25_32".
+
+set PATH=%PATH%;c:\mingw\bin
+%*
+
+  - Create a file called 'setupcompilerandexecute.bat' in "C:\Python26_32".
+
+call "C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\VCVARSALL.bat" x86
+set PATH=%PATH%;"C:\Program Files\Microsoft SDKs\Windows\v6.1\Bin"
+%*
+
+  - Create a file called 'setupcompilerandexecute.bat' in "C:\Python25_64".
+
+call "C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\bin\VCVARSX86_AMD64.bat"
+set PATH=%PATH%;"C:\Program Files\Microsoft SDKs\Windows\v6.1\Bin\x64"
+%*
+
+  - for the rest see master.cfg
\ No newline at end of file



More information about the checkins mailing list