Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(162)

Side by Side Diff: build/android/pylib/android_commands.py

Issue 17467003: [android] Switch test scripts to use last modified time instead of md5sum when checking dependencie… (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | build/android/pylib/gtest/test_package_apk.py » ('j') | build/java_apk.gypi » ('J')
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 # Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 # Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 # Use of this source code is governed by a BSD-style license that can be 2 # Use of this source code is governed by a BSD-style license that can be
3 # found in the LICENSE file. 3 # found in the LICENSE file.
4 4
5 """Provides an interface to communicate with the device via the adb command. 5 """Provides an interface to communicate with the device via the adb command.
6 6
7 Assumes adb binary is currently on system path. 7 Assumes adb binary is currently on system path.
8 """ 8 """
9 9
10 import collections 10 import collections
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
54 54
55 # Keycode "enum" suitable for passing to AndroidCommands.SendKey(). 55 # Keycode "enum" suitable for passing to AndroidCommands.SendKey().
56 KEYCODE_HOME = 3 56 KEYCODE_HOME = 3
57 KEYCODE_BACK = 4 57 KEYCODE_BACK = 4
58 KEYCODE_DPAD_UP = 19 58 KEYCODE_DPAD_UP = 19
59 KEYCODE_DPAD_DOWN = 20 59 KEYCODE_DPAD_DOWN = 20
60 KEYCODE_DPAD_RIGHT = 22 60 KEYCODE_DPAD_RIGHT = 22
61 KEYCODE_ENTER = 66 61 KEYCODE_ENTER = 66
62 KEYCODE_MENU = 82 62 KEYCODE_MENU = 82
63 63
64 MD5SUM_DEVICE_FOLDER = constants.TEST_EXECUTABLE_DIR + '/md5sum/' 64 TIMEMODIFIED_DEVICE_FOLDER = constants.TEST_EXECUTABLE_DIR + '/timemodified/'
frankf 2013/06/20 22:52:38 If these are only used in one function, let's move
frankf 2013/06/20 22:52:38 FOLDER -> DIRECTORY
craigdh 2013/07/02 17:26:12 Done.
craigdh 2013/07/02 17:26:12 Done.
65 MD5SUM_DEVICE_PATH = MD5SUM_DEVICE_FOLDER + 'md5sum_bin' 65 TIMEMODIFIED_DEVICE_PATH = TIMEMODIFIED_DEVICE_FOLDER + 'timemodified_bin'
66 MD5SUM_LD_LIBRARY_PATH = 'LD_LIBRARY_PATH=%s' % MD5SUM_DEVICE_FOLDER 66 TIMEMODIFIED_LD_LIBRARY_PATH = 'LD_LIBRARY_PATH=%s' % TIMEMODIFIED_DEVICE_FOLDER
67 67
68 def GetEmulators(): 68 def GetEmulators():
69 """Returns a list of emulators. Does not filter by status (e.g. offline). 69 """Returns a list of emulators. Does not filter by status (e.g. offline).
70 70
71 Both devices starting with 'emulator' will be returned in below output: 71 Both devices starting with 'emulator' will be returned in below output:
72 72
73 * daemon not running. starting it now on port 5037 * 73 * daemon not running. starting it now on port 5037 *
74 * daemon started successfully * 74 * daemon started successfully *
75 List of devices attached 75 List of devices attached
76 027c10494100b4d7 device 76 027c10494100b4d7 device
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
164 if isinstance(utc_offset, str) and len(utc_offset) == 5: 164 if isinstance(utc_offset, str) and len(utc_offset) == 5:
165 utc_delta = datetime.timedelta(hours=int(utc_offset[1:3]), 165 utc_delta = datetime.timedelta(hours=int(utc_offset[1:3]),
166 minutes=int(utc_offset[3:5])) 166 minutes=int(utc_offset[3:5]))
167 if utc_offset[0:1] == '-': 167 if utc_offset[0:1] == '-':
168 utc_delta = -utc_delta 168 utc_delta = -utc_delta
169 lastmod -= utc_delta 169 lastmod -= utc_delta
170 files[filename] = (int(file_match.group('size')), lastmod) 170 files[filename] = (int(file_match.group('size')), lastmod)
171 return files 171 return files
172 172
173 173
174 def _ComputeFileListHash(md5sum_output): 174 def _ComputeFileListTimesModified(timemodified_output):
175 """Returns a list of MD5 strings from the provided md5sum output.""" 175 """Returns a list of time strings from the provided timemodified output."""
176 return [line.split(' ')[0] for line in md5sum_output] 176 return [line.split(' ')[0] for line in timemodified_output]
177 177
178 178
179 def _HasAdbPushSucceeded(command_output): 179 def _HasAdbPushSucceeded(command_output):
180 """Returns whether adb push has succeeded from the provided output.""" 180 """Returns whether adb push has succeeded from the provided output."""
181 if not command_output: 181 if not command_output:
182 return False 182 return False
183 # Success looks like this: "3035 KB/s (12512056 bytes in 4.025s)" 183 # Success looks like this: "3035 KB/s (12512056 bytes in 4.025s)"
184 # Errors look like this: "failed to copy ... " 184 # Errors look like this: "failed to copy ... "
185 if not re.search('^[0-9]', command_output.splitlines()[-1]): 185 if not re.search('^[0-9]', command_output.splitlines()[-1]):
186 logging.critical('PUSH FAILED: ' + command_output) 186 logging.critical('PUSH FAILED: ' + command_output)
(...skipping 26 matching lines...) Expand all
213 os.environ['PATH'] += os.pathsep + adb_dir 213 os.environ['PATH'] += os.pathsep + adb_dir
214 self._adb = adb_interface.AdbInterface() 214 self._adb = adb_interface.AdbInterface()
215 if device: 215 if device:
216 self._adb.SetTargetSerial(device) 216 self._adb.SetTargetSerial(device)
217 self._device = device 217 self._device = device
218 self._logcat = None 218 self._logcat = None
219 self.logcat_process = None 219 self.logcat_process = None
220 self._logcat_tmpoutfile = None 220 self._logcat_tmpoutfile = None
221 self._pushed_files = [] 221 self._pushed_files = []
222 self._device_utc_offset = self.RunShellCommand('date +%z')[0] 222 self._device_utc_offset = self.RunShellCommand('date +%z')[0]
223 self._md5sum_build_dir = '' 223 self._timemodified_build_dir = ''
224 self._external_storage = '' 224 self._external_storage = ''
225 self._util_wrapper = '' 225 self._util_wrapper = ''
226 226
227 def _LogShell(self, cmd): 227 def _LogShell(self, cmd):
228 """Logs the adb shell command.""" 228 """Logs the adb shell command."""
229 if self._device: 229 if self._device:
230 device_repr = self._device[-4:] 230 device_repr = self._device[-4:]
231 else: 231 else:
232 device_repr = '????' 232 device_repr = '????'
233 logging.info('[%s]> %s', device_repr, cmd) 233 logging.info('[%s]> %s', device_repr, cmd)
(...skipping 455 matching lines...) Expand 10 before | Expand all | Expand 10 after
689 self.RunShellCommand('pm clear ' + package) 689 self.RunShellCommand('pm clear ' + package)
690 690
691 def SendKeyEvent(self, keycode): 691 def SendKeyEvent(self, keycode):
692 """Sends keycode to the device. 692 """Sends keycode to the device.
693 693
694 Args: 694 Args:
695 keycode: Numeric keycode to send (see "enum" at top of file). 695 keycode: Numeric keycode to send (see "enum" at top of file).
696 """ 696 """
697 self.RunShellCommand('input keyevent %d' % keycode) 697 self.RunShellCommand('input keyevent %d' % keycode)
698 698
699 def CheckMd5Sum(self, local_path, device_path, ignore_paths=False): 699 def CheckTimesModified(self, local_path, device_path, ignore_paths=False):
frankf 2013/06/20 22:52:38 I would rename this to something like FileOutOfSyn
craigdh 2013/07/02 17:26:12 Done.
craigdh 2013/07/02 17:26:12 Done.
700 """Compares the md5sum of a local path against a device path. 700 """Compares the time modified of a local path against a device path.
701 701
702 Args: 702 Args:
703 local_path: Path (file or directory) on the host. 703 local_path: Path (file or directory) on the host.
704 device_path: Path on the device. 704 device_path: Path on the device.
705 ignore_paths: If False, both the md5sum and the relative paths/names of 705 ignore_paths: If False, both the time modified and the relative
706 files must match. If True, only the md5sum must match. 706 paths/names of files must match. If True, only the time modified
707 must match.
707 708
708 Returns: 709 Returns:
709 True if the md5sums match. 710 True if the time the files were modified match or are more recent.
710 """ 711 """
711 assert os.path.exists(local_path), 'Local path not found %s' % local_path 712 assert os.path.exists(local_path), 'Local path not found %s' % local_path
712 713
713 if not self._md5sum_build_dir: 714 if not self._timemodified_build_dir:
714 default_build_type = os.environ.get('BUILD_TYPE', 'Debug') 715 default_build_type = os.environ.get('BUILD_TYPE', 'Debug')
715 build_dir = '%s/%s/' % ( 716 build_dir = '%s/%s/' % (
716 cmd_helper.OutDirectory().get(), default_build_type) 717 cmd_helper.OutDirectory().get(), default_build_type)
frankf 2013/06/20 22:52:38 We should really set the out directory once instea
craigdh 2013/07/02 17:26:12 Why? It's not a very heavy call.
717 md5sum_dist_path = '%s/md5sum_dist' % build_dir 718 timemodified_dist_path = '%s/timemodified_dist' % build_dir
frankf 2013/06/20 22:52:38 let's have 'host'/'device' in the variable names t
craigdh 2013/07/02 17:26:12 Done.
718 if not os.path.exists(md5sum_dist_path): 719 if not os.path.exists(timemodified_dist_path):
719 build_dir = '%s/Release/' % cmd_helper.OutDirectory().get() 720 build_dir = '%s/Release/' % cmd_helper.OutDirectory().get()
720 md5sum_dist_path = '%s/md5sum_dist' % build_dir 721 timemodified_dist_path = '%s/timemodified_dist' % build_dir
721 assert os.path.exists(md5sum_dist_path), 'Please build md5sum.' 722 assert os.path.exists(timemodified_dist_path), 'Build timemodified.'
722 command = 'push %s %s' % (md5sum_dist_path, MD5SUM_DEVICE_FOLDER) 723 command = 'push %s %s' % (timemodified_dist_path,
724 TIMEMODIFIED_DEVICE_FOLDER)
723 assert _HasAdbPushSucceeded(self._adb.SendCommand(command)) 725 assert _HasAdbPushSucceeded(self._adb.SendCommand(command))
724 self._md5sum_build_dir = build_dir 726 self._timemodified_build_dir = build_dir
725 727
726 self._pushed_files.append(device_path) 728 self._pushed_files.append(device_path)
727 hashes_on_device = _ComputeFileListHash( 729 hashes_on_device = _ComputeFileListTimesModified(
728 self.RunShellCommand(MD5SUM_LD_LIBRARY_PATH + ' ' + self._util_wrapper + 730 self.RunShellCommand(TIMEMODIFIED_LD_LIBRARY_PATH + ' ' +
729 ' ' + MD5SUM_DEVICE_PATH + ' ' + device_path)) 731 self._util_wrapper + ' ' + TIMEMODIFIED_DEVICE_PATH + ' ' +
732 device_path))
730 assert os.path.exists(local_path), 'Local path not found %s' % local_path 733 assert os.path.exists(local_path), 'Local path not found %s' % local_path
731 md5sum_output = cmd_helper.GetCmdOutput( 734 timemodified_output = cmd_helper.GetCmdOutput(
732 ['%s/md5sum_bin_host' % self._md5sum_build_dir, local_path]) 735 ['%s/timemodified_bin_host' % self._timemodified_build_dir, local_path])
733 hashes_on_host = _ComputeFileListHash(md5sum_output.splitlines()) 736 hashes_on_host = _ComputeFileListTimesModified(
737 timemodified_output.splitlines())
734 738
739 #TODO(craigdh): This doesn't appear to have any effect.
frankf 2013/06/20 22:52:38 What's the deal here? If not used, can we remove i
craigdh 2013/07/02 17:26:12 Done.
735 if ignore_paths: 740 if ignore_paths:
736 hashes_on_device = [h.split()[0] for h in hashes_on_device] 741 hashes_on_device = [h.split()[0] for h in hashes_on_device]
737 hashes_on_host = [h.split()[0] for h in hashes_on_host] 742 hashes_on_host = [h.split()[0] for h in hashes_on_host]
738 743
739 return hashes_on_device == hashes_on_host 744 if len(hashes_on_device) != len(hashes_on_host):
745 return False
746 hashes_on_device.sort()
747 hashes_on_host.sort()
748 return all(int(dtime) >= int(htime) for dtime, htime in
749 zip(hashes_on_device, hashes_on_host))
740 750
741 def PushIfNeeded(self, local_path, device_path): 751 def PushIfNeeded(self, local_path, device_path):
742 """Pushes |local_path| to |device_path|. 752 """Pushes |local_path| to |device_path|.
743 753
744 Works for files and directories. This method skips copying any paths in 754 Works for files and directories. This method skips copying any paths in
745 |test_data_paths| that already exist on the device with the same hash. 755 |test_data_paths| that already exist on the device with the same modified
756 time.
746 757
747 All pushed files can be removed by calling RemovePushedFiles(). 758 All pushed files can be removed by calling RemovePushedFiles().
748 """ 759 """
749 if self.CheckMd5Sum(local_path, device_path): 760 if self.CheckTimesModified(local_path, device_path):
750 return 761 return
751 762
752 # They don't match, so remove everything first and then create it. 763 # They don't match, so remove everything first and then create it.
753 if os.path.isdir(local_path): 764 if os.path.isdir(local_path):
754 self.RunShellCommand('rm -r %s' % device_path, timeout_time=2 * 60) 765 self.RunShellCommand('rm -r %s' % device_path, timeout_time=2 * 60)
755 self.RunShellCommand('mkdir -p %s' % device_path) 766 self.RunShellCommand('mkdir -p %s' % device_path)
756 767
757 # NOTE: We can't use adb_interface.Push() because it hardcodes a timeout of 768 # NOTE: We can't use adb_interface.Push() because it hardcodes a timeout of
758 # 60 seconds which isn't sufficient for a lot of users of this method. 769 # 60 seconds which isn't sufficient for a lot of users of this method.
759 push_command = 'push %s %s' % (local_path, device_path) 770 push_command = 'push %s %s' % (local_path, device_path)
(...skipping 507 matching lines...) Expand 10 before | Expand all | Expand 10 after
1267 host_dir = os.path.dirname(host_file) 1278 host_dir = os.path.dirname(host_file)
1268 if not os.path.exists(host_dir): 1279 if not os.path.exists(host_dir):
1269 os.makedirs(host_dir) 1280 os.makedirs(host_dir)
1270 device_file = '%s/screenshot.png' % self.GetExternalStorage() 1281 device_file = '%s/screenshot.png' % self.GetExternalStorage()
1271 self.RunShellCommand('/system/bin/screencap -p %s' % device_file) 1282 self.RunShellCommand('/system/bin/screencap -p %s' % device_file)
1272 assert self._adb.Pull(device_file, host_file) 1283 assert self._adb.Pull(device_file, host_file)
1273 assert os.path.exists(host_file) 1284 assert os.path.exists(host_file)
1274 1285
1275 def SetUtilWrapper(self, util_wrapper): 1286 def SetUtilWrapper(self, util_wrapper):
1276 """Sets a wrapper prefix to be used when running a locally-built 1287 """Sets a wrapper prefix to be used when running a locally-built
1277 binary on the device (ex.: md5sum_bin). 1288 binary on the device (ex.: timemodified_bin).
1278 """ 1289 """
1279 self._util_wrapper = util_wrapper 1290 self._util_wrapper = util_wrapper
1280 1291
1281 def RunInstrumentationTest(self, test, test_package, instr_args, timeout): 1292 def RunInstrumentationTest(self, test, test_package, instr_args, timeout):
1282 """Runs a single instrumentation test. 1293 """Runs a single instrumentation test.
1283 1294
1284 Args: 1295 Args:
1285 test: Test class/method. 1296 test: Test class/method.
1286 test_package: Package name of test apk. 1297 test_package: Package name of test apk.
1287 instr_args: Extra key/value to pass to am instrument. 1298 instr_args: Extra key/value to pass to am instrument.
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
1337 """ 1348 """
1338 def __init__(self, output): 1349 def __init__(self, output):
1339 self._output = output 1350 self._output = output
1340 1351
1341 def write(self, data): 1352 def write(self, data):
1342 data = data.replace('\r\r\n', '\n') 1353 data = data.replace('\r\r\n', '\n')
1343 self._output.write(data) 1354 self._output.write(data)
1344 1355
1345 def flush(self): 1356 def flush(self):
1346 self._output.flush() 1357 self._output.flush()
OLDNEW
« no previous file with comments | « no previous file | build/android/pylib/gtest/test_package_apk.py » ('j') | build/java_apk.gypi » ('J')

Powered by Google App Engine
This is Rietveld 408576698