Home | History | Annotate | Download | only in brillo_Gtests
      1 # Copyright 2015 The Chromium OS 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 from collections import namedtuple
      6 import logging
      7 import os
      8 
      9 import common
     10 from autotest_lib.client.common_lib import error
     11 from autotest_lib.server import site_gtest_runner
     12 from autotest_lib.server import test
     13 
     14 
     15 NATIVE_TESTS_PATH = '/data/nativetest'
     16 WHITELIST_FILE = '/data/nativetest/tests.txt'
     17 LIST_TEST_BINARIES_TEMPLATE = (
     18         'find %(path)s -type f -mindepth 2 -maxdepth 2 '
     19         '\( -perm -100 -o -perm -010 -o -perm -001 \)')
     20 
     21 GtestSuite = namedtuple('GtestSuite', ['path', 'run_as_root'])
     22 
     23 class brillo_Gtests(test.test):
     24     """Run one or more native gTest Suites."""
     25     version = 1
     26 
     27 
     28     def _get_whitelisted_tests(self, whitelist_path):
     29         """Return the list of whitelisted tests.
     30 
     31         The whitelist is expected to be a two column CSV file containing the
     32         test name and "yes" or "no" whether the test should be run as root or
     33         not.
     34         Anything after a # on a line is considered to be a comment and  ignored.
     35 
     36         @param whitelist_path: Path to the whitelist.
     37 
     38         @return a list of GtestSuite tuples.
     39         """
     40         suites = []
     41         for line in self.host.run_output(
     42                 'cat %s' % whitelist_path).splitlines():
     43             # Remove anything after the first # (comments).
     44             line = line.split('#')[0]
     45             if line.strip() == '':
     46                 continue
     47 
     48             parts = line.split(',')
     49             if len(parts) != 2:
     50                 logging.error('badly formatted line in %s: %s', whitelist_path,
     51                               line)
     52                 continue
     53 
     54             name = parts[0].strip()
     55             path = os.path.join(NATIVE_TESTS_PATH, name, name)
     56             suites.append(GtestSuite(path, parts[1].strip() == 'yes'))
     57         return suites
     58 
     59 
     60     def _find_all_gtestsuites(self, use_whitelist=False):
     61         """Find all the gTest Suites installed on the DUT.
     62 
     63         @param use_whitelist: Only whitelisted tests found on the system will
     64                               be used.
     65         """
     66         list_cmd = LIST_TEST_BINARIES_TEMPLATE % {'path': NATIVE_TESTS_PATH}
     67         gtest_suites_path = self.host.run_output(list_cmd).splitlines()
     68         gtest_suites = [GtestSuite(path, True) for path in gtest_suites_path]
     69 
     70         if use_whitelist:
     71             try:
     72                 whitelisted = self._get_whitelisted_tests(WHITELIST_FILE)
     73                 gtest_suites = [t for t in whitelisted
     74                                 if t.path in gtest_suites_path]
     75             except error.AutoservRunError:
     76                 logging.error('Failed to read whitelist %s', WHITELIST_FILE)
     77 
     78         if not gtest_suites:
     79             raise error.TestWarn('No test executables found on the DUT')
     80         logging.debug('Test executables found:\n%s',
     81                       '\n'.join([str(t) for t in gtest_suites]))
     82         return gtest_suites
     83 
     84 
     85     def run_gtestsuite(self, gtestSuite):
     86         """Run a gTest Suite.
     87 
     88         @param gtestSuite: GtestSuite tuple.
     89 
     90         @return True if the all the tests in the gTest Suite pass. False
     91                 otherwise.
     92         """
     93         # Make sure the gTest Suite exists.
     94         result = self.host.run('test -e %s' % gtestSuite.path,
     95                                ignore_status=True)
     96         if not result.exit_status == 0:
     97             logging.error('Unable to find %s', gtestSuite.path)
     98             return False
     99 
    100         result = self.host.run('test -x %s' % gtestSuite.path,
    101                                ignore_status=True)
    102         if not result.exit_status == 0:
    103             self.host.run('chmod +x %s' % gtestSuite.path)
    104 
    105         logging.debug('Running: %s', gtestSuite)
    106         command = gtestSuite.path
    107         if not gtestSuite.run_as_root:
    108           command = 'su shell %s' % command
    109 
    110         result = self.host.run(command, ignore_status=True)
    111         logging.debug(result.stdout)
    112 
    113         parser = site_gtest_runner.gtest_parser()
    114         for line in result.stdout.splitlines():
    115             parser.ProcessLogLine(line)
    116         passed_tests = parser.PassedTests()
    117         if passed_tests:
    118             logging.debug('Passed Tests: %s', passed_tests)
    119         failed_tests = parser.FailedTests(include_fails=True,
    120                                           include_flaky=True)
    121         if failed_tests:
    122             logging.error('Failed Tests: %s', failed_tests)
    123             for test in failed_tests:
    124                 logging.error('Test %s failed:\n%s', test,
    125                               parser.FailureDescription(test))
    126             return False
    127         if result.exit_status != 0:
    128             logging.error('%s exited with exit code: %s',
    129                           gtestSuite, result.exit_status)
    130             return False
    131         return True
    132 
    133 
    134     def run_once(self, host=None, gtest_suites=None, use_whitelist=False):
    135         """Run gTest Suites on the DUT.
    136 
    137         @param host: host object representing the device under test.
    138         @param gtest_suites: List of gTest suites to run. Default is to run
    139                              every gTest suite on the host.
    140         @param use_whitelist: If gTestSuites is not passed in and use_whitelist
    141                               is true, only whitelisted tests found on the
    142                               system will be used.
    143 
    144         @raise TestFail: The test failed.
    145         """
    146         self.host = host
    147         if not gtest_suites:
    148             gtest_suites = self._find_all_gtestsuites(
    149                     use_whitelist=use_whitelist)
    150 
    151         failed_gtest_suites = []
    152         for gtestSuite in gtest_suites:
    153             if not self.run_gtestsuite(gtestSuite):
    154                 failed_gtest_suites.append(gtestSuite)
    155 
    156         if failed_gtest_suites:
    157             logging.error(
    158                     'The following gTest Suites failed: \n %s',
    159                     '\n'.join([str(t) for t in failed_gtest_suites]))
    160             raise error.TestFail(
    161                     'Not all gTest Suites completed successfully. '
    162                     '%s out of %s suites failed. '
    163                     'Failed Suites: %s'
    164                     % (len(failed_gtest_suites),
    165                        len(gtest_suites),
    166                        failed_gtest_suites))
    167