Skip to content

Commit

Permalink
Add PersistentQueue, StatusPush and HttpStatusPush and their unit tests
Browse files Browse the repository at this point in the history
Remove patch from SourceStamp.asDict since the content is usually too large.
Change some asDict variable names.
Add filtering to StatusJson.
  • Loading branch information
maruel committed Mar 12, 2010
1 parent 1400c91 commit f081199
Show file tree
Hide file tree
Showing 10 changed files with 2,008 additions and 49 deletions.
860 changes: 860 additions & 0 deletions buildbot/broken_test/runs/test_status_push.py

Large diffs are not rendered by default.

56 changes: 45 additions & 11 deletions buildbot/broken_test/runs/test_web_status_json.py
Expand Up @@ -24,11 +24,14 @@
'schedulers': [basic.Scheduler(name='name', branch=None,
treeStableTimer=60, builderNames=['builder1'])],
'slavePortnum': 0,
}
c['builders'] = [
BuilderConfig(name='builder1', slavename='bot1name', factory=BuildFactory()),
]
c['status'] = [html.WebStatus(http_port=0)]
'builders': [
BuilderConfig(name='builder1', slavename='bot1name',
factory=BuildFactory()),
],
'status': [html.WebStatus(http_port=0)],
'projectUrl': 'example.com/yay',
'projectName': 'Pouet',
'buildbotURL': 'build.example.com/yo',
"""


Expand Down Expand Up @@ -66,12 +69,43 @@ def testPresence(self):
d = self.startup()
def _check(page):
data = json.loads(page)
self.assertEqual(len(data), 4)
self.assertEqual(len(data['builders']), 1)
self.assertEqual(len(data['change_sources']), 1)
self.assertEqual(len(data['project']), 2)
self.assertEqual(len(data['slaves']), 1)
d.addCallback(lambda ign: self.getPage('/json', _check))
EXPECTED = {
'builders': {
'builder1': {
'basedir': 'builder1',
'cachedBuilds': [],
'category': None,
'currentBuilds': [],
'pendingBuilds': [],
'slaves': ['bot1name'],
'state': 'offline'
}
},
'change_sources': {
'0': {
'description': 'PBChangeSource listener on all-purpose slaveport'
}
},
'project': {
'buildbotURL': 'build.example.com/yo',
'projectName': 'Pouet',
'projectURL': None
},
'slaves': {
'bot1name': {
'access_uri': None,
'admin': None,
'builders': {u'builder1': []},
'connected': False,
'host': None,
'name': u'bot1name',
'runningBuilds': [],
'version': None
}
}
}
self.assertEqual(EXPECTED, data)
d.addCallback(lambda _: self.getPage('/json', _check))
return d

def testHelp(self):
Expand Down
111 changes: 111 additions & 0 deletions buildbot/broken_test/status_push_server.py
@@ -0,0 +1,111 @@
#!/usr/bin/python

"""Implements a sample server to receive status_push notifications.
It is mainly for testing.
Use with buildbot.status.status_push.StatusPush to receive all the buildbot
events.
"""

import logging
import optparse
import sys

try:
from urlparse import parse_qs
except ImportError:
from cgi import parse_qs

import BaseHTTPServer

try:
import simplejson as json
except ImportError:
try:
import json
except ImportError:
# We can live without it.
json = None


OPTIONS = None


class EventsHandler(BaseHTTPServer.BaseHTTPRequestHandler):
def do_POST(self):
try:
length = int(self.headers['Content-Length'])
except (ValueError, KeyError):
self.send_response(411)
return

try:
if (self.headers['Content-Type'] !=
'application/x-www-form-urlencoded'):
raise KeyError()
except KeyError:
self.send_response(406)
return

data = self.rfile.read(length)
remaining = length - len(data)
while remaining:
data += self.rfile.read(remaining)
remaining = length - len(data)

data_dict = parse_qs(data, True)
for packet in data_dict['packets']:
if json != None:
for p in json.loads(packet):
if OPTIONS.long:
print p
else:
print p['event']
else:
if OPTIONS.long:
print packet
else:
print packet[:90] + '...'
self.send_response(200, 'OK')
self.send_header('Content-Type', 'text/plan')
self.end_headers()
self.wfile.write('OK')


def main(argv):
parser = optparse.OptionParser(usage='%prog [options]\n\n' + __doc__)
parser.add_option('-v', '--verbose', default=0, action='count',
help='Use multiple times to increase logging')
parser.add_option('-p', '--port', type='int', default=8000,
help='HTTP port to bind to; default=%default')
parser.add_option('-b', '--binding', default='',
help='IP address to bind, default=all')
parser.add_option('-l', '--long', action='store_true',
help='Prints the whole packet')
options, args = parser.parse_args(argv)

if options.verbose == 0:
logging.basicConfig(level=logging.ERROR)
elif options.verbose == 1:
logging.basicConfig(level=logging.WARNING)
elif options.verbose == 2:
logging.basicConfig(level=logging.INFO)
else:
logging.basicConfig(level=logging.DEBUG)

global OPTIONS
OPTIONS = options

httpd = BaseHTTPServer.HTTPServer((options.binding, options.port),
EventsHandler)
if options.port == 0:
options.port = httpd.server_port
print 'Listening on port %d' % options.port
sys.stdout.flush()
httpd.serve_forever()


if __name__ == '__main__':
sys.exit(main(sys.argv))

# vim: set ts=4 sts=4 sw=4 et:
31 changes: 13 additions & 18 deletions buildbot/broken_test/unit/test_sourcestamp.py
Expand Up @@ -7,28 +7,25 @@

class SourceStampTest(unittest.TestCase):
def testAsDictEmpty(self):
s = SourceStamp()
r = s.asDict()
self.assertEqual(r, {
EXPECTED = {
'revision': None,
'patch': None,
'branch': None,
'changes': [],
'project': '',
'repository': '',
})
}
self.assertEqual(EXPECTED, SourceStamp().asDict())

def testAsDictBranch(self):
s = SourceStamp(branch='Br', revision='Rev')
r = s.asDict()
self.assertEqual(r, {
EXPECTED = {
'revision': 'Rev',
'patch': None,
'branch': 'Br',
'changes': [],
'project': '',
'repository': '',
})
}
self.assertEqual(EXPECTED,
SourceStamp(branch='Br', revision='Rev').asDict())

def testAsDictChanges(self):
changes = [
Expand All @@ -39,11 +36,10 @@ def testAsDictChanges(self):
s = SourceStamp(branch='Br', revision='Rev', patch=(1,'Pat'),
changes=changes)
r = s.asDict()
r['changes'][0]['when'] = 23
r['changes'][1]['when'] = 42
self.assertEqual(r, {
del r['changes'][0]['when']
del r['changes'][1]['when']
EXPECTED = {
'revision': 'rev3',
'patch': (1,'Pat'),
'branch': 'br3',
'project': '',
'repository':'',
Expand All @@ -57,10 +53,9 @@ def testAsDictChanges(self):
'properties': [],
'revision': 'rev2',
'revlink': '',
'when': 23,
'who': 'nobody',
'project' : '',
'repository' : '',
'who': 'nobody'
},
{
'branch': 'br3',
Expand All @@ -71,12 +66,12 @@ def testAsDictChanges(self):
'properties': [],
'revision': 'rev3',
'revlink': '',
'when': 42,
'who': 'nob',
'project' : '',
'repository' : '',
}
],
})
}
self.assertEqual(EXPECTED, r)

# vim: set ts=4 sts=4 sw=4 et:
1 change: 0 additions & 1 deletion buildbot/sourcestamp.py
Expand Up @@ -158,7 +158,6 @@ def asDict(self):
# Constant
result['revision'] = self.revision
# TODO(maruel): Make the patch content a suburl.
result['patch'] = self.patch
result['branch'] = self.branch
result['changes'] = [c.asDict() for c in getattr(self, 'changes', [])]
result['project'] = self.project
Expand Down
31 changes: 18 additions & 13 deletions buildbot/status/builder.py
Expand Up @@ -1082,8 +1082,8 @@ def asDict(self):
# Transient
result['text'] = self.getText()
result['results'] = self.getResults()
result['is_started'] = self.isStarted()
result['is_finished'] = self.isFinished()
result['isStarted'] = self.isStarted()
result['isFinished'] = self.isFinished()
result['statistics'] = self.statistics
result['times'] = self.getTimes()
result['expectations'] = self.getExpectations()
Expand Down Expand Up @@ -1497,12 +1497,11 @@ def saveYourself(self):
def asDict(self):
result = {}
# Constant
result['builderName'] = self.builder.name
result['number'] = self.getNumber()
result['source_stamp'] = self.getSourceStamp().asDict()
result['sourceStamp'] = self.getSourceStamp().asDict()
result['reason'] = self.getReason()
result['requests'] = [r.asDict() for r in self.getRequests()]
result['blame'] = self.getResponsibleUsers()
result['changes'] = [c.asText() for c in self.getChanges()]

# Transient
result['properties'] = self.getProperties().asList()
Expand All @@ -1517,9 +1516,9 @@ def asDict(self):
result['eta'] = self.getETA()
result['steps'] = [bss.asDict() for bss in self.steps]
if self.getCurrentStep():
result['current_step'] = self.getCurrentStep().asDict()
result['currentStep'] = self.getCurrentStep().asDict()
else:
result['current_step'] = None
result['currentStep'] = None
return result


Expand Down Expand Up @@ -2109,11 +2108,11 @@ def asDict(self):
current_builds = [b.getNumber() for b in self.currentBuilds]
cached_builds = list(set(self.buildCache.keys() + current_builds))
cached_builds.sort()
result['cached_builds'] = cached_builds
result['current_builds'] = current_builds
result['cachedBuilds'] = cached_builds
result['currentBuilds'] = current_builds
result['state'] = self.getState()[0]
# BuildRequestStatus doesn't have a number so display the SourceStamp.
result['pending_builds'] = [
result['pendingBuilds'] = [
b.getSourceStamp().asDict() for b in self.getPendingBuilds()
]
return result
Expand Down Expand Up @@ -2191,11 +2190,16 @@ def removeGracefulWatcher(self, watcher):

def asDict(self):
result = {}
# Transient
# Constant
result['name'] = self.getName()
result['access_uri'] = self.getAccessURI()

# Transient (since it changes when the slave reconnects)
result['host'] = self.getHost()
result['admin'] = self.getAdmin()
result['version'] = self.getVersion()
result['connected'] = self.isConnected()
result['runningBuilds'] = [b.asDict() for b in self.getRunningBuilds()]
return result


Expand Down Expand Up @@ -2488,8 +2492,9 @@ def changeAdded(self, change):
def asDict(self):
result = {}
# Constant
result['name'] = self.getProjectName()
result['url'] = self.getProjectURL()
result['projectName'] = self.getProjectName()
result['projectURL'] = self.getProjectURL()
result['buildbotURL'] = self.getBuildbotURL()
# TODO: self.getSchedulers()
# self.getChangeSources()
return result
Expand Down

0 comments on commit f081199

Please sign in to comment.