15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch"""Defines TestPackageExecutable to help run stand-alone executables.""" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import logging 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import os 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import sys 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import tempfile 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)from pylib import cmd_helper 132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)from pylib import constants 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)from pylib import pexpect 15cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)from pylib.device import device_errors 165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)from pylib.gtest.test_package import TestPackage 172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class TestPackageExecutable(TestPackage): 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) """A helper class for running stand-alone executables.""" 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) _TEST_RUNNER_RET_VAL_FILE = 'gtest_retval' 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 243551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) def __init__(self, suite_name): 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) """ 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Args: 27fb250657ef40d7500f20882d5c9909c1013367d3Ben Murdoch suite_name: Name of the test suite (e.g. base_unittests). 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) """ 29fb250657ef40d7500f20882d5c9909c1013367d3Ben Murdoch TestPackage.__init__(self, suite_name) 3058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) self.suite_path = os.path.join(constants.GetOutDirectory(), suite_name) 3158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) self._symbols_dir = os.path.join(constants.GetOutDirectory(), 3258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 'lib.target') 337dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 347dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch #override 35a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch def GetGTestReturnCode(self, device): 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ret = None 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ret_code = 1 # Assume failure if we can't find it 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ret_code_file = tempfile.NamedTemporaryFile() 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) try: 40116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if not device.PullFile( 412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) constants.TEST_EXECUTABLE_DIR + '/' + 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TestPackageExecutable._TEST_RUNNER_RET_VAL_FILE, 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ret_code_file.name): 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) logging.critical('Unable to pull gtest ret val file %s', 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ret_code_file.name) 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) raise ValueError 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ret_code = file(ret_code_file.name).read() 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ret = int(ret_code) 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) except ValueError: 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) logging.critical('Error reading gtest ret val file %s [%s]', 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ret_code_file.name, ret_code) 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ret = 1 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ret 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) @staticmethod 56a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch def _AddNativeCoverageExports(device): 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # export GCOV_PREFIX set the path for native coverage results 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # export GCOV_PREFIX_STRIP indicates how many initial directory 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # names to strip off the hardwired absolute paths. 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # This value is calculated in buildbot.sh and 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # depends on where the tree is built. 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # Ex: /usr/local/google/code/chrome will become 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # /code/chrome if GCOV_PREFIX_STRIP=3 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) try: 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) depth = os.environ['NATIVE_COVERAGE_DEPTH_STRIP'] 66cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) export_string = ('export GCOV_PREFIX="%s/gcov"\n' % 67cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) device.GetExternalStoragePath()) 68cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) export_string += 'export GCOV_PREFIX_STRIP=%s\n' % depth 69cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return export_string 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) except KeyError: 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) logging.info('NATIVE_COVERAGE_DEPTH_STRIP is not defined: ' 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 'No native coverage.') 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return '' 74cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) except device_errors.CommandFailedError: 75cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) logging.info('No external storage found: No native coverage.') 76cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return '' 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 787dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch #override 79a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch def ClearApplicationState(self, device): 80116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch try: 81116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch # We don't expect the executable to be running, so we don't attempt 82116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch # to retry on failure. 83116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch device.KillAll(self.suite_name, blocking=True, timeout=30, retries=0) 84116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch except device_errors.CommandFailedError: 85116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch # KillAll raises an exception if it can't find a process with the given 86116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch # name. We only care that there is no process with the given name, so 87116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch # we can safely eat the exception. 88116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch pass 892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 907dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch #override 91a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch def CreateCommandLineFileOnDevice(self, device, test_filter, test_arguments): 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tool_wrapper = self.tool.GetTestWrapper() 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sh_script_file = tempfile.NamedTemporaryFile() 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # We need to capture the exit status from the script since adb shell won't 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # propagate to us. 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sh_script_file.write('cd %s\n' 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) '%s' 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) '%s %s/%s --gtest_filter=%s %s\n' 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 'echo $? > %s' % 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (constants.TEST_EXECUTABLE_DIR, 101a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch self._AddNativeCoverageExports(device), 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tool_wrapper, constants.TEST_EXECUTABLE_DIR, 103fb250657ef40d7500f20882d5c9909c1013367d3Ben Murdoch self.suite_name, 104eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch test_filter, test_arguments, 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TestPackageExecutable._TEST_RUNNER_RET_VAL_FILE)) 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sh_script_file.flush() 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cmd_helper.RunCmd(['chmod', '+x', sh_script_file.name]) 108116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch device.PushChangedFiles( 109eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch sh_script_file.name, 110eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch constants.TEST_EXECUTABLE_DIR + '/chrome_test_runner.sh') 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) logging.info('Conents of the test runner script: ') 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for line in open(sh_script_file.name).readlines(): 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) logging.info(' ' + line.rstrip()) 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1157dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch #override 116a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch def GetAllTests(self, device): 117f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) all_tests = device.RunShellCommand( 1187dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch '%s %s/%s --gtest_list_tests' % 1197dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch (self.tool.GetTestWrapper(), 1207dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch constants.TEST_EXECUTABLE_DIR, 121fb250657ef40d7500f20882d5c9909c1013367d3Ben Murdoch self.suite_name)) 1227dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch return self._ParseGTestListTests(all_tests) 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1247dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch #override 125a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch def SpawnTestProcess(self, device): 1265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) args = ['adb', '-s', str(device), 'shell', 'sh', 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) constants.TEST_EXECUTABLE_DIR + '/chrome_test_runner.sh'] 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) logging.info(args) 1297dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch return pexpect.spawn(args[0], args[1:], logfile=sys.stdout) 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1317dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch #override 132a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch def Install(self, device): 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if self.tool.NeedsDebugInfo(): 134ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch target_name = self.suite_path 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else: 1365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) target_name = self.suite_path + '_stripped' 1375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if not os.path.isfile(target_name): 1385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) raise Exception('Did not find %s, build target %s' % 1395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) (target_name, self.suite_name + '_stripped')) 1405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) target_mtime = os.stat(target_name).st_mtime 1425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) source_mtime = os.stat(self.suite_path).st_mtime 1435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if target_mtime < source_mtime: 1445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) raise Exception( 1455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 'stripped binary (%s, timestamp %d) older than ' 1465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 'source binary (%s, timestamp %d), build target %s' % 1475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) (target_name, target_mtime, self.suite_path, source_mtime, 1485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) self.suite_name + '_stripped')) 1495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 150fb250657ef40d7500f20882d5c9909c1013367d3Ben Murdoch test_binary = constants.TEST_EXECUTABLE_DIR + '/' + self.suite_name 151116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch device.PushChangedFiles(target_name, test_binary) 152