diff --git a/testing/mozbase/mozdevice/mozdevice/devicemanager.py b/testing/mozbase/mozdevice/mozdevice/devicemanager.py index 4aad2c3fb70b..b6be6476669d 100644 --- a/testing/mozbase/mozdevice/mozdevice/devicemanager.py +++ b/testing/mozbase/mozdevice/mozdevice/devicemanager.py @@ -180,9 +180,13 @@ class DeviceManager(object): """ @abstractmethod - def pullFile(self, remoteFilename): + def pullFile(self, remoteFilename, offset=None, length=None): """ Returns contents of remoteFile using the "pull" command. + + :param remoteFilename: Path to file to pull from remote device. + :param offset: Offset in bytes from which to begin reading (optional) + :param length: Number of bytes to read (optional) """ @abstractmethod diff --git a/testing/mozbase/mozdevice/mozdevice/devicemanagerADB.py b/testing/mozbase/mozdevice/mozdevice/devicemanagerADB.py index b4f96e2c238d..afcf8ad8d45d 100644 --- a/testing/mozbase/mozdevice/mozdevice/devicemanagerADB.py +++ b/testing/mozbase/mozdevice/mozdevice/devicemanagerADB.py @@ -386,13 +386,24 @@ class DeviceManagerADB(DeviceManager): except (OSError, ValueError): raise DMError("Error pulling remote file '%s' to '%s'" % (remoteFile, localFile)) - def pullFile(self, remoteFile): + def pullFile(self, remoteFile, offset=None, length=None): # TODO: add debug flags and allow for printing stdout localFile = tempfile.mkstemp()[1] self._runPull(remoteFile, localFile) f = open(localFile, 'r') - ret = f.read() + + # ADB pull does not support offset and length, but we can instead + # read only the requested portion of the local file + if offset is not None and length is not None: + f.seek(offset) + ret = f.read(length) + elif offset is not None: + f.seek(offset) + ret = f.read() + else: + ret = f.read() + f.close() os.remove(localFile) return ret diff --git a/testing/mozbase/mozdevice/mozdevice/devicemanagerSUT.py b/testing/mozbase/mozdevice/mozdevice/devicemanagerSUT.py index 653a1fe4ad81..acf4c8262c63 100644 --- a/testing/mozbase/mozdevice/mozdevice/devicemanagerSUT.py +++ b/testing/mozbase/mozdevice/mozdevice/devicemanagerSUT.py @@ -542,7 +542,7 @@ class DeviceManagerSUT(DeviceManager): def getTempDir(self): return self._runCmds([{ 'cmd': 'tmpd' }]).strip() - def pullFile(self, remoteFile): + def pullFile(self, remoteFile, offset=None, length=None): # The "pull" command is different from other commands in that DeviceManager # has to read a certain number of bytes instead of just reading to the # next prompt. This is more robust than the "cat" command, which will be @@ -604,7 +604,14 @@ class DeviceManagerSUT(DeviceManager): # ,-1\n # just send the command first, we read the response inline below - self._runCmds([{ 'cmd': 'pull ' + remoteFile }]) + if offset is not None and length is not None: + cmd = 'pull %s %d %d' % (remoteFile, offset, length) + elif offset is not None: + cmd = 'pull %s %d' % (remoteFile, offset) + else: + cmd = 'pull %s' % remoteFile + + self._runCmds([{ 'cmd': cmd }]) # read metadata; buffer the rest metadata, sep, buf = read_until_char('\n', buf, 'could not find metadata') diff --git a/testing/mozbase/mozdevice/setup.py b/testing/mozbase/mozdevice/setup.py index 70f16060cbb2..4b7ada51e81f 100644 --- a/testing/mozbase/mozdevice/setup.py +++ b/testing/mozbase/mozdevice/setup.py @@ -4,7 +4,7 @@ from setuptools import setup -PACKAGE_VERSION = '0.26' +PACKAGE_VERSION = '0.27' setup(name='mozdevice', version=PACKAGE_VERSION, diff --git a/testing/mozbase/mozdevice/tests/sut.py b/testing/mozbase/mozdevice/tests/sut.py index 473d5172816e..af69db8beff1 100644 --- a/testing/mozbase/mozdevice/tests/sut.py +++ b/testing/mozbase/mozdevice/tests/sut.py @@ -3,11 +3,17 @@ # Any copyright is dedicated to the Public Domain. # http://creativecommons.org/publicdomain/zero/1.0/ +import datetime import socket -from threading import Thread import time +from threading import Thread + class MockAgent(object): + + MAX_WAIT_TIME_SECONDS = 10 + SOCKET_TIMEOUT_SECONDS = 5 + def __init__(self, tester, start_commands = None, commands = []): if start_commands: self.commands = start_commands @@ -37,10 +43,22 @@ class MockAgent(object): while self.commands: if not conn: conn, addr = self._sock.accept() + conn.settimeout(self.SOCKET_TIMEOUT_SECONDS) conn.send("$>\x00") (command, response) = self.commands.pop(0) - data = conn.recv(1024).strip() - self.tester.assertEqual(data, command) + data = '' + timeout = datetime.datetime.now() + datetime.timedelta( + seconds=self.MAX_WAIT_TIME_SECONDS) + # The data might come in chunks, particularly if we are expecting + # multiple lines, as with push commands. + while (len(data) < len(command) and + datetime.datetime.now() < timeout): + try: + data += conn.recv(1024) + except socket.timeout: + # We handle timeouts in the main loop. + pass + self.tester.assertEqual(data.strip(), command) # send response and prompt separately to test for bug 789496 # FIXME: Improve the mock agent, since overloading the meaning # of 'response' is getting confusing. diff --git a/testing/mozbase/mozdevice/tests/sut_push.py b/testing/mozbase/mozdevice/tests/sut_push.py index 37d51f7daf74..8f2e7b7269c5 100644 --- a/testing/mozbase/mozdevice/tests/sut_push.py +++ b/testing/mozbase/mozdevice/tests/sut_push.py @@ -16,7 +16,7 @@ class PushTest(unittest.TestCase): # (good response, no exception), (bad response, exception) for response in [ (expectedResponse, False), ("BADHASH", True) ]: - cmd = "push /mnt/sdcard/foobar %s" % len(pushfile) + cmd = "push /mnt/sdcard/foobar %s\r\n%s" % (len(pushfile), pushfile) a = MockAgent(self, commands = [("isdir /mnt/sdcard", "TRUE"), (cmd, response[0])]) exceptionThrown = False @@ -46,14 +46,16 @@ class PushTest(unittest.TestCase): subTests = [ { 'cmds': [ ("isdir /mnt/sdcard//baz", "TRUE"), ("isdir /mnt/sdcard//baz", "TRUE"), - ("push /mnt/sdcard//baz/%s %s" % - (os.path.basename(f.name), len(pushfile)), + ("push /mnt/sdcard//baz/%s %s\r\n%s" % + (os.path.basename(f.name), len(pushfile), + pushfile), expectedFileResponse) ], 'expectException': False }, { 'cmds': [ ("isdir /mnt/sdcard//baz", "TRUE"), ("isdir /mnt/sdcard//baz", "TRUE"), - ("push /mnt/sdcard//baz/%s %s" % - (os.path.basename(f.name), len(pushfile)), + ("push /mnt/sdcard//baz/%s %s\r\n%s" % + (os.path.basename(f.name), len(pushfile), + pushfile), "BADHASH") ], 'expectException': True }, { 'cmds': [ ("isdir /mnt/sdcard//baz", "FALSE"), diff --git a/testing/mozbase/test-manifest.ini b/testing/mozbase/test-manifest.ini index c91393c8dba6..30ac9f65246d 100644 --- a/testing/mozbase/test-manifest.ini +++ b/testing/mozbase/test-manifest.ini @@ -10,7 +10,7 @@ [include:manifestdestiny/tests/manifest.ini] [include:mozcrash/tests/manifest.ini] -# [include:mozdevice/tests/manifest.ini] bug 885784 +[include:mozdevice/tests/manifest.ini] [include:mozfile/tests/manifest.ini] [include:mozhttpd/tests/manifest.ini] [include:mozprocess/tests/manifest.ini]