OLD | NEW |
(Empty) | |
| 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 |
| 3 # found in the LICENSE file. |
| 4 |
| 5 """Defines TestPackageApk to help run APK-based native tests.""" |
| 6 # pylint: disable=W0212 |
| 7 |
| 8 import itertools |
| 9 import logging |
| 10 import os |
| 11 import posixpath |
| 12 import shlex |
| 13 import sys |
| 14 import tempfile |
| 15 import time |
| 16 |
| 17 from pylib import android_commands |
| 18 from pylib import constants |
| 19 from pylib import pexpect |
| 20 from pylib.device import device_errors |
| 21 from pylib.device import intent |
| 22 from pylib.gtest import gtest_test_instance |
| 23 from pylib.gtest import local_device_gtest_run |
| 24 from pylib.gtest.test_package import TestPackage |
| 25 |
| 26 |
| 27 class TestPackageApk(TestPackage): |
| 28 """A helper class for running APK-based native tests.""" |
| 29 |
| 30 def __init__(self, suite_name): |
| 31 """ |
| 32 Args: |
| 33 suite_name: Name of the test suite (e.g. base_unittests). |
| 34 """ |
| 35 TestPackage.__init__(self, suite_name) |
| 36 self.suite_path = os.path.join( |
| 37 constants.GetOutDirectory(), '%s_apk' % suite_name, |
| 38 '%s-debug.apk' % suite_name) |
| 39 if suite_name == 'content_browsertests': |
| 40 self._package_info = constants.PACKAGE_INFO['content_browsertests'] |
| 41 elif suite_name == 'components_browsertests': |
| 42 self._package_info = constants.PACKAGE_INFO['components_browsertests'] |
| 43 else: |
| 44 self._package_info = constants.PACKAGE_INFO['gtest'] |
| 45 |
| 46 if suite_name == 'net_unittests': |
| 47 self._extras = {'RunInSubThread': ''} |
| 48 else: |
| 49 self._extras = [] |
| 50 |
| 51 def _CreateCommandLineFileOnDevice(self, device, options): |
| 52 device.WriteFile(self._package_info.cmdline_file, |
| 53 self.suite_name + ' ' + options) |
| 54 |
| 55 def _GetFifo(self): |
| 56 # The test.fifo path is determined by: |
| 57 # testing/android/native_test/java/src/org/chromium/native_test/ |
| 58 # NativeTestActivity.java and |
| 59 # testing/android/native_test_launcher.cc |
| 60 return '/data/data/' + self._package_info.package + '/files/test.fifo' |
| 61 |
| 62 def _ClearFifo(self, device): |
| 63 device.RunShellCommand('rm -f ' + self._GetFifo()) |
| 64 |
| 65 def _WatchFifo(self, device, timeout, logfile=None): |
| 66 for i in range(100): |
| 67 if device.FileExists(self._GetFifo()): |
| 68 logging.info('Fifo created. Slept for %f secs' % (i * 0.5)) |
| 69 break |
| 70 time.sleep(0.5) |
| 71 else: |
| 72 raise device_errors.DeviceUnreachableError( |
| 73 'Unable to find fifo on device %s ' % self._GetFifo()) |
| 74 args = shlex.split(device.old_interface.Adb()._target_arg) |
| 75 args += ['shell', 'cat', self._GetFifo()] |
| 76 return pexpect.spawn('adb', args, timeout=timeout, logfile=logfile) |
| 77 |
| 78 def _StartActivity(self, device, force_stop=True): |
| 79 device.StartActivity( |
| 80 intent.Intent(package=self._package_info.package, |
| 81 activity=self._package_info.activity, |
| 82 action='android.intent.action.MAIN', |
| 83 extras=self._extras), |
| 84 # No wait since the runner waits for FIFO creation anyway. |
| 85 blocking=False, |
| 86 force_stop=force_stop) |
| 87 |
| 88 #override |
| 89 def ClearApplicationState(self, device): |
| 90 device.ClearApplicationState(self._package_info.package) |
| 91 # Content shell creates a profile on the sdscard which accumulates cache |
| 92 # files over time. |
| 93 if self.suite_name == 'content_browsertests': |
| 94 try: |
| 95 device.RunShellCommand( |
| 96 'rm -r %s/content_shell' % device.GetExternalStoragePath(), |
| 97 timeout=60 * 2) |
| 98 except device_errors.CommandFailedError: |
| 99 # TODO(jbudorick) Handle this exception appropriately once the |
| 100 # conversions are done. |
| 101 pass |
| 102 elif self.suite_name == 'components_browsertests': |
| 103 try: |
| 104 device.RunShellCommand( |
| 105 'rm -r %s/components_shell' % device.GetExternalStoragePath(), |
| 106 timeout=60 * 2) |
| 107 except device_errors.CommandFailedError: |
| 108 # TODO(jbudorick) Handle this exception appropriately once the |
| 109 # conversions are done. |
| 110 pass |
| 111 |
| 112 #override |
| 113 def CreateCommandLineFileOnDevice(self, device, test_filter, test_arguments): |
| 114 self._CreateCommandLineFileOnDevice( |
| 115 device, '--gtest_filter=%s %s' % (test_filter, test_arguments)) |
| 116 |
| 117 #override |
| 118 def GetAllTests(self, device): |
| 119 self._CreateCommandLineFileOnDevice(device, '--gtest_list_tests') |
| 120 try: |
| 121 self.tool.SetupEnvironment() |
| 122 # Clear and start monitoring logcat. |
| 123 self._ClearFifo(device) |
| 124 self._StartActivity(device) |
| 125 # Wait for native test to complete. |
| 126 p = self._WatchFifo(device, timeout=30 * self.tool.GetTimeoutScale()) |
| 127 p.expect('<<ScopedMainEntryLogger') |
| 128 p.close() |
| 129 finally: |
| 130 self.tool.CleanUpEnvironment() |
| 131 # We need to strip the trailing newline. |
| 132 content = [line.rstrip() for line in p.before.splitlines()] |
| 133 return gtest_test_instance.ParseGTestListTests(content) |
| 134 |
| 135 #override |
| 136 def SpawnTestProcess(self, device): |
| 137 try: |
| 138 self.tool.SetupEnvironment() |
| 139 self._ClearFifo(device) |
| 140 # Doesn't need to stop an Activity because ClearApplicationState() is |
| 141 # always called before this call and so it is already stopped at this |
| 142 # point. |
| 143 self._StartActivity(device, force_stop=False) |
| 144 finally: |
| 145 self.tool.CleanUpEnvironment() |
| 146 logfile = android_commands.NewLineNormalizer(sys.stdout) |
| 147 return self._WatchFifo(device, timeout=10, logfile=logfile) |
| 148 |
| 149 #override |
| 150 def Install(self, device): |
| 151 self.tool.CopyFiles(device) |
| 152 device.Install(self.suite_path) |
| 153 |
| 154 #override |
| 155 def PullAppFiles(self, device, files, directory): |
| 156 local_device_gtest_run.PullAppFilesImpl( |
| 157 device, self._package_info.package, files, directory) |
OLD | NEW |