From 4758a0ac129c95a0f4ccecd3663bf874bcb5b5d8 Mon Sep 17 00:00:00 2001 From: Stein Magnus Jodal Date: Sun, 29 Dec 2013 15:04:47 +0100 Subject: [PATCH] tools: Remove unused dev tools --- docs/devtools.rst | 42 --------- tools/debug-proxy.py | 195 ----------------------------------------- tools/idle.py | 203 ------------------------------------------- 3 files changed, 440 deletions(-) delete mode 100755 tools/debug-proxy.py delete mode 100644 tools/idle.py diff --git a/docs/devtools.rst b/docs/devtools.rst index 858cc7f8..64bb7e6b 100644 --- a/docs/devtools.rst +++ b/docs/devtools.rst @@ -27,48 +27,6 @@ code. So, if you're out of work, the code coverage and flake8 data at the CI server should give you a place to start. -Protocol debugger -================= - -Since the main interface provided to Mopidy is through the MPD protocol, it is -crucial that we try and stay in sync with protocol developments. In an attempt -to make it easier to debug differences Mopidy and MPD protocol handling we have -created ``tools/debug-proxy.py``. - -This tool is proxy that sits in front of two MPD protocol aware servers and -sends all requests to both, returning the primary response to the client and -then printing any diff in the two responses. - -Note that this tool depends on ``gevent`` unlike the rest of Mopidy at the time -of writing. See :option:`tools/debug-proxy.py --help` for available options. -Sample session:: - - [127.0.0.1]:59714 - listallinfo - --- Reference response - +++ Actual response - @@ -1,16 +1,1 @@ - -file: uri1 - -Time: 4 - -Artist: artist1 - -Title: track1 - -Album: album1 - -file: uri2 - -Time: 4 - -Artist: artist2 - -Title: track2 - -Album: album2 - -file: uri3 - -Time: 4 - -Artist: artist3 - -Title: track3 - -Album: album3 - -OK - +ACK [2@0] {listallinfo} incorrect arguments - -To ensure that Mopidy and MPD have comparable state it is suggested you scan -the same media directory with both servers. - Documentation writing ===================== diff --git a/tools/debug-proxy.py b/tools/debug-proxy.py deleted file mode 100755 index 938afa57..00000000 --- a/tools/debug-proxy.py +++ /dev/null @@ -1,195 +0,0 @@ -#! /usr/bin/env python - -from __future__ import unicode_literals - -import argparse -import difflib -import sys - -from gevent import select, server, socket - -COLORS = ['\033[1;%dm' % (30 + i) for i in range(8)] -BLACK, RED, GREEN, YELLOW, BLUE, MAGENTA, CYAN, WHITE = COLORS -RESET = "\033[0m" -BOLD = "\033[1m" - - -def proxy(client, address, reference_address, actual_address): - """Main handler code that gets called for each connection.""" - client.setblocking(False) - - reference = connect(reference_address) - actual = connect(actual_address) - - if reference and actual: - loop(client, address, reference, actual) - else: - print 'Could not connect to one of the backends.' - - for sock in (client, reference, actual): - close(sock) - - -def connect(address): - """Connect to given address and set socket non blocking.""" - try: - sock = socket.socket() - sock.connect(address) - sock.setblocking(False) - except socket.error: - return None - return sock - - -def close(sock): - """Shutdown and close our sockets.""" - try: - sock.shutdown(socket.SHUT_WR) - sock.close() - except socket.error: - pass - - -def loop(client, address, reference, actual): - """Loop that handles one MPD reqeust/response pair per iteration.""" - - # Consume banners from backends - responses = dict() - disconnected = read( - [reference, actual], responses, find_response_end_token) - diff(address, '', responses[reference], responses[actual]) - - # We lost a backend, might as well give up. - if disconnected: - return - - client.sendall(responses[reference]) - - while True: - responses = dict() - - # Get the command from the client. Not sure how an if this will handle - # client sending multiple commands currently :/ - disconnected = read([client], responses, find_request_end_token) - - # We lost the client, might as well give up. - if disconnected: - return - - # Send the entire command to both backends. - reference.sendall(responses[client]) - actual.sendall(responses[client]) - - # Get the entire resonse from both backends. - disconnected = read( - [reference, actual], responses, find_response_end_token) - - # Send the client the complete reference response - client.sendall(responses[reference]) - - # Compare our responses - diff(address, - responses[client], responses[reference], responses[actual]) - - # Give up if we lost a backend. - if disconnected: - return - - -def read(sockets, responses, find_end_token): - """Keep reading from sockets until they disconnet or we find our token.""" - - # This function doesn't go to well with idle when backends are out of sync. - disconnected = False - - for sock in sockets: - responses.setdefault(sock, '') - - while sockets: - for sock in select.select(sockets, [], [])[0]: - data = sock.recv(4096) - responses[sock] += data - - if find_end_token(responses[sock]): - sockets.remove(sock) - - if not data: - sockets.remove(sock) - disconnected = True - - return disconnected - - -def find_response_end_token(data): - """Find token that indicates the response is over.""" - for line in data.splitlines(True): - if line.startswith(('OK', 'ACK')) and line.endswith('\n'): - return True - return False - - -def find_request_end_token(data): - """Find token that indicates that request is over.""" - lines = data.splitlines(True) - if not lines: - return False - elif 'command_list_ok_begin' == lines[0].strip(): - return 'command_list_end' == lines[-1].strip() - else: - return lines[0].endswith('\n') - - -def diff(address, command, reference_response, actual_response): - """Print command from client and a unified diff of the responses.""" - sys.stdout.write('[%s]:%s\n%s' % (address[0], address[1], command)) - for line in difflib.unified_diff(reference_response.splitlines(True), - actual_response.splitlines(True), - fromfile='Reference response', - tofile='Actual response'): - - if line.startswith('+') and not line.startswith('+++'): - sys.stdout.write(GREEN) - elif line.startswith('-') and not line.startswith('---'): - sys.stdout.write(RED) - elif line.startswith('@@'): - sys.stdout.write(CYAN) - - sys.stdout.write(line) - sys.stdout.write(RESET) - - sys.stdout.flush() - - -def parse_args(): - """Handle flag parsing.""" - parser = argparse.ArgumentParser( - description='Proxy and compare MPD protocol interactions.') - parser.add_argument('--listen', default=':6600', type=parse_address, - help='address:port to listen on.') - parser.add_argument('--reference', default=':6601', type=parse_address, - help='address:port for the reference backend.') - parser.add_argument('--actual', default=':6602', type=parse_address, - help='address:port for the actual backend.') - - return parser.parse_args() - - -def parse_address(address): - """Convert host:port or port to address to pass to connect.""" - if ':' not in address: - return ('', int(address)) - host, port = address.rsplit(':', 1) - return (host, int(port)) - - -if __name__ == '__main__': - args = parse_args() - - def handle(client, address): - """Wrapper that adds reference and actual backends to proxy calls.""" - return proxy(client, address, args.reference, args.actual) - - try: - server.StreamServer(args.listen, handle).serve_forever() - except (KeyboardInterrupt, SystemExit): - pass diff --git a/tools/idle.py b/tools/idle.py deleted file mode 100644 index 122e998d..00000000 --- a/tools/idle.py +++ /dev/null @@ -1,203 +0,0 @@ -#! /usr/bin/env python - -# This script is helper to systematicly test the behaviour of MPD's idle -# command. It is simply provided as a quick hack, expect nothing more. - -from __future__ import unicode_literals - -import logging -import pprint -import socket - -host = '' -port = 6601 - -url = "13 - a-ha - White Canvas.mp3" -artist = "a-ha" - -data = {'id': None, 'id2': None, 'url': url, 'artist': artist} - -# Commands to run before test requests to coerce MPD into right state -setup_requests = [ - 'clear', - 'add "%(url)s"', - 'add "%(url)s"', - 'add "%(url)s"', - 'play', - #'pause', # Uncomment to test paused idle behaviour - #'stop', # Uncomment to test stopped idle behaviour -] - -# List of commands to test for idle behaviour. Ordering of list is important in -# order to keep MPD state as intended. Commands that are obviously -# informational only or "harmfull" have been excluded. -test_requests = [ - 'add "%(url)s"', - 'addid "%(url)s" "1"', - 'clear', - #'clearerror', - #'close', - #'commands', - 'consume "1"', - 'consume "0"', - # 'count', - 'crossfade "1"', - 'crossfade "0"', - #'currentsong', - #'delete "1:2"', - 'delete "0"', - 'deleteid "%(id)s"', - 'disableoutput "0"', - 'enableoutput "0"', - #'find', - #'findadd "artist" "%(artist)s"', - #'idle', - #'kill', - #'list', - #'listall', - #'listallinfo', - #'listplaylist', - #'listplaylistinfo', - #'listplaylists', - #'lsinfo', - 'move "0:1" "2"', - 'move "0" "1"', - 'moveid "%(id)s" "1"', - 'next', - #'notcommands', - #'outputs', - #'password', - 'pause', - #'ping', - 'play', - 'playid "%(id)s"', - #'playlist', - 'playlistadd "foo" "%(url)s"', - 'playlistclear "foo"', - 'playlistadd "foo" "%(url)s"', - 'playlistdelete "foo" "0"', - #'playlistfind', - #'playlistid', - #'playlistinfo', - 'playlistadd "foo" "%(url)s"', - 'playlistadd "foo" "%(url)s"', - 'playlistmove "foo" "0" "1"', - #'playlistsearch', - #'plchanges', - #'plchangesposid', - 'previous', - 'random "1"', - 'random "0"', - 'rm "bar"', - 'rename "foo" "bar"', - 'repeat "0"', - 'rm "bar"', - 'save "bar"', - 'load "bar"', - #'search', - 'seek "1" "10"', - 'seekid "%(id)s" "10"', - #'setvol "10"', - 'shuffle', - 'shuffle "0:1"', - 'single "1"', - 'single "0"', - #'stats', - #'status', - 'stop', - 'swap "1" "2"', - 'swapid "%(id)s" "%(id2)s"', - #'tagtypes', - #'update', - #'urlhandlers', - #'volume', -] - - -def create_socketfile(): - sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - sock.connect((host, port)) - sock.settimeout(0.5) - fd = sock.makefile('rw', 1) # 1 = line buffered - fd.readline() # Read banner - return fd - - -def wait(fd, prefix=None, collect=None): - while True: - line = fd.readline().rstrip() - if prefix: - logging.debug('%s: %s', prefix, repr(line)) - if line.split()[0] in ('OK', 'ACK'): - break - - -def collect_ids(fd): - fd.write('playlistinfo\n') - - ids = [] - while True: - line = fd.readline() - if line.split()[0] == 'OK': - break - if line.split()[0] == 'Id:': - ids.append(line.split()[1]) - return ids - - -def main(): - subsystems = {} - - command = create_socketfile() - - for test in test_requests: - # Remove any old ids - del data['id'] - del data['id2'] - - # Run setup code to force MPD into known state - for setup in setup_requests: - command.write(setup % data + '\n') - wait(command) - - data['id'], data['id2'] = collect_ids(command)[:2] - - # This connection needs to be make after setup commands are done or - # else they will cause idle events. - idle = create_socketfile() - - # Wait for new idle events - idle.write('idle\n') - - test = test % data - - logging.debug('idle: %s', repr('idle')) - logging.debug('command: %s', repr(test)) - - command.write(test + '\n') - wait(command, prefix='command') - - while True: - try: - line = idle.readline().rstrip() - except socket.timeout: - # Abort try if we time out. - idle.write('noidle\n') - break - - logging.debug('idle: %s', repr(line)) - - if line == 'OK': - break - - request_type = test.split()[0] - subsystem = line.split()[1] - subsystems.setdefault(request_type, set()).add(subsystem) - - logging.debug('---') - - pprint.pprint(subsystems) - - -if __name__ == '__main__': - main()