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