237 lines
7.1 KiB
Python
Executable File
237 lines
7.1 KiB
Python
Executable File
#!/usr/bin/env python
|
|
|
|
from __future__ import print_function
|
|
|
|
# this is mostly for testing that the examples run without errors
|
|
#
|
|
# To use this script:
|
|
#
|
|
# 0. change to this directory
|
|
# 1. be in an activated Python2 virtual-env with crossbar installed
|
|
# 2. pip install colorama
|
|
# 3. have a virtualenv called ./venv-py3 using a Python3
|
|
# interpreter with crossbar (or just Autobahn) installed.
|
|
#
|
|
# ...then just run this script; it colors the output and runs each
|
|
# frontend/backend pair for a few seconds.
|
|
|
|
import sys
|
|
from os import environ
|
|
from os.path import join, exists
|
|
|
|
import colorama
|
|
from colorama import Fore
|
|
|
|
from twisted.internet.protocol import ProcessProtocol
|
|
from twisted.internet.defer import inlineCallbacks, Deferred, returnValue
|
|
from twisted.internet.error import ProcessExitedAlready
|
|
from twisted.internet import reactor
|
|
from twisted.internet.task import react
|
|
|
|
from autobahn.twisted.util import sleep
|
|
|
|
|
|
class CrossbarProcessProtocol(ProcessProtocol):
|
|
"""
|
|
A helper to talk to a crossbar instance we've launched.
|
|
"""
|
|
|
|
def __init__(self, all_done, launched, color=None, prefix=''):
|
|
"""
|
|
:param all_done: Deferred that gets callback() when our process exits (.errback if it exits non-zero)
|
|
:param launched: Deferred that gets callback() when our process starts.
|
|
"""
|
|
self.all_done = all_done
|
|
self.launched = launched
|
|
self.color = color or ''
|
|
self.prefix = prefix
|
|
self._out = ''
|
|
self._err = ''
|
|
|
|
def connectionMade(self):
|
|
"""ProcessProtocol override"""
|
|
if not self.launched.called:
|
|
self.launched.callback(self)
|
|
|
|
def outReceived(self, data):
|
|
"""ProcessProtocol override"""
|
|
self._out += data.decode('utf8')
|
|
while '\n' in self._out:
|
|
idx = self._out.find('\n')
|
|
line = self._out[:idx]
|
|
self._out = self._out[idx + 1:]
|
|
sys.stdout.write(self.prefix + self.color + line + Fore.RESET + '\n')
|
|
|
|
def errReceived(self, data):
|
|
"""ProcessProtocol override"""
|
|
self._err += data.decode('utf8')
|
|
while '\n' in self._err:
|
|
idx = self._err.find('\n')
|
|
line = self._err[:idx]
|
|
self._err = self._err[idx + 1:]
|
|
sys.stderr.write(self.prefix + self.color + line + Fore.RESET + '\n')
|
|
|
|
def processEnded(self, reason):
|
|
"""IProcessProtocol API"""
|
|
# reason.value should always be a ProcessTerminated instance
|
|
fail = reason.value
|
|
# print('processEnded', fail)
|
|
|
|
if fail.exitCode != 0 and fail.exitCode is not None:
|
|
msg = 'Process exited with code "{}".'.format(fail.exitCode)
|
|
err = RuntimeError(msg)
|
|
self.all_done.errback(err)
|
|
if not self.launched.called:
|
|
self.launched.errback(err)
|
|
else:
|
|
self.all_done.callback(fail)
|
|
if not self.launched.called:
|
|
print("FIXME: _launched should have been callbacked by now.")
|
|
self.launched.callback(self)
|
|
|
|
|
|
@inlineCallbacks
|
|
def start_crossbar():
|
|
finished = Deferred()
|
|
launched = Deferred()
|
|
protocol = CrossbarProcessProtocol(finished, launched, Fore.RED)
|
|
exe = 'crossbar'
|
|
args = [exe, 'start', '--cbdir', './router/.crossbar']
|
|
|
|
env = environ.copy()
|
|
env["PYTHONUNBUFFERED"] = "1"
|
|
|
|
reactor.spawnProcess(protocol, exe, args, path='.', env=env)
|
|
|
|
yield launched
|
|
returnValue(protocol)
|
|
|
|
|
|
@inlineCallbacks
|
|
def start_example(py_fname, color, prefix='', exe=sys.executable):
|
|
finished = Deferred()
|
|
launched = Deferred()
|
|
protocol = CrossbarProcessProtocol(finished, launched, color, prefix)
|
|
args = [exe, py_fname]
|
|
|
|
env = environ.copy()
|
|
env["PYTHONUNBUFFERED"] = "1"
|
|
|
|
reactor.spawnProcess(protocol, exe, args, path='.', env=env)
|
|
|
|
yield launched
|
|
returnValue(protocol)
|
|
|
|
|
|
def print_banner(title):
|
|
print('-' * 80)
|
|
print(title)
|
|
print('-' * 80)
|
|
print()
|
|
|
|
|
|
@inlineCallbacks
|
|
def main(reactor):
|
|
colorama.init()
|
|
examples = [
|
|
'./twisted/wamp/overview',
|
|
|
|
'./twisted/wamp/pubsub/basic/',
|
|
'./twisted/wamp/pubsub/complex/',
|
|
'./twisted/wamp/pubsub/decorators/',
|
|
'./twisted/wamp/pubsub/options/',
|
|
'./twisted/wamp/pubsub/tls/',
|
|
'./twisted/wamp/pubsub/unsubscribe/',
|
|
|
|
'./twisted/wamp/rpc/timeservice/',
|
|
'./twisted/wamp/rpc/slowsquare/',
|
|
'./twisted/wamp/rpc/progress/',
|
|
'./twisted/wamp/rpc/options/',
|
|
'./twisted/wamp/rpc/errors/',
|
|
'./twisted/wamp/rpc/decorators/',
|
|
'./twisted/wamp/rpc/complex/',
|
|
'./twisted/wamp/rpc/arguments/',
|
|
|
|
'py3 ./asyncio/wamp/overview',
|
|
|
|
'py3 ./asyncio/wamp/pubsub/unsubscribe/',
|
|
'py3 ./asyncio/wamp/pubsub/tls/',
|
|
'py3 ./asyncio/wamp/pubsub/options/',
|
|
'py3 ./asyncio/wamp/pubsub/decorators/',
|
|
'py3 ./asyncio/wamp/pubsub/complex/',
|
|
'py3 ./asyncio/wamp/pubsub/basic/',
|
|
|
|
'py3 ./asyncio/wamp/rpc/timeservice/',
|
|
'py3 ./asyncio/wamp/rpc/slowsquare/',
|
|
'py3 ./asyncio/wamp/rpc/progress/',
|
|
'py3 ./asyncio/wamp/rpc/options/',
|
|
'py3 ./asyncio/wamp/rpc/errors/',
|
|
'py3 ./asyncio/wamp/rpc/decorators/',
|
|
'py3 ./asyncio/wamp/rpc/complex/',
|
|
'py3 ./asyncio/wamp/rpc/arguments/',
|
|
|
|
]
|
|
|
|
print_banner("Running crossbar.io instance")
|
|
cb_proto = yield start_crossbar()
|
|
yield sleep(2) # wait for sockets to be listening
|
|
if cb_proto.all_done.called:
|
|
raise RuntimeError("crossbar exited already")
|
|
|
|
success = True
|
|
for exdir in examples:
|
|
py = sys.executable
|
|
if exdir.startswith('py3 '):
|
|
exdir = exdir[4:]
|
|
if sys.version_info.major < 3:
|
|
print("don't have python3, skipping:", exdir)
|
|
continue
|
|
frontend = join(exdir, 'frontend.py')
|
|
backend = join(exdir, 'backend.py')
|
|
if not exists(frontend) or not exists(backend):
|
|
print("skipping:", exdir, exists(frontend), exists(backend))
|
|
continue
|
|
|
|
print_banner("Running example: " + exdir)
|
|
print(" starting backend")
|
|
back_proto = yield start_example(backend, Fore.BLUE, ' backend: ', exe=py)
|
|
yield sleep(1)
|
|
print(" starting frontend")
|
|
front_proto = yield start_example(frontend, Fore.YELLOW, 'frontend: ', exe=py)
|
|
yield sleep(3)
|
|
|
|
for p in [back_proto, front_proto]:
|
|
try:
|
|
if p.all_done.called:
|
|
yield p.all_done
|
|
except Exception as e:
|
|
print("FAILED:", e)
|
|
success = False
|
|
|
|
for p in [front_proto, back_proto]:
|
|
try:
|
|
p.transport.signalProcess('KILL')
|
|
except ProcessExitedAlready:
|
|
pass
|
|
|
|
if not success:
|
|
break
|
|
yield sleep(1)
|
|
|
|
print("Killing crossbar")
|
|
try:
|
|
cb_proto.transport.signalProcess('KILL')
|
|
yield cb_proto.all_done
|
|
except:
|
|
pass
|
|
if success:
|
|
print()
|
|
print("Success!")
|
|
print(" ...all the examples neither crashed nor burned...")
|
|
returnValue(0)
|
|
returnValue(5)
|
|
|
|
|
|
if __name__ == '__main__':
|
|
sys.exit(react(main))
|