1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/testing/mozbase/mozdevice/tests/sut.py Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,90 @@ 1.4 +#!/usr/bin/env python 1.5 + 1.6 +# Any copyright is dedicated to the Public Domain. 1.7 +# http://creativecommons.org/publicdomain/zero/1.0/ 1.8 + 1.9 +import datetime 1.10 +import socket 1.11 +import time 1.12 + 1.13 +from threading import Thread 1.14 + 1.15 +class MockAgent(object): 1.16 + 1.17 + MAX_WAIT_TIME_SECONDS = 10 1.18 + SOCKET_TIMEOUT_SECONDS = 5 1.19 + 1.20 + def __init__(self, tester, start_commands = None, commands = []): 1.21 + if start_commands: 1.22 + self.commands = start_commands 1.23 + else: 1.24 + self.commands = [("testroot", "/mnt/sdcard"), 1.25 + ("isdir /mnt/sdcard/tests", "TRUE"), 1.26 + ("ver", "SUTAgentAndroid Version 1.14")] 1.27 + self.commands = self.commands + commands 1.28 + 1.29 + self._sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 1.30 + self._sock.bind(("127.0.0.1", 0)) 1.31 + self._sock.listen(1) 1.32 + 1.33 + self.tester = tester 1.34 + 1.35 + self.thread = Thread(target=self._serve_thread) 1.36 + self.thread.start() 1.37 + 1.38 + self.should_stop = False 1.39 + 1.40 + @property 1.41 + def port(self): 1.42 + return self._sock.getsockname()[1] 1.43 + 1.44 + def _serve_thread(self): 1.45 + conn = None 1.46 + while self.commands: 1.47 + if not conn: 1.48 + conn, addr = self._sock.accept() 1.49 + conn.settimeout(self.SOCKET_TIMEOUT_SECONDS) 1.50 + conn.send("$>\x00") 1.51 + (command, response) = self.commands.pop(0) 1.52 + data = '' 1.53 + timeout = datetime.datetime.now() + datetime.timedelta( 1.54 + seconds=self.MAX_WAIT_TIME_SECONDS) 1.55 + # The data might come in chunks, particularly if we are expecting 1.56 + # multiple lines, as with push commands. 1.57 + while (len(data) < len(command) and 1.58 + datetime.datetime.now() < timeout): 1.59 + try: 1.60 + data += conn.recv(1024) 1.61 + except socket.timeout: 1.62 + # We handle timeouts in the main loop. 1.63 + pass 1.64 + self.tester.assertEqual(data.strip(), command) 1.65 + # send response and prompt separately to test for bug 789496 1.66 + # FIXME: Improve the mock agent, since overloading the meaning 1.67 + # of 'response' is getting confusing. 1.68 + if response is None: # code for "shut down" 1.69 + conn.shutdown(socket.SHUT_RDWR) 1.70 + conn.close() 1.71 + conn = None 1.72 + elif type(response) is int: # code for "time out" 1.73 + max_timeout = 15.0 1.74 + timeout = 0.0 1.75 + interval = 0.1 1.76 + while not self.should_stop and timeout < max_timeout: 1.77 + time.sleep(interval) 1.78 + timeout += interval 1.79 + if timeout >= max_timeout: 1.80 + raise Exception("Maximum timeout reached! This should not " 1.81 + "happen") 1.82 + return 1.83 + else: 1.84 + # pull is handled specially, as we just pass back the full 1.85 + # command line 1.86 + if "pull" in command: 1.87 + conn.send(response) 1.88 + else: 1.89 + conn.send("%s\n" % response) 1.90 + conn.send("$>\x00") 1.91 + 1.92 + def wait(self): 1.93 + self.thread.join()