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 6import os 7import shlex 8import sys 9import tempfile 10import time 11 12import android_commands 13import constants 14from test_package import TestPackage 15from pylib import pexpect 16 17class TestPackageApk(TestPackage): 18 """A helper class for running APK-based native tests. 19 20 Args: 21 adb: ADB interface the tests are using. 22 device: Device to run the tests. 23 test_suite: A specific test suite to run, empty to run all. 24 timeout: Timeout for each test. 25 rebaseline: Whether or not to run tests in isolation and update the filter. 26 performance_test: Whether or not performance test(s). 27 cleanup_test_files: Whether or not to cleanup test files on device. 28 tool: Name of the Valgrind tool. 29 dump_debug_info: A debug_info object. 30 """ 31 32 def __init__(self, adb, device, test_suite, timeout, rebaseline, 33 performance_test, cleanup_test_files, tool, 34 dump_debug_info): 35 TestPackage.__init__(self, adb, device, test_suite, timeout, 36 rebaseline, performance_test, cleanup_test_files, 37 tool, dump_debug_info) 38 39 def _CreateTestRunnerScript(self, options): 40 command_line_file = tempfile.NamedTemporaryFile() 41 # GTest expects argv[0] to be the executable path. 42 command_line_file.write(self.test_suite_basename + ' ' + options) 43 command_line_file.flush() 44 self.adb.PushIfNeeded(command_line_file.name, 45 constants.TEST_EXECUTABLE_DIR + 46 '/chrome-native-tests-command-line') 47 48 def _GetGTestReturnCode(self): 49 return None 50 51 def _GetFifo(self): 52 # The test.fifo path is determined by: 53 # testing/android/java/src/org/chromium/native_test/ 54 # ChromeNativeTestActivity.java and 55 # testing/android/native_test_launcher.cc 56 return '/data/data/org.chromium.native_test/files/test.fifo' 57 58 def _ClearFifo(self): 59 self.adb.RunShellCommand('rm -f ' + self._GetFifo()) 60 61 def _WatchFifo(self, timeout, logfile=None): 62 for i in range(10): 63 if self.adb.FileExistsOnDevice(self._GetFifo()): 64 print 'Fifo created...' 65 break 66 time.sleep(i) 67 else: 68 raise Exception('Unable to find fifo on device %s ' % self._GetFifo()) 69 args = shlex.split(self.adb.Adb()._target_arg) 70 args += ['shell', 'cat', self._GetFifo()] 71 return pexpect.spawn('adb', args, timeout=timeout, logfile=logfile) 72 73 def GetAllTests(self): 74 """Returns a list of all tests available in the test suite.""" 75 self._CreateTestRunnerScript('--gtest_list_tests') 76 try: 77 self.tool.SetupEnvironment() 78 # Clear and start monitoring logcat. 79 self._ClearFifo() 80 self.adb.RunShellCommand( 81 'am start -n ' 82 'org.chromium.native_test/' 83 'org.chromium.native_test.ChromeNativeTestActivity') 84 # Wait for native test to complete. 85 p = self._WatchFifo(timeout=30 * self.tool.GetTimeoutScale()) 86 p.expect("<<ScopedMainEntryLogger") 87 p.close() 88 finally: 89 self.tool.CleanUpEnvironment() 90 # We need to strip the trailing newline. 91 content = [line.rstrip() for line in p.before.splitlines()] 92 ret = self._ParseGTestListTests(content) 93 return ret 94 95 def CreateTestRunnerScript(self, gtest_filter, test_arguments): 96 self._CreateTestRunnerScript('--gtest_filter=%s %s' % (gtest_filter, 97 test_arguments)) 98 99 def RunTestsAndListResults(self): 100 try: 101 self.tool.SetupEnvironment() 102 self._ClearFifo() 103 self.adb.RunShellCommand( 104 'am start -n ' 105 'org.chromium.native_test/' 106 'org.chromium.native_test.ChromeNativeTestActivity') 107 finally: 108 self.tool.CleanUpEnvironment() 109 logfile = android_commands.NewLineNormalizer(sys.stdout) 110 return self._WatchTestOutput(self._WatchFifo(timeout=10, logfile=logfile)) 111 112 def StripAndCopyExecutable(self): 113 # Always uninstall the previous one (by activity name); we don't 114 # know what was embedded in it. 115 self.adb.ManagedInstall(self.test_suite_full, False, 116 package_name='org.chromium.native_test') 117 118 def _GetTestSuiteBaseName(self): 119 """Returns the base name of the test suite.""" 120 # APK test suite names end with '-debug.apk' 121 return os.path.basename(self.test_suite).rsplit('-debug', 1)[0] 122