- add sources.
[platform/framework/web/crosswalk.git] / src / build / android / pylib / gtest / test_package_exe.py
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 TestPackageExecutable to help run stand-alone executables."""
6
7 import logging
8 import os
9 import shutil
10 import sys
11 import tempfile
12
13 from pylib import cmd_helper
14 from pylib import constants
15 from pylib import pexpect
16
17 from test_package import TestPackage
18
19
20 class TestPackageExecutable(TestPackage):
21   """A helper class for running stand-alone executables."""
22
23   _TEST_RUNNER_RET_VAL_FILE = 'gtest_retval'
24
25   def __init__(self, suite_name):
26     """
27     Args:
28       suite_name: Name of the test suite (e.g. base_unittests).
29     """
30     TestPackage.__init__(self, suite_name)
31     self.suite_path = os.path.join(constants.GetOutDirectory(), suite_name)
32     self._symbols_dir = os.path.join(constants.GetOutDirectory(),
33                                      'lib.target')
34
35   #override
36   def GetGTestReturnCode(self, adb):
37     ret = None
38     ret_code = 1  # Assume failure if we can't find it
39     ret_code_file = tempfile.NamedTemporaryFile()
40     try:
41       if not adb.Adb().Pull(
42           constants.TEST_EXECUTABLE_DIR + '/' +
43           TestPackageExecutable._TEST_RUNNER_RET_VAL_FILE,
44           ret_code_file.name):
45         logging.critical('Unable to pull gtest ret val file %s',
46                          ret_code_file.name)
47         raise ValueError
48       ret_code = file(ret_code_file.name).read()
49       ret = int(ret_code)
50     except ValueError:
51       logging.critical('Error reading gtest ret val file %s [%s]',
52                        ret_code_file.name, ret_code)
53       ret = 1
54     return ret
55
56   def _AddNativeCoverageExports(self, adb):
57     # export GCOV_PREFIX set the path for native coverage results
58     # export GCOV_PREFIX_STRIP indicates how many initial directory
59     #                          names to strip off the hardwired absolute paths.
60     #                          This value is calculated in buildbot.sh and
61     #                          depends on where the tree is built.
62     # Ex: /usr/local/google/code/chrome will become
63     #     /code/chrome if GCOV_PREFIX_STRIP=3
64     try:
65       depth = os.environ['NATIVE_COVERAGE_DEPTH_STRIP']
66     except KeyError:
67       logging.info('NATIVE_COVERAGE_DEPTH_STRIP is not defined: '
68                    'No native coverage.')
69       return ''
70     export_string = ('export GCOV_PREFIX="%s/gcov"\n' %
71                      adb.GetExternalStorage())
72     export_string += 'export GCOV_PREFIX_STRIP=%s\n' % depth
73     return export_string
74
75   #override
76   def ClearApplicationState(self, adb):
77     adb.KillAllBlocking(self.suite_name, 30)
78
79   #override
80   def CreateCommandLineFileOnDevice(self, adb, test_filter, test_arguments):
81     tool_wrapper = self.tool.GetTestWrapper()
82     sh_script_file = tempfile.NamedTemporaryFile()
83     # We need to capture the exit status from the script since adb shell won't
84     # propagate to us.
85     sh_script_file.write('cd %s\n'
86                          '%s'
87                          '%s %s/%s --gtest_filter=%s %s\n'
88                          'echo $? > %s' %
89                          (constants.TEST_EXECUTABLE_DIR,
90                           self._AddNativeCoverageExports(adb),
91                           tool_wrapper, constants.TEST_EXECUTABLE_DIR,
92                           self.suite_name,
93                           test_filter, test_arguments,
94                           TestPackageExecutable._TEST_RUNNER_RET_VAL_FILE))
95     sh_script_file.flush()
96     cmd_helper.RunCmd(['chmod', '+x', sh_script_file.name])
97     adb.PushIfNeeded(
98         sh_script_file.name,
99         constants.TEST_EXECUTABLE_DIR + '/chrome_test_runner.sh')
100     logging.info('Conents of the test runner script: ')
101     for line in open(sh_script_file.name).readlines():
102       logging.info('  ' + line.rstrip())
103
104   #override
105   def GetAllTests(self, adb):
106     all_tests = adb.RunShellCommand(
107         '%s %s/%s --gtest_list_tests' %
108         (self.tool.GetTestWrapper(),
109          constants.TEST_EXECUTABLE_DIR,
110          self.suite_name))
111     return self._ParseGTestListTests(all_tests)
112
113   #override
114   def SpawnTestProcess(self, adb):
115     args = ['adb', '-s', adb.GetDevice(), 'shell', 'sh',
116             constants.TEST_EXECUTABLE_DIR + '/chrome_test_runner.sh']
117     logging.info(args)
118     return pexpect.spawn(args[0], args[1:], logfile=sys.stdout)
119
120   #override
121   def Install(self, adb):
122     if self.tool.NeedsDebugInfo():
123       target_name = self.suite_path
124     else:
125       target_name = self.suite_path + '_' + adb.GetDevice() + '_stripped'
126       should_strip = True
127       if os.path.isfile(target_name):
128         logging.info('Found target file %s' % target_name)
129         target_mtime = os.stat(target_name).st_mtime
130         source_mtime = os.stat(self.suite_path).st_mtime
131         if target_mtime > source_mtime:
132           logging.info('Target mtime (%d) is newer than source (%d), assuming '
133                        'no change.' % (target_mtime, source_mtime))
134           should_strip = False
135
136       if should_strip:
137         logging.info('Did not find up-to-date stripped binary. Generating a '
138                      'new one (%s).' % target_name)
139         # Whenever we generate a stripped binary, copy to the symbols dir. If we
140         # aren't stripping a new binary, assume it's there.
141         if not os.path.exists(self._symbols_dir):
142           os.makedirs(self._symbols_dir)
143         shutil.copy(self.suite_path, self._symbols_dir)
144         strip = os.environ['STRIP']
145         cmd_helper.RunCmd([strip, self.suite_path, '-o', target_name])
146     test_binary = constants.TEST_EXECUTABLE_DIR + '/' + self.suite_name
147     adb.PushIfNeeded(target_name, test_binary)