[svn r62612] moved the attic somewhere darker.
--HG-- branch : trunk
This commit is contained in:
parent
65b75cead6
commit
27a501d171
|
@ -1 +0,0 @@
|
|||
#
|
|
@ -1,287 +0,0 @@
|
|||
|
||||
""" Rest reporting stuff
|
||||
"""
|
||||
|
||||
import py
|
||||
import sys
|
||||
from StringIO import StringIO
|
||||
from py.__.test.reporter import AbstractReporter
|
||||
from py.__.test import event
|
||||
from py.__.rest.rst import *
|
||||
|
||||
class RestReporter(AbstractReporter):
|
||||
linkwriter = None
|
||||
|
||||
def __init__(self, config, hosts):
|
||||
super(RestReporter, self).__init__(config, hosts)
|
||||
self.rest = Rest()
|
||||
self.traceback_num = 0
|
||||
self.failed = dict([(host, 0) for host in hosts])
|
||||
self.skipped = dict([(host, 0) for host in hosts])
|
||||
self.passed = dict([(host, 0) for host in hosts])
|
||||
|
||||
def get_linkwriter(self):
|
||||
if self.linkwriter is None:
|
||||
try:
|
||||
self.linkwriter = self.config.getvalue('linkwriter')
|
||||
except KeyError:
|
||||
print >>sys.stderr, ('no linkwriter configured, using default '
|
||||
'one')
|
||||
self.linkwriter = RelLinkWriter()
|
||||
return self.linkwriter
|
||||
|
||||
def report_unknown(self, what):
|
||||
if self.config.option.verbose:
|
||||
self.add_rest(Paragraph("Unknown report: %s" % what))
|
||||
|
||||
def gethost(self, item):
|
||||
if item.channel:
|
||||
return item.channel.gateway.host
|
||||
return self.hosts[0]
|
||||
|
||||
def report_SendItem(self, item):
|
||||
address = self.gethost(item).hostname
|
||||
if self.config.option.verbose:
|
||||
self.add_rest(Paragraph('sending item %s to %s' % (item.item,
|
||||
address)))
|
||||
|
||||
def report_HostRSyncing(self, item):
|
||||
self.add_rest(LiteralBlock('%10s: RSYNC ==> %s' % (item.host.hostname[:10],
|
||||
item.host.relpath)))
|
||||
|
||||
def _host_ready(self, item):
|
||||
self.add_rest(LiteralBlock('%10s: READY' % (item.host.hostname[:10],)))
|
||||
|
||||
def report_TestStarted(self, event):
|
||||
txt = "Running tests on hosts: %s" % ", ".join([i.hostname for i in
|
||||
event.hosts])
|
||||
self.add_rest(Title(txt, abovechar='=', belowchar='='))
|
||||
self.timestart = event.timestart
|
||||
|
||||
def report_TestTestrunFinish(self, item):
|
||||
self.timeend = item.timeend
|
||||
self.summary()
|
||||
return len(self.failed_tests_outcome) > 0
|
||||
|
||||
def report_ImmediateFailure(self, item):
|
||||
pass
|
||||
|
||||
def report_HostGatewayReady(self, item):
|
||||
self.to_rsync[item.host] = len(item.roots)
|
||||
|
||||
def report_ItemStart(self, event):
|
||||
item = event.item
|
||||
if isinstance(item, py.test.collect.Module):
|
||||
lgt = len(list(item._tryiter()))
|
||||
lns = item.listnames()[1:]
|
||||
name = "/".join(lns)
|
||||
link = self.get_linkwriter().get_link(self.get_rootpath(item),
|
||||
item.fspath)
|
||||
if link:
|
||||
name = Link(name, link)
|
||||
txt = 'Testing module %s (%d items)' % (name, lgt)
|
||||
self.add_rest(Title('Testing module', name, '(%d items)' % (lgt,),
|
||||
belowchar='-'))
|
||||
|
||||
def get_rootpath(self, item):
|
||||
root = item.parent
|
||||
while root.parent is not None:
|
||||
root = root.parent
|
||||
return root.fspath
|
||||
|
||||
def print_summary(self, total, skipped_str, failed_str):
|
||||
self.skips()
|
||||
self.failures()
|
||||
|
||||
txt = "%d tests run%s%s in %.2fs (rsync: %.2f)" % \
|
||||
(total, skipped_str, failed_str, self.timeend - self.timestart,
|
||||
self.timersync - self.timestart)
|
||||
self.add_rest(Title(txt, belowchar='-'))
|
||||
|
||||
# since we're rendering each item, the links haven't been rendered
|
||||
# yet
|
||||
self.out.write(self.rest.render_links())
|
||||
|
||||
def report_ItemFinish(self, event):
|
||||
host = self.gethost(event)
|
||||
if event.outcome.passed:
|
||||
status = [Strong("PASSED")]
|
||||
self.passed[host] += 1
|
||||
elif event.outcome.skipped:
|
||||
status = [Strong("SKIPPED")]
|
||||
self.skipped_tests_outcome.append(event)
|
||||
self.skipped[host] += 1
|
||||
else:
|
||||
status = [Strong("FAILED"),
|
||||
InternalLink("traceback%d" % self.traceback_num)]
|
||||
self.traceback_num += 1
|
||||
self.failed[host] += 1
|
||||
self.failed_tests_outcome.append(event)
|
||||
# we'll take care of them later
|
||||
itempath = self.get_path_from_item(event.item)
|
||||
status.append(Text(itempath))
|
||||
hostname = host.hostname
|
||||
self.add_rest(ListItem(Text("%10s:" % (hostname[:10],)), *status))
|
||||
|
||||
def skips(self):
|
||||
# XXX hrmph, copied code
|
||||
texts = {}
|
||||
for event in self.skipped_tests_outcome:
|
||||
colitem = event.item
|
||||
if isinstance(event, event.ItemFinish):
|
||||
outcome = event.outcome
|
||||
text = outcome.skipped
|
||||
itemname = self.get_item_name(event, colitem)
|
||||
elif isinstance(event, event.DeselectedItem):
|
||||
text = str(event.excinfo.value)
|
||||
itemname = "/".join(colitem.listnames())
|
||||
if text not in texts:
|
||||
texts[text] = [itemname]
|
||||
else:
|
||||
texts[text].append(itemname)
|
||||
if texts:
|
||||
self.add_rest(Title('Reasons for skipped tests:', belowchar='+'))
|
||||
for text, items in texts.items():
|
||||
for item in items:
|
||||
self.add_rest(ListItem('%s: %s' % (item, text)))
|
||||
|
||||
def get_host(self, event):
|
||||
try:
|
||||
return event.channel.gateway.host
|
||||
except AttributeError:
|
||||
return None
|
||||
|
||||
def failures(self):
|
||||
self.traceback_num = 0
|
||||
tbstyle = self.config.option.tbstyle
|
||||
if self.failed_tests_outcome:
|
||||
self.add_rest(Title('Exceptions:', belowchar='+'))
|
||||
for i, event in enumerate(self.failed_tests_outcome):
|
||||
if i > 0:
|
||||
self.add_rest(Transition())
|
||||
if isinstance(event, event.ItemFinish):
|
||||
host = self.get_host(event)
|
||||
itempath = self.get_path_from_item(event.item)
|
||||
root = self.get_rootpath(event.item)
|
||||
link = self.get_linkwriter().get_link(root, event.item.fspath)
|
||||
t = Title(belowchar='+')
|
||||
if link:
|
||||
t.add(Link(itempath, link))
|
||||
else:
|
||||
t.add(Text(itempath))
|
||||
if host:
|
||||
t.add(Text('on %s' % (host.hostname,)))
|
||||
self.add_rest(t)
|
||||
if event.outcome.signal:
|
||||
self.repr_signal(event.item, event.outcome)
|
||||
else:
|
||||
self.repr_failure(event.item, event.outcome, tbstyle)
|
||||
else:
|
||||
itempath = self.get_path_from_item(event.item)
|
||||
root = self.get_rootpath(event.item)
|
||||
link = self.get_linkwriter().get_link(root, event.item.fspath)
|
||||
t = Title(abovechar='+', belowchar='+')
|
||||
if link:
|
||||
t.add(Link(itempath, link))
|
||||
else:
|
||||
t.add(Text(itempath))
|
||||
out = outcome.Outcome(excinfo=event.excinfo)
|
||||
self.repr_failure(event.item,
|
||||
outcome.ReprOutcome(out.make_repr()),
|
||||
tbstyle)
|
||||
|
||||
def repr_signal(self, item, outcome):
|
||||
signal = outcome.signal
|
||||
self.add_rest(Title('Received signal: %d' % (outcome.signal,),
|
||||
abovechar='+', belowchar='+'))
|
||||
if outcome.stdout.strip():
|
||||
self.add_rest(Paragraph('Captured process stdout:'))
|
||||
self.add_rest(LiteralBlock(outcome.stdout))
|
||||
if outcome.stderr.strip():
|
||||
self.add_rest(Paragraph('Captured process stderr:'))
|
||||
self.add_rest(LiteralBlock(outcome.stderr))
|
||||
|
||||
def repr_failure(self, item, outcome, style):
|
||||
excinfo = outcome.excinfo
|
||||
traceback = excinfo.traceback
|
||||
if not traceback:
|
||||
self.add_rest(Paragraph('empty traceback from item %r' % (item,)))
|
||||
return
|
||||
self.repr_traceback(item, excinfo, traceback, style)
|
||||
if outcome.stdout:
|
||||
self.add_rest(Title('Captured process stdout:', abovechar='+',
|
||||
belowchar='+'))
|
||||
self.add_rest(LiteralBlock(outcome.stdout))
|
||||
if outcome.stderr:
|
||||
self.add_rest(Title('Captured process stderr:', abovechar='+',
|
||||
belowchar='+'))
|
||||
self.add_rest(LiteralBlock(outcome.stderr))
|
||||
|
||||
def repr_traceback(self, item, excinfo, traceback, style):
|
||||
root = self.get_rootpath(item)
|
||||
self.add_rest(LinkTarget('traceback%d' % self.traceback_num, ""))
|
||||
self.traceback_num += 1
|
||||
if style == 'long':
|
||||
for entry in traceback:
|
||||
link = self.get_linkwriter().get_link(root,
|
||||
py.path.local(entry.path))
|
||||
if link:
|
||||
self.add_rest(Title(Link(entry.path, link),
|
||||
'line %d' % (entry.lineno,),
|
||||
belowchar='+', abovechar='+'))
|
||||
else:
|
||||
self.add_rest(Title('%s line %d' % (entry.path,
|
||||
entry.lineno,),
|
||||
belowchar='+', abovechar='+'))
|
||||
self.add_rest(LiteralBlock(self.prepare_source(entry.relline,
|
||||
entry.source)))
|
||||
elif style == 'short':
|
||||
text = []
|
||||
for entry in traceback:
|
||||
text.append('%s line %d' % (entry.path, entry.lineno))
|
||||
text.append(' %s' % (entry.source.strip(),))
|
||||
self.add_rest(LiteralBlock('\n'.join(text)))
|
||||
self.add_rest(Title(excinfo.typename, belowchar='+'))
|
||||
self.add_rest(LiteralBlock(excinfo.value))
|
||||
|
||||
def prepare_source(self, relline, source):
|
||||
text = []
|
||||
for num, line in enumerate(source.split('\n')):
|
||||
if num == relline:
|
||||
text.append('>>> %s' % (line,))
|
||||
else:
|
||||
text.append(' %s' % (line,))
|
||||
return '\n'.join(text)
|
||||
|
||||
def add_rest(self, item):
|
||||
self.rest.add(item)
|
||||
self.out.write('%s\n\n' % (item.text(),))
|
||||
|
||||
def get_path_from_item(self, item):
|
||||
lns = item.listnames()[1:]
|
||||
for i, ln in enumerate(lns):
|
||||
if i > 0 and ln != '()':
|
||||
lns[i] = '/%s' % (ln,)
|
||||
itempath = ''.join(lns)
|
||||
return itempath
|
||||
|
||||
class AbstractLinkWriter(object):
|
||||
def get_link(self, base, path):
|
||||
pass
|
||||
|
||||
class NoLinkWriter(AbstractLinkWriter):
|
||||
def get_link(self, base, path):
|
||||
return ''
|
||||
|
||||
class LinkWriter(AbstractLinkWriter):
|
||||
def __init__(self, baseurl):
|
||||
self.baseurl = baseurl
|
||||
|
||||
def get_link(self, base, path):
|
||||
relpath = path.relto(base)
|
||||
return self.baseurl + relpath
|
||||
|
||||
class RelLinkWriter(AbstractLinkWriter):
|
||||
def get_link(self, base, path):
|
||||
return path.relto(base)
|
||||
|
|
@ -1 +0,0 @@
|
|||
#
|
|
@ -1,356 +0,0 @@
|
|||
|
||||
""" tests of rest reporter backend
|
||||
"""
|
||||
|
||||
import py
|
||||
|
||||
py.test.skip("refactor ReST reporter tests")
|
||||
|
||||
from py.__.test.testing.test_reporter import AbstractTestReporter,\
|
||||
DummyChannel
|
||||
from py.__.test import event
|
||||
from py.__.test.dsession.rest import RestReporter, NoLinkWriter
|
||||
from py.__.rest.rst import *
|
||||
from py.__.test.dsession.hostmanage import Host
|
||||
from py.__.test.outcome import SerializableOutcome
|
||||
|
||||
class Container(object):
|
||||
def __init__(self, **args):
|
||||
for arg, val in args.items():
|
||||
setattr(self, arg, val)
|
||||
|
||||
class RestTestReporter(RestReporter):
|
||||
def __init__(self, *args, **kwargs):
|
||||
if args:
|
||||
super(RestReporter, self).__init__(*args, **kwargs)
|
||||
|
||||
class TestRestUnits(object):
|
||||
def setup_method(self, method):
|
||||
config = py.test.config._reparse(["some_sub"])
|
||||
config.option.verbose = False
|
||||
self.config = config
|
||||
hosts = [Host('localhost')]
|
||||
method.im_func.func_globals['ch'] = DummyChannel(hosts[0])
|
||||
method.im_func.func_globals['reporter'] = r = RestReporter(config,
|
||||
hosts)
|
||||
method.im_func.func_globals['stdout'] = s = py.std.StringIO.StringIO()
|
||||
r.out = s # XXX will need to become a real reporter some time perhaps?
|
||||
r.linkwriter = NoLinkWriter()
|
||||
|
||||
def test_report_unknown(self):
|
||||
self.config.option.verbose = True
|
||||
reporter.report_unknown('foo')
|
||||
assert stdout.getvalue() == 'Unknown report\\: foo\n\n'
|
||||
self.config.option.verbose = False
|
||||
|
||||
def test_report_SendItem(self):
|
||||
event = event.SendItem(item='foo/bar.py', channel=ch)
|
||||
reporter.report(event)
|
||||
assert stdout.getvalue() == ''
|
||||
stdout.seek(0)
|
||||
stdout.truncate()
|
||||
reporter.config.option.verbose = True
|
||||
reporter.report(event)
|
||||
assert stdout.getvalue() == ('sending item foo/bar.py to '
|
||||
'localhost\n\n')
|
||||
|
||||
def test_report_HostRSyncing(self):
|
||||
event = event.HostRSyncing(Host('localhost:/foo/bar'), "a",
|
||||
"b", False)
|
||||
reporter.report(event)
|
||||
assert stdout.getvalue() == ('::\n\n localhost: RSYNC ==> '
|
||||
'/foo/bar\n\n')
|
||||
|
||||
def test_report_HostRSyncRootReady(self):
|
||||
h = Host('localhost')
|
||||
reporter.hosts_to_rsync = 1
|
||||
reporter.report(event.HostGatewayReady(h, ["a"]))
|
||||
event = event.HostRSyncRootReady(h, "a")
|
||||
reporter.report(event)
|
||||
assert stdout.getvalue() == '::\n\n localhost: READY\n\n'
|
||||
|
||||
def test_report_TestStarted(self):
|
||||
event = event.TestStarted([Host('localhost'),
|
||||
Host('foo.com')],
|
||||
"aa", ["a", "b"])
|
||||
reporter.report(event)
|
||||
assert stdout.getvalue() == """\
|
||||
===========================================
|
||||
Running tests on hosts\: localhost, foo.com
|
||||
===========================================
|
||||
|
||||
"""
|
||||
|
||||
def test_report_ItemStart(self):
|
||||
class FakeModule(py.test.collect.Module):
|
||||
def __init__(self, parent):
|
||||
self.parent = parent
|
||||
self.fspath = py.path.local('.')
|
||||
def _tryiter(self):
|
||||
return ['test_foo', 'test_bar']
|
||||
def listnames(self):
|
||||
return ['package', 'foo', 'bar.py']
|
||||
|
||||
parent = Container(parent=None, fspath=py.path.local('.'))
|
||||
event = event.ItemStart(item=FakeModule(parent))
|
||||
reporter.report(event)
|
||||
assert stdout.getvalue() == """\
|
||||
Testing module foo/bar.py (2 items)
|
||||
-----------------------------------
|
||||
|
||||
"""
|
||||
|
||||
def test_print_summary(self):
|
||||
reporter.timestart = 10
|
||||
reporter.timeend = 20
|
||||
reporter.timersync = 15
|
||||
reporter.print_summary(10, '', '')
|
||||
assert stdout.getvalue() == """\
|
||||
10 tests run in 10.00s (rsync\: 5.00)
|
||||
-------------------------------------
|
||||
|
||||
"""
|
||||
|
||||
def test_ItemFinish_PASSED(self):
|
||||
outcome = SerializableOutcome()
|
||||
item = Container(listnames=lambda: ['', 'foo.py', 'bar', '()', 'baz'])
|
||||
event = event.ItemFinish(channel=ch, outcome=outcome, item=item)
|
||||
reporter.report(event)
|
||||
assert stdout.getvalue() == ('* localhost\\: **PASSED** '
|
||||
'foo.py/bar()/baz\n\n')
|
||||
|
||||
def test_ItemFinish_SKIPPED(self):
|
||||
outcome = SerializableOutcome(skipped="reason")
|
||||
item = Container(listnames=lambda: ['', 'foo.py', 'bar', '()', 'baz'])
|
||||
event = event.ItemFinish(channel=ch, outcome=outcome, item=item)
|
||||
reporter.report(event)
|
||||
assert stdout.getvalue() == ('* localhost\\: **SKIPPED** '
|
||||
'foo.py/bar()/baz\n\n')
|
||||
|
||||
def test_ItemFinish_FAILED(self):
|
||||
outcome = SerializableOutcome(excinfo="xxx")
|
||||
item = Container(listnames=lambda: ['', 'foo.py', 'bar', '()', 'baz'])
|
||||
event = event.ItemFinish(channel=ch, outcome=outcome, item=item)
|
||||
reporter.report(event)
|
||||
assert stdout.getvalue() == """\
|
||||
* localhost\: **FAILED** `traceback0`_ foo.py/bar()/baz
|
||||
|
||||
"""
|
||||
|
||||
def test_ItemFinish_FAILED_stdout(self):
|
||||
excinfo = Container(
|
||||
typename='FooError',
|
||||
value='A foo has occurred',
|
||||
traceback=[
|
||||
Container(
|
||||
path='foo/bar.py',
|
||||
lineno=1,
|
||||
relline=1,
|
||||
source='foo()',
|
||||
),
|
||||
Container(
|
||||
path='foo/baz.py',
|
||||
lineno=4,
|
||||
relline=1,
|
||||
source='raise FooError("A foo has occurred")',
|
||||
),
|
||||
]
|
||||
)
|
||||
outcome = SerializableOutcome(excinfo=excinfo)
|
||||
outcome.stdout = '<printed>'
|
||||
outcome.stderr = ''
|
||||
parent = Container(parent=None, fspath=py.path.local('.'))
|
||||
item = Container(listnames=lambda: ['', 'foo.py', 'bar', '()', 'baz'],
|
||||
parent=parent, fspath=py.path.local('foo'))
|
||||
event = event.ItemFinish(channel=ch, outcome=outcome,
|
||||
item=item)
|
||||
reporter.report(event)
|
||||
reporter.timestart = 10
|
||||
reporter.timeend = 20
|
||||
reporter.timersync = 15
|
||||
reporter.print_summary(10, '', '')
|
||||
|
||||
reporter.print_summary(1, 'skipped', 'failed')
|
||||
out = stdout.getvalue()
|
||||
assert out.find('<printed>') > -1
|
||||
|
||||
def test_skips(self):
|
||||
class FakeOutcome(Container, event.ItemFinish):
|
||||
pass
|
||||
|
||||
class FakeTryiter(Container, event.DeselectedItem):
|
||||
pass
|
||||
|
||||
reporter.skips()
|
||||
assert stdout.getvalue() == ''
|
||||
reporter.skipped_tests_outcome = [
|
||||
FakeOutcome(outcome=Container(skipped='problem X'),
|
||||
item=Container(listnames=lambda: ['foo', 'bar.py'])),
|
||||
FakeTryiter(excinfo=Container(value='problem Y'),
|
||||
item=Container(listnames=lambda: ['foo', 'baz.py']))]
|
||||
reporter.skips()
|
||||
assert stdout.getvalue() == """\
|
||||
Reasons for skipped tests\:
|
||||
+++++++++++++++++++++++++++
|
||||
|
||||
* foo/bar.py\: problem X
|
||||
|
||||
* foo/baz.py\: problem Y
|
||||
|
||||
"""
|
||||
|
||||
def test_failures(self):
|
||||
class FakeOutcome(Container, event.ItemFinish):
|
||||
pass
|
||||
|
||||
parent = Container(parent=None, fspath=py.path.local('.'))
|
||||
reporter.failed_tests_outcome = [
|
||||
FakeOutcome(
|
||||
outcome=Container(
|
||||
signal=False,
|
||||
excinfo=Container(
|
||||
typename='FooError',
|
||||
value='A foo has occurred',
|
||||
traceback=[
|
||||
Container(
|
||||
path='foo/bar.py',
|
||||
lineno=1,
|
||||
relline=1,
|
||||
source='foo()',
|
||||
),
|
||||
Container(
|
||||
path='foo/baz.py',
|
||||
lineno=4,
|
||||
relline=1,
|
||||
source='raise FooError("A foo has occurred")',
|
||||
),
|
||||
]
|
||||
),
|
||||
stdout='',
|
||||
stderr='',
|
||||
),
|
||||
item=Container(
|
||||
listnames=lambda: ['package', 'foo', 'bar.py',
|
||||
'baz', '()'],
|
||||
parent=parent,
|
||||
fspath=py.path.local('.'),
|
||||
),
|
||||
channel=ch,
|
||||
),
|
||||
]
|
||||
reporter.config.option.tbstyle = 'no'
|
||||
reporter.failures()
|
||||
expected = """\
|
||||
Exceptions\:
|
||||
++++++++++++
|
||||
|
||||
foo/bar.py/baz() on localhost
|
||||
+++++++++++++++++++++++++++++
|
||||
|
||||
.. _`traceback0`:
|
||||
|
||||
|
||||
FooError
|
||||
++++++++
|
||||
|
||||
::
|
||||
|
||||
A foo has occurred
|
||||
|
||||
"""
|
||||
assert stdout.getvalue() == expected
|
||||
|
||||
reporter.config.option.tbstyle = 'short'
|
||||
stdout.seek(0)
|
||||
stdout.truncate()
|
||||
reporter.failures()
|
||||
expected = """\
|
||||
Exceptions\:
|
||||
++++++++++++
|
||||
|
||||
foo/bar.py/baz() on localhost
|
||||
+++++++++++++++++++++++++++++
|
||||
|
||||
.. _`traceback0`:
|
||||
|
||||
|
||||
::
|
||||
|
||||
foo/bar.py line 1
|
||||
foo()
|
||||
foo/baz.py line 4
|
||||
raise FooError("A foo has occurred")
|
||||
|
||||
FooError
|
||||
++++++++
|
||||
|
||||
::
|
||||
|
||||
A foo has occurred
|
||||
|
||||
"""
|
||||
assert stdout.getvalue() == expected
|
||||
|
||||
reporter.config.option.tbstyle = 'long'
|
||||
stdout.seek(0)
|
||||
stdout.truncate()
|
||||
reporter.failures()
|
||||
expected = """\
|
||||
Exceptions\:
|
||||
++++++++++++
|
||||
|
||||
foo/bar.py/baz() on localhost
|
||||
+++++++++++++++++++++++++++++
|
||||
|
||||
.. _`traceback0`:
|
||||
|
||||
|
||||
+++++++++++++++++
|
||||
foo/bar.py line 1
|
||||
+++++++++++++++++
|
||||
|
||||
::
|
||||
|
||||
foo()
|
||||
|
||||
+++++++++++++++++
|
||||
foo/baz.py line 4
|
||||
+++++++++++++++++
|
||||
|
||||
::
|
||||
|
||||
raise FooError("A foo has occurred")
|
||||
|
||||
FooError
|
||||
++++++++
|
||||
|
||||
::
|
||||
|
||||
A foo has occurred
|
||||
|
||||
"""
|
||||
assert stdout.getvalue() == expected
|
||||
|
||||
|
||||
class TestRestReporter(AbstractTestReporter):
|
||||
reporter = RestReporter
|
||||
|
||||
def get_hosts(self):
|
||||
return [Host('localhost')]
|
||||
|
||||
def test_failed_to_load(self):
|
||||
py.test.skip("Not implemented")
|
||||
|
||||
def test_report_received_item_outcome(self):
|
||||
val = self.report_received_item_outcome()
|
||||
expected_list = [
|
||||
"**FAILED**",
|
||||
"**SKIPPED**",
|
||||
"**PASSED**",
|
||||
"* localhost\:",
|
||||
"`traceback0`_ test\_one.py/funcpass",
|
||||
"test\_one.py/funcpass"]
|
||||
for expected in expected_list:
|
||||
assert val.find(expected) != -1
|
||||
|
||||
|
|
@ -1,90 +0,0 @@
|
|||
|
||||
""" webtest
|
||||
"""
|
||||
|
||||
import py
|
||||
|
||||
def setup_module(mod):
|
||||
try:
|
||||
from pypy.translator.js.main import rpython2javascript
|
||||
from pypy.translator.js import commproxy
|
||||
mod.commproxy = commproxy
|
||||
mod.rpython2javascript = rpython2javascript
|
||||
except ImportError:
|
||||
py.test.skip("PyPy not found")
|
||||
mod.commproxy.USE_MOCHIKIT = False
|
||||
mod.rpython2javascript = rpython2javascript
|
||||
mod.commproxy = mod.commproxy
|
||||
from py.__.test.report.web import TestHandler as _TestHandler
|
||||
from py.__.test.report.web import MultiQueue
|
||||
mod._TestHandler = _TestHandler
|
||||
mod.MultiQueue = MultiQueue
|
||||
|
||||
def test_js_generate():
|
||||
from py.__.test.report import webjs
|
||||
from py.__.test.report.web import FUNCTION_LIST, IMPORTED_PYPY
|
||||
|
||||
source = rpython2javascript(webjs, FUNCTION_LIST, use_pdb=False)
|
||||
assert source
|
||||
|
||||
def test_parse_args():
|
||||
class TestTestHandler(_TestHandler):
|
||||
def __init__(self):
|
||||
pass
|
||||
h = TestTestHandler()
|
||||
assert h.parse_args('foo=bar') == {'foo': 'bar'}
|
||||
assert h.parse_args('foo=bar%20baz') == {'foo': 'bar baz'}
|
||||
assert h.parse_args('foo%20bar=baz') == {'foo bar': 'baz'}
|
||||
assert h.parse_args('foo=bar%baz') == {'foo': 'bar\xbaz'}
|
||||
py.test.raises(ValueError, 'h.parse_args("foo")')
|
||||
|
||||
class TestMultiQueue(object):
|
||||
def test_get_one_sessid(self):
|
||||
mq = MultiQueue()
|
||||
mq.put(1)
|
||||
result = mq.get(1234)
|
||||
assert result == 1
|
||||
|
||||
def test_get_two_sessid(self):
|
||||
mq = MultiQueue()
|
||||
mq.put(1)
|
||||
result = mq.get(1234)
|
||||
assert result == 1
|
||||
mq.put(2)
|
||||
result = mq.get(1234)
|
||||
assert result == 2
|
||||
result = mq.get(5678)
|
||||
assert result == 1
|
||||
result = mq.get(5678)
|
||||
assert result == 2
|
||||
|
||||
def test_get_blocking(self):
|
||||
import thread
|
||||
result = []
|
||||
def getitem(mq, sessid):
|
||||
result.append(mq.get(sessid))
|
||||
mq = MultiQueue()
|
||||
thread.start_new_thread(getitem, (mq, 1234))
|
||||
assert not result
|
||||
mq.put(1)
|
||||
py.std.time.sleep(0.1)
|
||||
assert result == [1]
|
||||
|
||||
def test_empty(self):
|
||||
mq = MultiQueue()
|
||||
assert mq.empty()
|
||||
mq.put(1)
|
||||
assert not mq.empty()
|
||||
result = mq.get(1234)
|
||||
result == 1
|
||||
assert mq.empty()
|
||||
mq.put(2)
|
||||
result = mq.get(4567)
|
||||
assert result == 1
|
||||
result = mq.get(1234)
|
||||
assert result == 2
|
||||
assert not mq.empty()
|
||||
result = mq.get(4567)
|
||||
assert result == 2
|
||||
assert mq.empty()
|
||||
|
|
@ -1,143 +0,0 @@
|
|||
import py
|
||||
|
||||
def check(mod):
|
||||
try:
|
||||
import pypy
|
||||
from pypy.translator.js.modules import dom
|
||||
from pypy.translator.js.tester import schedule_callbacks
|
||||
dom.Window # check whether dom was properly imported or is just a
|
||||
# leftover in sys.modules
|
||||
except (ImportError, AttributeError):
|
||||
py.test.skip('PyPy not found')
|
||||
mod.dom = dom
|
||||
mod.schedule_callbacks = schedule_callbacks
|
||||
|
||||
from py.__.test.report import webjs
|
||||
from py.__.test.report.web import exported_methods
|
||||
mod.webjs = webjs
|
||||
mod.exported_methods = exported_methods
|
||||
mod.here = py.magic.autopath().dirpath()
|
||||
|
||||
def setup_module(mod):
|
||||
check(mod)
|
||||
|
||||
# load HTML into window object
|
||||
html = here.join('../webdata/index.html').read()
|
||||
mod.html = html
|
||||
from pypy.translator.js.modules import dom
|
||||
mod.dom = dom
|
||||
dom.window = dom.Window(html)
|
||||
dom.document = dom.window.document
|
||||
from py.__.test.report import webjs
|
||||
from py.__.test.report.web import exported_methods
|
||||
mod.webjs = webjs
|
||||
mod.exported_methods = exported_methods
|
||||
|
||||
def setup_function(f):
|
||||
dom.window = dom.Window(html)
|
||||
dom.document = dom.window.document
|
||||
|
||||
def test_html_loaded():
|
||||
body = dom.window.document.getElementsByTagName('body')[0]
|
||||
assert len(body.childNodes) > 0
|
||||
assert str(body.childNodes[1].nodeName) == 'A'
|
||||
|
||||
def test_set_msgbox():
|
||||
py.test.skip("not implemented in genjs")
|
||||
msgbox = dom.window.document.getElementById('messagebox')
|
||||
assert len(msgbox.childNodes) == 0
|
||||
webjs.set_msgbox('foo', 'bar')
|
||||
assert len(msgbox.childNodes) == 1
|
||||
assert msgbox.childNodes[0].nodeName == 'PRE'
|
||||
assert msgbox.childNodes[0].childNodes[0].nodeValue == 'foo\nbar'
|
||||
|
||||
def test_show_info():
|
||||
info = dom.window.document.getElementById('info')
|
||||
info.style.visibility = 'hidden'
|
||||
info.innerHTML = ''
|
||||
webjs.show_info('foobar')
|
||||
content = info.innerHTML
|
||||
assert content == 'foobar'
|
||||
bgcolor = info.style.backgroundColor
|
||||
assert bgcolor == 'beige'
|
||||
|
||||
def test_hide_info():
|
||||
info = dom.window.document.getElementById('info')
|
||||
info.style.visibility = 'visible'
|
||||
webjs.hide_info()
|
||||
assert info.style.visibility == 'hidden'
|
||||
|
||||
def test_process():
|
||||
main_t = dom.window.document.getElementById('main_table')
|
||||
assert len(main_t.getElementsByTagName('tr')) == 0
|
||||
assert not webjs.process({})
|
||||
|
||||
msg = {'type': 'ItemStart',
|
||||
'itemtype': 'Module',
|
||||
'itemname': 'foo.py',
|
||||
'fullitemname': 'modules/foo.py',
|
||||
'length': 10,
|
||||
}
|
||||
assert webjs.process(msg)
|
||||
trs = main_t.getElementsByTagName('tr')
|
||||
assert len(trs) == 1
|
||||
tr = trs[0]
|
||||
assert len(tr.childNodes) == 2
|
||||
assert tr.childNodes[0].nodeName == 'TD'
|
||||
assert tr.childNodes[0].innerHTML == 'foo.py[0/10]'
|
||||
assert tr.childNodes[1].nodeName == 'TD'
|
||||
assert tr.childNodes[1].childNodes[0].nodeName == 'TABLE'
|
||||
assert len(tr.childNodes[1].getElementsByTagName('tr')) == 0
|
||||
|
||||
def test_process_two():
|
||||
main_t = dom.window.document.getElementById('main_table')
|
||||
msg = {'type': 'ItemStart',
|
||||
'itemtype': 'Module',
|
||||
'itemname': 'foo.py',
|
||||
'fullitemname': 'modules/foo.py',
|
||||
'length': 10,
|
||||
}
|
||||
webjs.process(msg)
|
||||
msg = {'type': 'ItemFinish',
|
||||
'fullmodulename': 'modules/foo.py',
|
||||
'passed' : 'True',
|
||||
'fullitemname' : 'modules/foo.py/test_item',
|
||||
'hostkey': None,
|
||||
}
|
||||
webjs.process(msg)
|
||||
trs = main_t.getElementsByTagName('tr')
|
||||
tds = trs[0].getElementsByTagName('td')
|
||||
# two cells in the row, one in the table inside one of the cells
|
||||
assert len(tds) == 3
|
||||
html = tds[0].innerHTML
|
||||
assert html == 'foo.py[1/10]'
|
||||
assert tds[2].innerHTML == '.'
|
||||
|
||||
def test_signal():
|
||||
main_t = dom.window.document.getElementById('main_table')
|
||||
msg = {'type': 'ItemStart',
|
||||
'itemtype': 'Module',
|
||||
'itemname': 'foo.py',
|
||||
'fullitemname': 'modules/foo.py',
|
||||
'length': 10,
|
||||
}
|
||||
webjs.process(msg)
|
||||
msg = {'type': 'ItemFinish',
|
||||
'fullmodulename': 'modules/foo.py',
|
||||
'passed' : 'False',
|
||||
'fullitemname' : 'modules/foo.py/test_item',
|
||||
'hostkey': None,
|
||||
'signal': '10',
|
||||
'skipped': 'False',
|
||||
}
|
||||
exported_methods.fail_reasons['modules/foo.py/test_item'] = 'Received signal 10'
|
||||
exported_methods.stdout['modules/foo.py/test_item'] = ''
|
||||
exported_methods.stderr['modules/foo.py/test_item'] = ''
|
||||
webjs.process(msg)
|
||||
schedule_callbacks(exported_methods)
|
||||
# ouch
|
||||
assert dom.document.getElementById('modules/foo.py').childNodes[0].\
|
||||
childNodes[0].childNodes[0].childNodes[0].nodeValue == 'F'
|
||||
|
||||
# XXX: Write down test for full run
|
||||
|
|
@ -1,471 +0,0 @@
|
|||
|
||||
""" web server for py.test
|
||||
"""
|
||||
|
||||
from BaseHTTPServer import HTTPServer, BaseHTTPRequestHandler
|
||||
|
||||
import thread, threading
|
||||
import re
|
||||
import time
|
||||
import random
|
||||
import Queue
|
||||
import os
|
||||
import sys
|
||||
import socket
|
||||
|
||||
import py
|
||||
from py.test import collect
|
||||
from py.__.test.report.webdata import json
|
||||
|
||||
DATADIR = py.path.local(__file__).dirpath("webdata")
|
||||
FUNCTION_LIST = ["main", "show_skip", "show_traceback", "show_info", "hide_info",
|
||||
"show_host", "hide_host", "hide_messagebox", "opt_scroll"]
|
||||
|
||||
try:
|
||||
from pypy.rpython.ootypesystem.bltregistry import MethodDesc, BasicExternal
|
||||
from pypy.translator.js.main import rpython2javascript
|
||||
from pypy.translator.js import commproxy
|
||||
from pypy.translator.js.lib.support import callback
|
||||
|
||||
commproxy.USE_MOCHIKIT = False
|
||||
IMPORTED_PYPY = True
|
||||
except (ImportError, NameError):
|
||||
class BasicExternal(object):
|
||||
pass
|
||||
|
||||
def callback(*args, **kwargs):
|
||||
def decorator(func):
|
||||
return func
|
||||
return decorator
|
||||
|
||||
IMPORTED_PYPY = False
|
||||
|
||||
def add_item(event):
|
||||
""" A little helper
|
||||
"""
|
||||
item = event.item
|
||||
itemtype = item.__class__.__name__
|
||||
itemname = item.name
|
||||
fullitemname = "/".join(item.listnames())
|
||||
d = {'fullitemname': fullitemname, 'itemtype': itemtype,
|
||||
'itemname': itemname}
|
||||
#if itemtype == 'Module':
|
||||
try:
|
||||
d['length'] = str(len(list(event.item._tryiter())))
|
||||
except:
|
||||
d['length'] = "?"
|
||||
return d
|
||||
|
||||
class MultiQueue(object):
|
||||
""" a tailor-made queue (internally using Queue) for py.test.dsession.web
|
||||
|
||||
API-wise the main difference is that the get() method gets a sessid
|
||||
argument, which is used to determine what data to feed to the client
|
||||
|
||||
when a data queue for a sessid doesn't yet exist, it is created, and
|
||||
filled with data that has already been fed to the other clients
|
||||
"""
|
||||
def __init__(self):
|
||||
self._cache = []
|
||||
self._session_queues = {}
|
||||
self._lock = py.std.thread.allocate_lock()
|
||||
|
||||
def put(self, item):
|
||||
self._lock.acquire()
|
||||
try:
|
||||
self._cache.append(item)
|
||||
for key, q in self._session_queues.items():
|
||||
q.put(item)
|
||||
finally:
|
||||
self._lock.release()
|
||||
|
||||
def _del(self, sessid):
|
||||
self._lock.acquire()
|
||||
try:
|
||||
del self._session_queues[sessid]
|
||||
finally:
|
||||
self._lock.release()
|
||||
|
||||
def get(self, sessid):
|
||||
self._lock.acquire()
|
||||
try:
|
||||
if not sessid in self._session_queues:
|
||||
self._create_session_queue(sessid)
|
||||
finally:
|
||||
self._lock.release()
|
||||
return self._session_queues[sessid].get(sessid)
|
||||
|
||||
def empty(self):
|
||||
self._lock.acquire()
|
||||
try:
|
||||
if not self._session_queues:
|
||||
return not len(self._cache)
|
||||
for q in self._session_queues.values():
|
||||
if not q.empty():
|
||||
return False
|
||||
finally:
|
||||
self._lock.release()
|
||||
return True
|
||||
|
||||
def empty_queue(self, sessid):
|
||||
return self._session_queues[sessid].empty()
|
||||
|
||||
def _create_session_queue(self, sessid):
|
||||
self._session_queues[sessid] = q = Queue.Queue()
|
||||
for item in self._cache:
|
||||
q.put(item)
|
||||
|
||||
class ExportedMethods(BasicExternal):
|
||||
_render_xmlhttp = True
|
||||
def __init__(self):
|
||||
self.pending_events = MultiQueue()
|
||||
self.start_event = threading.Event()
|
||||
self.end_event = threading.Event()
|
||||
self.skip_reasons = {}
|
||||
self.fail_reasons = {}
|
||||
self.stdout = {}
|
||||
self.stderr = {}
|
||||
self.all = 0
|
||||
self.to_rsync = {}
|
||||
|
||||
def findmodule(self, item):
|
||||
# find the most outwards parent which is module
|
||||
current = item
|
||||
while current:
|
||||
if isinstance(current, collect.Module):
|
||||
break
|
||||
current = current.parent
|
||||
|
||||
if current is not None:
|
||||
return str(current.name), str("/".join(current.listnames()))
|
||||
else:
|
||||
return str(item.parent.name), str("/".join(item.parent.listnames()))
|
||||
|
||||
def show_hosts(self):
|
||||
self.start_event.wait()
|
||||
to_send = {}
|
||||
for host in self.hosts:
|
||||
to_send[host.hostid] = host.hostname
|
||||
return to_send
|
||||
show_hosts = callback(retval={str:str})(show_hosts)
|
||||
|
||||
def show_skip(self, item_name="aa"):
|
||||
return {'item_name': item_name,
|
||||
'reason': self.skip_reasons[item_name]}
|
||||
show_skip = callback(retval={str:str})(show_skip)
|
||||
|
||||
def show_fail(self, item_name="aa"):
|
||||
return {'item_name':item_name,
|
||||
'traceback':str(self.fail_reasons[item_name]),
|
||||
'stdout':self.stdout[item_name],
|
||||
'stderr':self.stderr[item_name]}
|
||||
show_fail = callback(retval={str:str})(show_fail)
|
||||
|
||||
_sessids = None
|
||||
_sesslock = py.std.thread.allocate_lock()
|
||||
def show_sessid(self):
|
||||
if not self._sessids:
|
||||
self._sessids = []
|
||||
self._sesslock.acquire()
|
||||
try:
|
||||
while 1:
|
||||
sessid = ''.join(py.std.random.sample(
|
||||
py.std.string.lowercase, 8))
|
||||
if sessid not in self._sessids:
|
||||
self._sessids.append(sessid)
|
||||
break
|
||||
finally:
|
||||
self._sesslock.release()
|
||||
return sessid
|
||||
show_sessid = callback(retval=str)(show_sessid)
|
||||
|
||||
def failed(self, **kwargs):
|
||||
if not 'sessid' in kwargs:
|
||||
return
|
||||
sessid = kwargs['sessid']
|
||||
to_del = -1
|
||||
for num, i in enumerate(self._sessids):
|
||||
if i == sessid:
|
||||
to_del = num
|
||||
if to_del != -1:
|
||||
del self._sessids[to_del]
|
||||
self.pending_events._del(kwargs['sessid'])
|
||||
|
||||
def show_all_statuses(self, sessid='xx'):
|
||||
retlist = [self.show_status_change(sessid)]
|
||||
while not self.pending_events.empty_queue(sessid):
|
||||
retlist.append(self.show_status_change(sessid))
|
||||
retval = retlist
|
||||
return retval
|
||||
show_all_statuses = callback(retval=[{str:str}])(show_all_statuses)
|
||||
|
||||
def show_status_change(self, sessid):
|
||||
event = self.pending_events.get(sessid)
|
||||
if event is None:
|
||||
self.end_event.set()
|
||||
return {}
|
||||
# some dispatcher here
|
||||
if isinstance(event, event.ItemFinish):
|
||||
args = {}
|
||||
outcome = event.outcome
|
||||
for key, val in outcome.__dict__.iteritems():
|
||||
args[key] = str(val)
|
||||
args.update(add_item(event))
|
||||
mod_name, mod_fullname = self.findmodule(event.item)
|
||||
args['modulename'] = str(mod_name)
|
||||
args['fullmodulename'] = str(mod_fullname)
|
||||
fullitemname = args['fullitemname']
|
||||
if outcome.skipped:
|
||||
self.skip_reasons[fullitemname] = self.repr_failure_tblong(
|
||||
event.item,
|
||||
outcome.skipped,
|
||||
outcome.skipped.traceback)
|
||||
elif outcome.excinfo:
|
||||
self.fail_reasons[fullitemname] = self.repr_failure_tblong(
|
||||
event.item, outcome.excinfo, outcome.excinfo.traceback)
|
||||
self.stdout[fullitemname] = outcome.stdout
|
||||
self.stderr[fullitemname] = outcome.stderr
|
||||
elif outcome.signal:
|
||||
self.fail_reasons[fullitemname] = "Received signal %d" % outcome.signal
|
||||
self.stdout[fullitemname] = outcome.stdout
|
||||
self.stderr[fullitemname] = outcome.stderr
|
||||
if event.channel:
|
||||
args['hostkey'] = event.channel.gateway.host.hostid
|
||||
else:
|
||||
args['hostkey'] = ''
|
||||
elif isinstance(event, event.ItemStart):
|
||||
args = add_item(event)
|
||||
elif isinstance(event, event.TestTestrunFinish):
|
||||
args = {}
|
||||
args['run'] = str(self.all)
|
||||
args['fails'] = str(len(self.fail_reasons))
|
||||
args['skips'] = str(len(self.skip_reasons))
|
||||
elif isinstance(event, event.SendItem):
|
||||
args = add_item(event)
|
||||
args['hostkey'] = event.channel.gateway.host.hostid
|
||||
elif isinstance(event, event.HostRSyncRootReady):
|
||||
self.ready_hosts[event.host] = True
|
||||
args = {'hostname' : event.host.hostname, 'hostkey' : event.host.hostid}
|
||||
elif isinstance(event, event.FailedTryiter):
|
||||
args = add_item(event)
|
||||
elif isinstance(event, event.DeselectedItem):
|
||||
args = add_item(event)
|
||||
args['reason'] = str(event.excinfo.value)
|
||||
else:
|
||||
args = {}
|
||||
args['event'] = str(event)
|
||||
args['type'] = event.__class__.__name__
|
||||
return args
|
||||
|
||||
def repr_failure_tblong(self, item, excinfo, traceback):
|
||||
lines = []
|
||||
for index, entry in py.builtin.enumerate(traceback):
|
||||
lines.append('----------')
|
||||
lines.append("%s: %s" % (entry.path, entry.lineno))
|
||||
lines += self.repr_source(entry.relline, entry.source)
|
||||
lines.append("%s: %s" % (excinfo.typename, excinfo.value))
|
||||
return "\n".join(lines)
|
||||
|
||||
def repr_source(self, relline, source):
|
||||
lines = []
|
||||
for num, line in enumerate(str(source).split("\n")):
|
||||
if num == relline:
|
||||
lines.append(">>>>" + line)
|
||||
else:
|
||||
lines.append(" " + line)
|
||||
return lines
|
||||
|
||||
def report_ItemFinish(self, event):
|
||||
self.all += 1
|
||||
self.pending_events.put(event)
|
||||
|
||||
def report_FailedTryiter(self, event):
|
||||
fullitemname = "/".join(event.item.listnames())
|
||||
self.fail_reasons[fullitemname] = self.repr_failure_tblong(
|
||||
event.item, event.excinfo, event.excinfo.traceback)
|
||||
self.stdout[fullitemname] = ''
|
||||
self.stderr[fullitemname] = ''
|
||||
self.pending_events.put(event)
|
||||
|
||||
def report_ItemStart(self, event):
|
||||
if isinstance(event.item, py.test.collect.Module):
|
||||
self.pending_events.put(event)
|
||||
|
||||
def report_unknown(self, event):
|
||||
# XXX: right now, we just pass it for showing
|
||||
self.pending_events.put(event)
|
||||
|
||||
def _host_ready(self, event):
|
||||
self.pending_events.put(event)
|
||||
|
||||
def report_HostGatewayReady(self, item):
|
||||
self.to_rsync[item.host] = len(item.roots)
|
||||
|
||||
def report_HostRSyncRootReady(self, item):
|
||||
self.to_rsync[item.host] -= 1
|
||||
if not self.to_rsync[item.host]:
|
||||
self._host_ready(item)
|
||||
|
||||
def report_TestStarted(self, event):
|
||||
# XXX: It overrides our self.hosts
|
||||
self.hosts = {}
|
||||
self.ready_hosts = {}
|
||||
if not event.hosts:
|
||||
self.hosts = []
|
||||
else:
|
||||
for host in event.hosts:
|
||||
self.hosts[host] = host
|
||||
self.ready_hosts[host] = False
|
||||
self.start_event.set()
|
||||
self.pending_events.put(event)
|
||||
|
||||
def report_TestTestrunFinish(self, event):
|
||||
self.pending_events.put(event)
|
||||
kill_server()
|
||||
|
||||
report_InterruptedExecution = report_TestTestrunFinish
|
||||
report_CrashedExecution = report_TestTestrunFinish
|
||||
|
||||
def report(self, what):
|
||||
repfun = getattr(self, "report_" + what.__class__.__name__,
|
||||
self.report_unknown)
|
||||
try:
|
||||
repfun(what)
|
||||
except (KeyboardInterrupt, SystemExit):
|
||||
raise
|
||||
except:
|
||||
print "Internal reporting problem"
|
||||
excinfo = py.code.ExceptionInfo()
|
||||
for i in excinfo.traceback:
|
||||
print str(i)[2:-1]
|
||||
print excinfo
|
||||
|
||||
exported_methods = ExportedMethods()
|
||||
|
||||
class TestHandler(BaseHTTPRequestHandler):
|
||||
exported_methods = exported_methods
|
||||
|
||||
def do_GET(self):
|
||||
path = self.path
|
||||
if path.endswith("/"):
|
||||
path = path[:-1]
|
||||
if path.startswith("/"):
|
||||
path = path[1:]
|
||||
m = re.match('^(.*)\?(.*)$', path)
|
||||
if m:
|
||||
path = m.group(1)
|
||||
getargs = m.group(2)
|
||||
else:
|
||||
getargs = ""
|
||||
name_path = path.replace(".", "_")
|
||||
method_to_call = getattr(self, "run_" + name_path, None)
|
||||
if method_to_call is None:
|
||||
exec_meth = getattr(self.exported_methods, name_path, None)
|
||||
if exec_meth is None:
|
||||
self.send_error(404, "File %s not found" % path)
|
||||
else:
|
||||
try:
|
||||
self.serve_data('text/json',
|
||||
json.write(exec_meth(**self.parse_args(getargs))))
|
||||
except socket.error:
|
||||
# client happily disconnected
|
||||
exported_methods.failed(**self.parse_args(getargs))
|
||||
else:
|
||||
method_to_call()
|
||||
|
||||
def parse_args(self, getargs):
|
||||
# parse get argument list
|
||||
if getargs == "":
|
||||
return {}
|
||||
|
||||
unquote = py.std.urllib.unquote
|
||||
args = {}
|
||||
arg_pairs = getargs.split("&")
|
||||
for arg in arg_pairs:
|
||||
key, value = arg.split("=")
|
||||
args[unquote(key)] = unquote(value)
|
||||
return args
|
||||
|
||||
def log_message(self, format, *args):
|
||||
# XXX just discard it
|
||||
pass
|
||||
|
||||
do_POST = do_GET
|
||||
|
||||
def run_(self):
|
||||
self.run_index()
|
||||
|
||||
def run_index(self):
|
||||
data = py.path.local(DATADIR).join("index.html").open().read()
|
||||
self.serve_data("text/html", data)
|
||||
|
||||
def run_jssource(self):
|
||||
js_name = py.path.local(__file__).dirpath("webdata").join("source.js")
|
||||
web_name = py.path.local(__file__).dirpath().join("webjs.py")
|
||||
if IMPORTED_PYPY and web_name.mtime() > js_name.mtime() or \
|
||||
(not js_name.check()):
|
||||
from py.__.test.dsession import webjs
|
||||
|
||||
javascript_source = rpython2javascript(webjs,
|
||||
FUNCTION_LIST, use_pdb=False)
|
||||
open(str(js_name), "w").write(javascript_source)
|
||||
self.serve_data("text/javascript", javascript_source)
|
||||
else:
|
||||
js_source = open(str(js_name), "r").read()
|
||||
self.serve_data("text/javascript", js_source)
|
||||
|
||||
def serve_data(self, content_type, data):
|
||||
self.send_response(200)
|
||||
self.send_header("Content-type", content_type)
|
||||
self.send_header("Content-length", len(data))
|
||||
self.end_headers()
|
||||
self.wfile.write(data)
|
||||
|
||||
class WebReporter(object):
|
||||
""" A simple wrapper, this file needs ton of refactoring
|
||||
anyway, so this is just to satisfy things below
|
||||
(and start to create saner interface as well)
|
||||
"""
|
||||
def __init__(self, config, hosts):
|
||||
start_server_from_config(config)
|
||||
|
||||
def was_failure(self):
|
||||
return sum(exported_methods.fail_reasons.values()) > 0
|
||||
|
||||
# rebind
|
||||
report = exported_methods.report
|
||||
__call__ = report
|
||||
|
||||
def start_server_from_config(config):
|
||||
if config.option.runbrowser:
|
||||
port = socket.INADDR_ANY
|
||||
else:
|
||||
port = 8000
|
||||
|
||||
httpd = start_server(server_address = ('', port))
|
||||
port = httpd.server_port
|
||||
if config.option.runbrowser:
|
||||
import webbrowser, thread
|
||||
# webbrowser.open() may block until the browser finishes or not
|
||||
url = "http://localhost:%d" % (port,)
|
||||
thread.start_new_thread(webbrowser.open, (url,))
|
||||
|
||||
return exported_methods.report
|
||||
|
||||
def start_server(server_address = ('', 8000), handler=TestHandler, start_new=True):
|
||||
httpd = HTTPServer(server_address, handler)
|
||||
|
||||
if start_new:
|
||||
thread.start_new_thread(httpd.serve_forever, ())
|
||||
print "Server started, listening on port %d" % (httpd.server_port,)
|
||||
return httpd
|
||||
else:
|
||||
print "Server started, listening on port %d" % (httpd.server_port,)
|
||||
httpd.serve_forever()
|
||||
|
||||
def kill_server():
|
||||
exported_methods.pending_events.put(None)
|
||||
while not exported_methods.pending_events.empty():
|
||||
time.sleep(.1)
|
||||
exported_methods.end_event.wait()
|
||||
|
|
@ -1,126 +0,0 @@
|
|||
<html>
|
||||
<head>
|
||||
<title>Py.test</title>
|
||||
<script type="text/javascript" src="/jssource"></script>
|
||||
<style type="text/css">
|
||||
|
||||
body, td, div {
|
||||
font-family: Andale mono;
|
||||
background-color: #ffd;
|
||||
color: #003;
|
||||
}
|
||||
|
||||
#info {
|
||||
visibility: hidden;
|
||||
position: fixed;
|
||||
left: 0px;
|
||||
top: 0px;
|
||||
text-align: center;
|
||||
width: 100%;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
div.main {
|
||||
margin-right: 170px;
|
||||
}
|
||||
|
||||
.error {
|
||||
color: #F00;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
#navbar {
|
||||
position: fixed;
|
||||
right: 1em;
|
||||
top: 1em;
|
||||
background-color: #ffd;
|
||||
border: 1px solid #003;
|
||||
z-index: 1;
|
||||
width: 160px;
|
||||
}
|
||||
|
||||
#navbar tr, #navbar td {
|
||||
border: 0px;
|
||||
}
|
||||
|
||||
#navbar a {
|
||||
color: #003;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
#navbar .title {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
#jobs {
|
||||
position: absolute;
|
||||
visibility: hidden;
|
||||
right: 2px;
|
||||
}
|
||||
|
||||
#jobs, #jobs td {
|
||||
background-color: #ffd;
|
||||
border: 1px solid #003;
|
||||
}
|
||||
|
||||
#jobs tr, #jobs td {
|
||||
border: 0px;
|
||||
}
|
||||
|
||||
</style>
|
||||
</head>
|
||||
<body onload="main()">
|
||||
<a name="beginning">
|
||||
<h3 id="Tests">Tests</h3>
|
||||
</a>
|
||||
<div id="info">
|
||||
 
