Home | History | Annotate | Download | only in cheets_CTS_N
      1 # Copyright 2016 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 # repohooks/pre-upload.py currently does not run pylint. But for developers who
      6 # want to check their code manually we disable several harmless pylint warnings
      7 # which just distract from more serious remaining issues.
      8 #
      9 # The instance variable _android_cts is not defined in __init__().
     10 # pylint: disable=attribute-defined-outside-init
     11 #
     12 # Many short variable names don't follow the naming convention.
     13 # pylint: disable=invalid-name
     14 
     15 import logging
     16 import os
     17 
     18 from autotest_lib.server import utils
     19 from autotest_lib.server.cros import tradefed_test
     20 
     21 # Maximum default time allowed for each individual CTS module.
     22 _CTS_TIMEOUT_SECONDS = 3600
     23 
     24 # Public download locations for android cts bundles.
     25 _DL_CTS = 'https://dl.google.com/dl/android/cts/'
     26 _CTS_URI = {
     27     'arm': _DL_CTS + 'android-cts-7.1_r14-linux_x86-arm.zip',
     28     'x86': _DL_CTS + 'android-cts-7.1_r14-linux_x86-x86.zip',
     29     'media': _DL_CTS + 'android-cts-media-1.4.zip',
     30 }
     31 
     32 
     33 class cheets_CTS_N(tradefed_test.TradefedTest):
     34     """Sets up tradefed to run CTS tests."""
     35     version = 1
     36 
     37     # TODO(bmgordon): Remove kahlee once the bulk of failing tests are fixed.
     38     _BOARD_RETRY = {'betty': 0, 'kahlee': 0}
     39     _CHANNEL_RETRY = {'dev': 5, 'beta': 5, 'stable': 5}
     40 
     41     def _get_default_bundle_url(self, bundle):
     42         return _CTS_URI[bundle]
     43 
     44     def _get_tradefed_base_dir(self):
     45         return 'android-cts'
     46 
     47     def _tradefed_run_command(self,
     48                               module=None,
     49                               plan=None,
     50                               session_id=None,
     51                               test_class=None,
     52                               test_method=None):
     53         """Builds the CTS tradefed 'run' command line.
     54 
     55         There are five different usages:
     56 
     57         1. Test a module: assign the module name via |module|.
     58         2. Test a plan: assign the plan name via |plan|.
     59         3. Continue a session: assign the session ID via |session_id|.
     60         4. Run all test cases of a class: assign the class name via
     61            |test_class|.
     62         5. Run a specific test case: assign the class name and method name in
     63            |test_class| and |test_method|.
     64 
     65         @param module: the name of test module to be run.
     66         @param plan: name of the plan to be run.
     67         @param session_id: tradefed session id to continue.
     68         @param test_class: the name of the class of which all test cases will
     69                            be run.
     70         @param test_name: the name of the method of |test_class| to be run.
     71                           Must be used with |test_class|.
     72         @return: list of command tokens for the 'run' command.
     73         """
     74         if module is not None:
     75             # Run a particular module (used to be called package in M).
     76             cmd = ['run', 'commandAndExit', 'cts', '--module', module]
     77             if test_class is not None:
     78                 if test_method is not None:
     79                     cmd += ['-t', test_class + '#' + test_method]
     80                 else:
     81                     cmd += ['-t', test_class]
     82         elif plan is not None and session_id is not None:
     83             # In 7.1 R2 we can only retry session_id with the original plan.
     84             cmd = ['run', 'commandAndExit', 'cts', '--plan', plan,
     85                    '--retry', '%d' % session_id]
     86         elif plan is not None:
     87             # Subplan for any customized CTS test plan in form of xml.
     88             cmd = ['run', 'commandAndExit', 'cts', '--subplan', plan]
     89         else:
     90             logging.warning('Running all tests. This can take several days.')
     91             cmd = ['run', 'commandAndExit', 'cts']
     92         # We handle media download ourselves in the lab, as lazy as possible.
     93         cmd.append('--precondition-arg')
     94         cmd.append('skip-media-download')
     95         # If we are running outside of the lab we can collect more data.
     96         if not utils.is_in_container():
     97             logging.info('Running outside of lab, adding extra debug options.')
     98             cmd.append('--log-level-display=DEBUG')
     99             cmd.append('--screenshot-on-failure')
    100             # TODO(ihf): Add log collection once b/28333587 fixed.
    101             #cmd.append('--collect-deqp-logs')
    102         # TODO(ihf): Add tradefed_test.adb_keepalive() and remove
    103         # --disable-reboot. This might be more efficient.
    104         # At early stage, cts-tradefed tries to reboot the device by
    105         # "adb reboot" command. In a real Android device case, when the
    106         # rebooting is completed, adb connection is re-established
    107         # automatically, and cts-tradefed expects that behavior.
    108         # However, in ARC, it doesn't work, so the whole test process
    109         # is just stuck. Here, disable the feature.
    110         cmd.append('--disable-reboot')
    111         # Create a logcat file for each individual failure.
    112         cmd.append('--logcat-on-failure')
    113         return cmd
    114 
    115     def _get_timeout_factor(self):
    116         """Returns the factor to be multiplied to the timeout parameter.
    117         The factor is determined by the number of ABIs to run."""
    118         if self._timeoutfactor is None:
    119             abilist = self._run('adb', args=('shell', 'getprop',
    120                 'ro.product.cpu.abilist')).stdout.split(',')
    121             prefix = {'x86': 'x86', 'arm': 'armeabi-'}.get(self._abi)
    122             self._timeoutfactor = (1 if prefix is None else
    123                 sum(1 for abi in abilist if abi.startswith(prefix)))
    124         return self._timeoutfactor
    125 
    126     def _run_tradefed(self, commands):
    127         """Kick off CTS.
    128 
    129         @param commands: the command(s) to pass to CTS.
    130         @param datetime_id: For 'continue' datetime of previous run is known.
    131         @return: The result object from utils.run.
    132         """
    133         cts_tradefed = os.path.join(self._repository, 'tools', 'cts-tradefed')
    134         with tradefed_test.adb_keepalive(self._get_adb_target(),
    135                                          self._install_paths):
    136             for command in commands:
    137                 logging.info('RUN: ./cts-tradefed %s', ' '.join(command))
    138                 output = self._run(
    139                     cts_tradefed,
    140                     args=tuple(command),
    141                     timeout=self._timeout * self._get_timeout_factor(),
    142                     verbose=True,
    143                     ignore_status=False,
    144                     # Make sure to tee tradefed stdout/stderr to autotest logs
    145                     # continuously during the test run.
    146                     stdout_tee=utils.TEE_TO_LOGS,
    147                     stderr_tee=utils.TEE_TO_LOGS)
    148             logging.info('END: ./cts-tradefed %s\n', ' '.join(command))
    149         return output
    150 
    151     def _should_skip_test(self):
    152         """Some tests are expected to fail and are skipped."""
    153         # newbie and novato are x86 VMs without binary translation. Skip the ARM
    154         # tests.
    155         no_ARM_ABI_test_boards = ('newbie', 'novato', 'novato-arc64')
    156         if self._get_board_name(self._host) in no_ARM_ABI_test_boards:
    157             if self._abi == 'arm':
    158                 return True
    159         return False
    160 
    161     def generate_test_command(self, target_module, target_plan, target_class,
    162                               target_method, tradefed_args, session_id=0):
    163         """Generates the CTS command and name to use based on test arguments.
    164 
    165         @param target_module: the name of test module to run.
    166         @param target_plan: the name of the test plan to run.
    167         @param target_class: the name of the class to be tested.
    168         @param target_method: the name of the method to be tested.
    169         @param tradefed_args: a list of args to pass to tradefed.
    170         @param session_id: tradefed session_id.
    171         """
    172         if target_module is not None:
    173             if target_class is not None:
    174                 test_name = 'testcase.%s' % target_class
    175                 if target_method is not None:
    176                     test_name += '.' + target_method
    177                 test_command = self._tradefed_run_command(
    178                     module=target_module,
    179                     test_class=target_class,
    180                     test_method=target_method,
    181                     session_id=session_id)
    182             else:
    183                 test_name = 'module.%s' % target_module
    184                 test_command = self._tradefed_run_command(
    185                     module=target_module, session_id=session_id)
    186         elif target_plan is not None:
    187             test_name = 'plan.%s' % target_plan
    188             test_command = self._tradefed_run_command(plan=target_plan)
    189         elif tradefed_args is not None:
    190             test_name = 'run tradefed %s' % ' '.join(tradefed_args)
    191             test_command = tradefed_args
    192         else:
    193             test_command = self._tradefed_run_command()
    194             test_name = 'all_CTS'
    195 
    196         logging.info('CTS command: %s', test_command)
    197         return test_command, test_name
    198 
    199     def run_once(self,
    200                  target_module=None,
    201                  target_plan=None,
    202                  target_class=None,
    203                  target_method=None,
    204                  needs_push_media=False,
    205                  tradefed_args=None,
    206                  precondition_commands=[],
    207                  login_precondition_commands=[],
    208                  timeout=_CTS_TIMEOUT_SECONDS):
    209         """Runs the specified CTS once, but with several retries.
    210 
    211         There are four usages:
    212         1. Test the whole module named |target_module|.
    213         2. Test with a plan named |target_plan|.
    214         3. Run all the test cases of class named |target_class|.
    215         4. Run a specific test method named |target_method| of class
    216            |target_class|.
    217         5. Run an arbitrary tradefed command.
    218 
    219         @param target_module: the name of test module to run.
    220         @param target_plan: the name of the test plan to run.
    221         @param target_class: the name of the class to be tested.
    222         @param target_method: the name of the method to be tested.
    223         @param needs_push_media: need to push test media streams.
    224         @param timeout: time after which tradefed can be interrupted.
    225         @param precondition_commands: a list of scripts to be run on the
    226         dut before the test is run, the scripts must already be installed.
    227         @param login_precondition_commands: a list of scripts to be run on the
    228         dut before the log-in for the test is performed.
    229         @param tradefed_args: a list of args to pass to tradefed.
    230         """
    231 
    232         # On dev and beta channels timeouts are sharp, lenient on stable.
    233         self._timeout = timeout
    234         if self._get_release_channel(self._host) == 'stable':
    235             self._timeout += 3600
    236         # Retries depend on channel.
    237         self._timeoutfactor = None
    238 
    239         test_command, test_name = self.generate_test_command(target_module,
    240                                                              target_plan,
    241                                                              target_class,
    242                                                              target_method,
    243                                                              tradefed_args)
    244 
    245         self._run_tradefed_with_retries(target_module, test_command, test_name,
    246                                         target_plan, needs_push_media, _CTS_URI,
    247                                         login_precondition_commands,
    248                                         precondition_commands)
    249