| # Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| # Use of this source code is governed by a BSD-style license that can be |
| # found in the LICENSE file. |
| |
| """Defines TestPackageApk to help run APK-based native tests.""" |
| # pylint: disable=W0212 |
| |
| import logging |
| import os |
| import shlex |
| import sys |
| import tempfile |
| import time |
| |
| from pylib import android_commands |
| from pylib import constants |
| from pylib import pexpect |
| from pylib.device import device_errors |
| from pylib.device import intent |
| from pylib.gtest.test_package import TestPackage |
| |
| |
| class TestPackageApk(TestPackage): |
| """A helper class for running APK-based native tests.""" |
| |
| def __init__(self, suite_name): |
| """ |
| Args: |
| suite_name: Name of the test suite (e.g. base_unittests). |
| """ |
| TestPackage.__init__(self, suite_name) |
| if suite_name == 'content_browsertests': |
| self.suite_path = os.path.join( |
| constants.GetOutDirectory(), 'apks', '%s.apk' % suite_name) |
| self._package_info = constants.PACKAGE_INFO['content_browsertests'] |
| else: |
| self.suite_path = os.path.join( |
| constants.GetOutDirectory(), '%s_apk' % suite_name, |
| '%s-debug.apk' % suite_name) |
| self._package_info = constants.PACKAGE_INFO['gtest'] |
| |
| def _CreateCommandLineFileOnDevice(self, device, options): |
| device.WriteFile(self._package_info.cmdline_file, |
| self.suite_name + ' ' + options) |
| |
| def _GetFifo(self): |
| # The test.fifo path is determined by: |
| # testing/android/java/src/org/chromium/native_test/ |
| # ChromeNativeTestActivity.java and |
| # testing/android/native_test_launcher.cc |
| return '/data/data/' + self._package_info.package + '/files/test.fifo' |
| |
| def _ClearFifo(self, device): |
| device.RunShellCommand('rm -f ' + self._GetFifo()) |
| |
| def _WatchFifo(self, device, timeout, logfile=None): |
| for i in range(10): |
| if device.FileExists(self._GetFifo()): |
| logging.info('Fifo created.') |
| break |
| time.sleep(i) |
| else: |
| raise device_errors.DeviceUnreachableError( |
| 'Unable to find fifo on device %s ' % self._GetFifo()) |
| args = shlex.split(device.old_interface.Adb()._target_arg) |
| args += ['shell', 'cat', self._GetFifo()] |
| return pexpect.spawn('adb', args, timeout=timeout, logfile=logfile) |
| |
| def _StartActivity(self, device): |
| device.StartActivity( |
| intent.Intent(package=self._package_info.package, |
| activity=self._package_info.activity, |
| action='android.intent.action.MAIN'), |
| # No wait since the runner waits for FIFO creation anyway. |
| blocking=False, |
| force_stop=True) |
| |
| #override |
| def ClearApplicationState(self, device): |
| device.ClearApplicationState(self._package_info.package) |
| # Content shell creates a profile on the sdscard which accumulates cache |
| # files over time. |
| if self.suite_name == 'content_browsertests': |
| try: |
| device.RunShellCommand( |
| 'rm -r %s/content_shell' % device.GetExternalStoragePath(), |
| timeout=60 * 2) |
| except device_errors.CommandFailedError: |
| # TODO(jbudorick) Handle this exception appropriately once the |
| # conversions are done. |
| pass |
| |
| #override |
| def CreateCommandLineFileOnDevice(self, device, test_filter, test_arguments): |
| self._CreateCommandLineFileOnDevice( |
| device, '--gtest_filter=%s %s' % (test_filter, test_arguments)) |
| |
| #override |
| def GetAllTests(self, device): |
| self._CreateCommandLineFileOnDevice(device, '--gtest_list_tests') |
| try: |
| self.tool.SetupEnvironment() |
| # Clear and start monitoring logcat. |
| self._ClearFifo(device) |
| self._StartActivity(device) |
| # Wait for native test to complete. |
| p = self._WatchFifo(device, timeout=30 * self.tool.GetTimeoutScale()) |
| p.expect('<<ScopedMainEntryLogger') |
| p.close() |
| finally: |
| self.tool.CleanUpEnvironment() |
| # We need to strip the trailing newline. |
| content = [line.rstrip() for line in p.before.splitlines()] |
| return self._ParseGTestListTests(content) |
| |
| #override |
| def SpawnTestProcess(self, device): |
| try: |
| self.tool.SetupEnvironment() |
| self._ClearFifo(device) |
| self._StartActivity(device) |
| finally: |
| self.tool.CleanUpEnvironment() |
| logfile = android_commands.NewLineNormalizer(sys.stdout) |
| return self._WatchFifo(device, timeout=10, logfile=logfile) |
| |
| #override |
| def Install(self, device): |
| self.tool.CopyFiles(device) |
| device.Install(self.suite_path) |