|
||||
</div>
|
||||
<table id="navbar">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td class="title">Hosts status</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<table id="hosts">
|
||||
<tbody id="hostsbody">
|
||||
</tbody>
|
||||
</table>
|
||||
<table id="jobs">
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="title">Navigation</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="#beginning">Top</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="#message">Traceback info</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="#aftermessage">End of Traceback</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="title">Options</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><input type="checkbox" id="opt_scroll" onchange="javascript:opt_scroll()"/><u>S</u>croll with tests arriving</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<div class="main">
|
||||
<table id="main_table">
|
||||
</table>
|
||||
<fieldset id="messagebox_fieldset">
|
||||
<legend><b>Data [<a href="javascript:hide_messagebox()">hide</a>]:</b></legend>
|
||||
<a name="message"> </a>
|
||||
<div id="messagebox"></div>
|
||||
</fieldset>
|
||||
</div>
|
||||
<a name="aftermessage"> </a>
|
||||
<div id="testmain"></div>
|
||||
</body>
|
||||
</html>
|
|
@ -1,310 +0,0 @@
|
|||
import string
|
||||
import types
|
||||
|
||||
## json.py implements a JSON (http://json.org) reader and writer.
|
||||
## Copyright (C) 2005 Patrick D. Logan
|
||||
## Contact mailto:patrickdlogan@stardecisions.com
|
||||
##
|
||||
## This library is free software; you can redistribute it and/or
|
||||
## modify it under the terms of the GNU Lesser General Public
|
||||
## License as published by the Free Software Foundation; either
|
||||
## version 2.1 of the License, or (at your option) any later version.
|
||||
##
|
||||
## This library is distributed in the hope that it will be useful,
|
||||
## but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
## Lesser General Public License for more details.
|
||||
##
|
||||
## You should have received a copy of the GNU Lesser General Public
|
||||
## License along with this library; if not, write to the Free Software
|
||||
## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
|
||||
class _StringGenerator(object):
|
||||
def __init__(self, string):
|
||||
self.string = string
|
||||
self.index = -1
|
||||
def peek(self):
|
||||
i = self.index + 1
|
||||
if i < len(self.string):
|
||||
return self.string[i]
|
||||
else:
|
||||
return None
|
||||
def next(self):
|
||||
self.index += 1
|
||||
if self.index < len(self.string):
|
||||
return self.string[self.index]
|
||||
else:
|
||||
raise StopIteration
|
||||
def all(self):
|
||||
return self.string
|
||||
|
||||
class WriteException(Exception):
|
||||
pass
|
||||
|
||||
class ReadException(Exception):
|
||||
pass
|
||||
|
||||
class JsonReader(object):
|
||||
hex_digits = {'A': 10,'B': 11,'C': 12,'D': 13,'E': 14,'F':15}
|
||||
escapes = {'t':'\t','n':'\n','f':'\f','r':'\r','b':'\b'}
|
||||
|
||||
def read(self, s):
|
||||
self._generator = _StringGenerator(s)
|
||||
result = self._read()
|
||||
return result
|
||||
|
||||
def _read(self):
|
||||
self._eatWhitespace()
|
||||
peek = self._peek()
|
||||
if peek is None:
|
||||
raise ReadException, "Nothing to read: '%s'" % self._generator.all()
|
||||
if peek == '{':
|
||||
return self._readObject()
|
||||
elif peek == '[':
|
||||
return self._readArray()
|
||||
elif peek == '"':
|
||||
return self._readString()
|
||||
elif peek == '-' or peek.isdigit():
|
||||
return self._readNumber()
|
||||
elif peek == 't':
|
||||
return self._readTrue()
|
||||
elif peek == 'f':
|
||||
return self._readFalse()
|
||||
elif peek == 'n':
|
||||
return self._readNull()
|
||||
elif peek == '/':
|
||||
self._readComment()
|
||||
return self._read()
|
||||
else:
|
||||
raise ReadException, "Input is not valid JSON: '%s'" % self._generator.all()
|
||||
|
||||
def _readTrue(self):
|
||||
self._assertNext('t', "true")
|
||||
self._assertNext('r', "true")
|
||||
self._assertNext('u', "true")
|
||||
self._assertNext('e', "true")
|
||||
return True
|
||||
|
||||
def _readFalse(self):
|
||||
self._assertNext('f', "false")
|
||||
self._assertNext('a', "false")
|
||||
self._assertNext('l', "false")
|
||||
self._assertNext('s', "false")
|
||||
self._assertNext('e', "false")
|
||||
return False
|
||||
|
||||
def _readNull(self):
|
||||
self._assertNext('n', "null")
|
||||
self._assertNext('u', "null")
|
||||
self._assertNext('l', "null")
|
||||
self._assertNext('l', "null")
|
||||
return None
|
||||
|
||||
def _assertNext(self, ch, target):
|
||||
if self._next() != ch:
|
||||
raise ReadException, "Trying to read %s: '%s'" % (target, self._generator.all())
|
||||
|
||||
def _readNumber(self):
|
||||
isfloat = False
|
||||
result = self._next()
|
||||
peek = self._peek()
|
||||
while peek is not None and (peek.isdigit() or peek == "."):
|
||||
isfloat = isfloat or peek == "."
|
||||
result = result + self._next()
|
||||
peek = self._peek()
|
||||
try:
|
||||
if isfloat:
|
||||
return float(result)
|
||||
else:
|
||||
return int(result)
|
||||
except ValueError:
|
||||
raise ReadException, "Not a valid JSON number: '%s'" % result
|
||||
|
||||
def _readString(self):
|
||||
result = ""
|
||||
assert self._next() == '"'
|
||||
try:
|
||||
while self._peek() != '"':
|
||||
ch = self._next()
|
||||
if ch == "\\":
|
||||
ch = self._next()
|
||||
if ch in 'brnft':
|
||||
ch = self.escapes[ch]
|
||||
elif ch == "u":
|
||||
ch4096 = self._next()
|
||||
ch256 = self._next()
|
||||
ch16 = self._next()
|
||||
ch1 = self._next()
|
||||
n = 4096 * self._hexDigitToInt(ch4096)
|
||||
n += 256 * self._hexDigitToInt(ch256)
|
||||
n += 16 * self._hexDigitToInt(ch16)
|
||||
n += self._hexDigitToInt(ch1)
|
||||
ch = unichr(n)
|
||||
elif ch not in '"/\\':
|
||||
raise ReadException, "Not a valid escaped JSON character: '%s' in %s" % (ch, self._generator.all())
|
||||
result = result + ch
|
||||
except StopIteration:
|
||||
raise ReadException, "Not a valid JSON string: '%s'" % self._generator.all()
|
||||
assert self._next() == '"'
|
||||
return result
|
||||
|
||||
def _hexDigitToInt(self, ch):
|
||||
try:
|
||||
result = self.hex_digits[ch.upper()]
|
||||
except KeyError:
|
||||
try:
|
||||
result = int(ch)
|
||||
except ValueError:
|
||||
raise ReadException, "The character %s is not a hex digit." % ch
|
||||
return result
|
||||
|
||||
def _readComment(self):
|
||||
assert self._next() == "/"
|
||||
second = self._next()
|
||||
if second == "/":
|
||||
self._readDoubleSolidusComment()
|
||||
elif second == '*':
|
||||
self._readCStyleComment()
|
||||
else:
|
||||
raise ReadException, "Not a valid JSON comment: %s" % self._generator.all()
|
||||
|
||||
def _readCStyleComment(self):
|
||||
try:
|
||||
done = False
|
||||
while not done:
|
||||
ch = self._next()
|
||||
done = (ch == "*" and self._peek() == "/")
|
||||
if not done and ch == "/" and self._peek() == "*":
|
||||
raise ReadException, "Not a valid JSON comment: %s, '/*' cannot be embedded in the comment." % self._generator.all()
|
||||
self._next()
|
||||
except StopIteration:
|
||||
raise ReadException, "Not a valid JSON comment: %s, expected */" % self._generator.all()
|
||||
|
||||
def _readDoubleSolidusComment(self):
|
||||
try:
|
||||
ch = self._next()
|
||||
while ch != "\r" and ch != "\n":
|
||||
ch = self._next()
|
||||
except StopIteration:
|
||||
pass
|
||||
|
||||
def _readArray(self):
|
||||
result = []
|
||||
assert self._next() == '['
|
||||
done = self._peek() == ']'
|
||||
while not done:
|
||||
item = self._read()
|
||||
result.append(item)
|
||||
self._eatWhitespace()
|
||||
done = self._peek() == ']'
|
||||
if not done:
|
||||
ch = self._next()
|
||||
if ch != ",":
|
||||
raise ReadException, "Not a valid JSON array: '%s' due to: '%s'" % (self._generator.all(), ch)
|
||||
assert ']' == self._next()
|
||||
return result
|
||||
|
||||
def _readObject(self):
|
||||
result = {}
|
||||
assert self._next() == '{'
|
||||
done = self._peek() == '}'
|
||||
while not done:
|
||||
key = self._read()
|
||||
if type(key) is not types.StringType:
|
||||
raise ReadException, "Not a valid JSON object key (should be a string): %s" % key
|
||||
self._eatWhitespace()
|
||||
ch = self._next()
|
||||
if ch != ":":
|
||||
raise ReadException, "Not a valid JSON object: '%s' due to: '%s'" % (self._generator.all(), ch)
|
||||
self._eatWhitespace()
|
||||
val = self._read()
|
||||
result[key] = val
|
||||
self._eatWhitespace()
|
||||
done = self._peek() == '}'
|
||||
if not done:
|
||||
ch = self._next()
|
||||
if ch != ",":
|
||||
raise ReadException, "Not a valid JSON array: '%s' due to: '%s'" % (self._generator.all(), ch)
|
||||
assert self._next() == "}"
|
||||
return result
|
||||
|
||||
def _eatWhitespace(self):
|
||||
p = self._peek()
|
||||
while p is not None and p in string.whitespace or p == '/':
|
||||
if p == '/':
|
||||
self._readComment()
|
||||
else:
|
||||
self._next()
|
||||
p = self._peek()
|
||||
|
||||
def _peek(self):
|
||||
return self._generator.peek()
|
||||
|
||||
def _next(self):
|
||||
return self._generator.next()
|
||||
|
||||
class JsonWriter(object):
|
||||
|
||||
def _append(self, s):
|
||||
self._results.append(s)
|
||||
|
||||
def write(self, obj, escaped_forward_slash=False):
|
||||
self._escaped_forward_slash = escaped_forward_slash
|
||||
self._results = []
|
||||
self._write(obj)
|
||||
return "".join(self._results)
|
||||
|
||||
def _write(self, obj):
|
||||
ty = type(obj)
|
||||
if ty is types.DictType:
|
||||
n = len(obj)
|
||||
self._append("{")
|
||||
for k, v in obj.items():
|
||||
self._write(k)
|
||||
self._append(":")
|
||||
self._write(v)
|
||||
n = n - 1
|
||||
if n > 0:
|
||||
self._append(",")
|
||||
self._append("}")
|
||||
elif ty is types.ListType or ty is types.TupleType:
|
||||
n = len(obj)
|
||||
self._append("[")
|
||||
for item in obj:
|
||||
self._write(item)
|
||||
n = n - 1
|
||||
if n > 0:
|
||||
self._append(",")
|
||||
self._append("]")
|
||||
elif ty is types.StringType or ty is types.UnicodeType:
|
||||
self._append('"')
|
||||
obj = obj.replace('\\', r'\\')
|
||||
if self._escaped_forward_slash:
|
||||
obj = obj.replace('/', r'\/')
|
||||
obj = obj.replace('"', r'\"')
|
||||
obj = obj.replace('\b', r'\b')
|
||||
obj = obj.replace('\f', r'\f')
|
||||
obj = obj.replace('\n', r'\n')
|
||||
obj = obj.replace('\r', r'\r')
|
||||
obj = obj.replace('\t', r'\t')
|
||||
self._append(obj)
|
||||
self._append('"')
|
||||
elif ty is types.IntType or ty is types.LongType:
|
||||
self._append(str(obj))
|
||||
elif ty is types.FloatType:
|
||||
self._append("%f" % obj)
|
||||
elif obj is True:
|
||||
self._append("true")
|
||||
elif obj is False:
|
||||
self._append("false")
|
||||
elif obj is None:
|
||||
self._append("null")
|
||||
else:
|
||||
raise WriteException, "Cannot write in JSON: %s" % repr(obj)
|
||||
|
||||
def write(obj, escaped_forward_slash=False):
|
||||
return JsonWriter().write(obj, escaped_forward_slash)
|
||||
|
||||
def read(s):
|
||||
return JsonReader().read(s)
|
File diff suppressed because it is too large
Load Diff
|
@ -1,355 +0,0 @@
|
|||
|
||||
""" javascript source for py.test distributed
|
||||
"""
|
||||
|
||||
import py
|
||||
from py.__.test.report.web import exported_methods
|
||||
try:
|
||||
from pypy.translator.js.modules import dom
|
||||
from pypy.translator.js.helper import __show_traceback
|
||||
except ImportError:
|
||||
py.test.skip("PyPy not found")
|
||||
|
||||
def create_elem(s):
|
||||
return dom.document.createElement(s)
|
||||
|
||||
def get_elem(el):
|
||||
return dom.document.getElementById(el)
|
||||
|
||||
def create_text_elem(txt):
|
||||
return dom.document.createTextNode(txt)
|
||||
|
||||
tracebacks = {}
|
||||
skips = {}
|
||||
counters = {}
|
||||
max_items = {}
|
||||
short_item_names = {}
|
||||
|
||||
MAX_COUNTER = 30 # Maximal size of one-line table
|
||||
|
||||
class Globals(object):
|
||||
def __init__(self):
|
||||
self.pending = []
|
||||
self.host = ""
|
||||
self.data_empty = True
|
||||
|
||||
glob = Globals()
|
||||
|
||||
class Options(object):
|
||||
""" Store global options
|
||||
"""
|
||||
def __init__(self):
|
||||
self.scroll = True
|
||||
|
||||
opts = Options()
|
||||
|
||||
def comeback(msglist):
|
||||
if len(msglist) == 0:
|
||||
return
|
||||
for item in glob.pending[:]:
|
||||
if not process(item):
|
||||
return
|
||||
glob.pending = []
|
||||
for msg in msglist:
|
||||
if not process(msg):
|
||||
return
|
||||
exported_methods.show_all_statuses(glob.sessid, comeback)
|
||||
|
||||
def show_info(data="aa"):
|
||||
info = dom.document.getElementById("info")
|
||||
info.style.visibility = "visible"
|
||||
while len(info.childNodes):
|
||||
info.removeChild(info.childNodes[0])
|
||||
txt = create_text_elem(data)
|
||||
info.appendChild(txt)
|
||||
info.style.backgroundColor = "beige"
|
||||
# XXX: Need guido
|
||||
|
||||
def hide_info():
|
||||
info = dom.document.getElementById("info")
|
||||
info.style.visibility = "hidden"
|
||||
|
||||
def show_interrupt():
|
||||
glob.finished = True
|
||||
dom.document.title = "Py.test [interrupted]"
|
||||
dom.document.getElementById("Tests").childNodes[0].nodeValue = "Tests [interrupted]"
|
||||
|
||||
def show_crash():
|
||||
glob.finished = True
|
||||
dom.document.title = "Py.test [crashed]"
|
||||
dom.document.getElementById("Tests").childNodes[0].nodeValue = "Tests [crashed]"
|
||||
|
||||
SCROLL_LINES = 50
|
||||
|
||||
def opt_scroll():
|
||||
if opts.scroll:
|
||||
opts.scroll = False
|
||||
else:
|
||||
opts.scroll = True
|
||||
|
||||
def scroll_down_if_needed(mbox):
|
||||
if not opts.scroll:
|
||||
return
|
||||
#if dom.window.scrollMaxY - dom.window.scrollY < SCROLL_LINES:
|
||||
mbox.parentNode.scrollIntoView()
|
||||
|
||||
def hide_messagebox():
|
||||
mbox = dom.document.getElementById("messagebox")
|
||||
while mbox.childNodes:
|
||||
mbox.removeChild(mbox.childNodes[0])
|
||||
|
||||
def make_module_box(msg):
|
||||
tr = create_elem("tr")
|
||||
td = create_elem("td")
|
||||
tr.appendChild(td)
|
||||
td.appendChild(create_text_elem("%s[0/%s]" % (msg['itemname'],
|
||||
msg['length'])))
|
||||
max_items[msg['fullitemname']] = int(msg['length'])
|
||||
short_item_names[msg['fullitemname']] = msg['itemname']
|
||||
td.id = '_txt_' + msg['fullitemname']
|
||||
#tr.setAttribute("id", msg['fullitemname'])
|
||||
td.setAttribute("onmouseover",
|
||||
"show_info('%s')" % (msg['fullitemname'],))
|
||||
td.setAttribute("onmouseout", "hide_info()")
|
||||
td2 = create_elem('td')
|
||||
tr.appendChild(td2)
|
||||
table = create_elem("table")
|
||||
td2.appendChild(table)
|
||||
tbody = create_elem('tbody')
|
||||
tbody.id = msg['fullitemname']
|
||||
table.appendChild(tbody)
|
||||
counters[msg['fullitemname']] = 0
|
||||
return tr
|
||||
|
||||
def add_received_item_outcome(msg, module_part):
|
||||
if msg['hostkey']:
|
||||
host_elem = dom.document.getElementById(msg['hostkey'])
|
||||
glob.host_pending[msg['hostkey']].pop()
|
||||
count = len(glob.host_pending[msg['hostkey']])
|
||||
host_elem.childNodes[0].nodeValue = '%s[%s]' % (
|
||||
glob.host_dict[msg['hostkey']], count)
|
||||
|
||||
td = create_elem("td")
|
||||
td.setAttribute("onmouseover", "show_info('%s')" % (
|
||||
msg['fullitemname'],))
|
||||
td.setAttribute("onmouseout", "hide_info()")
|
||||
item_name = msg['fullitemname']
|
||||
# TODO: dispatch output
|
||||
if msg["passed"] == 'True':
|
||||
txt = create_text_elem(".")
|
||||
td.appendChild(txt)
|
||||
elif msg["skipped"] != 'None' and msg["skipped"] != "False":
|
||||
exported_methods.show_skip(item_name, skip_come_back)
|
||||
link = create_elem("a")
|
||||
link.setAttribute("href", "javascript:show_skip('%s')" % (
|
||||
msg['fullitemname'],))
|
||||
txt = create_text_elem('s')
|
||||
link.appendChild(txt)
|
||||
td.appendChild(link)
|
||||
else:
|
||||
link = create_elem("a")
|
||||
link.setAttribute("href", "javascript:show_traceback('%s')" % (
|
||||
msg['fullitemname'],))
|
||||
txt = create_text_elem('F')
|
||||
link.setAttribute('class', 'error')
|
||||
link.appendChild(txt)
|
||||
td.appendChild(link)
|
||||
exported_methods.show_fail(item_name, fail_come_back)
|
||||
|
||||
if counters[msg['fullmodulename']] == 0:
|
||||
tr = create_elem("tr")
|
||||
module_part.appendChild(tr)
|
||||
|
||||
name = msg['fullmodulename']
|
||||
counters[name] += 1
|
||||
counter_part = get_elem('_txt_' + name)
|
||||
newcontent = "%s[%d/%d]" % (short_item_names[name], counters[name],
|
||||
max_items[name])
|
||||
counter_part.childNodes[0].nodeValue = newcontent
|
||||
module_part.childNodes[-1].appendChild(td)
|
||||
|
||||
def process(msg):
|
||||
if len(msg) == 0:
|
||||
return False
|
||||
elem = dom.document.getElementById("testmain")
|
||||
#elem.innerHTML += '%s<br/>' % msg['event']
|
||||
main_t = dom.document.getElementById("main_table")
|
||||
if msg['type'] == 'ItemStart':
|
||||
# we start a new directory or what
|
||||
#if msg['itemtype'] == 'Module':
|
||||
tr = make_module_box(msg)
|
||||
main_t.appendChild(tr)
|
||||
elif msg['type'] == 'SendItem':
|
||||
host_elem = dom.document.getElementById(msg['hostkey'])
|
||||
glob.host_pending[msg['hostkey']].insert(0, msg['fullitemname'])
|
||||
count = len(glob.host_pending[msg['hostkey']])
|
||||
host_elem.childNodes[0].nodeValue = '%s[%s]' % (
|
||||
glob.host_dict[msg['hostkey']], count)
|
||||
|
||||
elif msg['type'] == 'HostRSyncRootReady':
|
||||
host_elem = dom.document.getElementById(msg['hostkey'])
|
||||
host_elem.style.background = \
|
||||
"#00ff00"
|
||||
host_elem.childNodes[0].nodeValue = '%s[0]' % (
|
||||
glob.host_dict[msg['hostkey']],)
|
||||
elif msg['type'] == 'ItemFinish':
|
||||
module_part = get_elem(msg['fullmodulename'])
|
||||
if not module_part:
|
||||
glob.pending.append(msg)
|
||||
return True
|
||||
|
||||
add_received_item_outcome(msg, module_part)
|
||||
elif msg['type'] == 'TestTestrunFinish':
|
||||
text = "FINISHED %s run, %s failures, %s skipped" % (msg['run'], msg['fails'], msg['skips'])
|
||||
glob.finished = True
|
||||
dom.document.title = "Py.test %s" % text
|
||||
dom.document.getElementById("Tests").childNodes[0].nodeValue = \
|
||||
"Tests [%s]" % text
|
||||
elif msg['type'] == 'FailedTryiter':
|
||||
module_part = get_elem(msg['fullitemname'])
|
||||
if not module_part:
|
||||
glob.pending.append(msg)
|
||||
return True
|
||||
tr = create_elem("tr")
|
||||
td = create_elem("td")
|
||||
a = create_elem("a")
|
||||
a.setAttribute("href", "javascript:show_traceback('%s')" % (
|
||||
msg['fullitemname'],))
|
||||
txt = create_text_elem("- FAILED TO LOAD MODULE")
|
||||
a.appendChild(txt)
|
||||
td.appendChild(a)
|
||||
tr.appendChild(td)
|
||||
module_part.appendChild(tr)
|
||||
item_name = msg['fullitemname']
|
||||
exported_methods.show_fail(item_name, fail_come_back)
|
||||
elif msg['type'] == 'DeselectedItem':
|
||||
module_part = get_elem(msg['fullitemname'])
|
||||
if not module_part:
|
||||
glob.pending.append(msg)
|
||||
return True
|
||||
tr = create_elem("tr")
|
||||
td = create_elem("td")
|
||||
txt = create_text_elem("- skipped (%s)" % (msg['reason'],))
|
||||
td.appendChild(txt)
|
||||
tr.appendChild(td)
|
||||
module_part.appendChild(tr)
|
||||
elif msg['type'] == 'RsyncFinished':
|
||||
glob.rsync_done = True
|
||||
elif msg['type'] == 'InterruptedExecution':
|
||||
show_interrupt()
|
||||
elif msg['type'] == 'CrashedExecution':
|
||||
show_crash()
|
||||
if glob.data_empty:
|
||||
mbox = dom.document.getElementById('messagebox')
|
||||
scroll_down_if_needed(mbox)
|
||||
return True
|
||||
|
||||
def show_skip(item_name="aa"):
|
||||
set_msgbox(item_name, skips[item_name])
|
||||
|
||||
def set_msgbox(item_name, data):
|
||||
msgbox = get_elem("messagebox")
|
||||
while len(msgbox.childNodes):
|
||||
msgbox.removeChild(msgbox.childNodes[0])
|
||||
pre = create_elem("pre")
|
||||
txt = create_text_elem(item_name + "\n" + data)
|
||||
pre.appendChild(txt)
|
||||
msgbox.appendChild(pre)
|
||||
dom.window.location.assign("#message")
|
||||
glob.data_empty = False
|
||||
|
||||
def show_traceback(item_name="aa"):
|
||||
data = ("====== Traceback: =========\n%s\n======== Stdout: ========\n%s\n"
|
||||
"========== Stderr: ==========\n%s\n" % tracebacks[item_name])
|
||||
set_msgbox(item_name, data)
|
||||
|
||||
def fail_come_back(msg):
|
||||
tracebacks[msg['item_name']] = (msg['traceback'], msg['stdout'],
|
||||
msg['stderr'])
|
||||
|
||||
def skip_come_back(msg):
|
||||
skips[msg['item_name']] = msg['reason']
|
||||
|
||||
def reshow_host():
|
||||
if glob.host == "":
|
||||
return
|
||||
show_host(glob.host)
|
||||
|
||||
def show_host(host_name="aa"):
|
||||
elem = dom.document.getElementById("jobs")
|
||||
if elem.childNodes:
|
||||
elem.removeChild(elem.childNodes[0])
|
||||
tbody = create_elem("tbody")
|
||||
for item in glob.host_pending[host_name]:
|
||||
tr = create_elem("tr")
|
||||
td = create_elem("td")
|
||||
td.appendChild(create_text_elem(item))
|
||||
tr.appendChild(td)
|
||||
tbody.appendChild(tr)
|
||||
elem.appendChild(tbody)
|
||||
elem.style.visibility = "visible"
|
||||
glob.host = host_name
|
||||
dom.setTimeout(reshow_host, 100)
|
||||
|
||||
def hide_host():
|
||||
elem = dom.document.getElementById("jobs")
|
||||
while len(elem.childNodes):
|
||||
elem.removeChild(elem.childNodes[0])
|
||||
elem.style.visibility = "hidden"
|
||||
glob.host = ""
|
||||
|
||||
def update_rsync():
|
||||
if glob.finished:
|
||||
return
|
||||
elem = dom.document.getElementById("Tests")
|
||||
if glob.rsync_done is True:
|
||||
elem.childNodes[0].nodeValue = "Tests"
|
||||
return
|
||||
text = "Rsyncing" + '.' * glob.rsync_dots
|
||||
glob.rsync_dots += 1
|
||||
if glob.rsync_dots > 5:
|
||||
glob.rsync_dots = 0
|
||||
elem.childNodes[0].nodeValue = "Tests [%s]" % text
|
||||
dom.setTimeout(update_rsync, 1000)
|
||||
|
||||
def host_init(host_dict):
|
||||
tbody = dom.document.getElementById("hostsbody")
|
||||
for host in host_dict.keys():
|
||||
tr = create_elem('tr')
|
||||
tbody.appendChild(tr)
|
||||
td = create_elem("td")
|
||||
td.style.background = "#ff0000"
|
||||
txt = create_text_elem(host_dict[host])
|
||||
td.appendChild(txt)
|
||||
td.id = host
|
||||
tr.appendChild(td)
|
||||
td.setAttribute("onmouseover", "show_host('%s')" % host)
|
||||
td.setAttribute("onmouseout", "hide_host()")
|
||||
glob.rsync_dots = 0
|
||||
glob.rsync_done = False
|
||||
dom.setTimeout(update_rsync, 1000)
|
||||
glob.host_dict = host_dict
|
||||
glob.host_pending = {}
|
||||
for key in host_dict.keys():
|
||||
glob.host_pending[key] = []
|
||||
|
||||
def key_pressed(key):
|
||||
if key.charCode == ord('s'):
|
||||
scroll_box = dom.document.getElementById("opt_scroll")
|
||||
if opts.scroll:
|
||||
scroll_box.removeAttribute("checked")
|
||||
opts.scroll = False
|
||||
else:
|
||||
scroll_box.setAttribute("checked", "true")
|
||||
opts.scroll = True
|
||||
|
||||
def sessid_comeback(id):
|
||||
glob.sessid = id
|
||||
exported_methods.show_all_statuses(id, comeback)
|
||||
|
||||
def main():
|
||||
glob.finished = False
|
||||
exported_methods.show_hosts(host_init)
|
||||
exported_methods.show_sessid(sessid_comeback)
|
||||
dom.document.onkeypress = key_pressed
|
||||
dom.document.getElementById("opt_scroll").setAttribute("checked", "True")
|
Loading…
Reference in New Issue